~ubuntu-branches/ubuntu/jaunty/clamav/jaunty-backports

« back to all changes in this revision

Viewing changes to libclamav/bytecode_api.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-10-02 15:36:00 UTC
  • mfrom: (10.1.6 sid)
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: james.westby@ubuntu.com-20101002153600-2tx3vki1u55cdrjy
Tags: 0.96.3+dfsg-2ubuntu0.10.04.1
Microversion update to 0.96.3 for Lucid (LP: #653738)

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include <fcntl.h>
32
32
#include <errno.h>
33
33
#include <string.h>
 
34
#include <math.h>
 
35
#include <ctype.h>
34
36
#include "cltypes.h"
35
37
#include "clambc.h"
36
38
#include "bytecode.h"
40
42
#include "bytecode_api_impl.h"
41
43
#include "others.h"
42
44
#include "pe.h"
 
45
#include "pdf.h"
43
46
#include "disasm.h"
44
47
#include "scanners.h"
45
48
#include "jsparse/js-norm.h"
 
49
#include "hashtab.h"
 
50
#include "str.h"
 
51
#include "filetypes.h"
46
52
 
47
53
uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t a, uint32_t b)
48
54
{
111
117
 
112
118
uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t a)
113
119
{
114
 
    cli_dbgmsg("bytecode debug: %u\n", a);
115
 
    return 0;
 
120
    if (!cli_debug_flag)
 
121
        return 0;
 
122
    return fprintf(stderr, "%d", a);
116
123
}
117
124
 
118
125
/*TODO: compiler should make sure that only constants are passed here, and not
120
127
 * executing */
121
128
uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx* ctx, const uint8_t *name, uint32_t len)
122
129
{
123
 
    ctx->virname = name;
 
130
    ctx->virname = (const char*)name;
124
131
    return 0;
125
132
}
126
133
 
127
134
uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT *res, uint32_t len)
128
135
{
129
136
    int n;
130
 
    const char *buf;
131
 
    const char* next;
 
137
    const unsigned char *buf;
 
138
    const unsigned char* next;
132
139
    if (!res || !ctx->fmap || ctx->off >= ctx->fmap->len)
133
140
        return -1;
134
141
    /* 32 should be longest instr we support decoding.
262
269
        ctx->trace(ctx, trace_param);
263
270
    }
264
271
    if (ctx->trace_val && name)
265
 
        ctx->trace_val(ctx, name, value);
 
272
        ctx->trace_val(ctx, (const char*)name, value);
266
273
    return 0;
267
274
}
268
275
 
283
290
uint32_t cli_bcapi_pe_rawaddr(struct cli_bc_ctx *ctx, uint32_t rva)
284
291
{
285
292
  uint32_t ret;
286
 
  int err = 0;
 
293
  unsigned err = 0;
287
294
  const struct cli_pe_hook_data *pe = ctx->hooks.pedata;
288
295
  ret = cli_rawaddr(rva, ctx->sections, pe->nsections, &err,
289
296
                    ctx->file_size, pe->hdr_size);
321
328
 
322
329
int32_t cli_bcapi_file_find(struct cli_bc_ctx *ctx, const uint8_t* data, uint32_t len)
323
330
{
 
331
    fmap_t *map = ctx->fmap;
 
332
    if (!map || len <= 0) {
 
333
        cli_dbgmsg("bcapi_file_find preconditions not met\n");
 
334
        return -1;
 
335
    }
 
336
    return cli_bcapi_file_find_limit(ctx, data, len, map->len);
 
337
}
 
338
 
 
339
int32_t cli_bcapi_file_find_limit(struct cli_bc_ctx *ctx , const uint8_t* data, uint32_t len, int32_t limit)
 
340
{
324
341
    char buf[4096];
325
342
    fmap_t *map = ctx->fmap;
326
 
    uint32_t off = ctx->off, newoff;
 
343
    uint32_t off = ctx->off;
327
344
    int n;
328
345
 
329
 
    if (!map || len > sizeof(buf)/4 || len <= 0) {
330
 
        cli_dbgmsg("bcapi_file_find preconditions not met\n");
 
346
    if (!map || len > sizeof(buf)/4 || len <= 0 || limit <= 0) {
 
347
        cli_dbgmsg("bcapi_file_find_limit preconditions not met\n");
331
348
        return -1;
332
349
    }
333
350
    for (;;) {
334
351
        const char *p;
335
 
        n = fmap_readn(map, buf, off, sizeof(buf));
 
352
        int32_t readlen = sizeof(buf);
 
353
        if (off + readlen > limit) {
 
354
            readlen = limit - off;
 
355
            if (readlen < 0)
 
356
                return -1;
 
357
        }
 
358
        n = fmap_readn(map, buf, off, readlen);
336
359
        if ((unsigned)n < len || n < 0)
337
360
            return -1;
338
361
        p = cli_memmem(buf, n, data, len);
421
444
int32_t cli_bcapi_extract_new(struct cli_bc_ctx *ctx, int32_t id)
422
445
{
423
446
    cli_ctx *cctx;
424
 
    int res;
 
447
    int res = -1;
425
448
    cli_dbgmsg("previous tempfile had %u bytes\n", ctx->written);
426
449
    if (!ctx->written)
427
450
        return 0;
432
455
    cli_dbgmsg("bytecode: scanning extracted file %s\n", ctx->tempfile);
433
456
    cctx = (cli_ctx*)ctx->ctx;
434
457
    if (cctx) {
 
458
        cli_file_t current = cctx->container_type;
 
459
        if (ctx->containertype != CL_TYPE_ANY)
 
460
            cctx->container_type = ctx->containertype;
435
461
        res = cli_magic_scandesc(ctx->outfd, cctx);
436
 
        if (res == CL_VIRUS)
 
462
        cctx->container_type = current;
 
463
        if (res == CL_VIRUS) {
 
464
            if (cctx->virname)
 
465
                ctx->virname = *cctx->virname;
437
466
            ctx->found = 1;
 
467
        }
438
468
    }
439
469
    if ((cctx && cctx->engine->keeptmp) ||
440
470
        (ftruncate(ctx->outfd, 0) == -1)) {
453
483
#define BUF 16
454
484
int32_t cli_bcapi_read_number(struct cli_bc_ctx *ctx, uint32_t radix)
455
485
{
456
 
    unsigned char number[16];
457
486
    unsigned i;
458
487
    char *p;
459
488
    int32_t result;
517
546
{
518
547
    struct cli_hashset *s = get_hashset(ctx, id);
519
548
    if (!s)
520
 
        return 0;
 
549
        return -1;
521
550
    return cli_hashset_contains(s, key);
522
551
}
523
552
 
533
562
    if (!s)
534
563
        return -1;
535
564
    cli_hashset_destroy(s);
 
565
    if (id == ctx->nhashsets-1) {
 
566
        ctx->nhashsets--;
 
567
        if (!ctx->nhashsets) {
 
568
            free(ctx->hashsets);
 
569
            ctx->hashsets = NULL;
 
570
        } else {
 
571
            s = cli_realloc(ctx->hashsets, ctx->nhashsets*sizeof(*s));
 
572
            if (s)
 
573
                ctx->hashsets = s;
 
574
        }
 
575
    }
536
576
    return 0;
537
577
}
538
578
 
603
643
            return 0;
604
644
        return b->write_cursor - b->read_cursor;
605
645
    }
606
 
    if (!ctx->fmap || ctx->off >= ctx->file_size)
 
646
    if (!ctx->fmap || b->read_cursor >= ctx->file_size)
607
647
        return 0;
608
 
    if (ctx->off + BUFSIZ <= ctx->file_size)
 
648
    if (b->read_cursor + BUFSIZ <= ctx->file_size)
609
649
        return BUFSIZ;
610
 
    return ctx->file_size - ctx->off;
 
650
    return ctx->file_size - b->read_cursor;
611
651
}
612
652
 
613
653
uint8_t* cli_bcapi_buffer_pipe_read_get(struct cli_bc_ctx *ctx , int32_t id, uint32_t size)
864
904
int32_t cli_bcapi_jsnorm_process(struct cli_bc_ctx *ctx, int32_t id)
865
905
{
866
906
    unsigned avail;
867
 
    char *in;
 
907
    unsigned char *in;
868
908
    cli_ctx *cctx = ctx->ctx;
869
909
    struct bc_jsnorm *b = get_jsnorm(ctx, id);
870
910
    if (!b || b->from == -1 || !b->state)
877
917
    if (cctx && cli_checklimits("bytecode js api", cctx, ctx->jsnormwritten + avail, 0, 0))
878
918
        return -1;
879
919
    cli_bcapi_buffer_pipe_read_stopped(ctx, b->from, avail);
880
 
    cli_js_process_buffer(b->state, in, avail);
 
920
    cli_js_process_buffer(b->state, (char*)in, avail);
881
921
    return 0;
882
922
}
883
923
 
895
935
    b->from = -1;
896
936
    return 0;
897
937
}
 
938
 
 
939
static inline double myround(double a)
 
940
{
 
941
    if (a < 0)
 
942
        return a-0.5;
 
943
    return a+0.5;
 
944
}
 
945
 
 
946
int32_t cli_bcapi_ilog2(struct cli_bc_ctx *ctx, uint32_t a, uint32_t b)
 
947
{
 
948
    double f;
 
949
    if (!b)
 
950
        return 0x7fffffff;
 
951
    /* log(a/b) is -32..32, so 2^26*32=2^31 covers the entire range of int32 */
 
952
    f = (1<<26)*log((double)a / b) / log(2);
 
953
    return (int32_t)myround(f);
 
954
}
 
955
 
 
956
int32_t cli_bcapi_ipow(struct cli_bc_ctx *ctx, int32_t a, int32_t b, int32_t c)
 
957
{
 
958
    if (!a && b < 0)
 
959
        return 0x7fffffff;
 
960
    return (int32_t)myround(c*pow(a,b));
 
961
}
 
962
 
 
963
uint32_t cli_bcapi_iexp(struct cli_bc_ctx *ctx, int32_t a, int32_t b, int32_t c)
 
964
{
 
965
    double f;
 
966
    if (!b)
 
967
        return 0x7fffffff;
 
968
    f= c*exp((double)a/b);
 
969
    return (uint32_t)myround(f);
 
970
}
 
971
 
 
972
int32_t cli_bcapi_isin(struct cli_bc_ctx *ctx, int32_t a, int32_t b, int32_t c)
 
973
{
 
974
    double f;
 
975
    if (!b)
 
976
        return 0x7fffffff;
 
977
    f = c*sin((double)a/b);
 
978
    return (int32_t)myround(f);
 
979
}
 
980
 
 
981
int32_t cli_bcapi_icos(struct cli_bc_ctx *ctx, int32_t a, int32_t b, int32_t c)
 
982
{
 
983
    double f;
 
984
    if (!b)
 
985
        return 0x7fffffff;
 
986
    f = c*cos((double)a/b);
 
987
    return (int32_t)myround(f);
 
988
}
 
989
 
 
990
int32_t cli_bcapi_memstr(struct cli_bc_ctx *ctx, const uint8_t* h, int32_t hs,
 
991
                         const uint8_t*n, int32_t ns)
 
992
{
 
993
    const uint8_t *s;
 
994
    if (!h || !n || hs < 0 || ns < 0)
 
995
        return -1;
 
996
    s = (const uint8_t*) cli_memstr((const char*)h, hs, (const char*)n, ns);
 
997
    if (!s)
 
998
        return -1;
 
999
    return s - h;
 
1000
}
 
1001
 
 
1002
int32_t cli_bcapi_hex2ui(struct cli_bc_ctx *ctx, uint32_t ah, uint32_t bh)
 
1003
{
 
1004
    char result = 0;
 
1005
    unsigned char in[2];
 
1006
    in[0] = ah;
 
1007
    in[1] = bh;
 
1008
 
 
1009
    if (cli_hex2str_to((const char*)in, &result, 2) == -1)
 
1010
        return -1;
 
1011
    return result;
 
1012
}
 
1013
 
 
1014
int32_t cli_bcapi_atoi(struct cli_bc_ctx *ctx, const uint8_t* str, int32_t len)
 
1015
{
 
1016
    int32_t number = 0;
 
1017
    const uint8_t *end = str + len;
 
1018
    while (isspace(*str) && str < end) str++;
 
1019
    if (str == end)
 
1020
        return -1;/* all spaces */
 
1021
    if (*str == '+') str++;
 
1022
    if (str == end)
 
1023
        return -1;/* all spaces and +*/
 
1024
    if (*str == '-')
 
1025
        return -1;/* only positive numbers */
 
1026
    if (!isdigit(*str))
 
1027
        return -1;
 
1028
    while (isdigit(*str) && str < end) {
 
1029
        number = number*10 + (*str - '0');
 
1030
    }
 
1031
    return number;
 
1032
}
 
1033
 
 
1034
uint32_t cli_bcapi_debug_print_str_start(struct cli_bc_ctx *ctx , const uint8_t* s, uint32_t len)
 
1035
{
 
1036
    if (!s || len <= 0)
 
1037
        return -1;
 
1038
    cli_dbgmsg("bytecode debug: %.*s", len, s);
 
1039
    return 0;
 
1040
}
 
1041
 
 
1042
uint32_t cli_bcapi_debug_print_str_nonl(struct cli_bc_ctx *ctx , const uint8_t* s, uint32_t len)
 
1043
{
 
1044
    if (!s || len <= 0)
 
1045
        return -1;
 
1046
    if (!cli_debug_flag)
 
1047
        return 0;
 
1048
    return fwrite(s, 1, len, stderr);
 
1049
}
 
1050
 
 
1051
uint32_t cli_bcapi_entropy_buffer(struct cli_bc_ctx *ctx , uint8_t* s, int32_t len)
 
1052
{
 
1053
    uint32_t probTable[256];
 
1054
    unsigned i;
 
1055
    double entropy = 0;
 
1056
    double log2 = log(2);
 
1057
 
 
1058
    if (!s || len <= 0)
 
1059
        return -1;
 
1060
    memset(probTable, 0, sizeof(probTable));
 
1061
    for (i=0;i<len;i++) {
 
1062
        probTable[s[i]]++;
 
1063
    }
 
1064
    for (i=0;i<256;i++) {
 
1065
        double p;
 
1066
        if (!probTable[i])
 
1067
            continue;
 
1068
        p = (double)probTable[i] / len;
 
1069
        entropy += -p*log(p)/log2;
 
1070
    }
 
1071
    entropy *= 1<<26;
 
1072
    return (uint32_t)entropy;
 
1073
}
 
1074
 
 
1075
int32_t cli_bcapi_map_new(struct cli_bc_ctx *ctx, int32_t keysize, int32_t valuesize)
 
1076
{
 
1077
    unsigned n = ctx->nmaps+1;
 
1078
    struct cli_map *s;
 
1079
    if (!keysize)
 
1080
        return -1;
 
1081
    s = cli_realloc(ctx->maps, sizeof(*ctx->maps)*n);
 
1082
    if (!s)
 
1083
        return -1;
 
1084
    ctx->maps = s;
 
1085
    ctx->nmaps = n;
 
1086
    s = &s[n-1];
 
1087
    cli_map_init(s, keysize, valuesize, 16);
 
1088
    return n-1;
 
1089
}
 
1090
 
 
1091
static struct cli_map *get_hashtab(struct cli_bc_ctx *ctx, int32_t id)
 
1092
{
 
1093
    if (id < 0 || id >= ctx->nmaps || !ctx->maps)
 
1094
        return NULL;
 
1095
    return &ctx->maps[id];
 
1096
}
 
1097
 
 
1098
int32_t cli_bcapi_map_addkey(struct cli_bc_ctx *ctx , const uint8_t* key, int32_t keysize, int32_t id)
 
1099
{
 
1100
    struct cli_map *s = get_hashtab(ctx, id);
 
1101
    if (!s)
 
1102
        return -1;
 
1103
    return cli_map_addkey(s, key, keysize);
 
1104
}
 
1105
 
 
1106
int32_t cli_bcapi_map_setvalue(struct cli_bc_ctx *ctx, const uint8_t* value, int32_t valuesize, int32_t id)
 
1107
{
 
1108
    struct cli_map *s = get_hashtab(ctx, id);
 
1109
    if (!s)
 
1110
        return -1;
 
1111
    return cli_map_setvalue(s, value, valuesize);
 
1112
}
 
1113
 
 
1114
int32_t cli_bcapi_map_remove(struct cli_bc_ctx *ctx , const uint8_t* key, int32_t keysize, int32_t id)
 
1115
{
 
1116
    struct cli_map *s = get_hashtab(ctx, id);
 
1117
    if (!s)
 
1118
        return -1;
 
1119
    return cli_map_removekey(s, key, keysize);
 
1120
}
 
1121
 
 
1122
int32_t cli_bcapi_map_find(struct cli_bc_ctx *ctx , const uint8_t* key, int32_t keysize, int32_t id)
 
1123
{
 
1124
    struct cli_map *s = get_hashtab(ctx, id);
 
1125
    if (!s)
 
1126
        return -1;
 
1127
    return cli_map_find(s, key, keysize);
 
1128
}
 
1129
 
 
1130
int32_t cli_bcapi_map_getvaluesize(struct cli_bc_ctx *ctx, int32_t id)
 
1131
{
 
1132
    struct cli_map *s = get_hashtab(ctx, id);
 
1133
    if (!s)
 
1134
        return -1;
 
1135
    return cli_map_getvalue_size(s);
 
1136
}
 
1137
 
 
1138
uint8_t* cli_bcapi_map_getvalue(struct cli_bc_ctx *ctx , int32_t id, int32_t valuesize)
 
1139
{
 
1140
    struct cli_map *s = get_hashtab(ctx, id);
 
1141
    if (!s)
 
1142
        return NULL;
 
1143
    if (cli_map_getvalue_size(s) != valuesize)
 
1144
        return NULL;
 
1145
    return cli_map_getvalue(s);
 
1146
}
 
1147
 
 
1148
int32_t cli_bcapi_map_done(struct cli_bc_ctx *ctx , int32_t id)
 
1149
{
 
1150
    struct cli_map *s = get_hashtab(ctx, id);
 
1151
    if (!s)
 
1152
        return -1;
 
1153
    cli_map_delete(s);
 
1154
    if (id == ctx->nmaps-1) {
 
1155
        ctx->nmaps--;
 
1156
        if (!ctx->nmaps) {
 
1157
            free(ctx->maps);
 
1158
            ctx->maps = NULL;
 
1159
        } else {
 
1160
            s = cli_realloc(ctx->maps, ctx->nmaps*(sizeof(*s)));
 
1161
            if (s)
 
1162
                ctx->maps = s;
 
1163
        }
 
1164
    }
 
1165
    return 0;
 
1166
}
 
1167
 
 
1168
uint32_t cli_bcapi_engine_functionality_level(struct cli_bc_ctx *ctx)
 
1169
{
 
1170
    return cl_retflevel();
 
1171
}
 
1172
 
 
1173
uint32_t cli_bcapi_engine_dconf_level(struct cli_bc_ctx *ctx)
 
1174
{
 
1175
    return CL_FLEVEL_DCONF;
 
1176
}
 
1177
 
 
1178
uint32_t cli_bcapi_engine_scan_options(struct cli_bc_ctx *ctx)
 
1179
{
 
1180
    cli_ctx *cctx = (cli_ctx*)ctx->ctx;
 
1181
    return cctx->options;
 
1182
}
 
1183
 
 
1184
uint32_t cli_bcapi_engine_db_options(struct cli_bc_ctx *ctx)
 
1185
{
 
1186
    cli_ctx *cctx = (cli_ctx*)ctx->ctx;
 
1187
    return cctx->engine->dboptions;
 
1188
}
 
1189
 
 
1190
int32_t cli_bcapi_extract_set_container(struct cli_bc_ctx *ctx, uint32_t ftype)
 
1191
{
 
1192
    if (ftype > CL_TYPE_IGNORED)
 
1193
        return -1;
 
1194
    ctx->containertype = ftype;
 
1195
    return 0;
 
1196
}
 
1197
 
 
1198
int32_t cli_bcapi_input_switch(struct cli_bc_ctx *ctx , int32_t extracted_file)
 
1199
{
 
1200
    fmap_t *map;
 
1201
    if (ctx->extracted_file_input == extracted_file)
 
1202
        return 0;
 
1203
    if (!extracted_file) {
 
1204
        cli_dbgmsg("bytecode api: input switched back to main file\n");
 
1205
        ctx->fmap = ctx->save_map;
 
1206
        ctx->extracted_file_input = 0;
 
1207
        return 0;
 
1208
    }
 
1209
    if (ctx->outfd < 0)
 
1210
        return -1;
 
1211
    map = fmap(ctx->outfd, 0, 0);
 
1212
    if (!map) {
 
1213
        cli_warnmsg("can't mmap() extracted temporary file %s\n", ctx->tempfile);
 
1214
        return -1;
 
1215
    }
 
1216
    ctx->save_map = ctx->fmap;
 
1217
    cli_bytecode_context_setfile(ctx, map);
 
1218
    ctx->extracted_file_input = 1;
 
1219
    cli_dbgmsg("bytecode api: input switched to extracted file\n");
 
1220
    return 0;
 
1221
}
 
1222
 
 
1223
uint32_t cli_bcapi_get_environment(struct cli_bc_ctx *ctx , struct cli_environment* env, uint32_t len)
 
1224
{
 
1225
    if (len > sizeof(*env)) {
 
1226
        cli_dbgmsg("cli_bcapi_get_environment len %u > %lu\n", len, sizeof(*env));
 
1227
        return -1;
 
1228
    }
 
1229
    memcpy(env, ctx->env, len);
 
1230
    return 0;
 
1231
}
 
1232
 
 
1233
uint32_t cli_bcapi_disable_bytecode_if(struct cli_bc_ctx *ctx , const int8_t* reason, uint32_t len, uint32_t cond)
 
1234
{
 
1235
    if (ctx->bc->kind != BC_STARTUP) {
 
1236
        cli_dbgmsg("Bytecode must be BC_STARTUP to call disable_bytecode_if\n");
 
1237
        return -1;
 
1238
    }
 
1239
    if (!cond)
 
1240
        return ctx->bytecode_disable_status;
 
1241
    if (*reason == '^')
 
1242
        cli_warnmsg("Bytecode: disabling completely because %s\n", reason+1);
 
1243
    else
 
1244
        cli_dbgmsg("Bytecode: disabling completely because %s\n", reason);
 
1245
    ctx->bytecode_disable_status = 2;
 
1246
    return ctx->bytecode_disable_status;
 
1247
}
 
1248
 
 
1249
uint32_t cli_bcapi_disable_jit_if(struct cli_bc_ctx *ctx , const int8_t* reason, uint32_t len, uint32_t cond)
 
1250
{
 
1251
    if (ctx->bc->kind != BC_STARTUP) {
 
1252
        cli_dbgmsg("Bytecode must be BC_STARTUP to call disable_jit_if\n");
 
1253
        return -1;
 
1254
    }
 
1255
    if (!cond)
 
1256
        return ctx->bytecode_disable_status;
 
1257
    if (*reason == '^')
 
1258
        cli_warnmsg("Bytecode: disabling JIT because %s\n", reason+1);
 
1259
    else
 
1260
        cli_dbgmsg("Bytecode: disabling JIT because %s\n", reason);
 
1261
    if (ctx->bytecode_disable_status != 2) /* no reenabling */
 
1262
        ctx->bytecode_disable_status = 1;
 
1263
    return ctx->bytecode_disable_status;
 
1264
}
 
1265
 
 
1266
int32_t cli_bcapi_version_compare(struct cli_bc_ctx *ctx , const uint8_t* lhs, uint32_t lhs_len, 
 
1267
                                  const uint8_t* rhs, uint32_t rhs_len)
 
1268
{
 
1269
    unsigned i = 0, j = 0;
 
1270
    unsigned long li=0, ri=0;
 
1271
    do {
 
1272
        while (i < lhs_len && j < rhs_len && lhs[i] == rhs[j] &&
 
1273
               !isdigit(lhs[i]) && !isdigit(rhs[j])) {
 
1274
            i++; j++;
 
1275
        }
 
1276
        if (i == lhs_len && j == rhs_len)
 
1277
            return 0;
 
1278
        if (i == lhs_len)
 
1279
            return -1;
 
1280
        if (j == rhs_len)
 
1281
            return 1;
 
1282
        if (!isdigit(lhs[i]) || !isdigit(rhs[j]))
 
1283
            return lhs[i] < rhs[j] ? -1 : 1;
 
1284
        while (isdigit(lhs[i]) && i < lhs_len)
 
1285
            li = 10*li + (lhs[i] - '0');
 
1286
        while (isdigit(rhs[j]) && j < rhs_len)
 
1287
            ri = 10*ri + (rhs[j] - '0');
 
1288
        if (li < ri)
 
1289
            return -1;
 
1290
        if (li > ri)
 
1291
            return 1;
 
1292
    } while (1);
 
1293
}
 
1294
 
 
1295
static int check_bits(uint32_t query, uint32_t value, uint8_t shift, uint8_t mask)
 
1296
{
 
1297
    uint8_t q = (query >> shift)&mask;
 
1298
    uint8_t v = (value >> shift)&mask;
 
1299
    /* q == mask -> ANY */
 
1300
    if (q == v || q == mask)
 
1301
        return 1;
 
1302
    return 0;
 
1303
}
 
1304
 
 
1305
uint32_t cli_bcapi_check_platform(struct cli_bc_ctx *ctx , uint32_t a, uint32_t b , uint32_t c)
 
1306
{
 
1307
    unsigned ret =
 
1308
        check_bits(a, ctx->env->platform_id_a, 24, 0xff) &&
 
1309
        check_bits(a, ctx->env->platform_id_a, 20, 0xf) &&
 
1310
        check_bits(a, ctx->env->platform_id_a, 16, 0xf) &&
 
1311
        check_bits(a, ctx->env->platform_id_a, 8, 0xff) &&
 
1312
        check_bits(a, ctx->env->platform_id_a, 0, 0xff) &&
 
1313
        check_bits(b, ctx->env->platform_id_b, 28, 0xf) &&
 
1314
        check_bits(b, ctx->env->platform_id_b, 24, 0xf) &&
 
1315
        check_bits(b, ctx->env->platform_id_b, 16, 0xff) &&
 
1316
        check_bits(b, ctx->env->platform_id_b, 8, 0xff) &&
 
1317
        check_bits(b, ctx->env->platform_id_b, 0, 0xff) &&
 
1318
        check_bits(c, ctx->env->platform_id_c, 24, 0xff) &&
 
1319
        check_bits(c, ctx->env->platform_id_c, 16, 0xff) &&
 
1320
        check_bits(c, ctx->env->platform_id_c, 8, 0xff) &&
 
1321
        check_bits(c, ctx->env->platform_id_c, 0, 0xff);
 
1322
    if (ret) {
 
1323
        cli_dbgmsg("check_platform(0x%08x,0x%08x,0x%08x) = match\n",a,b,c);
 
1324
    }
 
1325
    return ret;
 
1326
}
 
1327
 
 
1328
int cli_bytecode_context_setpdf(struct cli_bc_ctx *ctx, unsigned phase,
 
1329
                                unsigned nobjs,
 
1330
                                struct pdf_obj *objs, uint32_t *pdf_flags,
 
1331
                                uint32_t pdfsize, uint32_t pdfstartoff)
 
1332
{
 
1333
    ctx->pdf_nobjs = nobjs;
 
1334
    ctx->pdf_objs = objs;
 
1335
    ctx->pdf_flags = pdf_flags;
 
1336
    ctx->pdf_size = pdfsize;
 
1337
    ctx->pdf_startoff = pdfstartoff;
 
1338
    ctx->pdf_phase = phase;
 
1339
    return 0;
 
1340
}
 
1341
 
 
1342
int32_t cli_bcapi_pdf_get_obj_num(struct cli_bc_ctx *ctx)
 
1343
{
 
1344
    if (!ctx->pdf_phase)
 
1345
        return -1;
 
1346
    return ctx->pdf_nobjs;
 
1347
}
 
1348
 
 
1349
int32_t cli_bcapi_pdf_get_flags(struct cli_bc_ctx *ctx)
 
1350
{
 
1351
    if (!ctx->pdf_phase)
 
1352
        return -1;
 
1353
    return *ctx->pdf_flags;
 
1354
}
 
1355
 
 
1356
int32_t cli_bcapi_pdf_set_flags(struct cli_bc_ctx *ctx , int32_t flags)
 
1357
{
 
1358
    if (!ctx->pdf_phase)
 
1359
        return -1;
 
1360
    cli_dbgmsg("cli_pdf: bytecode set_flags %08x -> %08x\n",
 
1361
               *ctx->pdf_flags,
 
1362
               flags);
 
1363
    *ctx->pdf_flags = flags;
 
1364
    return 0;
 
1365
}
 
1366
 
 
1367
int32_t cli_bcapi_pdf_lookupobj(struct cli_bc_ctx *ctx , uint32_t objid)
 
1368
{
 
1369
    unsigned i;
 
1370
    if (!ctx->pdf_phase)
 
1371
        return -1;
 
1372
    for (i=0;i<ctx->pdf_nobjs;i++) {
 
1373
        if (ctx->pdf_objs[i].id == objid)
 
1374
            return i;
 
1375
    }
 
1376
    return -1;
 
1377
}
 
1378
 
 
1379
uint32_t cli_bcapi_pdf_getobjsize(struct cli_bc_ctx *ctx , int32_t objidx)
 
1380
{
 
1381
    if (!ctx->pdf_phase ||
 
1382
        objidx >= ctx->pdf_nobjs ||
 
1383
        ctx->pdf_phase == PDF_PHASE_POSTDUMP /* map is obj itself, no access to pdf anymore */
 
1384
       )
 
1385
        return 0;
 
1386
    if (objidx + 1 == ctx->pdf_nobjs)
 
1387
        return ctx->pdf_size - ctx->pdf_objs[objidx].start;
 
1388
    return ctx->pdf_objs[objidx+1].start - ctx->pdf_objs[objidx].start - 4;
 
1389
}
 
1390
 
 
1391
uint8_t* cli_bcapi_pdf_getobj(struct cli_bc_ctx *ctx , int32_t objidx, uint32_t amount)
 
1392
{
 
1393
    uint32_t size = cli_bcapi_pdf_getobjsize(ctx, objidx);
 
1394
    if (amount > size)
 
1395
        return NULL;
 
1396
    return fmap_need_off(ctx->fmap, ctx->pdf_objs[objidx].start, amount);
 
1397
}
 
1398
 
 
1399
int32_t cli_bcapi_pdf_getobjid(struct cli_bc_ctx *ctx , int32_t objidx)
 
1400
{
 
1401
    if (!ctx->pdf_phase ||
 
1402
        objidx >= ctx->pdf_nobjs)
 
1403
        return -1;
 
1404
    return ctx->pdf_objs[objidx].id;
 
1405
}
 
1406
 
 
1407
int32_t cli_bcapi_pdf_getobjflags(struct cli_bc_ctx *ctx , int32_t objidx)
 
1408
{
 
1409
    if (!ctx->pdf_phase ||
 
1410
        objidx >= ctx->pdf_nobjs)
 
1411
        return -1;
 
1412
    return ctx->pdf_objs[objidx].flags;
 
1413
}
 
1414
 
 
1415
int32_t cli_bcapi_pdf_setobjflags(struct cli_bc_ctx *ctx , int32_t objidx, int32_t flags)
 
1416
{
 
1417
    if (!ctx->pdf_phase ||
 
1418
        objidx >= ctx->pdf_nobjs)
 
1419
        return -1;
 
1420
    cli_dbgmsg("cli_pdf: bytecode setobjflags %08x -> %08x\n",
 
1421
               ctx->pdf_objs[objidx].flags,
 
1422
               flags);
 
1423
    ctx->pdf_objs[objidx].flags = flags;
 
1424
    return 0;
 
1425
}
 
1426
 
 
1427
int32_t cli_bcapi_pdf_get_offset(struct cli_bc_ctx *ctx , int32_t objidx)
 
1428
{
 
1429
    if (!ctx->pdf_phase ||
 
1430
        objidx >= ctx->pdf_nobjs)
 
1431
        return -1;
 
1432
    return ctx->pdf_startoff + ctx->pdf_objs[objidx].start;
 
1433
}
 
1434
 
 
1435
int32_t cli_bcapi_pdf_get_phase(struct cli_bc_ctx *ctx)
 
1436
{
 
1437
    return ctx->pdf_phase;
 
1438
}
 
1439
 
 
1440
int32_t cli_bcapi_pdf_get_dumpedobjid(struct cli_bc_ctx *ctx)
 
1441
{
 
1442
    if (ctx->pdf_phase != PDF_PHASE_POSTDUMP)
 
1443
        return -1;
 
1444
    return ctx->pdf_dumpedid;
 
1445
}
 
1446