]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gprofng: fix 32892 source line level information not available with "-g -O2"
authorVladimir Mezentsev <vladimir.mezentsev@oracle.com>
Fri, 2 May 2025 07:15:37 +0000 (00:15 -0700)
committerVladimir Mezentsev <vladimir.mezentsev@oracle.com>
Mon, 5 May 2025 06:57:06 +0000 (23:57 -0700)
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 <Unknown> module.

gprofng/ChangeLog
2025-05-01  Vladimir Mezentsev  <vladimir.mezentsev@oracle.com>

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
gprofng/src/Dwarf.h
gprofng/src/DwarfLib.cc
gprofng/src/DwarfLib.h
gprofng/src/LoadObject.cc
gprofng/src/Makefile.am
gprofng/src/Makefile.in
gprofng/src/Stabs.cc
gprofng/src/Stabs.h
gprofng/src/Symbol.cc [new file with mode: 0644]
gprofng/src/Symbol.h [new file with mode: 0644]

index 3b3fd63d795332a50d82a19728cca815419a8d4d..23ac5b9e55da6fca3b264c650a58cd810d24fd89 100644 (file)
@@ -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 <Range *> *ranges = get_ranges ();
+             if (ranges)
+               {
+                 Vector<Symbol *> *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<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));
+    }
+  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;
 }
 
index 8e3ee7aa7960aa2ce3cb882112b8c7a66366cca0..f46ad3fcf98aeb2237f859c801f9aa459a5aa597 100644 (file)
@@ -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<Range *> *get_ranges (uint64_t offset);
 
   Stabs::Stab_status status;
   Vector<DwrCU *> *dwrCUs;
index 3594c2f9ad5103420bc1405a0333a05cea43d4fb..9f55ab34ab0c9bd328b96c9fedec3737c9e9149f 100644 (file)
@@ -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 <Range *> *ranges = get_ranges ();
+  if (ranges)
+    {
+      Vector <Symbol *> *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 <Range *> *
+DwrCU::get_ranges ()
+{
+  Vector <Range *> *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 <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 && 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;
index 178801d8f572de6ac02b7e509581793e24e6d157..230e5517358ff006ae30216533fbef68613e80b4 100644 (file)
@@ -25,6 +25,8 @@
 
 class ElfReloc;
 class Dwr_type;
+class Function;
+class Range;
 class SourceFile;
 
 template <class ITEM> 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<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 +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 <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);
index 1ca6ab61f2e4b4ef02247718828d9bbcaaaac027..be7ad3a2c60ca68ea40269d43ca5c565704953cf 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include <errno.h>
+#include <libgen.h>
 
 #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");
          }
index 0465cdb06e3da07d823f20dd0e50dc37f563ccc0..f6d3f5da7594e07f64343255b9f86ca3475c002c 100644 (file)
@@ -78,6 +78,7 @@ CCSOURCES = \
        Stabs.cc \
        Stats_data.cc \
        StringBuilder.cc \
+       Symbol.cc \
        Table.cc \
        QLParser.tab.cc \
        dbe_collctrl.cc \
index 9f07986865a82ffb5d21a3df38ec0277d5de026d..0cdd4443670df54dbee7172ad44a09c816423f95 100644 (file)
@@ -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@
index b98ac2838873d4c339696efe3119860ee9904e1c..55fbc094cf63fda404e2ca64dcd9a395030b32c1 100644 (file)
@@ -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<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
@@ -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"));
 }
index d34741f8f914acbbafd801cdef4ebc352104fe9b..39370bf27b9e6db4c0cd8af8f3f6b8980554cc5a 100644 (file)
@@ -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<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);
diff --git a/gprofng/src/Symbol.cc b/gprofng/src/Symbol.cc
new file mode 100644 (file)
index 0000000..82fe788
--- /dev/null
@@ -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<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)
+{
+  // 'syms' and 'ranges' must already be sorted.
+  // return symbols matched by 'ranges'
+  if (VecSize (syms) == 0 || VecSize (ranges) == 0)
+    return NULL;
+  Vector<Symbol *> *symbols = new Vector<Symbol*> ();
+
+  // 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<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 (file)
index 0000000..25cceca
--- /dev/null
@@ -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<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);
+  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 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