Runtime Symbol Resolution

download Runtime Symbol Resolution

If you can't read please download the document

description

This presentation material is about runtime symbol resolution on Linux x86-64. We will not discuss Windows/Mac implementation.

Transcript of Runtime Symbol Resolution

  • 1. Runtime Symbol Resolution

2. Outline

  • Overview of Dynamic Library 3. Relocatable code / Relocation section 4. Executable code / PLT & GOT 5. Runtime process analysis with GDB 6. Summary

7. Overview

  • This is about runtime symbol resolution on Linux x86-64
    • Windows/Mac have different mechanisms
  • Assume source code is written in C 8. Linker means static linker (not dynamic) in this material

9. Build (& Load) Process Usually you just type gcc foo.c and it invokes the four sub-processes for you. (text) (text) (text) (ELF) (ELF) (ELF) C code Preprocessed C code Assembly code Executable code Relocatable code Preprocessor Compiler Process Image Assembler Linker Loader DL 10. What's Dynamic Library?

  • Dynamic library is linked at runtime
    • While static library is linked at compile-time
  • Shared by more than one application
    • Often called Shared library

Process 1 Process 2 Dynamic Lib Static Lib Static Lib Process 1 Process 2 Memory (or storage) image 11. How is DL different?

  • Address of symbols (functions, variables) are only known at run-time
    • Linker cannot tell where the DL will be loaded 12. Executables cannot contain exact addresses
  • Loader must play a role so that the code can call functions (or refer to variables) defined in DLs

13. Sample Code: Hello, World! #include int main() {puts("Hello, World!"); return 0; } hello.c 14. Build

  • Preprocess & Compile & Assemble
    • gcc -c hello.c generates a relocatable file hello.o
  • Preprocess & Compile & Assemble & Link
    • gcc hello.c generates an executable file a.out

% lsa.outhello.chello.o 15. Relocatable code % objdump -d hello.o // disassemble text section [...] 0000000000000000 : 0:55push%rbp 1:48 89 e5mov%rsp,%rbp 4:bf 00 00 00 00mov$0x0,%edi 9:e8 00 00 00 00callqe e:b8 00 00 00 00mov$0x0,%eax 13:5dpop%rbp 14:c3retqThis must be a call to puts. But ... 16. e8 or callq

  • Instruction e8 is Call displacement relative to nextinstruction...
    • See Intel Software Developer's Manual
  • e8 00 00 00 00 means call next instruction, which doesn't make sense 17. 00 00 00 00 must be replaced with puts
    • hello.o must contain relocation info

18. Relocation section % readelf-rhello.o # output edited for better readability Relocation section '.rela.text' at offset 0x598 contains 2 entries: OffsetInfoTypeSym. Val.Sym. Name+ Addend 0000000500050000000a R_X86_64_3200000000 .rodata + 0 0000000a 000a 00000002R_X86_64_PC32 00000000puts- 4 [] The symbol has index 0x0a (= puts) Show relocation section Replace value at 0x0a addend Value = [value of symbol] + [addend] - [offset] 19. Summary: Relocatable code

  • Code (or .text section) has zero as an address 20. Relocation table (or .rela section) tells what to replace the zero with 21. The later process must utilize the relocation info to actually link puts to the code

22. Executable code % objdump -d a.out // disassemble text section [...] 00000000004004c4 : 4004c4: 55push%rbp 4004c5: 48 89 e5mov%rsp,%rbp 4004c8: bf e0 05 40 00mov$0x4005e0,%edi 4004cd: e8 e6 fe ff ffcallq4003b8 4004d2: b8 00 00 00 00mov$0x0,%eax 4004d7: 5dpop%rbp 4004d8: c3retq Calling puts@plt, not puts 23. Executable code: PLT % objdump -d a.out [...] 00000000004003a8 : 4003a8: pushq0x2004b2(%rip)# 600860 4003ae: jmpq*0x2004b4(%rip)# 600868 4003b4: nopl0x0(%rax) 00000000004003b8 < [email_address] >: 4003b8: jmpq*0x2004b2(%rip)# 600870 4003be: pushq$0x0 4003c3: jmpq4003a8 _GLOBAL_OFFSET_TABLE_+0x8 _GLOBAL_OFFSET_TABLE_+0x10 _GLOBAL_OFFSET_TABLE_+0x18 Machine code is omitted as it's getting cryptic... 24. Executable code: GOT Symbol Address Value _GLOBAL_OFFSET_TABLE_ + 0x0 0x600858 0x006006c0 _GLOBAL_OFFSET_TABLE_ + 0x8 0x600860 0x00000000 _GLOBAL_OFFSET_TABLE_ + 0x10 0x600868 0x00000000 _GLOBAL_OFFSET_TABLE_ + 0x18 0x600870 0x004003be _GLOBAL_OFFSET_TABLE_ + 0x20 0x600878 0x004003ce

  • GOT contents can be shown with objdump
    • objdump -s --start-address=0x600858 --stop-address=0x600880 a.out

25. Summary: Executable code

  • When puts@plt is called
    • Jump to an address stored in GOT
      • The addresspoints to the next instruction
    • Push0to stack 26. Jump to puts@plt 0x10 27. Push an address of a GOT entry to stack 28. Jump to the address stored in GOT
      • The address is set to 0
  • What's going on???

??? Jumping to address 0 will crash the process What's this 0? What's this address used for? 29. A bit more analysis...

  • Just before jumping to address 0, stack should look like... 30. Executable code has .rela.plt section

Relocation section '.rela.plt' at offset 0x360 contains 2 entries: OffsetInfoTypeSym. Val.Sym. Name + Addend 00600870 []R_X86_64_JUMP_SLO 00000000puts + 0 00600878 []R_X86_64_JUMP_SLO 00000000__libc_start_main + 0 Stack Top ... 0x600860 0 31. Process Image

  • GOT in the executable code looks weird. Gdb can show us the real GOT at runtime

% gdb a.out [...] Reading symbols from /foo/a.out...[...] (gdb) start Temporary breakpoint 1 at 0x4004c8 Starting program: /foo/a.outTemporary breakpoint 1, 0x00000000004004c8 in main () 32. Process Image: GOT

  • Remember GOT is stored at 0x600858

(gdb) x/a 0x600858 0x600858:0x6006c0 (gdb) x/a 0x600860 0x600860:0x302cc20288 (gdb) x/a 0x600868 0x600868:0x302ca13850 (gdb) x/a 0x600870 0x600870:0x4003be (gdb) x/a 0x600878 0x600878:0x302ce212b0 33. Changes in GOT Address Value in Executable Value in Process 0x600858 0x6006c0 0x6006c0 0x600860 0x0 0x302cc20288 0x600868 0x0 0x302ca13850 0x600870 0x4003be 0x4003be 0x600878 0x4003ce 0x302ce212b0 Ignore this change for now 34. Revisiting puts@plt

  • When puts@plt is called
    • Jump to an address stored in GOT
      • The addresspoints to the next instruction
    • Push0to stack 35. Jump to puts@plt 0x10 36. Push an address of a GOT entry to stack
      • The address stores value 0x302cc20288
    • Jump to _dl_runtime_resolve
      • The name suggests runtime symbol resolution

??? What's this 0? What's this address used for? 37. _dl_runtime_resolve

  • Don't have time to dive into the function :-) 38. Takes 2 arguments
    • A pointer to a structure containing DL info
      • 0x302cc20288 in this case
    • An index of relocation entry in .rela.plt
      • 0 for puts; 1 for __libc_start_main
  • Replaces a value in GOT 39. Jmp to the function
    • puts in this case

40. Revisiting puts@plt (3 rdtime)

  • When puts@plt is called
    • Jump to an address stored in GOT
      • The addresspoints to the next instruction
    • Push0to stack
      • 2 ndargument to _dl_runtime_resolve
    • Jump to puts@plt 0x10 41. Push an address of a GOT entry to stack
      • 1 stargument to _dl_runtime_resolve
    • Jump to _dl_runtime_resolve
      • GOT entry is replaced with the address of puts

??? 42. GOT after calling puts (gdb) ni 0x00000000004004cd in main () (gdb) ni Hello, World! 0x00000000004004d2 in main () (gdb) x/a 0x600870 0x600870:0x302ce692e0 Step over to next instruction puts is called Now the GOT entry containsthe actual address of puts ! 43. Lazy link

  • What happens if the code has another call to puts
    • puts@plt is called 44. Jump to an address stored in GOT
      • Which is now an exact address of puts 45. No need to jump to _dl_runtime_resolve
  • The complicated code in .plt section is for lazy link
    • Every function call is resolved on the first call

46. Revisiting puts@plt (4 thtime)

  • When puts@plt is called
    • Jump to an address stored in GOT
      • The address initiallypoints to the next instructionand is later replaced with puts address
    • Push0to stack 47. Jump to puts@plt 0x10 48. Push an address of a GOT entry to stack 49. Jump to _dl_runtime_resolve
      • Which uses 0 and the GOT entry address

50. Summary

  • How dynamic link is implemented
    • .rela section in ELF 51. Indirect call via Procedure Linkage Table 52. Lazy linking by using Global Offset Table
      • Help to speed up application launch
    • _dl_runtime_resolve does the linking
      • Defined in glibc. Might be interesting to look into it.

53. References

  • AMD64 Application Binary Interface
    • http://www.x86-64.org/documentation/abi.pdf
  • Intel386 Architecture Processor Supplement
    • http://www.sco.com/developers/devspecs/abi386-4.pdf
  • Intel Software Developer Manual
    • http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
  • Linkers and Loaders
    • http://www.iecc.com/linker/