08 | ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?
08 | ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?
讲述:徐文浩
时长09:19大小8.55M
编译、链接和装载:拆解程序执行
ELF 格式和链接:理解链接过程
总结延伸
推荐阅读
课后思考
赞 80
提建议
精选留言(61)
- djfhchdh2019-06-14readelf -s link_example.o //查看符号表 objdump -r link_example.o //查看重定位表97
- 一步2019-05-13老师,我曾经在linux上使用过wine,有好多window软件不能很好兼容的运行,这是为什么呢?是不是除了执行文件格式之外,还有其他的因素影响软件的运行呢?
作者回复: 一步同学你好,当然,因为很多程序还依赖各种操作系统本身提供的动态链接库,系统调用等等。需要wine提供对应的实现,兼容格式只是万里长征第一步。
共 2 条评论63 - 有米2019-05-13Java的跨平台运行是如何做到的呢?跟本节内容有关系吗?
作者回复: Java是通过实现不同平台上的虚拟机,然后即时翻译javac生成的中间代码来做到跨平台的。跨平台的工作被虚拟机开发人员来解决了
53 - 二星球2019-05-18老师好,就是没有操作系统,直接在硬件上运行的可执行程序,其格式应该不是pe或elf,应该是纯的机器指令吧,pe或elf格式的可执行程序是跟操作系统绑定的,经过翻译后成为纯机器指令,才能被执行,不知道这样理解对不。
作者回复: 可以这样理解。实际机器启动加电的时候是从BIOS去读取MBR,再加载操作系统等等。 PE和ELF是在操作系统加载之后的事情了。
共 3 条评论30 - 二星球2019-05-13老师好,我有个问题,就是我可以用编程语言写一个不依赖操作系统的可执行程序,这个可执行程序不是pe格式,也不是elf的,那为什能执行呢,是不是因为这个可执行程序全是纯的cpu指令,没有其他要解析的东西?
作者回复: 如果不是pe格式也不是elf格式,就不能执行啊。能执行是因为实际执行的不是你的程序。比如你写了一段python代码,实际执行的是python解释器,而不是你的py代码
共 2 条评论27 - 陆离2019-05-23高级语言都是先编译成汇编语言,再汇编成机器码执行的吗?
作者回复: 如果是编译型的语言都是这样的。 也有通过解释器,或者虚拟机,转换成实际的机器码指令执行的。
23 - Spring2019-05-13补充一下: ELF其实是一种文件格式的标准,ELF文件有三类:可重定向文件、可执行文件、共享目标文件。代码经过预处理、编译、汇编后形成可重定向文件,可重定向文件经过链接后生成可执行文件。 另外我想请教一下,机器码是在哪一步形成的?
作者回复: 简单地说,可以认为是在汇编之后变成了机器码放在了elf的代码段里。
21 - 有铭2019-05-13所以理论上,只要不涉及到windows和linux的系统api调用,理论上只要搞定了可执行文件格式这个问题,那么C程序就是二进制可移植的?
作者回复: 除了系统调用,还要考虑是否有动态链接库的依赖等等
16 - 被过去推开2019-08-12Java的类加载是由jvm完成,大致过程为装载-链接-初始化-运行,所以是jvm帮我们屏蔽了操作系统之间的差异。为了加快程序启动速度,一些类会延迟加载,所以jvm中有很多动态链接。
作者回复: 👍
共 2 条评论13 - 罗耀龙@坐忘2020-11-14茶艺师学编程 关键词 编译 complie 汇编 assemble 链接 link 装载 load 装载器 loader 链接器 linker 目标代码 object program 可执行文件 executable flie 可执行可链接文件 ELF executable and linkable file format 符号表 symbols table file header .text section 代码段 (code section ) .data section 数据段 .rel text section 重定位 (relocation table) .symbols section 符号表 PE protable executable format展开9
- kdb_reboot2019-05-26这里(gcc -g -c add_lib.c link_example.c)需要extern int addd(int a, int b);
作者回复: 没错,不过其实你不加入对应的申明编译和运行也是能执行的,但是会有编译器的告警。
8 - WENMURAN2020-04-01ELF和静态链接 在“C语言代码-汇编代码-机器码”的过程中,计算机执行时由两部分组成:一:编译、汇编、链接。二:通过装载器把可执行文件装载到内存中。 C语言代码>编译器>汇编代码>汇编器>目标文件+静态程序库>链接器>可执行文件>加载器<内存中的过程和数据< CPU 从目标代码到可执行文件的过程中,经过了一道叫ELF的手续,它有个符号表,把之前的函数名变量名等到都保存起来,并且和地址关联起来,ELF文件格式把之前的各种信息分成一个一个section保存起来,包括跳转信息。然后CPU这边的加载器只要根据ELF的格式识别一下就可以直接执行了。 Section还有这些东西:代码段(保存指令),数据段(保存初始化数据信息),重定位表(跳转地址),符号表。 感觉ELF就像再加一层的编译展开共 1 条评论7
- 曾经瘦过2019-05-13mark 后面去读一读 程序员的自我修养
作者回复: 👍这本书对于做系统开发的同学是必读书目之一。
共 3 条评论7 - 疯狂土豆2019-10-03老师,我非科班出身,现在正在看汇编,像上面的汇编片段,我知道汇编指令,但是汇编指令之前的是什么东西,6b1: 48 89 e5 mov rbp,中的6b1: 48 89 e5大概是干什么用的,汇编刚刚开始学,像JVM等编译的字节码都有这些东西。只希望可以看懂这些是干什么用的。谢谢老师
作者回复: 盗马将同学,你好 6b1你可以认为是一个行号,也就是这条指令的内存地址 48 89 e5 是指这条指令的二进制表示,用16进制的方式书写出来。毕竟写一堆0和1太占地方了。
共 2 条评论6 - Only now2019-05-13mark 本章内容确实在链接装载与库里有更详尽的说明。
作者回复: 👍程序员的自我修养是一本好书。这个专栏的主题是组成原理,希望能带大家入个门。更深入地要去再花时间看书哦
5 - 程序水果宝2020-02-08为啥通过 gcc 的 -o 参数生成对应的可执行文件后,再执行objdump命令查看到的地址不是从0开始而是从6b0开始
作者回复: 程序水果宝同学, objdump命令并不是从6b0开始,只是add函数的text section从6b0开始而已。你可以自己试着在本地dump出来看一下。 ELF格式的文件有很多section,也有header部分,里面的地址本质上是一个相对的偏移量。想要对ELF格式做更深入的研究,推荐可以先花点时间看完《程序员的自我修养》这本书。
4 - skye2019-08-13老师,嵌入式开发都需要交叉编译,这个是因为CPU的指令集差异,现在什么方法屏蔽这个差异,实现不交叉编译也能实现程序在嵌入式设备上的运行吗?
作者回复: skye同学, 你好,据我所知是没有。这个硬件上的指令集差异避不开啊。
4 - 一步2019-05-13老师问一下Mac系统的可执行文件格式是什么,也是ELF吗?还是mac自己有自己一套?共 1 条评论4
- lzhao2019-05-13上周五还在思考这个问题?这答案说来就来,及时雨宋江
作者回复: 👍希望对大家有所帮助
4 - 人在江湖龙在江湖2020-11-12这一节可执行文件最好用gdb一步一步调试,最好看看每一步汇编,详细的看看内部一些细节才好。推荐陈皓10年前写的“用GDB调试程序”系列:https://blog.csdn.net/haoel/article/details/28793