ar rcs libvector.a addvec.o multvec.o
gcc main.o libvector.a -o main
.text
section in memorymain-dyn
demo:
$ # Object files that will go into a shared library must be compiled with -fpic.
$ # gcc -shared builds a shared library.
$ make
gcc -Wall -fpic -c -o main.o main.c
gcc -Wall -fpic -c -o sum.o sum.c
gcc -shared -o libsum.so sum.o
gcc -o main-dyn main.o libsum.so
$ # Dynamic linker can't find our libsum shared library
$ ./main-dyn
./main-dyn: error while loading shared libraries: libsum.so: cannot open shared object file: No such file or directory
$ ldd main-dyn
linux-vdso.so.1 (0x00007ffc951cf000)
libsum.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f279d400000)
/lib64/ld-linux-x86-64.so.2 (0x00007f279d74f000)
$ # Shared library must either be registered on the system or in LD_LIBRARY_PATH
$ LD_LIBRARY_PATH=. ./main-dyn
sum=10
dlopen()
A shared library can be dynamically loaded and linked at runtime without
previously having linked to it. The main-dlopen
program dynamically links
against libsum.so
, finds the sum_array()
function, and calls it.
main-dlopen
demo:
$ # Note that we do not link against libsum.so
$ gcc -Wall main-dlopen.c
$ LD_LIBRARY_PATH=. ./a.out
sum=10
We will use mymalloc.c
, adapted from CSAPP Figure 7.22, to demonstrate a
powerful technique called “library interpositioning”. The dynamic linker in
Linux will load in shared objects specified in the LD_PRELOAD
environment
variable before all others. This feature can be used to override functions in
other shared objects.
cal
demo: Intercept malloc()
and free()
calls in the cal
program:
$ gcc -fpic -shared -o mm.so mymalloc.c && LD_PRELOAD=./mm.so cal
malloc wrapper called
free wrapper called
malloc wrapper called
malloc wrapper called
...
free wrapper called
malloc wrapper called
malloc wrapper called
April 2024
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
free wrapper called
Recall symbol resolution & relocation: we calculated PC-relative addresses to symbols once they were resolved at link time.
But how do we do that for references to symbols defined in a shared library? Here are some issues:
mmap()
’d as read-only and
we can’t apply the relocations.R_X86_64_64
) is
possible, but then the text segment needs to be writeable to apply
relocations, and thus it cannot be shared among processes.Global offset table (GOT) adds one level of indirection for global data. CSAPP Figure 7.18 demonstrates how PIC uses the GOT to reference global data from shared objects.
Procedure linkage table (PLT) & GOT together add two levels of indirection for global functions defined in shared objects. This is illustrated in CSAPP Figure 7.19:
jmp *GOT[j]
f
, writes GOT[j] = &f
, and then
jmp *GOT[j]
PLT & GOT demo:
objdump -d main-dyn
main()
executes call 1070 <sum_array@plt>
1070
: bnd jmp *0x2f45(%rip) # 3fc0 <sum_array@Base>
readelf -a main-dyn
:
.rela.plt
for GOT entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000003fc0 000300000007 R_X86_64_JUMP_SLO 0000000000000000 sum_array + 0
readelf -x .got main-dyn
0x3fc0
: 0x1030
Hex dump of section '.got':
NOTE: This section has relocations against it, but these have NOT been applied to this dump.
0x00003fa8 a83d0000 00000000 00000000 00000000 .=..............
0x00003fb8 00000000 00000000 30100000 00000000 ........0.......
0x00003fc8 40100000 00000000 50100000 00000000 @.......P.......
0x00003fd8 00000000 00000000 00000000 00000000 ................
0x00003fe8 00000000 00000000 00000000 00000000 ................
0x00003ff8 00000000 00000000 ........
objdump -d main-dyn
:
.plt
section:
0000000000001020 <.plt>:
1020: ff 35 8a 2f 00 00 push 0x2f8a(%rip) # 3fb0 <_GLOBAL_OFFSET_TABLE_+0x8>
1026: f2 ff 25 8b 2f 00 00 bnd jmp *0x2f8b(%rip) # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x10>
102d: 0f 1f 00 nopl (%rax)
1030: f3 0f 1e fa endbr64
1034: 68 00 00 00 00 push $0x0
1039: f2 e9 e1 ff ff ff bnd jmp 1020 <_init+0x20>
103f: 90 nop
PIE and static/dynamic linkage are orthogonal concepts. Running file
, ldd
,
and objdump
on the following four executables demonstrates this point:
main-dyn
: pie & dynamically linked with libcmain-no-pie
: no pie, but still dynamically linked with libcmain-static-pie
: pie with statically linked libcmain-static
: no pie & statically linked with libcLast updated: 2024-04-09