可执行文件的建立——预处理、编译和连接 在object文件中有三种主要的类型。 一个可重定位(relocatable)文件保存着代码和适当的数据,用来和其余的object文件一块儿来建立一个可执行文件或者是一个共享文件。 一个可执行(executable)文件保存着一个用来执行的程序;该文件指出了exec(BA_OS)如何来建立程序进程映象。 一个共享object文件保存着代码和合适的数据,用来被下面的两个连接器连接: -第一个是链接编辑器[请参看ld(SD_CMD)],能够和其余的可重定位和共享object文件来建立其余的object。 -第二个是动态连接器,联合一个可执行文件和其余的共享object文件来建立一个进程映象。 一个object文件被汇编器和联接器建立, 想要在处理机上直接运行的object文件都是以二进制来存放的。 那些须要抽象机制的程序,好比shell脚本,是不被接受的。
Object文件格式 Linking 视角 Execution 视角 ============ ============== ELF header ELF header Program header table (optional) Program header table Section 1 Segment 1 ... Segment 2 Section n ... Section header table Section header table (optional) 一个ELF头在文件的开始,保存了路线图(road map),描述了该文件的组织状况。 sections保存着object 文件的信息,从链接角度看:包括指令,数据,符号表,重定位信息等。特别sections的描述会出项在之后的第一部分。 第二部分讨论了段和从程序的执行角度看文件。 假如一个程序头表(program header table)存在,那么它告诉系统如何来建立一 个进程的内存映象。被用来创建进程映象(执行一个程序)的文件必需要有一个程 序头表(program header table);可重定位文件不须要这个头表。一个 section头表(section header table)包含了描述文件sections的信息。每一个 section在这个表中有一个入口;每一个入口给出了该section的名字,大小, 等等信息。在联接过程当中的文件必须有一个section头表;其余object文件可要 可不要这个section头表。 注意: 虽然图显示出程序头表马上出如今一个ELF头后,section头表跟着其余 section部分出现,事实是的文件是能够不一样的。此外,sections和段(segments) 没有特别的顺序。只有ELF头(elf header)是在文件的固定位置。 数据表示 object文件格式支持8位、32位不一样的处理器。不过,它试图努力的在更大 或更小的体系上运行。所以,object文件描绘一些控制数据须要用与机器 无关的格式,使它尽量的用通常的方法甄别object文件和描述他们的内容。 在object文件中剩余的数据使用目标处理器的编码方式,无论文件是在哪台 机子上建立的。
实验楼环境图html
1.新的可执行程序是从哪里开始执行的? 2.为何execve系统调用返回后新的可执行程序能顺利执行? 3.对于静态连接的可执行程序和动态连接的可执行程序execve系统调用返回时会有什么不一样?shell
.ELF可执行文件会被默认映射到0x804800地址 execve内核态,可执行文件覆盖了原来的,返回时是新的可执行程序,也就是main函数发生的起点,加载新的可执行可执行环境。 须要动态连接的可执行文件先加载连接器ld 命令行参数和环境串都放在用户态堆栈中。 将CPU控制权交给LD来加载依赖库并完成动态连接。而后在初始化新程序堆栈时,拷贝进去,先函数调用参数传递,在系统调用参数传递 shell程序——>execve ——>sys_execve do_execve----> do_execve_common----->exec_vinprm------>search_binary_handler execve系统调用返回到用户态 栈底pt_regs start_thread(...,elf_entry,....) 经过修改内核堆栈中EIP的值做为新程序的起点。new ip, new sp. elf_entry是新的可执行程序的起点。 静态连接:程序开始是从0x8048300或0x8048400,也就是main开始的位置 动态连接:动态连接器的起点。
.ELF可执行文件会被默认映射到0x804800地址
execve内核态,可执行文件覆盖了原来的,返回时是新的可执行程序,也就是main函数发生的起点,加载新的可执行可执行环境。 shell程序——>execve ——>sys_execve do_execve----> do_execve_common----->exec_vinprm------>search_binary_handler 栈底pt_regs start_thread(...,elf_entry,....) 经过修改内核堆栈中EIP的值做为新程序的起点。new ip, new sp. elf_entry是新的可执行程序的起点。
静态连接:程序开始是从0x8048300或0x8048400,也就是main开始的位置
动态连接:须要动态连接的可执行文件先加载连接器ld,先从动态连接器开始,连接完成后,而后才返回到main函数起点。
将CPU控制权交给LD来加载依赖库并完成动态连接。而后在初始化新程序堆栈时,拷贝进去,先函数调用参数传递,在系统调用参数传递
**注明“郑伟 +编辑器
参考资料:函数
【1】http://www.xfocus.net/articles/200105/174.html 【2】http://mooc.study.163.com/learn/USTC-1000029000?tid=2001214000#/learn/hw?id=2001372010
能够结合实验截图、ELF可执行文件格式、用户态的相关代码等; 博客内容中须要仔细分析新可执行程序的执行起点及对应的堆栈状态等。编码