What exactly does R_386_PC32 point to?

78 views
Skip to first unread message

Rafael Espíndola

unread,
Sep 29, 2015, 1:53:28 PM9/29/15
to ia32...@googlegroups.com
The attached test computes the address of the symbol f in two different ways:

* function g loads from the got using f@GOT
* function h loads from the global zed that has the value (f - zed)
and then adds zed.

The function _start calls both and exits with 1 if they are equal and
0 if they are not.

From the text in the psabi I would expect both to produce the same
result and _start to always exit with 0.

If the symbol f is defined in a .o, that is the case.

If the symbol f is defined in a .so, zed ends up referring to the plt
entry for f and the program exits with 0.

The intention seems to be an optimization for the case of a
translation unit compiled without -fPIC ends up calling to a shared
object. By replacing f with its plt entry a writable text segment is
avoided.

The problem is that not all R_386_PC32 are from calls.

So, should this be considered a bug or should R_386_PC32 be defined to
point to a function or its plt entry at the linker discretion?

Cheers,
Rafael
test.s
test2.s
run.sh

H.J. Lu

unread,
Sep 29, 2015, 2:11:34 PM9/29/15
to IA32 System V Application Binary Interface
I don't see anything wrong here since the function pointer may not
be the same as the address of the function body:

g:
calll .Lfoo
.Lfoo:
popl %eax
.Lbar:
addl $_GLOBAL_OFFSET_TABLE_+(.Lbar-.Lfoo), %eax
movl f@GOT(%eax), %eax
ret

returns the address of the function body of function f.

h:
leal zed, %eax
movl zed, %ebx
addl %ebx, %eax
ret

returns the pointer of function f.


H.J.

Rafael Espíndola

unread,
Sep 29, 2015, 2:55:45 PM9/29/15
to ia32...@googlegroups.com
> I don't see anything wrong here since the function pointer may not
> be the same as the address of the function body:

Probably nothing wrong, I just could not find anything saying that
that treatment of R_386_PC32 was valid. The psabi just says it is "S +
A - P".

Btw, C compilers use the "load from got" code, so the it is 'g' that
returns what in C is the function pointer. For example, compiling

void f();
void *g() { return f; }

with gcc 4.9 (-Os -fPIC -m32) produces

g:
call __x86.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
movl f@GOT(%ecx), %eax
ret


Cheers,
Rafael

H.J. Lu

unread,
Sep 29, 2015, 3:29:56 PM9/29/15
to IA32 System V Application Binary Interface
That is correct for PIC. The GOT slot of f will be filled
with the function pointer of f. Linker will make sure that
the right thing happens at run-time.


--
H.J.

Alexander Monakov

unread,
Sep 29, 2015, 10:18:24 PM9/29/15
to IA32 System V Application Binary Interface, Rich Felker
I discussed this issue with Rich Felker (in Cc); this appears to be a linker bug (both in ld.bfd and gold). I'll try to summarize.

The main executable has a PLT entry for 'f'. The GOT in the executable has two slots for 'f': one with GLOB_DAT relocation, and another with JUMP_SLOT relocation. The latter is created for the PLT entry, and should be resolved by the dynamic linker to the address of 'f' in the shared object that provides it. The former is emitted for the f@GOT(%ebx) expression in the assembly, and should point to the PLT entry, which is the nominal address of 'f'.

The problem is that this former GOT slot is not filled to point to the PLT slot by the dynamic linker. This is because the symbol table has:

00000000     0 FUNC    GLOBAL DEFAULT  UND f

Symbol value should be non-zero, holding the address of the PLT entry. For some reason the linker created the PLT entry, but emitted the symbol table entry as if the PLT entry was not created.

There are two possible fixes. Either fix the symbol table definition. Or do not emit the PLT entry in the first place: it is possible to represent 'f-.' with a relocation to 'f' with an appropriate "negative" inline addend. I suppose it's not possible for .rodata though.

As far as I see there's a bug in the linker, but the spec is fine; I wish it explained things like this in more detail, though :)

Hope that helps (and I didn't mess up details too much),
Alexander

H.J. Lu

unread,
Sep 29, 2015, 10:48:11 PM9/29/15
to IA32 System V Application Binary Interface, Rich Felker
Please fill a binutils bug report with a testcase.

Thanks.


--
H.J.

Rafael Espíndola

unread,
Sep 30, 2015, 9:36:29 AM9/30/15
to ia32...@googlegroups.com, Rich Felker
>> Hope that helps (and I didn't mess up details too much),
>> Alexander

I does, thanks a lot!

> Please fill a binutils bug report with a testcase.

https://sourceware.org/bugzilla/show_bug.cgi?id=19031

Cheers,
Rafael
Reply all
Reply to author
Forward
0 new messages