Thumb pic bug with address of function

Richard Earnshaw rearnsha@arm.com
Sun Mar 17 08:58:00 GMT 2002


Compiling the following program (from the gcc testsuites) shows a bug in 
the
handling of Thumb pic code.  It turns out that this is a linker/assembler 
bug.

The problem is that the entry in the GOT for a thumb function should have 
the bottom bit set, so that when it is added to the GOT address we get a 
correct thumb function pointer.  As it isn't, the call to the function 
does not work correctly, and we end up trying to interpret the target 
function as ARM code.

double
f(double x)
{
  return x*x;
}

double
Int(double (*f)(double), double a)
{
  return (*f)(a);
}

main()
{
  if (Int(&f,2.0) != 4.0)
    abort();
  exit (0);
}

main:
        push    {lr}
        ldr     r3, .L7
        mov     sl, r3
.L6:
        add     sl, pc		@ SL now points to the GOT
        ldr     r0, .L7+4	@ Load the offset for 'f'
        add     r0, r0, sl	@ And add it to the GOT
        ldr     r1, .L7+8
        ldr     r2, .L7+12
        bl      Int
...
.L7:
        .word   _GLOBAL_OFFSET_TABLE_-(.L6+4)
        .word   f(GOTOFF)
...

When we execute this code, then SL is set to 0xb7a4 (Reasonable, since 
this is the base of the GOT table) and r0 is set initially to -13848, when 
we add the two together we get 0x818c which is the absolute address of 
'f'.  However, in oder to correctly call this code, the result should have 
been 0x818d (ie have the bottom bit set).

Fix: Take the 'Thumb' bit into account when creating GOTOFF entries.

R.





More information about the Binutils mailing list