当前位置: 首页 > 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实…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...