死锁检测组件 -- 使用hook检测死锁

文章介绍了hook的概念,它允许替换系统或第三方库的函数。文章详细讲解了dlsym()函数的作用,用于获取共享对象中符号的地址,并展示了hook的实现步骤,包括定义目标函数类型、实现同名函数以及使用dlsym()进行函数替换。还提供了一个示例代码,演示如何在多线程场景中应用hook来追踪mutex锁的使用。
摘要由CSDN通过智能技术生成

目录

hook

hook是什么

dlsym()函数

hook的实现步骤

加入hook的demo


C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

hook

hook可以把系统或第三方库提供的函数,替换成我们写的同名函数。会调用我们实现的函数。

hook是什么

hook提供了两个接口;1. dlsym()是针对系统的,系统原始的api。2. dlopen()是针对第三方的库。

dlsym()函数

获取共享对象或可执行文件中符号的地址。
函数原型:

描述:

        函数dlsym()接受dlopen()返回的动态加载共享对象的“句柄”以及以空结尾的符号名,并返回该符号加载到内存中的地址。如果在指定对象或加载对象时dlopen()自动加载的任何共享对象中找不到该符号,dlsym()将返回NULL。(dlsym()执行的搜索是通过这些共享对象的依赖关系树进行的广度优先搜索。)

        handle中可以指定两个特殊的伪句柄:

返回值:

成功时,这些函数返回与符号关联的地址。

失败时,返回NULL;可以使用dlerror()诊断错误的原因。

hook的实现步骤

/* ******* ******************hook****************** ******* */
//第一步定义目标函数一样的类型
typedef int (*pthread_mutex_lock_t)(pthread_mutex_t *mutex);
typedef int (*pthread_mutex_unlock_t)(pthread_mutex_t *mutex);

pthread_mutex_lock_t pthread_mutex_lock_f;
pthread_mutex_unlock_t pthread_mutex_unlock_f;

//第二步实现目标函数名一致
//pthread_mutex_lock()会调用本函数
int pthread_mutex_lock(pthread_mutex_t *mutex) {

	pthread_t selfid = pthread_self();

	pthread_mutex_lock_f(mutex);
	printf("pthread_mutex_lock: %ld, %p\n", selfid, mutex);
} 

//pthread_mutex_unlock()会调用本函数
int pthread_mutex_unlock(pthread_mutex_t *mutex) {

	pthread_t selfid = pthread_self();
	
	pthread_mutex_unlock_f(mutex);
	printf("pthread_mutex_unlock: %ld, %p\n", selfid, mutex);
} 

//第三步dlsym,放到main初始化
void init_hook(void) {

	pthread_mutex_lock_f = dlsym(RTLD_NEXT, "pthread_mutex_lock");
	pthread_mutex_unlock_f = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
}

加入hook的demo

//gcc Dead_lock.c -lpthread -ldl
#define _GNU_SOURCE
#include <dlfcn.h>


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include <unistd.h>

/* ******* ******************hook****************** ******* */
//第一步定义目标函数一样的类型
typedef int (*pthread_mutex_lock_t)(pthread_mutex_t *mutex);
typedef int (*pthread_mutex_unlock_t)(pthread_mutex_t *mutex);

pthread_mutex_lock_t pthread_mutex_lock_f;
pthread_mutex_unlock_t pthread_mutex_unlock_f;

//第二步实现目标函数名一致
//pthread_mutex_lock()会调用本函数
int pthread_mutex_lock(pthread_mutex_t *mutex) {

	pthread_t selfid = pthread_self();

	pthread_mutex_lock_f(mutex);
	printf("pthread_mutex_lock: %ld, %p\n", selfid, mutex);
} 

//pthread_mutex_unlock()会调用本函数
int pthread_mutex_unlock(pthread_mutex_t *mutex) {

	pthread_t selfid = pthread_self();
	
	pthread_mutex_unlock_f(mutex);
	printf("pthread_mutex_unlock: %ld, %p\n", selfid, mutex);
} 

//第三步dlsym,放到main初始化
void init_hook(void) {

	pthread_mutex_lock_f = dlsym(RTLD_NEXT, "pthread_mutex_lock");
	pthread_mutex_unlock_f = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
}


//测试代码
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex4 = PTHREAD_MUTEX_INITIALIZER;

void *thread_funcA(void *arg) {

	pthread_mutex_lock(&mutex1);
	sleep(1);
	pthread_mutex_lock(&mutex2);

	printf("thread_funcA\n");

	pthread_mutex_unlock(&mutex2);
	pthread_mutex_unlock(&mutex1);

}

void *thread_funcB(void *arg) {

	pthread_mutex_lock(&mutex2);
	sleep(1);
	pthread_mutex_lock(&mutex3);

	printf("thread_funcB\n");

	pthread_mutex_unlock(&mutex3);
	pthread_mutex_unlock(&mutex2);

}

void *thread_funcC(void *arg) {

	pthread_mutex_lock(&mutex3);
	sleep(1);
	pthread_mutex_lock(&mutex4);

	printf("thread_funcC\n");

	pthread_mutex_unlock(&mutex4);
	pthread_mutex_unlock(&mutex3);
}

void *thread_funcD(void *arg) {

	pthread_mutex_lock(&mutex4);
	sleep(1);
	pthread_mutex_lock(&mutex1);
	
	printf("thread_funcD\n");
	
	pthread_mutex_unlock(&mutex1);
	pthread_mutex_unlock(&mutex4);

}

int main() {
	pthread_t tida, tidb, tidc, tidd;

	init_hook();

	pthread_create(&tida, NULL, thread_funcA, NULL);
	pthread_create(&tidb, NULL, thread_funcB, NULL);
	pthread_create(&tidc, NULL, thread_funcC, NULL);
	pthread_create(&tidd, NULL, thread_funcD, NULL);


	pthread_join(tida, NULL);
	pthread_join(tidb, NULL);
	pthread_join(tidc, NULL);
	pthread_join(tidd, NULL);
	
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值