Hi hackers, On Sat, 2016-01-23 at 21:39 +0100, Mark Wielaard wrote: > On Wed, Jan 20, 2016 at 03:14:16PM -0800, Roland McGrath wrote: > > > Other addresses in this code are printed with ("%#" PRIx64). > > > (AFAIK '#' here will always give "0x", but lets keep it consistent). > > > > %#x prints "0" for zero (not "0x0"). Indeed it is the right thing to use > > here. > > > > > It's also curious that nothing is done with op1 after printing it. > > > Shouldn't this set pc, at least? > > > > I think it should, but that is unrelated to this change. > > Arguably, it should be: > > > > get_uleb128 (op1, readp, endp); > > op1 *= code_align; > > printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n", > > op1, pc = vma_base + op1); > > > > so that it displays the literal value (like the other cases do) as well as > > the final value (which in this case is just with VMA_BASE added in). > > I agree with using %# for printing the address and setting the pc using > vma_base and op1. But the argument of a DW_CFA_set_loc is an address, not > a uleb128 and it should not be adjusted by code_align, which is only used > for CFA_advance operations as far as I understand it. To read an address > we need to know the FDE address encoding and use read_encoded (which > isn't defined till a bit later, so we need to move it up).
So, no comments about this at all? Sounds sane, sounds insane? What if I attach a full patch and threaten to commit it? See attached. Cheers, Mark
From 76a2452866bdc93a8891018ec3281b7e1c56e367 Mon Sep 17 00:00:00 2001 From: Mark Wielaard <m...@redhat.com> Date: Tue, 9 Feb 2016 23:25:54 +0100 Subject: [PATCH] readelf: Read and print (encoded) DW_CFA_set_loc op and update pc. DW_CFA_set_loc takes an address as op, not an uleb128. Read and decode it. Print the actual address and (updated) pc (address plus vma_base). Signed-off-by: Mark Wielaard <m...@redhat.com> --- src/ChangeLog | 7 ++++ src/readelf.c | 121 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 707c271..71709e4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2016-02-09 Mark Wielaard <m...@redhat.com> + + * readelf.c (read_encoded): Move up. + (print_cfa_program): Add encoding argument. Use it for read_encoded + when reading DW_CFA_set_loc op. + (print_debug_frame_section): Pass fde_encoding to print_cfa_program. + 2016-01-13 Mark Wielaard <m...@redhat.com> * elflint.c (check_elf_header): Recognize ELFOSABI_FREEBSD. diff --git a/src/readelf.c b/src/readelf.c index 0db192e..a25e4ac 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -5044,11 +5044,68 @@ register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc, return set; } +static const unsigned char * +read_encoded (unsigned int encoding, const unsigned char *readp, + const unsigned char *const endp, uint64_t *res, Dwarf *dbg) +{ + if ((encoding & 0xf) == DW_EH_PE_absptr) + encoding = gelf_getclass (dbg->elf) == ELFCLASS32 + ? DW_EH_PE_udata4 : DW_EH_PE_udata8; + + switch (encoding & 0xf) + { + case DW_EH_PE_uleb128: + get_uleb128 (*res, readp, endp); + break; + case DW_EH_PE_sleb128: + get_sleb128 (*res, readp, endp); + 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_cfa_program (const unsigned char *readp, const unsigned char *const endp, Dwarf_Word vma_base, unsigned int code_align, int data_align, unsigned int version, unsigned int ptr_size, + unsigned int encoding, Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg) { char regnamebuf[REGNAMESZ]; @@ -5079,9 +5136,9 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, case DW_CFA_set_loc: if ((uint64_t) (endp - readp) < 1) goto invalid; - get_uleb128 (op1, readp, endp); - op1 += vma_base; - printf (" set_loc %" PRIu64 "\n", op1 * code_align); + readp = read_encoded (encoding, readp, endp, &op1, dbg); + printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n", + op1, pc = vma_base + op1); break; case DW_CFA_advance_loc1: if ((uint64_t) (endp - readp) < 1) @@ -5421,62 +5478,6 @@ print_encoding_base (const char *pfx, 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) -{ - if ((encoding & 0xf) == DW_EH_PE_absptr) - encoding = gelf_getclass (dbg->elf) == ELFCLASS32 - ? DW_EH_PE_udata4 : DW_EH_PE_udata8; - - switch (encoding & 0xf) - { - case DW_EH_PE_uleb128: - get_uleb128 (*res, readp, endp); - break; - case DW_EH_PE_sleb128: - get_sleb128 (*res, readp, endp); - 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) @@ -5851,7 +5852,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, else print_cfa_program (readp, cieend, vma_base, code_alignment_factor, data_alignment_factor, version, ptr_size, - dwflmod, ebl, dbg); + fde_encoding, dwflmod, ebl, dbg); readp = cieend; } } -- 2.5.0