【深入理解计算机系统】库打桩 - 阅读笔记
文章目录
- 库打桩机制
- 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 链接器支持一个很强大的技术,称为库打桩 (library interpositioning),它允许你截获对共享库函数的调用,取而代之执行自己的代码。使用打桩机制,你可以…...
RocketMQ高性能原理分析
目录一、读队列与写队列1.概念介绍2.读写队列个数关系分析二、消息持久化1.持久化文件介绍2.持久化结构介绍:三、过期文件删除1.如何判断文件过期2.什么时候删除过期文件四、高效文件写1.零拷贝技术加速文件读写2.文件顺序写3.刷盘机制五、 消息主从复制六、负载均衡…...
前端面试当中CDN会问啥------CDN详细教程来啦
⼀、CDN 1. CDN的概念 CDN(Content Delivery Network,内容分发⽹络)是指⼀种通过互联⽹互相连接的电脑⽹络系统,利 ⽤最靠近每位⽤户的服务器,更快、更可靠地将⾳乐、图⽚、视频、应⽤程序及其他⽂件发送给⽤户&…...
刷题记录:牛客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一道区间求和区间异或的题目,可以称得上是线段树的一道好题 首先对于异或运算来说,并不满足…...
信息数智化招采系统源码——信息数智化招采系统
信息数智化招采系统 服务框架:Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构:VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术: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:rk3399-android-11-r20211216.tar.xzrootrootrootroot-X99-Turbo:~$ tar xvf rk3399-android-11-r20211216.tar.xz 2、编译U-boot: rootrootrootroot-X99-Turbo:~/rk3399-a…...
Java 基础面试题——面向对象
目录1.面向对象和面向过程有什么区别?2.面向对象的有哪些特征?3.静态变量和实例变量有什么区别?4.Java 对象实例化顺序是怎样的?5.浅拷贝和深拷贝的区别是什么?5.1.浅拷贝5.2.深拷贝5.3.总结6.Java 中创建对象的方式有哪几种&…...
PDF文件替换内容(电子签章),依赖免费pdfbox
首先提前准备,压入如下依赖 <!-- 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,根据官网操作 2、如果之前安装过的nodejs,且安装的目录改变了,需重新配置系统环境 第一步:打开此电脑 > 右键属性 > 高级系统设置 > 环境变量 第二步: 在系统变量中选中…...
javaEE 初阶 — 传输层 TCP 协议中的异常情况与面向字节流的粘包问题
文章目录1 粘包问题1.1 什么是粘包问题1.2 如何解决粘包问题2 异常情况TCP 的十个特性:确认应答机制 超时重传机制 连接管理机制 滑动窗口 流量控制与拥塞控制 延迟应答与捎带应答 1 粘包问题 1.1 什么是粘包问题 面向字节流引入了一个比较麻烦的粘包问题。 …...
IP路由基础
——IP路由基础(IA)—— HCIA全套笔记已经上线(arpAAAvlanTrunk链路聚合vlan间通信ACL广域网技术以太网交换...........)_孤城286的博客-CSDN博客 目录 ——IP路由基础(IA)—— (1&#…...
12.centos7部署sonarqube9.6
12.centos7部署sonarqube9.6环境:sonarqube9.6Postgresql13JDK11sonarqube9.6下载地址:Postgresql13 rpm下载地址:JDK11下载地址:准备工作:修改文件句柄数(最大文件数)和用户最大进程数限制修改…...
大学四年自学Java编程,现在拿到28万年薪的offer,还是觉得挺值的
最近刚拿到美团的Java后端工程师的offer,(底薪、奖金、补贴、年终奖、五险一金)总包加在大概有28万的年薪,实际到手不会有这么多,但是我对于这个待遇还是非常满意的。说来还是非常的感慨,我属于那种从大一到…...
MySQL的日志详解
目录 一.介绍 日志分类 二.错误日志 三.二进制日志—binlog 概述 日志格式 操作 四.查询日志 五.慢查询日志 一.介绍 在任何一种数据库中,都会有各种各样的日志,记录着数据库工作的方方面面,以帮助数据库管理员追踪数据库曾经发生过的…...
输出该股票所有收盘比开盘上涨3%以上的日期
1:输出该股票所有收盘比开盘上涨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. 数值卡增加「数值标题」、「图标」、「进度条」功能,使得应用场景更为广泛,实现数据可视化,让用户能够轻松地获取、处理信息。 2.「数据模型」支持0个维度1个指标、1个维度1个指标。…...
有这几个表现可能是认知障碍前兆
我国目前对于认知障碍的认知率、就诊率、诊断率很低,然而认知障碍如果能在早期发现,并及时治疗,生活质量会有效提高,缓解家属的精神和经济负担。所以,认知障碍的前兆一定要了解。1.记忆力减退,一周内的重要…...
java面试题-阿里真题详解
前言 大家好,我是局外人一枚,最近有不少粉丝去阿里巴巴面试了,回来之后总结不少难题给我,以下是面试的真题,跟大家一起来讨论怎么回答。 阿里一面 1、说⼀下ArrayList和LinkedList区别 ⾸先,他们的底层数…...
JSON格式解析关键词搜索API
为了进行此平台API的调用,首先我们需要做下面几件事情。 1、 获取一个KEY。 2、 参考API文档里的接入方式和示例。 3、查看测试工具是否有需要的接口,响应实例的返回字段是否符合参数要求。 4、利用平台的文档中心和API测试工具,对接口进…...
【Java基础】泛型(二)-泛型的难点:通配符
本文将尝试将通配符和泛型中的继承,多态一并讲解 关于泛型中继承的注意事项 因为Integer、Double继承了Number,根据多态性,以下语句是合法的 Number n new Integer(10); // OK, 父类引用变量可以指向子类对象 n 2.9 // OK,n实…...
黑马】后台管理-两个括号的坑
记录一下这两天的坑没想到后台管理系统上线这两天都没有搞明白1.首先第一个坑是使用node.js的express中间件框架创建一个微型服务器,然后将vue脚手架生成的dist文件夹的文件放入里面了 ,把项目加载到web服务器之后运行node .\app.js,页面显示…...
05:进阶篇 - 使用 CTKWidgets
作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 CTKWidgets 包含了一组 Qt 部件,用于生物医学成像应用程序。当然,即使你的程序与医学无关,很多部件也是很有参考意义的。 在 CTK 源码中,有很多选项开关,可以控制你想要编译的内容(详见:04:进阶篇 …...
【YOLO V5】代码复现过程
接上篇,讲到如何从mask转成YOLOv5训练需要的txt数据集格式,这篇就在此基础上进行模型训练预测和部署转换吧! 目录 1.环境准备 2.YOLO训练 2.1 数据集准备 2.2 data.yaml准备 2.3 yolov5.yaml准备 2.4 训练命令 3.YOLO预测 3.1OLOv5 P…...
汽车如何实现制动
汽车如何实现制动 汽车如何实现制动 难点答疑:汽车刹车时,四个车轮是如何制动的?制动机理是什么? 第一步:驾驶员踩下制动踏板,推动制动主缸 第二步:制动主缸将制动液的压力通过制动管道传递到四…...
cmake 引入第三方库(头文件目录、库目录、库文件)
程序的编写需要用到头文件,程序的编译需要lib文件,程序的运行需要dll文件,因此cmake引入第三方库其实就是将include目录、lib目录、bin目录引入工程。 目录 1、find_package(批量引入库文件和头文件) 2、include_dir…...
插件开发版|Authing 结合 APISIX 实现统一可配置 API 权限网关
当开发者在构建网站、移动设备或物联网应用程序时,API 网关作为微服务架构中不可或缺的控制组件,是流量的核心进出口。通过有效的权限管控,可以实现认证授权、监控分析等功能,提高 API 的安全性、可用性、拓展性以及优化 API 性能…...
deepinlinux v20安装rust和tauri并配置vscode开发工具过程
rust 很快进入linux内核开发,作为高效后台语言值得学习 tauri是代替electron的跨平台框架,不打包浏览器内核,所以打包出来体积小 安装rust 命令 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh 安装后看版本 rustc -V 看构…...
通俗易懂的机器学习——sklearn鸢尾花分类(KNN)
前言 KNN算法是机器学习中较为简单的入门算法,其主要思想是选取k个与待预测点相近的数据,观察他们的类别,本着离谁近就更像谁的思路对于待预测点进行预测,本文将针对使用sklearn进行KNN算法的使用进行详解 数据预处理 在正式开…...
操作系统引论
操作系统是管理硬件和软件的一种应用程序。操作系统是运行在计算机上最重要的一种软件,它管理计算机的资源和进程以及所有的硬件和软件。它为计算机硬件和软件提供了一种中间层,使应用软件和硬件进行分离,让我们无需关注硬件的实现࿰…...
优质 CS 读博 (PhD) 经验贴汇总
前言 如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 Advice for early-stage Ph.D. students 读博的核心是在研究上取得进展,只有在研究上取得一些进展ÿ…...
包头网站建设易通/软文范文大全
Network Address Translation 来源:http://alexanderlaw.blog.hexun.com/9791596_d.html 地址转换用来改变源/目的地址/端口,是netfilter的一部分,也是通过hook点上注册相应的结构来工作 Nat注册的hook点和conntrack相同,只是优先…...
关于设计的网站/百度学术免费查重入口
1,hbase 全称:hadoop dataBase ,即hadoop数据库 2,使用场景:大数据量,准实时查询 3,特点:面向列,支持独立索引,每个列支持存储多版本,稀疏性:空…...
网站模板带手机站/网络推广网站
前言 基于哨兵机制,实现高可用,也就是集群架构。 主数据节点挂了 依次执行以下步骤 哨兵节点监控数据节点 1.所有从数据节点监控挂了,然后,中止复制主数据节点 2.所有哨兵节点监控挂了,然后,判断是否超过下…...
怎么做网站上面的那种卡通图片/电商培训机构排名前十
看到很多人提问非科班该如何学习编程,其实科班也基本靠自学。有句话叫“师傅领进门修行靠个人”,再厉害的老师 能教你的东西都是很有限的,真正的修行还是要靠自己。我本科是学数学的,虽然研究生是计算机专业,但研究生往…...
请问新疆哪家网站建设公司比较好/免费推广方法有哪些
一个良好的界面应该是这样的。它给予用户的界面,应该只有一些简单的设定。用户应该用同样的方法来设置所有程序的所有参数,因为它们只不过是一个从变量到值的映射(map)。至于系统要在什么地方存储这些设定,如何找到它们…...
成功的网站建设/关键词优化和seo
写出人生目标 尽快写出人生目标,并及时更新。(人生目标应该对人是很重要的,但是有一部分人很难写出人生目标,这很可能是因为懒惰或拖延。)利用时间 “不要一味追求投入更多时间,要注重效率,养成…...