Bug 10073

Summary: R_ARM_THM_PC8 Relocation Not Implemented in elf32-arm.c
Product: binutils Reporter: Owen Kirby <osk>
Component: ldAssignee: unassigned
Status: RESOLVED FIXED    
Severity: normal CC: bug-binutils, fff
Priority: P2    
Version: 2.19   
Target Milestone: ---   
Host: x86_64-pc-linux-gnu Target: arm-elf-unknown
Build: x86_64-pc-linux-gnu Last reconfirmed:
Attachments: Add support for reloc #8
revised form of previous patch
IAR object producing error.

Description Owen Kirby 2009-04-15 21:13:55 UTC
We are trying to link a 3rd party library compiled using the ARM/IAR compiler
into our project, which we compile using the GNU arm-elf toolchain. ld fails to
link the 3rd party library, and spits out warnings: "warning: internal error:
unsupported relocation error"

The ld appears to be complaining because the IAR compiler produces instructions
which must be relocated using R_ARM_THM_PC8, but it appears that R_ARM_THM_PC8
isn't implemented in binutils. I was able to confirm this by recompiling
binutils with some printf statements describing the unsupported relocation method.
Comment 1 Nick Clifton 2009-04-21 17:12:18 UTC
Created attachment 3898 [details]
Add support for reloc #8
Comment 2 Nick Clifton 2009-04-21 17:13:57 UTC
Hi Owen,

  I have uploaded a possible patch to fix this problem - please could you try it
out for me ?

  Not having any binaries containing the R_ARM_THM_PC8 reloc makes testing
locally impossible, but I think that I have implemented it correctly.

Cheers
  Nick
Comment 3 Owen Kirby 2009-04-30 18:42:16 UTC
Hi Nick,

I tried out the patch, but it doesn't appear to work correctly. GNU ld still
outputs warnings when attempting to link the two libraries. We get the following
warnings:

libecc.a(tk-aes-e.obj): In function `tkAesSetupEnc':
c:\IAR_work\mce_release\src\aes\tk-aes-e.c:(.text+0x98): relocation truncated to
fit: R_ARM_THM_PC8 against `.text_9'
libecc.a(tk-aes-e.obj): In function `aesEnc':
c:\IAR_work\mce_release\src\aes\tk-aes-e.c:(.text+0x416): relocation truncated
to fit: R_ARM_THM_PC8 against `.text_11'

I downloded a copy of the ARM/ELF specification, and it shows that the
R_ARM_THM_PC8 appears to be a special case for computing the initial addend. I'm
not sure if the submitted patch takes this into account.

Thanks,
Owen

(In reply to comment #2)
> Hi Owen,
> 
>   I have uploaded a possible patch to fix this problem - please could you try it
> out for me ?
> 
>   Not having any binaries containing the R_ARM_THM_PC8 reloc makes testing
> locally impossible, but I think that I have implemented it correctly.
> 
> Cheers
>   Nick
> 

Comment 4 JayS@spectralogic.com 2009-05-04 03:50:16 UTC
Subject: RE:  R_ARM_THM_PC8 Relocation Not Implemented in elf32-arm.c

Owen, Nick, et. al.,

I've been working towards the same objective and stumbled across your post.

I tried Nick's fix of 4/21 and had similar results.

I believe that there is an additional problem.

If you go to the HOWTO() macro for R_ARM_THM_PC8 (elf32-arm.c, line 235), it shows a shift count of one.  ARM's documentation shows that the R_ARM_THM_PC8 relocation is only used for an LDR(3) instruction, which uses a shift count of two:

Syntax

LDR <Rd>, [PC, #<immed_8> * 4]

where:

<Rd> Is the destination register for the word loaded from memory.

PC Is the program counter. Its value is used to calculate the memory address. Bit 1 of the PC
value is forced to zero for the purpose of this calculation, so the address is always
word-aligned.

<immed_8> Is an 8-bit value that is multiplied by 4 and added to the value of the PC to form the memory
address.

I haven't had a chance to rebuild and test it with a shift count of two.  I don't subscribe to the mailing list, but if you are interested in how it comes out, email me at jays at spectralogic dot com and I will let you know.  I'd ask that you do the same if you find anything out.

Thanks for the suggestions so far, and good luck.

Jay



Comment 5 JayS@spectralogic.com 2009-05-04 22:05:22 UTC
Subject:  R_ARM_THM_PC8 Relocation Not Implemented in elf32-arm.c

Some thoughts:

I'm now linking an IAR object file that used to produce the same type of
errors that Owen had.  I made my own changes to the "case" handler that
seem logical to me, but I didn't try very hard to use the version that
Nick posted, so I can't say whether or not his version would work.

It looks like there were at least two distinct problems, and likely
more.  The first, of course, is that the linker didn't handle the
R_ARM_THM_PC8 case.  The second is the handling of overflows.  Also (as
mentioned above), I'm not sure that the way shifts were handled was
correct.

The IAR compiler apparently generates "signed" offsets in the
instructions, even though the offset used by ldr(3) is specified as
unsigned.  Their object files typically contain an offset of 0xff to
start with, and to which the relocation displacement is added.  This
always results in an overflow when interpreted by arm32-elf ld.  They
may do this for convenience, so that the relocation entry is relative to
the beginning of the instruction, not the pc register at the time of
execution.  I'm not sure what, if any, side effects may result from this
practice.  There may be none.  It still looks scary.

I think that they may also do this with other relocations.  I also get
overflow errors with the R_ARM_THM_CALL relocation.  I've disabled these
with a "#if 0" in my build, and it now builds code that looks like it
will run okay. 

The case statement for R_ARM_THM_PC8 relocation now reads:

    case R_ARM_THM_PC8:

    	/* XXXjs 5/04/2009 Support thumb ldr(3) instruction, ignore
overflow. */
	{
		bfd_vma insn;
		bfd_signed_vma relocation;

		insn = bfd_get_16 (input_bfd, hit_data);

		if (globals->use_rel)
			addend = (insn & 0x00ff) << 2;

		signed_addend = addend;

		relocation = value + signed_addend;
		relocation -= (input_section->output_section->vma
						+
input_section->output_offset
						+ rel->r_offset);

		value = abs (relocation);

		insn = (insn & 0xff00) | (value >> 2);

		bfd_put_16 (input_bfd, insn, hit_data);

		return bfd_reloc_ok;
	}

Also, I disable testing and setting the overflow flag in the handler for
R_ARM_THM_XPC22, R_ARM_THM_CALL and R_ARM_THM_JUMP24.  I presume that
the errors that I've seen in R_ARM_THM_CALL are caused by the same
situation as R_ARM_THM_PC8, although I haven't put the effort into
dumping these out in detail.

Jay
Comment 6 Nick Clifton 2009-05-05 11:12:41 UTC
Created attachment 3924 [details]
revised form of previous patch
Comment 7 Nick Clifton 2009-05-05 11:15:48 UTC
Hi Owen,

  OK, I have uploaded a revised patch based Jay's suggestion.  Please give it a
go and let me know if it works this time.

  I am not comfortable with suppressing the overflow warnings for the other
relocations however.  The checks are correct and those relocs are being
processed in the way that ARM specifies.  I think that it would be better to
find out exactly why the overflows are occurring an then determine if the IAR
compiler is at fault or if there is some kind of gcc specific assumption in the
linker.

  Would it be possible for you to post a simple IAR compiled object file that
generates these overflowing relocs ?

Cheers
  Nick
Comment 8 Owen Kirby 2009-05-06 20:10:34 UTC
Created attachment 3926 [details]
IAR object producing error.

I've uploaded some sample code that can be used to reproduce the bug and to
test the fix. The object file (test-pc8.o) was compiled using an evaluation
copy of IAR's C compiler.
Comment 9 Nick Clifton 2009-07-01 14:47:16 UTC
Hi Owen,

  Thanks for the test case, and sorry for the long delay in getting back to this
bug.  Using that test case and the second version of the patch I created I get a
working executable (which prints 0x00000000) and no linker warnings about
relocation overflows.

  So I am going to check in the patch and close this PR.  If you find that there
is still a problem, please feel free to reopen the PR and upload a new test.

Cheers
  Nick