Bug 14961 - Dynamic IFUNC pointer to local function doesn't work for i386
Summary: Dynamic IFUNC pointer to local function doesn't work for i386
Status: RESOLVED DUPLICATE of bug 20515
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-14 19:37 UTC by H.J. Lu
Modified: 2016-08-29 15:16 UTC (History)
0 users

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2012-12-14 19:37:43 UTC
[hjl@gnu-6 ifunc-xxx]$ cat foo.c
static int
two (void)
{
  return 2;
}

void * foo_ifunc (void) __asm__ ("foo") __attribute__ ((visibility ("hidden")));
__asm__(".type foo, %gnu_indirect_function");

void * 
foo_ifunc (void)
{
  return two;
}

extern int foo (void) __attribute__ ((visibility ("hidden")));
int (*foo1_ptr) (void);

void
bar (void)
{
  foo1_ptr = foo;
}
[hjl@gnu-6 ifunc-xxx]$ cat main.c
#include <stdlib.h>

extern int (*foo1_ptr) (void);

extern void bar (void);

int
main (void)
{
  int foo1;
  
  bar ();
  foo1 = foo1_ptr ();
  if (foo1 != 2)
    abort ();
  return 0;
}
[hjl@gnu-6 ifunc-xxx]$ make
gcc -m32 -O3   -c -o main.o main.c
gcc -m32 -O3 -fPIC   -c -o foo.o foo.c
./ld -m elf_i386 --shared -o libfoo.so -z nocombreloc foo.o
gcc -m32 -o main main.o libfoo.so -Wl,-rpath,.
./main
make: *** [all] Segmentation fault
[hjl@gnu-6 ifunc-xxx]$
Comment 1 H.J. Lu 2012-12-14 22:36:23 UTC
This may never work correctly for i386 since its PLT entry uses
%ebx:

000001b0 <foo@plt>:
 1b0:	ff a3 0c 00 00 00    	jmp    *0xc(%ebx)
 1b6:	68 00 00 00 00       	push   $0x0
 1bb:	e9 e0 ff ff ff       	jmp    1a0 <foo@plt-0x10>

We can't return pointer to PLT entry since wrong %ebx
may be used when calling it.
Comment 2 H.J. Lu 2012-12-14 23:08:42 UTC
This is the known limitation in i386 IFUNC. The work around is
not mark IFUNC function hidden.
Comment 3 H.J. Lu 2016-08-26 18:13:02 UTC
Dup.

*** This bug has been marked as a duplicate of bug 20515 ***
Comment 4 Sourceware Commits 2016-08-29 15:16:00 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=74437ea28fb611d4c88077b486fd7c0a8b4c2a25

commit 74437ea28fb611d4c88077b486fd7c0a8b4c2a25
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Aug 29 08:12:59 2016 -0700

    i386: Issue an error on non-PIC call to IFUNC in PIC object
    
    On i386, IFUNC function must be called via PLT.  Since PLT in PIC
    object uses EBX register, R_386_PLT32 relocation must be used to
    call IFUNC function even when IFUNC function is defined locally.
    Linker should issue an error when R_386_PC32 relocation is used
    to call IFUNC function.
    
    Since PR ld/19784 tests doesn't use PLT relocation to local IFUNC
    function, they are moved to the x86-64 test directory.
    
    bfd/
    
    	PR ld/14961
    	PR ld/20515
    	* elf32-i386.c (elf_i386_check_relocs): Issue an error when
    	R_386_PC32 relocation is used to call IFUNC function in PIC
    	object.
    
    ld/
    
    	PR ld/14961
    	PR ld/20515
    	* testsuite/ld-i386/i386.exp: Run pr20515.
    	* testsuite/ld-i386/pr20515.d: New file.
    	* testsuite/ld-i386/pr20515.s: Likewise.
    	* testsuite/ld-ifunc/ifunc-14a.s: Use R_386_PLT32 to call IFUNC
    	function.
    	* testsuite/ld-ifunc/ifunc-14c.s: Likewise.
    	* testsuite/ld-ifunc/ifunc-2-i386.s: Likewise.
    	* testsuite/ld-ifunc/ifunc-2-local-i386.s: Likewise.
    	* testsuite/ld-ifunc/ifunc.exp: Move PR ld/19784 tests to ...
    	* testsuite/ld-x86-64/x86-64.exp: Here.
    	* testsuite/ld-ifunc/pr19784a.c: Moved to ...
    	* testsuite/ld-x86-64/pr19784a.c: Here.
    	* testsuite/ld-ifunc/pr19784b.c: Moved to ...
    	* testsuite/ld-x86-64/pr19784b.c: Here.
    	* testsuite/ld-ifunc/pr19784c.c: Moved to ...
    	* testsuite/ld-x86-64/pr19784c.c: Here.