How can I debug runtime library interpositioned process?

吃可爱长大的小学妹 提交于 2020-01-03 05:18:34

问题


I'm now studying library interpositioning with C in Ubuntu 18.04, and I'm testing two simple codes to wrap strlen: "mystrlen.c", "mystrlenTest.c".

Here is the code I wrote: mystrlen.c

#ifdef RUNTIME
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

/* strlen wrapper function */
size_t strlen(const char *str) {
    size_t (*strlenp)(const char *) = NULL;
    printf("%s\n", *str);

    strlenp = dlsym(RTLD_NEXT, "strlen");   // Get address of libc strlen
    printf("length: %ld\n", strlenp(str));

    return strlenp(str);
}
#endif

And mystrlenTest.c:

#include <stdio.h>
#include <string.h>

int main(void) {
    char testString[] = "Hello World!";
    printf("length of the testString: %ld\n", strlen(testString));

    return 0;
}

I tried to inject during runtime with the command below:

$ gcc -DRUNTIME -shared -fpic -g -o mystrlen.so mystrlen.c -ldl
$ gcc -g -o mystrlenTest mystrlenTest.c
$ LD_PRELOAD=./mystrlen.so ./mystrlenTest

And this is all I get: Segmentation fault (core dumped) So I tried dmesg command to find out what happened, and the result was like below:

[842291.658267] mystrlenTest[51446]: segfault at 48 ip 00007f7b918e35a1 sp 00007ffdd7158c88 error 4 in libc-2.27.so[7f7b91755000+1e7000]
[842291.658272] Code: 2e 0f 1f 84 00 00 00 00 00 31 c0 c5 f8 77 c3 66 2e 0f 1f 84 00 00 00 00 00 89 f9 48 89 fa c5 f9 ef c0 83 e1 3f 83 f9 20 77 1f <c5> fd 74 0f c5 fd d7 c1 85 c0 0f 85 df 00 00 00 48 83 c7 20 83 e1

What I wanted to ask was, how can I debug this with gdb? Or is there any other way to debug it? I know how to debug a single program with gdb, but I'm having difficulty with debuging the runtime library interpositioned process. If I can find out what is in 00007f7b918e35a1, it would be a great help.


回答1:


When invoking gdb, you can pass the environment variables you want to set, like:

gdb --args env LD_PRELOAD=./mystrlen.so ./mystrlenTest

Now you can use get the backtrace as usual in gdb.

You can also use system calls to print debug messages, such as:

write(2, "message", sizeof "message" - 1);

Which doesn't call any of the library functions at all. (Although, most system calls have thin wrappers in glibc,this is largely irrelevant for its users). In your specific case, the likely issue is that printf itself calls strlen as noted by Andrew Henle, thus resulting in infinite recursion.

When interposing, you need to careful about what you call from the interposed functions and always ask yourself whether any calls from inside the interposed function might result in call back to the same interposed function or any other interposed function(s) and take necessary steps to handle such cases. For example, a lot of standard functions might internally allocate memory via malloc family functions and if you're interposing malloc and friends, this could cause unexpected problems.




回答2:


Given this code:

size_t strlen(const char *str) {
    size_t (*strlenp)(const char *) = NULL;
    printf("%s\n", *str);

    strlenp = dlsym(RTLD_NEXT, "strlen");   // Get address of libc strlen
    printf("length: %ld\n", strlenp(str));

    return strlenp(str);
}

If printf() uses strlen() internally, you will get infinite recursion and almost certainly a segmentation violation.

Note that in GLIBC, the libc.so used on Linux, printf() is implemented via vfprintf(), which does indeed make use of strlen().



来源:https://stackoverflow.com/questions/59097526/how-can-i-debug-runtime-library-interpositioned-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!