diff options
Diffstat (limited to 'gprofng/src')
-rw-r--r-- | gprofng/src/CallStack.cc | 10 | ||||
-rw-r--r-- | gprofng/src/DbeSession.cc | 11 | ||||
-rw-r--r-- | gprofng/src/DbeSession.h | 1 | ||||
-rw-r--r-- | gprofng/src/Dwarf.cc | 271 | ||||
-rw-r--r-- | gprofng/src/Dwarf.h | 4 | ||||
-rw-r--r-- | gprofng/src/DwarfLib.cc | 333 | ||||
-rw-r--r-- | gprofng/src/DwarfLib.h | 64 | ||||
-rw-r--r-- | gprofng/src/Experiment.cc | 9 | ||||
-rw-r--r-- | gprofng/src/Experiment.h | 1 | ||||
-rw-r--r-- | gprofng/src/LoadObject.cc | 21 | ||||
-rw-r--r-- | gprofng/src/LoadObject.h | 1 | ||||
-rw-r--r-- | gprofng/src/Makefile.am | 1 | ||||
-rw-r--r-- | gprofng/src/Makefile.in | 4 | ||||
-rw-r--r-- | gprofng/src/Stabs.cc | 169 | ||||
-rw-r--r-- | gprofng/src/Stabs.h | 5 | ||||
-rw-r--r-- | gprofng/src/Symbol.cc | 218 | ||||
-rw-r--r-- | gprofng/src/Symbol.h | 84 | ||||
-rw-r--r-- | gprofng/src/collect.h | 1 | ||||
-rw-r--r-- | gprofng/src/envsets.cc | 10 | ||||
-rw-r--r-- | gprofng/src/gp-archive.cc | 3 | ||||
-rw-r--r-- | gprofng/src/gp-collect-app.cc | 5 | ||||
-rw-r--r-- | gprofng/src/gp-display-src.cc | 3 | ||||
-rw-r--r-- | gprofng/src/gp-display-text.cc | 3 | ||||
-rw-r--r-- | gprofng/src/gprofng.cc | 3 | ||||
-rw-r--r-- | gprofng/src/ipcio.cc | 5 |
25 files changed, 957 insertions, 283 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/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; +} diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h index 8e3ee7a..bf8ffb4 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,6 +70,8 @@ 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; @@ -82,6 +85,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..79be8cf 100644 --- a/gprofng/src/DwarfLib.cc +++ b/gprofng/src/DwarfLib.cc @@ -27,9 +27,9 @@ #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 @@ -998,7 +998,6 @@ Dwr_Tag::dump () 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: @@ -1037,6 +1036,7 @@ Dwr_Tag::dump () 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; @@ -1095,6 +1095,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; @@ -1795,6 +1796,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 (); @@ -1847,7 +1854,7 @@ DwrCU::DwrCU (Dwarf *_dwarf) (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 +1890,9 @@ DwrCU::~DwrCU () Destroy (dwrInlinedSubrs); delete srcFiles; delete dwrLineReg; + delete symbols; + delete symbols_sorted_by_name; + delete tmp_syms; free (comp_dir); } @@ -1925,7 +1935,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 +1955,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 +2004,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 (); @@ -2109,7 +2119,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 +2197,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 +2511,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 +2600,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 +2745,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..06b19b8 100644 --- a/gprofng/src/DwarfLib.h +++ b/gprofng/src/DwarfLib.h @@ -25,7 +25,10 @@ class ElfReloc; class Dwr_type; +class Function; +class Range; class SourceFile; +class Symbol; template <class ITEM> class Vector; template <class ITEM> class DbeArray; @@ -73,12 +76,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; @@ -260,6 +257,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 +316,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 +325,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 +362,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/Experiment.cc b/gprofng/src/Experiment.cc index 45550e8..4cbb7f6 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; diff --git a/gprofng/src/Experiment.h b/gprofng/src/Experiment.h index 2047a15..c85aadd 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 diff --git a/gprofng/src/LoadObject.cc b/gprofng/src/LoadObject.cc index 1ca6ab6..bf49e9d 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; @@ -298,18 +298,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"); } diff --git a/gprofng/src/LoadObject.h b/gprofng/src/LoadObject.h index 14dfe26..dd40ea0 100644 --- a/gprofng/src/LoadObject.h +++ b/gprofng/src/LoadObject.h @@ -167,7 +167,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 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/Stabs.cc b/gprofng/src/Stabs.cc index b98ac28..c6d6473 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 (); @@ -294,8 +182,6 @@ Stabs::Stabs (char *_path, char *_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>; @@ -341,8 +227,6 @@ Stabs::~Stabs () { delete SymLstByName; Destroy (SymLst); - Destroy (RelLst); - Destroy (RelPLTLst); Destroy (LocalFile); delete elfDis; delete dwarf; @@ -458,42 +342,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 +1554,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 +1610,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 +1690,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) @@ -2339,6 +2189,7 @@ Stabs::openDwarf () { dwarf = new Dwarf (this); check_Symtab (); + dump(); } return dwarf; } @@ -2363,8 +2214,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..c8da278 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; @@ -86,12 +85,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(); @@ -135,8 +134,6 @@ 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 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..ee9f917 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); } 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" |