作为一个高视角的科普吧,动态链接在装载过程中做了非常复杂的操作,还需要深入学习。
关于分段和分页
核心思想就是虚拟化,如何共用同一块内存,如何实现物理内存的复用,MMU和交换空间的发展使之一步一步成为可能,至于如何进行换页,如何进行映射这是OS该管的事,OS使用MMU提供的接口实现一些列换页算法,如LRU等等,装载器的实现的核心代码也是定义在内核中的,主要分为以下几步:

按我的理解就是,根据elf的各个段的大小以及类型等各个字段,来建立虚拟内存和文件系统以及物理内存之间的映射关系(俗称页表)。当然进程管理系统,也应该做事,这里只讨论文件装载。决定装载的映射关系的一个重要的地方就是内部碎片和外部碎片,感觉这两个非常矛盾,需要trade-off。段页式管理,多级页表虽然缓解了外部碎片,但是同样加剧了内部碎片,使本应该不占一个页的段,占据一个页空间。感觉这里面极度需要平衡,至于该如何装载那就是OS的事了。但是装载之前elf也是做了一些工作,可执行文件有一个叫程序头的东西,俗称段表,貌似也可以对装载的过程一窥一二。
其中描述了各个段的信息,大概就是描述了什么文件偏移该映射到什么地方,但是程序是有pie这个选项的,不知道内核是如何处理的。,可以观察到段表比节表少了好多,段表会将部分节表进行合并导致的。
typedef struct { Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Xword p_filesz; Elf64_Xword p_memsz; Elf64_Xword p_align; } Elf64_Phdr; 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.pr[...] NOTE 0000000000000338 00000338 0000000000000030 0000000000000000 A 0 0 8 [ 3] .note.gnu.bu[...] NOTE 0000000000000368 00000368 0000000000000024 0000000000000000 A 0 0 4 [ 4] .note.ABI-tag NOTE 000000000000038c 0000038c 0000000000000020 0000000000000000 A 0 0 4 [ 5] .gnu.hash GNU_HASH 00000000000003b0 000003b0 0000000000000024 0000000000000000 A 6 0 8 [ 6] .dynsym DYNSYM 00000000000003d8 000003d8 00000000000000a8 0000000000000018 A 7 1 8 [ 7] .dynstr STRTAB 0000000000000480 00000480 000000000000008f 0000000000000000 A 0 0 1 [ 8] .gnu.version VERSYM 0000000000000510 00000510 000000000000000e 0000000000000002 A 6 0 2 [ 9] .gnu.version_r VERNEED 0000000000000520 00000520 0000000000000030 0000000000000000 A 7 1 8 [10] .rela.dyn RELA 0000000000000550 00000550 00000000000000c0 0000000000000018 A 6 0 8 [11] .rela.plt RELA 0000000000000610 00000610 0000000000000018 0000000000000018 AI 6 24 8 [12] .init PROGBITS 0000000000001000 00001000 000000000000001b 0000000000000000 AX 0 0 4 [13] .plt PROGBITS 0000000000001020 00001020 0000000000000020 0000000000000010 AX 0 0 16 [14] .plt.got PROGBITS 0000000000001040 00001040 0000000000000010 0000000000000010 AX 0 0 16 [15] .plt.sec PROGBITS 0000000000001050 00001050 0000000000000010 0000000000000010 AX 0 0 16 [16] .text PROGBITS 0000000000001060 00001060 0000000000000117 0000000000000000 AX 0 0 16 [17] .fini PROGBITS 0000000000001178 00001178 000000000000000d 0000000000000000 AX 0 0 4 [18] .rodata PROGBITS 0000000000002000 00002000 0000000000000007 0000000000000000 A 0 0 4 [19] .eh_frame_hdr PROGBITS 0000000000002008 00002008 0000000000000034 0000000000000000 A 0 0 4 [20] .eh_frame PROGBITS 0000000000002040 00002040 00000000000000ac 0000000000000000 A 0 0 8 [21] .init_array INIT_ARRAY 0000000000003db8 00002db8 0000000000000008 0000000000000008 WA 0 0 8 [22] .fini_array FINI_ARRAY 0000000000003dc0 00002dc0 0000000000000008 0000000000000008 WA 0 0 8 [23] .dynamic DYNAMIC 0000000000003dc8 00002dc8 00000000000001f0 0000000000000010 WA 7 0 8 [24] .got PROGBITS 0000000000003fb8 00002fb8 0000000000000048 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 0000000000000360 0000000000000018 29 18 8 [29] .strtab STRTAB 0000000000000000 000033a0 00000000000001e0 0000000000000000 0 0 1 [30] .shstrtab STRTAB 0000000000000000 00003580 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), D (mbind), l (large), p (processor specific) Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x00000000000002d8 0x00000000000002d8 R 0x8 INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318 0x000000000000001c 0x000000000000001c R 0x1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000628 0x0000000000000628 R 0x1000 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000185 0x0000000000000185 R E 0x1000 LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000 0x00000000000000ec 0x00000000000000ec R 0x1000 LOAD 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8 0x0000000000000258 0x0000000000000260 RW 0x1000 DYNAMIC 0x0000000000002dc8 0x0000000000003dc8 0x0000000000003dc8 0x00000000000001f0 0x00000000000001f0 RW 0x8 NOTE 0x0000000000000338 0x0000000000000338 0x0000000000000338 0x0000000000000030 0x0000000000000030 R 0x8 NOTE 0x0000000000000368 0x0000000000000368 0x0000000000000368 0x0000000000000044 0x0000000000000044 R 0x4 GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338 0x0000000000000030 0x0000000000000030 R 0x8 GNU_EH_FRAME 0x0000000000002008 0x0000000000002008 0x0000000000002008 0x0000000000000034 0x0000000000000034 R 0x4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 GNU_RELRO 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8 0x0000000000000248 0x0000000000000248 R 0x1
|