Bug 13421 - readelf -u generates output for relocatable ARM objects
Summary: readelf -u generates output for relocatable ARM objects
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-21 15:29 UTC by Dave Martin
Modified: 2011-11-28 16:53 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Proposed fix (2.63 KB, patch)
2011-11-25 14:12 UTC, Nick Clifton
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Martin 2011-11-21 15:29:37 UTC
Observed in binutils CVS 20111121
Host: x86_64-linux-gnu
Target: arm-elf-eabi

(the host should not really matter, and any ARM target should show the same behaviour)

Readelf's unwind table dumping implementation for ARM appears to make incorrect assumptions which mean that readelf -u only generates valid output for fully linked objects (ET_EXEC/ET_DYN).

The reason seems to be that the implementation attempts to convert relocated unwind table information to absolute address offsets prematutely: this works when all loadable sections share a common addressing origin (as for fully linked objects) but not when each section has an independent origin (as for ET_REL).

This appears to cause the location of both the function body and the unwind opcodes to be miscalculated.

The erroneous code is in the following functions in binutils/readelf.c:
dump_arm_unwind ()
arm_section_get_word ()
arm_print_vma_and_name ()

To fix this, the code should not be fully applying the R_ARM_PREL31 relocations at all, since cross-section relocations cannot be applied without a common addressing origin.  Instead, a {section,address} pair should be generated by applying the relocation addend to the target symbol's {section,address} pair, with the resultant pair used for locating the unwind opcodes and function symbol.

Consider refactoring the code when resolving this: the resulting code should hopefully be simpler than the current code, since it would need to do less relocation processing.


Testcase:

$ cat <<EOF >unwind.txt
.type f1,%function
f1:
	.fnstart
	stmfd	sp!, {r0-r12,lr}
	.save	{r0-r12,lr}
	bl	foo
	ldmfd	sp!, {r0-r12,pc}
	.fnend
	.size f1,.-f1

.type f2,%function
f2:
	.fnstart
	stmfd	sp!, {r12,lr}
	.save	{r12,lr}
	stmfd	sp!, {r0-r3}
	.save	{r0-r3}
	bl	foo
	ldmfd	sp!, {r0-r3,r12,pc}
	.fnend
	.size f2,.-f2

.type f3,%function
f3:
	.fnstart
	stmfd	sp!,{r0,lr}
	.save	{r0,lr}
	bl	foo
	ldmfd	sp!,{r0,pc}
	.fnend
	.size f3,.-f3

.type f4,%function
f4:
	.fnstart
	stmfd	sp!,{r1,lr}
	.save	{r1,lr}
	bl	foo
	ldmfd	sp!,{r1,pc}
	.fnend
	.size f4,.-f4

.type f5,%function
f5:
	.fnstart
	stmfd	sp!,{r2,lr}
	.save	{r2,lr}
	bl	foo
	ldmfd	sp!,{r2,pc}
	.fnend
	.size f5,.-f5

.type f6,%function
f6:
	.fnstart
	stmfd	sp!,{r3,lr}
	.save	{r3,lr}
	bl	foo
	ldmfd	sp!,{r3,pc}
	.fnend
	.size f6,.-f6
EOF

$ as -o unwind.o unwind.s
$ readelf -u unwind.o

Unwind table index '.ARM.exidx' at offset 0xc8 contains 6 entries:

0x0: @0x0
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

0x0: @0x0
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

0x0: @0x0
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

0x0: @0x0
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

0x0: @0x0
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

0x0: @0x0
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

# Linking the .o file allows us to get valid output:
$ ld -shared -o unwind unwind.o
$ readelf -u unwind

Unwind table index '.ARM.exidx' at offset 0x2b8 contains 7 entries:

0x224 <f1>: @0x270
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0xff pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
  0xb0      finish
  0xb0      finish

0x230 <f2>: @0x27c
  Compact model 1
  0xb1 0x0f pop {r0, r1, r2, r3}
  0x85 0x00 pop {r12, r14}
  0xb0      finish
  0xb0      finish

0x240 <f3>: @0x288
  Compact model 1
  0xb1 0x01 pop {r0}
  0x84 0x00 pop {r14}
  0xb0      finish
  0xb0      finish

0x24c <f4>: @0x294
  Compact model 1
  0xb1 0x02 pop {r1}
  0x84 0x00 pop {r14}
  0xb0      finish
  0xb0      finish

0x258 <f5>: @0x2a0
  Compact model 1
  0xb1 0x04 pop {r2}
  0x84 0x00 pop {r14}
  0xb0      finish
  0xb0      finish

0x264 <f6>: @0x2ac
  Compact model 1
  0xb1 0x08 pop {r3}
  0x84 0x00 pop {r14}
  0xb0      finish
  0xb0      finish

0x270 <f6+0xc>: 0x1 [cantunwind]
Comment 1 Nick Clifton 2011-11-25 14:12:02 UTC
Created attachment 6075 [details]
Proposed fix
Comment 2 Nick Clifton 2011-11-25 14:16:56 UTC
Hi Dave,

> Instead, a {section,address} pair should be generated by
> applying the relocation addend to the target symbol's 
> {section,address} pair, with the resultant pair used 
> for locating the unwind opcodes and function symbol.

Actually this is being done already - it is just that the code that did this was broken...

Please try out the uploaded patch and let me know what you think.

The patch includes a lot of formatting and coding tidy-ups, (although not the full code refactoring that you suggested), so it may be hard to find the real changes.  The fixes are as follows:

  1. Correctly initialize the rel_type field in the arm_section structure.

  2. When displaying the function name, use the computed function section/offset abdaddr structure, not the entry absaddr structure.

Cheers
  Nick
Comment 3 Dave Martin 2011-11-25 18:32:39 UTC
On Fri, Nov 25, 2011 at 02:16:56PM +0000, nickc at redhat dot com wrote:
> http://sourceware.org/bugzilla/show_bug.cgi?id=13421
> 
> Nick Clifton <nickc at redhat dot com> changed:
> 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>              Status|NEW                         |WAITING
>                  CC|                            |nickc at redhat dot com
> 
> --- Comment #2 from Nick Clifton <nickc at redhat dot com> 2011-11-25 14:16:56 UTC ---
> Hi Dave,
> 
> > Instead, a {section,address} pair should be generated by
> > applying the relocation addend to the target symbol's 
> > {section,address} pair, with the resultant pair used 
> > for locating the unwind opcodes and function symbol.
> 
> Actually this is being done already - it is just that the code that did this
> was broken...
> 
> Please try out the uploaded patch and let me know what you think.
> 
> The patch includes a lot of formatting and coding tidy-ups, (although not the
> full code refactoring that you suggested), so it may be hard to find the real
> changes.  The fixes are as follows:
> 
>   1. Correctly initialize the rel_type field in the arm_section structure.
> 
>   2. When displaying the function name, use the computed function
> section/offset abdaddr structure, not the entry absaddr structure.

I guess I don't have a strong opinion on the code -- the fix appears to
work, so I'm happy.

Thanks for the quick response!

Cheers
---Dave
Comment 4 Sourceware Commits 2011-11-28 16:51:20 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	nickc@sourceware.org	2011-11-28 16:51:10

Modified files:
	binutils       : ChangeLog readelf.c 

Log message:
	PR binutils/13421
	* readelf.c (arm_section_get_word): Add descriptive comments.
	Initliase the rel_type field of the arm_sec structure.
	(expand_prel31): Rename to arm_expand_prel31.
	(dump_arm_unwind): Use new name.
	Print the function name based on the function address entry.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/ChangeLog.diff?cvsroot=src&r1=1.1853&r2=1.1854
http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/readelf.c.diff?cvsroot=src&r1=1.561&r2=1.562
Comment 5 Nick Clifton 2011-11-28 16:53:01 UTC
Patch applied.