This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][x86_64] Convert indirect call via GOT to direct when possible

On Fri, May 20, 2016 at 2:15 PM, Sriraman Tallam <> wrote:
> On Fri, May 20, 2016 at 1:32 PM, H.J. Lu <> wrote:
>> On Fri, May 20, 2016 at 1:27 PM, Sriraman Tallam <> wrote:
>>> Hi,
>>>    GCC has option -fno-plt which converts all extern calls to indirect
>>> calls via GOT to prevent the linker for generating any PLT stubs.
>>> However, if the function ends up defined in the executable this patch
>>> will convert those indirect calls/jumps to direct.  Since the indirect
>>> calls are one byte longer, an extra nop is needed at the beginning.
>>> Here is a simple example:
>>> main.c
>>> ---------
>>> extern int foo();
>>> int main() {
>>>   return foo();
>>> }
>>> deffoo.c
>>> -----------
>>> int foo() {
>>>   return 0;
>>> }
>>> $ gcc -fno-plt main.c deffoo.c
>>> $objdump -d a.out
>>> 0000000000400626 <main>:
>>>   ...
>>>   40062a:       ff 15 28 14 00 00       callq  *0x1428(%rip)        #
>>> 401a58 <_DYNAMIC+0x1d8>
>>> The call is indirect even though foo is defined in the executable.
>>> With this patch,
>>> 0000000000400606 <main>:
>>>    ....
>>>    40060a:       90                      nop
>>>   40060b:       e8 03 00 00 00          callq  400613 <foo>
>>> The call is now direct with an extra nop.
>> Please try ld, which uses 0x67 prefix (addr32) instead of nop.
> Is this committed to ld?, trunk ld does not seem to do this.

It works for me.

> Also a quick thing about -fPIE and -fno-plt.  The assembly looks like
> this for the call:
> movq foo@GOTPCREL(%rip), %rax
> jmp *%rax
> Why can't we make this a single jmp *foo@GOTPCREL(%rip)

Works for me:

[hjl@gnu-6 tmp]$ cat x.c
extern void bar (void);

foo (void)
  bar ();
[hjl@gnu-6 tmp]$ cat y.c
extern void foo (void);

bar (void)

main (void)
  foo ();
  return 0;
[hjl@gnu-6 tmp]$ /usr/gcc-6.1.1-x32/bin/gcc -S -fPIE -fno-plt -O2 x.c y.c
[hjl@gnu-6 tmp]$ /usr/gcc-6.1.1-x32/bin/gcc -pie x.o y.o
gcc: error: y.o: No such file or directory
[hjl@gnu-6 tmp]$ /usr/gcc-6.1.1-x32/bin/gcc -S -fPIE -fno-plt -O2 x.c y.c
[hjl@gnu-6 tmp]$ /usr/gcc-6.1.1-x32/bin/gcc -pie x.s y.s
[hjl@gnu-6 tmp]$ cat x.s
.file "x.c"
.p2align 4,,15
.globl foo
.type foo, @function
jmp *bar@GOTPCREL(%rip)
.size foo, .-foo
.ident "GCC: (GNU) 6.1.1 20160428"
.section .note.GNU-stack,"",@progbits
[hjl@gnu-6 tmp]$ gdb a.out
GNU gdb (GDB) Fedora 7.10.1-31.fc23
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
Find the GDB manual and other documentation resources online at:
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) disass foo
Dump of assembler code for function foo:
   0x0000000000000660 <+0>: jmpq   0x670 <bar>
   0x0000000000000665 <+5>: nop
End of assembler dump.

> This goes via the GOT if foo is external and that is always reachable
> with a 32-bit offset. Did I miss anything obvious?
>> Also for
>> jmp *foo#GOTPCREL(%rip)
>>  ld converts it to
>> jmp foo
>> nop
>> --
>> H.J.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]