前些天為了排查我們程序中不知道是庫裡面還是我們自己調用了assert斷言,導致我們程序死亡。想通過hook攔截到調用這個函數的調用者,偶然間想起proload(預加載),小試牛刀使用如下代碼
#include <syscall.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void abort(void)
{
printf("****************my abort, getpid():%u\n", __FILE__, __LINE__, getpid());
int *a = NULL;
*a = 1;
while(1)
{
sleep(10000);
}
}
gcc --shared -fPIC preload.c -o libpreload.so 編譯成so的形式
使用如下代碼進行測試
#include <stdlib.h>
#include <stdio.h>
int main ( int argc, char *argv[] )
{
printf("file:%s, line:%d, getpid():%u\n", __FILE__, __LINE__, getpid());
abort();
printf("file:%s, line:%d\n", __FILE__, __LINE__);
void *p = malloc(3);
return p == NULL;
return EXIT_SUCCESS;
}
gcc testpreload.c -o testpreload 編譯可執行程序,默認鏈接到了glibc中的assert
啟動方式,
將libpreload.so放到和可執行程序testpreload同級目錄下
LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" LD_PRELOAD="libpreload.so" ./testpreload
加入LD_LIBRARY_PATH 對當前目錄的搜索,使用LD_PRELOAD 設定預加載的so,啟動後輸出如下結果
file:testpreload.c, line:31, getpid():9960
****************my abort, getpid():3086001460
./run.sh: line 1: 9960 段錯誤 LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" LD_PRELOAD="libpreload.so" ./testpreload
我故意產生了一個SIGV錯誤,暫時弄不清楚為什麼getpid()的系統調用返回值不對,printf卻可以運行無誤。
主要用途:
可以代替ptrace攔截系統調用,或者對函數的調用,可以用來分析一些比如內存洩露(malloc free是否成對調用)等等問題