库打桩技术
GUN binutils 工具包
readelf 显示目标文件的完整结构
LDD 列出一个可执行文件在运行时间所需要的共享库
ld -lUsefulFunctions --verbose 可以显示静态库的情况
Linux下的库打桩技术
/demo
+--- demo
|
+--- int.c
+--- malloc.h
+--- mymalloc.c
int.c
#include <stdio.h>
#include <malloc.h>
int main()
{
int *p = malloc(32);
free(p);
printf("Done!\n");
return 0;
}
malloc.h
#define malloc(size) mymalloc(size)
#define free(ptr) myfree(ptr)
void *mymalloc(size_t size);
void myfree(void *ptr);
mymalloc.c
#ifdef COMPILETIME
#include <stdio.h>
#include <malloc.h>
void* mymalloc(size_t size)
{
void *ptr = malloc(size);
printf("malloc(%d) = %p\n",(int)size,ptr);
return ptr;
}
void myfree(void* ptr)
{
free(ptr);
printf("free(%p)\n",ptr);
}
#endif
#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);
printf("malloc(%d) = %p\n",(int)size,ptr);
return ptr;
}
void __wrap_free(void* ptr)
{
__real_free(ptr);
printf("free(%p)\n",ptr);
}
#endif
编译期打桩
gcc -DCOMPILETIME -c mymalloc.c
gcc -I . -o intc int.c mymalloc.o // 注意-I .不是-I.
链接期打桩
gcc -DLINKTIME -c mymalloc.c
gcc -c int.c
gcc -Wl,--wrap,malloc -Wl,--wrap,free -o int1 int.o mymalloc.o
-Wl,--wrap,malloc = 把--wrap malloc传递给链接器,相当于链接器
把对malloc的引用解析为__wrap_malloc
把对__real_malloc的引用解析为malloc
运行期间打桩
这个很厉害的机制基于动态链接器的LD_PRELOAD环境变量
先把下面代码编译成动态链接库gcc -DRUNTIME -shared -fpic -o mymalloc.so mymalloc.c -ldl
g++ -std=c++11 test.cpp -o intr
g++ -std=c++11 -DRUNTIME -shared -fpic -o mymalloc.so mymalloc.cpp -ldl //编译成动态库,其中的malloc采用特殊的解析方式
LD_PRELOAD="./mymalloc.so" ./intr //单次有效,且并不影响./intr
#ifdef RUNTIME
//#define _GNU_SOURCE
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <iostream>
#include <fstream>
#include <string>
std::string GetTime(){
using namespace std;
time_t now = time(0);
tm *ltm = localtime(&now);
long long int tmp = 0;
tmp += 1900 + ltm->tm_year;
tmp *= 100;
tmp += 1 + ltm->tm_mon;
tmp *= 100;
tmp += ltm->tm_mday;
tmp *= 100;
tmp += ltm->tm_hour;
tmp *= 100;
tmp += ltm->tm_min;
tmp *= 100;
tmp += ltm->tm_sec;
string ret = to_string(tmp);
ret.insert(12,":");
ret.insert(10,":");
ret.insert(8,"-");
return ret;
}
const char * const output = "/home/mzb/Project/MemoryLeak/Memory.log";
FILE* fout = NULL;
using std::endl;
using std::cout;
using std::cerr;
static int is_self_reference = 0;
void init(){
static bool is_init = false;
if (!is_init){
is_init = true;
++is_self_reference;
fout = fopen(output,"at+");
--is_self_reference;
}
}
void* Dlsym(const char* const func_name){
auto ret = dlsym(RTLD_NEXT,func_name);
auto error = dlerror();
if (error != NULL){
cerr << "dlsym(" << func_name << ") = " << ret << endl;
cerr << "dlerror() = " << error << endl;
exit(0);
}
else{
return ret;
}
}
void* malloc(size_t size){
init();
using func_type = void* (*)(size_t size);
func_type mallocp = (func_type)Dlsym("malloc");
if (is_self_reference){
return mallocp(size);
}
else{
++is_self_reference;
auto ret = mallocp(size);
if (fout){
auto time = GetTime();
fprintf(fout,"%s malloc(%d) = %p\n",time.c_str(),(int)size,ret);
}
else{
cerr << "fopen(" << output << ",at+) failed" << endl;
}
--is_self_reference;
return ret;
}
}
void free(void* ptr){
using func_type = void (*)(void *);
func_type freep = (func_type)Dlsym("free");
if (is_self_reference){
freep(ptr);
}
else{
++is_self_reference;
if (fout){
auto time = GetTime();
fprintf(fout,"%s free(%p)\n",time.c_str(),ptr);
}
else{
cerr << "fopen(" << output << ",at+) failed" << endl;
}
freep(ptr);
--is_self_reference;
}
}
#endif
本文来自博客园,作者:XDU18清欢,转载请注明原文链接:https://www.cnblogs.com/XDU-mzb/p/15943290.html