Home Linked Libraries
Post
Cancel

Linked Libraries

Linked Libraries and their Functions

Lets start with a simple Hello World

#include <stdio.h>

int main(void)
{
	printf("Hello, World!\n");
	return 0;
}

To compile and execute from the shell

1
2
3
$ gcc -g hello.c -o hello
$ ./hello
Hello, World!

Now we all know that

  • executing this program means the kernel loads this program, then executes in in the given context. But how is it able to do this?
  • printf is the function call that sends the string to the stdout. But we have included just the header stdio.h, then where is the actual implementation of printf?

For these and more, we rely on libraries that have been created already. To find out which libraries are linked to an executable, we use the ldd command.

1
2
3
4
$ ldd ./hello
	linux-vdso.so.1 (0x00007fffc7f24000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f259c820000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f259ca32000) 

Lets look at what each of these shared objects are doing one by one

  1. linux-vdso
  2. libc
  3. ld-linux-x86-64

And to help us, lets take a look at the strace output of the hello program

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
31
32
33
34
35
36
37
38
39
$ strace ./hello
execve("./hello", ["./hello"], 0x7fffe8d00b60 /* 21 vars */) = 0
brk(NULL)                               = 0x7fffdd8c3000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fffe60351d0) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=32952, ...}) = 0
mmap(NULL, 32952, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb6df9c7000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360q\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2029224, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb6dfa00000
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68
mmap(NULL, 2036952, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb6df7d0000
mprotect(0x7fb6df7f5000, 1847296, PROT_NONE) = 0
mmap(0x7fb6df7f5000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7fb6df7f5000
mmap(0x7fb6df96d000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7fb6df96d000
mmap(0x7fb6df9b8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fb6df9b8000
mmap(0x7fb6df9be000, 13528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb6df9be000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7fb6dfa01340) = 0
mprotect(0x7fb6df9b8000, 12288, PROT_READ) = 0
mprotect(0x7fb6dfa0b000, 4096, PROT_READ) = 0
mprotect(0x7fb6df9fd000, 4096, PROT_READ) = 0
munmap(0x7fb6df9c7000, 32952)           = 0
fstat(1, {st_mode=S_IFCHR|0660, st_rdev=makedev(0x4, 0x2), ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
brk(NULL)                               = 0x7fffdd8c3000
brk(0x7fffdd8e4000)                     = 0x7fffdd8e4000
write(1, "Hello, World!\n", 14Hello, World!
)         = 14
exit_group(0)                           = ?
+++ exited with 0 +++
This post is licensed under CC BY 4.0 by the author.