当前位置: 首页 > news >正文

【深入理解计算机系统】库打桩 - 阅读笔记

文章目录

  • 库打桩机制
    • 1. 编译时打桩
    • 2. 链接时打桩
    • 3. 运行时打桩

库打桩机制

 Linux 链接器支持一个很强大的技术,称为库打桩 (library interpositioning),它允许你截获对共享库函数的调用,取而代之执行自己的代码。使用打桩机制,你可以追踪对某个特殊库函数的调用次数,验证和追踪它的输入和输出值,或者甚至把它替换成一个完全不同的实现。

 下面是它的基本思想:给定一个需要打桩的目标函数,创建一个包装函数,它的原型与目标函数完全一样。使用某种特殊的打桩机制,你就可以欺骗系统调用包装函数而不是目标函数了。包装函数通常会执行它自己的逻辑,然后调用目标函数,再将目标函数的返回值传递给调用者。

 打桩可以发生在编译时链接时或当程序被加载和执行的运行时

需求: 我们需要在主程序main.c中跟踪对库函数malloc和free的使用情况。(下面3种打桩以这个为例子)

1. 编译时打桩

 编译时打桩的本质就是借助#define预处理指令,让预处理器在预处理阶段帮助我们替换malloc为我们自己实现的mymalloc,这就是编译时打桩。

• mymalloc.c

 建立mymalloc.c文件, 定义需要的包装函数mymalloc和myfree。

#ifdef COMPILETIME
#include <stdio.h>
#include <malloc.h>//定义malloc 包装函数
void *mymalloc(size_t size)
{void *ptr = malloc(size);printf("my_malloc:%d=%p\n", (int)size, ptr);return ptr;
}//定义free 包装函数
void *myfree(void *ptr)
{free(ptr);printf("my_free:%p\n",  ptr);
}#endif

• malloc.h

 该文件向预处理器指明用mymalloc.c中的包装函数替换库里的目标函数。

#define malloc(size)  mymalloc(size)
#define free(ptr)        myfree(ptr)void *mymalloc(size_t size);
void *myfree(void *ptr);

• main.c

#include <stdio.h>
#include <malloc.h>int main()
{int *p = malloc(32);free(p);return 0;
}

编译指令:

gcc -DCOMPILETIME -c mymalloc.c
gcc -I. main.c mymalloc.o -o main

-D选项: 指定宏参数,设置COMPILETIME宏。
-I.选项: 指示C预处理器在搜索通常的系统目录前,先在当前目录中查找malloc.h

运行程序可得到下面的结果:

[wqj@VM-0-15-centos compile]$ ./main 
my_malloc:32=0xfb8010
my_free:0xfb8010

2. 链接时打桩

 Linux的静态连接器支持使用--wrap f标志进行链接时打桩。这个标志告诉链接器,请把符号f的引用解析为__wrap_f,并且将对符号__real_f的引用解析为f

举个栗子:

--wrap malloc <==> 将符号malloc的引用解析为__wrap_malloc,将__real_f的引用解析为malloc

 这就使得,用户在使用malloc接口时,malloc的引用被解析为了__wrap_malloc,因此程序会去调用__wrap_malloc。在__wrap_malloc中,我们可以再去调用__real_malloc方法,此时就会真正的去调用malloc方法。而我们也可以在__wrap_malloc方法中添加或修改一些额外的信息。(当然也可以完全实现一个自己的方法,不去调用__real_malloc)

注意: 在Linux指令当中,我们使用的是下面的形式的:

linux> gcc -Wl,--wrap,malloc -Wl,--wrap,free -o main main.o mymalloc.o

 这里的--wrap,malloc中的,会被翻译为空格。每一个函数的替换单位就是-Wl,--wrap,f


• mymalloc.c

#ifdef LINKTIME    
#include <stdio.h>    void* __real_malloc(size_t size);    
void  __real_free(void* ptr);    void* __wrap_malloc(size_t size)    
{    void* ptr = __real_malloc(size);  //call libc's malloc    printf("mymalloc:%d=%p\n", (int)size, ptr);    return ptr;    
}    void __wrap_free(void* ptr)                                                                                                                                                                                      
{    __real_free(ptr); //call libc's free    printf("myfree:%p\n", ptr);    
}    
#endif

main.c文件同1.编译时打桩的main.c

编译指令:

gcc -DLINKTIME -c mymalloc.c
gcc -c main.c
gcc -Wl,--wrap,malloc -Wl,--wrap,free -o main main.o mymalloc.o

-Wl,option 标志把 option 传递给链接器。option 中的每个逗号都要替换为一个空格。所以 -Wl,--wrap,malloc 就把 --wrap malloc 传递给链接器,以类似的方式传递 -Wl,--wrap,free

运行结果:

[wqj@VM-0-15-centos link]$ ./main
mymalloc:32=0x1fee010
myfree:0x1fee010

3. 运行时打桩

 运行时打桩主要依靠动态链接器的LD_PRELOAD环境变量。如果LD_PRELOAD环境变量被设置为一个动态库的路径名的列表(以空格或分隔间隔的列表, 一个元素也可以),那么当你加载和执行一个程序,需要解析未定义的引用时,动态链接器会优先搜索LD_PRELOAD,然后才会去搜索其它的库。

 有了上面这个机制,当你加载和执行任意的可执行文件时,可以对任何动态库的任何函数打桩,包括libc.so

• mymalloc.c

#ifdef RUNTIME    
#define _GNU_SOURCE //定义GUN宏,允许你使用一些被限制的特性(feature)    
#include <stdio.h>    
#include <stdlib.h>    
#include <dlfcn.h>    //malloc wrapper function    
void* malloc(size_t size)    
{    void* (*malloc_ptr)(size_t size);    char* error;    malloc_ptr = dlsym(RTLD_NEXT, "malloc");  //Get Address of libc malloc    if((error = dlerror()) != NULL){    fprintf(stderr, "%s\n", error);    exit(1);    }    void* ptr = malloc_ptr(size);    printf("my_malloc:%d=%p\n",(int)size, ptr);    return ptr;    
}    //free wrapper function    
void free(void* ptr)    
{    void (*free_ptr)(void*) = NULL;    char* error;    if(!ptr){    return;    }    free_ptr = dlsym(RTLD_NEXT, "free");  //Get Address of libc free    if((error = dlerror()) != NULL){    fprintf(stderr, "%s\n", error);    exit(2);    }    free_ptr(ptr);    printf("my_free:%p\n", ptr);    
}    
#endif

main.c文件同1.编译时打桩的main.c

编译指令:

gcc -DRUNTIME -shared -fPIC mymalloc.c -o libmymalloc.so -ldl
gcc main.c -o main

运行指令:

[wqj@VM-0-15-centos running]$ LD_PRELOAD="./libmymalloc.so" ./main
my_malloc:32=0x1d85010
my_free:0x1d85010

或者

[wqj@VM-0-15-centos running]$ (setenv LD_PRELOAD "./libmymalloc.so"; ./main; unsetenv LD_PRELOAD)
my_malloc:32=0x1d85010
my_free:0x1d85010

 上面的那种是设置本地变量LD_PRELOAD,下面的则是设置环境变量LD_PRELOAD。本地变量与环境变量的区别见Linux详解 — 进程管理2 (进程状态、环境变量与命令行参数)

相关文章:

【深入理解计算机系统】库打桩 - 阅读笔记

文章目录库打桩机制1. 编译时打桩2. 链接时打桩3. 运行时打桩库打桩机制 Linux 链接器支持一个很强大的技术&#xff0c;称为库打桩 (library interpositioning)&#xff0c;它允许你截获对共享库函数的调用&#xff0c;取而代之执行自己的代码。使用打桩机制&#xff0c;你可以…...

RocketMQ高性能原理分析

目录一、读队列与写队列1.概念介绍2.读写队列个数关系分析二、消息持久化1.持久化文件介绍2.持久化结构介绍&#xff1a;三、过期文件删除1.如何判断文件过期2.什么时候删除过期文件四、高效文件写1.零拷贝技术加速文件读写2.文件顺序写3.刷盘机制五、 消息主从复制六、负载均衡…...

前端面试当中CDN会问啥------CDN详细教程来啦

⼀、CDN 1. CDN的概念 CDN&#xff08;Content Delivery Network&#xff0c;内容分发⽹络&#xff09;是指⼀种通过互联⽹互相连接的电脑⽹络系统&#xff0c;利 ⽤最靠近每位⽤户的服务器&#xff0c;更快、更可靠地将⾳乐、图⽚、视频、应⽤程序及其他⽂件发送给⽤户&…...

刷题记录:牛客NC19429红球进黑洞 区间拆位异或+区间求和

传送门:牛客 题目描述: 区间求和区间异或k 输入: 10 10 8 5 8 9 3 9 8 3 3 6 2 1 4 1 1 2 6 2 9 10 8 1 1 7 2 4 7 8 2 8 8 6 2 2 3 0 1 1 2 2 9 10 4 1 2 3 输出: 33 50 13 13一道区间求和区间异或的题目,可以称得上是线段树的一道好题 首先对于异或运算来说,并不满足…...

信息数智化招采系统源码——信息数智化招采系统

​ ​ 信息数智化招采系统 服务框架&#xff1a;Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构&#xff1a;VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术&#xff1a;Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monit…...

20230217使AIO-3399J开发板上跑通Android11系统

20230217使AIO-3399J开发板上跑通Android11系统 2023/2/17 15:45 1、解压缩SDK&#xff1a;rk3399-android-11-r20211216.tar.xzrootrootrootroot-X99-Turbo:~$ tar xvf rk3399-android-11-r20211216.tar.xz 2、编译U-boot&#xff1a; rootrootrootroot-X99-Turbo:~/rk3399-a…...

Java 基础面试题——面向对象

目录1.面向对象和面向过程有什么区别&#xff1f;2.面向对象的有哪些特征?3.静态变量和实例变量有什么区别&#xff1f;4.Java 对象实例化顺序是怎样的&#xff1f;5.浅拷贝和深拷贝的区别是什么&#xff1f;5.1.浅拷贝5.2.深拷贝5.3.总结6.Java 中创建对象的方式有哪几种&…...

PDF文件替换内容(电子签章),依赖免费pdfbox

首先提前准备&#xff0c;压入如下依赖 <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId>…...

nvm 控制 node版本

nvm 官网 https://nvm.uihtm.com/ 1、卸掉nodejs&#xff0c;根据官网操作 2、如果之前安装过的nodejs,且安装的目录改变了&#xff0c;需重新配置系统环境 第一步&#xff1a;打开此电脑 > 右键属性 > 高级系统设置 > 环境变量 第二步&#xff1a; 在系统变量中选中…...

javaEE 初阶 — 传输层 TCP 协议中的异常情况与面向字节流的粘包问题

文章目录1 粘包问题1.1 什么是粘包问题1.2 如何解决粘包问题2 异常情况TCP 的十个特性&#xff1a;确认应答机制 超时重传机制 连接管理机制 滑动窗口 流量控制与拥塞控制 延迟应答与捎带应答 1 粘包问题 1.1 什么是粘包问题 面向字节流引入了一个比较麻烦的粘包问题。 …...

IP路由基础

——IP路由基础&#xff08;IA&#xff09;—— ​​​​​​​HCIA全套笔记已经上线&#xff08;arpAAAvlanTrunk链路聚合vlan间通信ACL广域网技术以太网交换...........)_孤城286的博客-CSDN博客 目录 ——IP路由基础&#xff08;IA&#xff09;—— &#xff08;1&#…...

12.centos7部署sonarqube9.6

12.centos7部署sonarqube9.6环境&#xff1a;sonarqube9.6Postgresql13JDK11sonarqube9.6下载地址&#xff1a;Postgresql13 rpm下载地址&#xff1a;JDK11下载地址&#xff1a;准备工作&#xff1a;修改文件句柄数&#xff08;最大文件数&#xff09;和用户最大进程数限制修改…...

大学四年自学Java编程,现在拿到28万年薪的offer,还是觉得挺值的

最近刚拿到美团的Java后端工程师的offer&#xff0c;&#xff08;底薪、奖金、补贴、年终奖、五险一金&#xff09;总包加在大概有28万的年薪&#xff0c;实际到手不会有这么多&#xff0c;但是我对于这个待遇还是非常满意的。说来还是非常的感慨&#xff0c;我属于那种从大一到…...

MySQL的日志详解

目录 一.介绍 日志分类 二.错误日志 三.二进制日志—binlog 概述 日志格式 操作 四.查询日志 五.慢查询日志 一.介绍 在任何一种数据库中&#xff0c;都会有各种各样的日志&#xff0c;记录着数据库工作的方方面面&#xff0c;以帮助数据库管理员追踪数据库曾经发生过的…...

输出该股票所有收盘比开盘上涨3%以上的日期

1&#xff1a;输出该股票所有收盘比开盘上涨3%以上的日期 #codingutf-8 import tushare as ts import pandas as pd import numpy as np#获取某支股票的历史行情数据 dfts.get_hist_data(code600519,start2001-01-01) #将互联网上的数据获取并且存储到本地 df.to_csv(./maotai…...

数值卡,让数据可视化玩出新花样丨三叠云

数值卡 路径 仪表盘 >> 仪表盘设计 功能简介 1. 数值卡增加「数值标题」、「图标」、「进度条」功能&#xff0c;使得应用场景更为广泛&#xff0c;实现数据可视化&#xff0c;让用户能够轻松地获取、处理信息。 2.「数据模型」支持0个维度1个指标、1个维度1个指标。…...

有这几个表现可能是认知障碍前兆

我国目前对于认知障碍的认知率、就诊率、诊断率很低&#xff0c;然而认知障碍如果能在早期发现&#xff0c;并及时治疗&#xff0c;生活质量会有效提高&#xff0c;缓解家属的精神和经济负担。所以&#xff0c;认知障碍的前兆一定要了解。1.记忆力减退&#xff0c;一周内的重要…...

java面试题-阿里真题详解

前言 大家好&#xff0c;我是局外人一枚&#xff0c;最近有不少粉丝去阿里巴巴面试了&#xff0c;回来之后总结不少难题给我&#xff0c;以下是面试的真题&#xff0c;跟大家一起来讨论怎么回答。 阿里一面 1、说⼀下ArrayList和LinkedList区别 ⾸先&#xff0c;他们的底层数…...

JSON格式解析关键词搜索API

为了进行此平台API的调用&#xff0c;首先我们需要做下面几件事情。 1、 获取一个KEY。 2、 参考API文档里的接入方式和示例。 3、查看测试工具是否有需要的接口&#xff0c;响应实例的返回字段是否符合参数要求。 4、利用平台的文档中心和API测试工具&#xff0c;对接口进…...

【Java基础】泛型(二)-泛型的难点:通配符

本文将尝试将通配符和泛型中的继承&#xff0c;多态一并讲解 关于泛型中继承的注意事项 因为Integer、Double继承了Number&#xff0c;根据多态性&#xff0c;以下语句是合法的 Number n new Integer(10); // OK, 父类引用变量可以指向子类对象 n 2.9 // OK&#xff0c;n实…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...