xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/src/Dwarf.cc (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
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
datatypeCmp(const void * a,const void * b)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
targetOffsetCmp(const void * a,const void * b)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 
Dwr_type(int64_t _cu_die_offset,int _tag)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
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 *
get_dwr_type(int64_t cu_die_offset)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 *
put_dwr_type(int64_t cu_die_offset,int tag)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 *
put_dwr_type(Dwr_Tag * dwrTag)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 *
dump()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
set_dobjname(char * spec,char * nm)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 *
get_dobjname(Dwarf_cnt * ctx)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*
get_datatype(Dwarf_cnt * ctx)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 *
get_dobj(Dwarf_cnt * ctx)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
get_dobj_for_members(Dwarf_cnt * ctx)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
Dwarf(Stabs * _stabs)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;
372   debug_line_strSec = NULL;
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"));
392   debug_line_strSec = dwrGetSec (".debug_line_str");
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 
~Dwarf()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 *
dwrGetSec(const char * sec_name)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
get_low_pc()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 *
get_linkage_name()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
parseChild(Dwarf_cnt * ctx)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 		}
504 	      break;
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
archive_Dwarf(LoadObject * lo)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 ();
610 	  if (lineReg != NULL)
611 	    {
612 	      dwrCU->srcFiles = new Vector<SourceFile *> (VecSize (lineReg->file_names));
613 	      for (long i = 0, sz = VecSize (lineReg->file_names); i < sz; i++)
614 		{
615 		  char *fname = lineReg->getPath (i);
616 		  if (fname)
617 		    dwrCU->srcFiles->append (mod->findSource (fname, true));
618 		}
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
srcline_Dwarf(Module * module)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
read_hwcprof_info(Module * module)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
read_hwcprof_info(Dwarf_cnt * ctx)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 *
append_Function(Dwarf_cnt * ctx)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);
993 	  int fileno = ((int) Dwarf_data (DW_AT_decl_file));
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
Dwarf_lang()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 }
1043