Runtime Symbol Resolution
Upcoming SlideShare
Loading in...5
×
 

Runtime Symbol Resolution

on

  • 3,718 views

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

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

Statistics

Views

Total Views
3,718
Slideshare-icon Views on SlideShare
3,710
Embed Views
8

Actions

Likes
1
Downloads
40
Comments
0

4 Embeds 8

http://www.thelibrarynews.com 4
https://twitter.com 2
http://www.slashdocs.com 1
http://www.linkedin.com 1

Accessibility

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Runtime Symbol Resolution Runtime Symbol Resolution Presentation Transcript

    • Runtime Symbol Resolution
    • Outline
      • Overview of Dynamic Library
      • Relocatable code / Relocation section
      • Executable code / PLT & GOT
      • Runtime process analysis with GDB
      • Summary
    • Overview
      • This is about runtime symbol resolution on Linux x86-64
        • Windows/Mac have different mechanisms
      • Assume source code is written in C
      • “Linker” means “static linker” (not dynamic) in this material
    • 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
    • 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
    • How is DL different?
      • Address of symbols (functions, variables) are only known at run-time
        • Linker cannot tell where the DL will be loaded
        • Executables cannot contain exact addresses
      • Loader must play a role so that the code can call functions (or refer to variables) defined in DLs
    • Sample Code: Hello, World! #include <stdio.h> int main() { puts(&quot;Hello, World!&quot;); return 0; } hello.c
    • 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”
      % ls a.out hello.c hello.o
    • Relocatable code % objdump -d hello.o // disassemble text section [...] 0000000000000000 <main>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: bf 00 00 00 00 mov $0x0,%edi 9: e8 00 00 00 00 callq e <main+0xe> e: b8 00 00 00 00 mov $0x0,%eax 13: 5d pop %rbp 14: c3 retq This must be a call to “puts”. But ...
    • “e8” or “callq”
      • Instruction “e8” is “Call … displacement relative to next instruction...”
        • See “Intel Software Developer's Manual”
      • “e8 00 00 00 00” means “call next instruction”, which doesn't make sense
      • “00 00 00 00” must be replaced with “puts”
        • “hello.o” must contain relocation info
    • Relocation section % readelf -r hello.o # output edited for better readability Relocation section '.rela.text' at offset 0x598 contains 2 entries: Offset Info Type Sym. Val. Sym. Name + Addend 00000005 00050000000a R_X86_64_32 00000000 .rodata + 0 0000000a 000a 00000002 R_X86_64_PC32 00000000 puts - 4 […] The symbol has index 0x0a (= “puts”) Show relocation section Replace value at 0x0a addend Value = [value of symbol] + [addend] - [offset]
    • Summary: Relocatable code
      • Code (or “.text” section) has zero as an address
      • Relocation table (or “.rela” section) tells what to replace the zero with
      • The later process must utilize the relocation info to actually link “puts” to the code
    • Executable code % objdump -d a.out // disassemble text section [...] 00000000004004c4 <main>: 4004c4: 55 push %rbp 4004c5: 48 89 e5 mov %rsp,%rbp 4004c8: bf e0 05 40 00 mov $0x4005e0,%edi 4004cd: e8 e6 fe ff ff callq 4003b8 <puts@plt> 4004d2: b8 00 00 00 00 mov $0x0,%eax 4004d7: 5d pop %rbp 4004d8: c3 retq Calling “puts@plt”, not “puts”
    • Executable code: PLT % objdump -d a.out [...] 00000000004003a8 <puts@plt-0x10>: 4003a8: pushq 0x2004b2(%rip) # 600860 4003ae: jmpq *0x2004b4(%rip) # 600868 4003b4: nopl 0x0(%rax) 00000000004003b8 < [email_address] >: 4003b8: jmpq *0x2004b2(%rip) # 600870 4003be: pushq $0x0 4003c3: jmpq 4003a8 <_init+0x18> _GLOBAL_OFFSET_TABLE_+0x8 _GLOBAL_OFFSET_TABLE_+0x10 _GLOBAL_OFFSET_TABLE_+0x18 Machine code is omitted as it's getting cryptic...
    • 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”
    • Summary: Executable code
      • When “puts@plt” is called …
        • Jump to an address stored in GOT
          • The address points to the next instruction
        • Push 0 to stack
        • Jump to “puts@plt – 0x10”
        • Push an address of a GOT entry to stack
        • 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?
    • A bit more analysis...
      • Just before jumping to address 0, stack should look like...
      • Executable code has “.rela.plt” section
      Relocation section '.rela.plt' at offset 0x360 contains 2 entries: Offset Info Type Sym. Val. Sym. Name + Addend 00600870 […] R_X86_64_JUMP_SLO 00000000 puts + 0 00600878 […] R_X86_64_JUMP_SLO 00000000 __libc_start_main + 0 Stack Top ... 0x600860 0
    • 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.out Temporary breakpoint 1, 0x00000000004004c8 in main ()
    • Process Image: GOT
      • Remember GOT is stored at 0x600858
      (gdb) x/a 0x600858 0x600858: 0x6006c0 <_DYNAMIC> (gdb) x/a 0x600860 0x600860: 0x302cc20288 (gdb) x/a 0x600868 0x600868: 0x302ca13850 <_dl_runtime_resolve> (gdb) x/a 0x600870 0x600870: 0x4003be <puts@plt+6> (gdb) x/a 0x600878 0x600878: 0x302ce212b0 <__libc_start_main>
    • Changes in GOT Address Value in Executable Value in Process 0x600858 0x6006c0 0x6006c0 0x600860 0x0 0x302cc20288 0x600868 0x0 0x302ca13850 <_dl_runtime_resolve> 0x600870 0x4003be <_puts@plt+6> 0x4003be <_puts@plt+6> 0x600878 0x4003ce <__libc_start_main@plt+6> 0x302ce212b0 <__libc_start_main> Ignore this change for now
    • Revisiting “puts@plt”
      • When “puts@plt” is called …
        • Jump to an address stored in GOT
          • The address points to the next instruction
        • Push 0 to stack
        • Jump to “puts@plt – 0x10”
        • 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?
    • _dl_runtime_resolve
      • Don't have time to dive into the function :-)
      • 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
      • Jmp to the function
        • “puts” in this case
    • Revisiting “puts@plt” (3 rd time)
      • When “puts@plt” is called …
        • Jump to an address stored in GOT
          • The address points to the next instruction
        • Push 0 to stack
          • 2 nd argument to “_dl_runtime_resolve”
        • Jump to “puts@plt – 0x10”
        • Push an address of a GOT entry to stack
          • 1 st argument to “_dl_runtime_resolve”
        • Jump to “_dl_runtime_resolve”
          • GOT entry is replaced with the address of “puts”
      ???
    • GOT after calling “puts” (gdb) ni 0x00000000004004cd in main () (gdb) ni Hello, World! 0x00000000004004d2 in main () (gdb) x/a 0x600870 0x600870: 0x302ce692e0 <puts> Step over to next instruction “ puts” is called Now the GOT entry contains the actual address of “puts” !
    • Lazy link
      • What happens if the code has another call to “puts”
        • “puts@plt” is called
        • Jump to an address stored in GOT
          • Which is now an exact address of “puts”
          • 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
    • Revisiting “puts@plt” (4 th time)
      • When “puts@plt” is called …
        • Jump to an address stored in GOT
          • The address initially points to the next instruction and is later replaced with “puts” address
        • Push 0 to stack
        • Jump to “puts@plt – 0x10”
        • Push an address of a GOT entry to stack
        • Jump to “_dl_runtime_resolve”
          • Which uses 0 and the GOT entry address
    • Summary
      • How dynamic link is implemented
        • “.rela” section in ELF
        • Indirect call via Procedure Linkage Table
        • 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.
    • 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/