diff options
Diffstat (limited to 'src/readelf.c')
-rw-r--r-- | src/readelf.c | 159 |
1 files changed, 95 insertions, 64 deletions
diff --git a/src/readelf.c b/src/readelf.c index d170fe0a..df565993 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4459,9 +4459,9 @@ print_relinfo (unsigned int val) static void -print_encoding_base (unsigned int fde_encoding) +print_encoding_base (const char *pfx, unsigned int fde_encoding) { - putchar_unlocked ('('); + printf ("(%s", pfx); unsigned int w = fde_encoding; @@ -4483,6 +4483,60 @@ print_encoding_base (unsigned int fde_encoding) } +static const unsigned char * +read_encoded (unsigned int encoding, const unsigned char *readp, + const unsigned char *const endp, uint64_t *res, Dwarf *dbg) +{ + switch (encoding & 0xf) + { + case DW_EH_PE_uleb128: + // XXX buffer overrun check + get_uleb128 (*res, readp); + break; + case DW_EH_PE_sleb128: + // XXX buffer overrun check + get_sleb128 (*res, readp); + break; + case DW_EH_PE_udata2: + if (readp + 2 > endp) + goto invalid; + *res = read_2ubyte_unaligned_inc (dbg, readp); + break; + case DW_EH_PE_udata4: + if (readp + 4 > endp) + goto invalid; + *res = read_4ubyte_unaligned_inc (dbg, readp); + break; + case DW_EH_PE_udata8: + if (readp + 8 > endp) + goto invalid; + *res = read_8ubyte_unaligned_inc (dbg, readp); + break; + case DW_EH_PE_sdata2: + if (readp + 2 > endp) + goto invalid; + *res = read_2sbyte_unaligned_inc (dbg, readp); + break; + case DW_EH_PE_sdata4: + if (readp + 4 > endp) + goto invalid; + *res = read_4sbyte_unaligned_inc (dbg, readp); + break; + case DW_EH_PE_sdata8: + if (readp + 8 > endp) + goto invalid; + *res = read_8sbyte_unaligned_inc (dbg, readp); + break; + default: + invalid: + error (1, 0, + gettext ("invalid encoding")); + } + + return readp; +} + + static void print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) @@ -4518,6 +4572,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, unsigned int code_alignment_factor; unsigned int data_alignment_factor; unsigned int fde_encoding; + unsigned int lsda_encoding; struct cieinfo *next; } *cies = NULL; @@ -4571,6 +4626,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, unsigned int code_alignment_factor; int data_alignment_factor; unsigned int fde_encoding = 0; + unsigned int lsda_encoding = 0; Dwarf_Word initial_location = 0; if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID)) @@ -4622,8 +4678,15 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (*cp == 'R') { - fde_encoding = *readp; - print_encoding_base (fde_encoding); + fde_encoding = *readp++; + print_encoding_base (gettext ("FDE address encoding: "), + fde_encoding); + } + else if (*cp == 'L') + { + lsda_encoding = *readp++; + print_encoding_base (gettext ("LSDA pointer encoding: "), + lsda_encoding); } else if (*cp == 'P') { @@ -4687,13 +4750,13 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, ++cp; } - readp += augmentationlen; } struct cieinfo *newp = alloca (sizeof (*newp)); newp->cie_offset = offset; newp->augmentation = augmentation; newp->fde_encoding = fde_encoding; + newp->lsda_encoding = lsda_encoding; newp->code_alignment_factor = code_alignment_factor; newp->data_alignment_factor = data_alignment_factor; newp->next = cies; @@ -4717,6 +4780,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, /* Initialize from CIE data. */ fde_encoding = cie->fde_encoding; + lsda_encoding = cie->lsda_encoding; ptr_size = encoded_ptr_size (fde_encoding, ptr_size); code_alignment_factor = cie->code_alignment_factor; data_alignment_factor = cie->data_alignment_factor; @@ -4754,12 +4818,33 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, { const char *hdr = "Augmentation data:"; const char *cp = cie->augmentation + 1; - for (unsigned int u = 0; u < augmentationlen; ++cp, ++u) + unsigned int u = 0; + while (*cp != '\0') + { + if (*cp == 'L') + { + uint64_t lsda_pointer; + const unsigned char *p + = read_encoded (lsda_encoding, &readp[u], + &readp[augmentationlen], + &lsda_pointer, dbg); + u = p - readp; + printf (gettext ("\ + %-26sLSDA pointer: %#" PRIx64 "\n"), + hdr, lsda_pointer); + hdr = ""; + } + ++cp; + } + + while (u < augmentationlen) { - printf (" %-26s%#x (", hdr, readp[u]); + printf (" %-26s%#x\n", hdr, readp[u++]); hdr = ""; } } + + readp += augmentationlen; } } @@ -5883,60 +5968,6 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } -static const unsigned char * -read_encoded (unsigned int encoding, const unsigned char *readp, - const unsigned char *const endp, uint64_t *res, Dwarf *dbg) -{ - switch (encoding & 0xf) - { - case DW_EH_PE_uleb128: - // XXX buffer overrun check - get_uleb128 (*res, readp); - break; - case DW_EH_PE_sleb128: - // XXX buffer overrun check - get_sleb128 (*res, readp); - break; - case DW_EH_PE_udata2: - if (readp + 2 > endp) - goto invalid; - *res = read_2ubyte_unaligned_inc (dbg, readp); - break; - case DW_EH_PE_udata4: - if (readp + 4 > endp) - goto invalid; - *res = read_4ubyte_unaligned_inc (dbg, readp); - break; - case DW_EH_PE_udata8: - if (readp + 8 > endp) - goto invalid; - *res = read_8ubyte_unaligned_inc (dbg, readp); - break; - case DW_EH_PE_sdata2: - if (readp + 2 > endp) - goto invalid; - *res = read_2sbyte_unaligned_inc (dbg, readp); - break; - case DW_EH_PE_sdata4: - if (readp + 4 > endp) - goto invalid; - *res = read_4sbyte_unaligned_inc (dbg, readp); - break; - case DW_EH_PE_sdata8: - if (readp + 8 > endp) - goto invalid; - *res = read_8sbyte_unaligned_inc (dbg, readp); - break; - default: - invalid: - error (1, 0, - gettext ("invalid encoding")); - } - - return readp; -} - - /* Print the content of the call frame search table section '.eh_frame_hdr'. */ static void @@ -5977,11 +6008,11 @@ print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)), printf (" version: %u\n" " eh_frame_ptr_enc: %#x ", version, eh_frame_ptr_enc); - print_encoding_base (eh_frame_ptr_enc); + print_encoding_base ("", eh_frame_ptr_enc); printf (" fde_count_enc: %#x ", fde_count_enc); - print_encoding_base (fde_count_enc); + print_encoding_base ("", fde_count_enc); printf (" table_enc: %#x ", table_enc); - print_encoding_base (table_enc); + print_encoding_base ("", table_enc); uint64_t eh_frame_ptr = 0; if (eh_frame_ptr_enc != DW_EH_PE_omit) |