文章目录

  • 1.前言
  • 2. 测试环境
  • 3.编译时打桩
    • 3.1.相关文件
      • 3.1.1.main.c
      • 3.1.2.newcalloc.h
      • 3.1.3.newcalloc.c
    • 3.2.编译命令
    • 3.3.运行情况和运行命令
    • 3.4.说明
  • 4.编译时打桩
    • 4.1.相关文件
      • 4.1.1.main.c
      • 4.1.2.newcalloc.c
    • 4.2.编译命令和运行命令
    • 4.3.运行情况
    • 4.4.说明
  • 5. 运行时打桩
    • 5.1.相关文件
      • 5.1.1.main.c
      • 5.1.2.newcalloc.c
    • 5.2.编译命令和运行命令
    • 5.3.运行情况
    • 5.4.说明
  • 6. 参考资料

1.前言

库打桩技术,可以截获对共享库函数的调用。应用上可以如可以控制函数调用的输入输出值,以自己的逻辑替换函数调用等;
基本思想:创建一个与目标函数相同原型的包装函数,通过编译时函数实现的搜索机制、或链接时函数符号解析搜索的机制、或运行时动态链接库的加载机制,将自定义的包装函数替换目标函数。

2. 测试环境

系统环境:Ubuntu14.04
Gcc版本:gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)

3.编译时打桩

3.1.相关文件

3.1.1.main.c

#include <stdio.h>
#include <malloc.h>
int main()
{size_t len = 10;char * msg =  calloc(1,len);snprintf( msg,len,"%s","aloha");printf("msg:%s\n",msg);free(msg);msg = 0;return 0;
}

3.1.2.newcalloc.h

#define  calloc(nmemb,size) newcalloc(nmemb,size)
#define free(ptr)   newfree(ptr)void *newcalloc(size_t nmemb, size_t size);
void newfree(void *ptr);

3.1.3.newcalloc.c

#include <stdio.h>
#include <malloc.h>void *newcalloc(size_t nmemb, size_t size){static int _newcalloc_calltime = 0;++_newcalloc_calltime;printf("calloc ptr(%d,%d) ,call times=%d\n",nmemb,size,_newcalloc_calltime);void * ptr = calloc( nmemb,size);printf("calloc return=%p\n",ptr);return ptr;}void newfree(void *ptr){static int _newfree_calltime = 0;++_newfree_calltime;free(ptr);printf("free(%p),call times =%d\n",ptr,_newfree_calltime);}

3.2.编译命令

gcc -m32 -g -c newcalloc.c;
gcc -m32 -g -I. -o main main.c newcalloc.o;
./main
备注 :从测试情况看,这里不指定-I编译选项,也能按期望运行,即main.c中即使以尖括号方式include了,也是从当前目录先搜索。

3.3.运行情况和运行命令

calloc ptr(1,10) ,call times=1
calloc return=0x8734008
msg:aloha
free(0x8734008),call times =1

3.4.说明

1、编译时打桩,需要能访问源代码,本质上就是先定义自己的包装函数,在包装函数中进行调用标准的目标方法,并生成可重定位的文件。再定义一个通过宏定义方式转换的头文件(名称同需要打桩的函数所在的头文件),gcc编译时优先从本地搜索该同名头文件而调用了包装函数;
2、这里的一个注意点,对于包装文件newcalloc.c的编译需要单独编译,不能与宏定义转换的头文件放在同一个目录下进行编译,否则会变成循环嵌套递归调用,最终导致程序异常。

4.编译时打桩

4.1.相关文件

4.1.1.main.c

#include <stdio.h>
#include <malloc.h>
int main()
{size_t len = 10;char * msg =  calloc(1,len);snprintf( msg,len,"%s","aloha");printf("msg:%s\n",msg);free(msg);msg = 0;return 0;
}

4.1.2.newcalloc.c

#include <stdio.h>
//#include <stdlib.h> void * __real_calloc(size_t nmemb, size_t size);void __real_free(void *ptr);void * __wrap_calloc(size_t nmemb, size_t size){static int _newcalloc_calltime = 0;++_newcalloc_calltime;printf("calloc ptr(%d,%d) ,call times=%d\n",nmemb,size,_newcalloc_calltime);void * ptr = __real_calloc( nmemb,size);printf("calloc return=%p\n",ptr);return ptr;}void __wrap_free(void *ptr){static int _newfree_calltime = 0;++_newfree_calltime;__real_free(ptr);printf("free(%p),call times =%d\n",ptr,_newfree_calltime);}

4.2.编译命令和运行命令

gcc -m32 -g -c newcalloc.c;
gcc -m32 -g -c main.c;
gcc -m32 -Wl,–wrap,calloc -Wl,–wrap,free -o main main.o newcalloc.o;
./main

4.3.运行情况

calloc ptr(1,10) ,call times=1
calloc return=0x840b008
msg:aloha
free(0x840b008),call times =1

4.4.说明

1、编译时打桩,需要能访问可重定位的目标文件;
2、静态链接器支持使用–wrap f选项进行打桩,即把对符号f的引用解析成__wrap_f,并对符号__real_f的引用解析成f。

5. 运行时打桩

5.1.相关文件

5.1.1.main.c

#include <stdio.h>
#include <malloc.h>
int main()
{size_t len = 10;char * msg =  calloc(1,len);snprintf( msg,len,"%s","aloha");printf("msg:%s\n",msg);free(msg);msg = 0;return 0;
}

5.1.2.newcalloc.c

#include <stdio.h>
#include <stdlib.h>  #define __USE_GNU
#include <dlfcn.h>//#define _GNU_SOURCEvoid * calloc(size_t nmemb, size_t size){void * (*callocp)(size_t nmemb, size_t size);char * error;callocp = dlsym(RTLD_NEXT,"calloc");if((error=dlerror())!=NULL){printf("dlsym calloc error,msg:%s\n",error);exit(1);}static int _newcalloc_calltime = 0;++_newcalloc_calltime;printf("calloc ptr(%d,%d) ,call times=%d\n",nmemb,size,_newcalloc_calltime);void * ptr = callocp( nmemb,size);printf("calloc return=%p\n",ptr);return ptr;}void free(void *ptr){void (*freep)(void *ptr);char * error;freep = dlsym(RTLD_NEXT,"free");static int _newfree_calltime = 0;++_newfree_calltime;freep(ptr);printf("free(%p),call times =%d\n",ptr,_newfree_calltime);}

5.2.编译命令和运行命令

gcc -m32 -g -shared -fpic -o newcalloc.so newcalloc.c -ldl;
gcc -m32 -g -o main main.c;
LD_PRELOAD="./newcalloc.so" ./main

5.3.运行情况

calloc ptr(1,10) ,call times=1
calloc return=0x8fb5008
msg:aloha
free(0x8fb5008),call times =1

5.4.说明

1、此机制基于动态链接器的LD_RELOAD环境变量。当加载和执行一个程序,需要解析未定义的引用时,动态链接器(LD-LINUX.SO)会先搜索LD_PRELOAD库,如果没有搜索到 ,则再搜索其他库。
2、中宏定义_GNU_SOURCE不能工作,查看dlfcn.h文件,需要使用__USE_GNU(#include <dlfcn.h>前面定义)

6. 参考资料

《深入理解计算机系统》中文版,[美]Randal E.Bryant等著,2019.3,机械工业出版社

Linux C 库打桩技术相关推荐

  1. linux程序打桩,一文搞懂linux的库打桩

    Linux下的链接器支持一个强大的库打桩(library interpositioning),允许你阻拦对系统标准库中某个目标函数的调用,取而代之执行自己的包装函数.它可以给我们带来两个好处,一是通过 ...

  2. Linux 程序开发 之 库打桩机制

    目录 前言 一.库打桩定义 二.编译时打桩 三.链接时打桩 四.运行时打桩 五.处理目标文件的工具 前言   Linux 链接器支持一个很强大的技术,称为库打桩(library interpositi ...

  3. Linux下的LD_PRELOAD环境变量与库打桩

    Linux下的LD_PRELOAD环境变量与库打桩 LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的 ...

  4. Linux 库打桩机制

    库打桩机制 Linux 链接器截获对共享库函数调用,转而执行自己的代码. 创建一个包装函数,对库函数进行包装(装饰器模式).利用打桩机制欺骗系统去调用包装函数. 编译时打桩 // malloc.c / ...

  5. 分析Windows和Linux动态库

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...

  6. Linux动态库应用

    Linux动态库应用 Linux动态库应用 简介: 动态库调用方式一 动态库调用方式二 简介: 动态库在编程过程中是一个很重要的技术,在实际开发过程中,我们在设计各模块时,常常会用到一些通用的功能,如 ...

  7. Linux 动态库和静态库

    From:http://blog.csdn.net/u010977122/article/details/52958330 From:http://blog.163.com/xychenbaihu@y ...

  8. Windows和Linux动态库比较 (Zhuan)

    Windows和Linux动态库比较 Description: 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库 可以有效的减少程序大小,节 ...

  9. Linux共享库概述

    Linux共享库概述 共享库是一种将库函数打包成一个单元使之能够在运行时被多个进程共享的技术.这种技术能够节省磁盘空间和RAM. 在继续阐述共享库之前,先来说说静态库,它是比共享库更早的存在.静态库也 ...

最新文章

  1. PyCharm 使用技巧
  2. linux 隐藏权限,Linux权限位,s权限,t权限,及隐藏权限
  3. 未来十年有望改变世界的五大发现
  4. java任何封闭实例都不是java_《java并发编程实战》读书笔记3--对象的组合
  5. python编程从入门到精通 叶维忠 pdf-零基础如何学习python?十本精品python书籍推荐...
  6. 有趣的css图形实现
  7. 笔记_SQLite入门
  8. 数据结构课程设计------c实现散列表(二次探测再哈希)电话簿(文件存储)
  9. java函数和构造函数_JAVA的构造器和C++的构造函数有什么区别?
  10. 【SpringBoot基础知识】如何在springboot中使用多线程
  11. lua.c:82:10: fatal error: readline/readline.h: 没有那个文件或目录
  12. Unity3D数学工具(Mathf)
  13. 英雄联盟数据分析专题(一)
  14. windows替换鼠标指针
  15. 【APT】The following signatures were invalid
  16. [WARNING IsDockerSystemdCheck]: detected “cgroupfs“ as the Docker cgroup driver. The recommended dri
  17. node.js+uniapp计算机毕业设计安卓在线民宿预定app(程序+APP+LW)
  18. 小程序引入的echarts过大如何解决_在微信小程序中使用 ECharts
  19. html相册代码大全
  20. CUDA计算能力显卡对照表

热门文章

  1. 微信公众号对接淘宝客系统,淘口令解析
  2. 梁漱溟:思考问题的八层境界
  3. python笛卡尔心脏线绘制_python 笛卡尔
  4. LQ0018 顺子日期【枚举+日期】
  5. 京峰教育Linux笔记
  6. C# 字符串操作--减少垃圾回收压力
  7. Paper reading (四十四): Machine learning methods for metabolic pathway prediction
  8. 芯片封装的作用以及常见封装技术
  9. Encyclopaedia Britannica Ultimate 2014电子版下载|大不列颠百科全书
  10. 如何使用 WordPress 创建和销售在线课程