前言

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编译成testgcc -fPIC -shared my.c -o libmy.somy.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的更多相关文章

  1. Linux下的库操作工具-nm、ar、ldd、ldconfig和ld.so

    Linux下的库操作工具-nm.ar.ldd.ldconfig和ld.so .nm [options] file 列出file中的所有符号 [option] -c 将符号转化为用户级的名字 -s 当用 ...

  2. CSAPP CH7链接的应用:静动态库制作与神奇的库打桩机制

    目录 创建静态库 创建动态库 库打桩机制 编译时打桩: 链接时打桩 运行时打桩 运行时打桩的printf与malloc循环调用debug 使用LD_PRELOAD对任意可执行程序调用运行时打桩 总结 ...

  3. 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 ...

  4. 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 ...

  5. Linux Dynamic Shared Library && LD Linker

    目录 . 动态链接的意义 . 地址无关代码: PIC . 延迟版定(PLT Procedure Linkage Table) . 动态链接相关结构 . 动态链接的步骤和实现 . Linux动态链接器实 ...

  6. gcc ld 链接器相关知识,调试指令(程序员的自我修养----链接、装载与库)

    最近解决一个动态链接上的问题,因为以前从来没有接触过这方面的知识,所以恶补了一下,首先要了解gcc编译指令(makefile),ld链接器的选项(还有连接脚本section指定内存位置),熟悉查看连接 ...

  7. 【Linux】LD_PRELOAD用法

    转载https://blog.csdn.net/iEearth/article/details/49952047 还有一篇博客也可以看看https://blog.csdn.net/xp5xp6/art ...

  8. LD_PRELOAD & LD_LIBRARY_PATH 动态库路径

    参考:http://www.cnblogs.com/waterlin/archive/2011/07/14/2106056.html 143上的glibc较低,同学又不能进行升级(造成全局影响),所以 ...

  9. 使用LD_Preload的Linux权限升级技巧

      0x00 前言 共享库是程序在启动时加载的库.正确安装共享库后,之后启动的所有程序将自动使用新的共享库. 0x01 共享库名称 每个共享库都有一个名为soname的特殊名称.soname有前缀li ...

随机推荐

  1. python连接greenplum_postgresql

    1. 场景描述 使用python连接greenplum或者postgresql. 2. 解决方案 2.1 真实代码 2.1.1 调用类 import dbgp as dbgp # 执行 def exe ...

  2. MPP install

    greenplum install 注意事项:1.hostname 不能大写##2.如果segment和mirror副本数比较大,建议调整/etc/ssh/sshd_config的maxconnect ...

  3. VUE+element tree 实现权限管理

    先写个标题~ ~,后续有空在写 具体功能: 1. 获取所有角色权限列表展示,点击进行编辑,编辑用terr树形结构显示页面结构 2.提交的数据格式(页面名称,角色ID,父节点ID,子节点ID) 3.后面 ...

  4. 简单函数编写_strcpy、_stroverchg、_strcmp

    字符串复制函数 void _strcpy(char *tar, const char * res) { char *p = tar; while(assert(tar && res), ...

  5. C# 针对特定的条件进行锁操作,不用lock,而是mutex

    背景:用户领取优惠券,同一个用户需要加锁验证是否已经领取,不同用户则可以同时领取. 上代码示例: 1.创建Person类 /// <summary> /// Person类 /// < ...

  6. hadoop之安装hadoop

    官网 http://hadoop.apache.org/ 下载页:https://hadoop.apache.org/releases.html 上传安装包到Linux 解压并进入到目录下 [root ...

  7. python 中多个装饰器的执行顺序

    python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...

  8. 小白学python-day06-

    今天是day06,以下是学习内容总结: 但行努力,莫问前程. --------------------------------------------------------------------- ...

  9. PHP -- 数据库访问

    一.过时方法(PHP5以前的版本用的):用函数链接数据库,相当于面向过程的方式 //设置页面编码格式 header("content-type:text/html;charset=utf-8 ...

  10. HPU暑期集训积分赛1

    A. Nth power of n 单点时限: 1.0 sec 内存限制: 512 MB 求 nn 的个位数. 输入格式 多组输入,处理到文件结束.每组数据输入一个 n.(1≤n≤109) 输出格式 ...