340 likes | 542 Views
Linking. Outline. Symbol Table Relocation Symbol Resolution Suggested reading: 7.5, 7.7, 7.6. Symbol Resolution. void foo(void) int main() { foo() ; return 0 ; } Unix> gcc –Wall –O2 –o linkerror linkerror.c /tmp/ccSz5uti.o: In function ‘main’:
E N D
Outline • Symbol Table • Relocation • Symbol Resolution • Suggested reading: 7.5, 7.7, 7.6
Symbol Resolution • void foo(void) • int main() • { • foo() ; • return 0 ; • } Unix> gcc –Wall –O2 –o linkerror linkerror.c /tmp/ccSz5uti.o: In function ‘main’: /tmp/ccSz5uti.o (.text+0x7): undefined reference to ‘foo’ collect2: ld return 1 exit status
ELF header Program header table (required for executables) .text section .data section .bss section .symtab .rel.txt .rel.data .debug .line .strtab Section header table (required for relocatables) EFI object file format
Symbols • Three kinds of symbols • Defined global symbols • Referenced global symbols • Local symbols
Symbols • Defined global symbols • Defined by the module (file) m and can be referenced by other modules (files) • Nonstatic C functions • Global variables that are defined without the C static attribute
Symbols • Referenced global symbols • Referenced by the module m but defined by some other modules • C functions and variables that are defined in other files • Local symbols • Defined and referenced exclusively by the module m. • C functions and global variables with static attribute
Symbol Tables • Each relocatable object file has a symbol table • A symbol table contains information about the symbols that are defined and referenced in the file
Symbol Tables • Local nonstatic program variables • does not contain in the symbol table in .symbol • Local static procedure variables • Are not managed on the stack • Be allocated in .data or .bss
Examples • int f() • { • static int x=1 ; • return x; • } • int g() • { • static int x = 1; • return x ; • } • x.1 and x.2 are allocated in .data
Symbol Tables • Compiler exports symbols in .s file • Assembler builds symbol tables using exported symbols • An ELF symbol table is contained in .symtab section • Symbol table contains an array of entries
Example (Symbol Table) (Hw 7.6) extern int buf[]; int *bufp0 = &buf[0]; static int *bufp1; static void incr() { static int count=0; count++; }
Example (Symbol Table) (Hw 7.6) .file“swap.c" .globlbufp0 .data .align 4 .typebufp0, @object .sizebufp0, 4 bufp0: .longbuf .localbufp1 .commbufp1,4,4
Example (Symbol Table) (Hw 7.6) .text .typeincr, @function incr: pushl%ebp movl%esp, %ebp movlcount.1231, %eax addl$1, %eax movl%eax, count.1231 popl%ebp ret .size incr, .-incr .localcount.1231 .commcount.1231,4,4
Example (Symbol Table) (Hw 7.6) void swap() { int temp; incr(); bufp1 = &buf[1]; temp = *bufp0; *bufp0 = *bufp1; *bufp1 = temp; }
Example (Symbol Table) (Hw 7.6) • the module that defines the symbol • swap.o • main.o • the symbol type • local • global • extern • the section • .text • .data • .bss
Example (Symbol Table) (Hw 7.6) main.o .data extern global swap.o .data swap.o local .bss swap.o global .txt local swap.o .txt swap.o local .data
ELF Symbol Tables • typedef struct { • int name ; /* string table offset */ • int value ; /* section offset, or VM address */ • int size ; /* object size in bytes */ • char type:4 , /* data, func, section, or src file name */ • binding:4 ; /* local or global */ • char reserved ;/* unused */ • char section ; /* section header index, ABS, UNDEF, */ • /* or COMMON */ • } • ABS, UNDEF, COMMON • GNU readelf tool
ELF Symbol Tables main.o Num: Value Size Type Bind Ot Ndx Name 8: 0 8 OBJECT GLOBAL 0 3 buf 9: 0 17 FUNC GLOBAL 0 1 main 10: 0 0 NOTYPE GLOBAL 0 UND swap
ELF Symbol Tables swap.o Num: Value Size Type Bind Ot Ndx Name 8: 0 4 OBJECT GLOBAL 0 3 bufp0 9: 0 0 NOTYPE GLOBAL 0 UND buf 10: 0 39 FUNC GLOBAL 0 1 swap 11: 4 4 OBJECT GLOBAL 0 COM bufp1 alignment
Relocation • Relocation • Merge the input modules • Assign runtime address to each symbol • Two steps • Relocating sections and symbol definitions • Relocating symbol references within sections
Relocation • For each reference to an object with unknown location • Assembler generates a relocation entry • Relocation entries for code are placed in .rel.text • Relocation entries for data are placed in .rel.data
Relocation • Relocation Entry typedef struct { int offset ; int symbol:24, type:8 ; } Elf32_Rel ;
Relocation • e8 fc ff ff ff call 7<main+0x7> swap(); There is a relocation entry in rel.text offset symbol type 7 swap R_386_PC32
Relocation int *bufp0 = &buf[0] ; 00000000 <bufp0>: 0: 00 00 00 00 There is a relocation entry in rel.data offset symbol type 0 buf R_386_32
Relocation • e8 fc ff ff ff call 7<main+0x7> swap(); 7: R_386_PC32 swap relocation entry r.offest = 0x7 r.symbol = swap r.type = R_386_PC32 ADDR(main)=ADDR(.text) = 0x80483b4 ADDR(swap)=0x80483c8 refaddr = ADDR(main)+r.offset = 0x80483bb ADDR(r.symbol)=ADDR(swap)=0x80483c8 *refptr = (unsigned) (ADDR(r.symbol) + *refptr – refaddr) = (unsigned) (0x80483c8 + (-4) – 0x80483bb) = (unsigned) 0x9 PC-relative
Relocation int *bufp0 = &buf[0] ; 00000000 <bufp0>: 0: 00 00 00 00 int *bufp0 = &buf[0]; 0: R_386_32 buf relocation entry ADDR(r.symbol) = ADDR(buf) = 0x8049454 *refptr = (unsigned) (ADDR(r.symbol)+ *refptr) = (unsigned) (0x8049454) 0804945c <bufp0>: 0804945c: 54 94 04 08
Relocation • foreach section s { • foreach relocation entry r { • refptr = s + r.offset ; /* ptr to reference to be relocated */ • /* relocate a PC-relative reference */ • if (r.type == R_386_PC32) { • refaddr = ADDR(s) + r.offset ; /* ref’s runtime address */ • *refptr=(unsigned) (ADDR(r.symbol)+*refptr –refaddr) ; • } • /* relocate an absolute reference */ • if ( r.type == R_386_32 ) • *refptr = (unsigned) (ADDR(r.symbol) + *refptr) ; • } • }
Example (Relocation) (Hw 7.12) 1 00000000 <swap>: 2 0: 55 push %ebp 3 1: 8b 15 00 00 00 00 mov 0x0,%edx Get *bufp0=&buf[0] 4 3: R_386_32 5 7: a1 04 00 00 00 mov 0x4,%eax Get buf[1] 6 8: R_386_32 7 c: 89 e5 mov %esp,%ebp 8 e: c7 05 00 00 00 00 movl $0x4,0x0 bufp1 = &buf 9 14: 04 00 00 00 10 10: R_386_32 11 14: R_386_32 12 18: 89 ec mov %ebp,%esp 13 1a: 8b 0a mov (%edx),%ecx temp = buf[0]; 14 1c: 89 02 mov %eax,(%edx) buf[0]=buf[1]; 15 1e: a1 00 00 00 00 mov 0x0,%eax Get *bufp1=&buf[1] 16 1f: R_386_32 17 23: 89 08 mov %ecx,(%eax) buf[1]=temp; 18 25: 5d pop %ebp 19 26: c3 ret
Example (Relocation) (Hw 7.12) .rel.text 3: R_386_32 bufp0 8: R_386_32 buf 10: R_386_32 bufp1 14: R_386_32 buf 1f: R_386_32 bufp1 ADDR(swap)=0x80483c8 ADDR(buf) = 0x8049454 ADDR(bufp0)=0x804945c ADDR(bufp1)=0x8049548
Relocation • 080483b4<main>: • 080483b4: 55 push %ebp • 080483b5: 89 e5 mov %esp, %ebp • 080483b7: 83 ec 08 sub $0x8, %esp • 080483ba: e8 09 00 00 00 call 80483c8 <swap> • 080483bf: 31 c0 xor %eax, %eax • 080483c1: 89 ec mov %ebp, %esp • 080483c3: 5d pop %ebp • 080483c4: c3 ret • 080483c5: 90 nop • 080483c6: 90 nop • 080483c7: 90 nop
Relocation • 080483c8<swap>: • 80483c8: 55 push %ebp • 80483c9: 8b 15 5c 94 04 08 mov 0x804945c, %edx get *bufp0 • 80483cf: a1 58 94 04 08 mov 0x8049458, %edx get buf[1] • 80483d4: 89 e5 mov %esp, %ebp • 80483d6: c7 05 48 95 04 08 movl $0x8049458, 0x8049548 • 80483de: 58 94 04 08bufp1 = &buf[1] • 80483e0: 89 ec mov %ebp, %esp • 80483e2: 8b 0a mov (%edx), %ecx • 80483e4: 80 02 mov %eax, (%edx) • 80483e6: a1 48 95 04 08 mov 0x8049548, %eax • 80483eb: 89 08 mov %ecx, (%eax) • 80483ed: 5d pop %ebp • 80483ee: c3 ret
Relocation • 08049454 <buf>: • 8049454: 01 00 00 00 02 00 00 00 • 0804945c<bufp0>: • 804945c: 54 94 04 08