diff options
| author | Root THC | 2026-02-24 12:42:47 +0000 |
|---|---|---|
| committer | Root THC | 2026-02-24 12:42:47 +0000 |
| commit | c9cbeced5b3f2bdd7407e29c0811e65954132540 (patch) | |
| tree | aefc355416b561111819de159ccbd86c3004cf88 /other/burneye2/elf/function-extract.c | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'other/burneye2/elf/function-extract.c')
| -rw-r--r-- | other/burneye2/elf/function-extract.c | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/other/burneye2/elf/function-extract.c b/other/burneye2/elf/function-extract.c new file mode 100644 index 0000000..8b8c3b4 --- /dev/null +++ b/other/burneye2/elf/function-extract.c | |||
| @@ -0,0 +1,347 @@ | |||
| 1 | /* donkey-fix, be an associal nerd | ||
| 2 | */ | ||
| 3 | |||
| 4 | #include <elf.h> | ||
| 5 | #include <stdio.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <unistd.h> | ||
| 8 | |||
| 9 | #include <common.h> | ||
| 10 | #include <elf_base.h> | ||
| 11 | #include <elf_file.h> | ||
| 12 | #include <elf_reloc.h> | ||
| 13 | #include <elf_section.h> | ||
| 14 | #include <elf_symbol.h> | ||
| 15 | #include <elf_dump.h> | ||
| 16 | #include <ia32-glue.h> | ||
| 17 | #include <ia32-debug.h> | ||
| 18 | |||
| 19 | |||
| 20 | extern dump_header dh_Shdr_short[]; | ||
| 21 | extern dump_header dh_Shdr[]; | ||
| 22 | |||
| 23 | |||
| 24 | extern int ia32_verbosity; | ||
| 25 | extern int ia32_graphviz_align_undefined; | ||
| 26 | |||
| 27 | |||
| 28 | void | ||
| 29 | function_dump (FILE *fp, ia32_function *func); | ||
| 30 | |||
| 31 | |||
| 32 | int dump_asm = 1; | ||
| 33 | char * progname; | ||
| 34 | char * binary; | ||
| 35 | |||
| 36 | |||
| 37 | void | ||
| 38 | usage (char *name) | ||
| 39 | { | ||
| 40 | fprintf (stderr, "usage: %s [options] <binary>\n\n", | ||
| 41 | progname); | ||
| 42 | |||
| 43 | fprintf (stderr, "options\n" | ||
| 44 | "\t-D\tprint DEBUG output from ia32_ module\n" | ||
| 45 | "\t-d\tdump all functions in object as .asm and .bin\n" | ||
| 46 | "\t-p name\tpalmers mode, print only calltree leading to function\n" | ||
| 47 | "\t\t`name'\n" | ||
| 48 | "\t-x\tabort when external references are found\n" | ||
| 49 | "\t-v\toutput the generated graph instantly\n" | ||
| 50 | "\t-A\talign \"undefined\"/external references seperatly in graph\n\n"); | ||
| 51 | |||
| 52 | exit (EXIT_FAILURE); | ||
| 53 | } | ||
| 54 | |||
| 55 | |||
| 56 | int dump_func = 0; | ||
| 57 | int visual = 0; | ||
| 58 | int warn_extern = 0; | ||
| 59 | char * fname = NULL; | ||
| 60 | |||
| 61 | |||
| 62 | int | ||
| 63 | main (int argc, char *argv[]) | ||
| 64 | { | ||
| 65 | unsigned int n; | ||
| 66 | char c; | ||
| 67 | unsigned int flist_count; /* number of items */ | ||
| 68 | ia32_function ** flist; /* function list */ | ||
| 69 | elf_base * elf; /* entire ELF object */ | ||
| 70 | FILE * fp; | ||
| 71 | elf_rel_list * rel_list; | ||
| 72 | elf_reloc_list * reloc_text; | ||
| 73 | elf_reloc_list * reloc_rodata; | ||
| 74 | unsigned int xref_count; | ||
| 75 | |||
| 76 | |||
| 77 | progname = argv[0]; | ||
| 78 | |||
| 79 | if (argc < 2) | ||
| 80 | usage (progname); | ||
| 81 | |||
| 82 | ia32_verbosity = IA32_FATAL; | ||
| 83 | |||
| 84 | while ((c = getopt (argc, argv, "Ddp:xvA")) != EOF) { | ||
| 85 | switch (c) { | ||
| 86 | case ('D'): | ||
| 87 | ia32_verbosity = IA32_DEBUG; | ||
| 88 | break; | ||
| 89 | case ('d'): | ||
| 90 | dump_func = 1; | ||
| 91 | break; | ||
| 92 | case ('p'): | ||
| 93 | fname = optarg; | ||
| 94 | break; | ||
| 95 | case ('x'): | ||
| 96 | warn_extern = 1; | ||
| 97 | break; | ||
| 98 | case ('v'): | ||
| 99 | visual = 1; | ||
| 100 | break; | ||
| 101 | case ('A'): | ||
| 102 | ia32_graphviz_align_undefined = 1; | ||
| 103 | break; | ||
| 104 | default: | ||
| 105 | usage (progname); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | binary = argv[argc - 1]; | ||
| 111 | if (binary[0] == '-') | ||
| 112 | usage (progname); | ||
| 113 | |||
| 114 | elf = elf_base_load (binary); | ||
| 115 | if (elf == NULL) { | ||
| 116 | fprintf (stderr, "elf_base_load: failed\n"); | ||
| 117 | exit (EXIT_FAILURE); | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | /* create and load section list | ||
| 122 | */ | ||
| 123 | flist = elf_function_list_create (elf->elf, elf->seclist, | ||
| 124 | &flist_count); | ||
| 125 | if (flist == NULL) { | ||
| 126 | fprintf (stderr, "failed to obtain list of functions, exit\n"); | ||
| 127 | |||
| 128 | exit (EXIT_FAILURE); | ||
| 129 | } | ||
| 130 | |||
| 131 | /* create relocation list | ||
| 132 | */ | ||
| 133 | rel_list = elf_rel_list_create (elf); | ||
| 134 | reloc_text = elf_reloc_list_create (elf, | ||
| 135 | elf_rel_list_find_byname (rel_list, ".rel.text"), | ||
| 136 | flist, flist_count); | ||
| 137 | reloc_rodata = elf_reloc_list_create (elf, | ||
| 138 | elf_rel_list_find_byname (rel_list, ".rel.rodata"), | ||
| 139 | NULL, 0); | ||
| 140 | |||
| 141 | printf ("analysing... "); | ||
| 142 | fflush (stdout); | ||
| 143 | |||
| 144 | /* FIXME: add rel_rodata */ | ||
| 145 | ia32_func_treeplain (&flist, &flist_count, reloc_text, reloc_rodata); | ||
| 146 | printf ("done.\n"); | ||
| 147 | |||
| 148 | xref_count = ia32_func_xref_count (flist, flist_count, | ||
| 149 | IA32_XREF_FUNCEXTERN); | ||
| 150 | if (warn_extern && xref_count != 0) { | ||
| 151 | fprintf (stderr, "%u extern function references, aborting\n", | ||
| 152 | xref_count); | ||
| 153 | |||
| 154 | exit (EXIT_FAILURE); | ||
| 155 | } | ||
| 156 | |||
| 157 | fp = fopen ("debug.dot", "w"); | ||
| 158 | if (fname == NULL) { | ||
| 159 | ia32_graphviz_func_out (fp, flist, flist_count, reloc_text); | ||
| 160 | } else { | ||
| 161 | ia32_function * func; | ||
| 162 | |||
| 163 | func = ia32_func_list_find_byname (flist, flist_count, | ||
| 164 | fname); | ||
| 165 | if (func == NULL) { | ||
| 166 | fprintf (stderr, "no such function: \"%s\"\n", | ||
| 167 | fname); | ||
| 168 | |||
| 169 | exit (EXIT_FAILURE); | ||
| 170 | } | ||
| 171 | |||
| 172 | ia32_graphviz_func_out_calltree (fp, flist, flist_count, | ||
| 173 | func); | ||
| 174 | } | ||
| 175 | fclose (fp); | ||
| 176 | |||
| 177 | if (visual) { | ||
| 178 | system ("dot -Tps -o debug.ps debug.dot"); | ||
| 179 | system ("gv debug.ps"); | ||
| 180 | } | ||
| 181 | |||
| 182 | |||
| 183 | for (n = 0 ; dump_func && n < flist_count ; ++n) { | ||
| 184 | char outname[128]; | ||
| 185 | |||
| 186 | snprintf (outname, sizeof (outname), "%s.bin", flist[n]->name); | ||
| 187 | outname[sizeof (outname) - 1] = '\0'; | ||
| 188 | |||
| 189 | fp = fopen (outname, "wb"); | ||
| 190 | fwrite (flist[n]->mem, 1, flist[n]->end - flist[n]->start, fp); | ||
| 191 | fclose (fp); | ||
| 192 | |||
| 193 | snprintf (outname, sizeof (outname), "%s.asm", flist[n]->name); | ||
| 194 | outname[sizeof (outname) - 1] = '\0'; | ||
| 195 | |||
| 196 | fp = fopen (outname, "w"); | ||
| 197 | function_dump (fp, flist[n]); | ||
| 198 | fclose (fp); | ||
| 199 | } | ||
| 200 | |||
| 201 | elf_base_destroy (elf); | ||
| 202 | |||
| 203 | exit (EXIT_SUCCESS); | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | void | ||
| 208 | function_dump (FILE *fp, ia32_function *func) | ||
| 209 | { | ||
| 210 | ia32_instruction * inst, | ||
| 211 | inst_s; | ||
| 212 | char inst_str[128]; | ||
| 213 | unsigned int i, | ||
| 214 | destaddr; | ||
| 215 | int resume; | ||
| 216 | |||
| 217 | |||
| 218 | i = 0; | ||
| 219 | |||
| 220 | while ((i + func->start) < func->end) { | ||
| 221 | fprintf (fp, "0x%08x(0x%08x)", func->start + i, i); | ||
| 222 | inst = ia32_decode_instruction (&func->mem[i], &inst_s); | ||
| 223 | |||
| 224 | if (inst == NULL) { | ||
| 225 | fprintf (fp, "INVALID\n"); | ||
| 226 | |||
| 227 | return; | ||
| 228 | } | ||
| 229 | |||
| 230 | ia32_sprint (inst, inst_str, sizeof (inst_str)); | ||
| 231 | fprintf (fp, "\t%s\n", inst_str); | ||
| 232 | |||
| 233 | if (OD_TEST (inst->opc.used, OP_CONTROL)) { | ||
| 234 | destaddr = ia32_trace_control (inst, &func->mem[i], | ||
| 235 | func->start + i, &resume, NULL); | ||
| 236 | |||
| 237 | fprintf (fp, "\tTRANSFER: 0x%08x, %s, %s, %s\n", destaddr, | ||
| 238 | (ia32_trace_range (func->start, func->end, | ||
| 239 | destaddr) == 1) ? "INTRA" : "INTER", | ||
| 240 | OD_TEST (inst->opc.used, OP_COND) ? "COND" : "UNCOND", | ||
| 241 | resume == 1 ? "RESUME" : "PASS"); | ||
| 242 | } | ||
| 243 | |||
| 244 | i += inst->length; | ||
| 245 | } | ||
| 246 | |||
| 247 | return; | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | #if 0 | ||
| 252 | void | ||
| 253 | function_dump (elf_file *elf, elf_section_list *slist, char *func_name, | ||
| 254 | char *section_name, unsigned int relofs, unsigned int relsize) | ||
| 255 | { | ||
| 256 | int i; | ||
| 257 | elf_section * sect = NULL; | ||
| 258 | FILE * fp; | ||
| 259 | char outname[128]; | ||
| 260 | |||
| 261 | |||
| 262 | for (i = 0 ; i < elf->Ehdr.e_shnum ; ++i) { | ||
| 263 | if (strcmp (&elf->sh_str[slist->list[i]->Shdr.sh_name], | ||
| 264 | section_name) != 0) | ||
| 265 | continue; | ||
| 266 | |||
| 267 | sect = slist->list[i]; | ||
| 268 | |||
| 269 | #if 0 | ||
| 270 | fprintf (stderr, "%2d (%2lu): ", i, slist->list[i]->sh_idx); | ||
| 271 | elf_dump_desc (elf, dh_Shdr_short, | ||
| 272 | (void *) &slist->list[i]->Shdr.sh_name, | ||
| 273 | elf->Ehdr.e_shentsize); | ||
| 274 | fprintf (stderr, "| %s\n", | ||
| 275 | &elf->sh_str[slist->list[i]->Shdr.sh_name]); | ||
| 276 | #endif | ||
| 277 | } | ||
| 278 | |||
| 279 | if (sect == NULL) | ||
| 280 | return; | ||
| 281 | |||
| 282 | relofs -= sect->Shdr.sh_addr; | ||
| 283 | if (sect->Shdr.sh_type != SHT_PROGBITS) | ||
| 284 | return; | ||
| 285 | |||
| 286 | if (sect == NULL) { | ||
| 287 | fprintf (stderr, "unable to find %s\n", section_name); | ||
| 288 | |||
| 289 | return; | ||
| 290 | } | ||
| 291 | |||
| 292 | i = 0; | ||
| 293 | |||
| 294 | snprintf (outname, sizeof (outname), "%s.bin", func_name); | ||
| 295 | outname[sizeof (outname) - 1] = '\0'; | ||
| 296 | |||
| 297 | fp = fopen (outname, "wb"); | ||
| 298 | fwrite (sect->data + relofs, 1, relsize, fp); | ||
| 299 | fclose (fp); | ||
| 300 | |||
| 301 | snprintf (outname, sizeof (outname), "%s.asm", func_name); | ||
| 302 | outname[sizeof (outname) - 1] = '\0'; | ||
| 303 | |||
| 304 | fp = fopen (outname, "w"); | ||
| 305 | |||
| 306 | while (i < relsize && (i + relofs) < sect->data_len) { | ||
| 307 | ia32_instruction * inst, | ||
| 308 | inst_s; | ||
| 309 | char inst_str[128]; | ||
| 310 | unsigned int destaddr; | ||
| 311 | int resume; | ||
| 312 | |||
| 313 | |||
| 314 | fprintf (fp, "0x%08x(0x%08x)", sect->Shdr.sh_addr + i + relofs, | ||
| 315 | i); | ||
| 316 | inst = ia32_decode_instruction (§->data[i + relofs], &inst_s); | ||
| 317 | |||
| 318 | if (inst == NULL) { | ||
| 319 | fprintf (fp, "INVALID\n"); | ||
| 320 | |||
| 321 | return; | ||
| 322 | } | ||
| 323 | |||
| 324 | ia32_sprint (inst, inst_str, sizeof (inst_str)); | ||
| 325 | fprintf (fp, "\t%s\n", inst_str); | ||
| 326 | |||
| 327 | if (OD_TEST (inst->opc.used, OP_CONTROL)) { | ||
| 328 | destaddr = ia32_trace_control (inst, §->data[i + relofs], | ||
| 329 | sect->Shdr.sh_addr + i + relofs, &resume); | ||
| 330 | |||
| 331 | fprintf (fp, "\tTRANSFER: 0x%08x, %s, %s, %s\n", destaddr, | ||
| 332 | (ia32_trace_range (sect->Shdr.sh_addr + relofs, | ||
| 333 | sect->Shdr.sh_addr + relofs + relsize, | ||
| 334 | destaddr) == 1) ? "INTRA" : "INTER", | ||
| 335 | OD_TEST (inst->opc.used, OP_COND) ? "COND" : "UNCOND", | ||
| 336 | resume == 1 ? "RESUME" : "PASS"); | ||
| 337 | } | ||
| 338 | |||
| 339 | i += inst->length; | ||
| 340 | } | ||
| 341 | |||
| 342 | fprintf (fp, "\n"); | ||
| 343 | fclose (fp); | ||
| 344 | } | ||
| 345 | |||
| 346 | #endif | ||
| 347 | |||
