objdump showing wrong start and end address for functions

676 Views Asked by At

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.

1

There are 1 best solutions below

1
On BEST ANSWER

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.