[binutils-gdb] gprofng: fix 32892 source line level information not available with "-g -O2"

Vladimir Mezentsev vmezents@sourceware.org
Mon May 5 07:15:19 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=470a0288a8180e4e66e0d239dc63d58f013f3d16

commit 470a0288a8180e4e66e0d239dc63d58f013f3d16
Author: Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
Date:   Fri May 2 00:15:37 2025 -0700

    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 <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.

Diff:
---
 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(-)

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 <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;
 }
 
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<Range *> *get_ranges (uint64_t offset);
 
   Stabs::Stab_status status;
   Vector<DwrCU *> *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 <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;
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 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);
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 <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");
 	  }
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<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"));
 }
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<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
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<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
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<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


More information about the Binutils-cvs mailing list