# [Record] How to build and use static library and dynamic library in linux ###### tags: `static library`,`dynamic library`, `.so`, `compile`, `link` [toc] ## Preface Here, we are going to demo how to build or create a static library and a dynamic library, and how to use them with our application. Asume we want to access a register by reading or writing it. First, we implement the library which includes a get and set function. The get function will read a value from a file, and the set function will set a value to the file. The value of a register is stored in a file. Second, we implement the application to call API from this library. Finally, we compile both the library and application and link them them together. ## Git repo https://github.com/anderson-tomas/demo_library ## Source code ### File tree The library is named regapi with a c file and a header as shown below. And the application is named main.c. ![](https://hackmd.io/_uploads/H1QnXYMfT.png) ### Library We declare a global and two functions which are get and set. ```c Tomas# cat regapi/include/regapi.h #ifndef __REGAPI_H__ #define __REGAPI_H__ #include <stdio.h> #include <stdlib.h> #define REG_FILE "reg.txt" int regget(); void regset(int x); #endif Tomas# cat cat regapi/src/regapi.c #include "regapi.h" int regget() { FILE *file = fopen(REG_FILE, "r"); // Open the file for writing char buffer[1024]; if (file == NULL) { perror("Error opening the file"); printf("Call %s to get the default reg value 666\n", __func__); return 1; } // Read the string from the file if (fgets(buffer, sizeof(buffer), file) != NULL) { printf("Call %s to get reg value %s\n", __func__, buffer); } // Close the file fclose(file); return atoi(buffer); } void regset(int val) { FILE *file = fopen(REG_FILE, "w"); // Open the file for writing if (file == NULL) { perror("Error opening the file"); return; } printf("Call %s to set reg value %d\n", __func__, val); // Write the string to the file fprintf(file, "%d", val); } ``` ### Application ```c Tomas# cat main.c #include <stdio.h> #include <stdlib.h> // Include for atoi #include <string.h> // Include for strcmp #include "regapi.h" int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s [get | set <value>]\n", argv[0]); return 1; } if (strcmp(argv[1], "get") == 0) { printf("get reg value: %d\n", regget()); } else if (strcmp(argv[1], "set") == 0) { if (argc < 3) { printf("Usage: %s set <value>\n", argv[0]); return 1; } int value = atoi(argv[2]); printf("set reg value to %d\n", value); regset(value); } else { printf("Invalid command. Usage: %s [get | set <value>]\n", argv[0]); return 1; } return 0; } ``` ## Static library 1. Compile the regapi.c to an object by gcc. ```shell Tomas# gcc -c regapi/src/regapi.c -Iregapi/include/ Tomas# ls -al regapi.o -rw-rw-r-- 1 tomas tomas 3088 十 22 19:53 regapi.o ``` ![](https://hackmd.io/_uploads/ByNraFzGT.png) 2. Create a static library and replace the object by ar. ```shell Tomas# ar rcs libregapi.a regapi.o Tomas# ls -al libregapi.a -rw-rw-r-- 1 tomas tomas 3242 十 22 19:55 libregapi.a ``` 3. Check symbols in library by nm ```shell Tomas# nm libregapi.a regapi.o: U atoi U fclose U fgets U fopen U fprintf 0000000000000091 r __func__.2837 0000000000000098 r __func__.2842 U _GLOBAL_OFFSET_TABLE_ U perror U printf 0000000000000000 T regget 00000000000000e3 T regset U __stack_chk_fail ``` :::spoiler ar --h Usage: ar [emulation options] [-]{dmpqrstx}[abcDfilMNoOPsSTuvV] [--plugin <name>] [member-name] [count] archive-file file... ar -M [<mri-script] commands: d - delete file(s) from the archive m[ab] - move file(s) in the archive p - print file(s) found in the archive q[f] - quick append file(s) to the archive r[ab][f][u] - replace existing or insert new file(s) into the archive s - act as ranlib t[O][v] - display contents of the archive x[o] - extract file(s) from the archive command specific modifiers: [a] - put file(s) after [member-name] [b] - put file(s) before [member-name] (same as [i]) [D] - use zero for timestamps and uids/gids (default) [U] - use actual timestamps and uids/gids [N] - use instance [count] of name [f] - truncate inserted file names [P] - use full path names when matching [o] - preserve original dates [O] - display offsets of files in the archive [u] - only replace files that are newer than current archive contents generic modifiers: [c] - do not warn if the library had to be created [s] - create an archive index (cf. ranlib) [S] - do not build a symbol table [T] - make a thin archive [v] - be verbose [V] - display the version number @<file> - read options from <file> --target=BFDNAME - specify the target object format as BFDNAME --output=DIRNAME - specify the output directory for extraction operations optional: --plugin <p> - load the specified plugin emulation options: No emulation specific options ar: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 srec symbolsrec verilog tekhex binary ihex plugin Report bugs to <http://www.sourceware.org/bugzilla/> ::: ### Build the application and link it with a static library 1. Compile the application as hello and link it with libregapi.a ```shell Tomas# gcc main.c libregapi.a -o hello -Iregapi/include Tomas# ls -al hello -rwxrwxr-x 1 tomas tomas 17208 十 22 20:06 hello -rw-rw-r-- 1 tomas tomas 3242 十 22 19:55 libregapi.a -rw-rw-r-- 1 tomas tomas 741 十 22 19:35 main.c drwxrwxr-x 4 tomas tomas 4096 十 22 17:25 regapi -rw-rw-r-- 1 tomas tomas 3088 十 22 19:53 regapi.o -rw-rw-r-- 1 tomas tomas 1 十 22 20:07 reg.txt ``` ![](https://hackmd.io/_uploads/SJB-x5zGa.png) 2. Execute it ```shell Tomas# ./hello Usage: ./hello [get | set <value>] Tomas#./hello set 5 set reg value to 5 Call regset to set reg value 5 Tomas# ./hello get Call regget to get reg value 5 get reg value: 5 ``` 3. Check symbols by nm ```bash Tomas# nm hello 0000000000003d80 d __do_global_dtors_aux_fini_array_entry 0000000000004008 D __dso_handle 0000000000003d88 d _DYNAMIC 0000000000004010 D _edata 0000000000004018 B _end U fclose@@GLIBC_2.2.5 U fgets@@GLIBC_2.2.5 0000000000001548 T _fini U fopen@@GLIBC_2.2.5 U fprintf@@GLIBC_2.2.5 0000000000001240 t frame_dummy 0000000000003d78 d __frame_dummy_init_array_entry 00000000000022dc r __FRAME_END__ 0000000000002131 r __func__.2837 0000000000002138 r __func__.2842 0000000000003f78 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 0000000000002140 r __GNU_EH_FRAME_HDR 0000000000001000 t _init 0000000000003d80 d __init_array_end 0000000000003d78 d __init_array_start 0000000000002000 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000001540 T __libc_csu_fini 00000000000014d0 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 0000000000001249 T main U perror@@GLIBC_2.2.5 U printf@@GLIBC_2.2.5 000000000000136e T regget 00000000000011c0 t register_tm_clones 0000000000001451 T regset U __stack_chk_fail@@GLIBC_2.4 0000000000001160 T _start U strcmp@@GLIBC_2.2.5 0000000000004010 D __TMC_END__ ``` :::spoiler ```shell Tomas# readelf -a libregapi.a File: libregapi.a(regapi.o) ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: REL (Relocatable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 2192 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 0 (bytes) Number of program headers: 0 Size of section headers: 64 (bytes) Number of section headers: 14 Section header string table index: 13 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000158 0000000000000000 AX 0 0 1 [ 2] .rela.text RELA 0000000000000000 00000590 0000000000000258 0000000000000018 I 11 1 8 [ 3] .data PROGBITS 0000000000000000 00000198 0000000000000000 0000000000000000 WA 0 0 1 [ 4] .bss NOBITS 0000000000000000 00000198 0000000000000000 0000000000000000 WA 0 0 1 [ 5] .rodata PROGBITS 0000000000000000 00000198 [ 8] .note.gnu.propert NOTE 0000000000000000 00000268 0000000000000020 0000000000000000 A 0 0 8 [ 9] .eh_frame PROGBITS 0000000000000000 00000288 0000000000000058 0000000000000000 A 0 0 8 [10] .rela.eh_frame RELA 0000000000000000 000007e8 0000000000000030 0000000000000018 I 11 9 8 [11] .symtab SYMTAB 0000000000000000 000002e0 0000000000000228 0000000000000018 12 12 8 [12] .strtab STRTAB 0000000000000000 00000508 0000000000000082 0000000000000000 0 0 1 [13] .shstrtab STRTAB 0000000000000000 00000818 0000000000000074 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. There are no program headers in this file. There is no dynamic section in this file. Relocation section '.rela.text' at offset 0x590 contains 25 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000021 000500000002 R_X86_64_PC32 0000000000000000 .rodata - 4 000000000028 000500000002 R_X86_64_PC32 0000000000000000 .rodata - 2 00000000002d 000e00000004 R_X86_64_PLT32 0000000000000000 fopen - 4 000000000045 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 6 00000000004a 000f00000004 R_X86_64_PLT32 0000000000000000 perror - 4 000000000051 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 8d 000000000058 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 24 000000000062 001000000004 R_X86_64_PLT32 0000000000000000 printf - 4 000000000084 001100000004 R_X86_64_PLT32 0000000000000000 fgets - 4 00000000009a 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 8d 0000000000a1 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 4e 0000000000ab 001000000004 R_X86_64_PLT32 0000000000000000 printf - 4 0000000000ba 001200000004 R_X86_64_PLT32 0000000000000000 fclose - 4 0000000000c9 001300000004 R_X86_64_PLT32 0000000000000000 atoi - 4 0000000000dd 001400000004 R_X86_64_PLT32 0000000000000000 __stack_chk_fail - 4 0000000000f5 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 6b 0000000000fc 000500000002 R_X86_64_PC32 0000000000000000 .rodata - 2 000000000101 000e00000004 R_X86_64_PLT32 0000000000000000 fopen - 4 000000000113 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 6 000000000118 000f00000004 R_X86_64_PLT32 0000000000000000 perror - 4 000000000126 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 94 00000000012d 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 6d 000000000137 001000000004 R_X86_64_PLT32 0000000000000000 printf - 4 000000000145 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 8a 000000000152 001600000004 R_X86_64_PLT32 0000000000000000 fprintf - 4 Relocation section '.rela.eh_frame' at offset 0x7e8 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0 000000000040 000200000002 R_X86_64_PC32 0000000000000000 .text + e3 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.symtab' contains 23 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS regapi.c 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 5 6: 0000000000000091 7 OBJECT LOCAL DEFAULT 5 __func__.2837 7: 0000000000000098 7 OBJECT LOCAL DEFAULT 5 __func__.2842 8: 0000000000000000 0 SECTION LOCAL DEFAULT 7 9: 0000000000000000 0 SECTION LOCAL DEFAULT 8 10: 0000000000000000 0 SECTION LOCAL DEFAULT 9 11: 0000000000000000 0 SECTION LOCAL DEFAULT 6 12: 0000000000000000 227 FUNC GLOBAL DEFAULT 1 regget 13: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_ 14: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fopen 15: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND perror 16: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf 17: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fgets 18: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fclose 19: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND atoi 20: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND __stack_chk_fail 21: 00000000000000e3 117 FUNC GLOBAL DEFAULT 1 regset 22: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fprintf No version information found in this file. Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK ::: :::spoiler Tomas# readelf -a hello ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x1160 Start of program headers: 64 (bytes into file) Start of section headers: 15224 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 13 Size of section headers: 64 (bytes) Number of section headers: 31 Section header string table index: 30 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000000318 00000318 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.gnu.propert NOTE 0000000000000338 00000338 0000000000000020 0000000000000000 A 0 0 8 [ 3] .note.gnu.build-i NOTE 0000000000000358 00000358 0000000000000024 0000000000000000 A 0 0 4 000000000000000d 0000000000000000 AX 0 0 4 [18] .rodata PROGBITS 0000000000002000 00002000 000000000000013f 0000000000000000 A 0 0 8 [19] .eh_frame_hdr PROGBITS 0000000000002140 00002140 0000000000000054 0000000000000000 A 0 0 4 [20] .eh_frame PROGBITS 0000000000002198 00002198 0000000000000148 0000000000000000 A 0 0 8 [21] .init_array INIT_ARRAY 0000000000003d78 00002d78 0000000000000008 0000000000000008 WA 0 0 8 [22] .fini_array FINI_ARRAY 0000000000003d80 00002d80 0000000000000008 0000000000000008 WA 0 0 8 [23] .dynamic DYNAMIC 0000000000003d88 00002d88 00000000000001f0 0000000000000010 WA 7 0 8 [24] .got PROGBITS 0000000000003f78 00002f78 0000000000000088 0000000000000008 WA 0 0 8 [25] .data PROGBITS 0000000000004000 00003000 0000000000000010 0000000000000000 WA 0 0 8 [26] .bss NOBITS 0000000000004010 00003010 0000000000000008 0000000000000000 WA 0 0 1 [27] .comment PROGBITS 0000000000000000 00003010 000000000000002b 0000000000000001 MS 0 0 1 [28] .symtab SYMTAB 0000000000000000 00003040 0000000000000750 0000000000000018 29 49 8 [29] .strtab STRTAB 0000000000000000 00003790 00000000000002c8 0000000000000000 0 0 1 [30] .shstrtab STRTAB 0000000000000000 00003a58 000000000000011a 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr on_r .rela.dyn .rela.plt 03 .init .plt .plt.got .plt.sec .text .fini 04 .rodata .eh_frame_hdr .eh_frame 05 .init_array .fini_array .dynamic .got .data .bss 06 .dynamic 07 .note.gnu.property 08 .note.gnu.build-id .note.ABI-tag 09 .note.gnu.property 10 .eh_frame_hdr 11 12 .init_array .fini_array .dynamic .got Dynamic section at offset 0x2d88 contains 27 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x1000 0x000000000000000d (FINI) 0x1548 0x0000000000000019 (INIT_ARRAY) 0x3d78 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x3d80 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x3a0 0x0000000000000005 (STRTAB) 0x530 0x0000000000000006 (SYMTAB) 0x3c8 0x000000000000000a (STRSZ) 198 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000015 (DEBUG) 0x0 0x0000000000000003 (PLTGOT) 0x3f78 0x0000000000000002 (PLTRELSZ) 216 (bytes) 0x0000000000000014 (PLTREL) RELA 0x0000000000000017 (JMPREL) 0x708 0x0000000000000007 (RELA) 0x648 0x0000000000000008 (RELASZ) 192 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000000000001e (FLAGS) BIND_NOW 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE 0x000000006ffffffe (VERNEED) 0x618 Relocation section '.rela.dyn' at offset 0x648 contains 8 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003d78 000000000008 R_X86_64_RELATIVE 1240 000000003d80 000000000008 R_X86_64_RELATIVE 1200 000000004008 000000000008 R_X86_64_RELATIVE 4008 000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0 000000003fe0 000500000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 000000003fe8 000900000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 000000003ff0 000d00000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0 000000003ff8 000e00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0 Relocation section '.rela.plt' at offset 0x708 contains 9 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003f90 000200000007 R_X86_64_JUMP_SLO 0000000000000000 fclose@GLIBC_2.2.5 + 0 000000003f98 000300000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail@GLIBC_2.4 + 0 000000003fa0 000400000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0 000000003fa8 000600000007 R_X86_64_JUMP_SLO 0000000000000000 fgets@GLIBC_2.2.5 + 0 000000003fb0 000700000007 R_X86_64_JUMP_SLO 0000000000000000 strcmp@GLIBC_2.2.5 + 0 000000003fb8 000800000007 R_X86_64_JUMP_SLO 0000000000000000 fprintf@GLIBC_2.2.5 + 0 000000003fc0 000a00000007 R_X86_64_JUMP_SLO 0000000000000000 fopen@GLIBC_2.2.5 + 0 000000003fc8 000b00000007 R_X86_64_JUMP_SLO 0000000000000000 perror@GLIBC_2.2.5 + 0 000000003fd0 000c00000007 R_X86_64_JUMP_SLO 0000000000000000 atoi@GLIBC_2.2.5 + 0 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.dynsym' contains 15 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fclose@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3) 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fgets@GLIBC_2.2.5 (2) 7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strcmp@GLIBC_2.2.5 (2) 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fprintf@GLIBC_2.2.5 (2) 9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 4: 000000000000037c 0 SECTION LOCAL DEFAULT 4 5: 00000000000003a0 0 SECTION LOCAL DEFAULT 5 6: 00000000000003c8 0 SECTION LOCAL DEFAULT 6 7: 0000000000000530 0 SECTION LOCAL DEFAULT 7 8: 00000000000005f6 0 SECTION LOCAL DEFAULT 8 9: 0000000000000618 0 SECTION LOCAL DEFAULT 9 10: 0000000000000648 0 SECTION LOCAL DEFAULT 10 11: 0000000000000708 0 SECTION LOCAL DEFAULT 11 12: 0000000000001000 0 SECTION LOCAL DEFAULT 12 13: 0000000000001020 0 SECTION LOCAL DEFAULT 13 14: 00000000000010c0 0 SECTION LOCAL DEFAULT 14 15: 00000000000010d0 0 SECTION LOCAL DEFAULT 15 16: 0000000000001160 0 SECTION LOCAL DEFAULT 16 17: 0000000000001548 0 SECTION LOCAL DEFAULT 17 18: 0000000000002000 0 SECTION LOCAL DEFAULT 18 19: 0000000000002140 0 SECTION LOCAL DEFAULT 19 20: 0000000000002198 0 SECTION LOCAL DEFAULT 20 21: 0000000000003d78 0 SECTION LOCAL DEFAULT 21 22: 0000000000003d80 0 SECTION LOCAL DEFAULT 22 23: 0000000000003d88 0 SECTION LOCAL DEFAULT 23 24: 0000000000003f78 0 SECTION LOCAL DEFAULT 24 25: 0000000000004000 0 SECTION LOCAL DEFAULT 25 26: 0000000000004010 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 28: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 29: 0000000000001190 0 FUNC LOCAL DEFAULT 16 deregister_tm_clones 30: 00000000000011c0 0 FUNC LOCAL DEFAULT 16 register_tm_clones 31: 0000000000001200 0 FUNC LOCAL DEFAULT 16 __do_global_dtors_aux 32: 0000000000004010 1 OBJECT LOCAL DEFAULT 26 completed.8061 33: 0000000000003d80 0 OBJECT LOCAL DEFAULT 22 __do_global_dtors_aux_fin 34: 0000000000001240 0 FUNC LOCAL DEFAULT 16 frame_dummy 35: 0000000000003d78 0 OBJECT LOCAL DEFAULT 21 __frame_dummy_init_array_ 36: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS regapi.c 38: 0000000000002131 7 OBJECT LOCAL DEFAULT 18 __func__.2837 39: 0000000000002138 7 OBJECT LOCAL DEFAULT 18 __func__.2842 40: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 54: 0000000000001548 0 FUNC GLOBAL HIDDEN 17 _fini 55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@@GLIBC_2 56: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.2.5 57: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 58: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fgets@@GLIBC_2.2.5 59: 0000000000004000 0 NOTYPE GLOBAL DEFAULT 25 __data_start 60: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strcmp@@GLIBC_2.2.5 61: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fprintf@@GLIBC_2.2.5 62: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 63: 0000000000004008 0 OBJECT GLOBAL HIDDEN 25 __dso_handle 64: 0000000000002000 4 OBJECT GLOBAL DEFAULT 18 _IO_stdin_used 65: 00000000000014d0 101 FUNC GLOBAL DEFAULT 16 __libc_csu_init 66: 0000000000004018 0 NOTYPE GLOBAL DEFAULT 26 _end 67: 0000000000001160 47 FUNC GLOBAL DEFAULT 16 _start 68: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 69: 0000000000001249 293 FUNC GLOBAL DEFAULT 16 main 70: 0000000000001451 117 FUNC GLOBAL DEFAULT 16 regset 71: 000000000000136e 227 FUNC GLOBAL DEFAULT 16 regget 72: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fopen@@GLIBC_2.2.5 73: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@@GLIBC_2.2.5 74: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atoi@@GLIBC_2.2.5 75: 0000000000004010 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ 76: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 77: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2 Histogram for `.gnu.hash' bucket list length (total of 2 buckets): Length Number % of total Coverage 0 1 ( 50.0%) 1 1 ( 50.0%) 100.0% Version symbols section '.gnu.version' contains 15 entries: Addr: 0x00000000000005f6 Offset: 0x0005f6 Link: 6 (.dynsym) 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.2.5) 3 (GLIBC_2.4) 004: 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 008: 2 (GLIBC_2.2.5) 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 00c: 2 (GLIBC_2.2.5) 0 (*local*) 2 (GLIBC_2.2.5) Version needs section '.gnu.version_r' contains 1 entry: Addr: 0x0000000000000618 Offset: 0x000618 Link: 7 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 2 0x0010: Name: GLIBC_2.4 Flags: none Version: 3 0x0020: Name: GLIBC_2.2.5 Flags: none Version: 2 Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK Displaying notes found in: .note.gnu.build-id Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: 353ed780fae95a5ba1e16889cafbc321fe205f40 Displaying notes found in: .note.ABI-tag Owner Data size Description GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) OS: Linux, ABI: 3.2.0 ::: ### Write the Makefile and build it ![](https://hackmd.io/_uploads/SkGGt9GGp.png) ```shell Tomas # ls -al -rw-rw-r-- 1 tomas tomas 741 十 22 19:35 main.c -rw-rw-r-- 1 tomas tomas 603 十 22 20:44 Makefile drwxrwxr-x 4 tomas tomas 4096 十 22 17:25 regapi Tomas# cat Makefile # Compiler and flags CC = gcc CFLAGS = -Wall -Wextra -Iregapi/include LDFLAGS = -L. -lregapi # Source files and objects SRC = main.c LIB_SRC = regapi/src/regapi.c OBJ = $(SRC:.c=.o) regapi.o # Target executable TARGET = hello .PHONY: all clean all: $(TARGET) # Build the static library libregapi.a: regapi.o ar rcs $@ $^ # Compile the library source file regapi.o: $(LIB_SRC) $(CC) $(CFLAGS) -c $< # Build the main executable $(TARGET): $(OBJ) libregapi.a $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) # Compile source files %.o: %.c $(CC) $(CFLAGS) -c $< clean: rm -f $(TARGET) $(OBJ) libregapi.a ``` --- ## Dynamic library 1. Compile the regapi.c to an object by gcc. ```shell Tomas# gcc -fPIC -c regapi/src/regapi.c -Iregapi/include Tomas# ls -al regapi.o -rw-rw-r-- 1 tomas tomas 3088 十 22 20:48 regapi.o ``` 2. Create the shared library ```shell Tomas# gcc -s -shared -o libregapi.so regapi.o Tomas# ls -al -rwxrwxr-x 1 tomas tomas 14472 十 22 20:49 libregapi.so -rw-rw-r-- 1 tomas tomas 741 十 22 19:35 main.c -rw-rw-r-- 1 tomas tomas 603 十 22 20:44 Makefile drwxrwxr-x 4 tomas tomas 4096 十 22 17:25 regapi -rw-rw-r-- 1 tomas tomas 3088 十 22 20:48 regapi.o ``` ![](https://hackmd.io/_uploads/ry5Kccff6.png) 3. Check the library dependency by ldd ```shell Tomas# ldd libregapi.so linux-vdso.so.1 (0x00007ffd05254000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4652994000) /lib64/ld-linux-x86-64.so.2 (0x00007f4652b9f000) ``` ### Build the application and link it with shared library ``` Tomas# gcc -o hello main.c -Wl,-rpath=. -L. -Iregapi/include -lregapi Tomas# ls -al -rwxrwxr-x 1 tomas tomas 16848 十 22 20:56 hello -rwxrwxr-x 1 tomas tomas 14472 十 22 20:53 libregapi.so -rw-rw-r-- 1 tomas tomas 741 十 22 19:35 main.c -rw-rw-r-- 1 tomas tomas 603 十 22 20:44 Makefile drwxrwxr-x 4 tomas tomas 4096 十 22 17:25 regapi ``` Execute it. ```shell Tomas# ./hello set 88 set reg value to 88 Call regset to set reg value 88 Tomas# ./hello get Call regget to get reg value 88 reg value: 88 ``` Check the symbols. ``` Tomas# nm hello U atoi@@GLIBC_2.2.5 0000000000004010 B __bss_start 0000000000004010 b completed.8061 w __cxa_finalize@@GLIBC_2.2.5 0000000000004000 D __data_start 0000000000004000 W data_start 0000000000001110 t deregister_tm_clones 0000000000001180 t __do_global_dtors_aux 0000000000003d80 d __do_global_dtors_aux_fini_array_entry 0000000000004008 D __dso_handle 0000000000003d88 d _DYNAMIC 0000000000004010 D _edata 0000000000004018 B _end 0000000000001368 T _fini 00000000000011c0 t frame_dummy 0000000000003d78 d __frame_dummy_init_array_entry 00000000000021ec r __FRAME_END__ 0000000000003f98 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 00000000000020a0 r __GNU_EH_FRAME_HDR 0000000000001000 t _init 0000000000003d80 d __init_array_end 0000000000003d78 d __init_array_start 0000000000002000 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000001360 T __libc_csu_fini 00000000000012f0 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 00000000000011c9 T main U printf@@GLIBC_2.2.5 U regget 0000000000001140 t register_tm_clones U regset 00000000000010e0 T _start U strcmp@@GLIBC_2.2.5 0000000000004010 D __TMC_END__ ``` :::spoiler ```shell Tomas# readelf -a libregapi.so ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x1140 Start of program headers: 64 (bytes into file) Start of section headers: 12680 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 11 Size of section headers: 64 (bytes) Number of section headers: 28 Section header string table index: 27 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .note.gnu.propert NOTE 00000000000002a8 000002a8 0000000000000020 0000000000000000 A 0 0 8 [ 2] .note.gnu.build-i NOTE 00000000000002c8 000002c8 0000000000000024 0000000000000000 A 0 0 4 [ 3] .gnu.hash GNU_HASH 00000000000002f0 000002f0 0000000000000028 0000000000000000 A 4 0 8 [15] .fini PROGBITS 0000000000001354 00001354 000000000000000d 0000000000000000 AX 0 0 4 [16] .rodata PROGBITS 0000000000002000 00002000 000000000000009f 0000000000000000 A 0 0 8 [17] .eh_frame_hdr PROGBITS 00000000000020a0 000020a0 0000000000000034 0000000000000000 A 0 0 4 [18] .eh_frame PROGBITS 00000000000020d8 000020d8 00000000000000b4 0000000000000000 A 0 0 8 [19] .init_array INIT_ARRAY 0000000000003e10 00002e10 0000000000000008 0000000000000008 WA 0 0 8 [20] .fini_array FINI_ARRAY 0000000000003e18 00002e18 0000000000000008 0000000000000008 WA 0 0 8 [21] .dynamic DYNAMIC 0000000000003e20 00002e20 00000000000001c0 0000000000000010 WA 5 0 8 [22] .got PROGBITS 0000000000003fe0 00002fe0 0000000000000020 0000000000000008 WA 0 0 8 [23] .got.plt PROGBITS 0000000000004000 00003000 0000000000000058 0000000000000008 WA 0 0 8 [24] .data PROGBITS 0000000000004058 00003058 0000000000000008 0000000000000000 WA 0 0 8 [25] .bss NOBITS 0000000000004060 00003060 0000000000000008 0000000000000000 WA 0 0 1 [26] .comment PROGBITS 0000000000000000 00003060 000000000000002b 0000000000000001 MS 0 0 1 [27] .shstrtab STRTAB 0000000000000000 0000308b 00000000000000fd 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x00000000000006f8 0x00000000000006f8 R 0x1000 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000361 0x0000000000000361 R E 0x1000 LOAD 0x0000000000002000 0x00000000000020 Dynamic section at offset 0x2e20 contains 24 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x1000 0x000000000000000d (FINI) 0x1354 0x0000000000000019 (INIT_ARRAY) 0x3e10 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x3e18 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x2f0 0x0000000000000005 (STRTAB) 0x480 0x0000000000000006 (SYMTAB) 0x318 0x000000000000000a (STRSZ) 187 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000003 (PLTGOT) 0x4000 0x0000000000000002 (PLTRELSZ) 192 (bytes) 0x0000000000000014 (PLTREL) RELA 0x0000000000000017 (JMPREL) 0x638 0x0000000000000007 (RELA) 0x590 0x0000000000000008 (RELASZ) 168 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000006ffffffe (VERNEED) 0x560 0x000000006fffffff (VERNEEDNUM) 1 0x000000006ffffff0 (VERSYM) 0x53c 0x000000006ffffff9 (RELACOUNT) 3 0x0000000000000000 (NULL) 0x0 Relocation section '.rela.dyn' at offset 0x590 contains 7 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003e10 000000000008 R_X86_64_RELATIVE 11f0 000000003e18 000000000008 R_X86_64_RELATIVE 11b0 000000004058 000000000008 R_X86_64_RELATIVE 4058 000000003fe0 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0 000000003fe8 000700000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 000000003ff0 000b00000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0 000000003ff8 000c00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0 Relocation section '.rela.plt' at offset 0x638 contains 8 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000004018 000200000007 R_X86_64_JUMP_SLO 0000000000000000 fclose@GLIBC_2.2.5 + 0 000000004020 000300000007 R_X86_6 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.dynsym' contains 15 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fclose@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3) 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fgets@GLIBC_2.2.5 (2) 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fprintf@GLIBC_2.2.5 (2) 7: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fopen@GLIBC_2.2.5 (2) 9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.2.5 (2) 10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atoi@GLIBC_2.2.5 (2) 11: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 12: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2) 13: 00000000000012dc 117 FUNC GLOBAL DEFAULT 14 regset 14: 00000000000011f9 227 FUNC GLOBAL DEFAULT 14 regget Histogram for `.gnu.hash' bucket list length (total of 2 buckets): Length Number % of total Coverage 0 1 ( 50.0%) 1 0 ( 0.0%) 0.0% 2 1 ( 50.0%) 100.0% Version symbols section '.gnu.version' contains 15 entries: Addr: 0x000000000000053c Offset: 0x00053c Link: 4 (.dynsym) 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.2.5) 3 (GLIBC_2.4) 004: 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*) 008: 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*) 00c: 2 (GLIBC_2.2.5) 1 (*global*) 1 (*global*) Version needs section '.gnu.version_r' contains 1 entry: Addr: 0x0000000000000560 Offset: 0x000560 Link: 5 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 2 0x0010: Name: GLIBC_2.4 Flags: none Version: 3 0x0020: Name: GLIBC_2.2.5 Flags: none Version: 2 Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK Displaying notes found in: .note.gnu.build-id Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: c172a62c7d23fe26fa3127ba7d4ceaeb6fce920e ``` ::: :::spoiler Tomas# readelf -a hello ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x10e0 Start of program headers: 64 (bytes into file) Start of section headers: 14864 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 13 Size of section headers: 64 (bytes) Number of section headers: 31 Section header string table index: 30 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000000318 00000318 0000000000000016 0000000000000002 A 6 0 2 [ 9] .gnu.version_r VERNEED 0000000000000598 00000598 0000000000000020 0000000000000000 A 7 1 8 [10] .rela.dyn RELA 00000000000005b8 000005b8 00000000000000c0 0000000000000018 A 6 0 8 [11] .rela.plt RELA 0000000000000678 00000678 0000000000000078 0000000000000018 AI 6 24 8 [12] .init PROGBITS 0000000000001000 00001000 000000000000001b 0000000000000000 AX 0 0 4 [13] .plt PROGBITS 0000000000001020 00001020 0000000000000060 0000000000000010 AX 0 0 16 [14] .plt.got PROGBITS 0000000000001080 00001080 0000000000000010 0000000000000010 AX 0 0 16 [15] .plt.sec PROGBITS 0000000000001090 00001090 0000000000000050 0000000000000010 AX 0 0 16 [16] .text PROGBITS 00000000000010e0 000010e0 0000000000000285 0000000000000000 AX 0 0 16 [17] .fini PROGBITS 0000000000001368 00001368 000000000000000d 0000000000000000 AX 0 0 4 [18] .rodata PROGBITS 0000000000002000 00002000 00000000000000a0 0000000000000000 A 0 0 8 [19] .eh_frame_hdr PROGBITS 00000000000020a0 000020a0 0000000000000044 0000000000000000 A 0 0 4 [20] .eh_frame PROGBITS 00000000000020e8 000020e8 0000000000000108 0000000000000000 A 0 0 8 [21] .init_array INIT_ARRAY 0000000000003d78 00002d78 0000000000000008 0000000000000008 WA 0 0 8 [22] .fini_array FINI_ARRAY 0000000000003d80 00002d80 0000000000000008 0000000000000008 WA 0 0 8 [23] .dynamic DYNAMIC 0000000000003d88 00002d88 0000000000000210 0000000000000010 WA 7 0 8 [24] .got PROGBITS 0000000000003f98 00002f98 0000000000000068 0000000000000008 WA 0 0 8 [25] .data PROGBITS 0000000000004000 00003000 0000000000000010 0000000000000000 WA 0 0 8 [26] .bss NOBITS 0000000000004010 00003010 0000000000000008 0000000000000000 WA 0 0 1 [27] .comment PROGBITS 0000000000000000 00003010 000000000000002b 0000000000000001 MS 0 0 1 [28] .symtab SYMTAB 0000000000000000 00003040 0000000000000678 0000000000000018 29 46 8 0x0000000000000044 0x0000000000000044 R 0x4 GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338 0x0000000000000020 0x0000000000000020 R 0x8 GNU_EH_FRAME 0x00000000000020a0 0x00000000000020a0 0x00000000000020a0 0x0000000000000044 0x0000000000000044 R 0x4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 GNU_RELRO 0x0000000000002d78 0x0000000000003d78 0x0000000000003d78 0x0000000000000288 0x0000000000000288 R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 03 .init .plt .plt.got .plt.sec .text .fini 04 .rodata .eh_frame_hdr .eh_frame 05 .init_array .fini_array .dynamic .got .data .bss 06 .dynamic 07 .note.gnu.property 08 .note.gnu.build-id .note.ABI-tag 09 .note.gnu.property 10 .eh_frame_hdr 11 12 .init_array .fini_array .dynamic .got Dynamic section at offset 0x2d88 contains 29 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libregapi.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000001d (RUNPATH) Library runpath: [.] 0x000000000000000c (INIT) 0x1000 0x000000000000000d (FINI) 0x1368 0x0000000000000019 (INIT_ARRAY) 0x3d78 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x3d80 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x3a0 0x0000000000000005 (STRTAB) 0x4d0 0x0000000000000006 (SYMTAB) 0x3c8 0x000000000000000a (STRSZ) 173 (bytes) 0x000000006ffffff0 (VERSYM) 0x57e 0x000000006ffffff9 (RELACOUNT) 3 0x0000000000000000 (NULL) 0x0 Relocation section '.rela.dyn' at offset 0x5b8 contains 8 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003d78 000000000008 R_X86_64_RELATIVE 11c0 000000003d80 000000000008 R_X86_64_RELATIVE 1180 000000004008 000000000008 R_X86_64_RELATIVE 4008 000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0 000000003fe0 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 000000003fe8 000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 000000003ff0 000900000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0 000000003ff8 000a00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0 Relocation section '.rela.plt' at offset 0x678 contains 5 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003fb0 000200000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0 000000003fb8 000400000007 R_X86_64_JUMP_SLO 0000000000000000 strcmp@GLIBC_2.2.5 + 0 000000003fc0 000600000007 R_X86_64_JUMP_SLO 0000000000000000 regset + 0 000000003fc8 000700000007 R_X86_64_JUMP_SLO 0000000000000000 regget + 0 000000003fd0 000800000007 R_X86_64_JUMP_SLO 0000000000000000 atoi@GLIBC_2.2.5 + 0 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.dynsym' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strcmp@GLIBC_2.2.5 (2) 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND regset 7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND regget 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atoi@GLIBC_2.2.5 (2) 9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 10: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 69 entries: Num: Value Size Type Bind Vis Ndx Name 10: 00000000000005b8 0 SECTION LOCAL DEFAULT 10 11: 0000000000000678 0 SECTION LOCAL DEFAULT 11 12: 0000000000001000 0 SECTION LOCAL DEFAULT 12 13: 0000000000001020 0 SECTION LOCAL DEFAULT 13 14: 0000000000001080 0 SECTION LOCAL DEFAULT 14 15: 0000000000001090 0 SECTION LOCAL DEFAULT 15 16: 00000000000010e0 0 SECTION LOCAL DEFAULT 16 17: 0000000000001368 0 SECTION LOCAL DEFAULT 17 18: 0000000000002000 0 SECTION LOCAL DEFAULT 18 19: 00000000000020a0 0 SECTION LOCAL DEFAULT 19 20: 00000000000020e8 0 SECTION LOCAL DEFAULT 20 21: 0000000000003d78 0 SECTION LOCAL DEFAULT 21 22: 0000000000003d80 0 SECTION LOCAL DEFAULT 22 23: 0000000000003d88 0 SECTION LOCAL DEFAULT 23 24: 0000000000003f98 0 SECTION LOCAL DEFAULT 24 25: 0000000000004000 0 SECTION LOCAL DEFAULT 25 26: 0000000000004010 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 28: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 29: 0000000000001110 0 FUNC LOCAL DEFAULT 16 deregister_tm_clones 30: 0000000000001140 0 FUNC LOCAL DEFAULT 16 register_tm_clones 31: 0000000000001180 0 FUNC LOCAL DEFAULT 16 __do_global_dtors_aux 32: 0000000000004010 1 OBJECT LOCAL DEFAULT 26 completed.8061 33: 0000000000003d80 0 OBJECT LOCAL DEFAULT 22 __do_global_dtors_aux_fin 34: 00000000000011c0 0 FUNC LOCAL DEFAULT 16 frame_dummy 35: 0000000000003d78 0 OBJECT LOCAL DEFAULT 21 __frame_dummy_init_array_ 36: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 38: 00000000000021ec 0 OBJECT LOCAL DEFAULT 20 __FRAME_END__ 39: 0000000000000000 0 FILE LOCAL DEFAULT ABS 40: 0000000000003d80 0 NOTYPE LOCAL DEFAULT 21 __init_array_end 41: 0000000000003d88 0 OBJECT LOCAL DEFAULT 23 _DYNAMIC 42: 0000000000003d78 0 NOTYPE LOCAL DEFAULT 21 __init_array_start 43: 00000000000020a0 0 NOTYPE LOCAL DEFAULT 19 __GNU_EH_FRAME_HDR 44: 0000000000003f98 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_ 45: 0000000000001000 0 FUNC LOCAL DEFAULT 12 _init 46: 0000000000001360 5 FUNC GLOBAL DEFAULT 16 __libc_csu_fini 47: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 48: 0000000000004000 0 NOTYPE WEAK DEFAULT 25 data_start 49: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 25 _edata 50: 0000000000001368 0 FUNC GLOBAL HIDDEN 17 _fini 59: 0000000000004018 0 NOTYPE GLOBAL DEFAULT 26 _end 60: 00000000000010e0 47 FUNC GLOBAL DEFAULT 16 _start 61: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 62: 00000000000011c9 293 FUNC GLOBAL DEFAULT 16 main 63: 0000000000000000 0 FUNC GLOBAL DEFAULT UND regset 64: 0000000000000000 0 FUNC GLOBAL DEFAULT UND regget 65: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atoi@@GLIBC_2.2.5 66: 0000000000004010 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ 67: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 68: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2 Histogram for `.gnu.hash' bucket list length (total of 2 buckets): Length Number % of total Coverage 0 1 ( 50.0%) 1 1 ( 50.0%) 100.0% Version symbols section '.gnu.version' contains 11 entries: Addr: 0x000000000000057e Offset: 0x00057e Link: 6 (.dynsym) 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 004: 2 (GLIBC_2.2.5) 0 (*local*) 0 (*local*) 0 (*local*) 008: 2 (GLIBC_2.2.5) 0 (*local*) 2 (GLIBC_2.2.5) Version needs section '.gnu.version_r' contains 1 entry: Addr: 0x0000000000000598 Offset: 0x000598 Link: 7 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 2 Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK Displaying notes found in: .note.gnu.build-id Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: e77046db6ef702a971f1bcda6ee429513c6ad762 Displaying notes found in: .note.ABI-tag Owner Data size Description GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) OS: Linux, ABI: 3.2.0 ::: ### Write the Makefile and build it ```shell Tomas# cat Makefile # Compiler and flags CC = gcc CFLAGS = -Wall -Wextra -Iregapi/include LIB_CFLAGS = -Wall -Wextra -Iregapi/include -fPIC LDFLAGS = -L. -lregapi # Source files and objects SRC = main.c LIB_SRC = regapi/src/regapi.c OBJ = $(SRC:.c=.o) regapi.o # Target executable TARGET = hello .PHONY: all clean all: $(TARGET) # Build the static library libregapi.a: regapi.o ar rcs $@ $^ # Build the static library libregapi.so: regapi.o $(CC) -s -shared -o $@ $^ # Compile the library source file #regapi.o: $(LIB_SRC) # $(CC) $(CFLAGS) -c $< regapi.o: $(LIB_SRC) $(CC) $(LIB_CFLAGS) -c $< # Build the main executable $(TARGET): $(OBJ) libregapi.so #$(TARGET): $(OBJ) libregapi.a $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) # Compile source files %.o: %.c $(CC) $(CFLAGS) -c $< clean: rm -f $(TARGET) $(OBJ) libregapi.a libregapi.so ``` ## Summary ### Comparision | Item | Type | File name | Size | |-| -------- | -------- | -------- | |1 |Static library | libregapi.a | 3242 | |2 |Dynamic library | libregapi.so | 14472 | |3 |Application w/ static library | hello | 16944 | |4 |Appliaction w/ dynamic library | hello| 17208 | From the table above, it is obvious to see 1. the size of the static library is smaller than the dynamic one. 2. the size of the main application with static library is 184 bytes larger than the one with dynamic library. ### Pros and cons | | Static library | Dynamic library | | -------- | -------- | -------- | | App size | larger | smaller | | Library size | smaller | larger| | Version control | No | Yes | | Easy to develop App | Yes | No | |Reusable | No| Yes | ## Appendix ### Common Makefile We write a Makefile to build the application with a static library and a dynamic library by setting the flag SHARED_LIB: - if SHARED_LIB = 1, hello with libregapi.so - if SHARED_LIB = 0, hello with libregapi.a - default, SHARED_LIB = 0 ```shell # # 'make SHARED_LIB=0' build executable file with libregapi.a # 'make SHARED_LIB=1' build executable file with libregapi.so # 'make clean' removes all .o, .a, .so and executable files # # Compiler and flags CC = gcc CFLAGS = -Wall -Wextra -Iregapi/include LIB_CFLAGS = -Wall -Wextra -Iregapi/include -fPIC LDFLAGS = -L. -lregapi # Source files and objects SRC = main.c LIB_SRC = regapi/src/regapi.c OBJ = $(SRC:.c=.o) regapi.o # Target executable TARGET = hello .PHONY: all clean all: $(TARGET) # Build the static library libregapi.so: regapi.o $(CC) -s -shared -o $@ $^ ifeq ($(SHARED_LIB),1) # Compile the library source file regapi.o: $(LIB_SRC) $(CC) $(LIB_CFLAGS) -c $< # Build the main executable $(TARGET): $(OBJ) libregapi.so $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) TARGET = hello .PHONY: all clean all: $(TARGET) # Build the static library libregapi.a: regapi.o ar rcs $@ $^ # Build the static library libregapi.so: regapi.o $(CC) -s -shared -o $@ $^ ifeq ($(SHARED_LIB),1) # Compile the library source file regapi.o: $(LIB_SRC) $(CC) $(LIB_CFLAGS) -c $< # Build the main executable $(TARGET): $(OBJ) libregapi.so $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) else # Compile the library source file regapi.o: $(LIB_SRC) $(CC) $(CFLAGS) -c $< # Build the main executable $(TARGET): $(OBJ) libregapi.a $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) endif # Compile source files %.o: %.c $(CC) $(CFLAGS) -c $< clean: rm -f $(TARGET) $(OBJ) libregapi.a libregapi.so ``` Example, ```shell Tomas# make SHARED_LIB=1 gcc -Wall -Wextra -Iregapi/include -c main.c gcc -Wall -Wextra -Iregapi/include -fPIC -c regapi/src/regapi.c gcc -s -shared -o libregapi.so regapi.o gcc -Wall -Wextra -Iregapi/include -o hello main.o regapi.o libregapi.so -L. -lregapi Tomas# ls -al -rwxrwxr-x 1 tomas tomas 17208 十 22 22:08 hello -rwxrwxr-x 1 tomas tomas 14472 十 22 22:08 libregapi.so -rw-rw-r-- 1 tomas tomas 741 十 22 19:35 main.c -rw-rw-r-- 1 tomas tomas 2576 十 22 22:08 main.o -rw-rw-r-- 1 tomas tomas 1148 十 22 22:07 Makefile -rw-rw-r-- 1 tomas tomas 603 十 22 21:19 Makefile.static drwxrwxr-x 4 tomas tomas 4096 十 22 17:25 regapi -rw-rw-r-- 1 tomas tomas 3088 十 22 22:08 regapi.o -rw-rw-r-- 1 tomas tomas 2 十 22 21:09 reg.txt Tomas# make gcc -Wall -Wextra -Iregapi/include -c main.c gcc -Wall -Wextra -Iregapi/include -c regapi/src/regapi.c ar rcs libregapi.a regapi.o gcc -Wall -Wextra -Iregapi/include -o hello main.o regapi.o libregapi.a -L. -lregapi Tomas# ls -al -rwxrwxr-x 1 tomas tomas 17208 十 22 22:08 hello -rw-rw-r-- 1 tomas tomas 3242 十 22 22:08 libregapi.a -rw-rw-r-- 1 tomas tomas 741 十 22 19:35 main.c -rw-rw-r-- 1 tomas tomas 2576 十 22 22:08 main.o -rw-rw-r-- 1 tomas tomas 1148 十 22 22:07 Makefile -rw-rw-r-- 1 tomas tomas 603 十 22 21:19 Makefile.static drwxrwxr-x 4 tomas tomas 4096 十 22 17:25 regapi -rw-rw-r-- 1 tomas tomas 3088 十 22 22:08 regapi.o -rw-rw-r-- 1 tomas tomas 2 十 22 21:09 reg.txt ``` ## Reference https://www.linkedin.com/pulse/differences-between-static-dynamic-libraries-juan-david-tuta-botero https://bryceknowhow.blogspot.com/2014/11/linux-static-library-dynamic-library.html https://hackmd.io/@TomasZheng/Sy6ly6JWa https://blog.gtwang.org/programming/howto-create-library-using-gcc/ https://stackoverflow.com/questions/6562403/i-dont-understand-wl-rpath-wl