diff options
Diffstat (limited to 'gprofng/src/DwarfLib.cc')
-rw-r--r-- | gprofng/src/DwarfLib.cc | 285 |
1 files changed, 19 insertions, 266 deletions
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc index 79be8cf..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,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: @@ -1033,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: @@ -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 @@ -1213,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 @@ -1283,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 (); @@ -1546,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: @@ -1843,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" @@ -1851,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, @@ -2050,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; @@ -2073,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); |