![Go语言底层原理剖析](https://wfqqreader-1252317822.image.myqcloud.com/cover/131/40795131/b_40795131.jpg)
1.15 ELF文件解析
在Windows操作系统下,编译后的Go文本文件最终会生成以.exe为后缀的PE格式的可执行文件,而在Linux和类UNIX操作系统下,会生成ELF格式的可执行文件。除机器码外,在可执行文件中还可能包含调试信息、动态链接库信息、符号表信息。ELF(Executable and Linkable Format)是类UNIX操作系统下最常见的可执行且可链接的文件格式。有许多工具可以完成对ELF文件的探索查看,如readelf、objdump。下面使用readelf查看ELF文件的头信息:
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_41_1.jpg?sign=1739252776-5lBkxotlC5kyrgdykgoPlk3Av7i0nbZ6-0-3c5ec18fb20f1645def2f62e88a85a25)
ELF包含多个segment与section。debug/elf包中给出了一些调试ELF的API,以下程序可以打印出ELF文件中section的信息。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_41_2.jpg?sign=1739252776-Am615QJJysI0db23r60DEemZ890zlGKF-0-09ed33b414edce3221bae07a34d3314c)
通过readelf工具查看ELF文件中section的信息。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_42_1.jpg?sign=1739252776-uYPlgBAdL9xcwlkMrTGhfLowN54hCi4C-0-213109775da8534289a0715516940ca6)
segment包含多个section,它描述程序如何映射到内存中,如哪些section需要导入内存、采取只读模式还是读写模式、内存对齐大小等。以下是section与segment的对应关系。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_42_2.jpg?sign=1739252776-0Y2xzSsM7mQJK3HufDg8rnTf3COB6BgA-0-a44d8ab21630b25aa337a02321b81839)
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_43_1.jpg?sign=1739252776-9Fr3goA0DLkU7hGWXWYnoZvpitZNTU1h-0-ca4e2087c3cdd225d820b401fbffec51)
并不是所有的section都需要导入内存,当Type为LOAD时,代表section需要被导入内存。后面的Flg代表内存的读写模式。包含.text的代码区代表可以被读和执行,包含.data与.bss的全局变量可以被读写,其中,为了满足垃圾回收的需要还区分了是否包含指针的区域。包含.rodata常量数据的区域代表只读区,其中,.itablink为与Go语言接口相关的全局符号表,详见第12章。.gopclntab包含程序计数器PC与源代码行的对应关系。
一个Hello World程序一共包含25个section,可以看到并不是所有section都需要导入内存,同时,该程序包含单独存储调试信息的区域。如.note.go.buildid包含Go程序唯一的ID,可以通过objdump工具在.note.go.buildid中查找到每个Go程序唯一的ID。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_43_2.jpg?sign=1739252776-hGow9j1POS8oPNxO0eThgNc0Yp0kXqLe-0-1d33ba9a48eb28d9856291847751c663)
另外,.go.buildinfo section包含Go程序的构建信息,“go version”命令会查找该区域的信息获取Go语言版本号。