110 |
|
|
111 |
#include "thunk.h" |
#include "thunk.h" |
112 |
|
|
113 |
|
enum { |
114 |
|
OUT_GEN_OP, |
115 |
|
OUT_CODE, |
116 |
|
OUT_INDEX_OP, |
117 |
|
}; |
118 |
|
|
119 |
/* all dynamically generated functions begin with this code */ |
/* all dynamically generated functions begin with this code */ |
120 |
#define OP_PREFIX "op_" |
#define OP_PREFIX "op_" |
121 |
|
|
1093 |
} |
} |
1094 |
|
|
1095 |
/* load an elf object file */ |
/* load an elf object file */ |
1096 |
int load_elf(const char *filename, FILE *outfile, int do_print_enum) |
int load_elf(const char *filename, FILE *outfile, int out_type) |
1097 |
{ |
{ |
1098 |
int fd; |
int fd; |
1099 |
struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec; |
struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec; |
1201 |
} |
} |
1202 |
} |
} |
1203 |
|
|
1204 |
if (do_print_enum) { |
if (out_type == OUT_INDEX_OP) { |
1205 |
fprintf(outfile, "DEF(end, 0, 0)\n"); |
fprintf(outfile, "DEF(end, 0, 0)\n"); |
1206 |
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
1207 |
const char *name, *p; |
const char *name, *p; |
1211 |
text, relocs, nb_relocs, 2); |
text, relocs, nb_relocs, 2); |
1212 |
} |
} |
1213 |
} |
} |
1214 |
|
} else if (out_type == OUT_GEN_OP) { |
1215 |
|
/* generate gen_xxx functions */ |
1216 |
|
|
1217 |
|
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
1218 |
|
const char *name; |
1219 |
|
name = strtab + sym->st_name; |
1220 |
|
if (strstart(name, OP_PREFIX, NULL)) { |
1221 |
|
if (sym->st_shndx != (text_sec - shdr)) |
1222 |
|
error("invalid section for opcode (0x%x)", sym->st_shndx); |
1223 |
|
gen_code(name, sym->st_value, sym->st_size, outfile, |
1224 |
|
text, relocs, nb_relocs, 0); |
1225 |
|
} |
1226 |
|
} |
1227 |
|
|
1228 |
} else { |
} else { |
1229 |
/* generate big code generation switch */ |
/* generate big code generation switch */ |
1230 |
fprintf(outfile, |
fprintf(outfile, |
1325 |
default: |
default: |
1326 |
error("unknown ELF architecture"); |
error("unknown ELF architecture"); |
1327 |
} |
} |
1328 |
|
/* flush instruction cache */ |
1329 |
|
fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n"); |
1330 |
|
|
1331 |
fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n"); |
fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n"); |
1332 |
fprintf(outfile, "}\n\n"); |
fprintf(outfile, "}\n\n"); |
1333 |
|
|
|
/* generate gen_xxx functions */ |
|
|
/* XXX: suppress the use of these functions to simplify code */ |
|
|
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
|
|
const char *name; |
|
|
name = strtab + sym->st_name; |
|
|
if (strstart(name, OP_PREFIX, NULL)) { |
|
|
if (sym->st_shndx != (text_sec - shdr)) |
|
|
error("invalid section for opcode (0x%x)", sym->st_shndx); |
|
|
gen_code(name, sym->st_value, sym->st_size, outfile, |
|
|
text, relocs, nb_relocs, 0); |
|
|
} |
|
|
} |
|
1334 |
} |
} |
1335 |
|
|
1336 |
close(fd); |
close(fd); |
1343 |
"usage: dyngen [-o outfile] [-c] objfile\n" |
"usage: dyngen [-o outfile] [-c] objfile\n" |
1344 |
"Generate a dynamic code generator from an object file\n" |
"Generate a dynamic code generator from an object file\n" |
1345 |
"-c output enum of operations\n" |
"-c output enum of operations\n" |
1346 |
|
"-g output gen_op_xx() functions\n" |
1347 |
); |
); |
1348 |
exit(1); |
exit(1); |
1349 |
} |
} |
1350 |
|
|
1351 |
int main(int argc, char **argv) |
int main(int argc, char **argv) |
1352 |
{ |
{ |
1353 |
int c, do_print_enum; |
int c, out_type; |
1354 |
const char *filename, *outfilename; |
const char *filename, *outfilename; |
1355 |
FILE *outfile; |
FILE *outfile; |
1356 |
|
|
1357 |
outfilename = "out.c"; |
outfilename = "out.c"; |
1358 |
do_print_enum = 0; |
out_type = OUT_CODE; |
1359 |
for(;;) { |
for(;;) { |
1360 |
c = getopt(argc, argv, "ho:c"); |
c = getopt(argc, argv, "ho:cg"); |
1361 |
if (c == -1) |
if (c == -1) |
1362 |
break; |
break; |
1363 |
switch(c) { |
switch(c) { |
1368 |
outfilename = optarg; |
outfilename = optarg; |
1369 |
break; |
break; |
1370 |
case 'c': |
case 'c': |
1371 |
do_print_enum = 1; |
out_type = OUT_INDEX_OP; |
1372 |
|
break; |
1373 |
|
case 'g': |
1374 |
|
out_type = OUT_GEN_OP; |
1375 |
break; |
break; |
1376 |
} |
} |
1377 |
} |
} |
1381 |
outfile = fopen(outfilename, "w"); |
outfile = fopen(outfilename, "w"); |
1382 |
if (!outfile) |
if (!outfile) |
1383 |
error("could not open '%s'", outfilename); |
error("could not open '%s'", outfilename); |
1384 |
load_elf(filename, outfile, do_print_enum); |
load_elf(filename, outfile, out_type); |
1385 |
fclose(outfile); |
fclose(outfile); |
1386 |
return 0; |
return 0; |
1387 |
} |
} |