]>
Commit | Line | Data |
---|---|---|
fd67aa11 | 1 | /* Copyright (C) 2021-2024 Free Software Foundation, Inc. |
bb368aad VM |
2 | Contributed by Oracle. |
3 | ||
4 | This file is part of GNU Binutils. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3, or (at your option) | |
9 | any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, 51 Franklin Street - Fifth Floor, Boston, | |
19 | MA 02110-1301, USA. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "util.h" | |
23 | #include "DbeSession.h" | |
24 | #include "Elf.h" | |
25 | #include "Stabs.h" | |
26 | #include "Dwarf.h" | |
27 | #include "DataObject.h" | |
28 | #include "Function.h" | |
29 | #include "LoadObject.h" | |
30 | #include "Module.h" | |
31 | #include "DefaultMap.h" | |
32 | ||
33 | static int | |
34 | datatypeCmp (const void *a, const void *b) | |
35 | { | |
36 | uint32_t o1 = ((datatype_t *) a)->datatype_id; | |
37 | uint32_t o2 = ((datatype_t *) b)->datatype_id; | |
38 | return o1 == o2 ? 0 : (o1 < o2 ? -1 : 1); | |
39 | } | |
40 | ||
41 | static int | |
42 | targetOffsetCmp (const void *a, const void *b) | |
43 | { | |
44 | uint32_t o1 = ((target_info_t *) a)->offset; | |
45 | uint32_t o2 = ((target_info_t *) b)->offset; | |
46 | return o1 == o2 ? 0 : (o1 < o2 ? -1 : 1); | |
47 | } | |
48 | ||
49 | ||
50 | ////////////////////////////////////////////////////////// | |
51 | // class Dwr_type | |
52 | class Dwr_type | |
53 | { | |
54 | public: | |
55 | ||
56 | Dwr_type (int64_t _cu_die_offset, int _tag) | |
57 | { | |
58 | cu_die_offset = _cu_die_offset; | |
59 | tag = _tag; | |
60 | name = NULL; | |
61 | dobj_name = NULL; | |
62 | dtype = NULL; | |
63 | extent = 0; | |
64 | parent = 0; | |
65 | child = 0; | |
66 | next = 0; | |
67 | ref_type = 0; | |
68 | size = 0; | |
69 | elems = 0; | |
70 | offset = -1; | |
71 | bit_size = 0; | |
72 | }; | |
73 | ||
74 | char *name, *dobj_name; | |
75 | int64_t cu_die_offset, ref_type, extent, parent, child, next; | |
76 | int64_t size, elems, offset; | |
77 | int tag, bit_size; | |
78 | ||
79 | DataObject *get_dobj (Dwarf_cnt *ctx); | |
80 | char *get_dobjname (Dwarf_cnt *ctx); | |
81 | char *dump (); | |
82 | ||
83 | private: | |
84 | datatype_t *dtype; | |
85 | datatype_t *get_datatype (Dwarf_cnt *ctx); | |
86 | void get_dobj_for_members (Dwarf_cnt *ctx); | |
87 | void set_dobjname (char *spec, char *nm); | |
88 | }; | |
89 | ||
90 | ||
91 | ////////////////////////////////////////////////////////// | |
92 | // class Dwarf_cnt | |
93 | Dwarf_cnt::Dwarf_cnt () | |
94 | { | |
95 | cu_offset = 0; | |
96 | parent = 0; | |
97 | module = NULL; | |
98 | name = NULL; | |
99 | func = NULL; | |
100 | fortranMAIN = NULL; | |
101 | dwr_types = NULL; | |
102 | inlinedSubr = NULL; | |
103 | level = 0; | |
104 | } | |
105 | ||
106 | Dwr_type * | |
107 | Dwarf_cnt::get_dwr_type (int64_t cu_die_offset) | |
108 | { | |
109 | Dwr_type *t = dwr_types->get (cu_die_offset); | |
110 | if (t == NULL) | |
111 | { | |
112 | Dprintf (DUMP_DWARFLIB, "DWARF_ERROR: %s:%d wrong cu_die_offset=%lld in Dwarf_cnt::get_dwr_type\n", | |
113 | get_basename (__FILE__), (int) __LINE__, | |
114 | (long long) cu_die_offset); | |
115 | t = put_dwr_type (cu_die_offset, 0); // DOBJ_UNSPECIFIED | |
116 | } | |
117 | return t; | |
118 | } | |
119 | ||
120 | Dwr_type * | |
121 | Dwarf_cnt::put_dwr_type (int64_t cu_die_offset, int tag) | |
122 | { | |
123 | Dwr_type *t = new Dwr_type (cu_die_offset, tag); | |
124 | dwr_types->put (cu_die_offset, t); | |
125 | return t; | |
126 | } | |
127 | ||
128 | Dwr_type * | |
129 | Dwarf_cnt::put_dwr_type (Dwr_Tag *dwrTag) | |
130 | { | |
131 | Dwr_type *t = new Dwr_type (dwrTag->die, dwrTag->tag); | |
132 | dwr_types->put (dwrTag->die, t); | |
133 | return t; | |
134 | } | |
135 | ||
136 | ////////////////////////////////////////////////////////// | |
137 | // class Dwr_type | |
138 | char * | |
139 | Dwr_type::dump () | |
140 | { | |
141 | char *s = dbe_sprintf ("%lld %-15s name='%s' parent=%lld next=%lld child=%lld dtype=%llx", | |
142 | (long long) cu_die_offset, DwrCU::tag2str (tag), | |
143 | STR (name), (long long) parent, (long long) next, | |
144 | (long long) child, (long long) dtype); | |
145 | return s; | |
146 | } | |
147 | ||
148 | void | |
149 | Dwr_type::set_dobjname (char *spec, char *nm) | |
150 | { | |
151 | if (spec) | |
152 | { | |
153 | if (nm) | |
154 | dobj_name = dbe_sprintf ("%s%s", spec, nm); | |
155 | else | |
156 | dobj_name = dbe_sprintf ("%s<ANON=%lld>", spec, | |
157 | (long long) cu_die_offset); | |
158 | } | |
159 | else | |
160 | { | |
161 | if (nm) | |
162 | dobj_name = dbe_sprintf ("%s", nm); | |
163 | else | |
164 | dobj_name = dbe_sprintf ("<ANON=%lld>", (long long) cu_die_offset); | |
165 | } | |
166 | } | |
167 | ||
168 | char * | |
169 | Dwr_type::get_dobjname (Dwarf_cnt *ctx) | |
170 | { | |
171 | if (dobj_name) | |
172 | return dobj_name; | |
173 | switch (tag) | |
174 | { | |
175 | case DW_TAG_base_type: | |
176 | set_dobjname (NULL, name); | |
177 | for (int i = 0, len = (int) strlen (dobj_name); i < len; i++) | |
178 | { | |
179 | if (dobj_name[i] == ' ') | |
180 | dobj_name[i] = '_'; | |
181 | } | |
182 | break; | |
183 | case DW_TAG_constant: | |
184 | case DW_TAG_formal_parameter: | |
185 | case DW_TAG_variable: | |
186 | { | |
187 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
188 | set_dobjname (NULL, t->get_dobjname (ctx)); | |
189 | break; | |
190 | } | |
191 | case DW_TAG_unspecified_type: | |
192 | set_dobjname (NTXT ("unspecified:"), name); | |
193 | break; | |
194 | case DW_TAG_enumeration_type: | |
195 | set_dobjname (NTXT ("enumeration:"), name); | |
196 | break; | |
197 | case DW_TAG_typedef: | |
198 | { | |
199 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
200 | dobj_name = dbe_sprintf ("%s=%s", name, t->get_dobjname (ctx)); | |
201 | break; | |
202 | } | |
203 | case DW_TAG_const_type: | |
204 | set_dobjname (NTXT ("const+"), name); | |
205 | break; | |
206 | case DW_TAG_volatile_type: | |
207 | set_dobjname (NTXT ("volatile+"), name); | |
208 | break; | |
209 | case DW_TAG_pointer_type: | |
210 | { | |
211 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
212 | set_dobjname (NTXT ("pointer+"), t->get_dobjname (ctx)); | |
213 | break; | |
214 | } | |
215 | case DW_TAG_reference_type: | |
216 | { | |
217 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
218 | set_dobjname (NTXT ("reference+"), t->get_dobjname (ctx)); | |
219 | break; | |
220 | } | |
221 | case DW_TAG_array_type: | |
222 | { | |
223 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
224 | if (elems > 0) | |
225 | dobj_name = dbe_sprintf ("array[%lld]:%s", | |
226 | (long long) elems, t->get_dobjname (ctx)); | |
227 | else | |
228 | dobj_name = dbe_sprintf ("array[]:%s", t->get_dobjname (ctx)); | |
229 | break; | |
230 | } | |
231 | case DW_TAG_structure_type: | |
232 | set_dobjname (NTXT ("structure:"), name); | |
233 | break; | |
234 | case DW_TAG_union_type: | |
235 | set_dobjname (NTXT ("union:"), name); | |
236 | break; | |
237 | case DW_TAG_class_type: | |
238 | set_dobjname (NTXT ("class:"), name); | |
239 | break; | |
240 | case DW_TAG_member: | |
241 | { | |
242 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
243 | if (bit_size > 0) | |
244 | dobj_name = dbe_sprintf (NTXT ("%s:%lld"), t->get_dobjname (ctx), | |
245 | (long long) bit_size); | |
246 | else | |
247 | dobj_name = dbe_sprintf (NTXT ("%s"), t->get_dobjname (ctx)); | |
248 | break; | |
249 | } | |
250 | default: | |
251 | Dprintf (DUMP_DWARFLIB, NTXT ("DWARF_ERROR: %s:%d No case for %s cu_die_offset=%lld\n"), | |
252 | get_basename (__FILE__), (int) __LINE__, | |
253 | DwrCU::tag2str (tag), (long long) cu_die_offset); | |
254 | set_dobjname (NTXT ("Undefined:"), NULL); | |
255 | break; | |
256 | } | |
257 | return dobj_name; | |
258 | } | |
259 | ||
260 | datatype_t* | |
261 | Dwr_type::get_datatype (Dwarf_cnt *ctx) | |
262 | { | |
263 | if (dtype) | |
264 | return dtype; | |
265 | dtype = new datatype_t; | |
266 | dtype->datatype_id = (unsigned) cu_die_offset; | |
267 | dtype->memop_refs = 0; | |
268 | dtype->event_data = 0; | |
269 | dtype->dobj = NULL; | |
270 | ctx->module->datatypes->incorporate (dtype, datatypeCmp); | |
271 | return dtype; | |
272 | } | |
273 | ||
274 | DataObject * | |
275 | Dwr_type::get_dobj (Dwarf_cnt *ctx) | |
276 | { | |
277 | if (dtype == NULL) | |
278 | dtype = get_datatype (ctx); | |
279 | dtype->memop_refs++; | |
280 | DataObject *dobj = dtype->dobj; | |
281 | if (dobj) | |
282 | return dobj; | |
283 | ||
284 | if (tag == 0) | |
285 | dobj = dbeSession->find_dobj_by_name (PTXT (DOBJ_UNSPECIFIED)); | |
286 | else | |
287 | { | |
288 | dobj = dbeSession->createDataObject (); | |
289 | dobj->size = size; | |
290 | dobj->offset = offset; | |
291 | dobj->scope = ctx->func ? (Histable*) ctx->func : (Histable*) ctx->module; | |
292 | } | |
293 | dtype->dobj = dobj; | |
294 | if (parent) | |
295 | { | |
296 | Dwr_type *t = ctx->get_dwr_type (parent); | |
297 | dobj->parent = t->get_dobj (ctx); | |
298 | } | |
299 | ||
300 | if (ref_type) | |
301 | { | |
302 | Dwr_type *t = ctx->get_dwr_type (ref_type); | |
303 | t->get_dobj (ctx); | |
304 | if (size == 0) | |
305 | { | |
306 | size = t->size; | |
307 | dobj->size = size; | |
308 | } | |
309 | } | |
310 | ||
311 | switch (tag) | |
312 | { | |
313 | case 0: | |
314 | break; | |
315 | case DW_TAG_array_type: | |
316 | case DW_TAG_base_type: | |
317 | case DW_TAG_unspecified_type: | |
318 | case DW_TAG_enumeration_type: | |
319 | case DW_TAG_typedef: | |
320 | case DW_TAG_const_type: | |
321 | case DW_TAG_volatile_type: | |
322 | case DW_TAG_pointer_type: | |
323 | case DW_TAG_reference_type: | |
324 | dobj->set_dobjname (get_dobjname (ctx), NULL); | |
325 | break; | |
326 | case DW_TAG_structure_type: | |
327 | case DW_TAG_union_type: | |
328 | case DW_TAG_class_type: | |
329 | dobj->set_dobjname (get_dobjname (ctx), NULL); | |
330 | dobj->master = dbeSession->find_dobj_by_name (dobj_name); | |
331 | get_dobj_for_members (ctx); | |
332 | break; | |
333 | case DW_TAG_constant: | |
334 | case DW_TAG_formal_parameter: | |
335 | case DW_TAG_member: | |
336 | case DW_TAG_variable: | |
337 | if (dobj->parent == NULL) | |
338 | dobj->parent = dbeSession->get_Scalars_DataObject (); | |
339 | dobj->set_dobjname (get_dobjname (ctx), name); | |
340 | break; | |
341 | default: | |
342 | Dprintf (DUMP_DWARFLIB, NTXT ("DWARF_ERROR: %s:%d No case for %s cu_die_offset=%lld\n"), | |
343 | get_basename (__FILE__), (int) __LINE__, | |
344 | DwrCU::tag2str (tag), (long long) cu_die_offset); | |
345 | break; | |
346 | } | |
347 | return dobj; | |
348 | } | |
349 | ||
350 | void | |
351 | Dwr_type::get_dobj_for_members (Dwarf_cnt *ctx) | |
352 | { | |
353 | for (int64_t i = child; i != 0;) | |
354 | { | |
355 | Dwr_type *t = ctx->get_dwr_type (i); | |
356 | t->get_dobj (ctx); | |
357 | i = t->next; | |
358 | } | |
359 | } | |
360 | ||
361 | ////////////////////////////////////////////////////////// | |
362 | // class Dwarf | |
363 | Dwarf::Dwarf (Stabs *_stabs) | |
364 | { | |
365 | stabs = _stabs; | |
366 | status = Stabs::DBGD_ERR_NONE; | |
367 | dwrCUs = 0; | |
368 | debug_infoSec = NULL; | |
369 | debug_abbrevSec = NULL; | |
370 | debug_strSec = NULL; | |
371 | debug_lineSec = NULL; | |
74f1d7f4 | 372 | debug_line_strSec = NULL; |
bb368aad VM |
373 | debug_rangesSec = NULL; |
374 | elf = stabs->openElf (true); | |
375 | if (elf == NULL) | |
376 | { | |
377 | status = Stabs::DBGD_ERR_BAD_ELF_FORMAT; | |
378 | return; | |
379 | } | |
380 | debug_infoSec = dwrGetSec (NTXT (".debug_info")); | |
381 | if (debug_infoSec) | |
382 | { | |
383 | debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rela.debug_info"), NULL); | |
384 | debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rel.debug_info"), debug_infoSec->reloc); | |
385 | if (debug_infoSec->reloc) | |
386 | debug_infoSec->reloc->dump (); | |
387 | } | |
388 | debug_abbrevSec = dwrGetSec (NTXT (".debug_abbrev")); | |
389 | debug_strSec = dwrGetSec (NTXT (".debug_str")); | |
390 | debug_lineSec = dwrGetSec (NTXT (".debug_line")); | |
391 | debug_rangesSec = dwrGetSec (NTXT (".debug_ranges")); | |
74f1d7f4 | 392 | debug_line_strSec = dwrGetSec (".debug_line_str"); |
bb368aad VM |
393 | |
394 | if ((debug_infoSec == NULL) || (debug_abbrevSec == NULL) || (debug_lineSec == NULL)) | |
395 | { | |
396 | status = Stabs::DBGD_ERR_NO_DWARF; | |
397 | return; | |
398 | } | |
399 | } | |
400 | ||
401 | Dwarf::~Dwarf () | |
402 | { | |
403 | delete debug_infoSec; | |
404 | delete debug_abbrevSec; | |
405 | delete debug_strSec; | |
406 | delete debug_lineSec; | |
407 | delete debug_rangesSec; | |
408 | Destroy (dwrCUs); | |
409 | } | |
410 | ||
411 | DwrSec * | |
412 | Dwarf::dwrGetSec (const char *sec_name) | |
413 | { | |
414 | int secN = elf->elf_get_sec_num (sec_name); | |
415 | if (secN > 0) | |
416 | { | |
417 | Elf_Data *elfData = elf->elf_getdata (secN); | |
418 | if (elfData) | |
419 | return new DwrSec ((unsigned char *) elfData->d_buf, elfData->d_size, | |
420 | elf->need_swap_endian, | |
421 | elf->elf_getclass () == ELFCLASS32); | |
422 | } | |
423 | return NULL; | |
424 | } | |
425 | ||
426 | uint64_t | |
427 | DwrCU::get_low_pc () | |
428 | { | |
429 | uint64_t pc = Dwarf_addr (DW_AT_low_pc); | |
430 | if (pc) | |
431 | return pc; | |
432 | return pc; | |
433 | } | |
434 | ||
435 | char * | |
436 | DwrCU::get_linkage_name () | |
437 | { | |
438 | char *nm = Dwarf_string (DW_AT_linkage_name); | |
439 | if (nm != NULL) | |
440 | return nm; | |
441 | nm = Dwarf_string (DW_AT_SUN_link_name); | |
442 | if (nm != NULL) | |
443 | return nm; | |
444 | return Dwarf_string (DW_AT_MIPS_linkage_name); | |
445 | } | |
446 | ||
447 | void | |
448 | DwrCU::parseChild (Dwarf_cnt *ctx) | |
449 | { | |
450 | if (!dwrTag.hasChild) | |
451 | return; | |
452 | uint64_t old_size = debug_infoSec->size; | |
453 | uint64_t next_die_offset = 0; | |
454 | Dwarf_Die next_die; | |
455 | if (read_ref_attr (DW_AT_sibling, &next_die) == DW_DLV_OK) | |
456 | { | |
457 | next_die_offset = next_die + cu_offset; | |
458 | if (next_die_offset <= debug_infoSec->offset) | |
459 | { | |
460 | Dprintf (DEBUG_ERR_MSG, NTXT ("DwrCU::parseChild: next_die(0x%llx) <= debug_infoSec->offset(%llx)\n"), | |
461 | (long long) next_die, (long long) debug_infoSec->offset); | |
462 | next_die_offset = 0; | |
463 | } | |
464 | else if (debug_infoSec->size > next_die_offset) | |
465 | debug_infoSec->size = next_die_offset; | |
466 | } | |
467 | dwrTag.level++; | |
468 | ctx->level++; | |
469 | for (;;) | |
470 | { | |
471 | if (set_die (0) != DW_DLV_OK) | |
472 | break; | |
473 | Function *func; | |
474 | char *old_name; | |
475 | int hasChild = dwrTag.hasChild; | |
476 | switch (dwrTag.tag) | |
477 | { | |
478 | case DW_TAG_imported_declaration: | |
479 | if (Stabs::is_fortran (ctx->module->lang_code)) | |
480 | { | |
481 | char *link_name = Dwarf_string (DW_AT_name); | |
482 | ctx->fortranMAIN = NULL; | |
483 | parseChild (ctx); | |
484 | hasChild = 0; | |
485 | if (ctx->fortranMAIN) | |
486 | { | |
487 | ctx->fortranMAIN->set_match_name (link_name); | |
488 | ctx->fortranMAIN = NULL; | |
489 | } | |
490 | } | |
491 | break; | |
492 | case DW_TAG_subprogram: | |
493 | if (dwrTag.get_attr (DW_AT_abstract_origin)) | |
494 | break; | |
495 | if (dwrTag.get_attr (DW_AT_declaration)) | |
496 | { | |
497 | // Only declaration | |
498 | if (Stabs::is_fortran (ctx->module->lang_code)) | |
499 | { | |
500 | char *link_name = Dwarf_string (DW_AT_name); | |
501 | if (link_name && streq (link_name, NTXT ("MAIN"))) | |
502 | ctx->fortranMAIN = Stabs::find_func (NTXT ("MAIN"), ctx->module->functions, true, true); | |
503 | } | |
490ea364 | 504 | break; |
bb368aad VM |
505 | } |
506 | func = append_Function (ctx); | |
507 | if (func) | |
508 | { | |
509 | if (Stabs::is_fortran (ctx->module->lang_code) && | |
510 | streq (func->get_match_name (), NTXT ("MAIN"))) | |
511 | ctx->fortranMAIN = func; | |
512 | old_name = ctx->name; | |
513 | Function *old_func = ctx->func; | |
514 | ctx->name = func->get_match_name (); | |
515 | ctx->func = func; | |
516 | parseChild (ctx); | |
517 | hasChild = 0; | |
518 | ctx->name = old_name; | |
519 | ctx->func = old_func; | |
520 | } | |
521 | break; | |
522 | case DW_TAG_module: | |
523 | old_name = ctx->name; | |
524 | ctx->name = Dwarf_string (DW_AT_SUN_link_name); | |
525 | parseChild (ctx); | |
526 | hasChild = 0; | |
527 | ctx->name = old_name; | |
528 | break; | |
529 | case DW_TAG_class_type: | |
530 | old_name = ctx->name; | |
531 | ctx->name = Dwarf_string (DW_AT_name); | |
532 | parseChild (ctx); | |
533 | hasChild = 0; | |
534 | ctx->name = old_name; | |
535 | break; | |
536 | case DW_TAG_structure_type: | |
537 | old_name = ctx->name; | |
538 | ctx->name = NULL; | |
539 | parseChild (ctx); | |
540 | hasChild = 0; | |
541 | ctx->name = old_name; | |
542 | break; | |
543 | case DW_TAG_namespace: | |
544 | old_name = ctx->name; | |
545 | ctx->name = Dwarf_string (DW_AT_name); | |
546 | parseChild (ctx); | |
547 | hasChild = 0; | |
548 | ctx->name = old_name; | |
549 | break; | |
550 | case DW_TAG_lexical_block: | |
551 | old_name = ctx->name; | |
552 | ctx->name = NULL; | |
553 | parseChild (ctx); | |
554 | hasChild = 0; | |
555 | ctx->name = old_name; | |
556 | break; | |
557 | case DW_TAG_SUN_memop_info: | |
558 | isMemop = true; | |
559 | break; | |
560 | case DW_TAG_inlined_subroutine: | |
561 | if (ctx->module) | |
562 | { | |
563 | parse_inlined_subroutine (ctx); | |
564 | hasChild = 0; | |
565 | } | |
566 | break; | |
567 | default: // No more special cases | |
568 | break; | |
569 | } | |
570 | if (hasChild) | |
571 | parseChild (ctx); | |
572 | } | |
573 | ctx->level--; | |
574 | dwrTag.level--; | |
575 | if (next_die_offset != 0) | |
576 | debug_infoSec->offset = next_die_offset; | |
577 | debug_infoSec->size = old_size; | |
578 | } | |
579 | ||
580 | bool | |
581 | Dwarf::archive_Dwarf (LoadObject *lo) | |
582 | { | |
583 | if (debug_infoSec == NULL) | |
584 | return false; | |
585 | if (dwrCUs) | |
586 | return true; | |
587 | dwrCUs = new Vector<DwrCU *>; | |
588 | ||
589 | debug_infoSec->offset = 0; | |
590 | while (debug_infoSec->offset < debug_infoSec->sizeSec) | |
591 | { | |
592 | DwrCU *dwrCU = new DwrCU (this); | |
593 | dwrCUs->append (dwrCU); | |
594 | debug_infoSec->size = debug_infoSec->sizeSec; | |
595 | debug_infoSec->offset = dwrCU->next_cu_offset; | |
596 | ||
597 | if (dwrCU->set_die (dwrCU->cu_header_offset) != DW_DLV_OK) | |
598 | { | |
599 | Dprintf (1, "DwrCU::archive_Dwarf: CU=%lld (offset=0x%llx); set_die(0x%llx) failed\n", | |
600 | (long long) dwrCUs->size (), (long long) dwrCU->cu_offset, | |
601 | (long long) dwrCU->cu_header_offset); | |
602 | continue; | |
603 | } | |
604 | ||
605 | Module *mod = dwrCU->parse_cu_header (lo); | |
606 | if (mod) | |
607 | { | |
608 | mod->hdrOffset = dwrCUs->size (); | |
609 | DwrLineRegs *lineReg = dwrCU->get_dwrLineReg (); | |
e02841b0 | 610 | if (lineReg != NULL) |
bb368aad | 611 | { |
e02841b0 VM |
612 | dwrCU->srcFiles = new Vector<SourceFile *> (VecSize (lineReg->file_names)); |
613 | for (long i = 0, sz = VecSize (lineReg->file_names); i < sz; i++) | |
614 | { | |
74f1d7f4 VM |
615 | char *fname = lineReg->getPath (i); |
616 | if (fname) | |
617 | dwrCU->srcFiles->append (mod->findSource (fname, true)); | |
e02841b0 | 618 | } |
bb368aad VM |
619 | } |
620 | ||
621 | Dwarf_cnt ctx; | |
622 | ctx.module = mod; | |
623 | dwrCU->parseChild (&ctx); | |
624 | if (dwrCU->dwrInlinedSubrs && DUMP_DWARFLIB) | |
625 | { | |
626 | char msg[128]; | |
627 | char *lo_name = mod->loadobject ? mod->loadobject->get_name () | |
628 | : NULL; | |
629 | snprintf (msg, sizeof (msg), NTXT ("\ndwrCUs[%lld]: %s:%s\n"), | |
630 | (long long) dwrCUs->size (), | |
631 | STR (lo_name), STR (mod->get_name ())); | |
632 | dwrCU->dwrInlinedSubrs->dump (msg); | |
633 | } | |
634 | } | |
635 | } | |
636 | return true; | |
637 | } | |
638 | ||
639 | void | |
640 | Dwarf::srcline_Dwarf (Module *module) | |
641 | { | |
642 | if (module == NULL || module->hdrOffset == 0) | |
643 | return; | |
644 | DwrCU *dwrCU = dwrCUs->get (module->hdrOffset - 1); | |
645 | dwrCU->map_dwarf_lines (module); | |
646 | } | |
647 | ||
648 | ||
649 | // parse hwcprof info for given module in loadobject | |
650 | ||
651 | void | |
652 | Dwarf::read_hwcprof_info (Module *module) | |
653 | { | |
654 | if (module->datatypes || (module->hdrOffset == 0)) | |
655 | return; | |
656 | DwrCU *dwrCU = dwrCUs->get (module->hdrOffset - 1); | |
657 | if (!dwrCU->isMemop) | |
658 | return; | |
659 | module->datatypes = new Vector<datatype_t*>; | |
660 | if (dwrCU->set_die (dwrCU->cu_header_offset) != DW_DLV_OK) | |
661 | { | |
662 | Dprintf (1, "Dwarf::read_hwcprof_info: CU=%lld (offset=0x%llx); set_die(0x%llx) failed\n", | |
663 | (long long) module->hdrOffset, (long long) dwrCU->cu_offset, | |
664 | (long long) dwrCU->cu_header_offset); | |
665 | return; | |
666 | } | |
667 | Dwarf_cnt ctx; | |
668 | ctx.module = module; | |
669 | ctx.cu_offset = dwrCU->cu_offset; // CU header offset; | |
670 | ctx.dwr_types = new DefaultMap<int64_t, Dwr_type*>; | |
671 | ctx.put_dwr_type (0, 0); // for DOBJ_UNSPECIFIED | |
672 | dwrCU->read_hwcprof_info (&ctx); | |
673 | ||
674 | Vector<inst_info_t*> *infoList = module->infoList; | |
675 | Dprintf (DUMP_DWARFLIB, | |
676 | "\n\n ### Dwarf::read_hwcprof_info: module: '%s' infoList->size()=%lld\n", | |
677 | STR (module->get_name ()), | |
678 | (long long) (infoList ? infoList->size () : -1)); | |
679 | for (int i = 0, sz = infoList ? infoList->size () : -1; i < sz; i++) | |
680 | { | |
681 | inst_info_t *ip = infoList->fetch (i); | |
682 | memop_info_t *mp = ip->memop; | |
683 | Dwr_type *t = ctx.get_dwr_type (mp->datatype_id); | |
684 | t->get_dobj (&ctx); | |
685 | } | |
686 | ||
687 | #ifdef DEBUG | |
688 | Dprintf (DUMP_DWARFLIB, | |
689 | "\n\n ### Dwarf::read_hwcprof_info: '%s' infoList->size()=%lld\n", | |
690 | STR (module->get_name ()), | |
691 | (long long) (infoList ? infoList->size () : 1)); | |
692 | for (int i = 0, sz = infoList ? infoList->size () : -1; i < sz; i++) | |
693 | { | |
694 | inst_info_t *ip = infoList->fetch (i); | |
695 | memop_info_t *mp = ip->memop; | |
696 | Dprintf (DUMP_DWARFLIB, | |
697 | " %d id=%lld offset=%lld signature=%lld datatype_id=%lld \n", | |
698 | i, (long long) mp->id, (long long) mp->offset, | |
699 | (long long) mp->signature, (long long) mp->datatype_id); | |
700 | } | |
701 | ||
702 | Vector<int64_t> *keys = ctx.dwr_types->keySet (); | |
703 | Dprintf (DUMP_DWARFLIB, | |
704 | "\n\n ### Dwarf::read_hwcprof_info: '%s' keys->size()=%lld\n", | |
705 | STR (module->get_name ()), (long long) (keys ? keys->size () : -1)); | |
706 | for (int i = 0, sz = keys->size (); i < sz; i++) | |
707 | { | |
708 | int64_t ind = keys->fetch (i); | |
709 | Dwr_type *t = ctx.get_dwr_type (ind); | |
710 | Dprintf (DUMP_DWARFLIB, NTXT (" %d %lld %s\n"), i, | |
711 | (long long) ind, t->dump ()); | |
712 | } | |
713 | #endif | |
714 | } | |
715 | ||
716 | void | |
717 | DwrCU::read_hwcprof_info (Dwarf_cnt *ctx) | |
718 | { | |
719 | if (!dwrTag.hasChild) | |
720 | return; | |
721 | uint64_t old_size = debug_infoSec->size; | |
722 | uint64_t next_die_offset = 0; | |
723 | Dwarf_Die next_die; | |
724 | if (read_ref_attr (DW_AT_sibling, &next_die) == DW_DLV_OK) | |
725 | { | |
726 | next_die_offset = next_die + cu_offset; | |
727 | if (next_die_offset <= debug_infoSec->offset) | |
728 | next_die_offset = 0; | |
729 | else if (debug_infoSec->size > next_die_offset) | |
730 | debug_infoSec->size = next_die_offset; | |
731 | } | |
732 | dwrTag.level++; | |
733 | ctx->level++; | |
734 | for (;;) | |
735 | { | |
736 | if (set_die (0) != DW_DLV_OK) | |
737 | break; | |
738 | Dprintf (DUMP_DWARFLIB, NTXT ("%s:%d <%lld:%lld> cu_die=%lld %-15s\n"), | |
739 | get_basename (__FILE__), (int) __LINE__, (long long) ctx->level, | |
740 | (long long) dwrTag.die, (long long) dwrTag.offset, | |
741 | DwrCU::tag2str (dwrTag.tag)); | |
742 | switch (dwrTag.tag) | |
743 | { | |
744 | case DW_TAG_SUN_memop_info: | |
745 | { | |
746 | if (ctx->func == NULL) | |
747 | break; | |
748 | Dwarf_Unsigned mid = Dwarf_data (DW_AT_SUN_profile_id); | |
749 | Dwarf_Unsigned off = Dwarf_data (DW_AT_SUN_func_offset); | |
750 | Dwarf_Unsigned sig = Dwarf_data (DW_AT_SUN_memop_signature); | |
751 | Dwarf_Off ref = Dwarf_ref (DW_AT_SUN_memop_type_ref); | |
752 | ||
753 | // define memop entry | |
754 | memop_info_t *memop = new memop_info_t; | |
755 | memop->id = (unsigned) mid; | |
756 | memop->signature = (unsigned) sig; | |
757 | memop->datatype_id = ref ? (unsigned) ref : 0; | |
758 | memop->offset = (unsigned) (ctx->func->img_offset + off); | |
759 | ||
760 | // define instop entry | |
761 | inst_info_t *instop = new inst_info_t; | |
762 | instop->type = CPF_INSTR_TYPE_PREFETCH; // XXXX UNKNOWN | |
763 | instop->offset = memop->offset; | |
764 | instop->memop = memop; | |
765 | if (ctx->module->infoList == NULL) | |
766 | ctx->module->infoList = new Vector<inst_info_t*>; | |
767 | ctx->module->infoList->append (instop); | |
768 | break; | |
769 | } | |
770 | case DW_TAG_SUN_codeflags: | |
771 | { | |
772 | if (ctx->func == NULL) | |
773 | break; | |
774 | Dwarf_Unsigned kind = Dwarf_data (DW_AT_SUN_cf_kind); | |
775 | if (kind == DW_ATCF_SUN_branch_target) | |
776 | { | |
777 | DwrSec *secp = Dwarf_block (DW_AT_SUN_func_offsets); | |
778 | if (secp) | |
779 | { | |
780 | int foffset = 0; | |
781 | for (int i = 0; secp->offset < secp->size; i++) | |
782 | { | |
783 | int val = (int) secp->GetSLEB128 (); | |
784 | if (i == 0 || val != 0) | |
785 | { | |
786 | foffset += val; | |
787 | target_info_t *t = new target_info_t; | |
788 | t->offset = (unsigned) (ctx->func->img_offset + foffset); | |
789 | ctx->module->bTargets.incorporate (t, targetOffsetCmp); | |
790 | } | |
791 | } | |
792 | delete(secp); | |
793 | } | |
794 | } | |
795 | break; | |
796 | } | |
797 | case DW_TAG_subprogram: | |
798 | { | |
799 | Function *old_func = ctx->func; | |
800 | if (dwrTag.get_attr (DW_AT_abstract_origin) | |
801 | || dwrTag.get_attr (DW_AT_declaration)) | |
802 | ctx->func = NULL; | |
803 | else | |
804 | ctx->func = append_Function (ctx); | |
805 | read_hwcprof_info (ctx); | |
806 | ctx->func = old_func; | |
807 | break; | |
808 | } | |
809 | case DW_TAG_base_type: | |
810 | { | |
811 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
812 | t->name = Dwarf_string (DW_AT_name); | |
813 | t->size = Dwarf_data (DW_AT_byte_size); | |
814 | break; | |
815 | } | |
816 | case DW_TAG_unspecified_type: | |
817 | ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
818 | break; | |
819 | case DW_TAG_enumeration_type: | |
820 | { | |
821 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
822 | t->name = Dwarf_string (DW_AT_name); | |
823 | t->size = Dwarf_data (DW_AT_byte_size); | |
824 | break; | |
825 | } | |
826 | case DW_TAG_constant: | |
827 | case DW_TAG_formal_parameter: | |
828 | case DW_TAG_variable: | |
829 | case DW_TAG_typedef: | |
830 | case DW_TAG_const_type: | |
831 | case DW_TAG_volatile_type: | |
832 | { | |
833 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
834 | t->name = Dwarf_string (DW_AT_name); | |
835 | t->ref_type = Dwarf_ref (DW_AT_type); | |
836 | break; | |
837 | } | |
838 | case DW_TAG_pointer_type: | |
839 | case DW_TAG_reference_type: | |
840 | { | |
841 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
842 | t->name = Dwarf_string (DW_AT_name); | |
843 | t->ref_type = Dwarf_ref (DW_AT_type); | |
844 | t->size = (dwarf->stabs->get_class () == W64) ? 8 : 4; | |
845 | break; | |
846 | } | |
847 | case DW_TAG_array_type: | |
848 | { | |
849 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
850 | t->name = Dwarf_string (DW_AT_name); | |
851 | t->ref_type = Dwarf_ref (DW_AT_type); | |
852 | t->size = Dwarf_data (DW_AT_byte_size); | |
853 | ctx->size = -1; | |
854 | read_hwcprof_info (ctx); | |
855 | t->elems = ctx->size; | |
856 | break; | |
857 | } | |
858 | case DW_TAG_subrange_type: | |
859 | { | |
860 | int64_t ref_type = Dwarf_ref (DW_AT_type); | |
861 | int64_t hi = Dwarf_data (DW_AT_upper_bound); | |
862 | int64_t lo = Dwarf_data (DW_AT_lower_bound); | |
863 | int64_t ss = Dwarf_data (DW_AT_stride_size); | |
864 | ctx->size = 1 + hi - lo; | |
865 | if (ss != 0) | |
866 | ctx->size /= ss; | |
867 | Dprintf (DUMP_DWARFLIB, | |
868 | "Got subrange [%lld:%lld:%lld] indexed <%lld>: size=%lld\n", | |
869 | (long long) lo, (long long) hi, (long long) ss, | |
870 | (long long) ref_type, (long long) ctx->size); | |
871 | break; | |
872 | } | |
873 | case DW_TAG_structure_type: | |
874 | case DW_TAG_union_type: | |
875 | case DW_TAG_class_type: | |
876 | { | |
877 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
878 | t->name = Dwarf_string (DW_AT_name); | |
879 | t->size = Dwarf_data (DW_AT_byte_size); | |
880 | t->extent = Dwarf_ref (DW_AT_sibling); | |
881 | int64_t old_parent = ctx->parent; | |
882 | ctx->parent = t->cu_die_offset; | |
883 | ||
884 | char *old_name = ctx->name; | |
885 | ctx->name = (dwrTag.tag == DW_TAG_class_type) ? Dwarf_string (DW_AT_name) : NULL; | |
886 | read_hwcprof_info (ctx); | |
887 | ctx->name = old_name; | |
888 | ctx->parent = old_parent; | |
889 | // Reverse children | |
890 | for (int64_t i = t->child, last = 0; i != 0;) | |
891 | { | |
892 | Dwr_type *t1 = ctx->get_dwr_type (i); | |
893 | t->child = i; | |
894 | i = t1->next; | |
895 | t1->next = last; | |
896 | last = t->child; | |
897 | } | |
898 | break; | |
899 | } | |
900 | case DW_TAG_member: | |
901 | { | |
902 | if (ctx->parent == 0) | |
903 | { | |
904 | Dprintf (DUMP_DWARFLIB, NTXT ("DWARF_ERROR: %s:%d %s cu_die_offset=%lld\n"), | |
905 | get_basename (__FILE__), (int) __LINE__, | |
906 | DwrCU::tag2str (dwrTag.tag), (long long) dwrTag.die); | |
907 | break; | |
908 | } | |
909 | Dwr_type *t = ctx->put_dwr_type (dwrTag.die, dwrTag.tag); | |
910 | t->name = Dwarf_string (DW_AT_name); | |
911 | t->ref_type = Dwarf_ref (DW_AT_type); | |
912 | t->offset = Dwarf_location (DW_AT_data_member_location); | |
913 | Dwr_type *parent = ctx->get_dwr_type (ctx->parent); | |
914 | t->parent = ctx->parent; | |
915 | t->next = parent->child; // a reverse order of members | |
916 | parent->child = t->cu_die_offset; | |
917 | t->bit_size = (uint32_t) Dwarf_data (DW_AT_bit_size); | |
918 | break; | |
919 | } | |
920 | case DW_TAG_module: | |
921 | { | |
922 | char *old_name = ctx->name; | |
923 | ctx->name = Dwarf_string (DW_AT_SUN_link_name); | |
924 | read_hwcprof_info (ctx); | |
925 | ctx->name = old_name; | |
926 | break; | |
927 | } | |
928 | case DW_TAG_namespace: | |
929 | { | |
930 | char *old_name = ctx->name; | |
931 | ctx->name = Dwarf_string (DW_AT_name); | |
932 | read_hwcprof_info (ctx); | |
933 | ctx->name = old_name; | |
934 | break; | |
935 | } | |
936 | case DW_TAG_lexical_block: | |
937 | { | |
938 | char *old_name = ctx->name; | |
939 | ctx->name = NULL; | |
940 | read_hwcprof_info (ctx); | |
941 | ctx->name = old_name; | |
942 | break; | |
943 | } | |
944 | default: // No more special cases | |
945 | read_hwcprof_info (ctx); | |
946 | break; | |
947 | } | |
948 | } | |
949 | ctx->level--; | |
950 | dwrTag.level--; | |
951 | if (next_die_offset != 0) | |
952 | debug_infoSec->offset = next_die_offset; | |
953 | debug_infoSec->size = old_size; | |
954 | } | |
955 | ||
956 | // Append function to module | |
957 | Function * | |
958 | DwrCU::append_Function (Dwarf_cnt *ctx) | |
959 | { | |
960 | char *outerName = ctx->name, *name, tmpname[2048]; | |
961 | Function *func; | |
962 | char *fname = Dwarf_string (DW_AT_name); | |
963 | if (fname && outerName && !strchr (fname, '.')) | |
964 | { | |
965 | size_t outerlen = strlen (outerName); | |
966 | if (outerlen > 0 && outerName[outerlen - 1] == '_') | |
967 | { | |
968 | outerlen--; | |
969 | snprintf (tmpname, sizeof (tmpname), NTXT ("%s"), outerName); | |
970 | snprintf (tmpname + outerlen, sizeof (tmpname) - outerlen, NTXT (".%s_"), fname); | |
971 | } | |
972 | else | |
973 | snprintf (tmpname, sizeof (tmpname), NTXT ("%s.%s"), outerName, fname); | |
974 | name = tmpname; | |
975 | Dprintf (DUMP_DWARFLIB, NTXT ("Generated innerfunc name %s\n"), name); | |
976 | } | |
977 | else | |
978 | name = fname; | |
979 | ||
980 | char *link_name = get_linkage_name (); | |
981 | if (link_name == NULL) | |
982 | link_name = name; | |
983 | ||
984 | uint64_t pc = get_low_pc (); | |
985 | func = dwarf->stabs->append_Function (module, link_name, pc); | |
986 | if (func != NULL) | |
987 | { | |
988 | int lineno = (int) Dwarf_data (DW_AT_decl_line); | |
989 | func->set_match_name (name); | |
990 | if (lineno > 0) | |
991 | { | |
992 | func->setLineFirst (lineno); | |
74f1d7f4 | 993 | int fileno = ((int) Dwarf_data (DW_AT_decl_file)); |
bb368aad VM |
994 | SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ? srcFiles->get (fileno) |
995 | : module->getMainSrc (); | |
996 | func->setDefSrc (sf); | |
997 | func->pushSrcFile (func->def_source, 0); | |
998 | func->popSrcFile (); | |
999 | } | |
1000 | } | |
1001 | return func; | |
1002 | } | |
1003 | ||
1004 | // Get language code | |
1005 | Sp_lang_code | |
1006 | DwrCU::Dwarf_lang () | |
1007 | { | |
1008 | char *str = Dwarf_string (DW_AT_producer); | |
1009 | if (str && strncmp (str, NTXT ("GNU"), 3) == 0) | |
1010 | isGNU = true; | |
1011 | int64_t lang = Dwarf_data (DW_AT_language); | |
1012 | switch (lang) | |
1013 | { | |
1014 | case DW_LANG_C89: | |
1015 | case DW_LANG_C: | |
1016 | return Sp_lang_c; // Sp_lang_ansic? | |
1017 | case DW_LANG_C99: | |
1018 | return Sp_lang_c99; | |
1019 | case DW_LANG_C_plus_plus: | |
1020 | return isGNU ? Sp_lang_gcc : Sp_lang_cplusplus; | |
1021 | case DW_LANG_Fortran90: | |
1022 | return Sp_lang_fortran90; | |
1023 | case DW_LANG_Fortran77: | |
1024 | return Sp_lang_fortran; | |
1025 | case DW_LANG_Java: | |
1026 | return Sp_lang_java; | |
1027 | case DW_LANG_Mips_Assembler: | |
1028 | case DW_LANG_SUN_Assembler: | |
1029 | return Sp_lang_asm; | |
1030 | case DW_LANG_Pascal83: | |
1031 | return Sp_lang_pascal; | |
1032 | default: | |
1033 | case DW_LANG_Ada83: | |
1034 | case DW_LANG_Cobol74: | |
1035 | case DW_LANG_Cobol85: | |
1036 | case DW_LANG_Modula2: | |
1037 | case DW_LANG_Ada95: | |
1038 | case DW_LANG_Fortran95: | |
1039 | case DW_LANG_lo_user: | |
1040 | return Sp_lang_unknown; | |
1041 | } | |
1042 | } |