25|可执行二进制文件里有什么?
于航
该思维导图由 AI 生成,仅供参考
你好,我是于航。从这一讲开始,我们就进入到了“C 程序运行原理篇”的学习。
和之前的内容相比,在这一模块中,我们将会从“台前”走向“幕后”:从由 C 代码直观表示的程序逻辑,走向程序在运行过程中,背后与操作系统交互时的具体原理。相信学习完这个模块后,你会对一个 C 程序从代码编写,到通过编译,再到最终被操作系统运行的完整过程有更深入的理解。其中,程序的运行细节仅与所在操作系统紧密相关,因此,这一模块中介绍的原理性知识也同样适用于由 Rust、C++,以及 Go 等其他系统级编程语言编写的程序。
而今天我们先来看下,经常被提及的“二进制可执行文件”究竟是什么。
可执行文件的格式
我们都知道,一份 C 代码在经过编译器处理后,便可得到能够直接运行的二进制可执行程序。而在不同操作系统上,这些编译生成的可执行文件都有着不同的特征,其中最明显的差别便是文件后缀名。比如,在 Microsoft Windows 操作系统上,通常会以 “.exe” 为后缀名来标注可执行文件;而在类 Unix 操作系统上,可执行文件通常没有任何后缀名。
除此之外,更重要的不同点体现在各类可执行文件在内部数据的组织和结构上。通常来说,最常见的几种可执行文件格式有针对微软 Windows 平台的 PE(Portable Executable)格式、针对类 Unix 平台的 ELF(Executable and Linkable Format)格式,以及针对 MacOS 和 IOS 平台的 Mach-O 格式。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了可执行二进制文件的内部结构和原理,以 ELF 格式为例,详细解释了可执行文件的基本组织方式,包括 ELF 头部和 ELF Section 头。通过实例展示了如何通过命令来查看可执行文件的内部组成结构,以及如何理解 ELF 文件的基本结构。此外,还介绍了 ELF 文件类型和各个 Section 的作用,以及静态视图在应用程序生命周期中的链接过程。文章还探讨了在 Linux 系统中使用内核提供的头文件 elf.h 进行针对 ELF 格式的应用编程的方法。最后,总结了几种不同 ELF 文件类型之间的区别。整体来看,本文对于想要深入了解程序运行原理的读者来说,是一篇很有价值的文章。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入 C 语言和程序运行原理》,新⼈⾸单¥59
《深入 C 语言和程序运行原理》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(9)
- 最新
- 精选
- LDxyElf64_Ehdr* elf_header;为指针类型,应该先让其指向内存空间再使用fread
作者回复: 感谢指正!
2022-02-1832 - 勿更改任何信息https://www.ics.uci.edu/~aburtsev/238P/hw/hw3-elf/hw3-elf.html 这里有一个ELF的作业,可以作为实践
作者回复: 看了一眼,这个实践不错的
2023-04-12归属地:福建 - 石天兰爱学习文章内容很硬核,赞👍🏻
作者回复: 感谢支持!
2022-04-12 - 龍蝦``` #include <stdio.h> #include <stdlib.h> #include <elf.h> void print_section(const char *strtable, int index, Elf64_Shdr *shdr) { printf("[%02d] sh_name: %21s, sh_size: %4x, sh_offset: %4x, \n", index, &strtable[shdr->sh_name], shdr->sh_size, shdr->sh_offset); } int main(int argc, char **argv) { Elf64_Ehdr elf_header; FILE *fp = fopen(argv[1], "r"); fread(&elf_header, sizeof(Elf64_Ehdr), 1, fp); Elf64_Shdr shdr; fseek(fp, elf_header.e_shoff + elf_header.e_shentsize * elf_header.e_shstrndx, SEEK_SET); fread(&shdr, sizeof(Elf64_Shdr), 1, fp); // Section 名字并不是保存在 Section 头结构中,而是保存在字符串表中 // Section 头结构的 sh_name 字段表示 Section 名称在字符串表中的偏移(以 \0 结尾) // 而字符串表其实是作为一个 Section 存在 ELF 中的,所以这里先把字符串表对应的 Section 读出来 char *strtable = (char *)calloc(shdr.sh_size, sizeof(char)); fseek(fp, shdr.sh_offset, SEEK_SET); fread(strtable, sizeof(char), shdr.sh_size, fp); fseek(fp, elf_header.e_shoff, SEEK_SET); for (int i = 0; i < elf_header.e_shnum; i++) { fread(&shdr, sizeof(Elf64_Shdr), 1, fp); print_section(strtable, i, &shdr); } free(strtable); fclose(fp); return 0; } ```2022-03-093
- 白花风信子最期待的就是原理篇了!!!2022-02-193
- 西坠客现在的gcc需要加上-no-pie选项才能编译出exec类型的文件2023-10-20归属地:安徽
- 前端1期-高雪荣readelf zsh: command not found: readelf2023-04-21归属地:河南
- TableBear今天这门课解决了不少我读程序员自我修养这本书时产生的疑惑。👍👍2022-08-11归属地:广东
- zxk最近刚看完 JVM 的字节码文件格式,配合这篇作对比两者的异同,十分有趣。2022-04-241
收起评论