二进制方式修改libpthread.so中的pthread_attr_setstacksize最小限制

       最近有个mips平台的嵌入式linux项目,官方提供了工具链,但发现他们所提供的libpthread.so库对线程的最小栈空间设置的是128K,造成程序运行时显示虚拟内存占用很高,虽然没太大影响,但是对我这样有洁癖的人感觉很不爽,所以我想把它改小,重新编译glibc感觉麻烦,好像也不安全,所以就想着直接修改库的二进制文件,下面是修改过程:

先写个测试代码如下:

#include
#include
#include

static void *func(void *arg)  
{ 
    printf("I am a thread\n");
    return NULL;
}

int main(int argc,char *argv[])
{
    pthread_t thread_id;
    int ret ,stacksize = 20480; 
    pthread_attr_t attr;
    
    if(argc > 1){
        stacksize = atoi(argv[1]);
    }
    
    printf("stacksize = %d\n",stacksize);
    
    ret = pthread_attr_init(&attr); 
    if (ret != 0){
        printf("pthread_attr_init fail\n");
        return -1;
    }
    ret = pthread_attr_setstacksize(&attr, stacksize);
    if(ret != 0){
        printf("pthread_attr_setstacksize fail\n");
        return -1;
    }
    ret = pthread_create (&thread_id, &attr, &func, NULL);
    if(ret != 0){
        printf("pthread_create fail\n");
        return -1;
    }
    ret = pthread_attr_destroy(&attr);
    if(ret != 0){
        printf("pthread_attr_destroy fail\n");
        return -1;
    }
    
    pthread_join(thread_id, NULL);
    
    printf("exit\n");
}

编译测试程序:

注意,建议使用-fno-omit-frame-pointer参数,不然gdb可能无法进入函数pthread_attr_setstacksize

mips-linux-gnu-gcc -g -EL -mips32r2 -fno-omit-frame-pointer -o thread_test thread_test.c -I/opt/mips-linux-gnu/libc/usr/include -L/opt/target/lib -lpthread

GDB调试测试程序:

二进制方式修改libpthread.so中的pthread_attr_setstacksize最小限制_第1张图片

gdb用到的几条命令:

target remote 192.168.1.125:1234

#连接远程目标(gdbserver)

set solib-search-path /buildroot-6.6.1.6/output/target/lib

#设置动态库路径,方便gdb加载调试符号

set heuristic-fence-post 100000

#不设置这个单步的时候可能停不到函数上,我理解的大概的原因就是函数的标准入口格式被优化掉了,gdb不能简单识别了,它要找找看。

b pthread_attr_setstacksize

#这个大家都懂,设置断点

disassemble

#反汇编当前段代码

x /5fx 0x77fabce0

#显示内存中的内容,我用它看当前的指令字节。


当断点停下来了,用disassemble反汇编查看代码和查看寄存器内容

lui     v0,0x2:这条指令是把立即数0x2放到v0的高16位,也就是0x20000,就是libpthread-2.18.so设置的最小线程栈128kBtye。

sltu    v0,a1,v0:这条指令是比较我们设置的堆栈大小和0x20000进行比较,如果我们传入的值大于这个值,程序继续运行,反之返回错误。我们可以看到a1中是我们代码中传入的0x5000。

接下来我们使用x /5fx 0x77fabce0看看lui v0,0x2的指令码:

我们看到的是0x3c020002,3c02是指令码,0002是立即数。

好了,现在我们要修改这条指令了,但是我发现个问题,如果只修改后面的立即数的话,我只有两个选择,一个是改成1,一个是改成0,改1的话限制大小变成64K,还是有点大,如果是0的话完全失去了限制,这都是我不想样要的。所有要想办法把整条指令改掉,但查mips指令手册太麻烦,直接用代码测试吧 。

int main(int argc,char *argv[])
{
    int a = 0;
    a = 0x2800;
    printf("I am a thread %d\n",a);
    return 0;
}

用mips-linux-gnu-gcc编译上面的代码,然后使用mips-linux-gnu-objdump -d查看

二进制方式修改libpthread.so中的pthread_attr_setstacksize最小限制_第2张图片

24022800     li    v0,10240

这句就是我们想要的,把立即数10240传给v0。

现在我们用UE打开libpthread-2.18.so文件,然后根据前面x /5fx 0x77fabce0看到的内容进行搜索和替换修改,注意大小端的问题,这样就搞定了。

二进制方式修改libpthread.so中的pthread_attr_setstacksize最小限制_第3张图片

把0200023c替换成00280224,完美收工。

谢谢观赏!



你可能感兴趣的:(二进制方式修改libpthread.so中的pthread_attr_setstacksize最小限制)