When highpc is in constant form it is relative to lowpc. In that case also show as address.
Suggested-by: Jan Kratochvil jan.kratochvil@redhat.com Signed-off-by: Mark Wielaard mjw@redhat.com --- src/ChangeLog | 7 +++++++ src/readelf.c | 16 +++++++++++++++- tests/ChangeLog | 4 ++++ tests/run-readelf-dwz-multi.sh | 12 ++++++------ 4 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog index a641d33..24bc6bf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2013-03-25 Mark Wielaard mjw@redhat.com + + * readelf.c (attrcb_args): Add Dwarf_Die. + (attr_callback): When highpc is in constant form also print as + address. + (print_debug_units): Set args.die. + 2013-03-19 Mark Wielaard mjw@redhat.com
* readelf.c (print_gdb_index_section): Free format_dwarf_addr results. diff --git a/src/readelf.c b/src/readelf.c index 1412bed..d70916a 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -5242,6 +5242,7 @@ struct attrcb_args { Dwfl_Module *dwflmod; Dwarf *dbg; + Dwarf_Die *die; int level; bool silent; unsigned int version; @@ -5437,7 +5438,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (cbargs->silent) break;
- if (valuestr == NULL) + /* When highpc is in constant form it is relative to lowpc. + In that case also show the address. */ + Dwarf_Addr highpc; + if (attr == DW_AT_high_pc && (dwarf_highpc (cbargs->die, &highpc) == 0)) + { + char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, + highpc - 1, highpc); + printf (" %*s%-20s (%s) %" PRIuMAX " (%s)\n", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num, a); + free (a); + } + else if (valuestr == NULL) printf (" %*s%-20s (%s) %" PRIuMAX "\n", (int) (level * 2), "", dwarf_attr_name (attr), dwarf_form_name (form), (uintmax_t) num); @@ -5659,6 +5672,7 @@ print_debug_units (Dwfl_Module *dwflmod,
/* Print the attribute values. */ args.level = level; + args.die = &dies[level]; (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
/* Make room for the next level's DIE. */ diff --git a/tests/ChangeLog b/tests/ChangeLog index 62b589d..3465777 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2013-03-25 Mark Wielaard mjw@redhat.com + + * run-readelf-dwz-multi.sh: Expect high_pc also as address. + 2013-03-20 Jan Kratochvil jan.kratochvil@redhat.com
* Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align. diff --git a/tests/run-readelf-dwz-multi.sh b/tests/run-readelf-dwz-multi.sh index 20c00c5..95bef55 100755 --- a/tests/run-readelf-dwz-multi.sh +++ b/tests/run-readelf-dwz-multi.sh @@ -90,7 +90,7 @@ DWARF section [28] '.debug_info' at offset 0x1078: name (strp) "main.c" comp_dir (GNU_strp_alt) "/home/mark/src/tests/dwz" low_pc (addr) 0x00000000004006ac <main> - high_pc (udata) 44 + high_pc (udata) 44 (0x00000000004006d7 <main+0x2b>) stmt_list (sec_offset) 0 [ 26] imported_unit import (GNU_ref_alt) [ b] @@ -105,7 +105,7 @@ DWARF section [28] '.debug_info' at offset 0x1078: prototyped (flag_present) type (GNU_ref_alt) [ 3e] low_pc (addr) 0x00000000004006ac <main> - high_pc (udata) 44 + high_pc (udata) 44 (0x00000000004006d7 <main+0x2b>) frame_base (exprloc) [ 0] call_frame_cfa GNU_all_tail_call_sites (flag_present) @@ -148,7 +148,7 @@ DWARF section [25] '.debug_info' at offset 0x106c: name (strp) "shared.c" comp_dir (GNU_strp_alt) "/home/mark/src/tests/dwz" low_pc (addr) +0x0000000000000670 <call_foo> - high_pc (udata) 23 + high_pc (udata) 23 (+0x0000000000000686 <call_foo+0x16>) stmt_list (sec_offset) 0 [ 26] imported_unit import (GNU_ref_alt) [ b] @@ -160,7 +160,7 @@ DWARF section [25] '.debug_info' at offset 0x106c: prototyped (flag_present) type (GNU_ref_alt) [ 3e] low_pc (addr) +0x0000000000000670 <call_foo> - high_pc (udata) 23 + high_pc (udata) 23 (+0x0000000000000686 <call_foo+0x16>) frame_base (exprloc) [ 0] call_frame_cfa GNU_all_call_sites (flag_present) @@ -185,7 +185,7 @@ DWARF section [28] '.debug_info' at offset 0x1088: name (GNU_strp_alt) "main.c" comp_dir (GNU_strp_alt) "/home/mark/src/tests" low_pc (addr) 0x00000000004004ec <main> - high_pc (udata) 18 + high_pc (udata) 18 (0x00000000004004fd <main+0x11>) stmt_list (sec_offset) 0 [ 26] imported_unit import (GNU_ref_alt) [ b] @@ -197,7 +197,7 @@ DWARF section [28] '.debug_info' at offset 0x1088: prototyped (flag_present) type (GNU_ref_alt) [ 30] low_pc (addr) 0x00000000004004ec <main> - high_pc (udata) 18 + high_pc (udata) 18 (0x00000000004004fd <main+0x11>) frame_base (exprloc) [ 0] call_frame_cfa GNU_all_call_sites (flag_present)
On Mon, 25 Mar 2013 21:23:26 +0100, Mark Wielaard wrote:
@@ -5437,7 +5438,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (cbargs->silent) break;
if (valuestr == NULL)
/* When highpc is in constant form it is relative to lowpc.
In that case also show the address. */
Dwarf_Addr highpc;
if (attr == DW_AT_high_pc && (dwarf_highpc (cbargs->die, &highpc) == 0))
- {
char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
highpc - 1, highpc);
That "- 1" is a bug:
DWARF-4.0: If the value of the DW_AT_high_pc is of class address, it is the relocated address of the first location past the last instruction associated with the entity; if it is of class constant, the value is an unsigned integer offset which when added to the low PC gives the address of the first location past the last instruction associated with the entity.
gcc/dwarf2out.c: case dw_val_class_high_pc: dw2_asm_output_delta (DWARF2_ADDR_SIZE, AT_lbl (a), get_AT_low_pc (die), "DW_AT_high_pc");
gdb/dwarf2read.c: if (attr_high->form == DW_FORM_addr || attr_high->form == DW_FORM_GNU_addr_index) high = DW_ADDR (attr_high); else high = low + DW_UNSND (attr_high);
I see no + 1 or -1 there.
low_pc (addr) 0x0000000000400530 <main> high_pc (data8) 32 (0x000000000040054f <main+0x1f>)
0000000000400530 <main>: main(): 400530: 55 push %rbp [...] 40054e: c9 leaveq 40054f: c3 retq 0000000000400550 <__libc_csu_init>:
vs. when build with FSF GCC 4.7:
low_pc (addr) 0x000000000040051c <main> high_pc (addr) 0x000000000040053c
000000000040051c <main>: 40051c: 55 push %rbp [...] 40053a: c9 leaveq 40053b: c3 retq 40053c: 0f 1f 40 00 nopl 0x0(%rax)
Thanks, Jan
On Tue, 2013-03-26 at 07:58 +0100, Jan Kratochvil wrote:
On Mon, 25 Mar 2013 21:23:26 +0100, Mark Wielaard wrote:
@@ -5437,7 +5438,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (cbargs->silent) break;
if (valuestr == NULL)
/* When highpc is in constant form it is relative to lowpc.
In that case also show the address. */
Dwarf_Addr highpc;
if (attr == DW_AT_high_pc && (dwarf_highpc (cbargs->die, &highpc) == 0))
- {
char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
highpc - 1, highpc);
That "- 1" is a bug:
DWARF-4.0: If the value of the DW_AT_high_pc is of class address, it is the relocated address of the first location past the last instruction associated with the entity; if it is of class constant, the value is an unsigned integer offset which when added to the low PC gives the address of the first location past the last instruction associated with the entity.
Right, so it isn't a bug, but was a deliberately choice because high_pc is "one to high". Normally when readelf displays ranges it displays them "inclusive". That way you get the proper symbols/offsets associated with the last byte of a code range. Otherwise readelf has to display a symbol associated with the "next" symbol, if any. If you want "uninterpreted" values you can always use -N or -U.
But it is inconsistent with how we display high_pc if it is a DW_FORM_addr, or when it is displayed on its own, not as a low_pc..high_pc range. So lets go for consistent and always display it as a "raw" single address instead of a range.
I also fixed the parens issue Roland noticed before pushing the attached.
Cheers,
Mark
On Tue, 26 Mar 2013 09:30:03 +0100, Mark Wielaard wrote:
Otherwise readelf has to display a symbol associated with the "next" symbol, if any.
Displaying such symbol is correct, it corresponds to the address being displayed.
But it is inconsistent with how we display high_pc if it is a DW_FORM_addr, or when it is displayed on its own, not as a low_pc..high_pc range. So lets go for consistent and always display it as a "raw" single address instead of a range.
It looks correct to me now: low_pc (addr) 0x00000000004005e0 <main> high_pc (data8) 32 (0x0000000000400600 <__libc_csu_init>)
I would prefer to align the addresses underneath but that is already not possible due to "(addr)" vs. "(data8)"; I am used more to binutils readelf.
Thanks, Jan
elfutils-devel@lists.fedorahosted.org