mirror of
https://github.com/bminor/binutils-gdb.git
synced 2026-03-27 17:59:53 +00:00
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 <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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
Elf_Data *dp = elf_getdata (sec);
|
||||
if (dp)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -131,7 +131,7 @@ Stabs *
|
||||
Module::openDebugInfo ()
|
||||
{
|
||||
setFile ();
|
||||
objStabs = loadobject->openDebugInfo (disPath);
|
||||
objStabs = loadobject->openDebugInfo ();
|
||||
return objStabs;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,75 +192,7 @@ Stabs::Stabs (char *_path, char *_lo_name)
|
||||
wsize = W64;
|
||||
break;
|
||||
}
|
||||
isRelocatable = elfDis->elf_getehdr ()->e_type == ET_REL;
|
||||
for (unsigned int pnum = 0; pnum < elfDis->elf_getehdr ()->e_phnum; pnum++)
|
||||
{
|
||||
Elf_Internal_Phdr *phdr = elfDis->get_phdr (pnum);
|
||||
if (phdr->p_type == PT_LOAD && phdr->p_flags == (PF_R | PF_X))
|
||||
{
|
||||
if (textsz == 0)
|
||||
textsz = phdr->p_memsz;
|
||||
else
|
||||
{
|
||||
textsz = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stabs::~Stabs ()
|
||||
{
|
||||
delete SymLstByName;
|
||||
Destroy (SymLst);
|
||||
Destroy (LocalFile);
|
||||
delete elfDis;
|
||||
delete dwarf;
|
||||
delete LocalLst;
|
||||
delete LocalFileIdx;
|
||||
delete stabsModules;
|
||||
free (path);
|
||||
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)
|
||||
switch (elfDis->elf_getehdr ()->e_machine)
|
||||
{
|
||||
case EM_SPARC:
|
||||
platform = Sparc;
|
||||
@@ -287,29 +217,42 @@ Stabs::openElf (char *fname, Stab_status &st)
|
||||
platform = Unknown;
|
||||
break;
|
||||
}
|
||||
return elf;
|
||||
isRelocatable = elfDis->elf_getehdr ()->e_type == ET_REL;
|
||||
for (unsigned int pnum = 0; pnum < elfDis->elf_getehdr ()->e_phnum; pnum++)
|
||||
{
|
||||
Elf_Internal_Phdr *phdr = elfDis->get_phdr (pnum);
|
||||
if (phdr->p_type == PT_LOAD && phdr->p_flags == (PF_R | PF_X))
|
||||
{
|
||||
if (textsz == 0)
|
||||
textsz = phdr->p_memsz;
|
||||
else
|
||||
{
|
||||
textsz = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stabs::~Stabs ()
|
||||
{
|
||||
delete SymLstByName;
|
||||
Destroy (SymLst);
|
||||
Destroy (LocalFile);
|
||||
delete dwarf;
|
||||
delete LocalLst;
|
||||
delete LocalFileIdx;
|
||||
delete stabsModules;
|
||||
free (path);
|
||||
free (lo_name);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
copy_files->append (df);
|
||||
if (elf)
|
||||
else if (df->inArchive)
|
||||
{
|
||||
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++)
|
||||
Dprintf (DEBUG_ARCHIVE,
|
||||
" loadObjs[%ld]: inArchive=1 '%s'\n", i, df->get_name ());
|
||||
continue;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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[])
|
||||
{
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
Reference in New Issue
Block a user