From: Vladimir Mezentsev Date: Mon, 7 Jul 2025 18:56:22 +0000 (-0700) Subject: gprofng: support external debug info X-Git-Tag: binutils-2_45~136 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=64fae1b70d3143824f73edfe14c9d8a7d4cc0c59;p=thirdparty%2Fbinutils-gdb.git gprofng: support external debug info 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 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. --- 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::dump (const char *msg) +{ + Dprintf (1, NTXT ("\nFile: %s Vector [%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 Vector; template 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 *ancillary_files; Elf *gnu_debug_file; + Elf *gnu_debugalt_file; // if the .gun_debugaltlink section presents DbeFile *dbeFile; Map *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 *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; 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 *LocalFile; // list of local files Vector *LocalFileIdx; // start index in LocalLst - Elf *openElf(char *fname, Stab_status &st); Map *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 *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 ();