diff options
Diffstat (limited to 'gprofng/src')
-rw-r--r-- | gprofng/src/DbeSession.cc | 11 | ||||
-rw-r--r-- | gprofng/src/DbeSession.h | 1 | ||||
-rw-r--r-- | gprofng/src/Disasm.cc | 17 | ||||
-rw-r--r-- | gprofng/src/Disasm.h | 3 | ||||
-rw-r--r-- | gprofng/src/Dwarf.cc | 208 | ||||
-rw-r--r-- | gprofng/src/Dwarf.h | 3 | ||||
-rw-r--r-- | gprofng/src/DwarfLib.cc | 559 | ||||
-rw-r--r-- | gprofng/src/DwarfLib.h | 54 | ||||
-rw-r--r-- | gprofng/src/Elf.cc | 225 | ||||
-rw-r--r-- | gprofng/src/Elf.h | 42 | ||||
-rw-r--r-- | gprofng/src/Experiment.cc | 12 | ||||
-rw-r--r-- | gprofng/src/Experiment.h | 5 | ||||
-rw-r--r-- | gprofng/src/LoadObject.cc | 83 | ||||
-rw-r--r-- | gprofng/src/LoadObject.h | 11 | ||||
-rw-r--r-- | gprofng/src/Module.cc | 2 | ||||
-rw-r--r-- | gprofng/src/Stabs.cc | 187 | ||||
-rw-r--r-- | gprofng/src/Stabs.h | 5 | ||||
-rw-r--r-- | gprofng/src/Symbol.cc | 14 | ||||
-rw-r--r-- | gprofng/src/Symbol.h | 10 | ||||
-rw-r--r-- | gprofng/src/gp-archive.cc | 65 | ||||
-rw-r--r-- | gprofng/src/gp-archive.h | 1 |
21 files changed, 742 insertions, 776 deletions
diff --git a/gprofng/src/DbeSession.cc b/gprofng/src/DbeSession.cc index f3426ce..b0aa745 100644 --- a/gprofng/src/DbeSession.cc +++ b/gprofng/src/DbeSession.cc @@ -2017,6 +2017,17 @@ DbeSession::is_omp_available () } bool +DbeSession::is_bigendian () +{ +#ifdef WORDS_BIGENDIAN + return true; +#else + return false; +#endif + +} + +bool DbeSession::has_java () { int status_has_java = 0; diff --git a/gprofng/src/DbeSession.h b/gprofng/src/DbeSession.h index 5cbddae..7db0998 100644 --- a/gprofng/src/DbeSession.h +++ b/gprofng/src/DbeSession.h @@ -120,6 +120,7 @@ public: bool is_timeline_available (); bool is_ifreq_available (); bool is_omp_available (); + static bool is_bigendian (); bool has_java (); bool has_ompavail (); diff --git a/gprofng/src/Disasm.cc b/gprofng/src/Disasm.cc index 42fb777..3ee50d7 100644 --- a/gprofng/src/Disasm.cc +++ b/gprofng/src/Disasm.cc @@ -50,19 +50,6 @@ struct DisContext static const int MAX_DISASM_STR = 2048; -Disasm::Disasm (char *fname) -{ - dwin = NULL; - dis_str = NULL; - need_swap_endian = false; - my_stabs = Stabs::NewStabs (fname, fname); - if (my_stabs == NULL) - return; - stabs = my_stabs; - platform = stabs->get_platform (); - disasm_open (); -} - Disasm::Disasm (Platform_t _platform, Stabs *_stabs) { dwin = NULL; @@ -70,7 +57,6 @@ Disasm::Disasm (Platform_t _platform, Stabs *_stabs) need_swap_endian = false; stabs = _stabs; platform = _platform; - my_stabs = NULL; disasm_open (); } @@ -263,7 +249,6 @@ Disasm::disasm_open () Disasm::~Disasm () { - delete my_stabs; delete dwin; delete dis_str; } @@ -370,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/Disasm.h b/gprofng/src/Disasm.h index 0326b5c..3d7159d 100644 --- a/gprofng/src/Disasm.h +++ b/gprofng/src/Disasm.h @@ -31,7 +31,6 @@ enum Platform_t; class Disasm { public: - Disasm (char *fname); Disasm (Platform_t _platform, Stabs *_stabs); ~Disasm (); void remove_disasm_hndl (void *hndl); @@ -59,7 +58,7 @@ private: disassemble_info dis_info; Data_window *dwin; - Stabs *stabs, *my_stabs; + Stabs *stabs; Platform_t platform; char addr_fmt[32]; int hex_visible; diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc index 23ac5b9..934ae44 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; @@ -378,18 +379,14 @@ Dwarf::Dwarf (Stabs *_stabs) return; } debug_infoSec = dwrGetSec (NTXT (".debug_info")); - if (debug_infoSec) - { - debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rela.debug_info"), NULL); - debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rel.debug_info"), debug_infoSec->reloc); - if (debug_infoSec->reloc) - debug_infoSec->reloc->dump (); - } debug_abbrevSec = dwrGetSec (NTXT (".debug_abbrev")); debug_strSec = dwrGetSec (NTXT (".debug_str")); debug_lineSec = dwrGetSec (NTXT (".debug_line")); 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)) { @@ -400,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 @@ -496,9 +482,24 @@ DwrCU::parseChild (Dwarf_cnt *ctx) break; case DW_TAG_subprogram: { - if (dwrTag.get_attr (DW_AT_abstract_origin)) - break; Symbol *sym = NULL; + Vector<Symbol *> *syms = NULL; + Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_abstract_origin); + if (dwrAttr) + { + // Set up functions from DW_AT_{ranges,low_pc,linkage_name} + set_up_funcs (dwrAttr->u.offset); + break; + } + + dwrAttr = dwrTag.get_attr (DW_AT_specification); + if (dwrAttr) + { + // Set up functions from DW_AT_{ranges,low_pc,linkage_name} + set_up_funcs (dwrAttr->u.offset); + break; + } + if (dwrTag.get_attr (DW_AT_declaration)) { // Only declaration @@ -508,58 +509,26 @@ DwrCU::parseChild (Dwarf_cnt *ctx) if (link_name && streq (link_name, NTXT ("MAIN"))) 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; + } + sym = Symbol::get_symbol (symbols_sorted_by_name, + get_linkage_name ()); + if (sym != NULL) func = append_Function (sym, ctx->name); - break; + break; } - Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_specification); - if (dwrAttr) + func = NULL; + syms = get_symbols (tmp_syms); + for (int i = 0, sz = VecSize (syms); i < sz; i++) { - // 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 = syms->get (i); + func = append_Function (sym, ctx->name); + if (Stabs::is_fortran (ctx->module->lang_code) && + streq (func->get_match_name (), "MAIN")) + ctx->fortranMAIN = func; } - - 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) + if (func == 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; @@ -712,14 +681,6 @@ 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) { @@ -741,7 +702,6 @@ Dwarf::get_ranges (uint64_t offset) break; ranges->append (new Range (low_pc, high_pc)); } - ranges->sort (rangeCmp); return ranges; } @@ -1127,3 +1087,93 @@ DwrCU::Dwarf_lang () return Sp_lang_unknown; } } + +Vector <Dwr_rng_entry *> * +Dwarf::get_debug_rnglists () +{ + if (debug_rnglists != NULL) + return debug_rnglists; + debug_rnglists = new Vector <Dwr_rng_entry *> (); + + DwrSec *debug_rnglistsSec = dwrGetSec (".debug_rnglists"); + if (debug_rnglistsSec == NULL) + { + Dprintf (1, "No section .debug_rnglists\n"); + return debug_rnglists; + } + while (debug_rnglistsSec->offset < debug_rnglistsSec->sizeSec) + { + uint64_t base_address = 0; + uint64_t length = debug_rnglistsSec->ReadLength (); + Dwr_rng_entry *rng = new Dwr_rng_entry (); + debug_rnglists->append (rng); + rng->offset = debug_rnglistsSec->offset; + rng->length = length; + rng->fmt64 = debug_rnglistsSec->fmt64; + rng->version = debug_rnglistsSec->Get_16 (); + rng->address_size = debug_rnglistsSec->Get_8 (); + rng->segment_selector_size = debug_rnglistsSec->Get_8 (); + rng->offset_entry_count = debug_rnglistsSec->Get_32 (); + while (debug_rnglistsSec->offset < debug_rnglistsSec->size) + { + uint64_t off = debug_rnglistsSec->offset; + uint64_t low_pc; + uint64_t high_pc; + int re = debug_rnglistsSec->Get_8 (); + switch (re) + { + case DW_RLE_end_of_list: + low_pc = 0; + high_pc = 0; + break; + case DW_RLE_base_address: + base_address = debug_rnglistsSec->GetADDR (); + low_pc = base_address; + high_pc = 0; + continue; + case DW_RLE_start_length: + low_pc = debug_rnglistsSec->GetADDR (); + high_pc = low_pc + debug_rnglistsSec->GetULEB128 (); + break; + case DW_RLE_offset_pair: + low_pc = base_address + debug_rnglistsSec->GetULEB128 (); + high_pc = base_address + debug_rnglistsSec->GetULEB128 (); + break; + case DW_RLE_start_end: + low_pc = debug_rnglistsSec->GetADDR (); + high_pc = debug_rnglistsSec->GetADDR (); + break; + case DW_RLE_base_addressx: + base_address = debug_rnglistsSec->GetULEB128 (); + low_pc = base_address; + high_pc = 0; + continue; + + // TODO x-variants need .debug_addr support used for split-dwarf + case DW_RLE_startx_endx: + low_pc = debug_rnglistsSec->GetRef (); + high_pc = debug_rnglistsSec->GetRef (); + Dprintf (1, "DW_RLE_startx_endx is not implemented\n"); + continue; + case DW_RLE_startx_length: + low_pc = debug_rnglistsSec->GetRef (); + high_pc = low_pc + debug_rnglistsSec->GetULEB128 (); + Dprintf (1, "DW_RLE_startx_length is not implemented\n"); + continue; + default: + Dprintf (1, "Unknown tag DW_RLE: %d, offset=0x%llx\n", re, + (long long) off); + debug_rnglistsSec->offset = debug_rnglistsSec->size; + continue; + } + Dprintf (DUMP_DWARFLIB, "0x%08llx %d-%-20s [0x%08llx - 0x%08llx)\n", + (long long) off, re, Dwr_rng_entry::rng_entry2str (re), + (long long) low_pc, (long long) high_pc); + rng->ranges->append (new ExtRange (off, low_pc, high_pc)); + } + debug_rnglistsSec->size = debug_rnglistsSec->sizeSec; + debug_rnglistsSec->offset = length; + } + debug_rnglists->dump ("Dwarf::get_debug_rnglists"); + return debug_rnglists; +} diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h index f46ad3f..14d9878 100644 --- a/gprofng/src/Dwarf.h +++ b/gprofng/src/Dwarf.h @@ -71,12 +71,14 @@ public: void srcline_Dwarf (Module *module); void read_hwcprof_info (Module *module); Vector<Range *> *get_ranges (uint64_t offset); + Vector <Dwr_rng_entry *> *get_debug_rnglists (); Stabs::Stab_status status; Vector<DwrCU *> *dwrCUs; DwrSec *debug_infoSec; DwrSec *debug_abbrevSec; DwrSec *debug_strSec; + DwrSec *debug_alt_strSec; DwrSec *debug_lineSec; DwrSec *debug_line_strSec; DwrSec *debug_rangesSec; @@ -84,6 +86,7 @@ public: Stabs *stabs; private: + Vector <Dwr_rng_entry *> *debug_rnglists; DwrSec *dwrGetSec (const char *sec_name); }; diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc index 9f55ab3..4720ef1 100644 --- a/gprofng/src/DwarfLib.cc +++ b/gprofng/src/DwarfLib.cc @@ -35,31 +35,6 @@ #define CASE_S(x) case x: s = (char *) #x; break static char * -gelf_st_type2str (int type) -{ - static char buf[128]; - char *s; - switch (type) - { - CASE_S (STT_NOTYPE); - CASE_S (STT_OBJECT); - CASE_S (STT_FUNC); - CASE_S (STT_SECTION); - CASE_S (STT_FILE); - CASE_S (STT_COMMON); - CASE_S (STT_TLS); - // CASE_S(STT_NUM); - CASE_S (STT_LOPROC); - CASE_S (STT_HIPROC); - default: s = NTXT ("???"); - break; - } - snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type); - buf[sizeof (buf) - 1] = 0; - return buf; -} - -static char * special_opcode2str (int opcode) { static char buf[128]; @@ -78,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; @@ -166,234 +142,6 @@ get_string (DwrSec *sec, uint64_t off) return NULL; } - -////////////////////////////////////////////////////////// -// class ElfReloc - -ElfReloc::ElfReloc (Elf *_elf) -{ - elf = _elf; - reloc = NULL; - cur_reloc_ind = 0; -} - -ElfReloc::~ElfReloc () -{ - if (reloc) - { - reloc->destroy (); - delete reloc; - } -} - -void -ElfReloc::dump_rela_debug_sec (int sec) -{ - if (!DUMP_RELA_SEC) - return; - Elf_Internal_Shdr *shdr = elf->get_shdr (sec); - if (shdr == NULL) - return; - - Elf_Data *data = elf->elf_getdata (sec); - if (data == NULL) - return; - - uint64_t ScnSize = data->d_size; - uint64_t EntSize = shdr->sh_entsize; - if (ScnSize == 0 || EntSize == 0) - return; - - Elf_Internal_Rela rela; - int n, cnt = (int) (ScnSize / EntSize); - - char *sec_name = elf->get_sec_name (sec); - if (sec_name == NULL) // It can not be, but let's check - return; - Dprintf (DUMP_RELA_SEC, - "======= DwarfLib::dump_rela_debug_sec Section:%2d '%s'\n", - sec, sec_name); - Dprintf (DUMP_RELA_SEC, - " N |addend| offset | r_info | stt_type |\n"); - for (n = 0; n < cnt; n++) - { - if (strncmp (sec_name, NTXT (".rela."), 6) == 0) - elf->elf_getrela (data, n, &rela); - else - { - elf->elf_getrel (data, n, &rela); - rela.r_addend = 0; - } - int ndx = (int) GELF_R_SYM (rela.r_info); - Elf_Internal_Shdr *secHdr; - Elf_Internal_Sym sym; - asymbol *asym; - asym = elf->elf_getsym (ndx, &sym, false); - Dprintf (DUMP_RELA_SEC, NTXT ("%3d:%5d |%11lld |0x%016llx | %-15s|"), - n, (int) rela.r_addend, - (long long) rela.r_offset, (long long) rela.r_info, - gelf_st_type2str ((int) GELF_ST_TYPE (sym.st_info))); - switch (GELF_ST_TYPE (sym.st_info)) - { - case STT_FUNC: - case STT_OBJECT: - case STT_NOTYPE: - Dprintf (DUMP_RELA_SEC, NTXT (" img_offset=0x%llx"), - (long long) (bfd_asymbol_value (asym))); - Dprintf (DUMP_RELA_SEC, NTXT (" %s"), bfd_asymbol_name (asym)); - break; - case STT_SECTION: - secHdr = elf->get_shdr (sym.st_shndx); - if (secHdr) - { - Dprintf (DUMP_RELA_SEC, NTXT (" value=0x%016llx (%lld)"), - (long long) (secHdr->sh_offset + rela.r_addend), - (long long) (secHdr->sh_offset + rela.r_addend)); - } - break; - default: - break; - } - Dprintf (DUMP_RELA_SEC, NTXT ("\n")); - } - Dprintf (DUMP_RELA_SEC, NTXT ("\n")); -} - -void -ElfReloc::dump () -{ - if (!DUMP_ELF_RELOC || (reloc == NULL) || (reloc->size () == 0)) - return; - Dprintf (DUMP_ELF_RELOC, NTXT ("======= ElfReloc::dump\n")); - Dprintf (DUMP_ELF_RELOC, NTXT (" N | offset | value | STT_TYPE\n")); - for (int i = 0; i < reloc->size (); i++) - { - Sreloc *srlc = reloc->fetch (i); - Dprintf (DUMP_ELF_RELOC, NTXT ("%3d:%11lld |%11lld | %s\n"), - i, (long long) srlc->offset, (long long) srlc->value, - gelf_st_type2str (srlc->stt_type)); - } - Dprintf (DUMP_ELF_RELOC, NTXT ("\n")); -} - -static int -DwrRelocOffsetCmp (const void *a, const void *b) -{ - ElfReloc::Sreloc *item1 = *((ElfReloc::Sreloc **) a); - ElfReloc::Sreloc *item2 = *((ElfReloc::Sreloc **) b); - return item1->offset < item2->offset ? -1 : - item1->offset == item2->offset ? 0 : 1; -} - -ElfReloc * -ElfReloc::get_elf_reloc (Elf *elfp, char *sec_name, ElfReloc *rlc) -{ - int et = elfp->elf_getehdr ()->e_type; - if (et == ET_EXEC || et == ET_DYN) - return rlc; - int sec = elfp->elf_get_sec_num (sec_name); - if (sec == 0) - return rlc; - Elf_Internal_Shdr *shdr = elfp->get_shdr (sec); - if (shdr == NULL || shdr->sh_entsize == 0) - return rlc; - - Elf_Data *data = elfp->elf_getdata (sec); - if (data == NULL || data->d_size == 0) - return rlc; - - int cnt = (int) (data->d_size / shdr->sh_entsize); - Vector<Sreloc *> *vp = NULL; - - for (int n = 0; n < cnt; n++) - { - Elf_Internal_Shdr *secHdr; - Sreloc *srlc; - Elf_Internal_Rela rela; - if (strncmp (sec_name, NTXT (".rela."), 6) == 0) - elfp->elf_getrela (data, n, &rela); - else - { - elfp->elf_getrel (data, n, &rela); - rela.r_addend = 0; - } - int ndx = (int) GELF_R_SYM (rela.r_info); - Elf_Internal_Sym sym; - elfp->elf_getsym (ndx, &sym, false); - - srlc = new Sreloc; - srlc->offset = rela.r_offset; - srlc->value = 0; - srlc->stt_type = (int) GELF_ST_TYPE (sym.st_info); - switch (GELF_ST_TYPE (sym.st_info)) - { - case STT_FUNC: - secHdr = elfp->get_shdr (sym.st_shndx); - if (secHdr) - srlc->value = secHdr->sh_offset + sym.st_value; - break; - case STT_OBJECT: - case STT_NOTYPE: - secHdr = elfp->get_shdr (shdr->sh_info); - if (secHdr) - { - srlc->offset = rela.r_info; - srlc->value = secHdr->sh_offset + rela.r_addend; - } - break; - case STT_SECTION: - secHdr = elfp->get_shdr (sym.st_shndx); - if (secHdr) - srlc->value = rela.r_addend; - break; - default: - srlc->value = 0; - break; - } - if (rlc == NULL) - { - rlc = new ElfReloc (elfp); - vp = rlc->reloc; - } - if (vp == NULL) - { - vp = new Vector<Sreloc*>; - rlc->reloc = vp; - } - vp->append (srlc); - } - if (vp) - vp->sort (DwrRelocOffsetCmp); - if (rlc) - { - rlc->dump_rela_debug_sec (sec); - rlc->dump (); - } - return rlc; -} - -long long -ElfReloc::get_reloc_addr (long long offset) -{ - Sreloc *srlc; - int i = cur_reloc_ind - 1; - if (i >= 0 && i < reloc->size ()) - { - srlc = reloc->fetch (i); - if (srlc->offset > offset) // need to reset - cur_reloc_ind = 0; - } - for (; cur_reloc_ind < reloc->size (); cur_reloc_ind++) - { - srlc = reloc->fetch (cur_reloc_ind); - if (srlc->offset == offset) - return srlc->value; - if (srlc->offset > offset) - return 0; - } - return 0; -} - DwrLocation * DwrCU::dwr_get_location (DwrSec *secp, DwrLocation *lp) { @@ -936,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); @@ -993,12 +743,12 @@ 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: case DW_FORM_strx3: case DW_FORM_strx4: - case DW_FORM_implicit_const: Dprintf (DUMP_DWARFLIB, " \"%s\"", atrp->u.str ? atrp->u.str : "<NULL>"); break; case DW_FORM_block: @@ -1034,9 +784,11 @@ 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: + case DW_FORM_implicit_const: Dprintf (DUMP_DWARFLIB, " 0x%llx (%lld)", (long long) atrp->u.val, (long long) atrp->u.val); break; @@ -1058,34 +810,28 @@ Dwr_Tag::dump () DwrSec::DwrSec (unsigned char *_data, uint64_t _size, bool _need_swap_endian, bool _addr32) { - isCopy = false; data = _data; sizeSec = _size; size = (data ? _size : 0); offset = 0; fmt64 = false; - reloc = NULL; need_swap_endian = _need_swap_endian; addr32 = _addr32; } DwrSec::DwrSec (DwrSec *secp, uint64_t _offset) { - isCopy = true; data = secp->data; sizeSec = secp->sizeSec; size = secp->size; offset = _offset; fmt64 = secp->fmt64; - reloc = secp->reloc; need_swap_endian = secp->need_swap_endian; addr32 = secp->addr32; } DwrSec::~DwrSec () { - if (!isCopy) - delete reloc; } bool @@ -1095,6 +841,7 @@ DwrSec::bounds_violation (uint64_t sz) { Dprintf (DEBUG_ERR_MSG, "DwrSec::bounds_violation: offset=%lld + sz=%lld > size=%lld\n", (long long) offset, (long long) sz, (long long) size); + offset = size; return true; } return false; @@ -1212,17 +959,13 @@ DwrSec::GetLong () uint64_t DwrSec::GetADDR_32 () { - uint64_t res = reloc ? reloc->get_reloc_addr (offset) : 0; - res += Get_32 (); - return res; + return Get_32 (); } uint64_t DwrSec::GetADDR_64 () { - uint64_t res = reloc ? reloc->get_reloc_addr (offset) : 0; - res += Get_64 (); - return res; + return Get_64 (); } uint64_t @@ -1282,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 (); @@ -1545,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: @@ -1795,6 +1541,10 @@ DwrLineRegs::getPath (int fn) DwrCU::DwrCU (Dwarf *_dwarf) { dwarf = _dwarf; + tmp_syms = new Vector<Symbol*>(); + rng_list = NULL; + rng_list_inited = false; + base_address = 0; symbols = NULL; symbols_sorted_by_name = NULL; cu_offset = dwarf->debug_infoSec->offset; @@ -1838,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" @@ -1846,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, @@ -1887,6 +1638,7 @@ DwrCU::~DwrCU () delete dwrLineReg; delete symbols; delete symbols_sorted_by_name; + delete tmp_syms; free (comp_dir); } @@ -1929,7 +1681,7 @@ DwrCU::build_abbrevTable (DwrSec *_debug_abbrevSec, uint64_t _offset) switch (atf.at_form) { case DW_FORM_implicit_const: - atf.len = debug_abbrevSec->GetSLEB128 (); + atf.u.val = debug_abbrevSec->GetSLEB128 (); break; } abbrevAtForm->append (atf); @@ -2044,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; @@ -2067,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); @@ -2113,7 +1872,7 @@ DwrCU::set_die (Dwarf_Die die) atf->len = 0; break; case DW_FORM_implicit_const: - atf->u.str = NULL; + // atf->u.val is already set break; default: DEBUG_CODE @@ -2193,17 +1952,46 @@ DwrCU::parse_cu_header (LoadObject *lo) module->set_name (path); // create a list of functions in this CU + base_address = get_low_pc (); 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); + symbols = Symbol::find_symbols (syms, ranges, new Vector <Symbol *> ()); + symbols_sorted_by_name = Symbol::sort_by_name (symbols); + if (DUMP_ELF_SYM) + symbols->dump ("DwrCU::parse_cu_header: symbols"); Destroy (ranges); } return module; } + +static int +cmp_ExtRange (const void *a, const void *b) +{ + uint64_t a1 = *((uint64_t *) a); + ExtRange *rng = *((ExtRange **) b); + uint64_t b1 = rng->offset; + return a1 < b1 ? -1 : (a1 == b1 ? 0 : 1); +} + +static int +cmp_offset (const void *a, const void *b) +{ + uint64_t off = *((uint64_t *) a); + Dwr_rng_entry *rng = *((Dwr_rng_entry **) b); + return off < rng->offset ? -1 : (off < rng->length ? 0 : 1); +} + +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 *> * DwrCU::get_ranges () { @@ -2211,9 +1999,48 @@ DwrCU::get_ranges () 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); + uint64_t offset = dwrAttr->u.offset; + Dprintf (DUMP_DWARFLIB, "DwrCU::get_ranges: 0x%llx\n", (long long) offset); + if (version < 5) + ranges = dwarf->get_ranges (offset); + else + { + if (rng_list == NULL && !rng_list_inited) + { + rng_list_inited = true; + // Find the corresponding section in .debug_rnglists + Vector <Dwr_rng_entry *> *rng_entrys = dwarf->get_debug_rnglists (); + if (rng_entrys == NULL) + return NULL; + int ind = rng_entrys->bisearch (0, -1, &offset, cmp_offset); + if (ind != -1) + rng_list = rng_entrys->get (ind); + else + { + Dprintf (1, "Cannot find rnglist. DW_AT_ranges=0x%llx\n", + (long long) offset); + return NULL; + } + } + if (rng_list == NULL) + return NULL; + int ind = rng_list->ranges->bisearch (0, -1, &offset, cmp_ExtRange); + if (ind == -1) + { + Dprintf (1, "Cannot find rnglist. DW_AT_ranges=0x%llx\n", + (long long) offset); + return NULL; + } + ranges = new Vector <Range *> (); + for (long i = ind, sz = VecSize (rng_list->ranges); i < sz; i++) + { + ExtRange *r = rng_list->ranges->get (i); + if (r->high == 0) + break; + ranges->append (new Range (r->low + base_address, + r->high + base_address)); + } + } } else { @@ -2227,11 +2054,38 @@ DwrCU::get_ranges () (long long) low_pc); } } - if (ranges && DUMP_DWARFLIB) - ranges->dump (" "); + if (ranges) + { + ranges->sort (rangeCmp); + if (DUMP_DWARFLIB) + ranges->dump ("DwrCU::get_ranges:"); + } return ranges; } +Vector<Symbol *> * +DwrCU::get_symbols (Vector<Symbol *> *syms) +{ + if (syms) + syms->reset (); + Vector <Range *> *ranges = get_ranges (); + if (ranges) + { + syms = Symbol::find_symbols (symbols, ranges, syms); + Destroy (ranges); + } + if (syms) + { + Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name, + get_linkage_name ()); + if (sym) + syms->append (sym); + } + if (syms && DUMP_ELF_SYM) + syms->dump ("DwrCU::get_symbols:"); + return syms; +} + void DwrCU::set_source (Function *func) { @@ -2239,27 +2093,93 @@ DwrCU::set_source (Function *func) func->setLineFirst (lineno); int fileno = (int) Dwarf_data (DW_AT_decl_file); + func->setDefSrc (get_source (fileno)); +} + +SourceFile * +DwrCU::get_source (int fileno) +{ if (fileno > 0 && fileno < VecSize (srcFiles)) - func->setDefSrc (srcFiles->get (fileno)); + return srcFiles->get (fileno); + return NULL; +} + +void +DwrCU::inherit_prop (int64_t offset, source_t *src) +{ + if (src->lineno == 0) + src->lineno = (int) Dwarf_data (DW_AT_decl_line); + if (src->sf == NULL) + src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file)); + + int64_t old_offset = dwrTag.offset; + if (set_die (offset) == DW_DLV_OK) + { + if (src->lineno == 0) + src->lineno = (int) Dwarf_data (DW_AT_decl_line); + if (src->sf == NULL) + src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file)); + + Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_specification); + if (dwrAttr) + inherit_prop (dwrAttr->u.offset, src); + else + { + Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name, + get_linkage_name ()); + if (sym) + update_source (sym, src); + } + } + set_die (old_offset); +} + +void +DwrCU::set_up_funcs (int64_t offset) +{ + // get symbols from DW_AT_ranges, DW_AT_low_pc, DW_AT_linkage_name + Vector<Symbol *> *syms = get_symbols (tmp_syms); + if (VecSize (syms) == 0) + return; + + // Find previous declaration to inherit settings. + source_t src = {.lineno = 0, .sf = NULL}; + inherit_prop (offset, &src); + + for (int i = 0, sz = VecSize (syms); i < sz; i++) + { + Symbol *sym = syms->get (i); + update_source (sym, &src); + if (sym->alias) + update_source (sym->alias, &src); + } +} + +/* Create a function if necessary. + * Update the source information */ +void +DwrCU::update_source (Symbol *sym, source_t *src) +{ + Function *f = sym->createFunction (module); + f->setLineFirst (src->lineno); + f->setDefSrc (src->sf); } Symbol * -DwrCU::find_declaration (int64_t offset) +DwrCU::find_declaration (int64_t offset, source_t *src) { int64_t old_offset = dwrTag.offset; Symbol *sym = NULL; if (set_die (offset) == DW_DLV_OK) { + if (src->lineno == 0) + src->lineno = (int) Dwarf_data (DW_AT_decl_line); + if (src->sf == NULL) + src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file)); + 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)); - } + update_source (sym, src); } set_die (old_offset); return sym; @@ -2344,6 +2264,7 @@ DwrCU::read_data_attr (Dwarf_Half attr, int64_t *retVal) case DW_FORM_data16: case DW_FORM_udata: case DW_FORM_sec_offset: + case DW_FORM_implicit_const: *retVal = dwrAttr->u.val; return DW_DLV_OK; @@ -2577,3 +2498,69 @@ DwrInlinedSubr::dump () (int) level, (long long) abstract_origin, (long long) low_pc, (long long) high_pc, (int) file, (int) line); } + + +////////////////////////////////////////////////////////// +// class Dwr_rng_entry +Dwr_rng_entry::Dwr_rng_entry () +{ + ranges = new Vector <ExtRange *>(); +} + +Dwr_rng_entry::~Dwr_rng_entry () +{ + delete ranges; +} + +void +Dwr_rng_entry::dump () +{ + Dprintf (DUMP_DWARFLIB, "offset=0x%08llx length=0x%08llx fmt=%d version=%d " + "addr_size=%d seg_size=%d offset_entry_count=0x%llx\n", + (long long) offset, (long long) (length - offset), fmt64 ? 64 : 32, + (int) version, (int) address_size, (int) segment_selector_size, + (long long) offset_entry_count); + for (long i = 0, sz = VecSize (ranges); i < sz; i++) + { + ExtRange *p = ranges->get (i); + Dprintf (DUMP_DWARFLIB, " %8ld: 0x%08llx 0x%08llx-0x%08llx [%lld-%lld)\n", + i, (long long) p->offset, (long long) p->low, (long long) p->high, + (long long) p->low, (long long) p->high); + } +} + +char * +Dwr_rng_entry::rng_entry2str (int val) +{ + char *s; + switch (val) + { + CASE_S (DW_RLE_end_of_list); + CASE_S (DW_RLE_base_address); + CASE_S (DW_RLE_start_length); + CASE_S (DW_RLE_offset_pair); + CASE_S (DW_RLE_start_end); + CASE_S (DW_RLE_base_addressx); + CASE_S (DW_RLE_startx_endx); + CASE_S (DW_RLE_startx_length); + default: s = (char *) "???"; + break; + } + return s; +} + +template<> void Vector<Dwr_rng_entry *>::dump (const char *msg) +{ + if (!DUMP_DWARFLIB) + return; + if (msg == NULL) + msg = "#"; + Dprintf (1, NTXT ("\n%s Vector<Dwr_rng_entry *> [%lld]\n"), msg, (long long) size ()); + for (long i = 0, sz = size (); i < sz; i++) + { + Dwr_rng_entry *p = get (i); + Dprintf (1, " %3ld ", i); + p->dump (); + } +} + diff --git a/gprofng/src/DwarfLib.h b/gprofng/src/DwarfLib.h index 230e551..49ecb41 100644 --- a/gprofng/src/DwarfLib.h +++ b/gprofng/src/DwarfLib.h @@ -23,11 +23,11 @@ #include "dwarf2.h" -class ElfReloc; class Dwr_type; class Function; class Range; class SourceFile; +class Symbol; template <class ITEM> class Vector; template <class ITEM> class DbeArray; @@ -75,7 +75,6 @@ public: return (uint32_t) GetULEB128 (); } - ElfReloc *reloc; uint64_t sizeSec; uint64_t size; uint64_t offset; @@ -86,7 +85,6 @@ public: int segment_selector_size; // DWARF 5 private: - bool isCopy; unsigned char *data; bool bounds_violation (uint64_t sz); }; @@ -256,6 +254,45 @@ public: Dwr_type *put_dwr_type (Dwr_Tag *dwrTag); }; +class ExtRange +{ +public: + ExtRange (uint64_t _off, uint64_t _low, uint64_t _high) + { + offset = _off; + low = _low; + high = _high; + }; + + uint64_t offset; + uint64_t low; + uint64_t high; +}; + +class Dwr_rng_entry +{ +public: + Dwr_rng_entry (); + ~Dwr_rng_entry (); + void dump(); + static char *rng_entry2str(int val); + + Dwarf_Half version; + Dwarf_Small address_size; + Dwarf_Small segment_selector_size; + int offset_entry_count; + uint64_t length; + uint64_t offset; + bool fmt64; + Vector <ExtRange *> *ranges; +}; + +typedef struct Source +{ + int lineno; + SourceFile *sf; +} source_t; + class DwrCU { public: @@ -286,7 +323,12 @@ public: private: void build_abbrevTable (DwrSec *debug_abbrevSec, uint64_t stmt_list_offset); Function *append_Function (Symbol *sym, const char *outerName); - Symbol *find_declaration(int64_t offset); + void set_up_funcs (int64_t offset); + void inherit_prop (int64_t offset, source_t *src); + void update_source (Symbol *sym, source_t *prop); + Symbol *find_declaration (int64_t offset, source_t *prop); + SourceFile *get_source (int fileno); + Vector<Symbol *> *get_symbols (Vector<Symbol *> *syms = NULL); Vector <Range *> *get_ranges(); void set_source (Function *func); void parse_inlined_subroutine (Dwarf_cnt *ctx); @@ -317,6 +359,10 @@ private: DwrLineRegs *dwrLineReg; DbeArray<DwrAbbrevTable> *abbrevTable; DbeArray<Dwr_Attr> *abbrevAtForm; + Vector<Symbol*> *tmp_syms; // reused vector for get_symbols() + Dwr_rng_entry *rng_list; // entry in the .debug_rnglists section + bool rng_list_inited; + uint64_t base_address; // low_pc in compile_unit }; #endif /* _DWARFLIB_H_ */ diff --git a/gprofng/src/Elf.cc b/gprofng/src/Elf.cc index f0fd121..e63e3c3 100644 --- a/gprofng/src/Elf.cc +++ b/gprofng/src/Elf.cc @@ -28,6 +28,8 @@ #include "Map.h" #include "StringBuilder.h" #include "DbeFile.h" +#include "DbeSession.h" +#include "Dwarf.h" typedef uint32_t Elf32_Word; typedef uint32_t Elf64_Word; @@ -83,55 +85,30 @@ 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 -// Symbol table -typedef struct -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; /* bind, type: ELF_32_ST_... */ - unsigned char st_other; - Elf32_Half st_shndx; /* SHN_... */ -} Elf32_Sym; - -typedef struct -{ - Elf64_Word st_name; - unsigned char st_info; /* bind, type: ELF_64_ST_... */ - unsigned char st_other; - Elf64_Half st_shndx; /* SHN_... */ - Elf64_Addr st_value; - Elf64_Xword st_size; -} Elf64_Sym; - - -// Relocation -typedef struct -{ - Elf32_Addr r_offset; - Elf32_Word r_info; /* sym, type: ELF32_R_... */ -} Elf32_Rel; - -typedef struct -{ - Elf32_Addr r_offset; - Elf32_Word r_info; /* sym, type: ELF32_R_... */ - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct -{ - Elf64_Addr r_offset; - Elf64_Xword r_info; /* sym, type: ELF64_R_... */ -} Elf64_Rel; +static const char *debug_dirs[] = { + DEBUGDIR, EXTRA_DEBUG_ROOT1, EXTRA_DEBUG_ROOT2, "." +}; -typedef struct +template<> void Vector<asymbol *>::dump (const char *msg) { - Elf64_Addr r_offset; - Elf64_Xword r_info; /* sym, type: ELF64_R_... */ - Elf64_Sxword r_addend; -} Elf64_Rela; + 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; @@ -149,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; @@ -196,23 +175,13 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename) } status = ELF_ERR_NONE; -#if ARCH(SPARC) - need_swap_endian = is_Intel (); -#else - need_swap_endian = !is_Intel (); -#endif - + need_swap_endian = DbeSession::is_bigendian () != bfd_big_endian (abfd); analyzerInfo = 0; - SUNW_ldynsym = 0; - gnuLink = 0; stab = 0; - stabStr = 0; stabIndex = 0; stabIndexStr = 0; stabExcl = 0; stabExclStr = 0; - symtab = 0; - dynsym = 0; info = 0; plt = 0; dwarf = false; @@ -234,20 +203,12 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename) stabExcl = sec; else if (streq (name, NTXT (".stab.exclstr"))) stabExclStr = sec; - else if (streq (name, NTXT (".gnu_debuglink"))) - gnuLink = sec; else if (streq (name, NTXT (".__analyzer_info"))) analyzerInfo = sec; else if (streq (name, NTXT (".info"))) info = true; else if (streq (name, NTXT (".plt"))) plt = sec; - else if (streq (name, NTXT (".SUNW_ldynsym"))) - SUNW_ldynsym = sec; - else if (streq (name, NTXT (".dynsym"))) - dynsym = sec; - else if (streq (name, NTXT (".symtab"))) - symtab = sec; else if (strncmp (name, NTXT (".debug"), 6) == 0) dwarf = true; } @@ -276,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 (); @@ -283,6 +250,7 @@ Elf::~Elf () } delete elfSymbols; delete gnu_debug_file; + delete gnu_debugalt_file; delete dbeFile; delete synthsym; free (bfd_sym); @@ -405,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 *)); @@ -572,50 +567,6 @@ Elf::elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic) return asym; } -Elf_Internal_Rela * -Elf::elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst) -{ - if (dst == NULL || edta == NULL || edta->d_buf == NULL) - return NULL; - if (elf_getclass () == ELFCLASS32) - { - Elf32_Rel *rel = ((Elf32_Rel *) edta->d_buf) + ndx; - dst->r_offset = decode (rel->r_offset); - dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rel->r_info)), - ELF32_R_TYPE (decode (rel->r_info))); - } - else - { - Elf64_Rel *rel = ((Elf64_Rel *) edta->d_buf) + ndx; - dst->r_offset = decode (rel->r_offset); - dst->r_info = decode (rel->r_info); - } - return dst; -} - -Elf_Internal_Rela * -Elf::elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst) -{ - if (dst == NULL || edta == NULL || edta->d_buf == NULL) - return NULL; - if (elf_getclass () == ELFCLASS32) - { - Elf32_Rela *rela = ((Elf32_Rela *) edta->d_buf) + ndx; - dst->r_offset = decode (rela->r_offset); - dst->r_addend = decode (rela->r_addend); - dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rela->r_info)), - ELF32_R_TYPE (decode (rela->r_info))); - } - else - { - Elf64_Rela *rela = ((Elf64_Rela *) edta->d_buf) + ndx; - dst->r_offset = decode (rela->r_offset); - dst->r_addend = decode (rela->r_addend); - dst->r_info = decode (rela->r_info); - } - return dst; -} - Elf64_Ancillary * Elf::elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst) { @@ -676,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); @@ -755,7 +735,6 @@ Elf::find_ancillary_files (char *lo_name) } } } - return NULL; } void @@ -828,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 b324c39..2d227f7 100644 --- a/gprofng/src/Elf.h +++ b/gprofng/src/Elf.h @@ -32,13 +32,12 @@ class Symbol; class DbeFile; +class DwrSec; template <class ITEM> class Vector; template <typename Key_t, typename Value_t> class Map; -#define GELF_R_SYM(info) ((info)>>32) #define GELF_ST_TYPE(info) ((info) & 0xf) #define GELF_ST_BIND(info) ((info) >> 4) -#define GELF_R_TYPE(info) ((((uint64_t)(info))<<56)>>56) #define SHF_SUNW_ABSENT 0x00200000 /* section data not present */ #define SEC_DECOMPRESSED 0x00400000 /* bfd allocated this memory */ @@ -94,10 +93,15 @@ public: char *elf_strptr (unsigned int sec, uint64_t off); long elf_getSymCount (bool is_dynamic); asymbol *elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic); - Elf_Internal_Rela *elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst); - Elf_Internal_Rela *elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst); 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 (); @@ -130,9 +134,10 @@ 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 gnuLink, analyzerInfo, SUNW_ldynsym, stab, stabStr, symtab, dynsym; + unsigned int analyzerInfo, stab, stabStr; unsigned int stabIndex, stabIndexStr, stabExcl, stabExclStr, info, plt; bool dwarf; @@ -143,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; @@ -154,28 +160,4 @@ protected: Vector <asymbol *> *synthsym; }; - -class ElfReloc -{ -public: - struct Sreloc - { - long long offset; - long long value; - int stt_type; - }; - - static ElfReloc *get_elf_reloc (Elf *elf, char *sec_name, ElfReloc *rlc); - ElfReloc (Elf *_elf); - ~ElfReloc (); - long long get_reloc_addr (long long offset); - void dump (); - void dump_rela_debug_sec (int sec); - -private: - Elf *elf; - Vector<Sreloc *> *reloc; - int cur_reloc_ind; -}; - #endif diff --git a/gprofng/src/Experiment.cc b/gprofng/src/Experiment.cc index 45550e8..2768927 100644 --- a/gprofng/src/Experiment.cc +++ b/gprofng/src/Experiment.cc @@ -541,10 +541,14 @@ Experiment::ExperimentHandler::startElement (char*, char*, char *qName, Attribut exp->platform = RISCV; else exp->platform = Sparc; - exp->need_swap_endian = (DbeSession::platform == Sparc) ? - (exp->platform != Sparc) : (exp->platform == Sparc); exp->architecture = xstrdup (str); } + str = attrs->getValue (NTXT ("bigendian")); + if (str != NULL) + { + exp->bigendian = *str == '1'; + exp->need_swap_endian = DbeSession::is_bigendian () != exp->bigendian; + } str = attrs->getValue (NTXT ("pagesz")); if (str != NULL) exp->page_size = atoi (str); @@ -1314,6 +1318,7 @@ Experiment::Experiment () exp_maj_version = 0; exp_min_version = 0; platform = Unknown; + bigendian = DbeSession::is_bigendian(); // can be changed in log.xml reading wsize = Wnone; page_size = 4096; npages = 0; @@ -6806,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 2047a15..9a3d226 100644 --- a/gprofng/src/Experiment.h +++ b/gprofng/src/Experiment.h @@ -135,6 +135,7 @@ public: // for current experiment, i.e. 8 for 32bit addresses int broken; // If SP_JCMD_RUN line not seen int obsolete; // If pointer file experiment detected + bool bigendian; // the experiment was created on a big_endian machine bool hwc_default; // True if HW counters were enabled by default int hwc_bogus; // Count of bogus HWC packets int hwc_lost_int; // Count of packets reflecting lost interrupt @@ -266,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 be7ad3a..7b4bef2 100644 --- a/gprofng/src/LoadObject.cc +++ b/gprofng/src/LoadObject.cc @@ -87,7 +87,6 @@ LoadObject::LoadObject (const char *loname) size = 0; type = SEG_UNKNOWN; isReadStabs = false; - need_swap_endian = false; instHTable = new DbeInstr*[LO_InstHTableSize]; for (int i = 0; i < LO_InstHTableSize; i++) instHTable[i] = NULL; @@ -103,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; @@ -136,7 +134,6 @@ LoadObject::~LoadObject () delete modules; delete elf_lo; free (pathname); - free (arch_name); free (runTimePath); delete objStabs; delete warnq; @@ -168,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; } @@ -299,7 +317,7 @@ LoadObject::dump_functions (FILE *out) if (fitem->alias && fitem->alias != fitem) fprintf (out, "id %6llu, @0x%llx - %s == alias of '%s'\n", (ull_t) fitem->id, (ull_t) fitem->img_offset, - fitem->get_name (), fitem->alias->get_name ()); + fitem->get_mangled_name (), fitem->alias->get_mangled_name ()); else { mname = fitem->module ? fitem->module->file_name : noname->file_name; @@ -561,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"); @@ -727,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 14dfe26..c93594b 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 (); @@ -167,7 +160,6 @@ public: unsigned int flags; // SEG_FLAG_* bool isReadStabs; - bool need_swap_endian; int seg_idx; // for compatibility (ADDRESS) seg_type type; int64_t size; // size of loadobject in bytes @@ -193,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 a62d3e8..55091ad 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 ff83949..116316e 100644 --- a/gprofng/src/Stabs.cc +++ b/gprofng/src/Stabs.cc @@ -163,21 +163,11 @@ Stabs::removeDupSyms () SymLst->truncate (last); } -Stabs * -Stabs::NewStabs (char *_path, char *lo_name) +Stabs::Stabs (Elf *elf, char *_lo_name) { - Stabs *stabs = new Stabs (_path, lo_name); - if (stabs->status != Stabs::DBGD_ERR_NONE) - { - delete stabs; - return NULL; - } - return stabs; -} - -Stabs::Stabs (char *_path, 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; @@ -187,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: @@ -206,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++) { @@ -228,7 +239,6 @@ Stabs::~Stabs () delete SymLstByName; Destroy (SymLst); Destroy (LocalFile); - delete elfDis; delete dwarf; delete LocalLst; delete LocalFileIdx; @@ -238,90 +248,11 @@ Stabs::~Stabs () } 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 @@ -1554,7 +1485,8 @@ Stabs::fixSymtabAlias () for (; i < k; i++) { sym = SymLst->fetch (i); - sym->alias = bestAlias; + if (sym != bestAlias) + sym->alias = bestAlias; sym->size = maxSize; } i--; @@ -2130,57 +2062,6 @@ Stabs::append_Function (Module *module, char *fname) return func; } -Function * -Stabs::append_Function (Module *module, char *linkerName, uint64_t pc) -{ - Dprintf (DEBUG_STABS, NTXT ("Stabs::append_Function: module=%s linkerName=%s pc=0x%llx\n"), - STR (module->get_name ()), STR (linkerName), (unsigned long long) pc); - long i; - Symbol *sitem = NULL, *sp; - Function *func; - sp = new Symbol; - if (pc) - { - sp->value = pc; - i = SymLst->bisearch (0, -1, &sp, SymFindCmp); - if (i != -1) - sitem = SymLst->fetch (i); - } - - if (!sitem && linkerName) - { - if (SymLstByName == NULL) - { - SymLstByName = SymLst->copy (); - SymLstByName->sort (SymNameCmp); - } - sp->name = linkerName; - i = SymLstByName->bisearch (0, -1, &sp, SymNameCmp); - sp->name = NULL; - if (i != -1) - sitem = SymLstByName->fetch (i); - } - delete sp; - - if (!sitem) - return NULL; - if (sitem->alias) - sitem = sitem->alias; - if (sitem->func) - return sitem->func; - - sitem->func = func = dbeSession->createFunction (); - func->img_fname = path; - func->img_offset = sitem->img_offset; - func->save_addr = sitem->save; - func->size = sitem->size; - func->module = module; - func->set_name (sitem->name); //XXXX ?? Now call it to set obj->name - module->functions->append (func); - module->loadobject->functions->append (func); - return func; -}// Stabs::append_Function - Dwarf * Stabs::openDwarf () { diff --git a/gprofng/src/Stabs.h b/gprofng/src/Stabs.h index c8da278..cd10c25 100644 --- a/gprofng/src/Stabs.h +++ b/gprofng/src/Stabs.h @@ -76,8 +76,7 @@ class Stabs { DBGD_ERR_CHK_SUM }; - static Stabs *NewStabs(char *_path, char *lo_name); - Stabs(char *_path, char *_lo_name); + Stabs(Elf *elf, char *_lo_name); ~Stabs(); bool is_relocatable(){ return isRelocatable; } @@ -100,7 +99,6 @@ class Stabs { static Function *find_func(char *fname, Vector<Function*> *functions, bool fortran, bool inner_names=false); Module *append_Module(LoadObject *lo, char *name, int lastMod = 0); Function *append_Function(Module *module, char *fname); - Function *append_Function(Module *module, char *linkerName, uint64_t pc); Function *map_PC_to_func(uint64_t pc, uint64_t &low_pc, Vector<Function*> *functions); char *path; // path to the object file char *lo_name; // User name of load object @@ -138,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/Symbol.cc b/gprofng/src/Symbol.cc index 82fe788..8cc578f 100644 --- a/gprofng/src/Symbol.cc +++ b/gprofng/src/Symbol.cc @@ -135,13 +135,13 @@ Symbol::sort_by_name (Vector<Symbol *> *syms) } Vector<Symbol *> * -Symbol::find_symbols (Vector<Symbol*> *syms, Vector<Range *> *ranges) +Symbol::find_symbols (Vector<Symbol*> *syms, Vector<Range *> *ranges, + Vector<Symbol *> *symbols) { // '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; @@ -182,15 +182,7 @@ Symbol::find_symbols (Vector<Symbol*> *syms, Vector<Range *> *ranges) 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; + return symbols; } /* Create and append a new function to the 'module'. diff --git a/gprofng/src/Symbol.h b/gprofng/src/Symbol.h index 25cceca..e9e0060 100644 --- a/gprofng/src/Symbol.h +++ b/gprofng/src/Symbol.h @@ -18,6 +18,9 @@ Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifndef _Symbol_h_ +#define _Symbol_h_ + class Function; class Module; @@ -54,7 +57,7 @@ public: // Find symbols in 'syms' matched by 'ranges'. static Vector<Symbol *> *find_symbols (Vector<Symbol *> *syms, - Vector<Range *> *ranges); + Vector<Range *> *ranges, Vector<Symbol *> *symbols = NULL); static Vector<Symbol *> *sort_by_name (Vector<Symbol *> *syms); // Find symbol in CU corresponding to pc or linker_name. @@ -62,7 +65,7 @@ public: 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, + // Copy attributes (size, name, etc) from Symbol, Function *createFunction(Module *module); void dump (const char *msg = NULL); @@ -77,4 +80,5 @@ public: int local_ind; int flags; bool defined; -};
\ No newline at end of file +}; +#endif diff --git a/gprofng/src/gp-archive.cc b/gprofng/src/gp-archive.cc index ee9f917..2c15da8 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; @@ -490,6 +524,15 @@ er_archive::start (int argc, char *argv[]) } 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[]) { int opt; diff --git a/gprofng/src/gp-archive.h b/gprofng/src/gp-archive.h index 41fb4b2..3b9d0ee 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 (); |