14 Linkers W
14 Linkers W
Hakim Weatherspoon
CS 3410, Spring 2013
Computer Science
Cornell University
See: P&H Appendix B.3-4 and 2.12
Goal for Today: Putting it all Together
Review Calling Convention
0x80000000
0x7ffffffc
stack
$0 (zero)
A
memory $1 ($at)
register
D
alu
file
$29 ($sp)
B
$31 ($ra)
+4
addr
inst
PC din dout
M
control
B
memory
imm
extend
new
forward
pc detect
unit Stack, Data, Code
hazard
Stored in Memory
Instruction Instruction Write-
ctrl
ctrl
ctrl
Fetch Decode Execute Memory Back
IF/ID ID/EX EX/MEM MEM/WB
Takeaway
We need a calling convention to coordinate use of
registers and memory. Registers exist in the
Register File. Stack, Code, and Data exist in
memory. Both instruction memory and data
memory accessed through cache (modified harvard
architecture) and a shared bus to memory (Von
Neumann).
Next Goal
Given a running program (a process), how do we
know what is going on (what function is executing,
what arguments were passed to where, where is
the stack and current stack frame, where is the
code and data, etc)?
Activity #1: Debugging
init(): 0x400000
printf(s, …): 0x4002B4 CPU:
vnorm(a,b): 0x40107C $pc=0x004003C0
main(a,b): 0x4010A0 0x00000000
$sp=0x7FFFFFAC
pi: 0x10000000 0x0040010c
str1: 0x10000004 $ra=0x00401090
0x7FFFFFF4
0x00000000
What func is running?
0x00000000
Who called it? 0x00000000
0x00000000
Has it called anything?
0x004010c4
Will it? 0x7FFFFFDC
Args? 0x00000000
0x00000000
Stack depth? 0x00000015
Call trace? 0x7FFFFFB0 0x10000004
0x00401090
Compilers and Assemblers
Next Goal
How do we compile a program from source to
assembly to machine object code?
Big Picture
Compiler output is assembly files
# Link
[csug01] mipsel-linux-gcc –o add1To100 add1To100.o
${LINKFLAGS}
# -nostartfiles –nodefaultlibs
# -static -mno-xgot -mno-embedded-pic
-mno-abicalls -G 0 -DMIPS -Wall
# Load
[csug01] simulate add1To100
Sum 1 to 100 is 5050
MIPS program exits with status 0 (approx. 2007
instructions in 143000 nsec at 14.14034 MHz)
Globals and Locals
Variables Visibility Lifetime Location
Function-Local
Global
Dynamic
int n = 100;
int main (int argc, char* argv[ ]) {
int i, m = n, sum = 0, *A = malloc(4 * m);
for (i = 1; i <= m; i++) { sum += i; A[i] = sum; }
printf ("Sum 1 to %d is %d\n", n, sum);
}
Globals and Locals
Variables Visibility Lifetime Location
Function-Local w/in func func stack
i, m, sum invocation
Global whole prgm prgm
.data
n, str execution
Dynamic A Anywhere that b/w malloc heap
C Pointers can be trouble has a ptr and free
Example #2: Review of Program Layout
calc.c
vector* v = malloc(8);
v->x = prompt(“enter x”); system reserved
v->y = prompt(“enter y”);
int c = pi + tnorm(v);
print(“result %d”, c); stack
math.c
int tnorm(vector* v) {
return abs(v->x)+abs(v->y);
}
dynamic data (heap)
lib3410.o
global variable: pi static data
entry point: prompt
entry point: print code (text)
entry point: malloc
system reserved
Assembler
calc.c calc.s calc.o
executable
math.c math.s math.o program
C source calc.exe
files io.s io.o exists on
disk
assembly
files libc.o loader
Compiler
libm.o
Executing
obj files in
Assembler
linker Memory
process
Next Goal
How do we understand the machine object code
that an assembler creates?
Big Picture
.o = Linux
math.c math.s math.o .obj Windows
Data Segment
• static data (local/global vars, strings, constants)
Debugging Information
• line number code address map, etc.
Symbol Table
• External (exported) references
• Unresolved (imported) references
Example
math.c
int pi = 3;
int e = 2;
static int randomval = 7;
int square(int x) { … }
static int is_prime(int x) { … }
int pick_prime() { … }
int pick_random() {
return randomval;
}
Objdump disassembly
csug01 ~$ mipsel-linux-objdump --disassemble math.o
math.o: file format elf32-tradlittlemips
Disassembly of section .text:
00000000 <pick_random>:
0: 27bdfff8 addiu sp,sp,-8
4: afbe0000 sw s8,0(sp)
8: 03a0f021 move s8,sp
c: 3c020000 lui v0,0x0
10: 8c420008 lw v0,8(v0)
14: 03c0e821 move sp,s8
18: 8fbe0000 lw s8,0(sp)
1c: 27bd0008 addiu sp,sp,8
20: 03e00008 jr ra
24: 00000000 nop
00000028 <square>:
28: 27bdfff8 addiu sp,sp,-8
2c: afbe0000 sw s8,0(sp)
30: 03a0f021 move s8,sp
34: afc40008 sw a0,8(s8)
Objdump symbols
csug01 ~$ mipsel-linux-objdump --syms math.o
math.o: file format elf32-tradlittlemips
SYMBOL TABLE:
00000000 l df *ABS* 00000000 math.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .mdebug.abi32 00000000 .mdebug.abi32
00000008 l O .data 00000004 randomval
00000060 l F .text 00000028 is_prime
00000000 l d .rodata 00000000 .rodata
00000000 l d .comment 00000000 .comment
00000000 g O .data 00000004 pi
00000004 g O .data 00000004 e
00000000 g F .text 00000028 pick_random
00000028 g F .text 00000038 square
00000088 g F .text 0000004c pick_prime
00000000 *UND* 00000000 username
00000000 *UND* 00000000 printf
Separate Compilation
Q: Why separate compile/assemble and linking steps?
A: Can recompile one object, then just relink.
Takeaway
We need a calling convention to coordinate use of
registers and memory. Registers exist in the Register
File. Stack, Code, and Data exist in memory. Both
instruction memory and data memory accessed
through cache (modified harvard architecture) and a
shared bus to memory (Von Neumann).
libc.o
libm.o
Executing
in
linker Memory
Linkers
Linker combines object files into an executable file
• Relocate each object’s text and data segments
• Resolve as-yet-unresolved symbols
• Record top-level entry point in executable file
1b80050C
4C040000 3C040000
21047002 34040000
0C000000 ...
... 20 T square
Relocation info Symbol tbl
00 D pi
00 T main
*UND* printf
00 D uname
*UND* uname
*UND* printf
*UND* pi 28, JL, printf
40, JL, printf 30, LUI, uname
4C, LW/gp, pi 34, LA, uname
54, JL, square
printf.o
...
3C T printf
Linker Example
main.o math.o calc.exe
... ...
... 21032040
0C000000 21032040
0C000000 0C40023C
21035000 1b301402 1
1b80050C 1b301402 1
2 3C040000 3C041000
4C040000 34040004
21047002 34040000
... ...
0C000000 0C40023C
... 20 T square
21035000
00 D pi A 1b80050c 2
00 T main B
*UND* printf 4C048004
00 D uname 21047002
*UND* uname
*UND* printf 0C400020
*UND* pi 28, JL, printf ...
40, JL, printf 30, LUI, uname 10201000
34, LA, uname 21040330 3
4C, LW/gp, pi 22500102
54, JL, square ...
printf.o uname 00000003
pi 0077616B
... 3 Entry:0040 0100
3C T printf text:0040 0000
data:1000 0000
Object file
Header
• location of main entry point (if any)
Text Segment
• instructions
Data Segment
Object File