For testing purposes, I modified the PLT stub that is generated by the llvm linker, lld.
The stub before was:
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
Linking a program with this (original) stub and inspecting it with objdump
yields something like this:
00000000002012d0 <printf@plt>:
2012d0: ff 25 62 0d 00 00 jmpq *0xd62(%rip) # 202038 <__TMC_END__+0x28>
2012d6: 68 02 00 00 00 pushq $0x2
2012db: e9 c0 ff ff ff jmpq 2012a0 <_fini+0x10>
I modified the PLT stub by simply adding a NOP at the end:
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
0xe9, 0x00, 0x00, 0x00, 0x00, // jmpq plt[0]
0x0f, 0x1f, 0x40, 0x00 // nop
I made sure to modify the PltEntrySize
variable so that it reflects the change in size. Linking and running programs with this modification seems to work just fine.
However, when I try to inspect the disassembly of a linked program with objdump
, I see something strange:
00000000002012d0 <printf@plt>:
2012d0: cc int3
2012d1: ff (bad)
2012d2: ff (bad)
2012d3: ff 0f decl (%rdi)
2012d5: 1f (bad)
2012d6: 40 00 ff add %dil,%dil
2012d9: 25 5a 0d 00 00 and $0xd5a,%eax
2012de: 68 02 00 00 00 pushq $0x2
2012e3: e9 b8 ff ff ff jmpq 2012a0 <_fini+0x10>
2012e8: 0f 1f 40 00 nopl 0x0(%rax)
The PLT stub's address is interpreted by objdump
to be at 0x2012d0
, but the real printf@plt
address is at 0x2012d8
! This is confirmed by readelf -s
:
Symbol table '.dynsym' contains 7 entries:
Num: Value Size Type Bind Vis Ndx Name
...
6: 00000000002012d8 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
Where does objdump
get its information from? It could very well be that I forgot to modify something in the linker.
For testing purposes, I modified the PLT stub that is generated by the llvm linker, lld.
The size and layout of the plt
entry is set in stone by the ABI (see pg. 79), and can not be changed.
Linking and running programs with this modification seems to work just fine.
I doubt any non-trivial program will run correctly with your modification -- the dynamic loader assumes ABI plt
layout, and should crash and burn when given bogus plt
.