Can a running C program access its own symbol table?

前端 未结 3 1488
伪装坚强ぢ
伪装坚强ぢ 2021-02-19 19:06

I have a linux C program that handles request sent to a TCP socket (bound to a particular port). I want to be able to query the internal state of the C program via a request to

3条回答
  •  挽巷
    挽巷 (楼主)
    2021-02-19 20:04

    This is actually fairly easy. You use dlopen / dlsym to access symbols. In order for this to work, the symbols have to be present in the dynamic symbol table. There are multiple symbol tables!

    #include 
    #include 
    
    __attribute__((visibility("default")))
    const char A[] = "Value of A";
    
    __attribute__((visibility("hidden")))
    const char B[] = "Value of B";
    
    const char C[] = "Value of C";
    
    int main(int argc, char *argv[])
    {
        void *hdl;
        const char *ptr;
        int i;
    
        hdl = dlopen(NULL, 0);
        for (i = 1; i < argc; ++i) {
            ptr = dlsym(hdl, argv[i]);
            printf("%s = %s\n", argv[i], ptr);
        }
        return 0;
    }
    

    In order to add all symbols to the dynamic symbol table, use -Wl,--export-dynamic. If you want to remove most symbols from the symbol table (recommended), set -fvisibility=hidden and then explicitly add the symbols you want with __attribute__((visibility("default"))) or one of the other methods.

    ~ $ gcc dlopentest.c -Wall -Wextra -ldl
    ~ $ ./a.out A B C
    A = (null)
    B = (null)
    C = (null)
    ~ $ gcc dlopentest.c -Wall -Wextra -ldl -Wl,--export-dynamic
    ~ $ ./a.out A B C
    A = Value of A
    B = (null)
    C = Value of C
    ~ $ gcc dlopentest.c -Wall -Wextra -ldl -Wl,--export-dynamic -fvisibility=hidden
    ~ $ ./a.out A B C
    A = Value of A
    B = (null)
    C = (null)
    

    Safety

    Notice that there is a lot of room for bad behavior.

    $ ./a.out printf
    printf = ▯▯▯▯ (garbage)
    

    If you want this to be safe, you should create a whitelist of permissible symbols.

提交回复
热议问题