aboutsummaryrefslogtreecommitdiff
path: root/gprofng/src
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src')
-rw-r--r--gprofng/src/CallStack.cc10
-rw-r--r--gprofng/src/DbeSession.cc11
-rw-r--r--gprofng/src/DbeSession.h1
-rw-r--r--gprofng/src/Disasm.cc17
-rw-r--r--gprofng/src/Disasm.h3
-rw-r--r--gprofng/src/Dwarf.cc299
-rw-r--r--gprofng/src/Dwarf.h5
-rw-r--r--gprofng/src/DwarfLib.cc618
-rw-r--r--gprofng/src/DwarfLib.h67
-rw-r--r--gprofng/src/Elf.cc225
-rw-r--r--gprofng/src/Elf.h42
-rw-r--r--gprofng/src/Experiment.cc12
-rw-r--r--gprofng/src/Experiment.h5
-rw-r--r--gprofng/src/LoadObject.cc101
-rw-r--r--gprofng/src/LoadObject.h11
-rw-r--r--gprofng/src/Makefile.am1
-rw-r--r--gprofng/src/Makefile.in4
-rw-r--r--gprofng/src/Module.cc2
-rw-r--r--gprofng/src/Stabs.cc353
-rw-r--r--gprofng/src/Stabs.h10
-rw-r--r--gprofng/src/Symbol.cc218
-rw-r--r--gprofng/src/Symbol.h84
-rw-r--r--gprofng/src/collect.h1
-rw-r--r--gprofng/src/envsets.cc10
-rw-r--r--gprofng/src/gp-archive.cc68
-rw-r--r--gprofng/src/gp-archive.h1
-rw-r--r--gprofng/src/gp-collect-app.cc5
-rw-r--r--gprofng/src/gp-display-src.cc3
-rw-r--r--gprofng/src/gp-display-text.cc3
-rw-r--r--gprofng/src/gprofng.cc3
-rw-r--r--gprofng/src/ipcio.cc5
31 files changed, 1237 insertions, 961 deletions
diff --git a/gprofng/src/CallStack.cc b/gprofng/src/CallStack.cc
index 6df4112..9a3a15d 100644
--- a/gprofng/src/CallStack.cc
+++ b/gprofng/src/CallStack.cc
@@ -527,14 +527,10 @@ CallStackP::add_stack (DataDescriptor *dDscr, long idx, FramePacket *frp,
Vaddr va = frp->getFromStack (index);
DbeInstr *cur_instr = experiment->map_Vaddr_to_PC (va, tstamp);
-#if ARCH(Intel)// TBR? FIXUP_XXX_SPARC_LINUX: switch should be on experiment ARCH, not dbe ARCH
// We need to adjust return addresses on intel
- // in order to attribute inclusive metrics to
- // proper call instructions.
- if (experiment->exp_maj_version <= 9)
- if (!leaf && cur_instr->addr != 0)
- cur_instr = cur_instr->func->find_dbeinstr (0, cur_instr->addr - 1);
-#endif
+ // in order to attribute inclusive metrics to proper instructions.
+ if (experiment->platform == Intel && cur_instr->addr != 0)
+ cur_instr = cur_instr->func->find_dbeinstr (0, cur_instr->addr - 1);
// Skip PC's from PLT, update leaf and state accordingly
if ((cur_instr->func->flags & FUNC_FLAG_PLT)
diff --git a/gprofng/src/DbeSession.cc b/gprofng/src/DbeSession.cc
index f3426ce..b0aa745 100644
--- a/gprofng/src/DbeSession.cc
+++ b/gprofng/src/DbeSession.cc
@@ -2017,6 +2017,17 @@ DbeSession::is_omp_available ()
}
bool
+DbeSession::is_bigendian ()
+{
+#ifdef WORDS_BIGENDIAN
+ return true;
+#else
+ return false;
+#endif
+
+}
+
+bool
DbeSession::has_java ()
{
int status_has_java = 0;
diff --git a/gprofng/src/DbeSession.h b/gprofng/src/DbeSession.h
index 5cbddae..7db0998 100644
--- a/gprofng/src/DbeSession.h
+++ b/gprofng/src/DbeSession.h
@@ -120,6 +120,7 @@ public:
bool is_timeline_available ();
bool is_ifreq_available ();
bool is_omp_available ();
+ static bool is_bigendian ();
bool has_java ();
bool has_ompavail ();
diff --git a/gprofng/src/Disasm.cc b/gprofng/src/Disasm.cc
index 42fb777..3ee50d7 100644
--- a/gprofng/src/Disasm.cc
+++ b/gprofng/src/Disasm.cc
@@ -50,19 +50,6 @@ struct DisContext
static const int MAX_DISASM_STR = 2048;
-Disasm::Disasm (char *fname)
-{
- dwin = NULL;
- dis_str = NULL;
- need_swap_endian = false;
- my_stabs = Stabs::NewStabs (fname, fname);
- if (my_stabs == NULL)
- return;
- stabs = my_stabs;
- platform = stabs->get_platform ();
- disasm_open ();
-}
-
Disasm::Disasm (Platform_t _platform, Stabs *_stabs)
{
dwin = NULL;
@@ -70,7 +57,6 @@ Disasm::Disasm (Platform_t _platform, Stabs *_stabs)
need_swap_endian = false;
stabs = _stabs;
platform = _platform;
- my_stabs = NULL;
disasm_open ();
}
@@ -263,7 +249,6 @@ Disasm::disasm_open ()
Disasm::~Disasm ()
{
- delete my_stabs;
delete dwin;
delete dis_str;
}
@@ -370,7 +355,7 @@ Disasm::get_funcname_in_plt (uint64_t pc)
{
if (stabs)
{
- Elf *elf = stabs->openElf (true);
+ Elf *elf = stabs->openElf (false);
if (elf)
return elf->get_funcname_in_plt (pc);
}
diff --git a/gprofng/src/Disasm.h b/gprofng/src/Disasm.h
index 0326b5c..3d7159d 100644
--- a/gprofng/src/Disasm.h
+++ b/gprofng/src/Disasm.h
@@ -31,7 +31,6 @@ enum Platform_t;
class Disasm
{
public:
- Disasm (char *fname);
Disasm (Platform_t _platform, Stabs *_stabs);
~Disasm ();
void remove_disasm_hndl (void *hndl);
@@ -59,7 +58,7 @@ private:
disassemble_info dis_info;
Data_window *dwin;
- Stabs *stabs, *my_stabs;
+ Stabs *stabs;
Platform_t platform;
char addr_fmt[32];
int hex_visible;
diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc
index a613c63..934ae44 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
@@ -368,6 +368,7 @@ Dwarf::Dwarf (Stabs *_stabs)
debug_infoSec = NULL;
debug_abbrevSec = NULL;
debug_strSec = NULL;
+ debug_alt_strSec = NULL;
debug_lineSec = NULL;
debug_line_strSec = NULL;
debug_rangesSec = NULL;
@@ -378,18 +379,14 @@ Dwarf::Dwarf (Stabs *_stabs)
return;
}
debug_infoSec = dwrGetSec (NTXT (".debug_info"));
- if (debug_infoSec)
- {
- debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rela.debug_info"), NULL);
- debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rel.debug_info"), debug_infoSec->reloc);
- if (debug_infoSec->reloc)
- debug_infoSec->reloc->dump ();
- }
debug_abbrevSec = dwrGetSec (NTXT (".debug_abbrev"));
debug_strSec = dwrGetSec (NTXT (".debug_str"));
debug_lineSec = dwrGetSec (NTXT (".debug_line"));
debug_rangesSec = dwrGetSec (NTXT (".debug_ranges"));
debug_line_strSec = dwrGetSec (".debug_line_str");
+ debug_rnglists = NULL;
+ if (elf->gnu_debugalt_file)
+ debug_alt_strSec = elf->gnu_debugalt_file->get_dwr_section (".debug_str");
if ((debug_infoSec == NULL) || (debug_abbrevSec == NULL) || (debug_lineSec == NULL))
{
@@ -400,27 +397,16 @@ Dwarf::Dwarf (Stabs *_stabs)
Dwarf::~Dwarf ()
{
- delete debug_infoSec;
- delete debug_abbrevSec;
- delete debug_strSec;
- delete debug_lineSec;
- delete debug_rangesSec;
Destroy (dwrCUs);
}
DwrSec *
Dwarf::dwrGetSec (const char *sec_name)
{
- int secN = elf->elf_get_sec_num (sec_name);
- if (secN > 0)
- {
- Elf_Data *elfData = elf->elf_getdata (secN);
- if (elfData)
- return new DwrSec ((unsigned char *) elfData->d_buf, elfData->d_size,
- elf->need_swap_endian,
- elf->elf_getclass () == ELFCLASS32);
- }
- return NULL;
+ DwrSec *p = elf->get_dwr_section (sec_name);
+ if (p)
+ p->offset = 0;
+ return p;
}
uint64_t
@@ -441,7 +427,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 +445,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 +481,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 +507,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 +652,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 +681,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 +782,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 +856,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 +1020,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 +1087,93 @@ 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;
+ }
+ debug_rnglists->dump ("Dwarf::get_debug_rnglists");
+ return debug_rnglists;
+}
diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h
index 8e3ee7a..14d9878 100644
--- a/gprofng/src/Dwarf.h
+++ b/gprofng/src/Dwarf.h
@@ -60,6 +60,7 @@ class LoadObject;
class Module;
class DwrCU;
class DwrSec;
+class Range;
class Dwarf
{
@@ -69,12 +70,15 @@ public:
bool archive_Dwarf (LoadObject *lo);
void srcline_Dwarf (Module *module);
void read_hwcprof_info (Module *module);
+ Vector<Range *> *get_ranges (uint64_t offset);
+ Vector <Dwr_rng_entry *> *get_debug_rnglists ();
Stabs::Stab_status status;
Vector<DwrCU *> *dwrCUs;
DwrSec *debug_infoSec;
DwrSec *debug_abbrevSec;
DwrSec *debug_strSec;
+ DwrSec *debug_alt_strSec;
DwrSec *debug_lineSec;
DwrSec *debug_line_strSec;
DwrSec *debug_rangesSec;
@@ -82,6 +86,7 @@ public:
Stabs *stabs;
private:
+ Vector <Dwr_rng_entry *> *debug_rnglists;
DwrSec *dwrGetSec (const char *sec_name);
};
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc
index d399c33..4720ef1 100644
--- a/gprofng/src/DwarfLib.cc
+++ b/gprofng/src/DwarfLib.cc
@@ -27,39 +27,14 @@
#include "Elf.h"
#include "Function.h"
#include "Module.h"
-#include "StringBuilder.h"
#include "DbeArray.h"
#include "DbeSession.h"
+#include "Symbol.h"
#define NO_STMT_LIST ((uint64_t) -1)
#define CASE_S(x) case x: s = (char *) #x; break
static char *
-gelf_st_type2str (int type)
-{
- static char buf[128];
- char *s;
- switch (type)
- {
- CASE_S (STT_NOTYPE);
- CASE_S (STT_OBJECT);
- CASE_S (STT_FUNC);
- CASE_S (STT_SECTION);
- CASE_S (STT_FILE);
- CASE_S (STT_COMMON);
- CASE_S (STT_TLS);
- // CASE_S(STT_NUM);
- CASE_S (STT_LOPROC);
- CASE_S (STT_HIPROC);
- default: s = NTXT ("???");
- break;
- }
- snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type);
- buf[sizeof (buf) - 1] = 0;
- return buf;
-}
-
-static char *
special_opcode2str (int opcode)
{
static char buf[128];
@@ -78,6 +53,7 @@ extended_opcode2str (int opcode)
CASE_S (DW_LNE_end_sequence);
CASE_S (DW_LNE_set_address);
CASE_S (DW_LNE_define_file);
+ CASE_S (DW_LNS_set_file);
default:
snprintf (buf, sizeof (buf), NTXT ("??? (%d)"), opcode);
buf[sizeof (buf) - 1] = 0;
@@ -166,234 +142,6 @@ get_string (DwrSec *sec, uint64_t off)
return NULL;
}
-
-//////////////////////////////////////////////////////////
-// class ElfReloc
-
-ElfReloc::ElfReloc (Elf *_elf)
-{
- elf = _elf;
- reloc = NULL;
- cur_reloc_ind = 0;
-}
-
-ElfReloc::~ElfReloc ()
-{
- if (reloc)
- {
- reloc->destroy ();
- delete reloc;
- }
-}
-
-void
-ElfReloc::dump_rela_debug_sec (int sec)
-{
- if (!DUMP_RELA_SEC)
- return;
- Elf_Internal_Shdr *shdr = elf->get_shdr (sec);
- if (shdr == NULL)
- return;
-
- Elf_Data *data = elf->elf_getdata (sec);
- if (data == NULL)
- return;
-
- uint64_t ScnSize = data->d_size;
- uint64_t EntSize = shdr->sh_entsize;
- if (ScnSize == 0 || EntSize == 0)
- return;
-
- Elf_Internal_Rela rela;
- int n, cnt = (int) (ScnSize / EntSize);
-
- char *sec_name = elf->get_sec_name (sec);
- if (sec_name == NULL) // It can not be, but let's check
- return;
- Dprintf (DUMP_RELA_SEC,
- "======= DwarfLib::dump_rela_debug_sec Section:%2d '%s'\n",
- sec, sec_name);
- Dprintf (DUMP_RELA_SEC,
- " N |addend| offset | r_info | stt_type |\n");
- for (n = 0; n < cnt; n++)
- {
- if (strncmp (sec_name, NTXT (".rela."), 6) == 0)
- elf->elf_getrela (data, n, &rela);
- else
- {
- elf->elf_getrel (data, n, &rela);
- rela.r_addend = 0;
- }
- int ndx = (int) GELF_R_SYM (rela.r_info);
- Elf_Internal_Shdr *secHdr;
- Elf_Internal_Sym sym;
- asymbol *asym;
- asym = elf->elf_getsym (ndx, &sym, false);
- Dprintf (DUMP_RELA_SEC, NTXT ("%3d:%5d |%11lld |0x%016llx | %-15s|"),
- n, (int) rela.r_addend,
- (long long) rela.r_offset, (long long) rela.r_info,
- gelf_st_type2str ((int) GELF_ST_TYPE (sym.st_info)));
- switch (GELF_ST_TYPE (sym.st_info))
- {
- case STT_FUNC:
- case STT_OBJECT:
- case STT_NOTYPE:
- Dprintf (DUMP_RELA_SEC, NTXT (" img_offset=0x%llx"),
- (long long) (bfd_asymbol_value (asym)));
- Dprintf (DUMP_RELA_SEC, NTXT (" %s"), bfd_asymbol_name (asym));
- break;
- case STT_SECTION:
- secHdr = elf->get_shdr (sym.st_shndx);
- if (secHdr)
- {
- Dprintf (DUMP_RELA_SEC, NTXT (" value=0x%016llx (%lld)"),
- (long long) (secHdr->sh_offset + rela.r_addend),
- (long long) (secHdr->sh_offset + rela.r_addend));
- }
- break;
- default:
- break;
- }
- Dprintf (DUMP_RELA_SEC, NTXT ("\n"));
- }
- Dprintf (DUMP_RELA_SEC, NTXT ("\n"));
-}
-
-void
-ElfReloc::dump ()
-{
- if (!DUMP_ELF_RELOC || (reloc == NULL) || (reloc->size () == 0))
- return;
- Dprintf (DUMP_ELF_RELOC, NTXT ("======= ElfReloc::dump\n"));
- Dprintf (DUMP_ELF_RELOC, NTXT (" N | offset | value | STT_TYPE\n"));
- for (int i = 0; i < reloc->size (); i++)
- {
- Sreloc *srlc = reloc->fetch (i);
- Dprintf (DUMP_ELF_RELOC, NTXT ("%3d:%11lld |%11lld | %s\n"),
- i, (long long) srlc->offset, (long long) srlc->value,
- gelf_st_type2str (srlc->stt_type));
- }
- Dprintf (DUMP_ELF_RELOC, NTXT ("\n"));
-}
-
-static int
-DwrRelocOffsetCmp (const void *a, const void *b)
-{
- ElfReloc::Sreloc *item1 = *((ElfReloc::Sreloc **) a);
- ElfReloc::Sreloc *item2 = *((ElfReloc::Sreloc **) b);
- return item1->offset < item2->offset ? -1 :
- item1->offset == item2->offset ? 0 : 1;
-}
-
-ElfReloc *
-ElfReloc::get_elf_reloc (Elf *elfp, char *sec_name, ElfReloc *rlc)
-{
- int et = elfp->elf_getehdr ()->e_type;
- if (et == ET_EXEC || et == ET_DYN)
- return rlc;
- int sec = elfp->elf_get_sec_num (sec_name);
- if (sec == 0)
- return rlc;
- Elf_Internal_Shdr *shdr = elfp->get_shdr (sec);
- if (shdr == NULL || shdr->sh_entsize == 0)
- return rlc;
-
- Elf_Data *data = elfp->elf_getdata (sec);
- if (data == NULL || data->d_size == 0)
- return rlc;
-
- int cnt = (int) (data->d_size / shdr->sh_entsize);
- Vector<Sreloc *> *vp = NULL;
-
- for (int n = 0; n < cnt; n++)
- {
- Elf_Internal_Shdr *secHdr;
- Sreloc *srlc;
- Elf_Internal_Rela rela;
- if (strncmp (sec_name, NTXT (".rela."), 6) == 0)
- elfp->elf_getrela (data, n, &rela);
- else
- {
- elfp->elf_getrel (data, n, &rela);
- rela.r_addend = 0;
- }
- int ndx = (int) GELF_R_SYM (rela.r_info);
- Elf_Internal_Sym sym;
- elfp->elf_getsym (ndx, &sym, false);
-
- srlc = new Sreloc;
- srlc->offset = rela.r_offset;
- srlc->value = 0;
- srlc->stt_type = (int) GELF_ST_TYPE (sym.st_info);
- switch (GELF_ST_TYPE (sym.st_info))
- {
- case STT_FUNC:
- secHdr = elfp->get_shdr (sym.st_shndx);
- if (secHdr)
- srlc->value = secHdr->sh_offset + sym.st_value;
- break;
- case STT_OBJECT:
- case STT_NOTYPE:
- secHdr = elfp->get_shdr (shdr->sh_info);
- if (secHdr)
- {
- srlc->offset = rela.r_info;
- srlc->value = secHdr->sh_offset + rela.r_addend;
- }
- break;
- case STT_SECTION:
- secHdr = elfp->get_shdr (sym.st_shndx);
- if (secHdr)
- srlc->value = rela.r_addend;
- break;
- default:
- srlc->value = 0;
- break;
- }
- if (rlc == NULL)
- {
- rlc = new ElfReloc (elfp);
- vp = rlc->reloc;
- }
- if (vp == NULL)
- {
- vp = new Vector<Sreloc*>;
- rlc->reloc = vp;
- }
- vp->append (srlc);
- }
- if (vp)
- vp->sort (DwrRelocOffsetCmp);
- if (rlc)
- {
- rlc->dump_rela_debug_sec (sec);
- rlc->dump ();
- }
- return rlc;
-}
-
-long long
-ElfReloc::get_reloc_addr (long long offset)
-{
- Sreloc *srlc;
- int i = cur_reloc_ind - 1;
- if (i >= 0 && i < reloc->size ())
- {
- srlc = reloc->fetch (i);
- if (srlc->offset > offset) // need to reset
- cur_reloc_ind = 0;
- }
- for (; cur_reloc_ind < reloc->size (); cur_reloc_ind++)
- {
- srlc = reloc->fetch (cur_reloc_ind);
- if (srlc->offset == offset)
- return srlc->value;
- if (srlc->offset > offset)
- return 0;
- }
- return 0;
-}
-
DwrLocation *
DwrCU::dwr_get_location (DwrSec *secp, DwrLocation *lp)
{
@@ -936,6 +684,8 @@ DwrCU::form2str (int tag)
CASE_S (DW_FORM_strp);
CASE_S (DW_FORM_udata);
CASE_S (DW_FORM_ref_addr);
+ CASE_S (DW_FORM_GNU_ref_alt);
+ CASE_S (DW_FORM_GNU_strp_alt);
CASE_S (DW_FORM_ref1);
CASE_S (DW_FORM_ref2);
CASE_S (DW_FORM_ref4);
@@ -993,12 +743,12 @@ Dwr_Tag::dump ()
case DW_FORM_strp:
case DW_FORM_string:
case DW_FORM_line_strp:
+ case DW_FORM_GNU_strp_alt:
case DW_FORM_strp_sup:
case DW_FORM_strx1:
case DW_FORM_strx2:
case DW_FORM_strx3:
case DW_FORM_strx4:
- case DW_FORM_implicit_const:
Dprintf (DUMP_DWARFLIB, " \"%s\"", atrp->u.str ? atrp->u.str : "<NULL>");
break;
case DW_FORM_block:
@@ -1034,9 +784,11 @@ Dwr_Tag::dump ()
case DW_FORM_ref_udata:
case DW_FORM_indirect:
case DW_FORM_sec_offset:
+ case DW_FORM_GNU_ref_alt:
case DW_FORM_exprloc:
case DW_FORM_ref_sig8:
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
Dprintf (DUMP_DWARFLIB, " 0x%llx (%lld)", (long long) atrp->u.val,
(long long) atrp->u.val);
break;
@@ -1058,34 +810,28 @@ Dwr_Tag::dump ()
DwrSec::DwrSec (unsigned char *_data, uint64_t _size, bool _need_swap_endian, bool _addr32)
{
- isCopy = false;
data = _data;
sizeSec = _size;
size = (data ? _size : 0);
offset = 0;
fmt64 = false;
- reloc = NULL;
need_swap_endian = _need_swap_endian;
addr32 = _addr32;
}
DwrSec::DwrSec (DwrSec *secp, uint64_t _offset)
{
- isCopy = true;
data = secp->data;
sizeSec = secp->sizeSec;
size = secp->size;
offset = _offset;
fmt64 = secp->fmt64;
- reloc = secp->reloc;
need_swap_endian = secp->need_swap_endian;
addr32 = secp->addr32;
}
DwrSec::~DwrSec ()
{
- if (!isCopy)
- delete reloc;
}
bool
@@ -1095,6 +841,7 @@ DwrSec::bounds_violation (uint64_t sz)
{
Dprintf (DEBUG_ERR_MSG, "DwrSec::bounds_violation: offset=%lld + sz=%lld > size=%lld\n",
(long long) offset, (long long) sz, (long long) size);
+ offset = size;
return true;
}
return false;
@@ -1212,17 +959,13 @@ DwrSec::GetLong ()
uint64_t
DwrSec::GetADDR_32 ()
{
- uint64_t res = reloc ? reloc->get_reloc_addr (offset) : 0;
- res += Get_32 ();
- return res;
+ return Get_32 ();
}
uint64_t
DwrSec::GetADDR_64 ()
{
- uint64_t res = reloc ? reloc->get_reloc_addr (offset) : 0;
- res += Get_64 ();
- return res;
+ return Get_64 ();
}
uint64_t
@@ -1282,6 +1025,7 @@ DwrSec::get_value (int dw_form)
case DW_FORM_line_strp:
case DW_FORM_strp:
case DW_FORM_strp_sup:
+ case DW_FORM_GNU_strp_alt:
return GetRef ();
case DW_FORM_data1:
return Get_8 ();
@@ -1545,6 +1289,8 @@ DwrLineRegs::read_file_names_dwarf5 ()
nm = get_string (dwarf->debug_line_strSec, off);
else if (efmt[k].form_code == DW_FORM_strp)
nm = get_string (dwarf->debug_strSec, off);
+ else if (efmt[k].form_code == DW_FORM_GNU_strp_alt)
+ nm = get_string (dwarf->debug_alt_strSec, off);
}
break;
case DW_LNCT_directory_index:
@@ -1795,6 +1541,12 @@ DwrLineRegs::getPath (int fn)
DwrCU::DwrCU (Dwarf *_dwarf)
{
dwarf = _dwarf;
+ tmp_syms = new Vector<Symbol*>();
+ rng_list = NULL;
+ rng_list_inited = false;
+ base_address = 0;
+ symbols = NULL;
+ symbols_sorted_by_name = NULL;
cu_offset = dwarf->debug_infoSec->offset;
debug_infoSec = new DwrSec (dwarf->debug_infoSec, cu_offset);
next_cu_offset = debug_infoSec->ReadLength ();
@@ -1836,7 +1588,7 @@ DwrCU::DwrCU (Dwarf *_dwarf)
if (DUMP_DWARFLIB)
{
Dprintf (DUMP_DWARFLIB,
- "CU_HEADER: header_offset = 0x%08llx %lld"
+ "File: %s\nCU_HEADER: header_offset = 0x%08llx %lld"
" next_header_offset=0x%08llx %lld\n"
" abbrev_offset = 0x%08llx %lld\n"
" unit_length = %lld\n"
@@ -1844,10 +1596,11 @@ DwrCU::DwrCU (Dwarf *_dwarf)
" address_size = %d\n"
" fmt64 = %s\n"
"debug_info: need_swap_endian=%s fmt64=%s addr32=%s\n",
+ dwarf->elf->get_location (),
(long long) cu_offset, (long long) cu_offset,
(long long) next_cu_offset, (long long) next_cu_offset,
(long long) debug_abbrev_offset, (long long) debug_abbrev_offset,
- (long long) (next_cu_offset - cu_offset),
+ (long long) (next_cu_offset),
(int) version, (int) address_size,
debug_infoSec->fmt64 ? "true" : "false",
debug_infoSec->need_swap_endian ? "true" : "false",
@@ -1883,6 +1636,9 @@ DwrCU::~DwrCU ()
Destroy (dwrInlinedSubrs);
delete srcFiles;
delete dwrLineReg;
+ delete symbols;
+ delete symbols_sorted_by_name;
+ delete tmp_syms;
free (comp_dir);
}
@@ -1925,7 +1681,7 @@ DwrCU::build_abbrevTable (DwrSec *_debug_abbrevSec, uint64_t _offset)
switch (atf.at_form)
{
case DW_FORM_implicit_const:
- atf.len = debug_abbrevSec->GetSLEB128 ();
+ atf.u.val = debug_abbrevSec->GetSLEB128 ();
break;
}
abbrevAtForm->append (atf);
@@ -1945,7 +1701,7 @@ DwrCU::set_die (Dwarf_Die die)
|| debug_infoSec->offset >= debug_infoSec->size)
return DW_DLV_ERROR;
dwrTag.offset = debug_infoSec->offset;
- dwrTag.die = debug_infoSec->offset - cu_offset;
+ dwrTag.die = debug_infoSec->offset;
dwrTag.num = debug_infoSec->GetULEB128_32 ();
if (dwrTag.num == 0)
return DW_DLV_NO_ENTRY;
@@ -1994,19 +1750,19 @@ DwrCU::set_die (Dwarf_Die die)
atf->u.str = debug_infoSec->GetData (atf->len);
break;
case DW_FORM_ref1:
- atf->u.offset = debug_infoSec->Get_8 ();
+ atf->u.offset = debug_infoSec->Get_8 () + cu_offset;
break;
case DW_FORM_ref2:
- atf->u.offset = debug_infoSec->Get_16 ();
+ atf->u.offset = debug_infoSec->Get_16 () + cu_offset;
break;
case DW_FORM_ref4:
- atf->u.offset = debug_infoSec->Get_32 ();
+ atf->u.offset = debug_infoSec->Get_32 () + cu_offset;
break;
case DW_FORM_ref8:
- atf->u.offset = debug_infoSec->Get_64 ();
+ atf->u.offset = debug_infoSec->Get_64 () + cu_offset;
break;
case DW_FORM_ref_udata:
- atf->u.offset = debug_infoSec->GetULEB128 ();
+ atf->u.offset = debug_infoSec->GetULEB128 () + cu_offset;
break;
case DW_FORM_data1:
atf->u.offset = debug_infoSec->Get_8 ();
@@ -2040,6 +1796,9 @@ DwrCU::set_die (Dwarf_Die die)
else
atf->u.offset = debug_infoSec->GetADDR ();
break;
+ case DW_FORM_GNU_ref_alt:
+ atf->u.offset = debug_infoSec->GetRef ();
+ break;
case DW_FORM_sec_offset:
atf->u.offset = debug_infoSec->GetRef ();
break;
@@ -2063,6 +1822,10 @@ DwrCU::set_die (Dwarf_Die die)
case DW_FORM_rnglistx:
atf->u.offset = debug_infoSec->GetULEB128 ();
break;
+ case DW_FORM_GNU_strp_alt:
+ atf->u.offset = debug_infoSec->GetRef ();
+ atf->u.str = get_string (dwarf->debug_alt_strSec, atf->u.offset);
+ break;
case DW_FORM_strx:
atf->u.offset = debug_infoSec->GetULEB128 ();
atf->u.str = get_string (dwarf->debug_strSec, atf->u.offset);
@@ -2109,7 +1872,7 @@ DwrCU::set_die (Dwarf_Die die)
atf->len = 0;
break;
case DW_FORM_implicit_const:
- atf->u.str = NULL;
+ // atf->u.val is already set
break;
default:
DEBUG_CODE
@@ -2187,9 +1950,241 @@ DwrCU::parse_cu_header (LoadObject *lo)
else
path = dbe_strdup (dwarf->stabs->path);
module->set_name (path);
+
+ // create a list of functions in this CU
+ base_address = get_low_pc ();
+ Vector <Range *> *ranges = get_ranges ();
+ if (ranges)
+ {
+ Vector <Symbol *> *syms = dwarf->stabs->get_symbols ();
+ symbols = Symbol::find_symbols (syms, ranges, new Vector <Symbol *> ());
+ symbols_sorted_by_name = Symbol::sort_by_name (symbols);
+ if (DUMP_ELF_SYM)
+ symbols->dump ("DwrCU::parse_cu_header: symbols");
+ Destroy (ranges);
+ }
return module;
}
+
+static int
+cmp_ExtRange (const void *a, const void *b)
+{
+ uint64_t a1 = *((uint64_t *) a);
+ ExtRange *rng = *((ExtRange **) b);
+ uint64_t b1 = rng->offset;
+ return a1 < b1 ? -1 : (a1 == b1 ? 0 : 1);
+}
+
+static int
+cmp_offset (const void *a, const void *b)
+{
+ uint64_t off = *((uint64_t *) a);
+ Dwr_rng_entry *rng = *((Dwr_rng_entry **) b);
+ return off < rng->offset ? -1 : (off < rng->length ? 0 : 1);
+}
+
+static int
+rangeCmp (const void *a, const void *b)
+{
+ Range *item1 = *((Range **) a);
+ Range *item2 = *((Range **) b);
+ return item1->low < item2->low ? -1 : (item1->low == item2->low ? 0 : 1);
+}
+
+Vector <Range *> *
+DwrCU::get_ranges ()
+{
+ Vector <Range *> *ranges = NULL;
+ Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_ranges);
+ if (dwrAttr)
+ {
+ uint64_t offset = dwrAttr->u.offset;
+ Dprintf (DUMP_DWARFLIB, "DwrCU::get_ranges: 0x%llx\n", (long long) offset);
+ if (version < 5)
+ ranges = dwarf->get_ranges (offset);
+ else
+ {
+ if (rng_list == NULL && !rng_list_inited)
+ {
+ rng_list_inited = true;
+ // Find the corresponding section in .debug_rnglists
+ Vector <Dwr_rng_entry *> *rng_entrys = dwarf->get_debug_rnglists ();
+ if (rng_entrys == NULL)
+ return NULL;
+ int ind = rng_entrys->bisearch (0, -1, &offset, cmp_offset);
+ if (ind != -1)
+ rng_list = rng_entrys->get (ind);
+ else
+ {
+ Dprintf (1, "Cannot find rnglist. DW_AT_ranges=0x%llx\n",
+ (long long) offset);
+ return NULL;
+ }
+ }
+ if (rng_list == NULL)
+ return NULL;
+ int ind = rng_list->ranges->bisearch (0, -1, &offset, cmp_ExtRange);
+ if (ind == -1)
+ {
+ Dprintf (1, "Cannot find rnglist. DW_AT_ranges=0x%llx\n",
+ (long long) offset);
+ return NULL;
+ }
+ ranges = new Vector <Range *> ();
+ for (long i = ind, sz = VecSize (rng_list->ranges); i < sz; i++)
+ {
+ ExtRange *r = rng_list->ranges->get (i);
+ if (r->high == 0)
+ break;
+ ranges->append (new Range (r->low + base_address,
+ r->high + base_address));
+ }
+ }
+ }
+ else
+ {
+ uint64_t low_pc = Dwarf_addr (DW_AT_low_pc);
+ if (low_pc > 0)
+ {
+ uint64_t high_pc = get_high_pc (low_pc);
+ ranges = new Vector <Range *> (1);
+ ranges->append (new Range (low_pc, high_pc));
+ Dprintf (DUMP_DWARFLIB, "DwrCU::get_ranges: pc=0x%llx\n",
+ (long long) low_pc);
+ }
+ }
+ if (ranges)
+ {
+ ranges->sort (rangeCmp);
+ if (DUMP_DWARFLIB)
+ ranges->dump ("DwrCU::get_ranges:");
+ }
+ return ranges;
+}
+
+Vector<Symbol *> *
+DwrCU::get_symbols (Vector<Symbol *> *syms)
+{
+ if (syms)
+ syms->reset ();
+ Vector <Range *> *ranges = get_ranges ();
+ if (ranges)
+ {
+ syms = Symbol::find_symbols (symbols, ranges, syms);
+ Destroy (ranges);
+ }
+ if (syms)
+ {
+ Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym)
+ syms->append (sym);
+ }
+ if (syms && DUMP_ELF_SYM)
+ syms->dump ("DwrCU::get_symbols:");
+ return syms;
+}
+
+void
+DwrCU::set_source (Function *func)
+{
+ int lineno = (int) Dwarf_data (DW_AT_decl_line);
+ func->setLineFirst (lineno);
+
+ int fileno = (int) Dwarf_data (DW_AT_decl_file);
+ func->setDefSrc (get_source (fileno));
+}
+
+SourceFile *
+DwrCU::get_source (int fileno)
+{
+ if (fileno > 0 && fileno < VecSize (srcFiles))
+ return srcFiles->get (fileno);
+ return NULL;
+}
+
+void
+DwrCU::inherit_prop (int64_t offset, source_t *src)
+{
+ if (src->lineno == 0)
+ src->lineno = (int) Dwarf_data (DW_AT_decl_line);
+ if (src->sf == NULL)
+ src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file));
+
+ int64_t old_offset = dwrTag.offset;
+ if (set_die (offset) == DW_DLV_OK)
+ {
+ if (src->lineno == 0)
+ src->lineno = (int) Dwarf_data (DW_AT_decl_line);
+ if (src->sf == NULL)
+ src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file));
+
+ Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_specification);
+ if (dwrAttr)
+ inherit_prop (dwrAttr->u.offset, src);
+ else
+ {
+ Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym)
+ update_source (sym, src);
+ }
+ }
+ set_die (old_offset);
+}
+
+void
+DwrCU::set_up_funcs (int64_t offset)
+{
+ // get symbols from DW_AT_ranges, DW_AT_low_pc, DW_AT_linkage_name
+ Vector<Symbol *> *syms = get_symbols (tmp_syms);
+ if (VecSize (syms) == 0)
+ return;
+
+ // Find previous declaration to inherit settings.
+ source_t src = {.lineno = 0, .sf = NULL};
+ inherit_prop (offset, &src);
+
+ for (int i = 0, sz = VecSize (syms); i < sz; i++)
+ {
+ Symbol *sym = syms->get (i);
+ update_source (sym, &src);
+ if (sym->alias)
+ update_source (sym->alias, &src);
+ }
+}
+
+/* Create a function if necessary.
+ * Update the source information */
+void
+DwrCU::update_source (Symbol *sym, source_t *src)
+{
+ Function *f = sym->createFunction (module);
+ f->setLineFirst (src->lineno);
+ f->setDefSrc (src->sf);
+}
+
+Symbol *
+DwrCU::find_declaration (int64_t offset, source_t *src)
+{
+ int64_t old_offset = dwrTag.offset;
+ Symbol *sym = NULL;
+ if (set_die (offset) == DW_DLV_OK)
+ {
+ if (src->lineno == 0)
+ src->lineno = (int) Dwarf_data (DW_AT_decl_line);
+ if (src->sf == NULL)
+ src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file));
+
+ sym = Symbol::get_symbol (symbols_sorted_by_name, get_linkage_name ());
+ if (sym && sym->func == NULL)
+ update_source (sym, src);
+ }
+ set_die (old_offset);
+ return sym;
+}
+
Dwr_Attr *
Dwr_Tag::get_attr (Dwarf_Half attr)
{
@@ -2269,6 +2264,7 @@ DwrCU::read_data_attr (Dwarf_Half attr, int64_t *retVal)
case DW_FORM_data16:
case DW_FORM_udata:
case DW_FORM_sec_offset:
+ case DW_FORM_implicit_const:
*retVal = dwrAttr->u.val;
return DW_DLV_OK;
@@ -2357,7 +2353,7 @@ DwrCU::map_dwarf_lines (Module *mod)
InlinedSubr *p = func->inlinedSubr + func->inlinedSubrCnt;
func->inlinedSubrCnt++;
int fileno = inlinedSubr->file - 1;
- SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ?
+ SourceFile *sf = ((fileno > 0) && (fileno < VecSize (srcFiles))) ?
srcFiles->get (fileno) : dbeSession->get_Unknown_Source ();
p->dbeLine = sf->find_dbeline (inlinedSubr->line);
p->high_pc = inlinedSubr->high_pc - low_pc;
@@ -2502,3 +2498,69 @@ DwrInlinedSubr::dump ()
(int) level, (long long) abstract_origin, (long long) low_pc,
(long long) high_pc, (int) file, (int) line);
}
+
+
+//////////////////////////////////////////////////////////
+// class Dwr_rng_entry
+Dwr_rng_entry::Dwr_rng_entry ()
+{
+ ranges = new Vector <ExtRange *>();
+}
+
+Dwr_rng_entry::~Dwr_rng_entry ()
+{
+ delete ranges;
+}
+
+void
+Dwr_rng_entry::dump ()
+{
+ Dprintf (DUMP_DWARFLIB, "offset=0x%08llx length=0x%08llx fmt=%d version=%d "
+ "addr_size=%d seg_size=%d offset_entry_count=0x%llx\n",
+ (long long) offset, (long long) (length - offset), fmt64 ? 64 : 32,
+ (int) version, (int) address_size, (int) segment_selector_size,
+ (long long) offset_entry_count);
+ for (long i = 0, sz = VecSize (ranges); i < sz; i++)
+ {
+ ExtRange *p = ranges->get (i);
+ Dprintf (DUMP_DWARFLIB, " %8ld: 0x%08llx 0x%08llx-0x%08llx [%lld-%lld)\n",
+ i, (long long) p->offset, (long long) p->low, (long long) p->high,
+ (long long) p->low, (long long) p->high);
+ }
+}
+
+char *
+Dwr_rng_entry::rng_entry2str (int val)
+{
+ char *s;
+ switch (val)
+ {
+ CASE_S (DW_RLE_end_of_list);
+ CASE_S (DW_RLE_base_address);
+ CASE_S (DW_RLE_start_length);
+ CASE_S (DW_RLE_offset_pair);
+ CASE_S (DW_RLE_start_end);
+ CASE_S (DW_RLE_base_addressx);
+ CASE_S (DW_RLE_startx_endx);
+ CASE_S (DW_RLE_startx_length);
+ default: s = (char *) "???";
+ break;
+ }
+ return s;
+}
+
+template<> void Vector<Dwr_rng_entry *>::dump (const char *msg)
+{
+ if (!DUMP_DWARFLIB)
+ return;
+ if (msg == NULL)
+ msg = "#";
+ Dprintf (1, NTXT ("\n%s Vector<Dwr_rng_entry *> [%lld]\n"), msg, (long long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ Dwr_rng_entry *p = get (i);
+ Dprintf (1, " %3ld ", i);
+ p->dump ();
+ }
+}
+
diff --git a/gprofng/src/DwarfLib.h b/gprofng/src/DwarfLib.h
index 178801d..49ecb41 100644
--- a/gprofng/src/DwarfLib.h
+++ b/gprofng/src/DwarfLib.h
@@ -23,9 +23,11 @@
#include "dwarf2.h"
-class ElfReloc;
class Dwr_type;
+class Function;
+class Range;
class SourceFile;
+class Symbol;
template <class ITEM> class Vector;
template <class ITEM> class DbeArray;
@@ -73,13 +75,6 @@ public:
return (uint32_t) GetULEB128 ();
}
- bool
- inRange (uint64_t left, uint64_t right)
- {
- return (offset >= left) && (offset < right);
- };
-
- ElfReloc *reloc;
uint64_t sizeSec;
uint64_t size;
uint64_t offset;
@@ -90,7 +85,6 @@ public:
int segment_selector_size; // DWARF 5
private:
- bool isCopy;
unsigned char *data;
bool bounds_violation (uint64_t sz);
};
@@ -260,6 +254,45 @@ public:
Dwr_type *put_dwr_type (Dwr_Tag *dwrTag);
};
+class ExtRange
+{
+public:
+ ExtRange (uint64_t _off, uint64_t _low, uint64_t _high)
+ {
+ offset = _off;
+ low = _low;
+ high = _high;
+ };
+
+ uint64_t offset;
+ uint64_t low;
+ uint64_t high;
+};
+
+class Dwr_rng_entry
+{
+public:
+ Dwr_rng_entry ();
+ ~Dwr_rng_entry ();
+ void dump();
+ static char *rng_entry2str(int val);
+
+ Dwarf_Half version;
+ Dwarf_Small address_size;
+ Dwarf_Small segment_selector_size;
+ int offset_entry_count;
+ uint64_t length;
+ uint64_t offset;
+ bool fmt64;
+ Vector <ExtRange *> *ranges;
+};
+
+typedef struct Source
+{
+ int lineno;
+ SourceFile *sf;
+} source_t;
+
class DwrCU
{
public:
@@ -280,6 +313,8 @@ public:
uint64_t cu_header_offset;
uint64_t cu_offset;
uint64_t next_cu_offset;
+ Vector<Symbol*> *symbols; // all symbols in this CU are sorted by pc
+ Vector<Symbol*> *symbols_sorted_by_name;
Vector<DwrInlinedSubr*> *dwrInlinedSubrs;
Vector<SourceFile *> *srcFiles;
bool isMemop;
@@ -287,7 +322,15 @@ public:
private:
void build_abbrevTable (DwrSec *debug_abbrevSec, uint64_t stmt_list_offset);
- Function *append_Function (Dwarf_cnt *ctx);
+ Function *append_Function (Symbol *sym, const char *outerName);
+ void set_up_funcs (int64_t offset);
+ void inherit_prop (int64_t offset, source_t *src);
+ void update_source (Symbol *sym, source_t *prop);
+ Symbol *find_declaration (int64_t offset, source_t *prop);
+ SourceFile *get_source (int fileno);
+ Vector<Symbol *> *get_symbols (Vector<Symbol *> *syms = NULL);
+ Vector <Range *> *get_ranges();
+ void set_source (Function *func);
void parse_inlined_subroutine (Dwarf_cnt *ctx);
uint64_t get_low_pc ();
uint64_t get_high_pc (uint64_t low_pc);
@@ -316,6 +359,10 @@ private:
DwrLineRegs *dwrLineReg;
DbeArray<DwrAbbrevTable> *abbrevTable;
DbeArray<Dwr_Attr> *abbrevAtForm;
+ Vector<Symbol*> *tmp_syms; // reused vector for get_symbols()
+ Dwr_rng_entry *rng_list; // entry in the .debug_rnglists section
+ bool rng_list_inited;
+ uint64_t base_address; // low_pc in compile_unit
};
#endif /* _DWARFLIB_H_ */
diff --git a/gprofng/src/Elf.cc b/gprofng/src/Elf.cc
index f0fd121..e63e3c3 100644
--- a/gprofng/src/Elf.cc
+++ b/gprofng/src/Elf.cc
@@ -28,6 +28,8 @@
#include "Map.h"
#include "StringBuilder.h"
#include "DbeFile.h"
+#include "DbeSession.h"
+#include "Dwarf.h"
typedef uint32_t Elf32_Word;
typedef uint32_t Elf64_Word;
@@ -83,55 +85,30 @@ struct S_Elf64_Dyn
} d_un;
};
+#ifndef DEBUGDIR
+#define DEBUGDIR "/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT1
+#define EXTRA_DEBUG_ROOT1 "/usr/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT2
+#define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
+#endif
-// Symbol table
-typedef struct
-{
- Elf32_Word st_name;
- Elf32_Addr st_value;
- Elf32_Word st_size;
- unsigned char st_info; /* bind, type: ELF_32_ST_... */
- unsigned char st_other;
- Elf32_Half st_shndx; /* SHN_... */
-} Elf32_Sym;
-
-typedef struct
-{
- Elf64_Word st_name;
- unsigned char st_info; /* bind, type: ELF_64_ST_... */
- unsigned char st_other;
- Elf64_Half st_shndx; /* SHN_... */
- Elf64_Addr st_value;
- Elf64_Xword st_size;
-} Elf64_Sym;
-
-
-// Relocation
-typedef struct
-{
- Elf32_Addr r_offset;
- Elf32_Word r_info; /* sym, type: ELF32_R_... */
-} Elf32_Rel;
-
-typedef struct
-{
- Elf32_Addr r_offset;
- Elf32_Word r_info; /* sym, type: ELF32_R_... */
- Elf32_Sword r_addend;
-} Elf32_Rela;
-
-typedef struct
-{
- Elf64_Addr r_offset;
- Elf64_Xword r_info; /* sym, type: ELF64_R_... */
-} Elf64_Rel;
+static const char *debug_dirs[] = {
+ DEBUGDIR, EXTRA_DEBUG_ROOT1, EXTRA_DEBUG_ROOT2, "."
+};
-typedef struct
+template<> void Vector<asymbol *>::dump (const char *msg)
{
- Elf64_Addr r_offset;
- Elf64_Xword r_info; /* sym, type: ELF64_R_... */
- Elf64_Sxword r_addend;
-} Elf64_Rela;
+ Dprintf (1, NTXT ("\nFile: %s Vector<asymbol *> [%ld]\n"),
+ msg ? msg : "NULL", (long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ asymbol *sym = get (i);
+ Dprintf (1, " %3ld %s\n", i, sym->name);
+ }
+}
int Elf::bfd_status = -1;
@@ -149,6 +126,8 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
ancillary_files = NULL;
elfSymbols = NULL;
gnu_debug_file = NULL;
+ gnu_debugalt_file = NULL;
+ sections = NULL;
dbeFile = NULL;
abfd = NULL;
bfd_symcnt = -1;
@@ -196,23 +175,13 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
}
status = ELF_ERR_NONE;
-#if ARCH(SPARC)
- need_swap_endian = is_Intel ();
-#else
- need_swap_endian = !is_Intel ();
-#endif
-
+ need_swap_endian = DbeSession::is_bigendian () != bfd_big_endian (abfd);
analyzerInfo = 0;
- SUNW_ldynsym = 0;
- gnuLink = 0;
stab = 0;
- stabStr = 0;
stabIndex = 0;
stabIndexStr = 0;
stabExcl = 0;
stabExclStr = 0;
- symtab = 0;
- dynsym = 0;
info = 0;
plt = 0;
dwarf = false;
@@ -234,20 +203,12 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
stabExcl = sec;
else if (streq (name, NTXT (".stab.exclstr")))
stabExclStr = sec;
- else if (streq (name, NTXT (".gnu_debuglink")))
- gnuLink = sec;
else if (streq (name, NTXT (".__analyzer_info")))
analyzerInfo = sec;
else if (streq (name, NTXT (".info")))
info = true;
else if (streq (name, NTXT (".plt")))
plt = sec;
- else if (streq (name, NTXT (".SUNW_ldynsym")))
- SUNW_ldynsym = sec;
- else if (streq (name, NTXT (".dynsym")))
- dynsym = sec;
- else if (streq (name, NTXT (".symtab")))
- symtab = sec;
else if (strncmp (name, NTXT (".debug"), 6) == 0)
dwarf = true;
}
@@ -276,6 +237,12 @@ Elf::~Elf ()
}
free (data);
}
+ if (sections)
+ {
+ for (int i = 0; i < (int) ehdrp->e_shnum; i++)
+ delete sections[i];
+ free (sections);
+ }
if (ancillary_files)
{
ancillary_files->destroy ();
@@ -283,6 +250,7 @@ Elf::~Elf ()
}
delete elfSymbols;
delete gnu_debug_file;
+ delete gnu_debugalt_file;
delete dbeFile;
delete synthsym;
free (bfd_sym);
@@ -405,9 +373,36 @@ Elf::get_sec_name (unsigned int sec)
return elf_strptr (ehdrp->e_shstrndx, shdr->sh_name);
}
+DwrSec *
+Elf::get_dwr_section (const char *sec_name)
+{
+ int sec_num = elf_get_sec_num (sec_name);
+ if (sec_num > 0)
+ {
+ if (sections == NULL)
+ {
+ sections = (DwrSec **) xmalloc (ehdrp->e_shnum * sizeof (DwrSec *));
+ for (int i = 0; i < (int) ehdrp->e_shnum; i++)
+ sections[i] = NULL;
+ }
+ if (sections[sec_num] == NULL)
+ {
+ Elf_Data *elfData = elf_getdata (sec_num);
+ if (elfData)
+ sections[sec_num] = new DwrSec ((unsigned char *) elfData->d_buf,
+ elfData->d_size, need_swap_endian,
+ elf_getclass () == ELFCLASS32);
+ }
+ return sections[sec_num];
+ }
+ return NULL;
+}
+
Elf_Data *
Elf::elf_getdata (unsigned int sec)
{
+ if (sec == 0)
+ return NULL;
if (data == NULL)
{
data = (Elf_Data **) xmalloc (ehdrp->e_shnum * sizeof (Elf_Data *));
@@ -572,50 +567,6 @@ Elf::elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic)
return asym;
}
-Elf_Internal_Rela *
-Elf::elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst)
-{
- if (dst == NULL || edta == NULL || edta->d_buf == NULL)
- return NULL;
- if (elf_getclass () == ELFCLASS32)
- {
- Elf32_Rel *rel = ((Elf32_Rel *) edta->d_buf) + ndx;
- dst->r_offset = decode (rel->r_offset);
- dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rel->r_info)),
- ELF32_R_TYPE (decode (rel->r_info)));
- }
- else
- {
- Elf64_Rel *rel = ((Elf64_Rel *) edta->d_buf) + ndx;
- dst->r_offset = decode (rel->r_offset);
- dst->r_info = decode (rel->r_info);
- }
- return dst;
-}
-
-Elf_Internal_Rela *
-Elf::elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst)
-{
- if (dst == NULL || edta == NULL || edta->d_buf == NULL)
- return NULL;
- if (elf_getclass () == ELFCLASS32)
- {
- Elf32_Rela *rela = ((Elf32_Rela *) edta->d_buf) + ndx;
- dst->r_offset = decode (rela->r_offset);
- dst->r_addend = decode (rela->r_addend);
- dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rela->r_info)),
- ELF32_R_TYPE (decode (rela->r_info)));
- }
- else
- {
- Elf64_Rela *rela = ((Elf64_Rela *) edta->d_buf) + ndx;
- dst->r_offset = decode (rela->r_offset);
- dst->r_addend = decode (rela->r_addend);
- dst->r_info = decode (rela->r_info);
- }
- return dst;
-}
-
Elf64_Ancillary *
Elf::elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst)
{
@@ -676,25 +627,54 @@ Elf::get_related_file (const char *lo_name, const char *nm)
return NULL;
}
-Elf *
-Elf::find_ancillary_files (char *lo_name)
+static char *
+find_file (char *(bfd_func) (bfd *, const char *), bfd *abfd)
{
- // read the .gnu_debuglink and .SUNW_ancillary seections
- if (gnu_debug_file)
- return gnu_debug_file;
- unsigned int sec = elf_get_sec_num (NTXT (".gnu_debuglink"));
- if (sec > 0)
+ char *fnm = NULL;
+ for (size_t i = 0; i < ARR_SIZE (debug_dirs); i++)
+ {
+ fnm = bfd_func (abfd, debug_dirs[i]);
+ if (fnm)
+ break;
+ }
+ Dprintf (DUMP_DWARFLIB, "FOUND: gnu_debug_file: %s --> %s\n",
+ abfd->filename, fnm);
+ return fnm;
+}
+
+void
+Elf::find_gnu_debug_files ()
+{
+ char *fnm;
+ if (gnu_debug_file == NULL)
{
- Elf_Data *dp = elf_getdata (sec);
- if (dp)
+ fnm = find_file (bfd_follow_gnu_debuglink, abfd);
+ if (fnm)
{
- gnu_debug_file = get_related_file (lo_name, (char *) (dp->d_buf));
+ gnu_debug_file = Elf::elf_begin (fnm);
+ free (fnm);
if (gnu_debug_file)
- return gnu_debug_file;
+ gnu_debug_file->find_gnu_debug_files ();
+ }
+ }
+ if (gnu_debugalt_file == NULL)
+ {
+ fnm = find_file (bfd_follow_gnu_debugaltlink, abfd);
+ if (fnm)
+ {
+ gnu_debugalt_file = Elf::elf_begin (fnm);
+ free (fnm);
}
}
+}
- sec = elf_get_sec_num (NTXT (".SUNW_ancillary"));
+void
+Elf::find_ancillary_files (const char *lo_name)
+{
+ // read the .SUNW_ancillary section
+ if (ancillary_files != NULL)
+ return;
+ unsigned int sec = elf_get_sec_num (".SUNW_ancillary");
if (sec > 0)
{
Elf_Internal_Shdr *shdr = get_shdr (sec);
@@ -755,7 +735,6 @@ Elf::find_ancillary_files (char *lo_name)
}
}
}
- return NULL;
}
void
@@ -828,6 +807,8 @@ Elf::get_funcname_in_plt (uint64_t pc)
for (long i = 0; i < bfd_synthcnt; i++)
synthsym->append (bfd_synthsym + i);
synthsym->sort (cmp_sym_addr);
+ if (DUMP_ELF_SYM)
+ synthsym->dump (get_location ());
}
asymbol sym, *symp = &sym;
diff --git a/gprofng/src/Elf.h b/gprofng/src/Elf.h
index b324c39..2d227f7 100644
--- a/gprofng/src/Elf.h
+++ b/gprofng/src/Elf.h
@@ -32,13 +32,12 @@
class Symbol;
class DbeFile;
+class DwrSec;
template <class ITEM> class Vector;
template <typename Key_t, typename Value_t> class Map;
-#define GELF_R_SYM(info) ((info)>>32)
#define GELF_ST_TYPE(info) ((info) & 0xf)
#define GELF_ST_BIND(info) ((info) >> 4)
-#define GELF_R_TYPE(info) ((((uint64_t)(info))<<56)>>56)
#define SHF_SUNW_ABSENT 0x00200000 /* section data not present */
#define SEC_DECOMPRESSED 0x00400000 /* bfd allocated this memory */
@@ -94,10 +93,15 @@ public:
char *elf_strptr (unsigned int sec, uint64_t off);
long elf_getSymCount (bool is_dynamic);
asymbol *elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic);
- Elf_Internal_Rela *elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst);
- Elf_Internal_Rela *elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst);
Elf64_Ancillary *elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst);
- Elf *find_ancillary_files (char *lo_name); // read the .gnu_debuglink and .SUNW_ancillary seections
+
+ // read the .SUNW_ancillary section
+ void find_ancillary_files (const char *lo_name);
+
+ // read the .gnu_debuglink and .gnu_debugaltlink sections
+ void find_gnu_debug_files ();
+
+ DwrSec *get_dwr_section (const char *sec_name); // Used in Dwarf reader
const char *get_funcname_in_plt (uint64_t pc);
char *get_location ();
char *dump ();
@@ -130,9 +134,10 @@ public:
Elf_status status;
Vector<Elf*> *ancillary_files;
Elf *gnu_debug_file;
+ Elf *gnu_debugalt_file; // if the .gun_debugaltlink section presents
DbeFile *dbeFile;
Map<const char*, Symbol*> *elfSymbols;
- unsigned int gnuLink, analyzerInfo, SUNW_ldynsym, stab, stabStr, symtab, dynsym;
+ unsigned int analyzerInfo, stab, stabStr;
unsigned int stabIndex, stabIndexStr, stabExcl, stabExclStr, info, plt;
bool dwarf;
@@ -143,6 +148,7 @@ protected:
int elf_datatype;
Elf_Internal_Ehdr *ehdrp;
Elf_Data **data;
+ DwrSec **sections;
bfd *abfd;
static int bfd_status;
long bfd_symcnt;
@@ -154,28 +160,4 @@ protected:
Vector <asymbol *> *synthsym;
};
-
-class ElfReloc
-{
-public:
- struct Sreloc
- {
- long long offset;
- long long value;
- int stt_type;
- };
-
- static ElfReloc *get_elf_reloc (Elf *elf, char *sec_name, ElfReloc *rlc);
- ElfReloc (Elf *_elf);
- ~ElfReloc ();
- long long get_reloc_addr (long long offset);
- void dump ();
- void dump_rela_debug_sec (int sec);
-
-private:
- Elf *elf;
- Vector<Sreloc *> *reloc;
- int cur_reloc_ind;
-};
-
#endif
diff --git a/gprofng/src/Experiment.cc b/gprofng/src/Experiment.cc
index 45550e8..2768927 100644
--- a/gprofng/src/Experiment.cc
+++ b/gprofng/src/Experiment.cc
@@ -541,10 +541,14 @@ Experiment::ExperimentHandler::startElement (char*, char*, char *qName, Attribut
exp->platform = RISCV;
else
exp->platform = Sparc;
- exp->need_swap_endian = (DbeSession::platform == Sparc) ?
- (exp->platform != Sparc) : (exp->platform == Sparc);
exp->architecture = xstrdup (str);
}
+ str = attrs->getValue (NTXT ("bigendian"));
+ if (str != NULL)
+ {
+ exp->bigendian = *str == '1';
+ exp->need_swap_endian = DbeSession::is_bigendian () != exp->bigendian;
+ }
str = attrs->getValue (NTXT ("pagesz"));
if (str != NULL)
exp->page_size = atoi (str);
@@ -1314,6 +1318,7 @@ Experiment::Experiment ()
exp_maj_version = 0;
exp_min_version = 0;
platform = Unknown;
+ bigendian = DbeSession::is_bigendian(); // can be changed in log.xml reading
wsize = Wnone;
page_size = 4096;
npages = 0;
@@ -6806,7 +6811,8 @@ Experiment::copy_file_to_common_archive (const char *name, const char *aname,
* @return 0 - success
*/
int
-Experiment::copy_file (char *name, char *aname, int hide_msg, char *common_archive, int relative_path)
+Experiment::copy_file (const char *name, const char *aname, int hide_msg,
+ const char *common_archive, int relative_path)
{
if (common_archive)
{
diff --git a/gprofng/src/Experiment.h b/gprofng/src/Experiment.h
index 2047a15..9a3d226 100644
--- a/gprofng/src/Experiment.h
+++ b/gprofng/src/Experiment.h
@@ -135,6 +135,7 @@ public:
// for current experiment, i.e. 8 for 32bit addresses
int broken; // If SP_JCMD_RUN line not seen
int obsolete; // If pointer file experiment detected
+ bool bigendian; // the experiment was created on a big_endian machine
bool hwc_default; // True if HW counters were enabled by default
int hwc_bogus; // Count of bogus HWC packets
int hwc_lost_int; // Count of packets reflecting lost interrupt
@@ -266,8 +267,8 @@ public:
static int copy_file_to_archive (const char *name, const char *aname, int hide_msg);
static int copy_file_to_common_archive (const char *name, const char *aname,
int hide_msg, const char *common_archive, int relative_path = 0);
- static int copy_file (char *name, char *aname, int hide_msg,
- char *common_archive = NULL, int relative_path = 0);
+ static int copy_file (const char *name, const char *aname, int hide_msg,
+ const char *common_archive = NULL, int relative_path = 0);
// get_raw_events()
// action: get unfiltered packets, loading them if required
diff --git a/gprofng/src/LoadObject.cc b/gprofng/src/LoadObject.cc
index 1ca6ab6..7b4bef2 100644
--- a/gprofng/src/LoadObject.cc
+++ b/gprofng/src/LoadObject.cc
@@ -20,6 +20,7 @@
#include "config.h"
#include <errno.h>
+#include <libgen.h>
#include "util.h"
#include "StringBuilder.h"
@@ -86,7 +87,6 @@ LoadObject::LoadObject (const char *loname)
size = 0;
type = SEG_UNKNOWN;
isReadStabs = false;
- need_swap_endian = false;
instHTable = new DbeInstr*[LO_InstHTableSize];
for (int i = 0; i < LO_InstHTableSize; i++)
instHTable[i] = NULL;
@@ -102,7 +102,6 @@ LoadObject::LoadObject (const char *loname)
noname = dbeSession->createUnknownModule (this);
modules->put (noname->get_name (), noname);
pathname = NULL;
- arch_name = NULL;
runTimePath = NULL;
objStabs = NULL;
firstExp = NULL;
@@ -135,7 +134,6 @@ LoadObject::~LoadObject ()
delete modules;
delete elf_lo;
free (pathname);
- free (arch_name);
free (runTimePath);
delete objStabs;
delete warnq;
@@ -167,45 +165,66 @@ LoadObject::get_elf ()
{
case Elf::ELF_ERR_CANT_OPEN_FILE:
append_msg (CMSG_ERROR, GTXT ("Cannot open ELF file `%s'"), fnm);
- break;
+ return NULL;
case Elf::ELF_ERR_BAD_ELF_FORMAT:
default:
append_msg (CMSG_ERROR, GTXT ("Cannot read ELF header of `%s'"),
fnm);
- break;
+ return NULL;
}
+ if (dbeFile->inArchive)
+ {
+ // Try to find gnu_debug and gnu debug_alt files in archive
+ char *nm = dbe_sprintf ("%s_debug", fnm);
+ elf_lo->gnu_debug_file = Elf::elf_begin (nm);
+ free (nm);
+ if (elf_lo->gnu_debug_file)
+ {
+ nm = dbe_sprintf ("%s_debug_alt", fnm);
+ elf_lo->gnu_debug_file->gnu_debugalt_file = Elf::elf_begin (nm);
+ free (nm);
+ }
+ nm = dbe_sprintf ("%s_alt", fnm);
+ elf_lo->gnu_debugalt_file = Elf::elf_begin (nm);
+ free (nm);
+ }
+ else if (checksum != 0 && elf_lo->elf_checksum () != 0 &&
+ checksum != elf_lo->elf_checksum ())
+ {
+ char *msg = dbe_sprintf (GTXT ("%s has an unexpected checksum value;"
+ "perhaps it was rebuilt. File ignored"),
+ dbeFile->get_location ());
+ commentq->append (new Emsg (CMSG_ERROR, msg));
+ delete msg;
+ delete elf_lo;
+ elf_lo = NULL;
+ return NULL;
+ }
+ elf_lo->find_gnu_debug_files ();
+ elf_lo->find_ancillary_files (get_pathname ());
}
return elf_lo;
}
Stabs *
-LoadObject::openDebugInfo (char *fname, Stabs::Stab_status *stp)
+LoadObject::openDebugInfo (Stabs::Stab_status *stp)
{
if (objStabs == NULL)
{
- if (fname == NULL)
- return NULL;
- objStabs = new Stabs (fname, get_pathname ());
- Stabs::Stab_status st = objStabs->get_status ();
- if ((st == Stabs::DBGD_ERR_NONE) && (checksum != 0))
+ Stabs::Stab_status st = Stabs::DBGD_ERR_BAD_ELF_LIB;
+ Elf *elf = get_elf ();
+ if (elf)
{
- Elf *elf = get_elf ();
- if (elf && (checksum != elf->elf_checksum ()))
+ objStabs = new Stabs (elf, get_pathname ());
+ st = objStabs->get_status ();
+ if (st != Stabs::DBGD_ERR_NONE)
{
- char *buf = dbe_sprintf (GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"),
- fname);
- commentq->append (new Emsg (CMSG_ERROR, buf));
- delete buf;
- st = Stabs::DBGD_ERR_CHK_SUM;
+ delete objStabs;
+ objStabs = NULL;
}
}
if (stp)
*stp = st;
- if (st != Stabs::DBGD_ERR_NONE)
- {
- delete objStabs;
- objStabs = NULL;
- }
}
return objStabs;
}
@@ -298,18 +317,21 @@ LoadObject::dump_functions (FILE *out)
if (fitem->alias && fitem->alias != fitem)
fprintf (out, "id %6llu, @0x%llx - %s == alias of '%s'\n",
(ull_t) fitem->id, (ull_t) fitem->img_offset,
- fitem->get_name (), fitem->alias->get_name ());
+ fitem->get_mangled_name (), fitem->alias->get_mangled_name ());
else
{
mname = fitem->module ? fitem->module->file_name : noname->file_name;
sname = fitem->getDefSrcName ();
- fprintf (out,
- "id %6llu, @0x%llx - 0x%llx [save 0x%llx] o-%lld sz-%lld %s (module = %s)",
- (ull_t) fitem->id, (ull_t) fitem->img_offset,
- (ull_t) (fitem->img_offset + fitem->size),
- (ull_t) fitem->save_addr, (ull_t) fitem->img_offset,
- (ll_t) fitem->size, fitem->get_name (), mname);
- if (sname && !streq (sname, mname))
+ fprintf (out, "id %6llu, @0x%llx-0x%llx sz-%lld", (ull_t) fitem->id,
+ (ull_t) fitem->img_offset,
+ (ull_t) (fitem->img_offset + fitem->size),
+ (ll_t) fitem->size);
+ if (fitem->save_addr != 0)
+ fprintf (out, " [save 0x%llx]", (ull_t) fitem->save_addr);
+ if (strcmp (fitem->get_mangled_name (), fitem->get_name ()) != 0)
+ fprintf (out, " [%s]", fitem->get_mangled_name ());
+ fprintf (out, " %s (module = %s)", fitem->get_name (), mname);
+ if (sname && strcmp (basename (sname), basename (mname)) != 0)
fprintf (out, " (Source = %s)", sname);
fprintf (out, "\n");
}
@@ -557,7 +579,7 @@ fixFuncAlias (Vector<Function*> *SymLst)
void
LoadObject::post_process_functions ()
{
- if (flags & SEG_FLAG_DYNAMIC || platform == Java)
+ if ((flags & SEG_FLAG_DYNAMIC) != 0 || platform == Java)
return;
char *msg = GTXT ("Processing Load Object Data");
@@ -723,21 +745,8 @@ LoadObject::read_stabs ()
delete msg;
return ARCHIVE_ERR_OPEN;
}
- else if (checksum != 0 && checksum != elf->elf_checksum ())
- {
- char *msg = dbe_sprintf (GTXT ("%s has an unexpected checksum value;"
- "perhaps it was rebuilt. File ignored"),
- dbeFile->get_location ());
- commentq->append (new Emsg (CMSG_ERROR, msg));
- delete msg;
- return ARCHIVE_ERR_OPEN;
- }
Stabs::Stab_status status = Stabs::DBGD_ERR_CANT_OPEN_FILE;
- char *location = dbeFile->get_location (true);
- if (location == NULL)
- return ARCHIVE_ERR_OPEN;
-
- if (openDebugInfo (location, &status))
+ if (openDebugInfo (&status))
{
status = objStabs->read_archive (this);
isRelocatable = objStabs->is_relocatable ();
diff --git a/gprofng/src/LoadObject.h b/gprofng/src/LoadObject.h
index 14dfe26..c93594b 100644
--- a/gprofng/src/LoadObject.h
+++ b/gprofng/src/LoadObject.h
@@ -117,13 +117,6 @@ public:
return pathname;
}
- void
- set_archname (char *aname)
- {
- free (arch_name);
- arch_name = aname;
- }
-
bool
is_relocatable ()
{
@@ -144,7 +137,7 @@ public:
Module *get_comparable_Module (Module *mod);
void append_module (Module *mod);
Elf *get_elf ();
- Stabs *openDebugInfo (char *fname, Stabs::Stab_status *stp = NULL);
+ Stabs *openDebugInfo (Stabs::Stab_status *stp = NULL);
Arch_status read_stabs ();
Arch_status sync_read_stabs ();
void post_process_functions ();
@@ -167,7 +160,6 @@ public:
unsigned int flags; // SEG_FLAG_*
bool isReadStabs;
- bool need_swap_endian;
int seg_idx; // for compatibility (ADDRESS)
seg_type type;
int64_t size; // size of loadobject in bytes
@@ -193,7 +185,6 @@ private:
char *pathname; // User name of object file
ino64_t inode; // inode number of segment file
bool isRelocatable; // is relocatable .o
- char *arch_name; // .archive name
Emsgqueue *warnq;
Emsgqueue *commentq;
Function **funcHTable; // hash table for functions
diff --git a/gprofng/src/Makefile.am b/gprofng/src/Makefile.am
index 0465cdb..f6d3f5d 100644
--- a/gprofng/src/Makefile.am
+++ b/gprofng/src/Makefile.am
@@ -78,6 +78,7 @@ CCSOURCES = \
Stabs.cc \
Stats_data.cc \
StringBuilder.cc \
+ Symbol.cc \
Table.cc \
QLParser.tab.cc \
dbe_collctrl.cc \
diff --git a/gprofng/src/Makefile.in b/gprofng/src/Makefile.in
index 9f07986..0cdd444 100644
--- a/gprofng/src/Makefile.in
+++ b/gprofng/src/Makefile.in
@@ -174,7 +174,7 @@ am__objects_1 = Application.lo BaseMetric.lo BaseMetricTreeNode.lo \
MemorySpace.lo Metric.lo MetricList.lo Module.lo Ovw_data.lo \
PRBTree.lo PathTree.lo PreviewExp.lo Print.lo \
SAXParserFactory.lo Sample.lo Settings.lo SourceFile.lo \
- Stabs.lo Stats_data.lo StringBuilder.lo Table.lo \
+ Stabs.lo Stats_data.lo StringBuilder.lo Symbol.lo Table.lo \
QLParser.tab.lo dbe_collctrl.lo i18n.lo parse.lo UserLabel.lo \
util.lo Dbe.lo
am__objects_2 = dbe_hwcdrv.lo dbe_hwcfuncs.lo dbe_hwctable.lo \
@@ -505,6 +505,7 @@ CCSOURCES = \
Stabs.cc \
Stats_data.cc \
StringBuilder.cc \
+ Symbol.cc \
Table.cc \
QLParser.tab.cc \
dbe_collctrl.cc \
@@ -777,6 +778,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Stabs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Stats_data.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StringBuilder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Symbol.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Table.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UserLabel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checks.Po@am__quote@
diff --git a/gprofng/src/Module.cc b/gprofng/src/Module.cc
index a62d3e8..55091ad 100644
--- a/gprofng/src/Module.cc
+++ b/gprofng/src/Module.cc
@@ -131,7 +131,7 @@ Stabs *
Module::openDebugInfo ()
{
setFile ();
- objStabs = loadobject->openDebugInfo (disPath);
+ objStabs = loadobject->openDebugInfo ();
return objStabs;
}
diff --git a/gprofng/src/Stabs.cc b/gprofng/src/Stabs.cc
index b98ac28..116316e 100644
--- a/gprofng/src/Stabs.cc
+++ b/gprofng/src/Stabs.cc
@@ -35,10 +35,7 @@
#include "StringBuilder.h"
#include "DbeFile.h"
#include "StringMap.h"
-
-#define DISASM_REL_NONE 0 /* symtab search only */
-#define DISASM_REL_ONLY 1 /* relocation search only */
-#define DISASM_REL_TARG 2 /* relocatoin then symtab */
+#include "Symbol.h"
///////////////////////////////////////////////////////////////////////////////
// class StabReader
@@ -62,105 +59,6 @@ private:
int StabEntSize;
};
-///////////////////////////////////////////////////////////////////////////////
-// class Symbol
-
-class Symbol
-{
-public:
- Symbol (Vector<Symbol*> *vec = NULL);
-
- ~Symbol ()
- {
- free (name);
- }
-
- inline Symbol *
- cardinal ()
- {
- return alias ? alias : this;
- }
-
- static void dump (Vector<Symbol*> *vec, char*msg);
-
- Function *func;
- Sp_lang_code lang_code;
- uint64_t value; // st_value used in sym_name()
- uint64_t save;
- int64_t size;
- uint64_t img_offset; // image offset in the ELF file
- char *name;
- Symbol *alias;
- int local_ind;
- int flags;
- bool defined;
-};
-
-Symbol::Symbol (Vector<Symbol*> *vec)
-{
- func = NULL;
- lang_code = Sp_lang_unknown;
- value = 0;
- save = 0;
- size = 0;
- img_offset = 0;
- name = NULL;
- alias = NULL;
- local_ind = -1;
- flags = 0;
- defined = false;
- if (vec)
- vec->append (this);
-}
-
-void
-Symbol::dump (Vector<Symbol*> *vec, char*msg)
-{
- if (!DUMP_ELF_SYM || vec == NULL || vec->size () == 0)
- return;
- printf (NTXT ("======= Symbol::dump: %s =========\n"
- " value | img_offset | flags|local_ind|\n"), msg);
- for (int i = 0; i < vec->size (); i++)
- {
- Symbol *sp = vec->fetch (i);
- printf (NTXT (" %3d %8lld |0x%016llx |%5d |%8d |%s\n"),
- i, (long long) sp->value, (long long) sp->img_offset, sp->flags,
- sp->local_ind, sp->name ? sp->name : NTXT ("NULL"));
- }
- printf (NTXT ("\n===== END of Symbol::dump: %s =========\n\n"), msg);
-}
-
-// end of class Symbol
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// class Reloc
-class Reloc
-{
-public:
- Reloc ();
- ~Reloc ();
- uint64_t type;
- uint64_t value;
- uint64_t addend;
- char *name;
-};
-
-Reloc::Reloc ()
-{
- type = 0;
- value = 0;
- addend = 0;
- name = NULL;
-}
-
-Reloc::~Reloc ()
-{
- free (name);
-}
-// end of class Reloc
-///////////////////////////////////////////////////////////////////////////////
-
enum
{
SYM_PLT = 1 << 0,
@@ -232,15 +130,6 @@ SymImgOffsetCmp (const void *a, const void *b)
(item1->img_offset == item2->img_offset) ? SymNameCmp (a, b) : -1;
}
-static int
-RelValueCmp (const void *a, const void *b)
-{
- Reloc *item1 = *((Reloc **) a);
- Reloc *item2 = *((Reloc **) b);
- return (item1->value > item2->value) ? 1 :
- (item1->value == item2->value) ? 0 : -1;
-}
-
/* Remove all duplicate symbols which can be in SymLst. The
duplication is due to processing of both static and dynamic
symbols. This function is called before computing symbol
@@ -252,7 +141,6 @@ Stabs::removeDupSyms ()
long ind, i, last;
Symbol *symA, *symB;
SymLst->sort (SymImgOffsetCmp);
- dump ();
last = 0;
ind = SymLst->size ();
@@ -275,42 +163,26 @@ Stabs::removeDupSyms ()
SymLst->truncate (last);
}
-Stabs *
-Stabs::NewStabs (char *_path, char *lo_name)
-{
- Stabs *stabs = new Stabs (_path, lo_name);
- if (stabs->status != Stabs::DBGD_ERR_NONE)
- {
- delete stabs;
- return NULL;
- }
- return stabs;
-}
-
-Stabs::Stabs (char *_path, char *_lo_name)
+Stabs::Stabs (Elf *elf, char *_lo_name)
{
- path = dbe_strdup (_path);
+ elfDis = elf;
+ elfDbg = elf->gnu_debug_file ? elf->gnu_debug_file : elf;
+ path = dbe_strdup (elf->get_location ());
lo_name = dbe_strdup (_lo_name);
SymLstByName = NULL;
pltSym = NULL;
SymLst = new Vector<Symbol*>;
- RelLst = new Vector<Reloc*>;
- RelPLTLst = new Vector<Reloc*>;
LocalLst = new Vector<Symbol*>;
LocalFile = new Vector<char*>;
LocalFileIdx = new Vector<int>;
last_PC_to_sym = NULL;
dwarf = NULL;
- elfDbg = NULL;
- elfDis = NULL;
stabsModules = NULL;
textsz = 0;
wsize = Wnone;
st_check_symtab = false;
status = DBGD_ERR_NONE;
- if (openElf (false) == NULL)
- return;
switch (elfDis->elf_getclass ())
{
case ELFCLASS32:
@@ -320,6 +192,31 @@ Stabs::Stabs (char *_path, char *_lo_name)
wsize = W64;
break;
}
+ switch (elfDis->elf_getehdr ()->e_machine)
+ {
+ case EM_SPARC:
+ platform = Sparc;
+ break;
+ case EM_SPARC32PLUS:
+ platform = Sparcv8plus;
+ break;
+ case EM_SPARCV9:
+ platform = Sparcv9;
+ break;
+ case EM_386:
+ // case EM_486:
+ platform = Intel;
+ break;
+ case EM_X86_64:
+ platform = Amd64;
+ break;
+ case EM_AARCH64:
+ platform = Aarch64;
+ break;
+ default:
+ platform = Unknown;
+ break;
+ }
isRelocatable = elfDis->elf_getehdr ()->e_type == ET_REL;
for (unsigned int pnum = 0; pnum < elfDis->elf_getehdr ()->e_phnum; pnum++)
{
@@ -341,10 +238,7 @@ Stabs::~Stabs ()
{
delete SymLstByName;
Destroy (SymLst);
- Destroy (RelLst);
- Destroy (RelPLTLst);
Destroy (LocalFile);
- delete elfDis;
delete dwarf;
delete LocalLst;
delete LocalFileIdx;
@@ -354,90 +248,11 @@ Stabs::~Stabs ()
}
Elf *
-Stabs::openElf (char *fname, Stab_status &st)
-{
- Elf::Elf_status elf_status;
- Elf *elf = Elf::elf_begin (fname, &elf_status);
- if (elf == NULL)
- {
- switch (elf_status)
- {
- case Elf::ELF_ERR_CANT_OPEN_FILE:
- case Elf::ELF_ERR_CANT_MMAP:
- case Elf::ELF_ERR_BIG_FILE:
- st = DBGD_ERR_CANT_OPEN_FILE;
- break;
- case Elf::ELF_ERR_BAD_ELF_FORMAT:
- default:
- st = DBGD_ERR_BAD_ELF_FORMAT;
- break;
- }
- return NULL;
- }
- if (elf->elf_version (EV_CURRENT) == EV_NONE)
- {
- // ELF library out of date
- delete elf;
- st = DBGD_ERR_BAD_ELF_LIB;
- return NULL;
- }
-
- Elf_Internal_Ehdr *ehdrp = elf->elf_getehdr ();
- if (ehdrp == NULL)
- {
- // check machine
- delete elf;
- st = DBGD_ERR_BAD_ELF_FORMAT;
- return NULL;
- }
- switch (ehdrp->e_machine)
- {
- case EM_SPARC:
- platform = Sparc;
- break;
- case EM_SPARC32PLUS:
- platform = Sparcv8plus;
- break;
- case EM_SPARCV9:
- platform = Sparcv9;
- break;
- case EM_386:
- // case EM_486:
- platform = Intel;
- break;
- case EM_X86_64:
- platform = Amd64;
- break;
- case EM_AARCH64:
- platform = Aarch64;
- break;
- default:
- platform = Unknown;
- break;
- }
- return elf;
-}
-
-Elf *
Stabs::openElf (bool dbg_info)
{
- if (status != DBGD_ERR_NONE)
- return NULL;
- if (elfDis == NULL)
- {
- elfDis = openElf (path, status);
- if (elfDis == NULL)
- return NULL;
- }
- if (!dbg_info)
- return elfDis;
- if (elfDbg == NULL)
- {
- elfDbg = elfDis->find_ancillary_files (lo_name);
- if (elfDbg == NULL)
- elfDbg = elfDis;
- }
- return elfDbg;
+ if (dbg_info)
+ return elfDbg;
+ return elfDis;
}
bool
@@ -458,42 +273,6 @@ Stabs::read_symbols (Vector<Function*> *functions)
return true;
}
-char *
-Stabs::sym_name (uint64_t target, uint64_t instr, int flag)
-{
- long index;
- if (flag == DISASM_REL_ONLY || flag == DISASM_REL_TARG)
- {
- Reloc *relptr = new Reloc;
- relptr->value = instr;
- index = RelLst->bisearch (0, -1, &relptr, RelValueCmp);
- if (index >= 0)
- {
- delete relptr;
- return RelLst->fetch (index)->name;
- }
- if (!is_relocatable ())
- {
- relptr->value = target;
- index = RelPLTLst->bisearch (0, -1, &relptr, RelValueCmp);
- if (index >= 0)
- {
- delete relptr;
- return RelPLTLst->fetch (index)->name;
- }
- }
- delete relptr;
- }
- if (flag == DISASM_REL_NONE || flag == DISASM_REL_TARG || !is_relocatable ())
- {
- Symbol *sptr;
- sptr = map_PC_to_sym (target);
- if (sptr && sptr->value == target)
- return sptr->name;
- }
- return NULL;
-}
-
Symbol *
Stabs::map_PC_to_sym (uint64_t pc)
{
@@ -1706,7 +1485,8 @@ Stabs::fixSymtabAlias ()
for (; i < k; i++)
{
sym = SymLst->fetch (i);
- sym->alias = bestAlias;
+ if (sym != bestAlias)
+ sym->alias = bestAlias;
sym->size = maxSize;
}
i--;
@@ -1761,10 +1541,12 @@ Stabs::readSymSec (Elf *elf, bool is_dynamic)
if (asym == NULL)
break;
const char *st_name = bfd_asymbol_name (asym);
+ if (st_name == NULL)
+ continue;
switch (GELF_ST_TYPE (Sym.st_info))
{
case STT_FUNC:
- if (Sym.st_size == 0)
+ if (Sym.st_size == 0 || ELF_ST_BIND (Sym.st_info) == STB_WEAK)
break;
if (Sym.st_shndx == 0)
{
@@ -1839,8 +1621,7 @@ Stabs::readSymSec (Elf *elf, bool is_dynamic)
fixSymtabAlias ();
SymLst->sort (SymValueCmp);
get_save_addr (elf->need_swap_endian);
- dump ();
-}//check_Symtab
+}
void
Stabs::get_save_addr (bool need_swap_endian)
@@ -2281,57 +2062,6 @@ Stabs::append_Function (Module *module, char *fname)
return func;
}
-Function *
-Stabs::append_Function (Module *module, char *linkerName, uint64_t pc)
-{
- Dprintf (DEBUG_STABS, NTXT ("Stabs::append_Function: module=%s linkerName=%s pc=0x%llx\n"),
- STR (module->get_name ()), STR (linkerName), (unsigned long long) pc);
- long i;
- Symbol *sitem = NULL, *sp;
- Function *func;
- sp = new Symbol;
- if (pc)
- {
- sp->value = pc;
- i = SymLst->bisearch (0, -1, &sp, SymFindCmp);
- if (i != -1)
- sitem = SymLst->fetch (i);
- }
-
- if (!sitem && linkerName)
- {
- if (SymLstByName == NULL)
- {
- SymLstByName = SymLst->copy ();
- SymLstByName->sort (SymNameCmp);
- }
- sp->name = linkerName;
- i = SymLstByName->bisearch (0, -1, &sp, SymNameCmp);
- sp->name = NULL;
- if (i != -1)
- sitem = SymLstByName->fetch (i);
- }
- delete sp;
-
- if (!sitem)
- return NULL;
- if (sitem->alias)
- sitem = sitem->alias;
- if (sitem->func)
- return sitem->func;
-
- sitem->func = func = dbeSession->createFunction ();
- func->img_fname = path;
- func->img_offset = sitem->img_offset;
- func->save_addr = sitem->save;
- func->size = sitem->size;
- func->module = module;
- func->set_name (sitem->name); //XXXX ?? Now call it to set obj->name
- module->functions->append (func);
- module->loadobject->functions->append (func);
- return func;
-}// Stabs::append_Function
-
Dwarf *
Stabs::openDwarf ()
{
@@ -2339,6 +2069,7 @@ Stabs::openDwarf ()
{
dwarf = new Dwarf (this);
check_Symtab ();
+ dump();
}
return dwarf;
}
@@ -2363,8 +2094,8 @@ Stabs::dump ()
printf (" %3d: %5d '%s'\n", i, LocalFileIdx->fetch (i),
LocalFile->fetch (i));
}
- Symbol::dump (SymLst, NTXT ("SymLst"));
- Symbol::dump (LocalLst, NTXT ("LocalLst"));
+ SymLst->dump ("SymLst");
+ LocalLst->dump ("LocalLst");
printf (NTXT ("\n===== END of Stabs::dump: %s =========\n\n"),
path ? path : NTXT ("NULL"));
}
diff --git a/gprofng/src/Stabs.h b/gprofng/src/Stabs.h
index d34741f..cd10c25 100644
--- a/gprofng/src/Stabs.h
+++ b/gprofng/src/Stabs.h
@@ -40,7 +40,6 @@ class ComC;
class Elf;
class Dwarf;
class Symbol;
-class Reloc;
struct cpf_stabs_t;
class SourceFile;
template <typename Key_t, typename Value_t> class Map;
@@ -77,8 +76,7 @@ class Stabs {
DBGD_ERR_CHK_SUM
};
- static Stabs *NewStabs(char *_path, char *lo_name);
- Stabs(char *_path, char *_lo_name);
+ Stabs(Elf *elf, char *_lo_name);
~Stabs();
bool is_relocatable(){ return isRelocatable; }
@@ -86,12 +84,12 @@ class Stabs {
Platform_t get_platform() { return platform; }
WSize_t get_class() { return wsize;}
Stab_status get_status() { return status;}
+ Vector<Symbol *> *get_symbols() { return SymLst; }
Stab_status read_stabs(ino64_t srcInode, Module *module, Vector<ComC*> *comComs, bool readDwarf = false);
Stab_status read_archive(LoadObject *lo);
bool read_symbols(Vector<Function*> *functions);
uint64_t mapOffsetToAddress(uint64_t img_offset);
- char *sym_name(uint64_t target, uint64_t instr, int flag);
Elf *openElf (bool dbg_info = false);
void read_hwcprof_info(Module *module);
void dump();
@@ -101,7 +99,6 @@ class Stabs {
static Function *find_func(char *fname, Vector<Function*> *functions, bool fortran, bool inner_names=false);
Module *append_Module(LoadObject *lo, char *name, int lastMod = 0);
Function *append_Function(Module *module, char *fname);
- Function *append_Function(Module *module, char *linkerName, uint64_t pc);
Function *map_PC_to_func(uint64_t pc, uint64_t &low_pc, Vector<Function*> *functions);
char *path; // path to the object file
char *lo_name; // User name of load object
@@ -135,13 +132,10 @@ class Stabs {
Symbol *pltSym;
Vector<Symbol*> *SymLst; // list of func symbols
Vector<Symbol*> *SymLstByName; // list of func symbols sorted by Name
- Vector<Reloc*> *RelLst; // list of text relocations
- Vector<Reloc*> *RelPLTLst; // list of PLT relocations
Vector<Symbol*> *LocalLst; // list of local func symbols
Vector<char*> *LocalFile; // list of local files
Vector<int> *LocalFileIdx; // start index in LocalLst
- Elf *openElf(char *fname, Stab_status &st);
Map<const char*, Symbol*> *get_elf_symbols();
Dwarf *dwarf;
diff --git a/gprofng/src/Symbol.cc b/gprofng/src/Symbol.cc
new file mode 100644
index 0000000..8cc578f
--- /dev/null
+++ b/gprofng/src/Symbol.cc
@@ -0,0 +1,218 @@
+/* Copyright (C) 2025 Free Software Foundation, Inc.
+ Contributed by Oracle.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+
+#include "DbeSession.h"
+#include "Function.h"
+#include "LoadObject.h"
+#include "Module.h"
+#include "Symbol.h"
+
+
+template<> void Vector<Symbol *>::dump (const char *msg)
+{
+ if (msg == NULL)
+ msg = "#";
+ Dprintf (1, NTXT ("\n%s Vector<Symbol *> [%lld]\n"), msg, (long long) size ());
+ if (size () > 0)
+ Dprintf (1, " value | img_offset | size | flags|local_ind|\n");
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ Symbol *sp = get (i);
+ Dprintf (1, " %3ld ", i);
+ sp->dump ();
+ }
+ if (size () > 0)
+ Dprintf (1, "===== END of Symbol::dump: %s =========\n\n", msg);
+}
+
+void
+Symbol::dump (const char *msg)
+{
+ if (msg)
+ Dprintf (1, "%s\n", msg);
+ Dprintf (1, "%8lld |%11lld |%6d |%5d |%8d |%s\n", (long long) value,
+ (long long) img_offset, (int) size, flags, local_ind,
+ name ? name : "NULL");
+}
+
+Symbol::Symbol (Vector<Symbol*> *vec)
+{
+ func = NULL;
+ lang_code = Sp_lang_unknown;
+ value = 0;
+ save = 0;
+ size = 0;
+ img_offset = 0;
+ name = NULL;
+ alias = NULL;
+ local_ind = -1;
+ flags = 0;
+ defined = false;
+ if (vec)
+ vec->append (this);
+}
+
+Symbol::~Symbol ()
+{
+ free (name);
+}
+
+static int
+cmpSym (const void *a, const void *b)
+{
+ Symbol *item1 = *((Symbol **) a);
+ Symbol *item2 = *((Symbol **) b);
+ return (item1->value > item2->value) ? 1 :
+ (item1->value == item2->value) ? 0 : -1;
+}
+
+static int
+cmpSymName (const void *a, const void *b)
+{
+ Symbol *item1 = *((Symbol **) a);
+ Symbol *item2 = *((Symbol **) b);
+ return strcmp (item1->name, item2->name);
+}
+
+Symbol *
+Symbol::get_symbol (Vector<Symbol*> *syms, uint64_t pc)
+{
+ if (syms != NULL && pc != 0)
+ {
+ Symbol *sp = new Symbol;
+ sp->value = pc;
+ long i = syms->bisearch (0, -1, &sp, cmpSym);
+ delete sp;
+ if (i != -1)
+ return syms->get (i)->cardinal ();
+ }
+ return NULL;
+}
+
+Symbol *
+Symbol::get_symbol (Vector<Symbol*> *syms, char *linker_name)
+{
+ if (syms != NULL && linker_name != NULL)
+ {
+ Symbol *sp = new Symbol;
+ sp->name = linker_name;
+ long i = syms->bisearch (0, -1, &sp, cmpSymName);
+ sp->name = NULL;
+ delete sp;
+ if (i != -1)
+ return syms->get (i)->cardinal ();
+ }
+ return NULL;
+}
+
+Vector<Symbol *> *
+Symbol::sort_by_name (Vector<Symbol *> *syms)
+{
+ if (VecSize (syms) == 0)
+ return NULL;
+ Vector<Symbol *> *symbols = syms->copy ();
+ symbols->sort (cmpSymName);
+ return symbols;
+}
+
+Vector<Symbol *> *
+Symbol::find_symbols (Vector<Symbol*> *syms, Vector<Range *> *ranges,
+ Vector<Symbol *> *symbols)
+{
+ // 'syms' and 'ranges' must already be sorted.
+ // return symbols matched by 'ranges'
+ if (VecSize (syms) == 0 || VecSize (ranges) == 0)
+ return NULL;
+
+ // Use binary search to find a suitable index in 'syms'
+ int ind = 0;
+ uint64_t addr = ranges->get (0)->low;
+ for (int lo = 0, hi = syms->size (); lo < hi;)
+ {
+ int mid = (hi + lo) >> 1;
+ Symbol *sym = syms->get (mid);
+ if (sym->value == addr)
+ {
+ ind = mid;
+ break;
+ }
+ else if (sym->value > addr)
+ hi = mid - 1;
+ else
+ {
+ ind = mid;
+ lo = mid + 1;
+ }
+ }
+
+ for (int i = 0, r_sz = ranges->size (), sz = syms->size (); ind < sz; ind++)
+ {
+ Symbol *sym = syms->get (ind);
+ while (i < r_sz)
+ {
+ Range *r = ranges->get (i);
+ if (sym->value < r->low)
+ break;
+ if (sym->value <= r->high)
+ {
+ symbols->append (sym);
+ break;
+ }
+ i++;
+ }
+ if (i >= r_sz)
+ break;
+ }
+ return symbols;
+}
+
+/* Create and append a new function to the 'module'.
+ * Copy attributes (size, name, etc) from Simbol, */
+Function *
+Symbol::createFunction (Module *module)
+{
+ if (func)
+ return func;
+ func = dbeSession->createFunction ();
+ func->img_fname = module->file_name;
+ func->img_offset = img_offset;
+ func->save_addr = save;
+ func->size = size;
+ func->module = module;
+ func->set_name (name);
+ module->functions->append (func);
+ module->loadobject->functions->append (func);
+ return func;
+}
+
+template<> void Vector<Range *>::dump (const char *msg)
+{
+ Dprintf (1, NTXT ("%s Vector<Range *> [%lld]\n"),
+ msg ? msg : "#", (long long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ Range *p = get (i);
+ Dprintf (1, "%3ld 0x%08llx 0x%08llx (%lld - %lld)\n", i,
+ (long long) p->low, (long long) p->high,
+ (long long) p->low, (long long) p->high);
+ }
+} \ No newline at end of file
diff --git a/gprofng/src/Symbol.h b/gprofng/src/Symbol.h
new file mode 100644
index 0000000..e9e0060
--- /dev/null
+++ b/gprofng/src/Symbol.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2025 Free Software Foundation, Inc.
+ Contributed by Oracle.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#ifndef _Symbol_h_
+#define _Symbol_h_
+
+class Function;
+class Module;
+
+class Range
+{
+public:
+ Range (uint64_t _low, uint64_t _high)
+ {
+ low = _low;
+ high = _high;
+ }
+
+ inline bool
+ inside (uint64_t val)
+ {
+ return val >= low && val < high;
+ };
+
+ uint64_t low;
+ uint64_t high;
+};
+
+class Symbol
+{
+public:
+ Symbol (Vector<Symbol *> *vec = NULL);
+ ~Symbol ();
+
+ Symbol *
+ cardinal ()
+ {
+ return alias ? alias : this;
+ }
+
+ // Find symbols in 'syms' matched by 'ranges'.
+ static Vector<Symbol *> *find_symbols (Vector<Symbol *> *syms,
+ Vector<Range *> *ranges, Vector<Symbol *> *symbols = NULL);
+ static Vector<Symbol *> *sort_by_name (Vector<Symbol *> *syms);
+
+ // Find symbol in CU corresponding to pc or linker_name.
+ static Symbol *get_symbol (Vector<Symbol *> *syms, uint64_t pc);
+ static Symbol *get_symbol (Vector<Symbol *> *syms, char *linker_name);
+
+ // Create and append a new function to the 'module'.
+ // Copy attributes (size, name, etc) from Symbol,
+ Function *createFunction(Module *module);
+ void dump (const char *msg = NULL);
+
+ Function *func;
+ Sp_lang_code lang_code;
+ uint64_t value;
+ uint64_t save;
+ int64_t size;
+ uint64_t img_offset; // image offset in the ELF file
+ char *name;
+ Symbol *alias;
+ int local_ind;
+ int flags;
+ bool defined;
+};
+#endif
diff --git a/gprofng/src/collect.h b/gprofng/src/collect.h
index 18ab564..3ce6b28 100644
--- a/gprofng/src/collect.h
+++ b/gprofng/src/collect.h
@@ -32,7 +32,6 @@ class Coll_Ctrl;
class Elf;
#define MAXLABELS 10 /* maximum number of -C arguments */
-#define STDEBUFSIZE 24000
enum { MAX_LD_PRELOAD_TYPES = 3 };
diff --git a/gprofng/src/envsets.cc b/gprofng/src/envsets.cc
index 30803aa..e92c017 100644
--- a/gprofng/src/envsets.cc
+++ b/gprofng/src/envsets.cc
@@ -31,16 +31,6 @@
#include "StringBuilder.h"
#include "Settings.h"
-#define STDEBUFSIZE 24000
-
-#define LIBGP_COLLECTOR "libgp-collector.so"
-#define GPROFNG_PRELOAD_LIBDIRS "GPROFNG_PRELOAD_LIBDIRS"
-#define SP_COLLECTOR_EXPNAME "SP_COLLECTOR_EXPNAME"
-#define SP_COLLECTOR_FOLLOW_SPEC "SP_COLLECTOR_FOLLOW_SPEC"
-#define SP_COLLECTOR_PARAMS "SP_COLLECTOR_PARAMS"
-#define SP_COLLECTOR_FOUNDER "SP_COLLECTOR_FOUNDER"
-#define SP_COLLECTOR_ORIGIN_COLLECT "SP_COLLECTOR_ORIGIN_COLLECT"
-
static const char *LD_AUDIT[] = {
// "LD_AUDIT", Do not set LD_AUDIT on Linux
NULL
diff --git a/gprofng/src/gp-archive.cc b/gprofng/src/gp-archive.cc
index 4e68336..2c15da8 100644
--- a/gprofng/src/gp-archive.cc
+++ b/gprofng/src/gp-archive.cc
@@ -140,7 +140,8 @@ er_archive::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-collect-app(1), gprofng-display-html(1), "
- "gprofng-display-src(1), gprofng-display-text(1)\n"));
+ "gprofng-display-src(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
exit (1);
}
@@ -356,25 +357,59 @@ er_archive::start (int argc, char *argv[])
}
lo->sync_read_stabs ();
Elf *elf = lo->get_elf ();
- if (elf && (lo->checksum != 0) && (lo->checksum != elf->elf_checksum ()))
+ if (elf == NULL)
{
if (!quiet)
- fprintf (stderr, GTXT ("gp-archive: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored\n"),
+ fprintf (stderr, GTXT ("gp-archive: Cannot open \"%s\"\n"),
df->get_location ());
+ Dprintf (DEBUG_ARCHIVE,
+ " loadObjs[%ld]: not found '%s'\n", i, df->get_location ());
+ continue;
+ }
+ else if (df->inArchive)
+ {
+ Dprintf (DEBUG_ARCHIVE,
+ " loadObjs[%ld]: inArchive=1 '%s'\n", i, df->get_name ());
continue;
}
- copy_files->append (df);
- if (elf)
+ else if (!mask_is_on (df->get_name ()))
+ {
+ Dprintf (DEBUG_ARCHIVE,
+ " loadObjs[%ld]: mask_is_on=0 '%s'\n", i, df->get_name ());
+ continue;
+ }
+ char *fnm = elf->get_location ();
+ char *anm = founder_exp->getNameInArchive (fnm);
+ archive_file (fnm, anm);
+
+ // archive gnu_debug and gnu_debugalt files
+ if (elf->gnu_debug_file)
{
- Elf *f = elf->find_ancillary_files (lo->get_pathname ());
- if (f)
- copy_files->append (f->dbeFile);
- for (long i1 = 0, sz1 = VecSize(elf->ancillary_files); i1 < sz1; i1++)
+ char *arch_nm = dbe_sprintf ("%s_debug", anm);
+ archive_file (elf->gnu_debug_file->get_location (), arch_nm);
+ free (arch_nm);
+ if (elf->gnu_debug_file->gnu_debugalt_file)
{
- Elf *ancElf = elf->ancillary_files->get (i1);
- copy_files->append (ancElf->dbeFile);
+ arch_nm = dbe_sprintf ("%s_debug_alt", anm);
+ archive_file (elf->gnu_debug_file->gnu_debugalt_file->get_location (), arch_nm);
+ free (arch_nm);
}
}
+ if (elf->gnu_debugalt_file)
+ {
+ char *arch_nm = dbe_sprintf ("%s_alt", anm);
+ archive_file (elf->gnu_debugalt_file->get_location (), arch_nm);
+ free (arch_nm);
+ }
+ free (anm);
+
+ elf->find_ancillary_files (lo->get_pathname ());
+ for (long i1 = 0, sz1 = VecSize (elf->ancillary_files); i1 < sz1; i1++)
+ {
+ Elf *ancElf = elf->ancillary_files->get (i1);
+ copy_files->append (ancElf->dbeFile);
+ }
+
Vector<Module*> *modules = lo->seg_modules;
for (long i1 = 0, sz1 = VecSize(modules); i1 < sz1; i1++)
{
@@ -468,7 +503,7 @@ er_archive::start (int argc, char *argv[])
int res = founder_exp->copy_file (fnm, anm, quiet, common_archive_dir, use_relative_path);
if (0 == res) // file successfully archived
df->inArchive = 1;
- delete anm;
+ free (anm);
}
delete copy_files;
@@ -489,6 +524,15 @@ er_archive::start (int argc, char *argv[])
}
int
+er_archive::archive_file (const char *from, const char *to)
+{
+ if (force)
+ unlink (to);
+ return Experiment::copy_file (from, to, quiet, common_archive_dir,
+ use_relative_path);
+}
+
+int
er_archive::check_args (int argc, char *argv[])
{
int opt;
diff --git a/gprofng/src/gp-archive.h b/gprofng/src/gp-archive.h
index 41fb4b2..3b9d0ee 100644
--- a/gprofng/src/gp-archive.h
+++ b/gprofng/src/gp-archive.h
@@ -47,6 +47,7 @@ public:
private:
void usage ();
int check_args (int argc, char *argv[]);
+ int archive_file (const char *from, const char *to);
int clean_old_archive (char *expname, ArchiveExp *founder_exp);
int mask_is_on (const char *str);
void check_env_var ();
diff --git a/gprofng/src/gp-collect-app.cc b/gprofng/src/gp-collect-app.cc
index bf146d9..695c4af 100644
--- a/gprofng/src/gp-collect-app.cc
+++ b/gprofng/src/gp-collect-app.cc
@@ -44,8 +44,6 @@
#include "collect.h"
#include "StringBuilder.h"
-#define SP_COLLECTOR_FOUNDER "SP_COLLECTOR_FOUNDER"
-
extern char **environ;
static volatile int interrupt = 0;
@@ -1481,7 +1479,8 @@ collect::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-archive(1), gprofng-display-html(1), "
- "gpgprofng-display-src(1), gprofng-display-text(1)\n"));
+ "gpgprofng-display-src(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
}
void
diff --git a/gprofng/src/gp-display-src.cc b/gprofng/src/gp-display-src.cc
index 7eb6b33..5475f27 100644
--- a/gprofng/src/gp-display-src.cc
+++ b/gprofng/src/gp-display-src.cc
@@ -172,7 +172,8 @@ er_src::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-archive(1), gprofng-collect-app(1), "
- "gprofng-display-html(1), gprofng-display-text(1)\n"));
+ "gprofng-display-html(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
/*
printf (GTXT ("Usage: %s [OPTION] a.out/.so/.o/.class\n\n"), whoami);
printf (GTXT (" -func List all the functions from the given object\n"
diff --git a/gprofng/src/gp-display-text.cc b/gprofng/src/gp-display-text.cc
index 4fcd639..32bda49 100644
--- a/gprofng/src/gp-display-text.cc
+++ b/gprofng/src/gp-display-text.cc
@@ -254,7 +254,8 @@ er_print::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-archive(1), gprofng-collect-app(1), "
- "gprofng-display-html(1), gprofng-display-src(1)\n"));
+ "gprofng-display-html(1), gprofng-display-src(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
}
int // returns count of experiments read
diff --git a/gprofng/src/gprofng.cc b/gprofng/src/gprofng.cc
index 99f904a..4364d97 100644
--- a/gprofng/src/gprofng.cc
+++ b/gprofng/src/gprofng.cc
@@ -155,7 +155,8 @@ Gprofng::usage ()
"See also:\n"
"\n"
"gprofng-archive(1), gprofng-collect-app(1), gprofng-display-html(1), "
- "gprofng-display-src(1), gprofng-display-text(1)\n"));
+ "gprofng-display-src(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
/*
printf ( GTXT (
diff --git a/gprofng/src/ipcio.cc b/gprofng/src/ipcio.cc
index 36d2ba5..2890c6a 100644
--- a/gprofng/src/ipcio.cc
+++ b/gprofng/src/ipcio.cc
@@ -23,10 +23,7 @@
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-#include <queue>
+
#include "vec.h"
#include "util.h"
#include "ipcio.h"