rlm@1
|
1 #include <cstdio>
|
rlm@1
|
2 #include <cstdlib>
|
rlm@1
|
3 #include <cstring>
|
rlm@1
|
4
|
rlm@1
|
5 #include "../Port.h"
|
rlm@1
|
6 #include "../NLS.h"
|
rlm@1
|
7 #include "../common/System.h" // systemMessage
|
rlm@1
|
8 #include "GBAGlobals.h"
|
rlm@1
|
9 #include "elf.h"
|
rlm@1
|
10
|
rlm@1
|
11 #define elfReadMemory(addr) \
|
rlm@1
|
12 READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
rlm@1
|
13
|
rlm@1
|
14 #define DW_TAG_array_type 0x01
|
rlm@1
|
15 #define DW_TAG_enumeration_type 0x04
|
rlm@1
|
16 #define DW_TAG_formal_parameter 0x05
|
rlm@1
|
17 #define DW_TAG_label 0x0a
|
rlm@1
|
18 #define DW_TAG_lexical_block 0x0b
|
rlm@1
|
19 #define DW_TAG_member 0x0d
|
rlm@1
|
20 #define DW_TAG_pointer_type 0x0f
|
rlm@1
|
21 #define DW_TAG_reference_type 0x10
|
rlm@1
|
22 #define DW_TAG_compile_unit 0x11
|
rlm@1
|
23 #define DW_TAG_structure_type 0x13
|
rlm@1
|
24 #define DW_TAG_subroutine_type 0x15
|
rlm@1
|
25 #define DW_TAG_typedef 0x16
|
rlm@1
|
26 #define DW_TAG_union_type 0x17
|
rlm@1
|
27 #define DW_TAG_unspecified_parameters 0x18
|
rlm@1
|
28 #define DW_TAG_inheritance 0x1c
|
rlm@1
|
29 #define DW_TAG_inlined_subroutine 0x1d
|
rlm@1
|
30 #define DW_TAG_subrange_type 0x21
|
rlm@1
|
31 #define DW_TAG_base_type 0x24
|
rlm@1
|
32 #define DW_TAG_const_type 0x26
|
rlm@1
|
33 #define DW_TAG_enumerator 0x28
|
rlm@1
|
34 #define DW_TAG_subprogram 0x2e
|
rlm@1
|
35 #define DW_TAG_variable 0x34
|
rlm@1
|
36 #define DW_TAG_volatile_type 0x35
|
rlm@1
|
37
|
rlm@1
|
38 #define DW_AT_sibling 0x01
|
rlm@1
|
39 #define DW_AT_location 0x02
|
rlm@1
|
40 #define DW_AT_name 0x03
|
rlm@1
|
41 #define DW_AT_byte_size 0x0b
|
rlm@1
|
42 #define DW_AT_bit_offset 0x0c
|
rlm@1
|
43 #define DW_AT_bit_size 0x0d
|
rlm@1
|
44 #define DW_AT_stmt_list 0x10
|
rlm@1
|
45 #define DW_AT_low_pc 0x11
|
rlm@1
|
46 #define DW_AT_high_pc 0x12
|
rlm@1
|
47 #define DW_AT_language 0x13
|
rlm@1
|
48 #define DW_AT_compdir 0x1b
|
rlm@1
|
49 #define DW_AT_const_value 0x1c
|
rlm@1
|
50 #define DW_AT_containing_type 0x1d
|
rlm@1
|
51 #define DW_AT_inline 0x20
|
rlm@1
|
52 #define DW_AT_producer 0x25
|
rlm@1
|
53 #define DW_AT_prototyped 0x27
|
rlm@1
|
54 #define DW_AT_upper_bound 0x2f
|
rlm@1
|
55 #define DW_AT_abstract_origin 0x31
|
rlm@1
|
56 #define DW_AT_accessibility 0x32
|
rlm@1
|
57 #define DW_AT_artificial 0x34
|
rlm@1
|
58 #define DW_AT_data_member_location 0x38
|
rlm@1
|
59 #define DW_AT_decl_file 0x3a
|
rlm@1
|
60 #define DW_AT_decl_line 0x3b
|
rlm@1
|
61 #define DW_AT_declaration 0x3c
|
rlm@1
|
62 #define DW_AT_encoding 0x3e
|
rlm@1
|
63 #define DW_AT_external 0x3f
|
rlm@1
|
64 #define DW_AT_frame_base 0x40
|
rlm@1
|
65 #define DW_AT_macro_info 0x43
|
rlm@1
|
66 #define DW_AT_specification 0x47
|
rlm@1
|
67 #define DW_AT_type 0x49
|
rlm@1
|
68 #define DW_AT_virtuality 0x4c
|
rlm@1
|
69 #define DW_AT_vtable_elem_location 0x4d
|
rlm@1
|
70 // DWARF 2.1/3.0 extensions
|
rlm@1
|
71 #define DW_AT_entry_pc 0x52
|
rlm@1
|
72 #define DW_AT_ranges 0x55
|
rlm@1
|
73 // ARM Compiler extensions
|
rlm@1
|
74 #define DW_AT_proc_body 0x2000
|
rlm@1
|
75 #define DW_AT_save_offset 0x2001
|
rlm@1
|
76 #define DW_AT_user_2002 0x2002
|
rlm@1
|
77 // MIPS extensions
|
rlm@1
|
78 #define DW_AT_MIPS_linkage_name 0x2007
|
rlm@1
|
79
|
rlm@1
|
80 #define DW_FORM_addr 0x01
|
rlm@1
|
81 #define DW_FORM_data2 0x05
|
rlm@1
|
82 #define DW_FORM_data4 0x06
|
rlm@1
|
83 #define DW_FORM_string 0x08
|
rlm@1
|
84 #define DW_FORM_block 0x09
|
rlm@1
|
85 #define DW_FORM_block1 0x0a
|
rlm@1
|
86 #define DW_FORM_data1 0x0b
|
rlm@1
|
87 #define DW_FORM_flag 0x0c
|
rlm@1
|
88 #define DW_FORM_sdata 0x0d
|
rlm@1
|
89 #define DW_FORM_strp 0x0e
|
rlm@1
|
90 #define DW_FORM_udata 0x0f
|
rlm@1
|
91 #define DW_FORM_ref_addr 0x10
|
rlm@1
|
92 #define DW_FORM_ref4 0x13
|
rlm@1
|
93 #define DW_FORM_ref_udata 0x15
|
rlm@1
|
94 #define DW_FORM_indirect 0x16
|
rlm@1
|
95
|
rlm@1
|
96 #define DW_OP_addr 0x03
|
rlm@1
|
97 #define DW_OP_plus_uconst 0x23
|
rlm@1
|
98 #define DW_OP_reg0 0x50
|
rlm@1
|
99 #define DW_OP_reg1 0x51
|
rlm@1
|
100 #define DW_OP_reg2 0x52
|
rlm@1
|
101 #define DW_OP_reg3 0x53
|
rlm@1
|
102 #define DW_OP_reg4 0x54
|
rlm@1
|
103 #define DW_OP_reg5 0x55
|
rlm@1
|
104 #define DW_OP_reg6 0x56
|
rlm@1
|
105 #define DW_OP_reg7 0x57
|
rlm@1
|
106 #define DW_OP_reg8 0x58
|
rlm@1
|
107 #define DW_OP_reg9 0x59
|
rlm@1
|
108 #define DW_OP_reg10 0x5a
|
rlm@1
|
109 #define DW_OP_reg11 0x5b
|
rlm@1
|
110 #define DW_OP_reg12 0x5c
|
rlm@1
|
111 #define DW_OP_reg13 0x5d
|
rlm@1
|
112 #define DW_OP_reg14 0x5e
|
rlm@1
|
113 #define DW_OP_reg15 0x5f
|
rlm@1
|
114 #define DW_OP_fbreg 0x91
|
rlm@1
|
115
|
rlm@1
|
116 #define DW_LNS_extended_op 0x00
|
rlm@1
|
117 #define DW_LNS_copy 0x01
|
rlm@1
|
118 #define DW_LNS_advance_pc 0x02
|
rlm@1
|
119 #define DW_LNS_advance_line 0x03
|
rlm@1
|
120 #define DW_LNS_set_file 0x04
|
rlm@1
|
121 #define DW_LNS_set_column 0x05
|
rlm@1
|
122 #define DW_LNS_negate_stmt 0x06
|
rlm@1
|
123 #define DW_LNS_set_basic_block 0x07
|
rlm@1
|
124 #define DW_LNS_const_add_pc 0x08
|
rlm@1
|
125 #define DW_LNS_fixed_advance_pc 0x09
|
rlm@1
|
126
|
rlm@1
|
127 #define DW_LNE_end_sequence 0x01
|
rlm@1
|
128 #define DW_LNE_set_address 0x02
|
rlm@1
|
129 #define DW_LNE_define_file 0x03
|
rlm@1
|
130
|
rlm@1
|
131 #define DW_CFA_advance_loc 0x01
|
rlm@1
|
132 #define DW_CFA_offset 0x02
|
rlm@1
|
133 #define DW_CFA_restore 0x03
|
rlm@1
|
134 #define DW_CFA_set_loc 0x01
|
rlm@1
|
135 #define DW_CFA_advance_loc1 0x02
|
rlm@1
|
136 #define DW_CFA_advance_loc2 0x03
|
rlm@1
|
137 #define DW_CFA_advance_loc4 0x04
|
rlm@1
|
138 #define DW_CFA_offset_extended 0x05
|
rlm@1
|
139 #define DW_CFA_restore_extended 0x06
|
rlm@1
|
140 #define DW_CFA_undefined 0x07
|
rlm@1
|
141 #define DW_CFA_same_value 0x08
|
rlm@1
|
142 #define DW_CFA_register 0x09
|
rlm@1
|
143 #define DW_CFA_remember_state 0x0a
|
rlm@1
|
144 #define DW_CFA_restore_state 0x0b
|
rlm@1
|
145 #define DW_CFA_def_cfa 0x0c
|
rlm@1
|
146 #define DW_CFA_def_cfa_register 0x0d
|
rlm@1
|
147 #define DW_CFA_def_cfa_offset 0x0e
|
rlm@1
|
148 #define DW_CFA_nop 0x00
|
rlm@1
|
149
|
rlm@1
|
150 #define CASE_TYPE_TAG \
|
rlm@1
|
151 case DW_TAG_const_type: \
|
rlm@1
|
152 case DW_TAG_volatile_type: \
|
rlm@1
|
153 case DW_TAG_pointer_type: \
|
rlm@1
|
154 case DW_TAG_base_type: \
|
rlm@1
|
155 case DW_TAG_array_type: \
|
rlm@1
|
156 case DW_TAG_structure_type: \
|
rlm@1
|
157 case DW_TAG_union_type: \
|
rlm@1
|
158 case DW_TAG_typedef: \
|
rlm@1
|
159 case DW_TAG_subroutine_type: \
|
rlm@1
|
160 case DW_TAG_enumeration_type: \
|
rlm@1
|
161 case DW_TAG_enumerator: \
|
rlm@1
|
162 case DW_TAG_reference_type
|
rlm@1
|
163
|
rlm@1
|
164 struct ELFcie
|
rlm@1
|
165 {
|
rlm@1
|
166 ELFcie *next;
|
rlm@1
|
167 u32 offset;
|
rlm@1
|
168 u8 * augmentation;
|
rlm@1
|
169 u32 codeAlign;
|
rlm@1
|
170 s32 dataAlign;
|
rlm@1
|
171 int returnAddress;
|
rlm@1
|
172 u8 * data;
|
rlm@1
|
173 u32 dataLen;
|
rlm@1
|
174 };
|
rlm@1
|
175
|
rlm@1
|
176 struct ELFfde
|
rlm@1
|
177 {
|
rlm@1
|
178 ELFcie *cie;
|
rlm@1
|
179 u32 address;
|
rlm@1
|
180 u32 end;
|
rlm@1
|
181 u8 * data;
|
rlm@1
|
182 u32 dataLen;
|
rlm@1
|
183 };
|
rlm@1
|
184
|
rlm@1
|
185 enum ELFRegMode
|
rlm@1
|
186 {
|
rlm@1
|
187 REG_NOT_SET,
|
rlm@1
|
188 REG_OFFSET,
|
rlm@1
|
189 REG_REGISTER
|
rlm@1
|
190 };
|
rlm@1
|
191
|
rlm@1
|
192 struct ELFFrameStateRegister
|
rlm@1
|
193 {
|
rlm@1
|
194 ELFRegMode mode;
|
rlm@1
|
195 int reg;
|
rlm@1
|
196 s32 offset;
|
rlm@1
|
197 };
|
rlm@1
|
198
|
rlm@1
|
199 struct ELFFrameStateRegisters
|
rlm@1
|
200 {
|
rlm@1
|
201 ELFFrameStateRegister regs[16];
|
rlm@1
|
202 ELFFrameStateRegisters *previous;
|
rlm@1
|
203 };
|
rlm@1
|
204
|
rlm@1
|
205 enum ELFCfaMode
|
rlm@1
|
206 {
|
rlm@1
|
207 CFA_NOT_SET,
|
rlm@1
|
208 CFA_REG_OFFSET
|
rlm@1
|
209 };
|
rlm@1
|
210
|
rlm@1
|
211 struct ELFFrameState
|
rlm@1
|
212 {
|
rlm@1
|
213 ELFFrameStateRegisters registers;
|
rlm@1
|
214
|
rlm@1
|
215 ELFCfaMode cfaMode;
|
rlm@1
|
216 int cfaRegister;
|
rlm@1
|
217 s32 cfaOffset;
|
rlm@1
|
218
|
rlm@1
|
219 u32 pc;
|
rlm@1
|
220
|
rlm@1
|
221 int dataAlign;
|
rlm@1
|
222 int codeAlign;
|
rlm@1
|
223 int returnAddress;
|
rlm@1
|
224 };
|
rlm@1
|
225
|
rlm@1
|
226 extern bool8 cpuIsMultiBoot;
|
rlm@1
|
227
|
rlm@1
|
228 Symbol *elfSymbols = NULL;
|
rlm@1
|
229 char * elfSymbolsStrTab = NULL;
|
rlm@1
|
230 int elfSymbolsCount = 0;
|
rlm@1
|
231
|
rlm@1
|
232 ELFSectionHeader **elfSectionHeaders = NULL;
|
rlm@1
|
233 char *elfSectionHeadersStringTable = NULL;
|
rlm@1
|
234 int elfSectionHeadersCount = 0;
|
rlm@1
|
235 u8 * elfFileData = NULL;
|
rlm@1
|
236
|
rlm@1
|
237 CompileUnit *elfCompileUnits = NULL;
|
rlm@1
|
238 DebugInfo * elfDebugInfo = NULL;
|
rlm@1
|
239 char * elfDebugStrings = NULL;
|
rlm@1
|
240
|
rlm@1
|
241 ELFcie * elfCies = NULL;
|
rlm@1
|
242 ELFfde **elfFdes = NULL;
|
rlm@1
|
243 int elfFdeCount = 0;
|
rlm@1
|
244
|
rlm@1
|
245 CompileUnit *elfCurrentUnit = NULL;
|
rlm@1
|
246
|
rlm@1
|
247 u32 elfRead4Bytes(u8 *);
|
rlm@1
|
248 u16 elfRead2Bytes(u8 *);
|
rlm@1
|
249
|
rlm@1
|
250 CompileUnit *elfGetCompileUnit(u32 addr)
|
rlm@1
|
251 {
|
rlm@1
|
252 if (elfCompileUnits)
|
rlm@1
|
253 {
|
rlm@1
|
254 CompileUnit *unit = elfCompileUnits;
|
rlm@1
|
255 while (unit)
|
rlm@1
|
256 {
|
rlm@1
|
257 if (unit->lowPC)
|
rlm@1
|
258 {
|
rlm@1
|
259 if (addr >= unit->lowPC && addr < unit->highPC)
|
rlm@1
|
260 return unit;
|
rlm@1
|
261 }
|
rlm@1
|
262 else
|
rlm@1
|
263 {
|
rlm@1
|
264 ARanges *r = unit->ranges;
|
rlm@1
|
265 if (r)
|
rlm@1
|
266 {
|
rlm@1
|
267 int count = r->count;
|
rlm@1
|
268 for (int j = 0; j < count; j++)
|
rlm@1
|
269 {
|
rlm@1
|
270 if (addr >= r->ranges[j].lowPC && addr < r->ranges[j].highPC)
|
rlm@1
|
271 return unit;
|
rlm@1
|
272 }
|
rlm@1
|
273 }
|
rlm@1
|
274 }
|
rlm@1
|
275 unit = unit->next;
|
rlm@1
|
276 }
|
rlm@1
|
277 }
|
rlm@1
|
278 return NULL;
|
rlm@1
|
279 }
|
rlm@1
|
280
|
rlm@1
|
281 char *elfGetAddressSymbol(u32 addr)
|
rlm@1
|
282 {
|
rlm@1
|
283 static char buffer[256];
|
rlm@1
|
284
|
rlm@1
|
285 CompileUnit *unit = elfGetCompileUnit(addr);
|
rlm@1
|
286 // found unit, need to find function
|
rlm@1
|
287 if (unit)
|
rlm@1
|
288 {
|
rlm@1
|
289 Function *func = unit->functions;
|
rlm@1
|
290 while (func)
|
rlm@1
|
291 {
|
rlm@1
|
292 if (addr >= func->lowPC && addr < func->highPC)
|
rlm@1
|
293 {
|
rlm@1
|
294 int offset = addr - func->lowPC;
|
rlm@1
|
295 char *name = func->name;
|
rlm@1
|
296 if (!name)
|
rlm@1
|
297 name = "";
|
rlm@1
|
298 if (offset)
|
rlm@1
|
299 sprintf(buffer, "%s+%d", name, offset);
|
rlm@1
|
300 else
|
rlm@1
|
301 strcpy(buffer, name);
|
rlm@1
|
302 return buffer;
|
rlm@1
|
303 }
|
rlm@1
|
304 func = func->next;
|
rlm@1
|
305 }
|
rlm@1
|
306 }
|
rlm@1
|
307
|
rlm@1
|
308 if (elfSymbolsCount)
|
rlm@1
|
309 {
|
rlm@1
|
310 for (int i = 0; i < elfSymbolsCount; i++)
|
rlm@1
|
311 {
|
rlm@1
|
312 Symbol *s = &elfSymbols[i];
|
rlm@1
|
313 if ((addr >= s->value) && addr < (s->value+s->size))
|
rlm@1
|
314 {
|
rlm@1
|
315 int offset = addr-s->value;
|
rlm@1
|
316 char *name = s->name;
|
rlm@1
|
317 if (name == NULL)
|
rlm@1
|
318 name = "";
|
rlm@1
|
319 if (offset)
|
rlm@1
|
320 sprintf(buffer, "%s+%d", name, addr-s->value);
|
rlm@1
|
321 else
|
rlm@1
|
322 strcpy(buffer, name);
|
rlm@1
|
323 return buffer;
|
rlm@1
|
324 }
|
rlm@1
|
325 else if (addr == s->value)
|
rlm@1
|
326 {
|
rlm@1
|
327 if (s->name)
|
rlm@1
|
328 strcpy(buffer, s->name);
|
rlm@1
|
329 else
|
rlm@1
|
330 strcpy(buffer, "");
|
rlm@1
|
331 return buffer;
|
rlm@1
|
332 }
|
rlm@1
|
333 }
|
rlm@1
|
334 }
|
rlm@1
|
335
|
rlm@1
|
336 return "";
|
rlm@1
|
337 }
|
rlm@1
|
338
|
rlm@1
|
339 bool elfFindLineInModule(u32 *addr, char *name, int line)
|
rlm@1
|
340 {
|
rlm@1
|
341 CompileUnit *unit = elfCompileUnits;
|
rlm@1
|
342
|
rlm@1
|
343 while (unit)
|
rlm@1
|
344 {
|
rlm@1
|
345 if (unit->lineInfoTable)
|
rlm@1
|
346 {
|
rlm@1
|
347 int i;
|
rlm@1
|
348 int count = unit->lineInfoTable->fileCount;
|
rlm@1
|
349 char *found = NULL;
|
rlm@1
|
350 for (i = 0; i < count; i++)
|
rlm@1
|
351 {
|
rlm@1
|
352 if (strcmp(name, unit->lineInfoTable->files[i]) == 0)
|
rlm@1
|
353 {
|
rlm@1
|
354 found = unit->lineInfoTable->files[i];
|
rlm@1
|
355 break;
|
rlm@1
|
356 }
|
rlm@1
|
357 }
|
rlm@1
|
358 // found a matching filename... try to find line now
|
rlm@1
|
359 if (found)
|
rlm@1
|
360 {
|
rlm@1
|
361 LineInfoItem *table = unit->lineInfoTable->lines;
|
rlm@1
|
362 count = unit->lineInfoTable->number;
|
rlm@1
|
363 for (i = 0; i < count; i++)
|
rlm@1
|
364 {
|
rlm@1
|
365 if (table[i].file == found && table[i].line == line)
|
rlm@1
|
366 {
|
rlm@1
|
367 *addr = table[i].address;
|
rlm@1
|
368 return true;
|
rlm@1
|
369 }
|
rlm@1
|
370 }
|
rlm@1
|
371 // we can only find a single match
|
rlm@1
|
372 return false;
|
rlm@1
|
373 }
|
rlm@1
|
374 }
|
rlm@1
|
375 unit = unit->next;
|
rlm@1
|
376 }
|
rlm@1
|
377 return false;
|
rlm@1
|
378 }
|
rlm@1
|
379
|
rlm@1
|
380 int elfFindLine(CompileUnit *unit, Function * /* func */, u32 addr, char **f)
|
rlm@1
|
381 {
|
rlm@1
|
382 int currentLine = -1;
|
rlm@1
|
383 if (unit->hasLineInfo)
|
rlm@1
|
384 {
|
rlm@1
|
385 int count = unit->lineInfoTable->number;
|
rlm@1
|
386 LineInfoItem *table = unit->lineInfoTable->lines;
|
rlm@1
|
387 int i;
|
rlm@1
|
388 for (i = 0; i < count; i++)
|
rlm@1
|
389 {
|
rlm@1
|
390 if (addr <= table[i].address)
|
rlm@1
|
391 break;
|
rlm@1
|
392 }
|
rlm@1
|
393 if (i == count)
|
rlm@1
|
394 i--;
|
rlm@1
|
395 *f = table[i].file;
|
rlm@1
|
396 currentLine = table[i].line;
|
rlm@1
|
397 }
|
rlm@1
|
398 return currentLine;
|
rlm@1
|
399 }
|
rlm@1
|
400
|
rlm@1
|
401 bool elfFindLineInUnit(u32 *addr, CompileUnit *unit, int line)
|
rlm@1
|
402 {
|
rlm@1
|
403 if (unit->hasLineInfo)
|
rlm@1
|
404 {
|
rlm@1
|
405 int count = unit->lineInfoTable->number;
|
rlm@1
|
406 LineInfoItem *table = unit->lineInfoTable->lines;
|
rlm@1
|
407 int i;
|
rlm@1
|
408 for (i = 0; i < count; i++)
|
rlm@1
|
409 {
|
rlm@1
|
410 if (line == table[i].line)
|
rlm@1
|
411 {
|
rlm@1
|
412 *addr = table[i].address;
|
rlm@1
|
413 return true;
|
rlm@1
|
414 }
|
rlm@1
|
415 }
|
rlm@1
|
416 }
|
rlm@1
|
417 return false;
|
rlm@1
|
418 }
|
rlm@1
|
419
|
rlm@1
|
420 bool elfGetCurrentFunction(u32 addr, Function **f, CompileUnit **u)
|
rlm@1
|
421 {
|
rlm@1
|
422 CompileUnit *unit = elfGetCompileUnit(addr);
|
rlm@1
|
423 // found unit, need to find function
|
rlm@1
|
424 if (unit)
|
rlm@1
|
425 {
|
rlm@1
|
426 Function *func = unit->functions;
|
rlm@1
|
427 while (func)
|
rlm@1
|
428 {
|
rlm@1
|
429 if (addr >= func->lowPC && addr < func->highPC)
|
rlm@1
|
430 {
|
rlm@1
|
431 *f = func;
|
rlm@1
|
432 *u = unit;
|
rlm@1
|
433 return true;
|
rlm@1
|
434 }
|
rlm@1
|
435 func = func->next;
|
rlm@1
|
436 }
|
rlm@1
|
437 }
|
rlm@1
|
438 return false;
|
rlm@1
|
439 }
|
rlm@1
|
440
|
rlm@1
|
441 bool elfGetObject(char *name, Function *f, CompileUnit *u, Object **o)
|
rlm@1
|
442 {
|
rlm@1
|
443 if (f && u)
|
rlm@1
|
444 {
|
rlm@1
|
445 Object *v = f->variables;
|
rlm@1
|
446
|
rlm@1
|
447 while (v)
|
rlm@1
|
448 {
|
rlm@1
|
449 if (strcmp(name, v->name) == 0)
|
rlm@1
|
450 {
|
rlm@1
|
451 *o = v;
|
rlm@1
|
452 return true;
|
rlm@1
|
453 }
|
rlm@1
|
454 v = v->next;
|
rlm@1
|
455 }
|
rlm@1
|
456 v = f->parameters;
|
rlm@1
|
457 while (v)
|
rlm@1
|
458 {
|
rlm@1
|
459 if (strcmp(name, v->name) == 0)
|
rlm@1
|
460 {
|
rlm@1
|
461 *o = v;
|
rlm@1
|
462 return true;
|
rlm@1
|
463 }
|
rlm@1
|
464 v = v->next;
|
rlm@1
|
465 }
|
rlm@1
|
466 v = u->variables;
|
rlm@1
|
467 while (v)
|
rlm@1
|
468 {
|
rlm@1
|
469 if (strcmp(name, v->name) == 0)
|
rlm@1
|
470 {
|
rlm@1
|
471 *o = v;
|
rlm@1
|
472 return true;
|
rlm@1
|
473 }
|
rlm@1
|
474 v = v->next;
|
rlm@1
|
475 }
|
rlm@1
|
476 }
|
rlm@1
|
477
|
rlm@1
|
478 CompileUnit *c = elfCompileUnits;
|
rlm@1
|
479
|
rlm@1
|
480 while (c)
|
rlm@1
|
481 {
|
rlm@1
|
482 if (c != u)
|
rlm@1
|
483 {
|
rlm@1
|
484 Object *v = c->variables;
|
rlm@1
|
485 while (v)
|
rlm@1
|
486 {
|
rlm@1
|
487 if (strcmp(name, v->name) == 0)
|
rlm@1
|
488 {
|
rlm@1
|
489 *o = v;
|
rlm@1
|
490 return true;
|
rlm@1
|
491 }
|
rlm@1
|
492 v = v->next;
|
rlm@1
|
493 }
|
rlm@1
|
494 }
|
rlm@1
|
495 c = c->next;
|
rlm@1
|
496 }
|
rlm@1
|
497
|
rlm@1
|
498 return false;
|
rlm@1
|
499 }
|
rlm@1
|
500
|
rlm@1
|
501 char *elfGetSymbol(int i, u32 *value, u32 *size, int *type)
|
rlm@1
|
502 {
|
rlm@1
|
503 if (i < elfSymbolsCount)
|
rlm@1
|
504 {
|
rlm@1
|
505 Symbol *s = &elfSymbols[i];
|
rlm@1
|
506 *value = s->value;
|
rlm@1
|
507 *size = s->size;
|
rlm@1
|
508 *type = s->type;
|
rlm@1
|
509 return s->name;
|
rlm@1
|
510 }
|
rlm@1
|
511 return NULL;
|
rlm@1
|
512 }
|
rlm@1
|
513
|
rlm@1
|
514 bool elfGetSymbolAddress(char *sym, u32 *addr, u32 *size, int *type)
|
rlm@1
|
515 {
|
rlm@1
|
516 if (elfSymbolsCount)
|
rlm@1
|
517 {
|
rlm@1
|
518 for (int i = 0; i < elfSymbolsCount; i++)
|
rlm@1
|
519 {
|
rlm@1
|
520 Symbol *s = &elfSymbols[i];
|
rlm@1
|
521 if (strcmp(sym, s->name) == 0)
|
rlm@1
|
522 {
|
rlm@1
|
523 *addr = s->value;
|
rlm@1
|
524 *size = s->size;
|
rlm@1
|
525 *type = s->type;
|
rlm@1
|
526 return true;
|
rlm@1
|
527 }
|
rlm@1
|
528 }
|
rlm@1
|
529 }
|
rlm@1
|
530 return false;
|
rlm@1
|
531 }
|
rlm@1
|
532
|
rlm@1
|
533 ELFfde *elfGetFde(u32 address)
|
rlm@1
|
534 {
|
rlm@1
|
535 if (elfFdes)
|
rlm@1
|
536 {
|
rlm@1
|
537 int i;
|
rlm@1
|
538 for (i = 0; i < elfFdeCount; i++)
|
rlm@1
|
539 {
|
rlm@1
|
540 if (address >= elfFdes[i]->address &&
|
rlm@1
|
541 address < elfFdes[i]->end)
|
rlm@1
|
542 {
|
rlm@1
|
543 return elfFdes[i];
|
rlm@1
|
544 }
|
rlm@1
|
545 }
|
rlm@1
|
546 }
|
rlm@1
|
547
|
rlm@1
|
548 return NULL;
|
rlm@1
|
549 }
|
rlm@1
|
550
|
rlm@1
|
551 void elfExecuteCFAInstructions(ELFFrameState *state, u8 *data, u32 len,
|
rlm@1
|
552 u32 pc)
|
rlm@1
|
553 {
|
rlm@1
|
554 u8 *end = data + len;
|
rlm@1
|
555 int bytes;
|
rlm@1
|
556 int reg;
|
rlm@1
|
557 ELFFrameStateRegisters *fs;
|
rlm@1
|
558
|
rlm@1
|
559 while (data < end && state->pc < pc)
|
rlm@1
|
560 {
|
rlm@1
|
561 u8 op = *data++;
|
rlm@1
|
562
|
rlm@1
|
563 switch (op >> 6)
|
rlm@1
|
564 {
|
rlm@1
|
565 case DW_CFA_advance_loc:
|
rlm@1
|
566 state->pc += (op & 0x3f) * state->codeAlign;
|
rlm@1
|
567 break;
|
rlm@1
|
568 case DW_CFA_offset:
|
rlm@1
|
569 reg = op & 0x3f;
|
rlm@1
|
570 state->registers.regs[reg].mode = REG_OFFSET;
|
rlm@1
|
571 state->registers.regs[reg].offset = state->dataAlign *
|
rlm@1
|
572 (s32)elfReadLEB128(data, &bytes);
|
rlm@1
|
573 data += bytes;
|
rlm@1
|
574 break;
|
rlm@1
|
575 case DW_CFA_restore:
|
rlm@1
|
576 // we don't care much about the other possible settings,
|
rlm@1
|
577 // so just setting to unset is enough for now
|
rlm@1
|
578 state->registers.regs[op & 0x3f].mode = REG_NOT_SET;
|
rlm@1
|
579 break;
|
rlm@1
|
580 case 0:
|
rlm@1
|
581 switch (op & 0x3f)
|
rlm@1
|
582 {
|
rlm@1
|
583 case DW_CFA_nop:
|
rlm@1
|
584 break;
|
rlm@1
|
585 case DW_CFA_advance_loc1:
|
rlm@1
|
586 state->pc += state->codeAlign * (*data++);
|
rlm@1
|
587 break;
|
rlm@1
|
588 case DW_CFA_advance_loc2:
|
rlm@1
|
589 state->pc += state->codeAlign * elfRead2Bytes(data);
|
rlm@1
|
590 data += 2;
|
rlm@1
|
591 break;
|
rlm@1
|
592 case DW_CFA_advance_loc4:
|
rlm@1
|
593 state->pc += state->codeAlign * elfRead4Bytes(data);
|
rlm@1
|
594 data += 4;
|
rlm@1
|
595 break;
|
rlm@1
|
596 case DW_CFA_offset_extended:
|
rlm@1
|
597 reg = elfReadLEB128(data, &bytes);
|
rlm@1
|
598 data += bytes;
|
rlm@1
|
599 state->registers.regs[reg].mode = REG_OFFSET;
|
rlm@1
|
600 state->registers.regs[reg].offset = state->dataAlign *
|
rlm@1
|
601 (s32)elfReadLEB128(data, &bytes);
|
rlm@1
|
602 data += bytes;
|
rlm@1
|
603 break;
|
rlm@1
|
604 case DW_CFA_restore_extended:
|
rlm@1
|
605 case DW_CFA_undefined:
|
rlm@1
|
606 case DW_CFA_same_value:
|
rlm@1
|
607 reg = elfReadLEB128(data, &bytes);
|
rlm@1
|
608 data += bytes;
|
rlm@1
|
609 state->registers.regs[reg].mode = REG_NOT_SET;
|
rlm@1
|
610 break;
|
rlm@1
|
611 case DW_CFA_register:
|
rlm@1
|
612 reg = elfReadLEB128(data, &bytes);
|
rlm@1
|
613 data += bytes;
|
rlm@1
|
614 state->registers.regs[reg].mode = REG_REGISTER;
|
rlm@1
|
615 state->registers.regs[reg].reg = elfReadLEB128(data, &bytes);
|
rlm@1
|
616 data += bytes;
|
rlm@1
|
617 break;
|
rlm@1
|
618 case DW_CFA_remember_state:
|
rlm@1
|
619 fs = (ELFFrameStateRegisters *)calloc(1,
|
rlm@1
|
620 sizeof(ELFFrameStateRegisters));
|
rlm@1
|
621 memcpy(fs, &state->registers, sizeof(ELFFrameStateRegisters));
|
rlm@1
|
622 state->registers.previous = fs;
|
rlm@1
|
623 break;
|
rlm@1
|
624 case DW_CFA_restore_state:
|
rlm@1
|
625 if (state->registers.previous == NULL)
|
rlm@1
|
626 {
|
rlm@1
|
627 printf("Error: previous frame state is NULL.\n");
|
rlm@1
|
628 return;
|
rlm@1
|
629 }
|
rlm@1
|
630 fs = state->registers.previous;
|
rlm@1
|
631 memcpy(&state->registers, fs, sizeof(ELFFrameStateRegisters));
|
rlm@1
|
632 free(fs);
|
rlm@1
|
633 break;
|
rlm@1
|
634 case DW_CFA_def_cfa:
|
rlm@1
|
635 state->cfaRegister = elfReadLEB128(data, &bytes);
|
rlm@1
|
636 data += bytes;
|
rlm@1
|
637 state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
|
rlm@1
|
638 data += bytes;
|
rlm@1
|
639 state->cfaMode = CFA_REG_OFFSET;
|
rlm@1
|
640 break;
|
rlm@1
|
641 case DW_CFA_def_cfa_register:
|
rlm@1
|
642 state->cfaRegister = elfReadLEB128(data, &bytes);
|
rlm@1
|
643 data += bytes;
|
rlm@1
|
644 state->cfaMode = CFA_REG_OFFSET;
|
rlm@1
|
645 break;
|
rlm@1
|
646 case DW_CFA_def_cfa_offset:
|
rlm@1
|
647 state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
|
rlm@1
|
648 data += bytes;
|
rlm@1
|
649 state->cfaMode = CFA_REG_OFFSET;
|
rlm@1
|
650 break;
|
rlm@1
|
651 default:
|
rlm@1
|
652 printf("Unknown CFA opcode %08x\n", op);
|
rlm@1
|
653 return;
|
rlm@1
|
654 }
|
rlm@1
|
655 break;
|
rlm@1
|
656 default:
|
rlm@1
|
657 printf("Unknown CFA opcode %08x\n", op);
|
rlm@1
|
658 return;
|
rlm@1
|
659 }
|
rlm@1
|
660 }
|
rlm@1
|
661 }
|
rlm@1
|
662
|
rlm@1
|
663 ELFFrameState *elfGetFrameState(ELFfde *fde, u32 address)
|
rlm@1
|
664 {
|
rlm@1
|
665 ELFFrameState *state = (ELFFrameState *)calloc(1, sizeof(ELFFrameState));
|
rlm@1
|
666 state->pc = fde->address;
|
rlm@1
|
667 state->dataAlign = fde->cie->dataAlign;
|
rlm@1
|
668 state->codeAlign = fde->cie->codeAlign;
|
rlm@1
|
669 state->returnAddress = fde->cie->returnAddress;
|
rlm@1
|
670
|
rlm@1
|
671 elfExecuteCFAInstructions(state,
|
rlm@1
|
672 fde->cie->data,
|
rlm@1
|
673 fde->cie->dataLen,
|
rlm@1
|
674 0xffffffff);
|
rlm@1
|
675 elfExecuteCFAInstructions(state,
|
rlm@1
|
676 fde->data,
|
rlm@1
|
677 fde->dataLen,
|
rlm@1
|
678 address);
|
rlm@1
|
679
|
rlm@1
|
680 return state;
|
rlm@1
|
681 }
|
rlm@1
|
682
|
rlm@1
|
683 void elfPrintCallChain(u32 address)
|
rlm@1
|
684 {
|
rlm@1
|
685 int count = 1;
|
rlm@1
|
686
|
rlm@1
|
687 reg_pair regs[15];
|
rlm@1
|
688 reg_pair newRegs[15];
|
rlm@1
|
689
|
rlm@1
|
690 memcpy(®s[0], ®[0], sizeof(reg_pair) * 15);
|
rlm@1
|
691
|
rlm@1
|
692 while (count < 20)
|
rlm@1
|
693 {
|
rlm@1
|
694 char *addr = elfGetAddressSymbol(address);
|
rlm@1
|
695 if (*addr == 0)
|
rlm@1
|
696 addr = "???";
|
rlm@1
|
697
|
rlm@1
|
698 printf("%08x %s\n", address, addr);
|
rlm@1
|
699
|
rlm@1
|
700 ELFfde *fde = elfGetFde(address);
|
rlm@1
|
701
|
rlm@1
|
702 if (fde == NULL)
|
rlm@1
|
703 {
|
rlm@1
|
704 break;
|
rlm@1
|
705 }
|
rlm@1
|
706
|
rlm@1
|
707 ELFFrameState *state = elfGetFrameState(fde, address);
|
rlm@1
|
708
|
rlm@1
|
709 if (!state)
|
rlm@1
|
710 {
|
rlm@1
|
711 break;
|
rlm@1
|
712 }
|
rlm@1
|
713
|
rlm@1
|
714 if (state->cfaMode == CFA_REG_OFFSET)
|
rlm@1
|
715 {
|
rlm@1
|
716 memcpy(&newRegs[0], ®s[0], sizeof(reg_pair) * 15);
|
rlm@1
|
717 u32 addr = 0;
|
rlm@1
|
718 for (int i = 0; i < 15; i++)
|
rlm@1
|
719 {
|
rlm@1
|
720 ELFFrameStateRegister *r = &state->registers.
|
rlm@1
|
721 regs[i];
|
rlm@1
|
722
|
rlm@1
|
723 switch (r->mode)
|
rlm@1
|
724 {
|
rlm@1
|
725 case REG_NOT_SET:
|
rlm@1
|
726 newRegs[i].I = regs[i].I;
|
rlm@1
|
727 break;
|
rlm@1
|
728 case REG_OFFSET:
|
rlm@1
|
729 newRegs[i].I = elfReadMemory(regs[state->cfaRegister].I +
|
rlm@1
|
730 state->cfaOffset +
|
rlm@1
|
731 r->offset);
|
rlm@1
|
732 break;
|
rlm@1
|
733 case REG_REGISTER:
|
rlm@1
|
734 newRegs[i].I = regs[r->reg].I;
|
rlm@1
|
735 break;
|
rlm@1
|
736 default:
|
rlm@1
|
737 printf("Unknown register mode: %d\n", r->mode);
|
rlm@1
|
738 break;
|
rlm@1
|
739 }
|
rlm@1
|
740 }
|
rlm@1
|
741 memcpy(regs, newRegs, sizeof(reg_pair)*15);
|
rlm@1
|
742 addr = newRegs[14].I;
|
rlm@1
|
743 addr &= 0xfffffffe;
|
rlm@1
|
744 address = addr;
|
rlm@1
|
745 count++;
|
rlm@1
|
746 }
|
rlm@1
|
747 else
|
rlm@1
|
748 {
|
rlm@1
|
749 printf("CFA not set\n");
|
rlm@1
|
750 break;
|
rlm@1
|
751 }
|
rlm@1
|
752 if (state->registers.previous)
|
rlm@1
|
753 {
|
rlm@1
|
754 ELFFrameStateRegisters *prev = state->registers.previous;
|
rlm@1
|
755
|
rlm@1
|
756 while (prev)
|
rlm@1
|
757 {
|
rlm@1
|
758 ELFFrameStateRegisters *p = prev->previous;
|
rlm@1
|
759 free(prev);
|
rlm@1
|
760 prev = p;
|
rlm@1
|
761 }
|
rlm@1
|
762 }
|
rlm@1
|
763 free(state);
|
rlm@1
|
764 }
|
rlm@1
|
765 }
|
rlm@1
|
766
|
rlm@1
|
767 u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type, u32 base)
|
rlm@1
|
768 {
|
rlm@1
|
769 u32 framebase = 0;
|
rlm@1
|
770 if (f && f->frameBase)
|
rlm@1
|
771 {
|
rlm@1
|
772 ELFBlock *b = f->frameBase;
|
rlm@1
|
773 switch (*b->data)
|
rlm@1
|
774 {
|
rlm@1
|
775 case DW_OP_reg0:
|
rlm@1
|
776 case DW_OP_reg1:
|
rlm@1
|
777 case DW_OP_reg2:
|
rlm@1
|
778 case DW_OP_reg3:
|
rlm@1
|
779 case DW_OP_reg4:
|
rlm@1
|
780 case DW_OP_reg5:
|
rlm@1
|
781 case DW_OP_reg6:
|
rlm@1
|
782 case DW_OP_reg7:
|
rlm@1
|
783 case DW_OP_reg8:
|
rlm@1
|
784 case DW_OP_reg9:
|
rlm@1
|
785 case DW_OP_reg10:
|
rlm@1
|
786 case DW_OP_reg11:
|
rlm@1
|
787 case DW_OP_reg12:
|
rlm@1
|
788 case DW_OP_reg13:
|
rlm@1
|
789 case DW_OP_reg14:
|
rlm@1
|
790 case DW_OP_reg15:
|
rlm@1
|
791 framebase = reg[*b->data-0x50].I;
|
rlm@1
|
792 break;
|
rlm@1
|
793 default:
|
rlm@1
|
794 fprintf(stderr, "Unknown frameBase %02x\n", *b->data);
|
rlm@1
|
795 break;
|
rlm@1
|
796 }
|
rlm@1
|
797 }
|
rlm@1
|
798
|
rlm@1
|
799 ELFBlock *loc = o;
|
rlm@1
|
800 u32 location = 0;
|
rlm@1
|
801 int bytes = 0;
|
rlm@1
|
802 if (loc)
|
rlm@1
|
803 {
|
rlm@1
|
804 switch (*loc->data)
|
rlm@1
|
805 {
|
rlm@1
|
806 case DW_OP_addr:
|
rlm@1
|
807 location = elfRead4Bytes(loc->data+1);
|
rlm@1
|
808 *type = LOCATION_memory;
|
rlm@1
|
809 break;
|
rlm@1
|
810 case DW_OP_plus_uconst:
|
rlm@1
|
811 location = base + elfReadLEB128(loc->data+1, &bytes);
|
rlm@1
|
812 *type = LOCATION_memory;
|
rlm@1
|
813 break;
|
rlm@1
|
814 case DW_OP_reg0:
|
rlm@1
|
815 case DW_OP_reg1:
|
rlm@1
|
816 case DW_OP_reg2:
|
rlm@1
|
817 case DW_OP_reg3:
|
rlm@1
|
818 case DW_OP_reg4:
|
rlm@1
|
819 case DW_OP_reg5:
|
rlm@1
|
820 case DW_OP_reg6:
|
rlm@1
|
821 case DW_OP_reg7:
|
rlm@1
|
822 case DW_OP_reg8:
|
rlm@1
|
823 case DW_OP_reg9:
|
rlm@1
|
824 case DW_OP_reg10:
|
rlm@1
|
825 case DW_OP_reg11:
|
rlm@1
|
826 case DW_OP_reg12:
|
rlm@1
|
827 case DW_OP_reg13:
|
rlm@1
|
828 case DW_OP_reg14:
|
rlm@1
|
829 case DW_OP_reg15:
|
rlm@1
|
830 location = *loc->data - 0x50;
|
rlm@1
|
831 *type = LOCATION_register;
|
rlm@1
|
832 break;
|
rlm@1
|
833 case DW_OP_fbreg:
|
rlm@1
|
834 {
|
rlm@1
|
835 int bytes;
|
rlm@1
|
836 s32 off = elfReadSignedLEB128(loc->data+1, &bytes);
|
rlm@1
|
837 location = framebase + off;
|
rlm@1
|
838 *type = LOCATION_memory;
|
rlm@1
|
839 break;
|
rlm@1
|
840 }
|
rlm@1
|
841 default:
|
rlm@1
|
842 fprintf(stderr, "Unknown location %02x\n", *loc->data);
|
rlm@1
|
843 break;
|
rlm@1
|
844 }
|
rlm@1
|
845 }
|
rlm@1
|
846 return location;
|
rlm@1
|
847 }
|
rlm@1
|
848
|
rlm@1
|
849 u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type)
|
rlm@1
|
850 {
|
rlm@1
|
851 return elfDecodeLocation(f, o, type, 0);
|
rlm@1
|
852 }
|
rlm@1
|
853
|
rlm@1
|
854 // reading function
|
rlm@1
|
855
|
rlm@1
|
856 u32 elfRead4Bytes(u8 *data)
|
rlm@1
|
857 {
|
rlm@1
|
858 u32 value = *data++;
|
rlm@1
|
859 value |= (*data++ << 8);
|
rlm@1
|
860 value |= (*data++ << 16);
|
rlm@1
|
861 value |= (*data << 24);
|
rlm@1
|
862 return value;
|
rlm@1
|
863 }
|
rlm@1
|
864
|
rlm@1
|
865 u16 elfRead2Bytes(u8 *data)
|
rlm@1
|
866 {
|
rlm@1
|
867 u16 value = *data++;
|
rlm@1
|
868 value |= (*data << 8);
|
rlm@1
|
869 return value;
|
rlm@1
|
870 }
|
rlm@1
|
871
|
rlm@1
|
872 char *elfReadString(u8 *data, int *bytesRead)
|
rlm@1
|
873 {
|
rlm@1
|
874 if (*data == 0)
|
rlm@1
|
875 {
|
rlm@1
|
876 *bytesRead = 1;
|
rlm@1
|
877 return NULL;
|
rlm@1
|
878 }
|
rlm@1
|
879 *bytesRead = strlen((char *)data) + 1;
|
rlm@1
|
880 return (char *)data;
|
rlm@1
|
881 }
|
rlm@1
|
882
|
rlm@1
|
883 s32 elfReadSignedLEB128(u8 *data, int *bytesRead)
|
rlm@1
|
884 {
|
rlm@1
|
885 s32 result = 0;
|
rlm@1
|
886 int shift = 0;
|
rlm@1
|
887 int count = 0;
|
rlm@1
|
888
|
rlm@1
|
889 u8 byte;
|
rlm@1
|
890 do
|
rlm@1
|
891 {
|
rlm@1
|
892 byte = *data++;
|
rlm@1
|
893 count++;
|
rlm@1
|
894 result |= (byte & 0x7f) << shift;
|
rlm@1
|
895 shift += 7;
|
rlm@1
|
896 }
|
rlm@1
|
897 while (byte & 0x80);
|
rlm@1
|
898 if ((shift < 32) && (byte & 0x40))
|
rlm@1
|
899 result |= -(1 << shift);
|
rlm@1
|
900 *bytesRead = count;
|
rlm@1
|
901 return result;
|
rlm@1
|
902 }
|
rlm@1
|
903
|
rlm@1
|
904 u32 elfReadLEB128(u8 *data, int *bytesRead)
|
rlm@1
|
905 {
|
rlm@1
|
906 u32 result = 0;
|
rlm@1
|
907 int shift = 0;
|
rlm@1
|
908 int count = 0;
|
rlm@1
|
909 u8 byte;
|
rlm@1
|
910 do
|
rlm@1
|
911 {
|
rlm@1
|
912 byte = *data++;
|
rlm@1
|
913 count++;
|
rlm@1
|
914 result |= (byte & 0x7f) << shift;
|
rlm@1
|
915 shift += 7;
|
rlm@1
|
916 }
|
rlm@1
|
917 while (byte & 0x80);
|
rlm@1
|
918 *bytesRead = count;
|
rlm@1
|
919 return result;
|
rlm@1
|
920 }
|
rlm@1
|
921
|
rlm@1
|
922 u8 *elfReadSection(u8 *data, ELFSectionHeader *sh)
|
rlm@1
|
923 {
|
rlm@1
|
924 return data + READ32LE(&sh->offset);
|
rlm@1
|
925 }
|
rlm@1
|
926
|
rlm@1
|
927 ELFSectionHeader *elfGetSectionByName(char *name)
|
rlm@1
|
928 {
|
rlm@1
|
929 for (int i = 0; i < elfSectionHeadersCount; i++)
|
rlm@1
|
930 {
|
rlm@1
|
931 if (strcmp(name,
|
rlm@1
|
932 &elfSectionHeadersStringTable[READ32LE(&elfSectionHeaders[i]->
|
rlm@1
|
933 name)]) == 0)
|
rlm@1
|
934 {
|
rlm@1
|
935 return elfSectionHeaders[i];
|
rlm@1
|
936 }
|
rlm@1
|
937 }
|
rlm@1
|
938 return NULL;
|
rlm@1
|
939 }
|
rlm@1
|
940
|
rlm@1
|
941 ELFSectionHeader *elfGetSectionByNumber(int number)
|
rlm@1
|
942 {
|
rlm@1
|
943 if (number < elfSectionHeadersCount)
|
rlm@1
|
944 {
|
rlm@1
|
945 return elfSectionHeaders[number];
|
rlm@1
|
946 }
|
rlm@1
|
947 return NULL;
|
rlm@1
|
948 }
|
rlm@1
|
949
|
rlm@1
|
950 CompileUnit *elfGetCompileUnitForData(u8 *data)
|
rlm@1
|
951 {
|
rlm@1
|
952 u8 *end = elfCurrentUnit->top + 4 + elfCurrentUnit->length;
|
rlm@1
|
953
|
rlm@1
|
954 if (data >= elfCurrentUnit->top && data < end)
|
rlm@1
|
955 return elfCurrentUnit;
|
rlm@1
|
956
|
rlm@1
|
957 CompileUnit *unit = elfCompileUnits;
|
rlm@1
|
958
|
rlm@1
|
959 while (unit)
|
rlm@1
|
960 {
|
rlm@1
|
961 end = unit->top + 4 + unit->length;
|
rlm@1
|
962
|
rlm@1
|
963 if (data >= unit->top && data < end)
|
rlm@1
|
964 return unit;
|
rlm@1
|
965
|
rlm@1
|
966 unit = unit->next;
|
rlm@1
|
967 }
|
rlm@1
|
968
|
rlm@1
|
969 printf("Error: cannot find reference to compile unit at offset %08x\n",
|
rlm@1
|
970 (int)(data - elfDebugInfo->infodata));
|
rlm@1
|
971 exit(-1);
|
rlm@1
|
972 }
|
rlm@1
|
973
|
rlm@1
|
974 u8 *elfReadAttribute(u8 *data, ELFAttr *attr)
|
rlm@1
|
975 {
|
rlm@1
|
976 int bytes;
|
rlm@1
|
977 int form = attr->form;
|
rlm@1
|
978 start:
|
rlm@1
|
979 switch (form)
|
rlm@1
|
980 {
|
rlm@1
|
981 case DW_FORM_addr:
|
rlm@1
|
982 attr->value = elfRead4Bytes(data);
|
rlm@1
|
983 data += 4;
|
rlm@1
|
984 break;
|
rlm@1
|
985 case DW_FORM_data2:
|
rlm@1
|
986 attr->value = elfRead2Bytes(data);
|
rlm@1
|
987 data += 2;
|
rlm@1
|
988 break;
|
rlm@1
|
989 case DW_FORM_data4:
|
rlm@1
|
990 attr->value = elfRead4Bytes(data);
|
rlm@1
|
991 data += 4;
|
rlm@1
|
992 break;
|
rlm@1
|
993 case DW_FORM_string:
|
rlm@1
|
994 attr->string = (char *)data;
|
rlm@1
|
995 data += strlen(attr->string)+1;
|
rlm@1
|
996 break;
|
rlm@1
|
997 case DW_FORM_strp:
|
rlm@1
|
998 attr->string = elfDebugStrings + elfRead4Bytes(data);
|
rlm@1
|
999 data += 4;
|
rlm@1
|
1000 break;
|
rlm@1
|
1001 case DW_FORM_block:
|
rlm@1
|
1002 attr->block = (ELFBlock *)malloc(sizeof(ELFBlock));
|
rlm@1
|
1003 attr->block->length = elfReadLEB128(data, &bytes);
|
rlm@1
|
1004 data += bytes;
|
rlm@1
|
1005 attr->block->data = data;
|
rlm@1
|
1006 data += attr->block->length;
|
rlm@1
|
1007 break;
|
rlm@1
|
1008 case DW_FORM_block1:
|
rlm@1
|
1009 attr->block = (ELFBlock *)malloc(sizeof(ELFBlock));
|
rlm@1
|
1010 attr->block->length = *data++;
|
rlm@1
|
1011 attr->block->data = data;
|
rlm@1
|
1012 data += attr->block->length;
|
rlm@1
|
1013 break;
|
rlm@1
|
1014 case DW_FORM_data1:
|
rlm@1
|
1015 attr->value = *data++;
|
rlm@1
|
1016 break;
|
rlm@1
|
1017 case DW_FORM_flag:
|
rlm@1
|
1018 attr->flag = (*data++) ? true : false;
|
rlm@1
|
1019 break;
|
rlm@1
|
1020 case DW_FORM_sdata:
|
rlm@1
|
1021 attr->value = elfReadSignedLEB128(data, &bytes);
|
rlm@1
|
1022 data += bytes;
|
rlm@1
|
1023 break;
|
rlm@1
|
1024 case DW_FORM_udata:
|
rlm@1
|
1025 attr->value = elfReadLEB128(data, &bytes);
|
rlm@1
|
1026 data += bytes;
|
rlm@1
|
1027 break;
|
rlm@1
|
1028 case DW_FORM_ref_addr:
|
rlm@1
|
1029 attr->value = (elfDebugInfo->infodata + elfRead4Bytes(data)) -
|
rlm@1
|
1030 elfGetCompileUnitForData(data)->top;
|
rlm@1
|
1031 data += 4;
|
rlm@1
|
1032 break;
|
rlm@1
|
1033 case DW_FORM_ref4:
|
rlm@1
|
1034 attr->value = elfRead4Bytes(data);
|
rlm@1
|
1035 data += 4;
|
rlm@1
|
1036 break;
|
rlm@1
|
1037 case DW_FORM_ref_udata:
|
rlm@1
|
1038 attr->value = (elfDebugInfo->infodata +
|
rlm@1
|
1039 (elfGetCompileUnitForData(data)->top -
|
rlm@1
|
1040 elfDebugInfo->infodata) +
|
rlm@1
|
1041 elfReadLEB128(data, &bytes)) -
|
rlm@1
|
1042 elfCurrentUnit->top;
|
rlm@1
|
1043 data += bytes;
|
rlm@1
|
1044 break;
|
rlm@1
|
1045 case DW_FORM_indirect:
|
rlm@1
|
1046 form = elfReadLEB128(data, &bytes);
|
rlm@1
|
1047 data += bytes;
|
rlm@1
|
1048 goto start;
|
rlm@1
|
1049 default:
|
rlm@1
|
1050 fprintf(stderr, "Unsupported FORM %02x\n", form);
|
rlm@1
|
1051 exit(-1);
|
rlm@1
|
1052 }
|
rlm@1
|
1053 return data;
|
rlm@1
|
1054 }
|
rlm@1
|
1055
|
rlm@1
|
1056 ELFAbbrev *elfGetAbbrev(ELFAbbrev **table, u32 number)
|
rlm@1
|
1057 {
|
rlm@1
|
1058 int hash = number % 121;
|
rlm@1
|
1059
|
rlm@1
|
1060 ELFAbbrev *abbrev = table[hash];
|
rlm@1
|
1061
|
rlm@1
|
1062 while (abbrev)
|
rlm@1
|
1063 {
|
rlm@1
|
1064 if (abbrev->number == number)
|
rlm@1
|
1065 return abbrev;
|
rlm@1
|
1066 abbrev = abbrev->next;
|
rlm@1
|
1067 }
|
rlm@1
|
1068 return NULL;
|
rlm@1
|
1069 }
|
rlm@1
|
1070
|
rlm@1
|
1071 ELFAbbrev * *elfReadAbbrevs(u8 *data, u32 offset)
|
rlm@1
|
1072 {
|
rlm@1
|
1073 data += offset;
|
rlm@1
|
1074 ELFAbbrev **abbrevs = (ELFAbbrev * *)calloc(sizeof(ELFAbbrev *)*121, 1);
|
rlm@1
|
1075 int bytes = 0;
|
rlm@1
|
1076 u32 number = elfReadLEB128(data, &bytes);
|
rlm@1
|
1077 data += bytes;
|
rlm@1
|
1078 while (number)
|
rlm@1
|
1079 {
|
rlm@1
|
1080 ELFAbbrev *abbrev = (ELFAbbrev *)calloc(sizeof(ELFAbbrev), 1);
|
rlm@1
|
1081
|
rlm@1
|
1082 // read tag information
|
rlm@1
|
1083 abbrev->number = number;
|
rlm@1
|
1084 abbrev->tag = elfReadLEB128(data, &bytes);
|
rlm@1
|
1085 data += bytes;
|
rlm@1
|
1086 abbrev->hasChildren = *data++ ? true : false;
|
rlm@1
|
1087
|
rlm@1
|
1088 // read attributes
|
rlm@1
|
1089 int name = elfReadLEB128(data, &bytes);
|
rlm@1
|
1090 data += bytes;
|
rlm@1
|
1091 int form = elfReadLEB128(data, &bytes);
|
rlm@1
|
1092 data += bytes;
|
rlm@1
|
1093
|
rlm@1
|
1094 while (name)
|
rlm@1
|
1095 {
|
rlm@1
|
1096 if ((abbrev->numAttrs % 4) == 0)
|
rlm@1
|
1097 {
|
rlm@1
|
1098 abbrev->attrs = (ELFAttr *)realloc(abbrev->attrs,
|
rlm@1
|
1099 (abbrev->numAttrs + 4) *
|
rlm@1
|
1100 sizeof(ELFAttr));
|
rlm@1
|
1101 }
|
rlm@1
|
1102 abbrev->attrs[abbrev->numAttrs].name = name;
|
rlm@1
|
1103 abbrev->attrs[abbrev->numAttrs++].form = form;
|
rlm@1
|
1104
|
rlm@1
|
1105 name = elfReadLEB128(data, &bytes);
|
rlm@1
|
1106 data += bytes;
|
rlm@1
|
1107 form = elfReadLEB128(data, &bytes);
|
rlm@1
|
1108 data += bytes;
|
rlm@1
|
1109 }
|
rlm@1
|
1110
|
rlm@1
|
1111 int hash = number % 121;
|
rlm@1
|
1112 abbrev->next = abbrevs[hash];
|
rlm@1
|
1113 abbrevs[hash] = abbrev;
|
rlm@1
|
1114
|
rlm@1
|
1115 number = elfReadLEB128(data, &bytes);
|
rlm@1
|
1116 data += bytes;
|
rlm@1
|
1117
|
rlm@1
|
1118 if (elfGetAbbrev(abbrevs, number) != NULL)
|
rlm@1
|
1119 break;
|
rlm@1
|
1120 }
|
rlm@1
|
1121
|
rlm@1
|
1122 return abbrevs;
|
rlm@1
|
1123 }
|
rlm@1
|
1124
|
rlm@1
|
1125 void elfParseCFA(u8 *top)
|
rlm@1
|
1126 {
|
rlm@1
|
1127 ELFSectionHeader *h = elfGetSectionByName(".debug_frame");
|
rlm@1
|
1128
|
rlm@1
|
1129 if (h == NULL)
|
rlm@1
|
1130 {
|
rlm@1
|
1131 return;
|
rlm@1
|
1132 }
|
rlm@1
|
1133
|
rlm@1
|
1134 u8 *data = elfReadSection(top, h);
|
rlm@1
|
1135
|
rlm@1
|
1136 u8 *topOffset = data;
|
rlm@1
|
1137
|
rlm@1
|
1138 u8 *end = data + READ32LE(&h->size);
|
rlm@1
|
1139
|
rlm@1
|
1140 ELFcie *cies = NULL;
|
rlm@1
|
1141
|
rlm@1
|
1142 while (data < end)
|
rlm@1
|
1143 {
|
rlm@1
|
1144 u32 offset = data - topOffset;
|
rlm@1
|
1145 u32 len = elfRead4Bytes(data);
|
rlm@1
|
1146 data += 4;
|
rlm@1
|
1147
|
rlm@1
|
1148 u8 *dataEnd = data + len;
|
rlm@1
|
1149
|
rlm@1
|
1150 u32 id = elfRead4Bytes(data);
|
rlm@1
|
1151 data += 4;
|
rlm@1
|
1152
|
rlm@1
|
1153 if (id == 0xffffffff)
|
rlm@1
|
1154 {
|
rlm@1
|
1155 // skip version
|
rlm@1
|
1156 *data++;
|
rlm@1
|
1157
|
rlm@1
|
1158 ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
|
rlm@1
|
1159
|
rlm@1
|
1160 cie->next = cies;
|
rlm@1
|
1161 cies = cie;
|
rlm@1
|
1162
|
rlm@1
|
1163 cie->offset = offset;
|
rlm@1
|
1164
|
rlm@1
|
1165 cie->augmentation = data;
|
rlm@1
|
1166 while (*data)
|
rlm@1
|
1167 data++;
|
rlm@1
|
1168 data++;
|
rlm@1
|
1169
|
rlm@1
|
1170 if (*cie->augmentation)
|
rlm@1
|
1171 {
|
rlm@1
|
1172 fprintf(stderr, "Error: augmentation not supported\n");
|
rlm@1
|
1173 exit(-1);
|
rlm@1
|
1174 }
|
rlm@1
|
1175
|
rlm@1
|
1176 int bytes;
|
rlm@1
|
1177 cie->codeAlign = elfReadLEB128(data, &bytes);
|
rlm@1
|
1178 data += bytes;
|
rlm@1
|
1179
|
rlm@1
|
1180 cie->dataAlign = elfReadSignedLEB128(data, &bytes);
|
rlm@1
|
1181 data += bytes;
|
rlm@1
|
1182
|
rlm@1
|
1183 cie->returnAddress = *data++;
|
rlm@1
|
1184
|
rlm@1
|
1185 cie->data = data;
|
rlm@1
|
1186 cie->dataLen = dataEnd - data;
|
rlm@1
|
1187 }
|
rlm@1
|
1188 else
|
rlm@1
|
1189 {
|
rlm@1
|
1190 ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde));
|
rlm@1
|
1191
|
rlm@1
|
1192 ELFcie *cie = cies;
|
rlm@1
|
1193
|
rlm@1
|
1194 while (cie != NULL)
|
rlm@1
|
1195 {
|
rlm@1
|
1196 if (cie->offset == id)
|
rlm@1
|
1197 break;
|
rlm@1
|
1198 cie = cie->next;
|
rlm@1
|
1199 }
|
rlm@1
|
1200
|
rlm@1
|
1201 if (!cie)
|
rlm@1
|
1202 {
|
rlm@1
|
1203 fprintf(stderr, "Cannot find CIE %08x\n", id);
|
rlm@1
|
1204 exit(-1);
|
rlm@1
|
1205 }
|
rlm@1
|
1206
|
rlm@1
|
1207 fde->cie = cie;
|
rlm@1
|
1208
|
rlm@1
|
1209 fde->address = elfRead4Bytes(data);
|
rlm@1
|
1210 data += 4;
|
rlm@1
|
1211
|
rlm@1
|
1212 fde->end = fde->address + elfRead4Bytes(data);
|
rlm@1
|
1213 data += 4;
|
rlm@1
|
1214
|
rlm@1
|
1215 fde->data = data;
|
rlm@1
|
1216 fde->dataLen = dataEnd - data;
|
rlm@1
|
1217
|
rlm@1
|
1218 if ((elfFdeCount %10) == 0)
|
rlm@1
|
1219 {
|
rlm@1
|
1220 elfFdes = (ELFfde * *)realloc(elfFdes, (elfFdeCount+10) *
|
rlm@1
|
1221 sizeof(ELFfde *));
|
rlm@1
|
1222 }
|
rlm@1
|
1223 elfFdes[elfFdeCount++] = fde;
|
rlm@1
|
1224 }
|
rlm@1
|
1225 data = dataEnd;
|
rlm@1
|
1226 }
|
rlm@1
|
1227
|
rlm@1
|
1228 elfCies = cies;
|
rlm@1
|
1229 }
|
rlm@1
|
1230
|
rlm@1
|
1231 void elfAddLine(LineInfo *l, u32 a, int file, int line, int *max)
|
rlm@1
|
1232 {
|
rlm@1
|
1233 if (l->number == *max)
|
rlm@1
|
1234 {
|
rlm@1
|
1235 *max += 1000;
|
rlm@1
|
1236 l->lines = (LineInfoItem *)realloc(l->lines, *max*sizeof(LineInfoItem));
|
rlm@1
|
1237 }
|
rlm@1
|
1238 LineInfoItem *li = &l->lines[l->number];
|
rlm@1
|
1239 li->file = l->files[file-1];
|
rlm@1
|
1240 li->address = a;
|
rlm@1
|
1241 li->line = line;
|
rlm@1
|
1242 l->number++;
|
rlm@1
|
1243 }
|
rlm@1
|
1244
|
rlm@1
|
1245 void elfParseLineInfo(CompileUnit *unit, u8 *top)
|
rlm@1
|
1246 {
|
rlm@1
|
1247 ELFSectionHeader *h = elfGetSectionByName(".debug_line");
|
rlm@1
|
1248 if (h == NULL)
|
rlm@1
|
1249 {
|
rlm@1
|
1250 fprintf(stderr, "No line information found\n");
|
rlm@1
|
1251 return;
|
rlm@1
|
1252 }
|
rlm@1
|
1253 LineInfo *l = unit->lineInfoTable = (LineInfo *)calloc(1, sizeof(LineInfo));
|
rlm@1
|
1254 l->number = 0;
|
rlm@1
|
1255 int max = 1000;
|
rlm@1
|
1256 l->lines = (LineInfoItem *)malloc(1000*sizeof(LineInfoItem));
|
rlm@1
|
1257
|
rlm@1
|
1258 u8 *data = elfReadSection(top, h);
|
rlm@1
|
1259 data += unit->lineInfo;
|
rlm@1
|
1260 u32 totalLen = elfRead4Bytes(data);
|
rlm@1
|
1261 data += 4;
|
rlm@1
|
1262 u8 *end = data + totalLen;
|
rlm@1
|
1263 // u16 version = elfRead2Bytes(data);
|
rlm@1
|
1264 data += 2;
|
rlm@1
|
1265 // u32 offset = elfRead4Bytes(data);
|
rlm@1
|
1266 data += 4;
|
rlm@1
|
1267 int minInstrSize = *data++;
|
rlm@1
|
1268 int defaultIsStmt = *data++;
|
rlm@1
|
1269 int lineBase = (s8)*data++;
|
rlm@1
|
1270 int lineRange = *data++;
|
rlm@1
|
1271 int opcodeBase = *data++;
|
rlm@1
|
1272 u8 *stdOpLen = (u8 *)malloc(opcodeBase * sizeof(u8));
|
rlm@1
|
1273 stdOpLen[0] = 1;
|
rlm@1
|
1274 int i;
|
rlm@1
|
1275 for (i = 1; i < opcodeBase; i++)
|
rlm@1
|
1276 stdOpLen[i] = *data++;
|
rlm@1
|
1277
|
rlm@1
|
1278 free(stdOpLen); // todo
|
rlm@1
|
1279 int bytes = 0;
|
rlm@1
|
1280
|
rlm@1
|
1281 char *s;
|
rlm@1
|
1282 while ((s = elfReadString(data, &bytes)) != NULL)
|
rlm@1
|
1283 {
|
rlm@1
|
1284 data += bytes;
|
rlm@1
|
1285 // fprintf(stderr, "Directory is %s\n", s);
|
rlm@1
|
1286 }
|
rlm@1
|
1287 data += bytes;
|
rlm@1
|
1288 int count = 4;
|
rlm@1
|
1289 int index = 0;
|
rlm@1
|
1290 l->files = (char * *)malloc(sizeof(char *)*count);
|
rlm@1
|
1291
|
rlm@1
|
1292 while ((s = elfReadString(data, &bytes)) != NULL)
|
rlm@1
|
1293 {
|
rlm@1
|
1294 l->files[index++] = s;
|
rlm@1
|
1295
|
rlm@1
|
1296 data += bytes;
|
rlm@1
|
1297 // directory
|
rlm@1
|
1298 elfReadLEB128(data, &bytes);
|
rlm@1
|
1299 data += bytes;
|
rlm@1
|
1300 // time
|
rlm@1
|
1301 elfReadLEB128(data, &bytes);
|
rlm@1
|
1302 data += bytes;
|
rlm@1
|
1303 // size
|
rlm@1
|
1304 elfReadLEB128(data, &bytes);
|
rlm@1
|
1305 data += bytes;
|
rlm@1
|
1306 // fprintf(stderr, "File is %s\n", s);
|
rlm@1
|
1307 if (index == count)
|
rlm@1
|
1308 {
|
rlm@1
|
1309 count += 4;
|
rlm@1
|
1310 l->files = (char * *)realloc(l->files, sizeof(char *)*count);
|
rlm@1
|
1311 }
|
rlm@1
|
1312 }
|
rlm@1
|
1313 l->fileCount = index;
|
rlm@1
|
1314 data += bytes;
|
rlm@1
|
1315
|
rlm@1
|
1316 while (data < end)
|
rlm@1
|
1317 {
|
rlm@1
|
1318 u32 address = 0;
|
rlm@1
|
1319 int file = 1;
|
rlm@1
|
1320 int line = 1;
|
rlm@1
|
1321 int col = 0;
|
rlm@1
|
1322 int isStmt = defaultIsStmt;
|
rlm@1
|
1323 int basicBlock = 0;
|
rlm@1
|
1324 int endSeq = 0;
|
rlm@1
|
1325
|
rlm@1
|
1326 while (!endSeq)
|
rlm@1
|
1327 {
|
rlm@1
|
1328 int op = *data++;
|
rlm@1
|
1329 switch (op)
|
rlm@1
|
1330 {
|
rlm@1
|
1331 case DW_LNS_extended_op:
|
rlm@1
|
1332 {
|
rlm@1
|
1333 data++;
|
rlm@1
|
1334 op = *data++;
|
rlm@1
|
1335 switch (op)
|
rlm@1
|
1336 {
|
rlm@1
|
1337 case DW_LNE_end_sequence:
|
rlm@1
|
1338 endSeq = 1;
|
rlm@1
|
1339 break;
|
rlm@1
|
1340 case DW_LNE_set_address:
|
rlm@1
|
1341 address = elfRead4Bytes(data);
|
rlm@1
|
1342 data += 4;
|
rlm@1
|
1343 break;
|
rlm@1
|
1344 default:
|
rlm@1
|
1345 fprintf(stderr, "Unknown extended LINE opcode %02x\n", op);
|
rlm@1
|
1346 exit(-1);
|
rlm@1
|
1347 }
|
rlm@1
|
1348 break;
|
rlm@1
|
1349 }
|
rlm@1
|
1350 case DW_LNS_copy:
|
rlm@1
|
1351 // fprintf(stderr, "Address %08x line %d (%d)\n", address, line, file);
|
rlm@1
|
1352 elfAddLine(l, address, file, line, &max);
|
rlm@1
|
1353 basicBlock = 0;
|
rlm@1
|
1354 break;
|
rlm@1
|
1355 case DW_LNS_advance_pc:
|
rlm@1
|
1356 address += minInstrSize * elfReadLEB128(data, &bytes);
|
rlm@1
|
1357 data += bytes;
|
rlm@1
|
1358 break;
|
rlm@1
|
1359 case DW_LNS_advance_line:
|
rlm@1
|
1360 line += elfReadSignedLEB128(data, &bytes);
|
rlm@1
|
1361 data += bytes;
|
rlm@1
|
1362 break;
|
rlm@1
|
1363 case DW_LNS_set_file:
|
rlm@1
|
1364 file = elfReadLEB128(data, &bytes);
|
rlm@1
|
1365 data += bytes;
|
rlm@1
|
1366 break;
|
rlm@1
|
1367 case DW_LNS_set_column:
|
rlm@1
|
1368 col = elfReadLEB128(data, &bytes);
|
rlm@1
|
1369 data += bytes;
|
rlm@1
|
1370 break;
|
rlm@1
|
1371 case DW_LNS_negate_stmt:
|
rlm@1
|
1372 isStmt = !isStmt;
|
rlm@1
|
1373 break;
|
rlm@1
|
1374 case DW_LNS_set_basic_block:
|
rlm@1
|
1375 basicBlock = 1;
|
rlm@1
|
1376 break;
|
rlm@1
|
1377 case DW_LNS_const_add_pc:
|
rlm@1
|
1378 address += (minInstrSize *((255 - opcodeBase)/lineRange));
|
rlm@1
|
1379 break;
|
rlm@1
|
1380 case DW_LNS_fixed_advance_pc:
|
rlm@1
|
1381 address += elfRead2Bytes(data);
|
rlm@1
|
1382 data += 2;
|
rlm@1
|
1383 break;
|
rlm@1
|
1384 default:
|
rlm@1
|
1385 op = op - opcodeBase;
|
rlm@1
|
1386 address += (op / lineRange) * minInstrSize;
|
rlm@1
|
1387 line += lineBase + (op % lineRange);
|
rlm@1
|
1388 elfAddLine(l, address, file, line, &max);
|
rlm@1
|
1389 // fprintf(stderr, "Address %08x line %d (%d)\n", address, line,file);
|
rlm@1
|
1390 basicBlock = 1;
|
rlm@1
|
1391 break;
|
rlm@1
|
1392 }
|
rlm@1
|
1393 }
|
rlm@1
|
1394 }
|
rlm@1
|
1395 l->lines = (LineInfoItem *)realloc(l->lines, l->number*sizeof(LineInfoItem));
|
rlm@1
|
1396 }
|
rlm@1
|
1397
|
rlm@1
|
1398 u8 *elfSkipData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
|
rlm@1
|
1399 {
|
rlm@1
|
1400 int i;
|
rlm@1
|
1401 int bytes;
|
rlm@1
|
1402
|
rlm@1
|
1403 for (i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1404 {
|
rlm@1
|
1405 data = elfReadAttribute(data, &abbrev->attrs[i]);
|
rlm@1
|
1406 if (abbrev->attrs[i].form == DW_FORM_block1)
|
rlm@1
|
1407 free(abbrev->attrs[i].block);
|
rlm@1
|
1408 }
|
rlm@1
|
1409
|
rlm@1
|
1410 if (abbrev->hasChildren)
|
rlm@1
|
1411 {
|
rlm@1
|
1412 int nesting = 1;
|
rlm@1
|
1413 while (nesting)
|
rlm@1
|
1414 {
|
rlm@1
|
1415 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
1416 data += bytes;
|
rlm@1
|
1417
|
rlm@1
|
1418 if (!abbrevNum)
|
rlm@1
|
1419 {
|
rlm@1
|
1420 nesting--;
|
rlm@1
|
1421 continue;
|
rlm@1
|
1422 }
|
rlm@1
|
1423
|
rlm@1
|
1424 abbrev = elfGetAbbrev(abbrevs, abbrevNum);
|
rlm@1
|
1425
|
rlm@1
|
1426 for (i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1427 {
|
rlm@1
|
1428 data = elfReadAttribute(data, &abbrev->attrs[i]);
|
rlm@1
|
1429 if (abbrev->attrs[i].form == DW_FORM_block1)
|
rlm@1
|
1430 free(abbrev->attrs[i].block);
|
rlm@1
|
1431 }
|
rlm@1
|
1432
|
rlm@1
|
1433 if (abbrev->hasChildren)
|
rlm@1
|
1434 {
|
rlm@1
|
1435 nesting++;
|
rlm@1
|
1436 }
|
rlm@1
|
1437 }
|
rlm@1
|
1438 }
|
rlm@1
|
1439 return data;
|
rlm@1
|
1440 }
|
rlm@1
|
1441
|
rlm@1
|
1442 Type *elfParseType(CompileUnit *unit, u32);
|
rlm@1
|
1443 u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
|
rlm@1
|
1444 Object **object);
|
rlm@1
|
1445 u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
|
rlm@1
|
1446 Function **function);
|
rlm@1
|
1447 void elfCleanUp(Function *);
|
rlm@1
|
1448
|
rlm@1
|
1449 void elfAddType(Type *type, CompileUnit *unit, u32 offset)
|
rlm@1
|
1450 {
|
rlm@1
|
1451 if (type->next == NULL)
|
rlm@1
|
1452 {
|
rlm@1
|
1453 if (unit->types != type && type->offset == 0)
|
rlm@1
|
1454 {
|
rlm@1
|
1455 type->offset = offset;
|
rlm@1
|
1456 type->next = unit->types;
|
rlm@1
|
1457 unit->types = type;
|
rlm@1
|
1458 }
|
rlm@1
|
1459 }
|
rlm@1
|
1460 }
|
rlm@1
|
1461
|
rlm@1
|
1462 void elfParseType(u8 *data, u32 offset, ELFAbbrev *abbrev, CompileUnit *unit,
|
rlm@1
|
1463 Type **type)
|
rlm@1
|
1464 {
|
rlm@1
|
1465 switch (abbrev->tag)
|
rlm@1
|
1466 {
|
rlm@1
|
1467 case DW_TAG_typedef:
|
rlm@1
|
1468 {
|
rlm@1
|
1469 u32 typeref = 0;
|
rlm@1
|
1470 char *name = NULL;
|
rlm@1
|
1471 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1472 {
|
rlm@1
|
1473 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1474 data = elfReadAttribute(data, attr);
|
rlm@1
|
1475 switch (attr->name)
|
rlm@1
|
1476 {
|
rlm@1
|
1477 case DW_AT_name:
|
rlm@1
|
1478 name = attr->string;
|
rlm@1
|
1479 break;
|
rlm@1
|
1480 case DW_AT_type:
|
rlm@1
|
1481 typeref = attr->value;
|
rlm@1
|
1482 break;
|
rlm@1
|
1483 case DW_AT_decl_file:
|
rlm@1
|
1484 case DW_AT_decl_line:
|
rlm@1
|
1485 break;
|
rlm@1
|
1486 default:
|
rlm@1
|
1487 fprintf(stderr, "Unknown attribute for typedef %02x\n", attr->name);
|
rlm@1
|
1488 break;
|
rlm@1
|
1489 }
|
rlm@1
|
1490 }
|
rlm@1
|
1491 if (abbrev->hasChildren)
|
rlm@1
|
1492 fprintf(stderr, "Unexpected children for typedef\n");
|
rlm@1
|
1493 *type = elfParseType(unit, typeref);
|
rlm@1
|
1494 if (name)
|
rlm@1
|
1495 (*type)->name = name;
|
rlm@1
|
1496 return;
|
rlm@1
|
1497 break;
|
rlm@1
|
1498 }
|
rlm@1
|
1499 case DW_TAG_union_type:
|
rlm@1
|
1500 case DW_TAG_structure_type:
|
rlm@1
|
1501 {
|
rlm@1
|
1502 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1503 if (abbrev->tag == DW_TAG_structure_type)
|
rlm@1
|
1504 t->type = TYPE_struct;
|
rlm@1
|
1505 else
|
rlm@1
|
1506 t->type = TYPE_union;
|
rlm@1
|
1507
|
rlm@1
|
1508 Struct *s = (Struct *)calloc(sizeof(Struct), 1);
|
rlm@1
|
1509 t->structure = s;
|
rlm@1
|
1510 elfAddType(t, unit, offset);
|
rlm@1
|
1511
|
rlm@1
|
1512 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1513 {
|
rlm@1
|
1514 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1515 data = elfReadAttribute(data, attr);
|
rlm@1
|
1516 switch (attr->name)
|
rlm@1
|
1517 {
|
rlm@1
|
1518 case DW_AT_name:
|
rlm@1
|
1519 t->name = attr->string;
|
rlm@1
|
1520 break;
|
rlm@1
|
1521 case DW_AT_byte_size:
|
rlm@1
|
1522 t->size = attr->value;
|
rlm@1
|
1523 break;
|
rlm@1
|
1524 case DW_AT_decl_file:
|
rlm@1
|
1525 case DW_AT_decl_line:
|
rlm@1
|
1526 case DW_AT_sibling:
|
rlm@1
|
1527 case DW_AT_containing_type: // todo?
|
rlm@1
|
1528 case DW_AT_declaration:
|
rlm@1
|
1529 case DW_AT_specification: // TODO:
|
rlm@1
|
1530 break;
|
rlm@1
|
1531 default:
|
rlm@1
|
1532 fprintf(stderr, "Unknown attribute for struct %02x\n", attr->name);
|
rlm@1
|
1533 break;
|
rlm@1
|
1534 }
|
rlm@1
|
1535 }
|
rlm@1
|
1536 if (abbrev->hasChildren)
|
rlm@1
|
1537 {
|
rlm@1
|
1538 int bytes;
|
rlm@1
|
1539 u32 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1540 data += bytes;
|
rlm@1
|
1541 int index = 0;
|
rlm@1
|
1542 while (num)
|
rlm@1
|
1543 {
|
rlm@1
|
1544 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
|
rlm@1
|
1545
|
rlm@1
|
1546 switch (abbr->tag)
|
rlm@1
|
1547 {
|
rlm@1
|
1548 case DW_TAG_member:
|
rlm@1
|
1549 {
|
rlm@1
|
1550 if ((index % 4) == 0)
|
rlm@1
|
1551 s->members = (Member *)realloc(s->members,
|
rlm@1
|
1552 sizeof(Member)*(index+4));
|
rlm@1
|
1553 Member *m = &s->members[index];
|
rlm@1
|
1554 m->location = NULL;
|
rlm@1
|
1555 m->bitOffset = 0;
|
rlm@1
|
1556 m->bitSize = 0;
|
rlm@1
|
1557 m->byteSize = 0;
|
rlm@1
|
1558 for (int i = 0; i < abbr->numAttrs; i++)
|
rlm@1
|
1559 {
|
rlm@1
|
1560 ELFAttr *attr = &abbr->attrs[i];
|
rlm@1
|
1561 data = elfReadAttribute(data, attr);
|
rlm@1
|
1562 switch (attr->name)
|
rlm@1
|
1563 {
|
rlm@1
|
1564 case DW_AT_name:
|
rlm@1
|
1565 m->name = attr->string;
|
rlm@1
|
1566 break;
|
rlm@1
|
1567 case DW_AT_type:
|
rlm@1
|
1568 m->type = elfParseType(unit, attr->value);
|
rlm@1
|
1569 break;
|
rlm@1
|
1570 case DW_AT_data_member_location:
|
rlm@1
|
1571 m->location = attr->block;
|
rlm@1
|
1572 break;
|
rlm@1
|
1573 case DW_AT_byte_size:
|
rlm@1
|
1574 m->byteSize = attr->value;
|
rlm@1
|
1575 break;
|
rlm@1
|
1576 case DW_AT_bit_offset:
|
rlm@1
|
1577 m->bitOffset = attr->value;
|
rlm@1
|
1578 break;
|
rlm@1
|
1579 case DW_AT_bit_size:
|
rlm@1
|
1580 m->bitSize = attr->value;
|
rlm@1
|
1581 break;
|
rlm@1
|
1582 case DW_AT_decl_file:
|
rlm@1
|
1583 case DW_AT_decl_line:
|
rlm@1
|
1584 case DW_AT_accessibility:
|
rlm@1
|
1585 case DW_AT_artificial: // todo?
|
rlm@1
|
1586 break;
|
rlm@1
|
1587 default:
|
rlm@1
|
1588 fprintf(stderr, "Unknown member attribute %02x\n",
|
rlm@1
|
1589 attr->name);
|
rlm@1
|
1590 }
|
rlm@1
|
1591 }
|
rlm@1
|
1592 index++;
|
rlm@1
|
1593 break;
|
rlm@1
|
1594 }
|
rlm@1
|
1595 case DW_TAG_subprogram:
|
rlm@1
|
1596 {
|
rlm@1
|
1597 Function *fnc = NULL;
|
rlm@1
|
1598 data = elfParseFunction(data, abbr, unit, &fnc);
|
rlm@1
|
1599 if (fnc != NULL)
|
rlm@1
|
1600 {
|
rlm@1
|
1601 if (unit->lastFunction)
|
rlm@1
|
1602 unit->lastFunction->next = fnc;
|
rlm@1
|
1603 else
|
rlm@1
|
1604 unit->functions = fnc;
|
rlm@1
|
1605 unit->lastFunction = fnc;
|
rlm@1
|
1606 }
|
rlm@1
|
1607 break;
|
rlm@1
|
1608 }
|
rlm@1
|
1609 case DW_TAG_inheritance:
|
rlm@1
|
1610 // TODO: add support
|
rlm@1
|
1611 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1612 break;
|
rlm@1
|
1613 CASE_TYPE_TAG:
|
rlm@1
|
1614 // skip types... parsed only when used
|
rlm@1
|
1615 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1616 break;
|
rlm@1
|
1617 case DW_TAG_variable:
|
rlm@1
|
1618 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1619 break;
|
rlm@1
|
1620 default:
|
rlm@1
|
1621 fprintf(stderr, "Unknown struct tag %02x %s\n", abbr->tag, t->name);
|
rlm@1
|
1622 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1623 break;
|
rlm@1
|
1624 }
|
rlm@1
|
1625 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1626 data += bytes;
|
rlm@1
|
1627 }
|
rlm@1
|
1628 s->memberCount = index;
|
rlm@1
|
1629 }
|
rlm@1
|
1630 *type = t;
|
rlm@1
|
1631 return;
|
rlm@1
|
1632 break;
|
rlm@1
|
1633 }
|
rlm@1
|
1634 case DW_TAG_base_type:
|
rlm@1
|
1635 {
|
rlm@1
|
1636 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1637
|
rlm@1
|
1638 t->type = TYPE_base;
|
rlm@1
|
1639 elfAddType(t, unit, offset);
|
rlm@1
|
1640 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1641 {
|
rlm@1
|
1642 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1643 data = elfReadAttribute(data, attr);
|
rlm@1
|
1644 switch (attr->name)
|
rlm@1
|
1645 {
|
rlm@1
|
1646 case DW_AT_name:
|
rlm@1
|
1647 t->name = attr->string;
|
rlm@1
|
1648 break;
|
rlm@1
|
1649 case DW_AT_encoding:
|
rlm@1
|
1650 t->encoding = attr->value;
|
rlm@1
|
1651 break;
|
rlm@1
|
1652 case DW_AT_byte_size:
|
rlm@1
|
1653 t->size = attr->value;
|
rlm@1
|
1654 break;
|
rlm@1
|
1655 case DW_AT_bit_size:
|
rlm@1
|
1656 t->bitSize = attr->value;
|
rlm@1
|
1657 break;
|
rlm@1
|
1658 default:
|
rlm@1
|
1659 fprintf(stderr, "Unknown attribute for base type %02x\n",
|
rlm@1
|
1660 attr->name);
|
rlm@1
|
1661 break;
|
rlm@1
|
1662 }
|
rlm@1
|
1663 }
|
rlm@1
|
1664 if (abbrev->hasChildren)
|
rlm@1
|
1665 fprintf(stderr, "Unexpected children for base type\n");
|
rlm@1
|
1666 *type = t;
|
rlm@1
|
1667 return;
|
rlm@1
|
1668 break;
|
rlm@1
|
1669 }
|
rlm@1
|
1670 case DW_TAG_pointer_type:
|
rlm@1
|
1671 {
|
rlm@1
|
1672 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1673
|
rlm@1
|
1674 t->type = TYPE_pointer;
|
rlm@1
|
1675
|
rlm@1
|
1676 elfAddType(t, unit, offset);
|
rlm@1
|
1677
|
rlm@1
|
1678 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1679 {
|
rlm@1
|
1680 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1681 data = elfReadAttribute(data, attr);
|
rlm@1
|
1682 switch (attr->name)
|
rlm@1
|
1683 {
|
rlm@1
|
1684 case DW_AT_type:
|
rlm@1
|
1685 t->pointer = elfParseType(unit, attr->value);
|
rlm@1
|
1686 break;
|
rlm@1
|
1687 case DW_AT_byte_size:
|
rlm@1
|
1688 t->size = attr->value;
|
rlm@1
|
1689 break;
|
rlm@1
|
1690 default:
|
rlm@1
|
1691 fprintf(stderr, "Unknown pointer type attribute %02x\n", attr->name);
|
rlm@1
|
1692 break;
|
rlm@1
|
1693 }
|
rlm@1
|
1694 }
|
rlm@1
|
1695 if (abbrev->hasChildren)
|
rlm@1
|
1696 fprintf(stderr, "Unexpected children for pointer type\n");
|
rlm@1
|
1697 *type = t;
|
rlm@1
|
1698 return;
|
rlm@1
|
1699 break;
|
rlm@1
|
1700 }
|
rlm@1
|
1701 case DW_TAG_reference_type:
|
rlm@1
|
1702 {
|
rlm@1
|
1703 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1704
|
rlm@1
|
1705 t->type = TYPE_reference;
|
rlm@1
|
1706
|
rlm@1
|
1707 elfAddType(t, unit, offset);
|
rlm@1
|
1708
|
rlm@1
|
1709 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1710 {
|
rlm@1
|
1711 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1712 data = elfReadAttribute(data, attr);
|
rlm@1
|
1713 switch (attr->name)
|
rlm@1
|
1714 {
|
rlm@1
|
1715 case DW_AT_type:
|
rlm@1
|
1716 t->pointer = elfParseType(unit, attr->value);
|
rlm@1
|
1717 break;
|
rlm@1
|
1718 case DW_AT_byte_size:
|
rlm@1
|
1719 t->size = attr->value;
|
rlm@1
|
1720 break;
|
rlm@1
|
1721 default:
|
rlm@1
|
1722 fprintf(stderr, "Unknown ref type attribute %02x\n", attr->name);
|
rlm@1
|
1723 break;
|
rlm@1
|
1724 }
|
rlm@1
|
1725 }
|
rlm@1
|
1726 if (abbrev->hasChildren)
|
rlm@1
|
1727 fprintf(stderr, "Unexpected children for ref type\n");
|
rlm@1
|
1728 *type = t;
|
rlm@1
|
1729 return;
|
rlm@1
|
1730 break;
|
rlm@1
|
1731 }
|
rlm@1
|
1732 case DW_TAG_volatile_type:
|
rlm@1
|
1733 {
|
rlm@1
|
1734 u32 typeref = 0;
|
rlm@1
|
1735
|
rlm@1
|
1736 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1737 {
|
rlm@1
|
1738 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1739 data = elfReadAttribute(data, attr);
|
rlm@1
|
1740 switch (attr->name)
|
rlm@1
|
1741 {
|
rlm@1
|
1742 case DW_AT_type:
|
rlm@1
|
1743 typeref = attr->value;
|
rlm@1
|
1744 break;
|
rlm@1
|
1745 default:
|
rlm@1
|
1746 fprintf(stderr, "Unknown volatile attribute for type %02x\n",
|
rlm@1
|
1747 attr->name);
|
rlm@1
|
1748 break;
|
rlm@1
|
1749 }
|
rlm@1
|
1750 }
|
rlm@1
|
1751 if (abbrev->hasChildren)
|
rlm@1
|
1752 fprintf(stderr, "Unexpected children for volatile type\n");
|
rlm@1
|
1753 *type = elfParseType(unit, typeref);
|
rlm@1
|
1754 return;
|
rlm@1
|
1755 break;
|
rlm@1
|
1756 }
|
rlm@1
|
1757 case DW_TAG_const_type:
|
rlm@1
|
1758 {
|
rlm@1
|
1759 u32 typeref = 0;
|
rlm@1
|
1760
|
rlm@1
|
1761 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1762 {
|
rlm@1
|
1763 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1764 data = elfReadAttribute(data, attr);
|
rlm@1
|
1765 switch (attr->name)
|
rlm@1
|
1766 {
|
rlm@1
|
1767 case DW_AT_type:
|
rlm@1
|
1768 typeref = attr->value;
|
rlm@1
|
1769 break;
|
rlm@1
|
1770 default:
|
rlm@1
|
1771 fprintf(stderr, "Unknown const attribute for type %02x\n",
|
rlm@1
|
1772 attr->name);
|
rlm@1
|
1773 break;
|
rlm@1
|
1774 }
|
rlm@1
|
1775 }
|
rlm@1
|
1776 if (abbrev->hasChildren)
|
rlm@1
|
1777 fprintf(stderr, "Unexpected children for const type\n");
|
rlm@1
|
1778 *type = elfParseType(unit, typeref);
|
rlm@1
|
1779 return;
|
rlm@1
|
1780 break;
|
rlm@1
|
1781 }
|
rlm@1
|
1782 case DW_TAG_enumeration_type:
|
rlm@1
|
1783 {
|
rlm@1
|
1784 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1785 t->type = TYPE_enum;
|
rlm@1
|
1786 Enum *e = (Enum *)calloc(sizeof(Enum), 1);
|
rlm@1
|
1787 t->enumeration = e;
|
rlm@1
|
1788 elfAddType(t, unit, offset);
|
rlm@1
|
1789 int count = 0;
|
rlm@1
|
1790 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1791 {
|
rlm@1
|
1792 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1793 data = elfReadAttribute(data, attr);
|
rlm@1
|
1794 switch (attr->name)
|
rlm@1
|
1795 {
|
rlm@1
|
1796 case DW_AT_name:
|
rlm@1
|
1797 t->name = attr->string;
|
rlm@1
|
1798 break;
|
rlm@1
|
1799 case DW_AT_byte_size:
|
rlm@1
|
1800 t->size = attr->value;
|
rlm@1
|
1801 break;
|
rlm@1
|
1802 case DW_AT_sibling:
|
rlm@1
|
1803 case DW_AT_decl_file:
|
rlm@1
|
1804 case DW_AT_decl_line:
|
rlm@1
|
1805 break;
|
rlm@1
|
1806 default:
|
rlm@1
|
1807 fprintf(stderr, "Unknown enum attribute %02x\n", attr->name);
|
rlm@1
|
1808 }
|
rlm@1
|
1809 }
|
rlm@1
|
1810 if (abbrev->hasChildren)
|
rlm@1
|
1811 {
|
rlm@1
|
1812 int bytes;
|
rlm@1
|
1813 u32 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1814 data += bytes;
|
rlm@1
|
1815 while (num)
|
rlm@1
|
1816 {
|
rlm@1
|
1817 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
|
rlm@1
|
1818
|
rlm@1
|
1819 switch (abbr->tag)
|
rlm@1
|
1820 {
|
rlm@1
|
1821 case DW_TAG_enumerator:
|
rlm@1
|
1822 {
|
rlm@1
|
1823 count++;
|
rlm@1
|
1824 e->members = (EnumMember *)realloc(e->members,
|
rlm@1
|
1825 count*sizeof(EnumMember));
|
rlm@1
|
1826 EnumMember *m = &e->members[count-1];
|
rlm@1
|
1827 for (int i = 0; i < abbr->numAttrs; i++)
|
rlm@1
|
1828 {
|
rlm@1
|
1829 ELFAttr *attr = &abbr->attrs[i];
|
rlm@1
|
1830 data = elfReadAttribute(data, attr);
|
rlm@1
|
1831 switch (attr->name)
|
rlm@1
|
1832 {
|
rlm@1
|
1833 case DW_AT_name:
|
rlm@1
|
1834 m->name = attr->string;
|
rlm@1
|
1835 break;
|
rlm@1
|
1836 case DW_AT_const_value:
|
rlm@1
|
1837 m->value = attr->value;
|
rlm@1
|
1838 break;
|
rlm@1
|
1839 default:
|
rlm@1
|
1840 fprintf(stderr, "Unknown sub param attribute %02x\n",
|
rlm@1
|
1841 attr->name);
|
rlm@1
|
1842 }
|
rlm@1
|
1843 }
|
rlm@1
|
1844 break;
|
rlm@1
|
1845 }
|
rlm@1
|
1846 default:
|
rlm@1
|
1847 fprintf(stderr, "Unknown enum tag %02x\n", abbr->tag);
|
rlm@1
|
1848 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1849 break;
|
rlm@1
|
1850 }
|
rlm@1
|
1851 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1852 data += bytes;
|
rlm@1
|
1853 }
|
rlm@1
|
1854 }
|
rlm@1
|
1855 e->count = count;
|
rlm@1
|
1856 *type = t;
|
rlm@1
|
1857 return;
|
rlm@1
|
1858 break;
|
rlm@1
|
1859 }
|
rlm@1
|
1860 case DW_TAG_subroutine_type:
|
rlm@1
|
1861 {
|
rlm@1
|
1862 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1863 t->type = TYPE_function;
|
rlm@1
|
1864 FunctionType *f = (FunctionType *)calloc(sizeof(FunctionType), 1);
|
rlm@1
|
1865 t->function = f;
|
rlm@1
|
1866 elfAddType(t, unit, offset);
|
rlm@1
|
1867 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1868 {
|
rlm@1
|
1869 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1870 data = elfReadAttribute(data, attr);
|
rlm@1
|
1871 switch (attr->name)
|
rlm@1
|
1872 {
|
rlm@1
|
1873 case DW_AT_prototyped:
|
rlm@1
|
1874 case DW_AT_sibling:
|
rlm@1
|
1875 break;
|
rlm@1
|
1876 case DW_AT_type:
|
rlm@1
|
1877 f->returnType = elfParseType(unit, attr->value);
|
rlm@1
|
1878 break;
|
rlm@1
|
1879 default:
|
rlm@1
|
1880 fprintf(stderr, "Unknown subroutine attribute %02x\n", attr->name);
|
rlm@1
|
1881 }
|
rlm@1
|
1882 }
|
rlm@1
|
1883 if (abbrev->hasChildren)
|
rlm@1
|
1884 {
|
rlm@1
|
1885 int bytes;
|
rlm@1
|
1886 u32 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1887 data += bytes;
|
rlm@1
|
1888 Object *lastVar = NULL;
|
rlm@1
|
1889 while (num)
|
rlm@1
|
1890 {
|
rlm@1
|
1891 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
|
rlm@1
|
1892
|
rlm@1
|
1893 switch (abbr->tag)
|
rlm@1
|
1894 {
|
rlm@1
|
1895 case DW_TAG_formal_parameter:
|
rlm@1
|
1896 {
|
rlm@1
|
1897 Object *o;
|
rlm@1
|
1898 data = elfParseObject(data, abbr, unit, &o);
|
rlm@1
|
1899 if (f->args)
|
rlm@1
|
1900 lastVar->next = o;
|
rlm@1
|
1901 else
|
rlm@1
|
1902 f->args = o;
|
rlm@1
|
1903 lastVar = o;
|
rlm@1
|
1904 break;
|
rlm@1
|
1905 }
|
rlm@1
|
1906 case DW_TAG_unspecified_parameters:
|
rlm@1
|
1907 // no use in the debugger yet
|
rlm@1
|
1908 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1909 break;
|
rlm@1
|
1910 CASE_TYPE_TAG:
|
rlm@1
|
1911 // skip types... parsed only when used
|
rlm@1
|
1912 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1913 break;
|
rlm@1
|
1914 default:
|
rlm@1
|
1915 fprintf(stderr, "Unknown subroutine tag %02x\n", abbr->tag);
|
rlm@1
|
1916 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1917 break;
|
rlm@1
|
1918 }
|
rlm@1
|
1919 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1920 data += bytes;
|
rlm@1
|
1921 }
|
rlm@1
|
1922 }
|
rlm@1
|
1923 *type = t;
|
rlm@1
|
1924 return;
|
rlm@1
|
1925 break;
|
rlm@1
|
1926 }
|
rlm@1
|
1927 case DW_TAG_array_type:
|
rlm@1
|
1928 {
|
rlm@1
|
1929 u32 typeref = 0;
|
rlm@1
|
1930 int i;
|
rlm@1
|
1931 Array *array = (Array *)calloc(sizeof(Array), 1);
|
rlm@1
|
1932 Type * t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
1933 t->type = TYPE_array;
|
rlm@1
|
1934 elfAddType(t, unit, offset);
|
rlm@1
|
1935
|
rlm@1
|
1936 for (i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
1937 {
|
rlm@1
|
1938 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
1939 data = elfReadAttribute(data, attr);
|
rlm@1
|
1940 switch (attr->name)
|
rlm@1
|
1941 {
|
rlm@1
|
1942 case DW_AT_sibling:
|
rlm@1
|
1943 break;
|
rlm@1
|
1944 case DW_AT_type:
|
rlm@1
|
1945 typeref = attr->value;
|
rlm@1
|
1946 array->type = elfParseType(unit, typeref);
|
rlm@1
|
1947 break;
|
rlm@1
|
1948 default:
|
rlm@1
|
1949 fprintf(stderr, "Unknown array attribute %02x\n", attr->name);
|
rlm@1
|
1950 }
|
rlm@1
|
1951 }
|
rlm@1
|
1952 if (abbrev->hasChildren)
|
rlm@1
|
1953 {
|
rlm@1
|
1954 int bytes;
|
rlm@1
|
1955 u32 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1956 data += bytes;
|
rlm@1
|
1957 int index = 0;
|
rlm@1
|
1958 int maxBounds = 0;
|
rlm@1
|
1959 while (num)
|
rlm@1
|
1960 {
|
rlm@1
|
1961 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
|
rlm@1
|
1962
|
rlm@1
|
1963 switch (abbr->tag)
|
rlm@1
|
1964 {
|
rlm@1
|
1965 case DW_TAG_subrange_type:
|
rlm@1
|
1966 {
|
rlm@1
|
1967 if (maxBounds == index)
|
rlm@1
|
1968 {
|
rlm@1
|
1969 maxBounds += 4;
|
rlm@1
|
1970 array->bounds = (int *)realloc(array->bounds,
|
rlm@1
|
1971 sizeof(int)*maxBounds);
|
rlm@1
|
1972 }
|
rlm@1
|
1973 for (int i = 0; i < abbr->numAttrs; i++)
|
rlm@1
|
1974 {
|
rlm@1
|
1975 ELFAttr *attr = &abbr->attrs[i];
|
rlm@1
|
1976 data = elfReadAttribute(data, attr);
|
rlm@1
|
1977 switch (attr->name)
|
rlm@1
|
1978 {
|
rlm@1
|
1979 case DW_AT_upper_bound:
|
rlm@1
|
1980 array->bounds[index] = attr->value+1;
|
rlm@1
|
1981 break;
|
rlm@1
|
1982 case DW_AT_type: // ignore
|
rlm@1
|
1983 break;
|
rlm@1
|
1984 default:
|
rlm@1
|
1985 fprintf(stderr, "Unknown subrange attribute %02x\n",
|
rlm@1
|
1986 attr->name);
|
rlm@1
|
1987 }
|
rlm@1
|
1988 }
|
rlm@1
|
1989 index++;
|
rlm@1
|
1990 break;
|
rlm@1
|
1991 }
|
rlm@1
|
1992 default:
|
rlm@1
|
1993 fprintf(stderr, "Unknown array tag %02x\n", abbr->tag);
|
rlm@1
|
1994 data = elfSkipData(data, abbr, unit->abbrevs);
|
rlm@1
|
1995 break;
|
rlm@1
|
1996 }
|
rlm@1
|
1997 num = elfReadLEB128(data, &bytes);
|
rlm@1
|
1998 data += bytes;
|
rlm@1
|
1999 }
|
rlm@1
|
2000 array->maxBounds = index;
|
rlm@1
|
2001 }
|
rlm@1
|
2002 t->size = array->type->size;
|
rlm@1
|
2003 for (i = 0; i < array->maxBounds; i++)
|
rlm@1
|
2004 t->size *= array->bounds[i];
|
rlm@1
|
2005 t->array = array;
|
rlm@1
|
2006 *type = t;
|
rlm@1
|
2007 return;
|
rlm@1
|
2008 break;
|
rlm@1
|
2009 }
|
rlm@1
|
2010 default:
|
rlm@1
|
2011 fprintf(stderr, "Unknown type TAG %02x\n", abbrev->tag);
|
rlm@1
|
2012 exit(-1);
|
rlm@1
|
2013 }
|
rlm@1
|
2014 }
|
rlm@1
|
2015
|
rlm@1
|
2016 Type *elfParseType(CompileUnit *unit, u32 offset)
|
rlm@1
|
2017 {
|
rlm@1
|
2018 Type *t = unit->types;
|
rlm@1
|
2019
|
rlm@1
|
2020 while (t)
|
rlm@1
|
2021 {
|
rlm@1
|
2022 if (t->offset == offset)
|
rlm@1
|
2023 return t;
|
rlm@1
|
2024 t = t->next;
|
rlm@1
|
2025 }
|
rlm@1
|
2026 if (offset == 0)
|
rlm@1
|
2027 {
|
rlm@1
|
2028 Type *t = (Type *)calloc(sizeof(Type), 1);
|
rlm@1
|
2029 t->type = TYPE_void;
|
rlm@1
|
2030 t->offset = 0;
|
rlm@1
|
2031 elfAddType(t, unit, 0);
|
rlm@1
|
2032 return t;
|
rlm@1
|
2033 }
|
rlm@1
|
2034 u8 *data = unit->top + offset;
|
rlm@1
|
2035 int bytes;
|
rlm@1
|
2036 int abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2037 data += bytes;
|
rlm@1
|
2038 Type *type = NULL;
|
rlm@1
|
2039
|
rlm@1
|
2040 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2041
|
rlm@1
|
2042 elfParseType(data, offset, abbrev, unit, &type);
|
rlm@1
|
2043 return type;
|
rlm@1
|
2044 }
|
rlm@1
|
2045
|
rlm@1
|
2046 void elfGetObjectAttributes(CompileUnit *unit, u32 offset, Object *o)
|
rlm@1
|
2047 {
|
rlm@1
|
2048 u8 *data = unit->top + offset;
|
rlm@1
|
2049 int bytes;
|
rlm@1
|
2050 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2051 data += bytes;
|
rlm@1
|
2052
|
rlm@1
|
2053 if (!abbrevNum)
|
rlm@1
|
2054 {
|
rlm@1
|
2055 return;
|
rlm@1
|
2056 }
|
rlm@1
|
2057
|
rlm@1
|
2058 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2059
|
rlm@1
|
2060 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2061 {
|
rlm@1
|
2062 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
2063 data = elfReadAttribute(data, attr);
|
rlm@1
|
2064 switch (attr->name)
|
rlm@1
|
2065 {
|
rlm@1
|
2066 case DW_AT_location:
|
rlm@1
|
2067 o->location = attr->block;
|
rlm@1
|
2068 break;
|
rlm@1
|
2069 case DW_AT_name:
|
rlm@1
|
2070 if (o->name == NULL)
|
rlm@1
|
2071 o->name = attr->string;
|
rlm@1
|
2072 break;
|
rlm@1
|
2073 case DW_AT_MIPS_linkage_name:
|
rlm@1
|
2074 o->name = attr->string;
|
rlm@1
|
2075 break;
|
rlm@1
|
2076 case DW_AT_decl_file:
|
rlm@1
|
2077 o->file = attr->value;
|
rlm@1
|
2078 break;
|
rlm@1
|
2079 case DW_AT_decl_line:
|
rlm@1
|
2080 o->line = attr->value;
|
rlm@1
|
2081 break;
|
rlm@1
|
2082 case DW_AT_type:
|
rlm@1
|
2083 o->type = elfParseType(unit, attr->value);
|
rlm@1
|
2084 break;
|
rlm@1
|
2085 case DW_AT_external:
|
rlm@1
|
2086 o->external = attr->flag;
|
rlm@1
|
2087 break;
|
rlm@1
|
2088 case DW_AT_const_value:
|
rlm@1
|
2089 case DW_AT_abstract_origin:
|
rlm@1
|
2090 case DW_AT_declaration:
|
rlm@1
|
2091 case DW_AT_artificial:
|
rlm@1
|
2092 // todo
|
rlm@1
|
2093 break;
|
rlm@1
|
2094 case DW_AT_specification:
|
rlm@1
|
2095 // TODO:
|
rlm@1
|
2096 break;
|
rlm@1
|
2097 default:
|
rlm@1
|
2098 fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
|
rlm@1
|
2099 break;
|
rlm@1
|
2100 }
|
rlm@1
|
2101 }
|
rlm@1
|
2102 }
|
rlm@1
|
2103
|
rlm@1
|
2104 u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
|
rlm@1
|
2105 Object **object)
|
rlm@1
|
2106 {
|
rlm@1
|
2107 Object *o = (Object *)calloc(sizeof(Object), 1);
|
rlm@1
|
2108
|
rlm@1
|
2109 o->next = NULL;
|
rlm@1
|
2110
|
rlm@1
|
2111 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2112 {
|
rlm@1
|
2113 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
2114 data = elfReadAttribute(data, attr);
|
rlm@1
|
2115 switch (attr->name)
|
rlm@1
|
2116 {
|
rlm@1
|
2117 case DW_AT_location:
|
rlm@1
|
2118 o->location = attr->block;
|
rlm@1
|
2119 break;
|
rlm@1
|
2120 case DW_AT_name:
|
rlm@1
|
2121 if (o->name == NULL)
|
rlm@1
|
2122 o->name = attr->string;
|
rlm@1
|
2123 break;
|
rlm@1
|
2124 case DW_AT_MIPS_linkage_name:
|
rlm@1
|
2125 o->name = attr->string;
|
rlm@1
|
2126 break;
|
rlm@1
|
2127 case DW_AT_decl_file:
|
rlm@1
|
2128 o->file = attr->value;
|
rlm@1
|
2129 break;
|
rlm@1
|
2130 case DW_AT_decl_line:
|
rlm@1
|
2131 o->line = attr->value;
|
rlm@1
|
2132 break;
|
rlm@1
|
2133 case DW_AT_type:
|
rlm@1
|
2134 o->type = elfParseType(unit, attr->value);
|
rlm@1
|
2135 break;
|
rlm@1
|
2136 case DW_AT_external:
|
rlm@1
|
2137 o->external = attr->flag;
|
rlm@1
|
2138 break;
|
rlm@1
|
2139 case DW_AT_abstract_origin:
|
rlm@1
|
2140 elfGetObjectAttributes(unit, attr->value, o);
|
rlm@1
|
2141 break;
|
rlm@1
|
2142 case DW_AT_const_value:
|
rlm@1
|
2143 case DW_AT_declaration:
|
rlm@1
|
2144 case DW_AT_artificial:
|
rlm@1
|
2145 break;
|
rlm@1
|
2146 case DW_AT_specification:
|
rlm@1
|
2147 // TODO:
|
rlm@1
|
2148 break;
|
rlm@1
|
2149 default:
|
rlm@1
|
2150 fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
|
rlm@1
|
2151 break;
|
rlm@1
|
2152 }
|
rlm@1
|
2153 }
|
rlm@1
|
2154 *object = o;
|
rlm@1
|
2155 return data;
|
rlm@1
|
2156 }
|
rlm@1
|
2157
|
rlm@1
|
2158 u8 *elfParseBlock(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
|
rlm@1
|
2159 Function *func, Object **lastVar)
|
rlm@1
|
2160 {
|
rlm@1
|
2161 int bytes;
|
rlm@1
|
2162 u32 start = func->lowPC;
|
rlm@1
|
2163 u32 end = func->highPC;
|
rlm@1
|
2164
|
rlm@1
|
2165 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2166 {
|
rlm@1
|
2167 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
2168 data = elfReadAttribute(data, attr);
|
rlm@1
|
2169 switch (attr->name)
|
rlm@1
|
2170 {
|
rlm@1
|
2171 case DW_AT_sibling:
|
rlm@1
|
2172 break;
|
rlm@1
|
2173 case DW_AT_low_pc:
|
rlm@1
|
2174 start = attr->value;
|
rlm@1
|
2175 break;
|
rlm@1
|
2176 case DW_AT_high_pc:
|
rlm@1
|
2177 end = attr->value;
|
rlm@1
|
2178 break;
|
rlm@1
|
2179 case DW_AT_ranges: // ignore for now
|
rlm@1
|
2180 break;
|
rlm@1
|
2181 default:
|
rlm@1
|
2182 fprintf(stderr, "Unknown block attribute %02x\n", attr->name);
|
rlm@1
|
2183 break;
|
rlm@1
|
2184 }
|
rlm@1
|
2185 }
|
rlm@1
|
2186
|
rlm@1
|
2187 if (abbrev->hasChildren)
|
rlm@1
|
2188 {
|
rlm@1
|
2189 int nesting = 1;
|
rlm@1
|
2190
|
rlm@1
|
2191 while (nesting)
|
rlm@1
|
2192 {
|
rlm@1
|
2193 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2194 data += bytes;
|
rlm@1
|
2195
|
rlm@1
|
2196 if (!abbrevNum)
|
rlm@1
|
2197 {
|
rlm@1
|
2198 nesting--;
|
rlm@1
|
2199 continue;
|
rlm@1
|
2200 }
|
rlm@1
|
2201
|
rlm@1
|
2202 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2203
|
rlm@1
|
2204 switch (abbrev->tag)
|
rlm@1
|
2205 {
|
rlm@1
|
2206 CASE_TYPE_TAG: // types only parsed when used
|
rlm@1
|
2207 case DW_TAG_label: // not needed
|
rlm@1
|
2208 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2209 break;
|
rlm@1
|
2210 case DW_TAG_lexical_block:
|
rlm@1
|
2211 data = elfParseBlock(data, abbrev, unit, func, lastVar);
|
rlm@1
|
2212 break;
|
rlm@1
|
2213 case DW_TAG_subprogram:
|
rlm@1
|
2214 {
|
rlm@1
|
2215 Function *f = NULL;
|
rlm@1
|
2216 data = elfParseFunction(data, abbrev, unit, &f);
|
rlm@1
|
2217 if (f != NULL)
|
rlm@1
|
2218 {
|
rlm@1
|
2219 if (unit->lastFunction)
|
rlm@1
|
2220 unit->lastFunction->next = f;
|
rlm@1
|
2221 else
|
rlm@1
|
2222 unit->functions = f;
|
rlm@1
|
2223 unit->lastFunction = f;
|
rlm@1
|
2224 }
|
rlm@1
|
2225 break;
|
rlm@1
|
2226 }
|
rlm@1
|
2227 case DW_TAG_variable:
|
rlm@1
|
2228 {
|
rlm@1
|
2229 Object *o;
|
rlm@1
|
2230 data = elfParseObject(data, abbrev, unit, &o);
|
rlm@1
|
2231 if (o->startScope == 0)
|
rlm@1
|
2232 o->startScope = start;
|
rlm@1
|
2233 if (o->endScope == 0)
|
rlm@1
|
2234 o->endScope = 0;
|
rlm@1
|
2235 if (func->variables)
|
rlm@1
|
2236 (*lastVar)->next = o;
|
rlm@1
|
2237 else
|
rlm@1
|
2238 func->variables = o;
|
rlm@1
|
2239 *lastVar = o;
|
rlm@1
|
2240 break;
|
rlm@1
|
2241 }
|
rlm@1
|
2242 case DW_TAG_inlined_subroutine:
|
rlm@1
|
2243 // TODO:
|
rlm@1
|
2244 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2245 break;
|
rlm@1
|
2246 default:
|
rlm@1
|
2247 {
|
rlm@1
|
2248 fprintf(stderr, "Unknown block TAG %02x\n", abbrev->tag);
|
rlm@1
|
2249 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2250 break;
|
rlm@1
|
2251 }
|
rlm@1
|
2252 }
|
rlm@1
|
2253 }
|
rlm@1
|
2254 }
|
rlm@1
|
2255 return data;
|
rlm@1
|
2256 }
|
rlm@1
|
2257
|
rlm@1
|
2258 void elfGetFunctionAttributes(CompileUnit *unit, u32 offset, Function *func)
|
rlm@1
|
2259 {
|
rlm@1
|
2260 u8 *data = unit->top + offset;
|
rlm@1
|
2261 int bytes;
|
rlm@1
|
2262 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2263 data += bytes;
|
rlm@1
|
2264
|
rlm@1
|
2265 if (!abbrevNum)
|
rlm@1
|
2266 {
|
rlm@1
|
2267 return;
|
rlm@1
|
2268 }
|
rlm@1
|
2269
|
rlm@1
|
2270 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2271
|
rlm@1
|
2272 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2273 {
|
rlm@1
|
2274 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
2275 data = elfReadAttribute(data, attr);
|
rlm@1
|
2276
|
rlm@1
|
2277 switch (attr->name)
|
rlm@1
|
2278 {
|
rlm@1
|
2279 case DW_AT_sibling:
|
rlm@1
|
2280 break;
|
rlm@1
|
2281 case DW_AT_name:
|
rlm@1
|
2282 if (func->name == NULL)
|
rlm@1
|
2283 func->name = attr->string;
|
rlm@1
|
2284 break;
|
rlm@1
|
2285 case DW_AT_MIPS_linkage_name:
|
rlm@1
|
2286 func->name = attr->string;
|
rlm@1
|
2287 break;
|
rlm@1
|
2288 case DW_AT_low_pc:
|
rlm@1
|
2289 func->lowPC = attr->value;
|
rlm@1
|
2290 break;
|
rlm@1
|
2291 case DW_AT_high_pc:
|
rlm@1
|
2292 func->highPC = attr->value;
|
rlm@1
|
2293 break;
|
rlm@1
|
2294 case DW_AT_decl_file:
|
rlm@1
|
2295 func->file = attr->value;
|
rlm@1
|
2296 break;
|
rlm@1
|
2297 case DW_AT_decl_line:
|
rlm@1
|
2298 func->line = attr->value;
|
rlm@1
|
2299 break;
|
rlm@1
|
2300 case DW_AT_external:
|
rlm@1
|
2301 func->external = attr->flag;
|
rlm@1
|
2302 break;
|
rlm@1
|
2303 case DW_AT_frame_base:
|
rlm@1
|
2304 func->frameBase = attr->block;
|
rlm@1
|
2305 break;
|
rlm@1
|
2306 case DW_AT_type:
|
rlm@1
|
2307 func->returnType = elfParseType(unit, attr->value);
|
rlm@1
|
2308 break;
|
rlm@1
|
2309 case DW_AT_inline:
|
rlm@1
|
2310 case DW_AT_specification:
|
rlm@1
|
2311 case DW_AT_declaration:
|
rlm@1
|
2312 case DW_AT_artificial:
|
rlm@1
|
2313 case DW_AT_prototyped:
|
rlm@1
|
2314 case DW_AT_proc_body:
|
rlm@1
|
2315 case DW_AT_save_offset:
|
rlm@1
|
2316 case DW_AT_user_2002:
|
rlm@1
|
2317 case DW_AT_virtuality:
|
rlm@1
|
2318 case DW_AT_containing_type:
|
rlm@1
|
2319 case DW_AT_accessibility:
|
rlm@1
|
2320 // todo;
|
rlm@1
|
2321 break;
|
rlm@1
|
2322 case DW_AT_vtable_elem_location:
|
rlm@1
|
2323 free(attr->block);
|
rlm@1
|
2324 break;
|
rlm@1
|
2325 default:
|
rlm@1
|
2326 fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
|
rlm@1
|
2327 break;
|
rlm@1
|
2328 }
|
rlm@1
|
2329 }
|
rlm@1
|
2330
|
rlm@1
|
2331 return;
|
rlm@1
|
2332 }
|
rlm@1
|
2333
|
rlm@1
|
2334 u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
|
rlm@1
|
2335 Function **f)
|
rlm@1
|
2336 {
|
rlm@1
|
2337 Function *func = (Function *)calloc(sizeof(Function), 1);
|
rlm@1
|
2338 *f = func;
|
rlm@1
|
2339
|
rlm@1
|
2340 int bytes;
|
rlm@1
|
2341 bool mangled = false;
|
rlm@1
|
2342 bool declaration = false;
|
rlm@1
|
2343 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2344 {
|
rlm@1
|
2345 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
2346 data = elfReadAttribute(data, attr);
|
rlm@1
|
2347 switch (attr->name)
|
rlm@1
|
2348 {
|
rlm@1
|
2349 case DW_AT_sibling:
|
rlm@1
|
2350 break;
|
rlm@1
|
2351 case DW_AT_name:
|
rlm@1
|
2352 if (func->name == NULL)
|
rlm@1
|
2353 func->name = attr->string;
|
rlm@1
|
2354 break;
|
rlm@1
|
2355 case DW_AT_MIPS_linkage_name:
|
rlm@1
|
2356 func->name = attr->string;
|
rlm@1
|
2357 mangled = true;
|
rlm@1
|
2358 break;
|
rlm@1
|
2359 case DW_AT_low_pc:
|
rlm@1
|
2360 func->lowPC = attr->value;
|
rlm@1
|
2361 break;
|
rlm@1
|
2362 case DW_AT_high_pc:
|
rlm@1
|
2363 func->highPC = attr->value;
|
rlm@1
|
2364 break;
|
rlm@1
|
2365 case DW_AT_prototyped:
|
rlm@1
|
2366 break;
|
rlm@1
|
2367 case DW_AT_decl_file:
|
rlm@1
|
2368 func->file = attr->value;
|
rlm@1
|
2369 break;
|
rlm@1
|
2370 case DW_AT_decl_line:
|
rlm@1
|
2371 func->line = attr->value;
|
rlm@1
|
2372 break;
|
rlm@1
|
2373 case DW_AT_external:
|
rlm@1
|
2374 func->external = attr->flag;
|
rlm@1
|
2375 break;
|
rlm@1
|
2376 case DW_AT_frame_base:
|
rlm@1
|
2377 func->frameBase = attr->block;
|
rlm@1
|
2378 break;
|
rlm@1
|
2379 case DW_AT_type:
|
rlm@1
|
2380 func->returnType = elfParseType(unit, attr->value);
|
rlm@1
|
2381 break;
|
rlm@1
|
2382 case DW_AT_abstract_origin:
|
rlm@1
|
2383 elfGetFunctionAttributes(unit, attr->value, func);
|
rlm@1
|
2384 break;
|
rlm@1
|
2385 case DW_AT_declaration:
|
rlm@1
|
2386 declaration = attr->flag;
|
rlm@1
|
2387 break;
|
rlm@1
|
2388 case DW_AT_inline:
|
rlm@1
|
2389 case DW_AT_specification:
|
rlm@1
|
2390 case DW_AT_artificial:
|
rlm@1
|
2391 case DW_AT_proc_body:
|
rlm@1
|
2392 case DW_AT_save_offset:
|
rlm@1
|
2393 case DW_AT_user_2002:
|
rlm@1
|
2394 case DW_AT_virtuality:
|
rlm@1
|
2395 case DW_AT_containing_type:
|
rlm@1
|
2396 case DW_AT_accessibility:
|
rlm@1
|
2397 // todo;
|
rlm@1
|
2398 break;
|
rlm@1
|
2399 case DW_AT_vtable_elem_location:
|
rlm@1
|
2400 free(attr->block);
|
rlm@1
|
2401 break;
|
rlm@1
|
2402 default:
|
rlm@1
|
2403 fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
|
rlm@1
|
2404 break;
|
rlm@1
|
2405 }
|
rlm@1
|
2406 }
|
rlm@1
|
2407
|
rlm@1
|
2408 if (declaration)
|
rlm@1
|
2409 {
|
rlm@1
|
2410 elfCleanUp(func);
|
rlm@1
|
2411 free(func);
|
rlm@1
|
2412 *f = NULL;
|
rlm@1
|
2413
|
rlm@1
|
2414 while (1)
|
rlm@1
|
2415 {
|
rlm@1
|
2416 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2417 data += bytes;
|
rlm@1
|
2418
|
rlm@1
|
2419 if (!abbrevNum)
|
rlm@1
|
2420 {
|
rlm@1
|
2421 return data;
|
rlm@1
|
2422 }
|
rlm@1
|
2423
|
rlm@1
|
2424 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2425
|
rlm@1
|
2426 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2427 }
|
rlm@1
|
2428 }
|
rlm@1
|
2429
|
rlm@1
|
2430 if (abbrev->hasChildren)
|
rlm@1
|
2431 {
|
rlm@1
|
2432 int nesting = 1;
|
rlm@1
|
2433 Object *lastParam = NULL;
|
rlm@1
|
2434 Object *lastVar = NULL;
|
rlm@1
|
2435
|
rlm@1
|
2436 while (nesting)
|
rlm@1
|
2437 {
|
rlm@1
|
2438 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2439 data += bytes;
|
rlm@1
|
2440
|
rlm@1
|
2441 if (!abbrevNum)
|
rlm@1
|
2442 {
|
rlm@1
|
2443 nesting--;
|
rlm@1
|
2444 continue;
|
rlm@1
|
2445 }
|
rlm@1
|
2446
|
rlm@1
|
2447 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2448
|
rlm@1
|
2449 switch (abbrev->tag)
|
rlm@1
|
2450 {
|
rlm@1
|
2451 CASE_TYPE_TAG: // no need to parse types. only parsed when used
|
rlm@1
|
2452 case DW_TAG_label: // not needed
|
rlm@1
|
2453 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2454 break;
|
rlm@1
|
2455 case DW_TAG_subprogram:
|
rlm@1
|
2456 {
|
rlm@1
|
2457 Function *fnc = NULL;
|
rlm@1
|
2458 data = elfParseFunction(data, abbrev, unit, &fnc);
|
rlm@1
|
2459 if (fnc != NULL)
|
rlm@1
|
2460 {
|
rlm@1
|
2461 if (unit->lastFunction == NULL)
|
rlm@1
|
2462 unit->functions = fnc;
|
rlm@1
|
2463 else
|
rlm@1
|
2464 unit->lastFunction->next = fnc;
|
rlm@1
|
2465 unit->lastFunction = fnc;
|
rlm@1
|
2466 }
|
rlm@1
|
2467 break;
|
rlm@1
|
2468 }
|
rlm@1
|
2469 case DW_TAG_lexical_block:
|
rlm@1
|
2470 {
|
rlm@1
|
2471 data = elfParseBlock(data, abbrev, unit, func, &lastVar);
|
rlm@1
|
2472 break;
|
rlm@1
|
2473 }
|
rlm@1
|
2474 case DW_TAG_formal_parameter:
|
rlm@1
|
2475 {
|
rlm@1
|
2476 Object *o;
|
rlm@1
|
2477 data = elfParseObject(data, abbrev, unit, &o);
|
rlm@1
|
2478 if (func->parameters)
|
rlm@1
|
2479 lastParam->next = o;
|
rlm@1
|
2480 else
|
rlm@1
|
2481 func->parameters = o;
|
rlm@1
|
2482 lastParam = o;
|
rlm@1
|
2483 break;
|
rlm@1
|
2484 }
|
rlm@1
|
2485 case DW_TAG_variable:
|
rlm@1
|
2486 {
|
rlm@1
|
2487 Object *o;
|
rlm@1
|
2488 data = elfParseObject(data, abbrev, unit, &o);
|
rlm@1
|
2489 if (func->variables)
|
rlm@1
|
2490 lastVar->next = o;
|
rlm@1
|
2491 else
|
rlm@1
|
2492 func->variables = o;
|
rlm@1
|
2493 lastVar = o;
|
rlm@1
|
2494 break;
|
rlm@1
|
2495 }
|
rlm@1
|
2496 case DW_TAG_unspecified_parameters:
|
rlm@1
|
2497 case DW_TAG_inlined_subroutine:
|
rlm@1
|
2498 {
|
rlm@1
|
2499 // todo
|
rlm@1
|
2500 for (int i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2501 {
|
rlm@1
|
2502 data = elfReadAttribute(data, &abbrev->attrs[i]);
|
rlm@1
|
2503 if (abbrev->attrs[i].form == DW_FORM_block1)
|
rlm@1
|
2504 free(abbrev->attrs[i].block);
|
rlm@1
|
2505 }
|
rlm@1
|
2506
|
rlm@1
|
2507 if (abbrev->hasChildren)
|
rlm@1
|
2508 nesting++;
|
rlm@1
|
2509 break;
|
rlm@1
|
2510 }
|
rlm@1
|
2511 default:
|
rlm@1
|
2512 {
|
rlm@1
|
2513 fprintf(stderr, "Unknown function TAG %02x\n", abbrev->tag);
|
rlm@1
|
2514 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2515 break;
|
rlm@1
|
2516 }
|
rlm@1
|
2517 }
|
rlm@1
|
2518 }
|
rlm@1
|
2519 }
|
rlm@1
|
2520 return data;
|
rlm@1
|
2521 }
|
rlm@1
|
2522
|
rlm@1
|
2523 u8 *elfParseUnknownData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
|
rlm@1
|
2524 {
|
rlm@1
|
2525 int i;
|
rlm@1
|
2526 int bytes;
|
rlm@1
|
2527 // switch(abbrev->tag) {
|
rlm@1
|
2528 // default:
|
rlm@1
|
2529 fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
|
rlm@1
|
2530
|
rlm@1
|
2531 for (i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2532 {
|
rlm@1
|
2533 data = elfReadAttribute(data, &abbrev->attrs[i]);
|
rlm@1
|
2534 if (abbrev->attrs[i].form == DW_FORM_block1)
|
rlm@1
|
2535 free(abbrev->attrs[i].block);
|
rlm@1
|
2536 }
|
rlm@1
|
2537
|
rlm@1
|
2538 if (abbrev->hasChildren)
|
rlm@1
|
2539 {
|
rlm@1
|
2540 int nesting = 1;
|
rlm@1
|
2541 while (nesting)
|
rlm@1
|
2542 {
|
rlm@1
|
2543 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2544 data += bytes;
|
rlm@1
|
2545
|
rlm@1
|
2546 if (!abbrevNum)
|
rlm@1
|
2547 {
|
rlm@1
|
2548 nesting--;
|
rlm@1
|
2549 continue;
|
rlm@1
|
2550 }
|
rlm@1
|
2551
|
rlm@1
|
2552 abbrev = elfGetAbbrev(abbrevs, abbrevNum);
|
rlm@1
|
2553
|
rlm@1
|
2554 fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
|
rlm@1
|
2555
|
rlm@1
|
2556 for (i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2557 {
|
rlm@1
|
2558 data = elfReadAttribute(data, &abbrev->attrs[i]);
|
rlm@1
|
2559 if (abbrev->attrs[i].form == DW_FORM_block1)
|
rlm@1
|
2560 free(abbrev->attrs[i].block);
|
rlm@1
|
2561 }
|
rlm@1
|
2562
|
rlm@1
|
2563 if (abbrev->hasChildren)
|
rlm@1
|
2564 {
|
rlm@1
|
2565 nesting++;
|
rlm@1
|
2566 }
|
rlm@1
|
2567 }
|
rlm@1
|
2568 }
|
rlm@1
|
2569 // }
|
rlm@1
|
2570 return data;
|
rlm@1
|
2571 }
|
rlm@1
|
2572
|
rlm@1
|
2573 u8 *elfParseCompileUnitChildren(u8 *data, CompileUnit *unit)
|
rlm@1
|
2574 {
|
rlm@1
|
2575 int bytes;
|
rlm@1
|
2576 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2577 data += bytes;
|
rlm@1
|
2578 Object *lastObj = NULL;
|
rlm@1
|
2579 while (abbrevNum)
|
rlm@1
|
2580 {
|
rlm@1
|
2581 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
|
rlm@1
|
2582 switch (abbrev->tag)
|
rlm@1
|
2583 {
|
rlm@1
|
2584 case DW_TAG_subprogram:
|
rlm@1
|
2585 {
|
rlm@1
|
2586 Function *func = NULL;
|
rlm@1
|
2587 data = elfParseFunction(data, abbrev, unit, &func);
|
rlm@1
|
2588 if (func != NULL)
|
rlm@1
|
2589 {
|
rlm@1
|
2590 if (unit->lastFunction)
|
rlm@1
|
2591 unit->lastFunction->next = func;
|
rlm@1
|
2592 else
|
rlm@1
|
2593 unit->functions = func;
|
rlm@1
|
2594 unit->lastFunction = func;
|
rlm@1
|
2595 }
|
rlm@1
|
2596 break;
|
rlm@1
|
2597 }
|
rlm@1
|
2598 CASE_TYPE_TAG:
|
rlm@1
|
2599 data = elfSkipData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2600 break;
|
rlm@1
|
2601 case DW_TAG_variable:
|
rlm@1
|
2602 {
|
rlm@1
|
2603 Object *var = NULL;
|
rlm@1
|
2604 data = elfParseObject(data, abbrev, unit, &var);
|
rlm@1
|
2605 if (lastObj)
|
rlm@1
|
2606 lastObj->next = var;
|
rlm@1
|
2607 else
|
rlm@1
|
2608 unit->variables = var;
|
rlm@1
|
2609 lastObj = var;
|
rlm@1
|
2610 break;
|
rlm@1
|
2611 }
|
rlm@1
|
2612 default:
|
rlm@1
|
2613 data = elfParseUnknownData(data, abbrev, unit->abbrevs);
|
rlm@1
|
2614 break;
|
rlm@1
|
2615 }
|
rlm@1
|
2616
|
rlm@1
|
2617 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2618 data += bytes;
|
rlm@1
|
2619 }
|
rlm@1
|
2620 return data;
|
rlm@1
|
2621 }
|
rlm@1
|
2622
|
rlm@1
|
2623 CompileUnit *elfParseCompUnit(u8 *data, u8 *abbrevData)
|
rlm@1
|
2624 {
|
rlm@1
|
2625 int bytes;
|
rlm@1
|
2626 u8 *top = data;
|
rlm@1
|
2627
|
rlm@1
|
2628 u32 length = elfRead4Bytes(data);
|
rlm@1
|
2629 data += 4;
|
rlm@1
|
2630
|
rlm@1
|
2631 u16 version = elfRead2Bytes(data);
|
rlm@1
|
2632 data += 2;
|
rlm@1
|
2633
|
rlm@1
|
2634 u32 offset = elfRead4Bytes(data);
|
rlm@1
|
2635 data += 4;
|
rlm@1
|
2636
|
rlm@1
|
2637 u8 addrSize = *data++;
|
rlm@1
|
2638
|
rlm@1
|
2639 if (version != 2)
|
rlm@1
|
2640 {
|
rlm@1
|
2641 fprintf(stderr, "Unsupported debugging information version %d\n", version);
|
rlm@1
|
2642 return NULL;
|
rlm@1
|
2643 }
|
rlm@1
|
2644
|
rlm@1
|
2645 if (addrSize != 4)
|
rlm@1
|
2646 {
|
rlm@1
|
2647 fprintf(stderr, "Unsupported address size %d\n", addrSize);
|
rlm@1
|
2648 return NULL;
|
rlm@1
|
2649 }
|
rlm@1
|
2650
|
rlm@1
|
2651 ELFAbbrev **abbrevs = elfReadAbbrevs(abbrevData, offset);
|
rlm@1
|
2652
|
rlm@1
|
2653 u32 abbrevNum = elfReadLEB128(data, &bytes);
|
rlm@1
|
2654 data += bytes;
|
rlm@1
|
2655
|
rlm@1
|
2656 ELFAbbrev *abbrev = elfGetAbbrev(abbrevs, abbrevNum);
|
rlm@1
|
2657
|
rlm@1
|
2658 CompileUnit *unit = (CompileUnit *)calloc(sizeof(CompileUnit), 1);
|
rlm@1
|
2659 unit->top = top;
|
rlm@1
|
2660 unit->length = length;
|
rlm@1
|
2661 unit->abbrevs = abbrevs;
|
rlm@1
|
2662 unit->next = NULL;
|
rlm@1
|
2663
|
rlm@1
|
2664 elfCurrentUnit = unit;
|
rlm@1
|
2665
|
rlm@1
|
2666 int i;
|
rlm@1
|
2667
|
rlm@1
|
2668 for (i = 0; i < abbrev->numAttrs; i++)
|
rlm@1
|
2669 {
|
rlm@1
|
2670 ELFAttr *attr = &abbrev->attrs[i];
|
rlm@1
|
2671 data = elfReadAttribute(data, attr);
|
rlm@1
|
2672
|
rlm@1
|
2673 switch (attr->name)
|
rlm@1
|
2674 {
|
rlm@1
|
2675 case DW_AT_name:
|
rlm@1
|
2676 unit->name = attr->string;
|
rlm@1
|
2677 break;
|
rlm@1
|
2678 case DW_AT_stmt_list:
|
rlm@1
|
2679 unit->hasLineInfo = true;
|
rlm@1
|
2680 unit->lineInfo = attr->value;
|
rlm@1
|
2681 break;
|
rlm@1
|
2682 case DW_AT_low_pc:
|
rlm@1
|
2683 unit->lowPC = attr->value;
|
rlm@1
|
2684 break;
|
rlm@1
|
2685 case DW_AT_high_pc:
|
rlm@1
|
2686 unit->highPC = attr->value;
|
rlm@1
|
2687 break;
|
rlm@1
|
2688 case DW_AT_compdir:
|
rlm@1
|
2689 unit->compdir = attr->string;
|
rlm@1
|
2690 break;
|
rlm@1
|
2691 // ignore
|
rlm@1
|
2692 case DW_AT_language:
|
rlm@1
|
2693 case DW_AT_producer:
|
rlm@1
|
2694 case DW_AT_macro_info:
|
rlm@1
|
2695 case DW_AT_entry_pc:
|
rlm@1
|
2696 break;
|
rlm@1
|
2697 default:
|
rlm@1
|
2698 fprintf(stderr, "Unknown attribute %02x\n", attr->name);
|
rlm@1
|
2699 break;
|
rlm@1
|
2700 }
|
rlm@1
|
2701 }
|
rlm@1
|
2702
|
rlm@1
|
2703 if (abbrev->hasChildren)
|
rlm@1
|
2704 elfParseCompileUnitChildren(data, unit);
|
rlm@1
|
2705
|
rlm@1
|
2706 return unit;
|
rlm@1
|
2707 }
|
rlm@1
|
2708
|
rlm@1
|
2709 void elfParseAranges(u8 *data)
|
rlm@1
|
2710 {
|
rlm@1
|
2711 ELFSectionHeader *sh = elfGetSectionByName(".debug_aranges");
|
rlm@1
|
2712 if (sh == NULL)
|
rlm@1
|
2713 {
|
rlm@1
|
2714 fprintf(stderr, "No aranges found\n");
|
rlm@1
|
2715 return;
|
rlm@1
|
2716 }
|
rlm@1
|
2717
|
rlm@1
|
2718 data = elfReadSection(data, sh);
|
rlm@1
|
2719 u8 *end = data + READ32LE(&sh->size);
|
rlm@1
|
2720
|
rlm@1
|
2721 int max = 4;
|
rlm@1
|
2722 ARanges *ranges = (ARanges *)calloc(sizeof(ARanges), 4);
|
rlm@1
|
2723
|
rlm@1
|
2724 int index = 0;
|
rlm@1
|
2725
|
rlm@1
|
2726 while (data < end)
|
rlm@1
|
2727 {
|
rlm@1
|
2728 u32 len = elfRead4Bytes(data);
|
rlm@1
|
2729 data += 4;
|
rlm@1
|
2730 // u16 version = elfRead2Bytes(data);
|
rlm@1
|
2731 data += 2;
|
rlm@1
|
2732 u32 offset = elfRead4Bytes(data);
|
rlm@1
|
2733 data += 4;
|
rlm@1
|
2734 // u8 addrSize = *data++;
|
rlm@1
|
2735 // u8 segSize = *data++;
|
rlm@1
|
2736 data += 2; // remove if uncommenting above
|
rlm@1
|
2737 data += 4;
|
rlm@1
|
2738 ranges[index].count = (len-20)/8;
|
rlm@1
|
2739 ranges[index].offset = offset;
|
rlm@1
|
2740 ranges[index].ranges = (ARange *)calloc(sizeof(ARange), (len-20)/8);
|
rlm@1
|
2741 int i = 0;
|
rlm@1
|
2742 while (true)
|
rlm@1
|
2743 {
|
rlm@1
|
2744 u32 addr = elfRead4Bytes(data);
|
rlm@1
|
2745 data += 4;
|
rlm@1
|
2746 u32 len = elfRead4Bytes(data);
|
rlm@1
|
2747 data += 4;
|
rlm@1
|
2748 if (addr == 0 && len == 0)
|
rlm@1
|
2749 break;
|
rlm@1
|
2750 ranges[index].ranges[i].lowPC = addr;
|
rlm@1
|
2751 ranges[index].ranges[i].highPC = addr+len;
|
rlm@1
|
2752 i++;
|
rlm@1
|
2753 }
|
rlm@1
|
2754 index++;
|
rlm@1
|
2755 if (index == max)
|
rlm@1
|
2756 {
|
rlm@1
|
2757 max += 4;
|
rlm@1
|
2758 ranges = (ARanges *)realloc(ranges, max*sizeof(ARanges));
|
rlm@1
|
2759 }
|
rlm@1
|
2760 }
|
rlm@1
|
2761 elfDebugInfo->numRanges = index;
|
rlm@1
|
2762 elfDebugInfo->ranges = ranges;
|
rlm@1
|
2763 }
|
rlm@1
|
2764
|
rlm@1
|
2765 void elfReadSymtab(u8 *data)
|
rlm@1
|
2766 {
|
rlm@1
|
2767 ELFSectionHeader *sh = elfGetSectionByName(".symtab");
|
rlm@1
|
2768 int table = READ32LE(&sh->link);
|
rlm@1
|
2769
|
rlm@1
|
2770 char *strtable = (char *)elfReadSection(data, elfGetSectionByNumber(table));
|
rlm@1
|
2771
|
rlm@1
|
2772 ELFSymbol *symtab = (ELFSymbol *)elfReadSection(data, sh);
|
rlm@1
|
2773
|
rlm@1
|
2774 int count = READ32LE(&sh->size) / sizeof(ELFSymbol);
|
rlm@1
|
2775 elfSymbolsCount = 0;
|
rlm@1
|
2776
|
rlm@1
|
2777 elfSymbols = (Symbol *)malloc(sizeof(Symbol)*count);
|
rlm@1
|
2778
|
rlm@1
|
2779 int i;
|
rlm@1
|
2780
|
rlm@1
|
2781 for (i = 0; i < count; i++)
|
rlm@1
|
2782 {
|
rlm@1
|
2783 ELFSymbol *s = &symtab[i];
|
rlm@1
|
2784 int type = s->info & 15;
|
rlm@1
|
2785 int binding = s->info >> 4;
|
rlm@1
|
2786
|
rlm@1
|
2787 if (binding)
|
rlm@1
|
2788 {
|
rlm@1
|
2789 Symbol *sym = &elfSymbols[elfSymbolsCount];
|
rlm@1
|
2790 sym->name = &strtable[READ32LE(&s->name)];
|
rlm@1
|
2791 sym->binding = binding;
|
rlm@1
|
2792 sym->type = type;
|
rlm@1
|
2793 sym->value = READ32LE(&s->value);
|
rlm@1
|
2794 sym->size = READ32LE(&s->size);
|
rlm@1
|
2795 elfSymbolsCount++;
|
rlm@1
|
2796 }
|
rlm@1
|
2797 }
|
rlm@1
|
2798 for (i = 0; i < count; i++)
|
rlm@1
|
2799 {
|
rlm@1
|
2800 ELFSymbol *s = &symtab[i];
|
rlm@1
|
2801 int bind = s->info>>4;
|
rlm@1
|
2802 int type = s->info & 15;
|
rlm@1
|
2803
|
rlm@1
|
2804 if (!bind)
|
rlm@1
|
2805 {
|
rlm@1
|
2806 Symbol *sym = &elfSymbols[elfSymbolsCount];
|
rlm@1
|
2807 sym->name = &strtable[READ32LE(&s->name)];
|
rlm@1
|
2808 sym->binding = (s->info >> 4);
|
rlm@1
|
2809 sym->type = type;
|
rlm@1
|
2810 sym->value = READ32LE(&s->value);
|
rlm@1
|
2811 sym->size = READ32LE(&s->size);
|
rlm@1
|
2812 elfSymbolsCount++;
|
rlm@1
|
2813 }
|
rlm@1
|
2814 }
|
rlm@1
|
2815 elfSymbolsStrTab = strtable;
|
rlm@1
|
2816 // free(symtab);
|
rlm@1
|
2817 }
|
rlm@1
|
2818
|
rlm@1
|
2819 bool elfReadProgram(ELFHeader *eh, u8 *data, int& size, bool parseDebug)
|
rlm@1
|
2820 {
|
rlm@1
|
2821 int count = READ16LE(&eh->e_phnum);
|
rlm@1
|
2822 int i;
|
rlm@1
|
2823
|
rlm@1
|
2824 if (READ32LE(&eh->e_entry) == 0x2000000)
|
rlm@1
|
2825 cpuIsMultiBoot = true;
|
rlm@1
|
2826
|
rlm@1
|
2827 // read program headers... should probably move this code down
|
rlm@1
|
2828 u8 *p = data + READ32LE(&eh->e_phoff);
|
rlm@1
|
2829 size = 0;
|
rlm@1
|
2830 for (i = 0; i < count; i++)
|
rlm@1
|
2831 {
|
rlm@1
|
2832 ELFProgramHeader *ph = (ELFProgramHeader *)p;
|
rlm@1
|
2833 p += sizeof(ELFProgramHeader);
|
rlm@1
|
2834 if (READ16LE(&eh->e_phentsize) != sizeof(ELFProgramHeader))
|
rlm@1
|
2835 {
|
rlm@1
|
2836 p += READ16LE(&eh->e_phentsize) - sizeof(ELFProgramHeader);
|
rlm@1
|
2837 }
|
rlm@1
|
2838
|
rlm@1
|
2839 // printf("PH %d %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
rlm@1
|
2840 // i, ph->type, ph->offset, ph->vaddr, ph->paddr,
|
rlm@1
|
2841 // ph->filesz, ph->memsz, ph->flags, ph->align);
|
rlm@1
|
2842 if (cpuIsMultiBoot)
|
rlm@1
|
2843 {
|
rlm@1
|
2844 if (READ32LE(&ph->paddr) >= 0x2000000 &&
|
rlm@1
|
2845 READ32LE(&ph->paddr) <= 0x203ffff)
|
rlm@1
|
2846 {
|
rlm@1
|
2847 memcpy(&workRAM[READ32LE(&ph->paddr) & 0x3ffff],
|
rlm@1
|
2848 data + READ32LE(&ph->offset),
|
rlm@1
|
2849 READ32LE(&ph->filesz));
|
rlm@1
|
2850 }
|
rlm@1
|
2851 }
|
rlm@1
|
2852 else
|
rlm@1
|
2853 {
|
rlm@1
|
2854 if (READ32LE(&ph->paddr) >= 0x8000000 &&
|
rlm@1
|
2855 READ32LE(&ph->paddr) <= 0x9ffffff)
|
rlm@1
|
2856 {
|
rlm@1
|
2857 memcpy(&rom[READ32LE(&ph->paddr) & 0x1ffffff],
|
rlm@1
|
2858 data + READ32LE(&ph->offset),
|
rlm@1
|
2859 READ32LE(&ph->filesz));
|
rlm@1
|
2860 size += READ32LE(&ph->filesz);
|
rlm@1
|
2861 }
|
rlm@1
|
2862 }
|
rlm@1
|
2863 }
|
rlm@1
|
2864
|
rlm@1
|
2865 char *stringTable = NULL;
|
rlm@1
|
2866
|
rlm@1
|
2867 // read section headers
|
rlm@1
|
2868 p = data + READ32LE(&eh->e_shoff);
|
rlm@1
|
2869 count = READ16LE(&eh->e_shnum);
|
rlm@1
|
2870
|
rlm@1
|
2871 ELFSectionHeader **sh = (ELFSectionHeader * *)
|
rlm@1
|
2872 malloc(sizeof(ELFSectionHeader *) * count);
|
rlm@1
|
2873
|
rlm@1
|
2874 for (i = 0; i < count; i++)
|
rlm@1
|
2875 {
|
rlm@1
|
2876 sh[i] = (ELFSectionHeader *)p;
|
rlm@1
|
2877 p += sizeof(ELFSectionHeader);
|
rlm@1
|
2878 if (READ16LE(&eh->e_shentsize) != sizeof(ELFSectionHeader))
|
rlm@1
|
2879 p += READ16LE(&eh->e_shentsize) - sizeof(ELFSectionHeader);
|
rlm@1
|
2880 }
|
rlm@1
|
2881
|
rlm@1
|
2882 if (READ16LE(&eh->e_shstrndx) != 0)
|
rlm@1
|
2883 {
|
rlm@1
|
2884 stringTable = (char *)elfReadSection(data,
|
rlm@1
|
2885 sh[READ16LE(&eh->e_shstrndx)]);
|
rlm@1
|
2886 }
|
rlm@1
|
2887
|
rlm@1
|
2888 elfSectionHeaders = sh;
|
rlm@1
|
2889 elfSectionHeadersStringTable = stringTable;
|
rlm@1
|
2890 elfSectionHeadersCount = count;
|
rlm@1
|
2891
|
rlm@1
|
2892 for (i = 0; i < count; i++)
|
rlm@1
|
2893 {
|
rlm@1
|
2894 // printf("SH %d %-20s %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
rlm@1
|
2895 // i, &stringTable[sh[i]->name], sh[i]->name, sh[i]->type,
|
rlm@1
|
2896 // sh[i]->flags, sh[i]->addr, sh[i]->offset, sh[i]->size,
|
rlm@1
|
2897 // sh[i]->link, sh[i]->info);
|
rlm@1
|
2898 if (READ32LE(&sh[i]->flags) & 2) // load section
|
rlm@1
|
2899 {
|
rlm@1
|
2900 if (cpuIsMultiBoot)
|
rlm@1
|
2901 {
|
rlm@1
|
2902 if (READ32LE(&sh[i]->addr) >= 0x2000000 &&
|
rlm@1
|
2903 READ32LE(&sh[i]->addr) <= 0x203ffff)
|
rlm@1
|
2904 {
|
rlm@1
|
2905 memcpy(&workRAM[READ32LE(&sh[i]->addr) & 0x3ffff], data +
|
rlm@1
|
2906 READ32LE(&sh[i]->offset),
|
rlm@1
|
2907 READ32LE(&sh[i]->size));
|
rlm@1
|
2908 }
|
rlm@1
|
2909 }
|
rlm@1
|
2910 else
|
rlm@1
|
2911 {
|
rlm@1
|
2912 if (READ32LE(&sh[i]->addr) >= 0x8000000 &&
|
rlm@1
|
2913 READ32LE(&sh[i]->addr) <= 0x9ffffff)
|
rlm@1
|
2914 {
|
rlm@1
|
2915 memcpy(&rom[READ32LE(&sh[i]->addr) & 0x1ffffff],
|
rlm@1
|
2916 data + READ32LE(&sh[i]->offset),
|
rlm@1
|
2917 READ32LE(&sh[i]->size));
|
rlm@1
|
2918 size += READ32LE(&sh[i]->size);
|
rlm@1
|
2919 }
|
rlm@1
|
2920 }
|
rlm@1
|
2921 }
|
rlm@1
|
2922 }
|
rlm@1
|
2923
|
rlm@1
|
2924 if (parseDebug)
|
rlm@1
|
2925 {
|
rlm@1
|
2926 fprintf(stderr, "Parsing debug info\n");
|
rlm@1
|
2927
|
rlm@1
|
2928 ELFSectionHeader *dbgHeader = elfGetSectionByName(".debug_info");
|
rlm@1
|
2929 if (dbgHeader == NULL)
|
rlm@1
|
2930 {
|
rlm@1
|
2931 fprintf(stderr, "Cannot find debug information\n");
|
rlm@1
|
2932 goto end;
|
rlm@1
|
2933 }
|
rlm@1
|
2934
|
rlm@1
|
2935 ELFSectionHeader *h = elfGetSectionByName(".debug_abbrev");
|
rlm@1
|
2936 if (h == NULL)
|
rlm@1
|
2937 {
|
rlm@1
|
2938 fprintf(stderr, "Cannot find abbreviation table\n");
|
rlm@1
|
2939 goto end;
|
rlm@1
|
2940 }
|
rlm@1
|
2941
|
rlm@1
|
2942 elfDebugInfo = (DebugInfo *)calloc(sizeof(DebugInfo), 1);
|
rlm@1
|
2943 u8 *abbrevdata = elfReadSection(data, h);
|
rlm@1
|
2944
|
rlm@1
|
2945 h = elfGetSectionByName(".debug_str");
|
rlm@1
|
2946
|
rlm@1
|
2947 if (h == NULL)
|
rlm@1
|
2948 elfDebugStrings = NULL;
|
rlm@1
|
2949 else
|
rlm@1
|
2950 elfDebugStrings = (char *)elfReadSection(data, h);
|
rlm@1
|
2951
|
rlm@1
|
2952 u8 *debugdata = elfReadSection(data, dbgHeader);
|
rlm@1
|
2953
|
rlm@1
|
2954 elfDebugInfo->debugdata = data;
|
rlm@1
|
2955 elfDebugInfo->infodata = debugdata;
|
rlm@1
|
2956
|
rlm@1
|
2957 u32 total = READ32LE(&dbgHeader->size);
|
rlm@1
|
2958 u8 *end = debugdata + total;
|
rlm@1
|
2959 u8 *ddata = debugdata;
|
rlm@1
|
2960
|
rlm@1
|
2961 CompileUnit *last = NULL;
|
rlm@1
|
2962 CompileUnit *unit = NULL;
|
rlm@1
|
2963
|
rlm@1
|
2964 while (ddata < end)
|
rlm@1
|
2965 {
|
rlm@1
|
2966 unit = elfParseCompUnit(ddata, abbrevdata);
|
rlm@1
|
2967 unit->offset = ddata-debugdata;
|
rlm@1
|
2968 elfParseLineInfo(unit, data);
|
rlm@1
|
2969 if (last == NULL)
|
rlm@1
|
2970 elfCompileUnits = unit;
|
rlm@1
|
2971 else
|
rlm@1
|
2972 last->next = unit;
|
rlm@1
|
2973 last = unit;
|
rlm@1
|
2974 ddata += 4 + unit->length;
|
rlm@1
|
2975 }
|
rlm@1
|
2976 elfParseAranges(data);
|
rlm@1
|
2977 CompileUnit *comp = elfCompileUnits;
|
rlm@1
|
2978 while (comp)
|
rlm@1
|
2979 {
|
rlm@1
|
2980 ARanges *r = elfDebugInfo->ranges;
|
rlm@1
|
2981 for (int i = 0; i < elfDebugInfo->numRanges; i++)
|
rlm@1
|
2982 if (r[i].offset == comp->offset)
|
rlm@1
|
2983 {
|
rlm@1
|
2984 comp->ranges = &r[i];
|
rlm@1
|
2985 break;
|
rlm@1
|
2986 }
|
rlm@1
|
2987 comp = comp->next;
|
rlm@1
|
2988 }
|
rlm@1
|
2989 elfParseCFA(data);
|
rlm@1
|
2990 elfReadSymtab(data);
|
rlm@1
|
2991 }
|
rlm@1
|
2992 end:
|
rlm@1
|
2993 if (sh)
|
rlm@1
|
2994 {
|
rlm@1
|
2995 free(sh);
|
rlm@1
|
2996 }
|
rlm@1
|
2997
|
rlm@1
|
2998 elfSectionHeaders = NULL;
|
rlm@1
|
2999 elfSectionHeadersStringTable = NULL;
|
rlm@1
|
3000 elfSectionHeadersCount = 0;
|
rlm@1
|
3001
|
rlm@1
|
3002 return true;
|
rlm@1
|
3003 }
|
rlm@1
|
3004
|
rlm@1
|
3005 extern bool8 parseDebug;
|
rlm@1
|
3006
|
rlm@1
|
3007 bool elfRead(const char *name, int& siz, FILE *f)
|
rlm@1
|
3008 {
|
rlm@1
|
3009 fseek(f, 0, SEEK_END);
|
rlm@1
|
3010 long size = ftell(f);
|
rlm@1
|
3011 elfFileData = (u8 *)malloc(size);
|
rlm@1
|
3012 fseek(f, 0, SEEK_SET);
|
rlm@1
|
3013 fread(elfFileData, 1, size, f);
|
rlm@1
|
3014 fclose(f);
|
rlm@1
|
3015
|
rlm@1
|
3016 ELFHeader *header = (ELFHeader *)elfFileData;
|
rlm@1
|
3017
|
rlm@1
|
3018 if (READ32LE(&header->magic) != 0x464C457F ||
|
rlm@1
|
3019 READ16LE(&header->e_machine) != 40 ||
|
rlm@1
|
3020 header->clazz != 1)
|
rlm@1
|
3021 {
|
rlm@1
|
3022 systemMessage(0, N_("Not a valid ELF file %s"), name);
|
rlm@1
|
3023 free(elfFileData);
|
rlm@1
|
3024 elfFileData = NULL;
|
rlm@1
|
3025 return false;
|
rlm@1
|
3026 }
|
rlm@1
|
3027
|
rlm@1
|
3028 if (!elfReadProgram(header, elfFileData, siz, parseDebug))
|
rlm@1
|
3029 {
|
rlm@1
|
3030 free(elfFileData);
|
rlm@1
|
3031 elfFileData = NULL;
|
rlm@1
|
3032 return false;
|
rlm@1
|
3033 }
|
rlm@1
|
3034
|
rlm@1
|
3035 return true;
|
rlm@1
|
3036 }
|
rlm@1
|
3037
|
rlm@1
|
3038 void elfCleanUp(Object *o)
|
rlm@1
|
3039 {
|
rlm@1
|
3040 free(o->location);
|
rlm@1
|
3041 }
|
rlm@1
|
3042
|
rlm@1
|
3043 void elfCleanUp(Function *func)
|
rlm@1
|
3044 {
|
rlm@1
|
3045 Object *o = func->parameters;
|
rlm@1
|
3046 while (o)
|
rlm@1
|
3047 {
|
rlm@1
|
3048 elfCleanUp(o);
|
rlm@1
|
3049 Object *next = o->next;
|
rlm@1
|
3050 free(o);
|
rlm@1
|
3051 o = next;
|
rlm@1
|
3052 }
|
rlm@1
|
3053
|
rlm@1
|
3054 o = func->variables;
|
rlm@1
|
3055 while (o)
|
rlm@1
|
3056 {
|
rlm@1
|
3057 elfCleanUp(o);
|
rlm@1
|
3058 Object *next = o->next;
|
rlm@1
|
3059 free(o);
|
rlm@1
|
3060 o = next;
|
rlm@1
|
3061 }
|
rlm@1
|
3062 free(func->frameBase);
|
rlm@1
|
3063 }
|
rlm@1
|
3064
|
rlm@1
|
3065 void elfCleanUp(ELFAbbrev **abbrevs)
|
rlm@1
|
3066 {
|
rlm@1
|
3067 for (int i = 0; i < 121; i++)
|
rlm@1
|
3068 {
|
rlm@1
|
3069 ELFAbbrev *abbrev = abbrevs[i];
|
rlm@1
|
3070
|
rlm@1
|
3071 while (abbrev)
|
rlm@1
|
3072 {
|
rlm@1
|
3073 free(abbrev->attrs);
|
rlm@1
|
3074 ELFAbbrev *next = abbrev->next;
|
rlm@1
|
3075 free(abbrev);
|
rlm@1
|
3076
|
rlm@1
|
3077 abbrev = next;
|
rlm@1
|
3078 }
|
rlm@1
|
3079 }
|
rlm@1
|
3080 }
|
rlm@1
|
3081
|
rlm@1
|
3082 void elfCleanUp(Type *t)
|
rlm@1
|
3083 {
|
rlm@1
|
3084 switch (t->type)
|
rlm@1
|
3085 {
|
rlm@1
|
3086 case TYPE_function:
|
rlm@1
|
3087 if (t->function)
|
rlm@1
|
3088 {
|
rlm@1
|
3089 Object *o = t->function->args;
|
rlm@1
|
3090 while (o)
|
rlm@1
|
3091 {
|
rlm@1
|
3092 elfCleanUp(o);
|
rlm@1
|
3093 Object *next = o->next;
|
rlm@1
|
3094 free(o);
|
rlm@1
|
3095 o = next;
|
rlm@1
|
3096 }
|
rlm@1
|
3097 free(t->function);
|
rlm@1
|
3098 }
|
rlm@1
|
3099 break;
|
rlm@1
|
3100 case TYPE_array:
|
rlm@1
|
3101 if (t->array)
|
rlm@1
|
3102 {
|
rlm@1
|
3103 free(t->array->bounds);
|
rlm@1
|
3104 free(t->array);
|
rlm@1
|
3105 }
|
rlm@1
|
3106 break;
|
rlm@1
|
3107 case TYPE_struct:
|
rlm@1
|
3108 case TYPE_union:
|
rlm@1
|
3109 if (t->structure)
|
rlm@1
|
3110 {
|
rlm@1
|
3111 for (int i = 0; i < t->structure->memberCount; i++)
|
rlm@1
|
3112 {
|
rlm@1
|
3113 free(t->structure->members[i].location);
|
rlm@1
|
3114 }
|
rlm@1
|
3115 free(t->structure->members);
|
rlm@1
|
3116 free(t->structure);
|
rlm@1
|
3117 }
|
rlm@1
|
3118 break;
|
rlm@1
|
3119 case TYPE_enum:
|
rlm@1
|
3120 if (t->enumeration)
|
rlm@1
|
3121 {
|
rlm@1
|
3122 free(t->enumeration->members);
|
rlm@1
|
3123 free(t->enumeration);
|
rlm@1
|
3124 }
|
rlm@1
|
3125 break;
|
rlm@1
|
3126 case TYPE_base:
|
rlm@1
|
3127 case TYPE_pointer:
|
rlm@1
|
3128 case TYPE_void:
|
rlm@1
|
3129 case TYPE_reference:
|
rlm@1
|
3130 break; // nothing to do
|
rlm@1
|
3131 }
|
rlm@1
|
3132 }
|
rlm@1
|
3133
|
rlm@1
|
3134 void elfCleanUp(CompileUnit *comp)
|
rlm@1
|
3135 {
|
rlm@1
|
3136 elfCleanUp(comp->abbrevs);
|
rlm@1
|
3137 free(comp->abbrevs);
|
rlm@1
|
3138 Function *func = comp->functions;
|
rlm@1
|
3139 while (func)
|
rlm@1
|
3140 {
|
rlm@1
|
3141 elfCleanUp(func);
|
rlm@1
|
3142 Function *next = func->next;
|
rlm@1
|
3143 free(func);
|
rlm@1
|
3144 func = next;
|
rlm@1
|
3145 }
|
rlm@1
|
3146 Type *t = comp->types;
|
rlm@1
|
3147 while (t)
|
rlm@1
|
3148 {
|
rlm@1
|
3149 elfCleanUp(t);
|
rlm@1
|
3150 Type *next = t->next;
|
rlm@1
|
3151 free(t);
|
rlm@1
|
3152 t = next;
|
rlm@1
|
3153 }
|
rlm@1
|
3154 Object *o = comp->variables;
|
rlm@1
|
3155 while (o)
|
rlm@1
|
3156 {
|
rlm@1
|
3157 elfCleanUp(o);
|
rlm@1
|
3158 Object *next = o->next;
|
rlm@1
|
3159 free(o);
|
rlm@1
|
3160 o = next;
|
rlm@1
|
3161 }
|
rlm@1
|
3162 if (comp->lineInfoTable)
|
rlm@1
|
3163 {
|
rlm@1
|
3164 free(comp->lineInfoTable->lines);
|
rlm@1
|
3165 free(comp->lineInfoTable->files);
|
rlm@1
|
3166 free(comp->lineInfoTable);
|
rlm@1
|
3167 }
|
rlm@1
|
3168 }
|
rlm@1
|
3169
|
rlm@1
|
3170 void elfCleanUp()
|
rlm@1
|
3171 {
|
rlm@1
|
3172 CompileUnit *comp = elfCompileUnits;
|
rlm@1
|
3173
|
rlm@1
|
3174 while (comp)
|
rlm@1
|
3175 {
|
rlm@1
|
3176 elfCleanUp(comp);
|
rlm@1
|
3177 CompileUnit *next = comp->next;
|
rlm@1
|
3178 free(comp);
|
rlm@1
|
3179 comp = next;
|
rlm@1
|
3180 }
|
rlm@1
|
3181 elfCompileUnits = NULL;
|
rlm@1
|
3182 free(elfSymbols);
|
rlm@1
|
3183 elfSymbols = NULL;
|
rlm@1
|
3184 // free(elfSymbolsStrTab);
|
rlm@1
|
3185 elfSymbolsStrTab = NULL;
|
rlm@1
|
3186
|
rlm@1
|
3187 elfDebugStrings = NULL;
|
rlm@1
|
3188 if (elfDebugInfo)
|
rlm@1
|
3189 {
|
rlm@1
|
3190 int num = elfDebugInfo->numRanges;
|
rlm@1
|
3191 int i;
|
rlm@1
|
3192 for (i = 0; i < num; i++)
|
rlm@1
|
3193 {
|
rlm@1
|
3194 free(elfDebugInfo->ranges[i].ranges);
|
rlm@1
|
3195 }
|
rlm@1
|
3196 free(elfDebugInfo->ranges);
|
rlm@1
|
3197 free(elfDebugInfo);
|
rlm@1
|
3198 elfDebugInfo = NULL;
|
rlm@1
|
3199 }
|
rlm@1
|
3200
|
rlm@1
|
3201 if (elfFdes)
|
rlm@1
|
3202 {
|
rlm@1
|
3203 if (elfFdeCount)
|
rlm@1
|
3204 {
|
rlm@1
|
3205 for (int i = 0; i < elfFdeCount; i++)
|
rlm@1
|
3206 free(elfFdes[i]);
|
rlm@1
|
3207 }
|
rlm@1
|
3208 free(elfFdes);
|
rlm@1
|
3209
|
rlm@1
|
3210 elfFdes = NULL;
|
rlm@1
|
3211 elfFdeCount = 0;
|
rlm@1
|
3212 }
|
rlm@1
|
3213
|
rlm@1
|
3214 ELFcie *cie = elfCies;
|
rlm@1
|
3215 while (cie)
|
rlm@1
|
3216 {
|
rlm@1
|
3217 ELFcie *next = cie->next;
|
rlm@1
|
3218 free(cie);
|
rlm@1
|
3219 cie = next;
|
rlm@1
|
3220 }
|
rlm@1
|
3221 elfCies = NULL;
|
rlm@1
|
3222
|
rlm@1
|
3223 if (elfFileData)
|
rlm@1
|
3224 {
|
rlm@1
|
3225 free(elfFileData);
|
rlm@1
|
3226 elfFileData = NULL;
|
rlm@1
|
3227 }
|
rlm@1
|
3228 }
|
rlm@1
|
3229
|