☰
Linux系统——库的原理与制作之操作
2026/10/17 2:39:34 网站建设 项目流程

💁‍♂️个人主页:进击的荆棘

👇作者其它专栏:

《数据结构与算法》《算法》《C++起始之路》《Linux》


目录

1.什么是库

2.静态库

3.动态库

4.使用外部库

5.目标文件

6.ELF文件

7.ELF从形成到加载轮廓

8.理解连接与加载

附录:操作大全


附录:操作大全

附录1:ELF结构

附录2:查看ELF Header

-h或--file-header:显示ELF文件的文件头信息。文件头包括ELF文件的基本信息,如文件类型、机器类型、版本、入口点地址、程序头表、程序头表和节头表的位置和大小等

[sjx@VM-0-6-centos ~]$ readelf -h main.exe 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: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400440 Start of program headers: 64 (bytes into file) Start of section headers: 6496 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 9 Size of section headers: 64 (bytes) Number of section headers: 30 Section header string table index: 29 // 内核中关于ELF Header相关的数据结构 // 没错,操作系统⾃⼰必须能够识别特定格式的可执⾏程序:/linux/include/elf.h typedef struct elf32_hdr{ unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; /* Entry point */ Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr; typedef struct elf64_hdr { unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; /* Entry point virtual address */ Elf64_Off e_phoff; /* Program header table file offset */ Elf64_Off e_shoff; /* Section header table file offset */ Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr;

附录3:ELF Program Header Table

-l或--program-headers:显示ELF文件的程序头部(段头)信息。可执行文件在内存中的布局和加载过程非常重要

[sjx@VM-0-6-centos ~]$ readelf -l main.exe Elf file type is EXEC (Executable file) Entry point 0x400440 There are 9 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8 R E 8 INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x000000000000075c 0x000000000000075c R E 200000 LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x0000000000000224 0x0000000000000228 RW 200000 DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 0x00000000000001d0 0x00000000000001d0 RW 8 NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000044 0x0000000000000044 R 4 GNU_EH_FRAME 0x000000000000060c 0x000000000040060c 0x000000000040060c 0x000000000000003c 0x000000000000003c R 4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x00000000000001f0 0x00000000000001f0 R 1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got PhysAddr:现代OS,可以不考虑 LOAD:不是所有的section都要被加载到内存,有的是与加载链接有关的字段,但是又LOAD的就是将来要加载的部分 // 内核中关于ELF Program Header相关的数据结构 typedef struct elf32_phdr{ Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; } Elf32_Phdr; typedef struct elf64_phdr { Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; /* Segment file offset */ Elf64_Addr p_vaddr; /* Segment virtual address */ Elf64_Addr p_paddr; /* Segment physical address */ Elf64_Xword p_filesz; /* Segment size in file */ Elf64_Xword p_memsz; /* Segment size in memory */ Elf64_Xword p_align; /* Segment alignment, file & memory */ } Elf64_Phdr;

附录4:ELF Section Header Table

-S或--section-headers:显示ELF文件的节头信息。节头描述了ELF文件的各个节的起始地址、大小、标志等信息

[sjx@VM-0-6-centos ~]$ readelf -S main.exe There are 30 section headers, starting at offset 0x1960: 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 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 0 0 4 [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0000000000400298 00000298 000000000000001c 0000000000000000 A 5 0 8 [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 0000000000000060 0000000000000018 A 6 1 8 [ 6] .dynstr STRTAB 0000000000400318 00000318 000000000000003d 0000000000000000 A 0 0 1 [ 7] .gnu.version VERSYM 0000000000400356 00000356 0000000000000008 0000000000000002 A 5 0 2 [ 8] .gnu.version_r VERNEED 0000000000400360 00000360 0000000000000020 0000000000000000 A 6 1 8 [ 9] .rela.dyn RELA 0000000000400380 00000380 0000000000000018 0000000000000018 A 5 0 8 [10] .rela.plt RELA 0000000000400398 00000398 0000000000000048 0000000000000018 AI 5 23 8 [11] .init PROGBITS 00000000004003e0 000003e0 000000000000001a 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 0000000000400400 00000400 0000000000000040 0000000000000010 AX 0 0 16 [13] .text PROGBITS 0000000000400440 00000440 0000000000000192 0000000000000000 AX 0 0 16 [14] .fini PROGBITS 00000000004005d4 000005d4 0000000000000009 0000000000000000 AX 0 0 4 [15] .rodata PROGBITS 00000000004005e0 000005e0 000000000000002b 0000000000000000 A 0 0 8 [16] .eh_frame_hdr PROGBITS 000000000040060c 0000060c 000000000000003c 0000000000000000 A 0 0 4 [17] .eh_frame PROGBITS 0000000000400648 00000648 0000000000000114 0000000000000000 A 0 0 8 [18] .init_array INIT_ARRAY 0000000000600e10 00000e10 0000000000000008 0000000000000008 WA 0 0 8 [19] .fini_array FINI_ARRAY 0000000000600e18 00000e18 0000000000000008 0000000000000008 WA 0 0 8 [20] .jcr PROGBITS 0000000000600e20 00000e20 0000000000000008 0000000000000000 WA 0 0 8 [21] .dynamic DYNAMIC 0000000000600e28 00000e28 00000000000001d0 0000000000000010 WA 6 0 8 [22] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 0 0 8 [23] .got.plt PROGBITS 0000000000601000 00001000 0000000000000030 0000000000000008 WA 0 0 8 [24] .data PROGBITS 0000000000601030 00001030 0000000000000004 0000000000000000 WA 0 0 1 [25] .bss NOBITS 0000000000601034 00001034 0000000000000004 0000000000000000 WA 0 0 1 [26] .comment PROGBITS 0000000000000000 00001034 000000000000002d 0000000000000001 MS 0 0 1 [27] .symtab SYMTAB 0000000000000000 00001068 0000000000000618 0000000000000018 28 47 8 [28] .strtab STRTAB 0000000000000000 00001680 00000000000001d5 0000000000000000 0 0 1 [29] .shstrtab STRTAB 0000000000000000 00001855 0000000000000108 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) .got通常与全局偏移表(Global Offset Table,简称GOT) // 内核中关于ELF Section Header相关的数据结构 typedef struct { Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Word sh_addralign; Elf32_Word sh_entsize; } Elf32_Shdr; typedef struct elf64_shdr { Elf64_Word sh_name; /* Section name, index in string tbl */ Elf64_Word sh_type; /* Type of section */ Elf64_Xword sh_flags; /* Miscellaneous section attributes */ Elf64_Addr sh_addr; /* Section virtual addr at execution */ Elf64_Off sh_offset; /* Section file offset */ Elf64_Xword sh_size; /* Size of section in bytes */ Elf64_Word sh_link; /* Index of another section */ Elf64_Word sh_info; /* Additional section information */ Elf64_Xword sh_addralign; /* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */ } Elf64_Shdr;

附录5:查看具体的sections信息

[sjx@VM-0-6-centos ~]$ objdump -S main.exe main.exe: file format elf64-x86-64 Disassembly of section .init: 00000000004003e0 <_init>: 4003e0: 48 83 ec 08 sub $0x8,%rsp 4003e4: 48 8b 05 0d 0c 20 00 mov 0x200c0d(%rip),%rax # 600ff8 <__gmon_start__> 4003eb: 48 85 c0 test %rax,%rax 4003ee: 74 05 je 4003f5 <_init+0x15> 4003f0: e8 3b 00 00 00 callq 400430 <__gmon_start__@plt> 4003f5: 48 83 c4 08 add $0x8,%rsp 4003f9: c3 retq Disassembly of section .plt: 0000000000400400 <.plt>: 400400: ff 35 02 0c 20 00 pushq 0x200c02(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8> 400406: ff 25 04 0c 20 00 jmpq *0x200c04(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10> 40040c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000400410 <puts@plt>: 400410: ff 25 02 0c 20 00 jmpq *0x200c02(%rip) # 601018 <puts@GLIBC_2.2.5> 400416: 68 00 00 00 00 pushq $0x0 40041b: e9 e0 ff ff ff jmpq 400400 <.plt> 0000000000400420 <__libc_start_main@plt>: 400420: ff 25 fa 0b 20 00 jmpq *0x200bfa(%rip) # 601020 <__libc_start_main@GLIBC_2.2.5> 400426: 68 01 00 00 00 pushq $0x1 40042b: e9 d0 ff ff ff jmpq 400400 <.plt> 0000000000400430 <__gmon_start__@plt>: 400430: ff 25 f2 0b 20 00 jmpq *0x200bf2(%rip) # 601028 <__gmon_start__> 400436: 68 02 00 00 00 pushq $0x2 40043b: e9 c0 ff ff ff jmpq 400400 <.plt> Disassembly of section .text: 0000000000400440 <_start>: 400440: 31 ed xor %ebp,%ebp 400442: 49 89 d1 mov %rdx,%r9 400445: 5e pop %rsi 400446: 48 89 e2 mov %rsp,%rdx 400449: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 40044d: 50 push %rax 40044e: 54 push %rsp 40044f: 49 c7 c0 d0 05 40 00 mov $0x4005d0,%r8 400456: 48 c7 c1 60 05 40 00 mov $0x400560,%rcx 40045d: 48 c7 c7 3d 05 40 00 mov $0x40053d,%rdi 400464: e8 b7 ff ff ff callq 400420 <__libc_start_main@plt> 400469: f4 hlt 40046a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 0000000000400470 <deregister_tm_clones>: 400470: b8 3f 10 60 00 mov $0x60103f,%eax 400475: 55 push %rbp 400476: 48 2d 38 10 60 00 sub $0x601038,%rax 40047c: 48 83 f8 0e cmp $0xe,%rax 400480: 48 89 e5 mov %rsp,%rbp 400483: 77 02 ja 400487 <deregister_tm_clones+0x17> 400485: 5d pop %rbp 400486: c3 retq 400487: b8 00 00 00 00 mov $0x0,%eax 40048c: 48 85 c0 test %rax,%rax 40048f: 74 f4 je 400485 <deregister_tm_clones+0x15> 400491: 5d pop %rbp 400492: bf 38 10 60 00 mov $0x601038,%edi 400497: ff e0 jmpq *%rax 400499: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000004004a0 <register_tm_clones>: 4004a0: b8 38 10 60 00 mov $0x601038,%eax 4004a5: 55 push %rbp 4004a6: 48 2d 38 10 60 00 sub $0x601038,%rax 4004ac: 48 c1 f8 03 sar $0x3,%rax 4004b0: 48 89 e5 mov %rsp,%rbp 4004b3: 48 89 c2 mov %rax,%rdx 4004b6: 48 c1 ea 3f shr $0x3f,%rdx 4004ba: 48 01 d0 add %rdx,%rax 4004bd: 48 d1 f8 sar %rax 4004c0: 75 02 jne 4004c4 <register_tm_clones+0x24> 4004c2: 5d pop %rbp 4004c3: c3 retq 4004c4: ba 00 00 00 00 mov $0x0,%edx 4004c9: 48 85 d2 test %rdx,%rdx 4004cc: 74 f4 je 4004c2 <register_tm_clones+0x22> 4004ce: 5d pop %rbp 4004cf: 48 89 c6 mov %rax,%rsi 4004d2: bf 38 10 60 00 mov $0x601038,%edi 4004d7: ff e2 jmpq *%rdx 4004d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000004004e0 <__do_global_dtors_aux>: 4004e0: 80 3d 4d 0b 20 00 00 cmpb $0x0,0x200b4d(%rip) # 601034 <_edata> 4004e7: 75 11 jne 4004fa <__do_global_dtors_aux+0x1a> 4004e9: 55 push %rbp 4004ea: 48 89 e5 mov %rsp,%rbp 4004ed: e8 7e ff ff ff callq 400470 <deregister_tm_clones> 4004f2: 5d pop %rbp 4004f3: c6 05 3a 0b 20 00 01 movb $0x1,0x200b3a(%rip) # 601034 <_edata> 4004fa: f3 c3 repz retq 4004fc: 0f 1f 40 00 nopl 0x0(%rax) 0000000000400500 <frame_dummy>: 400500: 48 83 3d 18 09 20 00 cmpq $0x0,0x200918(%rip) # 600e20 <__JCR_END__> 400507: 00 400508: 74 1e je 400528 <frame_dummy+0x28> 40050a: b8 00 00 00 00 mov $0x0,%eax 40050f: 48 85 c0 test %rax,%rax 400512: 74 14 je 400528 <frame_dummy+0x28> 400514: 55 push %rbp 400515: bf 20 0e 60 00 mov $0x600e20,%edi 40051a: 48 89 e5 mov %rsp,%rbp 40051d: ff d0 callq *%rax 40051f: 5d pop %rbp 400520: e9 7b ff ff ff jmpq 4004a0 <register_tm_clones> 400525: 0f 1f 00 nopl (%rax) 400528: e9 73 ff ff ff jmpq 4004a0 <register_tm_clones> 000000000040052d <test>: 40052d: 55 push %rbp 40052e: 48 89 e5 mov %rsp,%rbp 400531: bf f0 05 40 00 mov $0x4005f0,%edi 400536: e8 d5 fe ff ff callq 400410 <puts@plt> 40053b: 5d pop %rbp 40053c: c3 retq 000000000040053d <main>: 40053d: 55 push %rbp 40053e: 48 89 e5 mov %rsp,%rbp 400541: b8 00 00 00 00 mov $0x0,%eax 400546: e8 e2 ff ff ff callq 40052d <test> 40054b: bf ff 05 40 00 mov $0x4005ff,%edi 400550: e8 bb fe ff ff callq 400410 <puts@plt> 400555: 5d pop %rbp 400556: c3 retq 400557: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 40055e: 00 00 0000000000400560 <__libc_csu_init>: 400560: 41 57 push %r15 400562: 41 89 ff mov %edi,%r15d 400565: 41 56 push %r14 400567: 49 89 f6 mov %rsi,%r14 40056a: 41 55 push %r13 40056c: 49 89 d5 mov %rdx,%r13 40056f: 41 54 push %r12 400571: 4c 8d 25 98 08 20 00 lea 0x200898(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry> 400578: 55 push %rbp 400579: 48 8d 2d 98 08 20 00 lea 0x200898(%rip),%rbp # 600e18 <__init_array_end> 400580: 53 push %rbx 400581: 4c 29 e5 sub %r12,%rbp 400584: 31 db xor %ebx,%ebx 400586: 48 c1 fd 03 sar $0x3,%rbp 40058a: 48 83 ec 08 sub $0x8,%rsp 40058e: e8 4d fe ff ff callq 4003e0 <_init> 400593: 48 85 ed test %rbp,%rbp 400596: 74 1e je 4005b6 <__libc_csu_init+0x56> 400598: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 40059f: 00 4005a0: 4c 89 ea mov %r13,%rdx 4005a3: 4c 89 f6 mov %r14,%rsi 4005a6: 44 89 ff mov %r15d,%edi 4005a9: 41 ff 14 dc callq *(%r12,%rbx,8) 4005ad: 48 83 c3 01 add $0x1,%rbx 4005b1: 48 39 eb cmp %rbp,%rbx 4005b4: 75 ea jne 4005a0 <__libc_csu_init+0x40> 4005b6: 48 83 c4 08 add $0x8,%rsp 4005ba: 5b pop %rbx 4005bb: 5d pop %rbp 4005bc: 41 5c pop %r12 4005be: 41 5d pop %r13 4005c0: 41 5e pop %r14 4005c2: 41 5f pop %r15 4005c4: c3 retq 4005c5: 90 nop 4005c6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 4005cd: 00 00 00 00000000004005d0 <__libc_csu_fini>: 4005d0: f3 c3 repz retq Disassembly of section .fini: 00000000004005d4 <_fini>: 4005d4: 48 83 ec 08 sub $0x8,%rsp 4005d8: 48 83 c4 08 add $0x8,%rsp 4005dc: c3 retq

查看编译后的.o目标文件

在了解ELF文件的基本格式后,就能查看经编译后产生的目标.o文件细节了

[sjx@VM-0-6-centos ~]$ objdump -S code.o code.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <test>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: bf 00 00 00 00 mov $0x0,%edi 9: e8 00 00 00 00 callq e <test+0xe> e: 5d pop %rbp f: c3 retq

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询