From ee15fc203cb3a2bc029d0d3f14daf3a648b38ebb Mon Sep 17 00:00:00 2001 From: FreeArtMan Date: Wed, 17 Aug 2022 14:10:46 +0100 Subject: Linking chapter --- md/notes/undefined_c/titles.md | 178 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 5 deletions(-) diff --git a/md/notes/undefined_c/titles.md b/md/notes/undefined_c/titles.md index 513b533..60e14a4 100644 --- a/md/notes/undefined_c/titles.md +++ b/md/notes/undefined_c/titles.md @@ -764,16 +764,182 @@ int main(void) { } ``` - -## Base usage +## Advanced topics ### Kernel module -### Write plugins +Linux kernel, macos kernel and *BSD's kernels written in C, +so there is possibility to write kernel modules in C for some of those. + +Example will not match some specific things to local distribution. + +```c + +``` -## Advanced cases +http://main.lv/writeup/kernel_hello_world.md ### Linking + +Linking is one of the most interesting parts of compiling of C code. When object file is created +it contains functions and variables that can be of different type. And linking tries to resolve +all of those. So there is possible to have fun with linking and content of object files. + + +First example is piece of C code that can be compiled to object file, but it will not able to +resolve to executable. +``` +gcc -c link_elf.c +``` +```c +int main() { + fun1(); + fun2(); +} +``` +So we can see that fun1 and fun2 are marked as undefined in object file. If we try compile it will not able to find those. +So lets create one more object file +``` +$ readelf -a link_elf.o + +Symbol table '.symtab' contains 6 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_elf.c + 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text + 3: 0000000000000000 31 FUNC GLOBAL DEFAULT 1 main + 4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fun1 + 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fun2 + +``` +__link_fun1.c__ +```c +void fun1() { + printf("Hello fun1\n"); +} +void fun2() { + printf("Hello fun2\n"); +} +``` + +So now we have object file with funtions that are defined. and we see that its now have undefine pritnf/puts function there. + +``` +readelf -a link_fun1.o +Symbol table '.symtab' contains 7 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun1.c + 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text + 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata + 4: 0000000000000000 22 FUNC GLOBAL DEFAULT 1 fun1 + 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts + 6: 0000000000000016 22 FUNC GLOBAL DEFAULT 1 fun2 + +``` + +we can merge both of those files together +```shell +gcc -o link_elf link_elf.o link_fun1.o +``` +The function in object files dont have any idea about input output types. That why anything can be linked that just match name +lets rewrite code like this + +```c +int fun1(int i) { + printf("Hello fun1\n"); +} +int fun2(int i) { + printf("Hello fun2\n"); +} +``` +And this links without issue. Theat this as 2 sets that are merge together only few thins know when linking things. +Return type, and function arguments arent exposed when object file is created. + +Functions can have aliases. + +__link_fun2.c__ +```c +static void fun2() { + printf("hello 2\n"); +} __attribute__ ((alias("fun1"))); +``` + +Now function is local. + +``` +Symbol table '.symtab' contains 6 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun2.c + 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text + 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata + 4: 0000000000000000 22 FUNC LOCAL DEFAULT 1 fun2 + 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts +``` + +Lets compile all object to executable. And the function fun2 isnt used in this case, + + + +``` +$ gcc link_fun1.o link_fun2.o link_elf.o -o link_elf +$ ./link_elf +Hello fun1 +Hello fun2 + +``` + + + +lets witch aliasing between 2 functions **fun2** + + +``` +link_fun1.o + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun1.c + 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text + 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata + 4: 000000000000001d 29 FUNC LOCAL DEFAULT 1 fun2 + 5: 0000000000000000 29 FUNC GLOBAL DEFAULT 1 fun1 + 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts + +link_fun2.o + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun2.c + 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text + 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata + 4: 0000000000000000 22 FUNC GLOBAL DEFAULT 1 fun2 + 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts + +``` + +``` +$ gcc link_fun1.o link_fun2.o link_elf.o -o link_elf +$ ./link_elf +Hello fun1 +hello 2 +``` + +So all of this plays role in linking object files. +There is more interesting utilit called ld its doing things on lower level then gcc. + +``` +$ ldd ./link_elf + linux-vdso.so.1 (0x00007ffd8f5d0000) + libc.so.6 => /usr/lib/libc.so.6 (0x00007f96c0e00000) + /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f96c10d2000) +``` + +We havent specified those options when we compiled executable, lets use **ld** for that. + +``` +ld -dynamic-linker /lib/ld-linux.so.2 link_elf.o link_fun1.o link_fun2.o -o link_elf +``` + + + ### Extern ### Attributes ### Creating shared library @@ -788,9 +954,10 @@ int main(void) { ### Canary ### Atomic ### Multithreading +### Write plugins -## Embedding +## Embedding C ### Embed in C++ ### Embed in Go @@ -816,6 +983,7 @@ int main(void) { ### SDL2 ### GTK ### OpenGL +### Shaders ### Generate image -- cgit v1.2.3