From 470a0288a8180e4e66e0d239dc63d58f013f3d16 Mon Sep 17 00:00:00 2001 From: Vladimir Mezentsev Date: Fri, 2 May 2025 00:15:37 -0700 Subject: [PATCH] gprofng: fix 32892 source line level information not available with "-g -O2" gprofng ignored DW_AT_specification. As a result, gprofng skiped Dwarf for all functions declared as: < 2>:<0x0000f725> DW_TAG_subprogram(46) DW_AT_linkage_name(110) "func_name" DW_AT_declaration*(60) 0x1 (1) < 1>:<0x00015acc> DW_TAG_subprogram(46) DW_AT_specification(71) 0xf725 (63269) Another problem was that gprofng ignored DW_AT_ranges. As a result, many functions are mapped to the module. gprofng/ChangeLog 2025-05-01 Vladimir Mezentsev PR 32892 * src/Dwarf.cc: Handle DW_AT_specification and DW_AT_ranges. * src/DwarfLib.cc: Likewise. * src/DwarfLib.h: Likewise. * src/Dwarf.h (get_ranges): New function. * src/Stabs.h (get_symbols): New function. * src/Stabs.cc: Move Symbol class to src/Symbol.cc. * src/Symbol.cc: New file. * src/Symbol.h: New file. * src/Makefile.am: Add Symbol.cc in build. * src/Makefile.in: Rebuild. * src/LoadObject.cc (dump_functions): Improve output for -dfunc option. --- gprofng/src/Dwarf.cc | 205 ++++++++++++++++++++++++---------- gprofng/src/Dwarf.h | 2 + gprofng/src/DwarfLib.cc | 79 ++++++++++++- gprofng/src/DwarfLib.h | 15 +-- gprofng/src/LoadObject.cc | 18 +-- gprofng/src/Makefile.am | 1 + gprofng/src/Makefile.in | 4 +- gprofng/src/Stabs.cc | 85 ++------------ gprofng/src/Stabs.h | 1 + gprofng/src/Symbol.cc | 226 ++++++++++++++++++++++++++++++++++++++ gprofng/src/Symbol.h | 80 ++++++++++++++ 11 files changed, 563 insertions(+), 153 deletions(-) create mode 100644 gprofng/src/Symbol.cc create mode 100644 gprofng/src/Symbol.h diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc index 3b3fd63d795..23ac5b9e55d 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 @@ -441,7 +441,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 @@ -490,8 +495,10 @@ DwrCU::parseChild (Dwarf_cnt *ctx) } break; case DW_TAG_subprogram: + { if (dwrTag.get_attr (DW_AT_abstract_origin)) break; + Symbol *sym = NULL; if (dwrTag.get_attr (DW_AT_declaration)) { // Only declaration @@ -499,26 +506,71 @@ 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); - } - break; + 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) + break; + func = append_Function (sym, ctx->name); + break; } - func = append_Function (ctx); - if (func) + + Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_specification); + if (dwrAttr) { - if (Stabs::is_fortran (ctx->module->lang_code) && - streq (func->get_match_name (), NTXT ("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; + // Find previous declaration to inherit settings. + sym = find_declaration (dwrAttr->u.offset); + if (sym == NULL) + break; + func = sym->func; + if (func == NULL) + break; + set_source (func); + + Vector *ranges = get_ranges (); + if (ranges) + { + Vector *syms = Symbol::find_symbols (symbols, ranges); + Destroy (ranges); + for (int i = 0, sz = VecSize (syms); i < sz; i++) + { + Symbol *sp = syms->get (i); + if (sp->alias) + sp = sp->alias; + Function *f = sp->func; + if (f == NULL) + f = sp->createFunction (func->module); + f->setLineFirst (func->line_first); + f->setDefSrc (func->def_source); + } + delete (syms); + } + break; } + + 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) + break; + func = append_Function (sym, ctx->name); + if (Stabs::is_fortran (ctx->module->lang_code) && + streq (func->get_match_name (), "MAIN")) + ctx->fortranMAIN = func; + set_source (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; break; + } case DW_TAG_module: old_name = ctx->name; ctx->name = Dwarf_string (DW_AT_SUN_link_name); @@ -631,6 +683,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 +712,38 @@ Dwarf::srcline_Dwarf (Module *module) dwrCU->map_dwarf_lines (module); } +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 * +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 *ranges = new Vector(); + 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)); + } + ranges->sort (rangeCmp); + return ranges; +} // parse hwcprof info for given module in loadobject @@ -797,11 +896,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 +1060,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; } diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h index 8e3ee7aa796..f46ad3fcf98 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,7 @@ public: bool archive_Dwarf (LoadObject *lo); void srcline_Dwarf (Module *module); void read_hwcprof_info (Module *module); + Vector *get_ranges (uint64_t offset); Stabs::Stab_status status; Vector *dwrCUs; diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc index 3594c2f9ad5..9f55ab34ab0 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 @@ -1795,6 +1795,8 @@ DwrLineRegs::getPath (int fn) DwrCU::DwrCU (Dwarf *_dwarf) { dwarf = _dwarf; + 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 (); @@ -1883,6 +1885,8 @@ DwrCU::~DwrCU () Destroy (dwrInlinedSubrs); delete srcFiles; delete dwrLineReg; + delete symbols; + delete symbols_sorted_by_name; free (comp_dir); } @@ -2187,9 +2191,80 @@ 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 + Vector *ranges = get_ranges (); + if (ranges) + { + Vector *syms = dwarf->stabs->get_symbols (); + symbols = Symbol::find_symbols (syms, ranges); + symbols_sorted_by_name = Symbol::sort_by_name (syms); + Destroy (ranges); + } return module; } +Vector * +DwrCU::get_ranges () +{ + Vector *ranges = NULL; + Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_ranges); + if (dwrAttr) + { + Dprintf (DUMP_DWARFLIB, "DwrCU::get_ranges: 0x%llx\n", + (long long) dwrAttr->u.offset); + ranges = dwarf->get_ranges (dwrAttr->u.offset); + } + 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 (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 && DUMP_DWARFLIB) + ranges->dump (" "); + return ranges; +} + +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); + if (fileno > 0 && fileno < VecSize (srcFiles)) + func->setDefSrc (srcFiles->get (fileno)); +} + +Symbol * +DwrCU::find_declaration (int64_t offset) +{ + int64_t old_offset = dwrTag.offset; + Symbol *sym = NULL; + if (set_die (offset) == DW_DLV_OK) + { + sym = Symbol::get_symbol (symbols_sorted_by_name, get_linkage_name ()); + if (sym && sym->func == NULL) + { + Function *func = sym->createFunction (module); + int lineno = (int) Dwarf_data (DW_AT_decl_line); + func->setLineFirst (lineno); + int fileno = (int) Dwarf_data (DW_AT_decl_file); + if (fileno > 0 && fileno < VecSize (srcFiles)) + func->setDefSrc (srcFiles->get (fileno)); + } + } + set_die (old_offset); + return sym; +} + Dwr_Attr * Dwr_Tag::get_attr (Dwarf_Half attr) { @@ -2357,7 +2432,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; diff --git a/gprofng/src/DwarfLib.h b/gprofng/src/DwarfLib.h index 178801d8f57..230e5517358 100644 --- a/gprofng/src/DwarfLib.h +++ b/gprofng/src/DwarfLib.h @@ -25,6 +25,8 @@ class ElfReloc; class Dwr_type; +class Function; +class Range; class SourceFile; template class Vector; @@ -73,12 +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; @@ -280,6 +276,8 @@ public: uint64_t cu_header_offset; uint64_t cu_offset; uint64_t next_cu_offset; + Vector *symbols; // all symbols in this CU are sorted by pc + Vector *symbols_sorted_by_name; Vector *dwrInlinedSubrs; Vector *srcFiles; bool isMemop; @@ -287,7 +285,10 @@ 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); + Symbol *find_declaration(int64_t offset); + Vector *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); diff --git a/gprofng/src/LoadObject.cc b/gprofng/src/LoadObject.cc index 1ca6ab61f2e..be7ad3a2c60 100644 --- a/gprofng/src/LoadObject.cc +++ b/gprofng/src/LoadObject.cc @@ -20,6 +20,7 @@ #include "config.h" #include +#include #include "util.h" #include "StringBuilder.h" @@ -303,13 +304,16 @@ LoadObject::dump_functions (FILE *out) { 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/Makefile.am b/gprofng/src/Makefile.am index 0465cdb06e3..f6d3f5da759 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 9f07986865a..0cdd4443670 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 b98ac283887..55fbc094cf6 100644 --- a/gprofng/src/Stabs.cc +++ b/gprofng/src/Stabs.cc @@ -35,6 +35,7 @@ #include "StringBuilder.h" #include "DbeFile.h" #include "StringMap.h" +#include "Symbol.h" #define DISASM_REL_NONE 0 /* symtab search only */ #define DISASM_REL_ONLY 1 /* relocation search only */ @@ -62,77 +63,6 @@ private: int StabEntSize; }; -/////////////////////////////////////////////////////////////////////////////// -// class Symbol - -class Symbol -{ -public: - Symbol (Vector *vec = NULL); - - ~Symbol () - { - free (name); - } - - inline Symbol * - cardinal () - { - return alias ? alias : this; - } - - static void dump (Vector *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 *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 *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 @@ -252,7 +182,6 @@ Stabs::removeDupSyms () long ind, i, last; Symbol *symA, *symB; SymLst->sort (SymImgOffsetCmp); - dump (); last = 0; ind = SymLst->size (); @@ -1761,10 +1690,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 +1770,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 +2269,7 @@ Stabs::openDwarf () { dwarf = new Dwarf (this); check_Symtab (); + dump(); } return dwarf; } @@ -2363,8 +2294,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 d34741f8f91..39370bf27b9 100644 --- a/gprofng/src/Stabs.h +++ b/gprofng/src/Stabs.h @@ -86,6 +86,7 @@ class Stabs { Platform_t get_platform() { return platform; } WSize_t get_class() { return wsize;} Stab_status get_status() { return status;} + Vector *get_symbols() { return SymLst; } Stab_status read_stabs(ino64_t srcInode, Module *module, Vector *comComs, bool readDwarf = false); Stab_status read_archive(LoadObject *lo); diff --git a/gprofng/src/Symbol.cc b/gprofng/src/Symbol.cc new file mode 100644 index 00000000000..82fe788a9e2 --- /dev/null +++ b/gprofng/src/Symbol.cc @@ -0,0 +1,226 @@ +/* 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::dump (const char *msg) +{ + if (msg == NULL) + msg = "#"; + Dprintf (1, NTXT ("\n%s Vector [%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 *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 *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 *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::sort_by_name (Vector *syms) +{ + if (VecSize (syms) == 0) + return NULL; + Vector *symbols = syms->copy (); + symbols->sort (cmpSymName); + return symbols; +} + +Vector * +Symbol::find_symbols (Vector *syms, Vector *ranges) +{ + // 'syms' and 'ranges' must already be sorted. + // return symbols matched by 'ranges' + if (VecSize (syms) == 0 || VecSize (ranges) == 0) + return NULL; + Vector *symbols = new Vector (); + + // 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; + } + if (DUMP_ELF_SYM) + { + syms->dump ( "Symbol::find_symbols: syms"); + symbols->dump ("Symbol::find_symbols: symbols"); + } + if (symbols->size () != 0) + return symbols; + delete symbols; + return NULL; +} + +/* 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::dump (const char *msg) +{ + Dprintf (1, NTXT ("%s Vector [%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 00000000000..25ccecafe7f --- /dev/null +++ b/gprofng/src/Symbol.h @@ -0,0 +1,80 @@ +/* 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. */ + +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 *vec = NULL); + ~Symbol (); + + Symbol * + cardinal () + { + return alias ? alias : this; + } + + // Find symbols in 'syms' matched by 'ranges'. + static Vector *find_symbols (Vector *syms, + Vector *ranges); + static Vector *sort_by_name (Vector *syms); + + // Find symbol in CU corresponding to pc or linker_name. + static Symbol *get_symbol (Vector *syms, uint64_t pc); + static Symbol *get_symbol (Vector *syms, char *linker_name); + + // Create and append a new function to the 'module'. + // Copy attributes (size, name, etc) from Simbol, + 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; +}; \ No newline at end of file -- 2.47.2