This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
Re: [PATCH] readelf: Show set_loc argument as hexadecimal
- From: Mark Wielaard <mjw at redhat dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Tue, 09 Feb 2016 23:35:25 +0100
- Subject: Re: [PATCH] readelf: Show set_loc argument as hexadecimal
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 <mjw@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 <mjw@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 <mjw@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 <mjw@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