Conflicts:
shared/optparser.c
... | ... |
@@ -56,6 +56,7 @@ static void help(void) |
56 | 56 |
printf(" --version -V Show version\n"); |
57 | 57 |
printf(" --info -i Print information about bytecode\n"); |
58 | 58 |
printf(" --printsrc -p Print bytecode source\n"); |
59 |
+ printf(" --printbcir -c Print bytecode IR\n"); |
|
59 | 60 |
printf(" --trace <level> Set bytecode trace level 0..7 (default 7)\n"); |
60 | 61 |
printf(" --no-trace-showsource Don't show source line during tracing\n"); |
61 | 62 |
printf(" file file to test\n"); |
... | ... |
@@ -328,6 +329,10 @@ int main(int argc, char *argv[]) |
328 | 328 |
cli_bytecode_describe(bc); |
329 | 329 |
} else if (optget(opts, "printsrc")->enabled) { |
330 | 330 |
print_src(opts->filename[0]); |
331 |
+ } else if (optget(opts, "printbcir")->enabled) { |
|
332 |
+ cli_bytetype_describe(bc); |
|
333 |
+ cli_bytevalue_describe(bc, 0); |
|
334 |
+ cli_bytefunc_describe(bc, 0); |
|
331 | 335 |
} else { |
332 | 336 |
cli_ctx cctx; |
333 | 337 |
struct cl_engine *engine = cl_engine_new(); |
... | ... |
@@ -1405,7 +1405,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char |
1405 | 1405 |
} |
1406 | 1406 |
bcfunc->dbgnodes = cli_malloc(num*sizeof(*bcfunc->dbgnodes)); |
1407 | 1407 |
if (!bcfunc->dbgnodes) { |
1408 |
- cli_errmsg("Unable to allocate memory for dbg nodes: %s\n", num*sizeof(*bcfunc->dbgnodes)); |
|
1408 |
+ cli_errmsg("Unable to allocate memory for dbg nodes: %u\n", num*sizeof(*bcfunc->dbgnodes)); |
|
1409 | 1409 |
return CL_EMEM; |
1410 | 1410 |
} |
1411 | 1411 |
for (i=0;i<num;i++) { |
... | ... |
@@ -3027,3 +3027,487 @@ void cli_bytecode_describe(const struct cli_bc *bc) |
3027 | 3027 |
} |
3028 | 3028 |
printf("\n"); |
3029 | 3029 |
} |
3030 |
+ |
|
3031 |
+const char *bc_tystr[] = { |
|
3032 |
+ "DFunctionType", |
|
3033 |
+ "DPointerType", |
|
3034 |
+ "DStructType", |
|
3035 |
+ "DPackedStructType", |
|
3036 |
+ "DArrayType" |
|
3037 |
+}; |
|
3038 |
+ |
|
3039 |
+const char *bc_opstr[] = { |
|
3040 |
+ "OP_BC_NULL", |
|
3041 |
+ "OP_BC_ADD", /* =1*/ |
|
3042 |
+ "OP_BC_SUB", |
|
3043 |
+ "OP_BC_MUL", |
|
3044 |
+ "OP_BC_UDIV", |
|
3045 |
+ "OP_BC_SDIV", |
|
3046 |
+ "OP_BC_UREM", |
|
3047 |
+ "OP_BC_SREM", |
|
3048 |
+ "OP_BC_SHL", |
|
3049 |
+ "OP_BC_LSHR", |
|
3050 |
+ "OP_BC_ASHR", |
|
3051 |
+ "OP_BC_AND", |
|
3052 |
+ "OP_BC_OR", |
|
3053 |
+ "OP_BC_XOR", |
|
3054 |
+ |
|
3055 |
+ "OP_BC_TRUNC", |
|
3056 |
+ "OP_BC_SEXT", |
|
3057 |
+ "OP_BC_ZEXT", |
|
3058 |
+ |
|
3059 |
+ "OP_BC_BRANCH", |
|
3060 |
+ "OP_BC_JMP", |
|
3061 |
+ "OP_BC_RET", |
|
3062 |
+ "OP_BC_RET_VOID", |
|
3063 |
+ |
|
3064 |
+ "OP_BC_ICMP_EQ", |
|
3065 |
+ "OP_BC_ICMP_NE", |
|
3066 |
+ "OP_BC_ICMP_UGT", |
|
3067 |
+ "OP_BC_ICMP_UGE", |
|
3068 |
+ "OP_BC_ICMP_ULT", |
|
3069 |
+ "OP_BC_ICMP_ULE", |
|
3070 |
+ "OP_BC_ICMP_SGT", |
|
3071 |
+ "OP_BC_ICMP_SGE", |
|
3072 |
+ "OP_BC_ICMP_SLE", |
|
3073 |
+ "OP_BC_ICMP_SLT", |
|
3074 |
+ "OP_BC_SELECT", |
|
3075 |
+ "OP_BC_CALL_DIRECT", |
|
3076 |
+ "OP_BC_CALL_API", |
|
3077 |
+ "OP_BC_COPY", |
|
3078 |
+ "OP_BC_GEP1", |
|
3079 |
+ "OP_BC_GEPZ", |
|
3080 |
+ "OP_BC_GEPN", |
|
3081 |
+ "OP_BC_STORE", |
|
3082 |
+ "OP_BC_LOAD", |
|
3083 |
+ "OP_BC_MEMSET", |
|
3084 |
+ "OP_BC_MEMCPY", |
|
3085 |
+ "OP_BC_MEMMOVE", |
|
3086 |
+ "OP_BC_MEMCMP", |
|
3087 |
+ "OP_BC_ISBIGENDIAN", |
|
3088 |
+ "OP_BC_ABORT", |
|
3089 |
+ "OP_BC_BSWAP16", |
|
3090 |
+ "OP_BC_BSWAP32", |
|
3091 |
+ "OP_BC_BSWAP64", |
|
3092 |
+ "OP_BC_PTRDIFF32", |
|
3093 |
+ "OP_BC_PTRTOINT64", |
|
3094 |
+ "OP_BC_INVALID" /* last */ |
|
3095 |
+}; |
|
3096 |
+ |
|
3097 |
+extern unsigned cli_numapicalls; |
|
3098 |
+static void cli_bytetype_helper(const struct cli_bc *bc, unsigned tid) |
|
3099 |
+{ |
|
3100 |
+ unsigned i, j; |
|
3101 |
+ |
|
3102 |
+ if (tid & 0x8000) { |
|
3103 |
+ printf("alloc "); |
|
3104 |
+ tid &= 0x7fff; |
|
3105 |
+ } |
|
3106 |
+ |
|
3107 |
+ if (tid < 65) { |
|
3108 |
+ printf("i%d", tid); |
|
3109 |
+ return; |
|
3110 |
+ } |
|
3111 |
+ |
|
3112 |
+ i = tid - 65; |
|
3113 |
+ const struct cli_bc_type *ty = &bc->types[i]; |
|
3114 |
+ |
|
3115 |
+ switch (ty->kind) { |
|
3116 |
+ case DFunctionType: |
|
3117 |
+ cli_bytetype_helper(bc, ty->containedTypes[0]); |
|
3118 |
+ printf(" func ( "); |
|
3119 |
+ for (j = 1; j < ty->numElements; ++j) { |
|
3120 |
+ cli_bytetype_helper(bc, ty->containedTypes[0]); |
|
3121 |
+ printf(" "); |
|
3122 |
+ } |
|
3123 |
+ printf(")"); |
|
3124 |
+ break; |
|
3125 |
+ case DPointerType: |
|
3126 |
+ cli_bytetype_helper(bc, ty->containedTypes[0]); |
|
3127 |
+ printf("*"); |
|
3128 |
+ break; |
|
3129 |
+ case DStructType: |
|
3130 |
+ case DPackedStructType: |
|
3131 |
+ printf("{ "); |
|
3132 |
+ for (j = 0; j < ty->numElements; ++j) { |
|
3133 |
+ cli_bytetype_helper(bc, ty->containedTypes[0]); |
|
3134 |
+ printf(" "); |
|
3135 |
+ } |
|
3136 |
+ printf("}"); |
|
3137 |
+ break; |
|
3138 |
+ case DArrayType: |
|
3139 |
+ printf("["); |
|
3140 |
+ printf("%d x ", ty->numElements); |
|
3141 |
+ cli_bytetype_helper(bc, ty->containedTypes[0]); |
|
3142 |
+ printf("]"); |
|
3143 |
+ break; |
|
3144 |
+ default: |
|
3145 |
+ printf("unhandled type kind %d, cannot parse", ty->kind); |
|
3146 |
+ break; |
|
3147 |
+ } |
|
3148 |
+ |
|
3149 |
+} |
|
3150 |
+ |
|
3151 |
+void cli_bytetype_describe(const struct cli_bc *bc) |
|
3152 |
+{ |
|
3153 |
+ unsigned i, tid; |
|
3154 |
+ |
|
3155 |
+ printf("found %d extra types of %d total, starting at tid %d\n", |
|
3156 |
+ bc->num_types, 64+bc->num_types, bc->start_tid); |
|
3157 |
+ |
|
3158 |
+ printf("TID KIND INTERNAL\n"); |
|
3159 |
+ printf("------------------------------------------------------------------------\n"); |
|
3160 |
+ for (i = 0, tid = 65; i < bc->num_types-1; ++i, ++tid) { |
|
3161 |
+ printf("%3d: %-20s", tid, bc_tystr[bc->types[i].kind]); |
|
3162 |
+ cli_bytetype_helper(bc, tid); |
|
3163 |
+ printf("\n"); |
|
3164 |
+ } |
|
3165 |
+ printf("------------------------------------------------------------------------\n"); |
|
3166 |
+} |
|
3167 |
+ |
|
3168 |
+void cli_bytevalue_describe(const struct cli_bc *bc, unsigned funcid) |
|
3169 |
+{ |
|
3170 |
+ unsigned i, j, total = 0; |
|
3171 |
+ const struct cli_bc_func *func; |
|
3172 |
+ |
|
3173 |
+ if (funcid >= bc->num_func) { |
|
3174 |
+ printf("bytecode diagnostic: funcid [%u] outside byecode numfuncs [%u]\n", |
|
3175 |
+ funcid, bc->num_func); |
|
3176 |
+ return; |
|
3177 |
+ } |
|
3178 |
+ // globals |
|
3179 |
+ printf("found a total of %d globals\n", bc->num_globals); |
|
3180 |
+ printf("GID ID VALUE\n"); |
|
3181 |
+ printf("------------------------------------------------------------------------\n"); |
|
3182 |
+ for (i = 0; i < bc->num_globals; ++i) { |
|
3183 |
+ printf("%3u [%3u]: ", i, i); |
|
3184 |
+ cli_bytetype_helper(bc, bc->globaltys[i]); |
|
3185 |
+ printf(" unknown\n"); |
|
3186 |
+ } |
|
3187 |
+ printf("------------------------------------------------------------------------\n"); |
|
3188 |
+ |
|
3189 |
+ // arguments and local values |
|
3190 |
+ func = &bc->funcs[funcid]; |
|
3191 |
+ printf("found %d values with %d arguments and %d locals\n", |
|
3192 |
+ func->numValues, func->numArgs, func->numLocals); |
|
3193 |
+ printf("VID ID VALUE\n"); |
|
3194 |
+ printf("------------------------------------------------------------------------\n"); |
|
3195 |
+ for (i = 0; i < func->numValues; ++i) { |
|
3196 |
+ printf("%3u [%3u]: ", i, total++); |
|
3197 |
+ cli_bytetype_helper(bc, func->types[i]); |
|
3198 |
+ if (i < func->numArgs) |
|
3199 |
+ printf("argument"); |
|
3200 |
+ printf("\n"); |
|
3201 |
+ } |
|
3202 |
+ printf("------------------------------------------------------------------------\n"); |
|
3203 |
+ |
|
3204 |
+ // constants |
|
3205 |
+ printf("found a total of %d constants\n", func->numConstants); |
|
3206 |
+ printf("CID ID VALUE\n"); |
|
3207 |
+ printf("------------------------------------------------------------------------\n"); |
|
3208 |
+ for (i = 0; i < func->numConstants; ++i) { |
|
3209 |
+ printf("%3u [%3u]: %llu(0x%llx)\n", i, total++, func->constants[i], func->constants[i]); |
|
3210 |
+ } |
|
3211 |
+ printf("------------------------------------------------------------------------\n"); |
|
3212 |
+ printf("found a total of %u total values\n", total); |
|
3213 |
+ printf("------------------------------------------------------------------------\n"); |
|
3214 |
+ return; |
|
3215 |
+} |
|
3216 |
+ |
|
3217 |
+void cli_byteinst_describe(const struct cli_bc_inst *inst, unsigned *bbnum) |
|
3218 |
+{ |
|
3219 |
+ unsigned j; |
|
3220 |
+ char inst_str[256]; |
|
3221 |
+ |
|
3222 |
+ if (inst->opcode > OP_BC_INVALID) { |
|
3223 |
+ printf("opcode %u[%u] of type %u is not implemented yet!", |
|
3224 |
+ inst->opcode, inst->interp_op/5, inst->interp_op%5); |
|
3225 |
+ return; |
|
3226 |
+ } |
|
3227 |
+ |
|
3228 |
+ snprintf(inst_str, 256, "%-20s[%-3d/%3d/%3d]", bc_opstr[inst->opcode], |
|
3229 |
+ inst->opcode, inst->interp_op, inst->interp_op%inst->opcode); |
|
3230 |
+ printf("%-35s", inst_str); |
|
3231 |
+ switch (inst->opcode) { |
|
3232 |
+ // binary operations |
|
3233 |
+ case OP_BC_ADD: |
|
3234 |
+ printf("%d = %d + %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3235 |
+ break; |
|
3236 |
+ case OP_BC_SUB: |
|
3237 |
+ printf("%d = %d - %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3238 |
+ break; |
|
3239 |
+ case OP_BC_MUL: |
|
3240 |
+ printf("%d = %d * %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3241 |
+ break; |
|
3242 |
+ case OP_BC_UDIV: |
|
3243 |
+ printf("%d = %d / %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3244 |
+ break; |
|
3245 |
+ case OP_BC_SDIV: |
|
3246 |
+ printf("%d = %d / %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3247 |
+ break; |
|
3248 |
+ case OP_BC_UREM: |
|
3249 |
+ printf("%d = %d %% %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3250 |
+ break; |
|
3251 |
+ case OP_BC_SREM: |
|
3252 |
+ printf("%d = %d %% %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3253 |
+ break; |
|
3254 |
+ case OP_BC_SHL: |
|
3255 |
+ printf("%d = %d << %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3256 |
+ break; |
|
3257 |
+ case OP_BC_LSHR: |
|
3258 |
+ printf("%d = %d >> %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3259 |
+ break; |
|
3260 |
+ case OP_BC_ASHR: |
|
3261 |
+ printf("%d = %d >> %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3262 |
+ break; |
|
3263 |
+ case OP_BC_AND: |
|
3264 |
+ printf("%d = %d & %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3265 |
+ break; |
|
3266 |
+ case OP_BC_OR: |
|
3267 |
+ printf("%d = %d | %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3268 |
+ break; |
|
3269 |
+ case OP_BC_XOR: |
|
3270 |
+ printf("%d = %d ^ %d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3271 |
+ break; |
|
3272 |
+ |
|
3273 |
+ // casting operations |
|
3274 |
+ case OP_BC_TRUNC: |
|
3275 |
+ printf("%d = %d trunc %llx", inst->dest, inst->u.cast.source, inst->u.cast.mask); |
|
3276 |
+ break; |
|
3277 |
+ case OP_BC_SEXT: |
|
3278 |
+ printf("%d = %d sext %llx", inst->dest, inst->u.cast.source, inst->u.cast.mask); |
|
3279 |
+ break; |
|
3280 |
+ case OP_BC_ZEXT: |
|
3281 |
+ printf("%d = %d zext %llx", inst->dest, inst->u.cast.source, inst->u.cast.mask); |
|
3282 |
+ break; |
|
3283 |
+ |
|
3284 |
+ // control operations (termination instructions) |
|
3285 |
+ case OP_BC_BRANCH: |
|
3286 |
+ printf("br %d ? bb.%d : bb.%d", inst->u.branch.condition, |
|
3287 |
+ inst->u.branch.br_true, inst->u.branch.br_false); |
|
3288 |
+ (*bbnum)++; |
|
3289 |
+ break; |
|
3290 |
+ case OP_BC_JMP: |
|
3291 |
+ printf("jmp bb.%d", inst->u.jump); |
|
3292 |
+ (*bbnum)++; |
|
3293 |
+ break; |
|
3294 |
+ case OP_BC_RET: |
|
3295 |
+ printf("ret %d", inst->u.unaryop); |
|
3296 |
+ (*bbnum)++; |
|
3297 |
+ break; |
|
3298 |
+ case OP_BC_RET_VOID: |
|
3299 |
+ printf("ret void"); |
|
3300 |
+ (*bbnum)++; |
|
3301 |
+ break; |
|
3302 |
+ |
|
3303 |
+ // comparison operations |
|
3304 |
+ case OP_BC_ICMP_EQ: |
|
3305 |
+ printf("%d = (%d == %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3306 |
+ break; |
|
3307 |
+ case OP_BC_ICMP_NE: |
|
3308 |
+ printf("%d = (%d != %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3309 |
+ break; |
|
3310 |
+ case OP_BC_ICMP_UGT: |
|
3311 |
+ printf("%d = (%d > %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3312 |
+ break; |
|
3313 |
+ case OP_BC_ICMP_UGE: |
|
3314 |
+ printf("%d = (%d >= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3315 |
+ break; |
|
3316 |
+ case OP_BC_ICMP_ULT: |
|
3317 |
+ printf("%d = (%d > %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3318 |
+ break; |
|
3319 |
+ case OP_BC_ICMP_ULE: |
|
3320 |
+ printf("%d = (%d >= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3321 |
+ break; |
|
3322 |
+ case OP_BC_ICMP_SGT: |
|
3323 |
+ printf("%d = (%d > %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3324 |
+ break; |
|
3325 |
+ case OP_BC_ICMP_SGE: |
|
3326 |
+ printf("%d = (%d >= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3327 |
+ break; |
|
3328 |
+ case OP_BC_ICMP_SLE: |
|
3329 |
+ printf("%d = (%d <= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3330 |
+ break; |
|
3331 |
+ case OP_BC_ICMP_SLT: |
|
3332 |
+ printf("%d = (%d < %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3333 |
+ break; |
|
3334 |
+ case OP_BC_SELECT: |
|
3335 |
+ printf("%d = %d ? %d : %d)", inst->dest, inst->u.three[0], |
|
3336 |
+ inst->u.three[1], inst->u.three[2]); |
|
3337 |
+ break; |
|
3338 |
+ |
|
3339 |
+ // function calling |
|
3340 |
+ case OP_BC_CALL_DIRECT: |
|
3341 |
+ printf("%d = call F.%d (", inst->dest, inst->u.ops.funcid); |
|
3342 |
+ for (j = 0; j < inst->u.ops.numOps; ++j) { |
|
3343 |
+ if (j == inst->u.ops.numOps-1) { |
|
3344 |
+ printf("%d", inst->u.ops.ops[j]); |
|
3345 |
+ } |
|
3346 |
+ else { |
|
3347 |
+ printf("%d, ", inst->u.ops.ops[j]); |
|
3348 |
+ } |
|
3349 |
+ } |
|
3350 |
+ printf(")"); |
|
3351 |
+ break; |
|
3352 |
+ case OP_BC_CALL_API: |
|
3353 |
+ { |
|
3354 |
+ if (inst->u.ops.funcid > cli_numapicalls) { |
|
3355 |
+ printf("apicall FID %d not yet implemented!\n", inst->u.ops.funcid); |
|
3356 |
+ break; |
|
3357 |
+ } |
|
3358 |
+ const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid]; |
|
3359 |
+ switch (api->kind) { |
|
3360 |
+ case 0: |
|
3361 |
+ printf("%d = %s[%d] (%d, %d)", inst->dest, api->name, |
|
3362 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1]); |
|
3363 |
+ break; |
|
3364 |
+ case 1: |
|
3365 |
+ printf("%d = %s[%d] (p.%d, %d)", inst->dest, api->name, |
|
3366 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1]); |
|
3367 |
+ break; |
|
3368 |
+ case 2: |
|
3369 |
+ printf("%d = %s[%d] (%d)", inst->dest, api->name, |
|
3370 |
+ inst->u.ops.funcid, inst->u.ops.ops[0]); |
|
3371 |
+ break; |
|
3372 |
+ case 3: |
|
3373 |
+ printf("p.%d = %s[%d] (%d)", inst->dest, api->name, |
|
3374 |
+ inst->u.ops.funcid, inst->u.ops.ops[0]); |
|
3375 |
+ break; |
|
3376 |
+ case 4: |
|
3377 |
+ printf("%d = %s[%d] (p.%d, %d, %d, %d, %d)", inst->dest, api->name, |
|
3378 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1], |
|
3379 |
+ inst->u.ops.ops[2], inst->u.ops.ops[3], inst->u.ops.ops[4]); |
|
3380 |
+ break; |
|
3381 |
+ case 5: |
|
3382 |
+ printf("%d = %s[%d] ()", inst->dest, api->name, |
|
3383 |
+ inst->u.ops.funcid); |
|
3384 |
+ break; |
|
3385 |
+ case 6: |
|
3386 |
+ printf("p.%d = %s[%d] (%d, %d)", inst->dest, api->name, |
|
3387 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1]); |
|
3388 |
+ break; |
|
3389 |
+ case 7: |
|
3390 |
+ printf("%d = %s[%d] (%d, %d, %d)", inst->dest, api->name, |
|
3391 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1], |
|
3392 |
+ inst->u.ops.ops[2]); |
|
3393 |
+ break; |
|
3394 |
+ case 8: |
|
3395 |
+ printf("%d = %s[%d] (p.%d, %d, p.%d, %d)", inst->dest, api->name, |
|
3396 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1], |
|
3397 |
+ inst->u.ops.ops[2], inst->u.ops.ops[3]); |
|
3398 |
+ break; |
|
3399 |
+ case 9: |
|
3400 |
+ printf("%d = %s[%d] (p.%d, %d, %d)", inst->dest, api->name, |
|
3401 |
+ inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1], |
|
3402 |
+ inst->u.ops.ops[2]); |
|
3403 |
+ break; |
|
3404 |
+ default: |
|
3405 |
+ printf("type %u apicalls not yet implemented!\n", api->kind); |
|
3406 |
+ break; |
|
3407 |
+ } |
|
3408 |
+ } |
|
3409 |
+ break; |
|
3410 |
+ |
|
3411 |
+ // memory operations |
|
3412 |
+ case OP_BC_COPY: |
|
3413 |
+ printf("cp %d -> %d", inst->u.binop[0], inst->u.binop[1]); |
|
3414 |
+ break; |
|
3415 |
+ case OP_BC_GEP1: |
|
3416 |
+ printf("%d = gep1 p.%d + (%d * %d)", inst->dest, inst->u.three[1], |
|
3417 |
+ inst->u.three[2], inst->u.three[0]); |
|
3418 |
+ break; |
|
3419 |
+ case OP_BC_GEPZ: |
|
3420 |
+ printf("%d = gepz p.%d + (%d)", inst->dest, |
|
3421 |
+ inst->u.three[1], inst->u.three[2]); |
|
3422 |
+ break; |
|
3423 |
+ case OP_BC_GEPN: |
|
3424 |
+ printf("illegal opcode, impossible"); |
|
3425 |
+ break; |
|
3426 |
+ case OP_BC_STORE: |
|
3427 |
+ printf("store %d -> p.%d", inst->u.binop[0], inst->u.binop[1]); |
|
3428 |
+ break; |
|
3429 |
+ case OP_BC_LOAD: |
|
3430 |
+ printf("load %d <- p.%d", inst->dest, inst->u.unaryop); |
|
3431 |
+ break; |
|
3432 |
+ |
|
3433 |
+ // llvm instrinsics |
|
3434 |
+ case OP_BC_MEMSET: |
|
3435 |
+ printf("%d = memset (p.%d, %d, %d)", inst->dest, inst->u.three[0], |
|
3436 |
+ inst->u.three[1], inst->u.three[2]); |
|
3437 |
+ break; |
|
3438 |
+ case OP_BC_MEMCPY: |
|
3439 |
+ printf("%d = memcpy (p.%d, p.%d, %d)", inst->dest, inst->u.three[0], |
|
3440 |
+ inst->u.three[1], inst->u.three[2]); |
|
3441 |
+ break; |
|
3442 |
+ case OP_BC_MEMMOVE: |
|
3443 |
+ printf("%d = memmove (p.%d, p.%d, %d)", inst->dest, inst->u.three[0], |
|
3444 |
+ inst->u.three[1], inst->u.three[2]); |
|
3445 |
+ break; |
|
3446 |
+ case OP_BC_MEMCMP: |
|
3447 |
+ printf("%d = memcmp (p.%d, p.%d, %d)", inst->dest, inst->u.three[0], |
|
3448 |
+ inst->u.three[1], inst->u.three[2]); |
|
3449 |
+ break; |
|
3450 |
+ |
|
3451 |
+ // utility operations |
|
3452 |
+ case OP_BC_ISBIGENDIAN: |
|
3453 |
+ printf("%d = isbigendian()", inst->dest); |
|
3454 |
+ break; |
|
3455 |
+ case OP_BC_ABORT: |
|
3456 |
+ printf("ABORT!!"); |
|
3457 |
+ break; |
|
3458 |
+ case OP_BC_BSWAP16: |
|
3459 |
+ printf("%d = bswap16 %d", inst->dest, inst->u.unaryop); |
|
3460 |
+ break; |
|
3461 |
+ case OP_BC_BSWAP32: |
|
3462 |
+ printf("%d = bswap32 %d", inst->dest, inst->u.unaryop); |
|
3463 |
+ break; |
|
3464 |
+ case OP_BC_BSWAP64: |
|
3465 |
+ printf("%d = bswap64 %d", inst->dest, inst->u.unaryop); |
|
3466 |
+ break; |
|
3467 |
+ case OP_BC_PTRDIFF32: |
|
3468 |
+ printf("%d = ptrdiff32 p.%d p.%d", inst->dest, inst->u.binop[0], inst->u.binop[1]); |
|
3469 |
+ break; |
|
3470 |
+ case OP_BC_PTRTOINT64: |
|
3471 |
+ printf("%d = ptrtoint64 p.%d", inst->dest, inst->u.unaryop); |
|
3472 |
+ break; |
|
3473 |
+ case OP_BC_INVALID: /* last */ |
|
3474 |
+ printf("INVALID!!"); |
|
3475 |
+ break; |
|
3476 |
+ |
|
3477 |
+ default: |
|
3478 |
+ // redundant check |
|
3479 |
+ printf("opcode %u[%u] of type %u is not implemented yet!", |
|
3480 |
+ inst->opcode, inst->interp_op/5, inst->interp_op%5); |
|
3481 |
+ break; |
|
3482 |
+ } |
|
3483 |
+} |
|
3484 |
+ |
|
3485 |
+void cli_bytefunc_describe(const struct cli_bc *bc, unsigned funcid) |
|
3486 |
+{ |
|
3487 |
+ unsigned i, bbnum, bbpre; |
|
3488 |
+ const struct cli_bc_func *func; |
|
3489 |
+ |
|
3490 |
+ if (funcid >= bc->num_func) { |
|
3491 |
+ printf("bytecode diagnostic: funcid [%u] outside byecode numfuncs [%u]\n", |
|
3492 |
+ funcid, bc->num_func); |
|
3493 |
+ return; |
|
3494 |
+ } |
|
3495 |
+ |
|
3496 |
+ func = &bc->funcs[funcid]; |
|
3497 |
+ |
|
3498 |
+ printf("FUNCTION ID: F.%d -> NUMINSTS %d\n", funcid, func->numInsts); |
|
3499 |
+ printf("BB IDX OPCODE [ID /IID/MOD] INST\n"); |
|
3500 |
+ printf("------------------------------------------------------------------------\n"); |
|
3501 |
+ bbpre = 0; bbnum = 0; |
|
3502 |
+ for (i = 0; i < func->numInsts; ++i) { |
|
3503 |
+ if (bbpre != bbnum) { |
|
3504 |
+ printf("\n"); |
|
3505 |
+ bbpre = bbnum; |
|
3506 |
+ } |
|
3507 |
+ |
|
3508 |
+ printf("%3d %3d ", bbnum, i); |
|
3509 |
+ cli_byteinst_describe(&func->allinsts[i], &bbnum); |
|
3510 |
+ printf("\n"); |
|
3511 |
+ } |
|
3512 |
+ printf("------------------------------------------------------------------------\n"); |
|
3513 |
+} |
... | ... |
@@ -114,7 +114,14 @@ int cli_bytecode_prepare2(struct cl_engine *engine, struct cli_all_bc *allbc, un |
114 | 114 |
int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx); |
115 | 115 |
void cli_bytecode_destroy(struct cli_bc *bc); |
116 | 116 |
int cli_bytecode_done(struct cli_all_bc *allbc); |
117 |
+ |
|
118 |
+/* Bytecode IR descriptions */ |
|
117 | 119 |
void cli_bytecode_describe(const struct cli_bc *bc); |
120 |
+void cli_bytetype_describe(const struct cli_bc *bc); |
|
121 |
+void cli_bytevalue_describe(const struct cli_bc *bc, unsigned funcid); |
|
122 |
+void cli_byteinst_describe(const struct cli_bc_inst *inst, unsigned *bbnum); |
|
123 |
+void cli_bytefunc_describe(const struct cli_bc *bc, unsigned funcid); |
|
124 |
+ |
|
118 | 125 |
|
119 | 126 |
/* Hooks */ |
120 | 127 |
struct cli_exe_info; |
... | ... |
@@ -214,8 +214,8 @@ const struct cli_bc_type cli_apicall_types[]={ |
214 | 214 |
{DArrayType, cli_tmp29, 3, 0, 0}, |
215 | 215 |
{DArrayType, cli_tmp30, 10, 0, 0} |
216 | 216 |
}; |
217 |
- |
|
218 | 217 |
const unsigned cli_apicall_maxtypes=sizeof(cli_apicall_types)/sizeof(cli_apicall_types[0]); |
218 |
+ |
|
219 | 219 |
const struct cli_apicall cli_apicalls[]={ |
220 | 220 |
/* Bytecode APIcalls BEGIN */ |
221 | 221 |
{"test1", 10, 0, 0}, |
... | ... |
@@ -320,6 +320,8 @@ const struct cli_apicall cli_apicalls[]={ |
320 | 320 |
{"json_get_int", 8, 33, 2} |
321 | 321 |
/* Bytecode APIcalls END */ |
322 | 322 |
}; |
323 |
+const unsigned cli_numapicalls=sizeof(cli_apicalls)/sizeof(cli_apicalls[0]); |
|
324 |
+ |
|
323 | 325 |
const cli_apicall_int2 cli_apicalls0[] = { |
324 | 326 |
(cli_apicall_int2)cli_bcapi_test1, |
325 | 327 |
(cli_apicall_int2)cli_bcapi_seek, |
... | ... |
@@ -199,6 +199,10 @@ CLAMAV_PRIVATE { |
199 | 199 |
cli_bytecode_debug_printsrc; |
200 | 200 |
cli_bytecode_printversion; |
201 | 201 |
cli_bytecode_describe; |
202 |
+ cli_bytetype_describe; |
|
203 |
+ cli_bytevalue_describe; |
|
204 |
+ cli_byteinst_describe; |
|
205 |
+ cli_bytefunc_describe; |
|
202 | 206 |
cli_printcxxver; |
203 | 207 |
cli_detect_environment; |
204 | 208 |
cli_disasm_one; |
... | ... |
@@ -141,6 +141,7 @@ const struct clam_option __clam_options[] = { |
141 | 141 |
{ NULL, "trust-bytecode", 't', CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMBC, "Trust loaded bytecode (default yes)", ""}, |
142 | 142 |
{ NULL, "info", 'i', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Load and print bytecode information without executing", ""}, |
143 | 143 |
{ NULL, "printsrc", 'p', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Print source code of bytecode", ""}, |
144 |
+ { NULL, "printbcir", 'c', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Print bytecode representation of bytecode signature", ""}, |
|
144 | 145 |
{ NULL, "input", 'r', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMBC, "Input file to run the bytecode n", ""}, |
145 | 146 |
{ NULL, "trace", 't', CLOPT_TYPE_NUMBER, MATCH_NUMBER, 7, NULL, 0, OPT_CLAMBC, "bytecode trace level",""}, |
146 | 147 |
{ NULL, "no-trace-showsource", 's', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Don't show source line during tracing",""}, |