summaryrefslogtreecommitdiff
path: root/other/burneye2/elf/function-extract.c
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /other/burneye2/elf/function-extract.c
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/burneye2/elf/function-extract.c')
-rw-r--r--other/burneye2/elf/function-extract.c347
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
20extern dump_header dh_Shdr_short[];
21extern dump_header dh_Shdr[];
22
23
24extern int ia32_verbosity;
25extern int ia32_graphviz_align_undefined;
26
27
28void
29function_dump (FILE *fp, ia32_function *func);
30
31
32int dump_asm = 1;
33char * progname;
34char * binary;
35
36
37void
38usage (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
56int dump_func = 0;
57int visual = 0;
58int warn_extern = 0;
59char * fname = NULL;
60
61
62int
63main (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
207void
208function_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
252void
253function_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 (&sect->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, &sect->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