LD_PRELOAD和ld --wrap
前言
LD_PRELOAD和ld --wrap都能实现不修改原始代码,替换指定函数的实现。通常我们会使用这些方法,替换如malloc)()/free()、read()/write()等函数,并在替换函数中做一些记录,以便能分析程序执行时的内存分配和IO情况。这些函数一般叫包裹函数。
LD_PRELAD
链接器会检查LD_PRELOAD这个环境变量,如果不为空,则优先使用LD_PRELOAD指定的动态库中的符号,以malloc()/free()为例。
代码清单 main.c
int main()
{
malloc(10);
return 0;
}
代码清单 my.c
void* malloc(size_t size)
{
void (*__real_malloc)(int) = NULL;
// 获取真实的malloc()地址
__real_malloc = dlsym(RTLD_NEXT, "malloc");
void* ptr = __real_malloc(size);
printf("[malloc] addr=%p, size=%u\n", ret, size);
return ptr;
}
void free(void* ptr)
{
printf("[free] addr=%p", ptr);
void (*__real_free)(void*) = NULL;
__real_free = dlsym(RTLD_NEXT, "free");
return __real_free(ptr);
}
gcc main.c -o test
将main.c编译成test
,gcc -fPIC -shared my.c -o libmy.so
my.c编译成libmy.so
。
export LD_PRELOAD=./libmy.so
后执行test
会发现,main()
中执行的malloc()
实际是libmy.so
中的malloc()
,其会输出分配的内存地址和大小。因为没有free的输出,所以我们可以得知test存在内存泄漏。这是一个很简陋的例子。
export使得LD_PRELOAD对所有该终端执行的程序都生效,不使用时还需要unset LD_PRELOAD
,我们可以通过LD_PRELOAD=./libmy.so ./test
使得其只对test生效。
LD_PRELOAD的本质是先加载的先使用。就像我们在编译时会发现如果两个库中有同名函数,那么哪个库在前,就用哪个库中的函数。
ld --wrap
ld --wrap是一个编译链接时的参数,其原理是在编译时将--wrap指定的函数名进行替换,其替换规则就是替换规则就是包裹函数前加__wrap_
,真实函数前加__real_
,比如gcc main.c -o test -Wl,--wrap=malloc
,编译器会将调用malloc()
的地方替换为__wrap_malloc()
,并将__real_malloc()
符号名映射到真实malloc()的地址。
此时my.c的实现就不一样了,我们需要提供__wrap_malloc()
,并在真正需要调用malloc()
的地方使用__real_malloc()
。
void* __wrap_malloc(size_t size)
{
void* ptr = __real_malloc(size);
printf("[malloc] addr=%p, size=%u\n", ret, size);
return ptr;
}
void __wrap_free(void* ptr)
{
printf("[free] addr=%p", ptr);
return __real_free(ptr);
}
如果有比较多的--wrap,那么可以将其放在一个文件中,假设文件名为ld-opt,其内容如下
--wrap=malloc
--wrap=free
使用gcc main.c -o test -Wl,@ld-opt
就能替换malloc和free了。
ld --wrap的本质是按指定规则替换符号名(malloc->__wrap_malloc),并将特定符号与执行代码关联(__real_malloc->maloc代码)。
LD_PRELOAD和ld --wrap的更多相关文章
- Linux下的库操作工具-nm、ar、ldd、ldconfig和ld.so
Linux下的库操作工具-nm.ar.ldd.ldconfig和ld.so .nm [options] file 列出file中的所有符号 [option] -c 将符号转化为用户级的名字 -s 当用 ...
- CSAPP CH7链接的应用:静动态库制作与神奇的库打桩机制
目录 创建静态库 创建动态库 库打桩机制 编译时打桩: 链接时打桩 运行时打桩 运行时打桩的printf与malloc循环调用debug 使用LD_PRELOAD对任意可执行程序调用运行时打桩 总结 ...
- How to install 64-bit Google Chrome 28+ on 64-bit RHEL/CentOS 6 or 7
How to install 64-bit Google Chrome 28+ on 64-bit RHEL/CentOS 6 or 7 The problem Google developers s ...
- ERROR: ld.so: object '/usr/lib64/libtcmalloc.so.4' from LD_PRELOAD cannot be preloaded: ignored
出现错误: ERROR: ld.so: object '/usr/lib64/libtcmalloc.so.4' from LD_PRELOAD cannot be preloaded: ignore ...
- Linux Dynamic Shared Library && LD Linker
目录 . 动态链接的意义 . 地址无关代码: PIC . 延迟版定(PLT Procedure Linkage Table) . 动态链接相关结构 . 动态链接的步骤和实现 . Linux动态链接器实 ...
- gcc ld 链接器相关知识,调试指令(程序员的自我修养----链接、装载与库)
最近解决一个动态链接上的问题,因为以前从来没有接触过这方面的知识,所以恶补了一下,首先要了解gcc编译指令(makefile),ld链接器的选项(还有连接脚本section指定内存位置),熟悉查看连接 ...
- 【Linux】LD_PRELOAD用法
转载https://blog.csdn.net/iEearth/article/details/49952047 还有一篇博客也可以看看https://blog.csdn.net/xp5xp6/art ...
- LD_PRELOAD & LD_LIBRARY_PATH 动态库路径
参考:http://www.cnblogs.com/waterlin/archive/2011/07/14/2106056.html 143上的glibc较低,同学又不能进行升级(造成全局影响),所以 ...
- 使用LD_Preload的Linux权限升级技巧
0x00 前言 共享库是程序在启动时加载的库.正确安装共享库后,之后启动的所有程序将自动使用新的共享库. 0x01 共享库名称 每个共享库都有一个名为soname的特殊名称.soname有前缀li ...
随机推荐
- java学习笔记(基础篇)—变量与表达式
一:局部变量和实例变量 定义变量是指设定变量的数据类型和变量的名字,Java语言要求变量遵循先定义,再初始化,然后使用的规则. 作用域:指它的存在范围,只有在这个范围内,程序代码才能访问它. 变量的生 ...
- [原创]lvs+ospf+nginx实现高可用大流量web架构
lvs+ospf+nginx实现高可用大流量web架构配置总概述 架构图: 配置如下: .quagga之zebra配置: # cat /etc/quagga/zebra.conf ! ! Zebra ...
- MongoDB基础教程[菜鸟教程整理]
MongoDB基础教程 ======================================================================================== ...
- error: 'commit' is not possible because you have unmerged files.
解决方案: 1.把修改的文件add下,如:git add bidder_mod/src/common/dragon_bidder_data.cc2.git commit
- Excel导出功能超时解决方案 -- 异步处理
背景 有运营同学反馈,最近导出excel会出现超时的情况,初步判断是数据增长太快,数据量太大,请求时间超过了设置的超时时间 尝试 有考虑直接更改该请求的超时时长,可是治标不治本 网上搜索发现,有很多人 ...
- Linux卸载MySql——ubuntu版
卸载mysql 1)删除mysql的数据文件 sudo rm /var/lib/mysql/ -R 2)删除mqsql的配置文件 sudo rm /etc/mysql/ -R 3)自动卸载mysql的 ...
- (原创)将Datatable数据按照Excel模板格式导出
最近遇到一个问题,就是导出数据的时候需要自定义的表头,如图 如果自己用代码写表头的话,可能会有点复杂,而且代码量很多,所以我就想了一个办法,直接在Excel里面把表头定义好,然后把数据写入Excel模 ...
- 算法-一步步教你如何用c语言实现堆排序(非递归)
看了左神的堆排序,觉得思路很清晰,比常见的递归的堆排序要更容易理解,所以自己整理了一下笔记,带大家一步步实现堆排序算法 首先介绍什么是大根堆:每一个子树的最大值都是子树的头结点,即根结点是所有结点的最 ...
- jsp数据交互(二).3
01.Application原理与应用 01.application对象的作用域范围是整个应用服务,而它在应用中所承担的责任就类似于一个全局变量.只要服务启动,则application对象就会存在. ...
- Divide and Conquer
1 2 218 The Skyline Problem 最大堆 遍历节点 public List<int[]> getSkyline(int[][] buildings) { ...