[PATCH v2] gprofng: support external debug info

vladimir.mezentsev@oracle.com vladimir.mezentsev@oracle.com
Tue Jul 8 04:50:49 GMT 2025


From: Vladimir Mezentsev <vladimir.mezentsev@oracle.com>

valgrind reported uninitialized memory.
Made an additional fix in src/Stabs.cc to fix this.



Use bfd_follow_gnu_debuglink() and bfd_follow_gnu_debugaltlink() to find files
with debug info.
If necessary, gprofng-archive copies these files to EXP/archives.

For each executable, gprofng creates the Elf class twice.
One of them was a memory leak.
Fixed this by adding a new argument to Stabs::Stabs().

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

	PR 32147
	PR 30194
	* src/Disasm.cc (get_funcname_in_plt): Use the executable file instead
	of the debug information file.
	* src/Dwarf.h: Define debug_alt_strSec.
	* src/DwarfLib.cc: Add support for DW_FORM_GNU_ref_alt,
	DW_FORM_GNU_strp_alt.
	* src/Elf.h (find_gnu_debug_files, get_dwr_section): New functions.
	* src/Elf.cc: Likewise.
	* src/Experiment.cc (copy_file): Add the const qualifier.
	* src/Experiment.h: Likewise.
	* src/LoadObject.cc (get_elf, openDebugInfo): Find files with debug info.
	* src/LoadObject.h: Remove unused variables.
	* src/Module.cc: Remove an argument in openDebugInfo().
	* src/Stabs.cc (Stabs::Stabs): Add the Elf* argument.
	* src/Stabs.h: Likewise.
	* src/gp-archive.cc: Archive files with debug info.
	* src/gp-archive.h (archive_file): New function.
---
 gprofng/src/Disasm.cc     |   2 +-
 gprofng/src/Dwarf.cc      |  23 +++-----
 gprofng/src/Dwarf.h       |   1 +
 gprofng/src/DwarfLib.cc   |  19 +++++-
 gprofng/src/Elf.cc        | 118 +++++++++++++++++++++++++++++++++----
 gprofng/src/Elf.h         |  12 +++-
 gprofng/src/Experiment.cc |   3 +-
 gprofng/src/Experiment.h  |   4 +-
 gprofng/src/LoadObject.cc |  80 +++++++++++++------------
 gprofng/src/LoadObject.h  |  10 +---
 gprofng/src/Module.cc     |   2 +-
 gprofng/src/Stabs.cc      | 121 ++++++++++----------------------------
 gprofng/src/Stabs.h       |   3 +-
 gprofng/src/gp-archive.cc |  65 ++++++++++++++++----
 gprofng/src/gp-archive.h  |   1 +
 15 files changed, 279 insertions(+), 185 deletions(-)

diff --git a/gprofng/src/Disasm.cc b/gprofng/src/Disasm.cc
index 348718b53e2..3ee50d789b3 100644
--- a/gprofng/src/Disasm.cc
+++ b/gprofng/src/Disasm.cc
@@ -355,7 +355,7 @@ Disasm::get_funcname_in_plt (uint64_t pc)
 {
   if (stabs)
     {
-      Elf *elf = stabs->openElf (true);
+      Elf *elf = stabs->openElf (false);
       if (elf)
 	return elf->get_funcname_in_plt (pc);
     }
diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc
index a54cdb18d46..934ae44149e 100644
--- a/gprofng/src/Dwarf.cc
+++ b/gprofng/src/Dwarf.cc
@@ -368,6 +368,7 @@ Dwarf::Dwarf (Stabs *_stabs)
   debug_infoSec = NULL;
   debug_abbrevSec = NULL;
   debug_strSec = NULL;
+  debug_alt_strSec = NULL;
   debug_lineSec = NULL;
   debug_line_strSec = NULL;
   debug_rangesSec = NULL;
@@ -384,6 +385,8 @@ Dwarf::Dwarf (Stabs *_stabs)
   debug_rangesSec = dwrGetSec (NTXT (".debug_ranges"));
   debug_line_strSec = dwrGetSec (".debug_line_str");
   debug_rnglists = NULL;
+  if (elf->gnu_debugalt_file)
+    debug_alt_strSec = elf->gnu_debugalt_file->get_dwr_section (".debug_str");
 
   if ((debug_infoSec == NULL) || (debug_abbrevSec == NULL) || (debug_lineSec == NULL))
     {
@@ -394,27 +397,16 @@ Dwarf::Dwarf (Stabs *_stabs)
 
 Dwarf::~Dwarf ()
 {
-  delete debug_infoSec;
-  delete debug_abbrevSec;
-  delete debug_strSec;
-  delete debug_lineSec;
-  delete debug_rangesSec;
   Destroy (dwrCUs);
 }
 
 DwrSec *
 Dwarf::dwrGetSec (const char *sec_name)
 {
-  int secN = elf->elf_get_sec_num (sec_name);
-  if (secN > 0)
-    {
-      Elf_Data *elfData = elf->elf_getdata (secN);
-      if (elfData)
-	return new DwrSec ((unsigned char *) elfData->d_buf, elfData->d_size,
-			   elf->need_swap_endian,
-			   elf->elf_getclass () == ELFCLASS32);
-    }
-  return NULL;
+  DwrSec *p = elf->get_dwr_section (sec_name);
+  if (p)
+    p->offset = 0;
+  return p;
 }
 
 uint64_t
@@ -1182,7 +1174,6 @@ Dwarf::get_debug_rnglists ()
       debug_rnglistsSec->size = debug_rnglistsSec->sizeSec;
       debug_rnglistsSec->offset = length;
     }
-  delete debug_rnglistsSec;
   debug_rnglists->dump ("Dwarf::get_debug_rnglists");
   return debug_rnglists;
 }
diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h
index bf8ffb43ddc..14d9878f9a1 100644
--- a/gprofng/src/Dwarf.h
+++ b/gprofng/src/Dwarf.h
@@ -78,6 +78,7 @@ public:
   DwrSec *debug_infoSec;
   DwrSec *debug_abbrevSec;
   DwrSec *debug_strSec;
+  DwrSec *debug_alt_strSec;
   DwrSec *debug_lineSec;
   DwrSec *debug_line_strSec;
   DwrSec *debug_rangesSec;
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc
index 9e116581b1f..4720ef154b8 100644
--- a/gprofng/src/DwarfLib.cc
+++ b/gprofng/src/DwarfLib.cc
@@ -53,6 +53,7 @@ extended_opcode2str (int opcode)
       CASE_S (DW_LNE_end_sequence);
       CASE_S (DW_LNE_set_address);
       CASE_S (DW_LNE_define_file);
+      CASE_S (DW_LNS_set_file);
     default:
       snprintf (buf, sizeof (buf), NTXT ("??? (%d)"), opcode);
       buf[sizeof (buf) - 1] = 0;
@@ -141,7 +142,6 @@ get_string (DwrSec *sec, uint64_t off)
   return NULL;
 }
 
-  
 DwrLocation *
 DwrCU::dwr_get_location (DwrSec *secp, DwrLocation *lp)
 {
@@ -684,6 +684,8 @@ DwrCU::form2str (int tag)
       CASE_S (DW_FORM_strp);
       CASE_S (DW_FORM_udata);
       CASE_S (DW_FORM_ref_addr);
+      CASE_S (DW_FORM_GNU_ref_alt);
+      CASE_S (DW_FORM_GNU_strp_alt);
       CASE_S (DW_FORM_ref1);
       CASE_S (DW_FORM_ref2);
       CASE_S (DW_FORM_ref4);
@@ -741,6 +743,7 @@ Dwr_Tag::dump ()
 	case DW_FORM_strp:
 	case DW_FORM_string:
 	case DW_FORM_line_strp:
+	case DW_FORM_GNU_strp_alt:
 	case DW_FORM_strp_sup:
 	case DW_FORM_strx1:
 	case DW_FORM_strx2:
@@ -781,6 +784,7 @@ Dwr_Tag::dump ()
 	case DW_FORM_ref_udata:
 	case DW_FORM_indirect:
 	case DW_FORM_sec_offset:
+	case DW_FORM_GNU_ref_alt:
 	case DW_FORM_exprloc:
 	case DW_FORM_ref_sig8:
 	case DW_FORM_flag_present:
@@ -1021,6 +1025,7 @@ DwrSec::get_value (int dw_form)
     case DW_FORM_line_strp:
     case DW_FORM_strp:
     case DW_FORM_strp_sup:
+    case DW_FORM_GNU_strp_alt:
       return GetRef ();
     case DW_FORM_data1:
       return Get_8 ();
@@ -1284,6 +1289,8 @@ DwrLineRegs::read_file_names_dwarf5 ()
 		  nm = get_string (dwarf->debug_line_strSec, off);
 		else if (efmt[k].form_code == DW_FORM_strp)
 		  nm = get_string (dwarf->debug_strSec, off);
+		else if (efmt[k].form_code == DW_FORM_GNU_strp_alt)
+		  nm = get_string (dwarf->debug_alt_strSec, off);
 	      }
 	    break;
 	  case DW_LNCT_directory_index:
@@ -1581,7 +1588,7 @@ DwrCU::DwrCU (Dwarf *_dwarf)
   if (DUMP_DWARFLIB)
     {
       Dprintf (DUMP_DWARFLIB,
-	       "CU_HEADER: header_offset = 0x%08llx %lld"
+	       "File: %s\nCU_HEADER: header_offset = 0x%08llx %lld"
 	       " next_header_offset=0x%08llx %lld\n"
 	       "    abbrev_offset = 0x%08llx %lld\n"
 	       "    unit_length   = %lld\n"
@@ -1589,6 +1596,7 @@ DwrCU::DwrCU (Dwarf *_dwarf)
 	       "    address_size  = %d\n"
 	       "    fmt64         = %s\n"
 	       "debug_info:   need_swap_endian=%s  fmt64=%s addr32=%s\n",
+	       dwarf->elf->get_location (),
 	       (long long) cu_offset, (long long) cu_offset,
 	       (long long) next_cu_offset, (long long) next_cu_offset,
 	       (long long) debug_abbrev_offset, (long long) debug_abbrev_offset,
@@ -1788,6 +1796,9 @@ DwrCU::set_die (Dwarf_Die die)
 	  else
 	    atf->u.offset = debug_infoSec->GetADDR ();
 	  break;
+	case DW_FORM_GNU_ref_alt:
+	  atf->u.offset = debug_infoSec->GetRef ();
+	  break;
 	case DW_FORM_sec_offset:
 	  atf->u.offset = debug_infoSec->GetRef ();
 	  break;
@@ -1811,6 +1822,10 @@ DwrCU::set_die (Dwarf_Die die)
 	case DW_FORM_rnglistx:
 	  atf->u.offset = debug_infoSec->GetULEB128 ();
 	  break;
+	case DW_FORM_GNU_strp_alt:
+	  atf->u.offset = debug_infoSec->GetRef ();
+	  atf->u.str = get_string (dwarf->debug_alt_strSec, atf->u.offset);
+	  break;
 	case DW_FORM_strx:
 	  atf->u.offset = debug_infoSec->GetULEB128 ();
 	  atf->u.str = get_string (dwarf->debug_strSec, atf->u.offset);
diff --git a/gprofng/src/Elf.cc b/gprofng/src/Elf.cc
index b90ad29dc5b..e63e3c3fa68 100644
--- a/gprofng/src/Elf.cc
+++ b/gprofng/src/Elf.cc
@@ -29,6 +29,7 @@
 #include "StringBuilder.h"
 #include "DbeFile.h"
 #include "DbeSession.h"
+#include "Dwarf.h"
 
 typedef uint32_t Elf32_Word;
 typedef uint32_t Elf64_Word;
@@ -84,6 +85,31 @@ struct S_Elf64_Dyn
   } d_un;
 };
 
+#ifndef DEBUGDIR
+#define DEBUGDIR "/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT1
+#define EXTRA_DEBUG_ROOT1 "/usr/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT2
+#define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
+#endif
+
+static const char *debug_dirs[] = {
+  DEBUGDIR, EXTRA_DEBUG_ROOT1, EXTRA_DEBUG_ROOT2, "."
+};
+
+template<> void Vector<asymbol *>::dump (const char *msg)
+{
+  Dprintf (1, NTXT ("\nFile: %s Vector<asymbol *> [%ld]\n"),
+	   msg ? msg : "NULL", (long) size ());
+  for (long i = 0, sz = size (); i < sz; i++)
+    {
+      asymbol *sym = get (i);
+      Dprintf (1, "  %3ld %s\n", i, sym->name);
+    }
+}
+
 int Elf::bfd_status = -1;
 
 void
@@ -100,6 +126,8 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
   ancillary_files = NULL;
   elfSymbols = NULL;
   gnu_debug_file = NULL;
+  gnu_debugalt_file = NULL;
+  sections = NULL;
   dbeFile = NULL;
   abfd = NULL;
   bfd_symcnt = -1;
@@ -209,6 +237,12 @@ Elf::~Elf ()
 	}
       free (data);
     }
+  if (sections)
+    {
+      for (int i = 0; i < (int) ehdrp->e_shnum; i++)
+	delete sections[i];
+      free (sections);
+    }
   if (ancillary_files)
     {
       ancillary_files->destroy ();
@@ -216,6 +250,7 @@ Elf::~Elf ()
     }
   delete elfSymbols;
   delete gnu_debug_file;
+  delete gnu_debugalt_file;
   delete dbeFile;
   delete synthsym;
   free (bfd_sym);
@@ -338,9 +373,36 @@ Elf::get_sec_name (unsigned int sec)
   return elf_strptr (ehdrp->e_shstrndx, shdr->sh_name);
 }
 
+DwrSec *
+Elf::get_dwr_section (const char *sec_name)
+{
+  int sec_num = elf_get_sec_num (sec_name);
+  if (sec_num > 0)
+    {
+      if (sections == NULL)
+	{
+	  sections = (DwrSec **) xmalloc (ehdrp->e_shnum * sizeof (DwrSec *));
+	  for (int i = 0; i < (int) ehdrp->e_shnum; i++)
+	    sections[i] = NULL;
+	}
+      if (sections[sec_num] == NULL)
+	{
+	  Elf_Data *elfData = elf_getdata (sec_num);
+	  if (elfData)
+	    sections[sec_num] = new DwrSec ((unsigned char *) elfData->d_buf,
+				    elfData->d_size, need_swap_endian,
+				    elf_getclass () == ELFCLASS32);
+	}
+      return sections[sec_num];
+    }
+  return NULL;
+}
+
 Elf_Data *
 Elf::elf_getdata (unsigned int sec)
 {
+  if (sec == 0)
+    return NULL;
   if (data == NULL)
     {
       data = (Elf_Data **) xmalloc (ehdrp->e_shnum * sizeof (Elf_Data *));
@@ -565,25 +627,54 @@ Elf::get_related_file (const char *lo_name, const char *nm)
   return NULL;
 }
 
-Elf *
-Elf::find_ancillary_files (char *lo_name)
+static char *
+find_file (char *(bfd_func) (bfd *, const char *), bfd *abfd)
 {
-  // read the .gnu_debuglink and .SUNW_ancillary seections
-  if (gnu_debug_file)
-    return gnu_debug_file;
-  unsigned int sec = elf_get_sec_num (NTXT (".gnu_debuglink"));
-  if (sec > 0)
+  char *fnm = NULL;
+  for (size_t i = 0; i < ARR_SIZE (debug_dirs); i++)
+    {
+      fnm = bfd_func (abfd, debug_dirs[i]);
+      if (fnm)
+	break;
+    }
+  Dprintf (DUMP_DWARFLIB, "FOUND: gnu_debug_file: %s --> %s\n",
+	   abfd->filename, fnm);
+  return fnm;
+}
+
+void
+Elf::find_gnu_debug_files ()
+{
+  char *fnm;
+  if (gnu_debug_file == NULL)
     {
-      Elf_Data *dp = elf_getdata (sec);
-      if (dp)
+      fnm = find_file (bfd_follow_gnu_debuglink, abfd);
+      if (fnm)
 	{
-	  gnu_debug_file = get_related_file (lo_name, (char *) (dp->d_buf));
+	  gnu_debug_file = Elf::elf_begin (fnm);
+	  free (fnm);
 	  if (gnu_debug_file)
-	    return gnu_debug_file;
+	    gnu_debug_file->find_gnu_debug_files ();
 	}
     }
+  if (gnu_debugalt_file == NULL)
+    {
+      fnm = find_file (bfd_follow_gnu_debugaltlink, abfd);
+      if (fnm)
+	{
+	  gnu_debugalt_file = Elf::elf_begin (fnm);
+	  free (fnm);
+	}
+    }
+}
 
-  sec = elf_get_sec_num (NTXT (".SUNW_ancillary"));
+void
+Elf::find_ancillary_files (const char *lo_name)
+{
+  // read the .SUNW_ancillary section
+  if (ancillary_files != NULL)
+    return;
+  unsigned int sec = elf_get_sec_num (".SUNW_ancillary");
   if (sec > 0)
     {
       Elf_Internal_Shdr *shdr = get_shdr (sec);
@@ -644,7 +735,6 @@ Elf::find_ancillary_files (char *lo_name)
 	    }
 	}
     }
-  return NULL;
 }
 
 void
@@ -717,6 +807,8 @@ Elf::get_funcname_in_plt (uint64_t pc)
       for (long i = 0; i < bfd_synthcnt; i++)
 	synthsym->append (bfd_synthsym + i);
       synthsym->sort (cmp_sym_addr);
+      if (DUMP_ELF_SYM)
+	synthsym->dump (get_location ());
     }
 
   asymbol sym, *symp = &sym;
diff --git a/gprofng/src/Elf.h b/gprofng/src/Elf.h
index 66676702a85..2d227f7f74a 100644
--- a/gprofng/src/Elf.h
+++ b/gprofng/src/Elf.h
@@ -32,6 +32,7 @@
 
 class Symbol;
 class DbeFile;
+class DwrSec;
 template <class ITEM> class Vector;
 template <typename Key_t, typename Value_t> class Map;
 
@@ -93,7 +94,14 @@ public:
   long elf_getSymCount (bool is_dynamic);
   asymbol *elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic);
   Elf64_Ancillary *elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst);
-  Elf *find_ancillary_files (char *lo_name); // read the .gnu_debuglink and .SUNW_ancillary seections
+
+  // read the .SUNW_ancillary section
+  void find_ancillary_files (const char *lo_name);
+
+  // read the .gnu_debuglink and .gnu_debugaltlink sections
+  void find_gnu_debug_files ();
+
+  DwrSec *get_dwr_section (const char *sec_name);  // Used in Dwarf reader
   const char *get_funcname_in_plt (uint64_t pc);
   char *get_location ();
   char *dump ();
@@ -126,6 +134,7 @@ public:
   Elf_status status;
   Vector<Elf*> *ancillary_files;
   Elf *gnu_debug_file;
+  Elf *gnu_debugalt_file;  // if the .gun_debugaltlink section presents
   DbeFile *dbeFile;
   Map<const char*, Symbol*> *elfSymbols;
   unsigned int analyzerInfo, stab, stabStr;
@@ -139,6 +148,7 @@ protected:
   int elf_datatype;
   Elf_Internal_Ehdr *ehdrp;
   Elf_Data **data;
+  DwrSec **sections;
   bfd *abfd;
   static int bfd_status;
   long bfd_symcnt;
diff --git a/gprofng/src/Experiment.cc b/gprofng/src/Experiment.cc
index 4cbb7f6d33b..27689277391 100644
--- a/gprofng/src/Experiment.cc
+++ b/gprofng/src/Experiment.cc
@@ -6811,7 +6811,8 @@ Experiment::copy_file_to_common_archive (const char *name, const char *aname,
  * @return 0 - success
  */
 int
-Experiment::copy_file (char *name, char *aname, int hide_msg, char *common_archive, int relative_path)
+Experiment::copy_file (const char *name, const char *aname, int hide_msg,
+		       const char *common_archive, int relative_path)
 {
   if (common_archive)
     {
diff --git a/gprofng/src/Experiment.h b/gprofng/src/Experiment.h
index c85aadd5181..9a3d2262701 100644
--- a/gprofng/src/Experiment.h
+++ b/gprofng/src/Experiment.h
@@ -267,8 +267,8 @@ public:
   static int copy_file_to_archive (const char *name, const char *aname, int hide_msg);
   static int copy_file_to_common_archive (const char *name, const char *aname,
 	       int hide_msg, const char *common_archive, int relative_path = 0);
-  static int copy_file (char *name, char *aname, int hide_msg,
-			char *common_archive = NULL, int relative_path = 0);
+  static int copy_file (const char *name, const char *aname, int hide_msg,
+		      const char *common_archive = NULL, int relative_path = 0);
 
   // get_raw_events()
   // action: get unfiltered packets, loading them if required
diff --git a/gprofng/src/LoadObject.cc b/gprofng/src/LoadObject.cc
index bf49e9d24a8..7b4bef2aadb 100644
--- a/gprofng/src/LoadObject.cc
+++ b/gprofng/src/LoadObject.cc
@@ -102,7 +102,6 @@ LoadObject::LoadObject (const char *loname)
   noname = dbeSession->createUnknownModule (this);
   modules->put (noname->get_name (), noname);
   pathname = NULL;
-  arch_name = NULL;
   runTimePath = NULL;
   objStabs = NULL;
   firstExp = NULL;
@@ -135,7 +134,6 @@ LoadObject::~LoadObject ()
   delete modules;
   delete elf_lo;
   free (pathname);
-  free (arch_name);
   free (runTimePath);
   delete objStabs;
   delete warnq;
@@ -167,45 +165,66 @@ LoadObject::get_elf ()
 	  {
 	  case Elf::ELF_ERR_CANT_OPEN_FILE:
 	    append_msg (CMSG_ERROR, GTXT ("Cannot open ELF file `%s'"), fnm);
-	    break;
+	    return NULL;
 	  case Elf::ELF_ERR_BAD_ELF_FORMAT:
 	  default:
 	    append_msg (CMSG_ERROR, GTXT ("Cannot read ELF header of `%s'"),
 			fnm);
-	    break;
+	    return NULL;
 	  }
+      if (dbeFile->inArchive)
+	{
+	  // Try to find gnu_debug and gnu debug_alt files in archive
+	  char *nm = dbe_sprintf ("%s_debug", fnm);
+          elf_lo->gnu_debug_file = Elf::elf_begin (nm);
+	  free (nm);
+	  if (elf_lo->gnu_debug_file)
+	    {
+	      nm = dbe_sprintf ("%s_debug_alt", fnm);
+	      elf_lo->gnu_debug_file->gnu_debugalt_file = Elf::elf_begin (nm);
+	      free (nm);
+	    }
+	  nm = dbe_sprintf ("%s_alt", fnm);
+	  elf_lo->gnu_debugalt_file = Elf::elf_begin (nm);
+	  free (nm);
+	}
+      else if (checksum != 0 && elf_lo->elf_checksum () != 0 &&
+	  checksum != elf_lo->elf_checksum ())
+	{
+	  char *msg = dbe_sprintf (GTXT ("%s has an unexpected checksum value;"
+				  "perhaps it was rebuilt. File ignored"),
+				  dbeFile->get_location ());
+	  commentq->append (new Emsg (CMSG_ERROR, msg));
+	  delete msg;
+	  delete elf_lo;
+	  elf_lo = NULL;
+	  return NULL;
+	}
+      elf_lo->find_gnu_debug_files ();
+      elf_lo->find_ancillary_files (get_pathname ());
     }
   return elf_lo;
 }
 
 Stabs *
-LoadObject::openDebugInfo (char *fname, Stabs::Stab_status *stp)
+LoadObject::openDebugInfo (Stabs::Stab_status *stp)
 {
   if (objStabs == NULL)
     {
-      if (fname == NULL)
-	return NULL;
-      objStabs = new Stabs (fname, get_pathname ());
-      Stabs::Stab_status st = objStabs->get_status ();
-      if ((st == Stabs::DBGD_ERR_NONE) && (checksum != 0))
+      Stabs::Stab_status st = Stabs::DBGD_ERR_BAD_ELF_LIB;
+      Elf *elf = get_elf ();
+      if (elf)
 	{
-	  Elf *elf = get_elf ();
-	  if (elf && (checksum != elf->elf_checksum ()))
+	  objStabs = new Stabs (elf, get_pathname ());
+	  st = objStabs->get_status ();
+	  if (st != Stabs::DBGD_ERR_NONE)
 	    {
-	      char *buf = dbe_sprintf (GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"),
-				       fname);
-	      commentq->append (new Emsg (CMSG_ERROR, buf));
-	      delete buf;
-	      st = Stabs::DBGD_ERR_CHK_SUM;
+	      delete objStabs;
+	      objStabs = NULL;
 	    }
 	}
       if (stp)
 	*stp = st;
-      if (st != Stabs::DBGD_ERR_NONE)
-	{
-	  delete objStabs;
-	  objStabs = NULL;
-	}
     }
   return objStabs;
 }
@@ -560,7 +579,7 @@ fixFuncAlias (Vector<Function*> *SymLst)
 void
 LoadObject::post_process_functions ()
 {
-  if (flags & SEG_FLAG_DYNAMIC || platform == Java)
+  if ((flags & SEG_FLAG_DYNAMIC) != 0 || platform == Java)
     return;
 
   char *msg = GTXT ("Processing Load Object Data");
@@ -726,21 +745,8 @@ LoadObject::read_stabs ()
 	  delete msg;
 	  return ARCHIVE_ERR_OPEN;
 	}
-      else if (checksum != 0 && checksum != elf->elf_checksum ())
-	{
-	  char *msg = dbe_sprintf (GTXT ("%s has an unexpected checksum value;"
-					"perhaps it was rebuilt. File ignored"),
-				   dbeFile->get_location ());
-	  commentq->append (new Emsg (CMSG_ERROR, msg));
-	  delete msg;
-	  return ARCHIVE_ERR_OPEN;
-	}
       Stabs::Stab_status status = Stabs::DBGD_ERR_CANT_OPEN_FILE;
-      char *location = dbeFile->get_location (true);
-      if (location == NULL)
-	return ARCHIVE_ERR_OPEN;
-
-      if (openDebugInfo (location, &status))
+      if (openDebugInfo (&status))
 	{
 	  status = objStabs->read_archive (this);
 	  isRelocatable = objStabs->is_relocatable ();
diff --git a/gprofng/src/LoadObject.h b/gprofng/src/LoadObject.h
index dd40ea0a050..c93594b9338 100644
--- a/gprofng/src/LoadObject.h
+++ b/gprofng/src/LoadObject.h
@@ -117,13 +117,6 @@ public:
     return pathname;
   }
 
-  void
-  set_archname (char *aname)
-  {
-    free (arch_name);
-    arch_name = aname;
-  }
-
   bool
   is_relocatable ()
   {
@@ -144,7 +137,7 @@ public:
   Module *get_comparable_Module (Module *mod);
   void append_module (Module *mod);
   Elf *get_elf ();
-  Stabs *openDebugInfo (char *fname, Stabs::Stab_status *stp = NULL);
+  Stabs *openDebugInfo (Stabs::Stab_status *stp = NULL);
   Arch_status read_stabs ();
   Arch_status sync_read_stabs ();
   void post_process_functions ();
@@ -192,7 +185,6 @@ private:
   char *pathname;               // User name of object file
   ino64_t inode;                // inode number of segment file
   bool isRelocatable;           // is relocatable .o
-  char *arch_name;              // .archive name
   Emsgqueue *warnq;
   Emsgqueue *commentq;
   Function **funcHTable;        // hash table for functions
diff --git a/gprofng/src/Module.cc b/gprofng/src/Module.cc
index a62d3e8dc77..55091ad619e 100644
--- a/gprofng/src/Module.cc
+++ b/gprofng/src/Module.cc
@@ -131,7 +131,7 @@ Stabs *
 Module::openDebugInfo ()
 {
   setFile ();
-  objStabs = loadobject->openDebugInfo (disPath);
+  objStabs = loadobject->openDebugInfo ();
   return objStabs;
 }
 
diff --git a/gprofng/src/Stabs.cc b/gprofng/src/Stabs.cc
index 53f7ef1c3df..116316ed5b6 100644
--- a/gprofng/src/Stabs.cc
+++ b/gprofng/src/Stabs.cc
@@ -163,9 +163,11 @@ Stabs::removeDupSyms ()
   SymLst->truncate (last);
 }
 
-Stabs::Stabs (char *_path, char *_lo_name)
+Stabs::Stabs (Elf *elf, char *_lo_name)
 {
-  path = dbe_strdup (_path);
+  elfDis = elf;
+  elfDbg = elf->gnu_debug_file ? elf->gnu_debug_file : elf;
+  path = dbe_strdup (elf->get_location ());
   lo_name = dbe_strdup (_lo_name);
   SymLstByName = NULL;
   pltSym = NULL;
@@ -175,16 +177,12 @@ Stabs::Stabs (char *_path, char *_lo_name)
   LocalFileIdx = new Vector<int>;
   last_PC_to_sym = NULL;
   dwarf = NULL;
-  elfDbg = NULL;
-  elfDis = NULL;
   stabsModules = NULL;
   textsz = 0;
   wsize = Wnone;
   st_check_symtab = false;
   status = DBGD_ERR_NONE;
 
-  if (openElf (false) == NULL)
-    return;
   switch (elfDis->elf_getclass ())
     {
     case ELFCLASS32:
@@ -194,6 +192,31 @@ Stabs::Stabs (char *_path, char *_lo_name)
       wsize = W64;
       break;
     }
+  switch (elfDis->elf_getehdr ()->e_machine)
+    {
+    case EM_SPARC:
+      platform = Sparc;
+      break;
+    case EM_SPARC32PLUS:
+      platform = Sparcv8plus;
+      break;
+    case EM_SPARCV9:
+      platform = Sparcv9;
+      break;
+    case EM_386:
+      //    case EM_486:
+      platform = Intel;
+      break;
+    case EM_X86_64:
+      platform = Amd64;
+      break;
+    case EM_AARCH64:
+      platform = Aarch64;
+      break;
+    default:
+      platform = Unknown;
+      break;
+    }
   isRelocatable = elfDis->elf_getehdr ()->e_type == ET_REL;
   for (unsigned int pnum = 0; pnum < elfDis->elf_getehdr ()->e_phnum; pnum++)
     {
@@ -216,7 +239,6 @@ Stabs::~Stabs ()
   delete SymLstByName;
   Destroy (SymLst);
   Destroy (LocalFile);
-  delete elfDis;
   delete dwarf;
   delete LocalLst;
   delete LocalFileIdx;
@@ -225,91 +247,12 @@ Stabs::~Stabs ()
   free (lo_name);
 }
 
-Elf *
-Stabs::openElf (char *fname, Stab_status &st)
-{
-  Elf::Elf_status elf_status;
-  Elf *elf = Elf::elf_begin (fname, &elf_status);
-  if (elf == NULL)
-    {
-      switch (elf_status)
-	{
-	case Elf::ELF_ERR_CANT_OPEN_FILE:
-	case Elf::ELF_ERR_CANT_MMAP:
-	case Elf::ELF_ERR_BIG_FILE:
-	  st = DBGD_ERR_CANT_OPEN_FILE;
-	  break;
-	case Elf::ELF_ERR_BAD_ELF_FORMAT:
-	default:
-	  st = DBGD_ERR_BAD_ELF_FORMAT;
-	  break;
-	}
-      return NULL;
-    }
-  if (elf->elf_version (EV_CURRENT) == EV_NONE)
-    {
-      // ELF library out of date
-      delete elf;
-      st = DBGD_ERR_BAD_ELF_LIB;
-      return NULL;
-    }
-
-  Elf_Internal_Ehdr *ehdrp = elf->elf_getehdr ();
-  if (ehdrp == NULL)
-    {
-      // check machine
-      delete elf;
-      st = DBGD_ERR_BAD_ELF_FORMAT;
-      return NULL;
-    }
-  switch (ehdrp->e_machine)
-    {
-    case EM_SPARC:
-      platform = Sparc;
-      break;
-    case EM_SPARC32PLUS:
-      platform = Sparcv8plus;
-      break;
-    case EM_SPARCV9:
-      platform = Sparcv9;
-      break;
-    case EM_386:
-      //    case EM_486:
-      platform = Intel;
-      break;
-    case EM_X86_64:
-      platform = Amd64;
-      break;
-    case EM_AARCH64:
-      platform = Aarch64;
-      break;
-    default:
-      platform = Unknown;
-      break;
-    }
-  return elf;
-}
-
 Elf *
 Stabs::openElf (bool dbg_info)
 {
-  if (status != DBGD_ERR_NONE)
-    return NULL;
-  if (elfDis == NULL)
-    {
-      elfDis = openElf (path, status);
-      if (elfDis == NULL)
-	return NULL;
-    }
-  if (!dbg_info)
-    return elfDis;
-  if (elfDbg == NULL)
-    {
-      elfDbg = elfDis->find_ancillary_files (lo_name);
-      if (elfDbg == NULL)
-	elfDbg = elfDis;
-    }
-  return elfDbg;
+  if (dbg_info)
+    return elfDbg;
+  return elfDis;
 }
 
 bool
diff --git a/gprofng/src/Stabs.h b/gprofng/src/Stabs.h
index f0e162b8fa6..cd10c255c0c 100644
--- a/gprofng/src/Stabs.h
+++ b/gprofng/src/Stabs.h
@@ -76,7 +76,7 @@ class Stabs {
 	DBGD_ERR_CHK_SUM
     };
 
-    Stabs(char *_path, char *_lo_name);
+    Stabs(Elf *elf, char *_lo_name);
     ~Stabs();
 
     bool	is_relocatable(){ return isRelocatable; }
@@ -136,7 +136,6 @@ class Stabs {
     Vector<char*>	*LocalFile;		// list of local files
     Vector<int>		*LocalFileIdx;		// start index in LocalLst
 
-    Elf         *openElf(char *fname, Stab_status &st);
     Map<const char*, Symbol*> *get_elf_symbols();
     Dwarf       *dwarf;
 
diff --git a/gprofng/src/gp-archive.cc b/gprofng/src/gp-archive.cc
index ee9f91784ab..2c15da865be 100644
--- a/gprofng/src/gp-archive.cc
+++ b/gprofng/src/gp-archive.cc
@@ -357,25 +357,59 @@ er_archive::start (int argc, char *argv[])
 	}
       lo->sync_read_stabs ();
       Elf *elf = lo->get_elf ();
-      if (elf && (lo->checksum != 0) && (lo->checksum != elf->elf_checksum ()))
+      if (elf == NULL)
 	{
 	  if (!quiet)
-	    fprintf (stderr, GTXT ("gp-archive: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored\n"),
+	    fprintf (stderr, GTXT ("gp-archive: Cannot open \"%s\"\n"),
 		       df->get_location ());
+	  Dprintf (DEBUG_ARCHIVE,
+		  " loadObjs[%ld]: not found '%s'\n", i, df->get_location ());
+	  continue;
+	}
+      else if (df->inArchive)
+	{
+	  Dprintf (DEBUG_ARCHIVE,
+		  " loadObjs[%ld]: inArchive=1 '%s'\n", i, df->get_name ());
 	  continue;
 	}
-      copy_files->append (df);
-      if (elf)
+      else if (!mask_is_on (df->get_name ()))
+	{
+	  Dprintf (DEBUG_ARCHIVE,
+		" loadObjs[%ld]: mask_is_on=0 '%s'\n", i, df->get_name ());
+	  continue;
+	}
+      char *fnm = elf->get_location ();
+      char *anm = founder_exp->getNameInArchive (fnm);
+      archive_file (fnm, anm);
+
+      // archive gnu_debug and gnu_debugalt files
+      if (elf->gnu_debug_file)
 	{
-	  Elf *f = elf->find_ancillary_files (lo->get_pathname ());
-	  if (f)
-	    copy_files->append (f->dbeFile);
-	  for (long i1 = 0, sz1 = VecSize(elf->ancillary_files); i1 < sz1; i1++)
+	  char *arch_nm = dbe_sprintf ("%s_debug", anm);
+	  archive_file (elf->gnu_debug_file->get_location (), arch_nm);
+	  free (arch_nm);
+	  if (elf->gnu_debug_file->gnu_debugalt_file)
 	    {
-	      Elf *ancElf = elf->ancillary_files->get (i1);
-	      copy_files->append (ancElf->dbeFile);
+	      arch_nm = dbe_sprintf ("%s_debug_alt", anm);
+	      archive_file (elf->gnu_debug_file->gnu_debugalt_file->get_location (), arch_nm);
+	      free (arch_nm);
 	    }
 	}
+      if (elf->gnu_debugalt_file)
+	{
+	  char *arch_nm = dbe_sprintf ("%s_alt", anm);
+	  archive_file (elf->gnu_debugalt_file->get_location (), arch_nm);
+	  free (arch_nm);
+	}
+      free (anm);
+
+      elf->find_ancillary_files (lo->get_pathname ());
+      for (long i1 = 0, sz1 = VecSize (elf->ancillary_files); i1 < sz1; i1++)
+	{
+	  Elf *ancElf = elf->ancillary_files->get (i1);
+	  copy_files->append (ancElf->dbeFile);
+	}
+
       Vector<Module*> *modules = lo->seg_modules;
       for (long i1 = 0, sz1 = VecSize(modules); i1 < sz1; i1++)
 	{
@@ -469,7 +503,7 @@ er_archive::start (int argc, char *argv[])
       int res = founder_exp->copy_file (fnm, anm, quiet, common_archive_dir, use_relative_path);
       if (0 == res)  // file successfully archived
 	df->inArchive = 1;
-      delete anm;
+      free (anm);
     }
   delete copy_files;
 
@@ -489,6 +523,15 @@ er_archive::start (int argc, char *argv[])
   delete notfound_files;
 }
 
+int
+er_archive::archive_file (const char *from, const char *to)
+{
+  if (force)
+    unlink (to);
+  return Experiment::copy_file (from, to, quiet, common_archive_dir,
+			  use_relative_path);
+}
+
 int
 er_archive::check_args (int argc, char *argv[])
 {
diff --git a/gprofng/src/gp-archive.h b/gprofng/src/gp-archive.h
index 41fb4b2d5e6..3b9d0eeab7d 100644
--- a/gprofng/src/gp-archive.h
+++ b/gprofng/src/gp-archive.h
@@ -47,6 +47,7 @@ public:
 private:
   void usage ();
   int check_args (int argc, char *argv[]);
+  int archive_file (const char *from, const char *to);
   int clean_old_archive (char *expname, ArchiveExp *founder_exp);
   int mask_is_on (const char *str);
   void check_env_var ();
-- 
2.43.5



More information about the Binutils mailing list