aboutsummaryrefslogtreecommitdiff
path: root/gprofng/src/Dwarf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/Dwarf.cc')
-rw-r--r--gprofng/src/Dwarf.cc271
1 files changed, 212 insertions, 59 deletions
diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc
index a613c63..85891099 100644
--- a/gprofng/src/Dwarf.cc
+++ b/gprofng/src/Dwarf.cc
@@ -29,6 +29,7 @@
#include "LoadObject.h"
#include "Module.h"
#include "DefaultMap.h"
+#include "Symbol.h"
static int
datatypeCmp (const void *a, const void *b)
@@ -46,7 +47,6 @@ targetOffsetCmp (const void *a, const void *b)
return o1 == o2 ? 0 : (o1 < o2 ? -1 : 1);
}
-
//////////////////////////////////////////////////////////
// class Dwr_type
class Dwr_type
@@ -390,6 +390,7 @@ Dwarf::Dwarf (Stabs *_stabs)
debug_lineSec = dwrGetSec (NTXT (".debug_line"));
debug_rangesSec = dwrGetSec (NTXT (".debug_ranges"));
debug_line_strSec = dwrGetSec (".debug_line_str");
+ debug_rnglists = NULL;
if ((debug_infoSec == NULL) || (debug_abbrevSec == NULL) || (debug_lineSec == NULL))
{
@@ -441,7 +442,12 @@ DwrCU::get_linkage_name ()
nm = Dwarf_string (DW_AT_SUN_link_name);
if (nm != NULL)
return nm;
- return Dwarf_string (DW_AT_MIPS_linkage_name);
+ if (nm != NULL)
+ return nm;
+ nm = Dwarf_string (DW_AT_MIPS_linkage_name);
+ if (nm != NULL)
+ return nm;
+ return Dwarf_string (DW_AT_name);
}
void
@@ -454,7 +460,7 @@ DwrCU::parseChild (Dwarf_cnt *ctx)
Dwarf_Die next_die;
if (read_ref_attr (DW_AT_sibling, &next_die) == DW_DLV_OK)
{
- next_die_offset = next_die + cu_offset;
+ next_die_offset = next_die;
if (next_die_offset <= debug_infoSec->offset)
{
Dprintf (DEBUG_ERR_MSG, NTXT ("DwrCU::parseChild: next_die(0x%llx) <= debug_infoSec->offset(%llx)\n"),
@@ -490,8 +496,25 @@ DwrCU::parseChild (Dwarf_cnt *ctx)
}
break;
case DW_TAG_subprogram:
- if (dwrTag.get_attr (DW_AT_abstract_origin))
- break;
+ {
+ Symbol *sym = NULL;
+ Vector<Symbol *> *syms = NULL;
+ Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_abstract_origin);
+ if (dwrAttr)
+ {
+ // Set up functions from DW_AT_{ranges,low_pc,linkage_name}
+ set_up_funcs (dwrAttr->u.offset);
+ break;
+ }
+
+ dwrAttr = dwrTag.get_attr (DW_AT_specification);
+ if (dwrAttr)
+ {
+ // Set up functions from DW_AT_{ranges,low_pc,linkage_name}
+ set_up_funcs (dwrAttr->u.offset);
+ break;
+ }
+
if (dwrTag.get_attr (DW_AT_declaration))
{
// Only declaration
@@ -499,26 +522,39 @@ DwrCU::parseChild (Dwarf_cnt *ctx)
{
char *link_name = Dwarf_string (DW_AT_name);
if (link_name && streq (link_name, NTXT ("MAIN")))
- ctx->fortranMAIN = Stabs::find_func (NTXT ("MAIN"), ctx->module->functions, true, true);
+ ctx->fortranMAIN = Stabs::find_func (NTXT ("MAIN"),
+ ctx->module->functions, true, true);
}
+ sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym != NULL)
+ func = append_Function (sym, ctx->name);
break;
}
- func = append_Function (ctx);
- if (func)
+
+ func = NULL;
+ syms = get_symbols (tmp_syms);
+ for (int i = 0, sz = VecSize (syms); i < sz; i++)
{
+ sym = syms->get (i);
+ func = append_Function (sym, ctx->name);
if (Stabs::is_fortran (ctx->module->lang_code) &&
- streq (func->get_match_name (), NTXT ("MAIN")))
+ streq (func->get_match_name (), "MAIN"))
ctx->fortranMAIN = func;
- old_name = ctx->name;
- Function *old_func = ctx->func;
- ctx->name = func->get_match_name ();
- ctx->func = func;
- parseChild (ctx);
- hasChild = 0;
- ctx->name = old_name;
- ctx->func = old_func;
}
+ if (func == NULL)
+ break;
+
+ old_name = ctx->name;
+ Function *old_func = ctx->func;
+ ctx->name = func->get_match_name ();
+ ctx->func = func;
+ parseChild (ctx);
+ hasChild = 0;
+ ctx->name = old_name;
+ ctx->func = old_func;
break;
+ }
case DW_TAG_module:
old_name = ctx->name;
ctx->name = Dwarf_string (DW_AT_SUN_link_name);
@@ -631,6 +667,21 @@ Dwarf::archive_Dwarf (LoadObject *lo)
STR (lo_name), STR (mod->get_name ()));
dwrCU->dwrInlinedSubrs->dump (msg);
}
+ for (int i = 0, sz = VecSize (dwrCU->symbols); i < sz; i++)
+ {
+ Symbol *sp = dwrCU->symbols->get (i);
+ Function *f = sp->func;
+ if (f == NULL)
+ {
+ f = sp->createFunction (mod);
+ if (sp->alias && sp->alias->func)
+ {
+ Function *func = sp->alias->func;
+ f->setLineFirst (func->line_first);
+ f->setDefSrc (func->def_source);
+ }
+ }
+ }
}
}
return true;
@@ -645,6 +696,29 @@ Dwarf::srcline_Dwarf (Module *module)
dwrCU->map_dwarf_lines (module);
}
+Vector<Range *> *
+Dwarf::get_ranges (uint64_t offset)
+{
+ if (debug_rangesSec == NULL)
+ return NULL;
+ if (offset >= debug_rangesSec->size)
+ {
+ Dprintf (DUMP_DWARFLIB, "ERROR: Dwarf::get_ranges(0x%llx). size=0x%llx\n",
+ (long long) offset, (long long) debug_rangesSec->size);
+ return NULL;
+ }
+ Vector<Range*> *ranges = new Vector<Range*>();
+ debug_rangesSec->offset = offset;
+ for (;;)
+ {
+ uint64_t low_pc = debug_rangesSec->GetADDR ();
+ uint64_t high_pc = debug_rangesSec->GetADDR ();
+ if (low_pc == 0 || low_pc > high_pc)
+ break;
+ ranges->append (new Range (low_pc, high_pc));
+ }
+ return ranges;
+}
// parse hwcprof info for given module in loadobject
@@ -723,7 +797,7 @@ DwrCU::read_hwcprof_info (Dwarf_cnt *ctx)
Dwarf_Die next_die;
if (read_ref_attr (DW_AT_sibling, &next_die) == DW_DLV_OK)
{
- next_die_offset = next_die + cu_offset;
+ next_die_offset = next_die;
if (next_die_offset <= debug_infoSec->offset)
next_die_offset = 0;
else if (debug_infoSec->size > next_die_offset)
@@ -797,11 +871,17 @@ DwrCU::read_hwcprof_info (Dwarf_cnt *ctx)
case DW_TAG_subprogram:
{
Function *old_func = ctx->func;
- if (dwrTag.get_attr (DW_AT_abstract_origin)
- || dwrTag.get_attr (DW_AT_declaration))
- ctx->func = NULL;
- else
- ctx->func = append_Function (ctx);
+ ctx->func = NULL;
+ if (dwrTag.get_attr (DW_AT_abstract_origin) == NULL
+ && dwrTag.get_attr (DW_AT_declaration) == NULL)
+ {
+ Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym == NULL)
+ sym = Symbol::get_symbol (symbols, get_low_pc ());
+ if (sym != NULL)
+ ctx->func = sym->func;
+ }
read_hwcprof_info (ctx);
ctx->func = old_func;
break;
@@ -955,49 +1035,31 @@ DwrCU::read_hwcprof_info (Dwarf_cnt *ctx)
// Append function to module
Function *
-DwrCU::append_Function (Dwarf_cnt *ctx)
+DwrCU::append_Function (Symbol *sym, const char *outerName)
{
- char *outerName = ctx->name, *name, tmpname[2048];
- Function *func;
+ if (sym->func != NULL)
+ return sym->func;
+ Function *func = sym->createFunction (module);
+
char *fname = Dwarf_string (DW_AT_name);
- if (fname && outerName && !strchr (fname, '.'))
+ if (fname)
{
- size_t outerlen = strlen (outerName);
- if (outerlen > 0 && outerName[outerlen - 1] == '_')
+ if (outerName && !strchr (fname, '.'))
{
- outerlen--;
- snprintf (tmpname, sizeof (tmpname), NTXT ("%s"), outerName);
- snprintf (tmpname + outerlen, sizeof (tmpname) - outerlen, NTXT (".%s_"), fname);
+ char *tmpname;
+ int outerlen = (int) strlen (outerName);
+ if (outerlen > 0 && outerName[outerlen - 1] == '_')
+ tmpname = dbe_sprintf ("%.*s.%s_", outerlen - 1, outerName, fname);
+ else
+ tmpname = dbe_sprintf ("%s.%s", outerName, fname);
+ func->set_match_name (tmpname);
+ Dprintf (DUMP_DWARFLIB, "Generated innerfunc name %s\n", tmpname);
+ free(tmpname);
}
else
- snprintf (tmpname, sizeof (tmpname), NTXT ("%s.%s"), outerName, fname);
- name = tmpname;
- Dprintf (DUMP_DWARFLIB, NTXT ("Generated innerfunc name %s\n"), name);
- }
- else
- name = fname;
-
- char *link_name = get_linkage_name ();
- if (link_name == NULL)
- link_name = name;
-
- uint64_t pc = get_low_pc ();
- func = dwarf->stabs->append_Function (module, link_name, pc);
- if (func != NULL)
- {
- int lineno = (int) Dwarf_data (DW_AT_decl_line);
- func->set_match_name (name);
- if (lineno > 0)
- {
- func->setLineFirst (lineno);
- int fileno = ((int) Dwarf_data (DW_AT_decl_file));
- SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ? srcFiles->get (fileno)
- : module->getMainSrc ();
- func->setDefSrc (sf);
- func->pushSrcFile (func->def_source, 0);
- func->popSrcFile ();
- }
+ func->set_match_name (fname);
}
+ set_source (func);
return func;
}
@@ -1040,3 +1102,94 @@ DwrCU::Dwarf_lang ()
return Sp_lang_unknown;
}
}
+
+Vector <Dwr_rng_entry *> *
+Dwarf::get_debug_rnglists ()
+{
+ if (debug_rnglists != NULL)
+ return debug_rnglists;
+ debug_rnglists = new Vector <Dwr_rng_entry *> ();
+
+ DwrSec *debug_rnglistsSec = dwrGetSec (".debug_rnglists");
+ if (debug_rnglistsSec == NULL)
+ {
+ Dprintf (1, "No section .debug_rnglists\n");
+ return debug_rnglists;
+ }
+ while (debug_rnglistsSec->offset < debug_rnglistsSec->sizeSec)
+ {
+ uint64_t base_address = 0;
+ uint64_t length = debug_rnglistsSec->ReadLength ();
+ Dwr_rng_entry *rng = new Dwr_rng_entry ();
+ debug_rnglists->append (rng);
+ rng->offset = debug_rnglistsSec->offset;
+ rng->length = length;
+ rng->fmt64 = debug_rnglistsSec->fmt64;
+ rng->version = debug_rnglistsSec->Get_16 ();
+ rng->address_size = debug_rnglistsSec->Get_8 ();
+ rng->segment_selector_size = debug_rnglistsSec->Get_8 ();
+ rng->offset_entry_count = debug_rnglistsSec->Get_32 ();
+ while (debug_rnglistsSec->offset < debug_rnglistsSec->size)
+ {
+ uint64_t off = debug_rnglistsSec->offset;
+ uint64_t low_pc;
+ uint64_t high_pc;
+ int re = debug_rnglistsSec->Get_8 ();
+ switch (re)
+ {
+ case DW_RLE_end_of_list:
+ low_pc = 0;
+ high_pc = 0;
+ break;
+ case DW_RLE_base_address:
+ base_address = debug_rnglistsSec->GetADDR ();
+ low_pc = base_address;
+ high_pc = 0;
+ continue;
+ case DW_RLE_start_length:
+ low_pc = debug_rnglistsSec->GetADDR ();
+ high_pc = low_pc + debug_rnglistsSec->GetULEB128 ();
+ break;
+ case DW_RLE_offset_pair:
+ low_pc = base_address + debug_rnglistsSec->GetULEB128 ();
+ high_pc = base_address + debug_rnglistsSec->GetULEB128 ();
+ break;
+ case DW_RLE_start_end:
+ low_pc = debug_rnglistsSec->GetADDR ();
+ high_pc = debug_rnglistsSec->GetADDR ();
+ break;
+ case DW_RLE_base_addressx:
+ base_address = debug_rnglistsSec->GetULEB128 ();
+ low_pc = base_address;
+ high_pc = 0;
+ continue;
+
+ // TODO x-variants need .debug_addr support used for split-dwarf
+ case DW_RLE_startx_endx:
+ low_pc = debug_rnglistsSec->GetRef ();
+ high_pc = debug_rnglistsSec->GetRef ();
+ Dprintf (1, "DW_RLE_startx_endx is not implemented\n");
+ continue;
+ case DW_RLE_startx_length:
+ low_pc = debug_rnglistsSec->GetRef ();
+ high_pc = low_pc + debug_rnglistsSec->GetULEB128 ();
+ Dprintf (1, "DW_RLE_startx_length is not implemented\n");
+ continue;
+ default:
+ Dprintf (1, "Unknown tag DW_RLE: %d, offset=0x%llx\n", re,
+ (long long) off);
+ debug_rnglistsSec->offset = debug_rnglistsSec->size;
+ continue;
+ }
+ Dprintf (DUMP_DWARFLIB, "0x%08llx %d-%-20s [0x%08llx - 0x%08llx)\n",
+ (long long) off, re, Dwr_rng_entry::rng_entry2str (re),
+ (long long) low_pc, (long long) high_pc);
+ rng->ranges->append (new ExtRange (off, low_pc, high_pc));
+ }
+ debug_rnglistsSec->size = debug_rnglistsSec->sizeSec;
+ debug_rnglistsSec->offset = length;
+ }
+ delete debug_rnglistsSec;
+ debug_rnglists->dump ("Dwarf::get_debug_rnglists");
+ return debug_rnglists;
+}