网站推广工具大全网络营销推广服务商

张小明 2026/1/3 14:31:27
网站推广工具大全,网络营销推广服务商,什么网站可以做ppt,软件开发有哪些C语言编译 - ELF文件加载过程解析bin 文件通常用于嵌入式裸机程序的烧录#xff0c;elf 可执行文件通常运行在操作系统之上。bin 是扁平的二进制文件#xff0c;没有任何说明#xff0c;它假设加载它的环境#xff08;如嵌入式引导程序#xff0c;BootRom#xff09;已经…C语言编译 - ELF文件加载过程解析bin 文件通常用于嵌入式裸机程序的烧录elf 可执行文件通常运行在操作系统之上。bin 是扁平的二进制文件没有任何说明它假设加载它的环境如嵌入式引导程序BootRom已经预先知道了代码存放的地址代码的入口数据段代码段的地址。大家如果烧录过嵌入式裸机程序应该有所体会。elf 则是带有详细说明和装配图的文件因此 elf 可执行程序的运行是需要对其所包含的信息进行解析并建立执行环境的这就决定了其不可能作为裸机程序去执行。一、C语言执行需要的内存环境一个可执行文件加载过程中需要创建执行所需要的内存空间。对于操作系统而言一般指的是每个进程的虚拟地址空间。一个进程的内存空间一般存在四个核心区域代码段.text数据段.data堆.heap栈.stack。代码段用于存放编译后的机器指令。数据段data 段已初始化的非零全局变量和静态变量。bss 段未初始化或者初始化值为0的全局变量静态变量。rodata段const 关键字修饰的常量只读。堆用于动态空间分配C语言中需要手动分配和释放malloc/free。栈存储局部变量、函数参数、返回地址自动分配和释放遵循 “先进后出” 规则。需要注意的是栈的地址是从高地址到低地址堆的地址是从低地址到高地址。二、C语言编译过程C语言从源代码到可执行文件一般需要四个过程即预处理编译汇编链接。预处理处理源代码中的预处理指令以#开头生成纯 C 代码.i文件。宏替换展开#define定义的宏如#define PI 3.14替换为实际值。文件包含将#include指令指向的头文件如stdio.h内容插入当前文件。条件编译根据#if、#ifdef等指令保留或删除部分代码如调试代码#ifdef DEBUG ... #endif。删除注释移除//和/* */注释不影响代码逻辑。编译将预处理后的纯 C 代码.i文件转换为汇编代码.s文件。语法分析检查代码语法是否符合 C 语言规则如括号匹配、关键字使用等若出错则终止编译。语义分析验证代码逻辑合理性如变量未声明就使用、类型不匹配等。中间代码生成将合法代码转换为中间表示如三地址码。优化对中间代码进行优化如常量折叠、循环展开提升执行效率。汇编生成将优化后的中间代码转换为对应 CPU 架构的汇编指令。汇编将汇编代码.s文件转换为机器指令二进制目标文件.o或.obj。把汇编指令一一对应为 CPU 可识别的二进制 opcode如call printf转换为对应的机器码生成的目标文件包含二进制指令代码段变量数据数据段符号表记录函数、变量的地址信息供后续链接使用。目标文件是 “部分编译” 的结果可能包含未解析的外部符号如printf函数的地址尚未确定。链接将多个目标文件.o和库文件如libc.so合并生成可执行文件。符号解析找到所有外部符号的实际地址如printf在 C 标准库中的地址。重定位调整目标文件中指令的地址因为多个文件合并后原地址可能偏移。合并段将多个目标文件的代码段、数据段等合并为统一的内存布局。链接又分为静态链接和动态链接。Linux 环境下使用 gcc 进行编译默认使用动态链接。静态链接将程序依赖的库函数代码如printf、malloc直接复制到可执行文件中形成一个独立的二进制文件。依赖的库称为 “静态库”Windows 下为.libLinux 下为.a。动态链接仅在可执行文件中记录库函数的引用信息如函数名、库路径不复制库代码。程序运行时由操作系统的动态链接器如 Linux 的ld.soWindows 的ntdll.dll 加载依赖的库文件到内存并解析引用后面会展开讲。依赖的库称为 “动态库”Windows 下为.dllLinux 下为.somacOS 下为.dylib。Linux默认的动态库链接是/lib/usr/lib。gcc -E main.c -o main.i # 预处理gcc -S main.i -o main.s # 编译gcc -c main.s -o mian.o # 汇编gcc -static main.o -o main # 静态链接gcc main.o -o main # 默认动态链接将自己的代码编译为动态库# -fPIC为位置无关代码-shared指示gcc生成一个共享库而不是一个可执行文件共享库可以被多个程序同时使用节省了内存和磁盘空间。gcc hello.o -fPIC -shared -o libxxx.sogcc main.o -L ./ -lhello -o main2 # main 中用到 hello.c 的库函数# -lhello -l 库的名称。上面的命令只是告诉动态链接库是谁并没有指定动态库所在的路径因此需要添加要使用的动态库文件路径然后执行。# 或者将库文件所在路径添加进环境变量 LD_LIBRARY_PATH将自己的代码编译为静态库ar crv libhello.a hello.ogcc main.o -L ./ -lhello -o main3 # 注意当同一个目录下既有静态库又有动态库默认链接动态库。三、elf 可执行程序3.1 elf 文件的组成elf 文件的主要包括ELF头部程序头表节区节头表几个部分。ELF头部标识这是一个ELF文件文件类型可重定位文件还是共享库文件ARM架构。e_entry程序的入口地址第一条指令的虚拟地址。对于动态链接的程序这个地址通常不是 main 函数而是动态链接器 _start 的入口后面会讲。程序头表和节头表的偏移。程序头表程序头表相当于一个加载说明书告诉操作系统如何将 elf 文件的内容映射到内存中以创建一个进程。程序头表在实现上是一个结构体数组每个结构体segment描述了文件中的一块区域应该如何被映射到内存中。PT_LOAD代码段数据段等需要被加载到内存中的段。PT_DYNAMIC包含动态链接信息的段。PT_INTERP动态链接器的路径lib/ld-linux.so.2。每个程序头都包含了该段在文件中的偏移在内存中的虚拟地址大小执行权限等。节区保存着不同节的具体内容。.text存放程序指令代码。.data存放已初始化的全局变量和静态变量。.bss存放未初始化的全局变量和静态变量此节在文件中不占空间只在运行时在内存中分配。.rodata存放只读数据如常量字符串。.symtab符号表记录了函数和变量的名称及其地址。.symtab / .dynsym符号表.symtab 包含所有符号包括本地符号.dynsym 仅包含动态链接所需的符号如外部库函数。.rel.text / .rel.data重定位信息用于链接时修正地址。节头表所有节的索引目录。存放一个数组数组中的每个元素对应一个节描述了该节的名称在.strtab中的索引类型在文件中的偏移大小链接信息等。3.2 elf 文件的加载过程shell 调用shell 会 fork 一个子进程然后 execve 跳转到 elf 可执行文件中。跳转到内核分配各区域虚拟地址空间创建C语言进程运行环境读取 elf 头部。验证是不是 elf 文件读取头部信息找到程序头表。解析程序头表。寻找 PT_LOAD 段这是唯一需要被实际加载到内存中的段通常一个 ELF 文件至少有两个PT_LOAD段即代码段和数据段。在找到 PT_LOAD 段之后加载器会为当前进程创建一个新的虚拟内存区域起始地址和大小 PT_LOAD-p_vaddr 和PT_LOAD-p_memsz 决定。设置权限。上面的步骤建立了进程的虚拟内存区域现在需要完成虚拟内存区域到物理内存的映射。需要注意的是这个映射并不是把磁盘的所有内容都直接复制到内存里面而是在 MMU 触发缺页中断的时候才从磁盘中把需要的数据放入内存。处理 .bss 段其在二进制文件中不占用空间但是需要在内存中为其分配 p_memsz 的空间。寻找程序头表中的 PT_INTERP 段其存放着动态链接器的路径加载器会把这个动态链接器也放到进程的虚拟内存中。设置栈。内核会在进程空间地址顶端创建一个栈区域压入一些数据传入参数个数传入参数指针指向各环境变量的字符串等和一些辅助向量。从内核跳转到用户空间加载动态链接库重定位内核将指令指针 PC 设置为动态链接器的入口。栈指针指向刚刚的栈顶切换到用户模式。动态链接器 _start 函数开始运行。读取主程序的 .dynamic 节区找到程序依赖的共享库列表加载这些库。上一步动态库加载了之后就有了地址此时就需要对库函数地址占位符进行替换为真实的虚拟地址。执行主程序和各个共享库的初始化代码。跳转main函数执行。3.3 符号表字符串表和重定位符号表字符串表重定位信息都属于节区。静态链接静态链接情况下不存在动态库根据上一节所讲的 elf 文件加载过程需要动态库的可执行文件是运行时加载然后进行重定位的因此静态链接的可执行文件在编译完成的时候重定位就已经完成节区中的重定位信息被删除或者为空符号表通常会保留用于 GDB 调试。符号表 .symtab 与字符串 strtab 表结合作用符号表中保存着程序中变量函数文件名节区名等的名称索引 st_name指向 strtab 中的对应位置地址st_value通常是函数变量的地址或者偏移量大小st_size一个数组或者函数的字节大小类型st_info如 STT_FUNC 函数, STT_OBJECT 对象绑定属性STB_LOCAL局部符号STB_GLOBAL全局符号STB_WEAK弱符号st_shndx一个索引指明该符号位于哪个节区。为什么不直接把字符串存在 .symtab 里呢因为这样做效率低下且浪费空间。使用索引的方式多个符号可以共享同一个字符串例如多个文件都引用 printf并且符号表条目可以保持固定大小便于快速查找。重定位表rel.text/rel.data要解决的问题当存在多个 .c 文件时一个 c 文件使用到另一个 c 文件的函数在编译单个 c 文件时编译器并不知道调用的这个函数的最终地址也不知道自己定义的函数或者变量最终会被链接到可执行文件的哪个地址。这时汇编器会生成一个重定位条目并留下一个占位符表示这个位置的代码需要被修正。重定位条目生成在汇编阶段最终地址的确定发生在链接阶段。每个重定位条目通常是一个结构体变量Elf_Rel或Elf_Rela包含需要被修正的地址在节点中的偏移量 r_offsetr_info存放符号索引和重定位类型。对某个函数和变量进行重定位首先是要知道这个需要被重定位的函数变量在哪r_offset其次是要知道要填充进这个占位符的地址是什么从符号表中获得r_info。两种重定位表的介绍.rel.text包含了对代码节区 (.text) 的重定位信息。例如call printf 指令中的 printf 函数地址在编译时是未知的这里就会生成一个重定位条目。.rel.data包含了对已初始化数据节区 (.data) 的重定位信息。例如int *ptr global_var; 这行代码ptr 变量在 .data 节区但它存储的 global_var 的地址在编译时也是未知的这里也会生成一个重定位条目。对于一个工程文件的编译流程预处理编译汇编链接。假设一个简单的工程文件包括 a.cb.c 包括静态库文件 .a。在汇编阶段汇编器会对各个 .c 文件进行汇编由于这时各个文件中的函数变量在可执行文件中的地址并没有被确定会生成很多重定位条目。在链接阶段链接器 ld 会读取所有的 .o 文件和静态库文件 .a把所有同类型的节区合并读取各个 .o 文件的符号表创建一个全局符号表并且在这个过程中进行符号解析。此时整个可执行文件的地址符号表基本确定需要根据重定位条目对一些占位符进行重定位处理。根据 r_info 找到符号表中的对应位置获取该符号的最终地址。分析 r_info 中的重定位类型计算出需要写入的值。找到 r_offset 指定的需要重定位的占位符的位置执行重定位。链接完成之后.text 和 .data 中的地址引用都是完整的、可以直接运行的。.rel.text 和 .rel.data 节区通常会被丢弃因为所有重定位工作已经完成不再需要它们了。.symtab 和 .strtab 可能会被保留用于调试或者被 strip 工具移除以减小文件大小。动态链接首先根据 elf 加载流程动态链接的地址重定位是在可执行文件执行过程中在内核分配完内存空间和栈空间之后调用 ld.so 动态连接器转到用户空间加载依赖的共享库然后进行运行时地址重定位。最终跳转程序入口开始执行程序。链接过程处理内部符号的重定位。对于外部符号因为地址并不确定所以链接器并不会解析它的最终地址。链接器为外部符号生成动态重定位信息保存在 .rela.plt函数和 .rela.dyn数据节区中对应的动态符号表 .dynsym 是 .symtab 的一个子集只包含用于动态链接的全局符号。动态字符串表为.dynstr。程序加载过程调用动态链接器 ld.so并执行。根据程序头表中的 PT_DYNAMIC 找到 .dynamic 节区遍历所有的 DT_NEEDED 条目加载所有依赖的共享库文件此时主程序所用的库文件都有了自己的地址。然后根据 DT_RELA、DT_RELASZ、DT_JMPREL告诉动态链接器 .rela.dyn 和 .rela.plt 的位置。处理数据重定位 .rela.dyn。处理函数重定位 .rela.plt 。使用延迟绑定策略当函数第一次被调用时控制权会转到 PLT 中PLT 代码会触发 ld.so 解析真正的函数地址。解析完成后写入 PLT后续调用查表即可。结语对整个 elf 可执行文件的加载过程大多数人其实只需要了解即可知道它的流程是怎么样的重定位和链接的关系和设计思想。以及elf 文件加载和 bin 文件的区别。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

造作网站开发网页美工怎么做

Linly-Talker在消防应急演练中的语音指挥应用 在一场高层建筑的消防应急演练中,刺耳的警报声响起,人群开始有序疏散。与此同时,监控大屏上一位神情严肃的“指挥官”正通过清晰、镇定的声音发布指令:“请三楼东侧人员沿安全通道向南…

张小明 2025/12/23 22:49:53 网站建设

官方网站套餐wordpress code 标签

Joplin手写输入:效率提升3倍的终极指南 【免费下载链接】joplin Joplin 是一款安全笔记记录与待办事项应用,具备跨平台同步功能,支持 Windows、macOS、Linux、Android 和 iOS 平台。 项目地址: https://gitcode.com/GitHub_Trending/jo/jop…

张小明 2025/12/22 20:57:55 网站建设

wordpress 获取自定义分类列表泰州做网站优化

目录已开发项目效果实现截图已开发项目效果实现截图开发技术系统开发工具:核心代码参考示例1.建立用户稀疏矩阵,用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 :文章底部…

张小明 2025/12/24 5:09:30 网站建设

贵州华瑞网站建设有限公司建官网公司

雷递网 雷建平 12月17日巴奴国际控股有限公司(简称:“巴奴毛肚火锅”)日前更新招股书,准备在港交所上市。截至目前,巴奴毛肚火锅持有的门店数为162家,2024年12月24日时,为144家。前9个月营收20.…

张小明 2025/12/25 3:52:35 网站建设

网站图片怎么做超链接广州网站建设解决方案

Qwen3-VL-30B Docker部署实战:从零构建高可用多模态服务 在金融文档自动解析、智能座舱视觉交互、工业图纸理解等前沿场景中,一个共同的挑战浮现出来:如何让像 Qwen3-VL-30B 这类参数规模高达300亿的多模态大模型,在生产环境中稳定…

张小明 2026/1/1 0:26:32 网站建设

沧州网站设计报价怎么描述网站主页做的好

炉石传说HsMod插件:55项功能全面优化你的游戏体验 【免费下载链接】HsMod Hearthstone Modify Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 炉石传说作为全球最受欢迎的卡牌游戏,玩家们在享受策略对弈的同时也面临…

张小明 2025/12/24 22:19:18 网站建设