0%

动态库编译原理

操作系统基础

操作系统存在多任务机制,多个任务存在某些共享资源,由此引出共享库的设计

操作系统存在复杂的缓存策略

操作系统使用虚拟内存保证物理内存与程序内存不是一一对应

程序使用虚拟地址完成寻址,软件开发过程不必关注物理内存

程序虚拟内存划分方案:

​ 内核段代码与数据

​ 栈:函数调用数据

​ 动态库段

​ 堆:动态分配内存

​ 数据段:初始化数据(.data)、未初始化数据(.bss)、只读数据(.rdata)

​ 程序代码段:启动程序、main函数、其它函数、静态库函数

程序编译阶段

编译基本流程

编译:预处理、编译(词法分析、语法分析、语义分析、代码精简与优化、翻译成汇编代码)、汇编成二进制目标文件、链接多个目标文件生成可执行文件

目标文件结构

每个源码文件对应一个目标文件

由地址符号与段组成

​ 地址符号包括导出符号、局部符号、外部调用符号

​ 段包括代码段、数据段、调试信息、动态链接信息等

链接时会将多个目标文件的代码段数据段合并到最终的一个代码段一个数据段

程序的堆、栈等内存是运行时确定,与目标文件无关

未初始化数据段(.bss)只有字节长度信息,内存分配在程序启动时确定

可以使用objdump查看目标文件反汇编内容与分段信息

链接

对多个目标文件完成各种段的拼接

将每个目标文件内部的局部地址符号转换为程序整体的局部地址

完成外部调用符号的查找

启动基本流程

操作系统创建程序内存空间

将链接得到的各种段的信息加载到程序虚拟内存

操作系统通过libc标准库找到程序main函数

目标文件复用

静态库

将目标文件封装打包成一个单独的文件,链接时会将静态库拷贝到可执行文件中

动态库

如果多个程序使用了同一个目标文件,那么这个目标文件的代码段理论上没有必要拷贝到每一个程序中,代码段是可以复用的。

动态库本质与可执行程序结构类似,包括数据段、代码段、调试段、导出符号、外部调用符号等,但不包含启动程序

程序可以在链接时查找动态库符号,但是只有程序执行且调用到动态库的函数时,操作系统才会完成动态库的加载

程序在启动时会检查动态库是否存在,检查动态库的导出符号是否满足程序的外部符号调用依赖

程序运行时会将动态库的数据段拷贝到程序动态库段中,将程序的外部调用符号指向动态库的导出符号

动态库也可以链接其它库

动态库符号导出分析

exe文件分析

在微软官网下载WinDbg

进入 cmd 输入 WinDbgx,点击文件 -> lanunch executable -> 在命令窗口输入.childdbg 1绑定可执行程序的子进程 -> 点击左上角的go -> 开始调试

dll文件

进入Developer Command Prompt for VS 2019

输入dumpbin /exports Name.dll 查看符号表

输入dumpbin /dependents Name.dll 查看依赖项

so文件

nm命令:查看符号表

readelf:查看elf或so文件基本信息,包括依赖库。命令参数

LD_DEBUG环境变量:可以让动态链接器在运行时输出详细的加载信息,包括尝试加载的库的名称、路径以及成功或失败的信息。

ldd命令:查看动态依赖库

QNX命令目录

qnx710\host\win64\x86_64\usr\bin\ntoaarch64-readelf

echo $LD_LIBRARY_PATH 查看so库查找路径

export LD_LIBRARY_PATH=/nfs_share/POC_QNX: 设置so库查找路径

export LD_LIBRARY_PATH=/nfs_share/TestHmiLogic_QNX:/ifs/lib64/:/ifs/usr/lib64:/ifs/lib64/dll:/ifs/lib/:/ifs/usr/lib:/ifs/lib64/dll/pci:/mnt/lib64/:/mnt/usr/lib64:/mnt/lib64/dll:/mnt/lib/:/mnt/usr/lib:/mnt/lib64/dll/pci:/mnt/lib64/camera:/ifs/lib64/camera:

WinDbg用法

绑定子进程 .childdbg 1

查看进程 |

切换到指定进程 |[id] s

查找符号 x ModuleName!Class*

添加断点 bu ModuleName!ClassFunction

添加断点 文件窗口类似vs直接添加即可