游戏网站建设系统介绍谷德设计网官网首页入口

张小明 2025/12/30 10:54:49
游戏网站建设系统介绍,谷德设计网官网首页入口,凡科网做的网站怎么样,个人可以做宣传片视频网站深入理解CC的编译与链接技术9#xff1a;动态库细节#xff08;完结#xff09; 前言 下面#xff0c;我们准备来聊一下动态库的细节问题。这个问题一般而言#xff0c;工程开发不太可能会涉及到#xff0c;但是知道动态库的工作原理总比不知道好。所以#xff0c;笔者这…深入理解CC的编译与链接技术9动态库细节完结前言下面我们准备来聊一下动态库的细节问题。这个问题一般而言工程开发不太可能会涉及到但是知道动态库的工作原理总比不知道好。所以笔者这里专门的结合《C/C高级编译技术》重新聊一聊动态库的一些细节8.1 解析内存地址的必要性先不着急前进补充几个汇编。很显然我们知道现代计算机的基本模型都是图灵机我们知道操作数在哪取出来做运算再放回去。X86为例子我们要知道内存操作数的地址这样我们才能在内存和CPU之间来回传递数据。mov eax, ds:0xBAD10000 ; 将地址0xBAD10000装载到eax中 add eax, 0x1 ; 装载值自增 mov ds:0xBAD10000, eax; 写回操作非常好知道这个事情之后我们要指出函数调用的本质也是找到代码段的函数地址——比如说咱们要调用一个平凡的add函数就要告诉我们的call指令add哈桑农户在哪也就说我们要提供add函数入口点的代码段地址add 0x11451400: ... ; Add Procedure main: ... ; Main Procedure call 11451400 ; add absolute当然有的时候我们也会call相对地址这种情况下会方便一点。引用解析中的常见问题我们来看看最简单的情况吧假如说可执行文件是加载单个动态链接库后才能进一步工作的。这些事情是显而易见的客户二进制文件提供进程内存映射中地址范围固定且可以预先确定的部分动态加载完成之后才属于进程中的有效的部分当可执行文件调用了一个或者几个由动态库对外提供的功能实现的时候比如说动态库的接口这个时候才去自然的建立联系上述基本情况我们可以知道一个事情动态库最核心的问题是库代码在运行时的位置是不确定的。无论是 Windows 的 DLLLinux 的 .so还是 macOS 的 dylib它们都有一个共同点动态库无法在编译阶段确定最终的加载地址。为什么呢主要是这几个原因1多个动态库可能发生地址冲突假设两个 .so 都想映射到虚拟内存中的 0x400000 区域这将导致冲突。为了避免冲突操作系统的加载器必须重新选择一个合适的基址。2ASLRAddress Space Layout Randomization现代操作系统会为安全性启用地址随机化动态库每次加载地址都不同。这意味着编译器和链接器不能假设动态库会在固定地址运行。3同一个动态库在不同进程中加载位置不同进程的地址空间彼此独立库在每个进程的加载位置可以完全不同。地址要做转换是解决方案Case: 我们就是要用导出的二进制符号比如说我们就是要用那些导出的符号比如说库提供的——create_windowinit_alldeinit_all等等接口。这就是使用导出的二进制符号这个时候客户程序显然要立马知道加载成功的地址在哪里而不是动态库原始的符号地址他们从0开始偏移呢所以在过去直接由链接器完成所有符号解析的工作显然就显得不可能了。符号地址的确定必须交由加载器一起确定才是。Case自己调用自己的私有符号不管如何有些私有的符号是无法被客户程序找到的但是有一个更加严峻的问题——如果这些符号是被导出的符号在调用这下又该怎么办呢链接器 - 装载器协作——旧技术现在我们来仔细聊聊链接器 - 装载器协作的事情了解了前面描述的所有约束后可以根据以下的规则来建立链接器和装载器之间的协作链接器识别自身符号解析的局限性。链接器精确统计失效的符号引用准备引用修复提示并将提示嵌入二进制文件中。装载器准确遵循链接器的重定位提示并且在完成地址转换后根据这些提示进行修复。链接器识别自身符号解析的局限性在创建一个动态库时链接器除了要明确地分清不同部分代码之间的关系也需要足够准确地识别出将代码段加载到不同的地址范围中时会失效的符号引用。首先与可执行文件不同动态库内存映射的地址范围是从零开始的。链接器处理可执行文件时大多情况下不会将地址范围的起点设置成零。其次在加载阶段前如果链接器发现某些符号的地址无法解析时就会停止解析取而代之会使用临时值填充未解析符号通常会使用明显错误的值比如0之类的数值。但是这并不意味着链接器会完全放弃符号解析任务。相反他只会放弃处理那些真的搞不定的符号。下一步链接器精确统计失效符号引用准备修复提示我们可以完全知道哪些已解析的引用会因装载器地址转换而失效。只要汇编指令需要绝对地址指令中的引用都会失效。在完成动态库构建的链接阶段时链接器可以标识出那些出现绝对地址的地方并通过某些方法让装载器知道这些信息。为了提供链接器-装载器协作支持链接器会为装载器预留一些提示这些提示为装载器指出了如何修复动态加载中由于地址转换引发的错误二进制格式规范支持一些新的节专门用于为这类提示预留空间。此外还设计了特定的简单语法以便于链接器准确指出装载器需要执行的动作。这些节在二进制文件中称为“重定位节”其中.rel.dyn节是最古老的重定位节。通常来说链接器将重定位提示写入二进制文件中以便于装载器读取这些提示。这些提示指定了装载器在完成整个进程的最终内存映射布局后需要修补的地址和装载器为了正确修补未解析引用需要执行的正确动作。装载器准确遵循链接器重定位提示最后一个阶段属于装载器。装载器读取由链接器创建的动态库读取动态库中的装载器段每个段都保存了多个链接器节并将所有数据放置到进程内存映射中存放在最初的可执行文件代码附近。最后装载器定位.rel.dyn节读取链接器预留下的提示并根据这些提示对原来的动态库代码进行修补。完成修补后就可以准备使用内存映射启动进程了。相比于处理基本任务在处理动态库加载时我们需要为装载器提供更多的信息。现代链接器-装载器协作的实现技术PLT/GOTGOT / PLT 的内部机制GOTGlobal Offset Table用于让代码不依赖固定地址而从表中取最终地址。当然这显然要求我们要给咱们的代码施加以-fPIC进行编译现在是否理解了为什么动态库的Step1是使用PIC位置无关了吧现在我们调用就变成了类似call [GOT foo]为此当 foo 的地址被确定后GOT 中的 foo 项被写成实际地址。这样我们就直接更新了PLT 结合 GOT 实现延迟绑定第一次调用函数 → PLT 跳到解析函数 → 更新 GOT→ 直接跳到正确地址 不再解析PLT 的好处加快程序启动速度仅在需要时解析符号延迟绑定Lazy Binding流程详解简单的说延迟绑定指的是直到最后采取真正设置GOT表的地址在那之前会轮询的解析所有的确定符号。call foo → 跳转到 PLT[foo]PLT[foo] 调用解析器 _dl_runtime_resolve解析器在所有动态库中查找符号 foo更新 GOT[foo] foo 的真实地址返回 foo之后的调用直接跳 GO[foo]动态链接时的重复符号 (Duplicate Symbols in Dynamic Linking)在静态链接中如果出现两个同名的全局符号链接器通常会直接报错Multiple Definition Error。但在动态链接的世界里规则却完全不同。这就是为什么值得单独聊聊重复的符号定义 (Duplicate Symbol Definitions)在大型项目中我们经常会链接多个第三方库。假设你的程序链接了 libA.so 和 libB.so巧合的是这两个库的开发者都定义了一个全局函数 void init() 或者一个全局变量 int g_config。当你的主程序启动并加载这两个库时内存中就会存在两个名为 init 的符号。为什么会发生常见的命名使用了过于通用的名称如utils,log,init且没有使用static限制作用域。钻石依赖 (Diamond Dependency)项目依赖库 A 和库 B而 A 和 B 内部都静态链接了同一个基础库 C比如老版本的 OpenSSL。这就导致 C 的符号在 A 和 B 中各有一份副本。头文件实现在头文件中定义了全局变量或非内联函数并被多个.c/.cpp文件包含。重复符号的默认处理Linux 下的动态链接器ld-linux采用了一套特定的规则来处理这种冲突这通常被称为符号介入 (Symbol Interposition)。规则先入为主 (First Match Wins)默认情况下动态链接器使用广度优先搜索 (BFS)的顺序来查找符号。它会按照全局符号表Global Symbol Table中的顺序绑定它找到的第一个匹配符号并忽略后续所有的同名符号。加载顺序决定一切这意味着链接顺序Link Order或加载顺序Load Order决定了程序到底调用了谁的代码。假设app依赖libA和libB且两者都有func()如果链接指令是gcc main.c -lA -lB主程序调用func()时通常会链接到libA的版本。危险的情况如果libB内部的代码调用了func()按照 ELF 的全局符号绑定规则libB也会调用libA的func()这被称为“符号劫持”。libB以为自己在调用自己的代码实际上却跑到了libA里这会导致逻辑错误甚至崩溃。应用场景LD_PRELOAD环境变量正是利用了这一机制。通过预加载一个包含malloc实现的库我们可以覆盖 libc 的标准malloc从而实现内存泄漏检测工具如 Valgrind 或 jemalloc。在动态库链接过程中处理重复符号 (Handling Duplicates)既然默认行为如此危险我们如何在开发动态库时保护自己的符号不被劫持或者不劫持别人1. 链接器参数-Bsymbolic在编译动态库时可以使用链接器参数-Wl,-Bsymbolic。作用强制动态库优先在自身内部解析全局符号引用。效果如果libB编译时加了这个参数那么libB内部调用func()时一定会调用libB自己的版本而不会被libA或主程序覆盖。2. 符号可见性 (Symbol Visibility)这是现代 C 开发的最佳实践。通过 GCC/Clang 的-fvisibilityhidden参数将所有符号默认隐藏只导出需要的接口。代码示例// 只有标记了 DEFAULT 的符号才会被导出到动态符号表 __attribute__((visibility(default))) void public_api(); // 即使是全局函数在外部看来也是不可见的避免冲突 void internal_helper();3.dlopen的作用域控制如果使用dlopen手动加载库可以指定RTLD_LOCAL标志这是默认值。这使得被加载库的符号不会进入全局符号表从而避免影响其他库。说几个经典的自定义内存分配器许多高性能服务如 Redis, MySQL会链接jemalloc或tcmalloc。现象这些库定义了与 Glibc 相同的malloc,free,realloc符号。机制由于它们被显式链接或预加载它们的符号在全局表中排在 Glibc 之前。结果整个进程包括依赖 Glibc 的其他第三方库的所有内存申请都会自动转发给jemalloc。这是一个良性的、有意为之的符号冲突。C STL 版本冲突这是一个恶性的案例。场景主程序使用 GCC 4.8 编译依赖libStdOld.so插件使用 GCC 9.0 编译依赖libStdNew.so。问题std::string或std::vector的内部实现在不同版本中可能不同但它们的符号名称Mangled Name可能通过部分兼容性保持一致或者发生冲突。后果当对象在跨库传递时由于内存布局不同但符号相同程序可能出现未定义行为Undefined Behavior通常表现为莫名其妙的 Segfault。链接并不提供任何类型的命名空间继承 (Tip: No Namespace Inheritance)这个事情要重复下很多人认为“我在 C 代码里把函数放在namespace MyLib { ... }里或者我把代码编译成了libMyLib.so那么这个库就像一个独立的容器里面的变量名count不会和外面冲突。”但是实际上链接器Linker是“符号类型盲Type-blind”和“结构盲”的。我们都知道C 命名空间只是语法糖编译器通过名字修饰Name Mangling将MyLib::foo()变成了字符串_ZN5MyLib3fooEv。对于链接器来说这只是一个长字符串。如果两个库碰巧生成了相同的修饰名Mangled Name冲突依然会发生。而动态库不是命名空间动态库只是文件组织形式。一旦被加载到进程内存所有导出符号Exported Symbols都会进入一个平铺的、扁平的全局符号池Global Symbol Table。libA.so里的全局变量g_context和libB.so里的g_context在链接器眼中就是同一个东西除非你使用了 Visibility 隐藏或 Local 绑定。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

贵阳开发网站建设濮阳创建网站公司

引言:运维的“最后一公里”困境 在云原生和分布式架构席卷IT世界的今天,运维工程师的日常工作却陷入了一种奇特的矛盾:一方面,基础设施的复杂度呈指数级增长,容器、微服务、服务网格等新技术层出不穷;另一方…

张小明 2025/12/30 10:54:17 网站建设

jianshe导航网站已有网站如何做直播

第一章:自主智能体Open-AutoGLM的架构概览Open-AutoGLM 是一个开源的自主智能体框架,专为实现复杂任务的自动化决策与执行而设计。其核心架构融合了大语言模型(LLM)、任务规划引擎、工具调用机制与记忆管理系统,支持在…

张小明 2025/12/30 10:53:42 网站建设

四川网站建设seo网站更多分享怎么做

还在为MacBook触控板缺少中键功能而烦恼吗?MiddleClick-Sonoma这款革命性的开源工具通过创新的三指点击手势,彻底改变了macOS系统的操作体验。无论你是日常浏览网页还是专业开发工作,这款免费工具都能让你的触控板发挥出前所未有的潜力。 【免…

张小明 2025/12/30 10:53:09 网站建设

长沙建站智能模板岳阳网站建设 熊掌号

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个java17新特性应用,利用快马平台的AI辅助功能,展示智能代码生成和优化。点击项目生成按钮,等待项目生成完整后预览效果 最近Java17的发布…

张小明 2025/12/30 10:52:36 网站建设

有做翻译英文网站免费ppt模板下载哪个网站好

第一章:工业控制 Agent 的实时响应在现代工业自动化系统中,工业控制 Agent 必须具备毫秒级的实时响应能力,以确保生产流程的稳定性与安全性。这类 Agent 通常部署在边缘计算节点上,直接与 PLC、传感器和执行器通信,承担…

张小明 2025/12/30 10:51:26 网站建设

湘潭网站seowordpress视频播放器m3u8

论文辅导可以让你在完成论文时候少走冤枉路,但是,如果找不到合适的辅导机构,就会增大论文写作的难度,也会让自己的职称评定因此被耽误,那么,论文辅导机构排行榜是怎样的?TOP机构有哪些呢&#x…

张小明 2025/12/30 10:50:51 网站建设