Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a running C program access its own symbol table?

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 that port, but I dont want to hard code what global variables can be queried. Thus I want the query to contain the string name of a global and the C code to look that string up in the symbol table to find its address and then send its value back over the TCP socket. Of course the symbol table must not have been stripped. So can the C program even locate its own symbol table, and is there a library interface for looking up symbols given their name? This is an ELF executable C program built with gcc.

like image 508
JimKleck Avatar asked Jun 29 '12 01:06

JimKleck


1 Answers

file: reflect.c

#include <stdio.h>
#include "reflect.h"

struct sym_table_t gbl_sym_table[1] __attribute__((weak)) = {{NULL, NULL}};

void * reflect_query_symbol(const char *name)
{
    struct sym_table_t *p = &gbl_sym_table[0];

    for(; p->name; p++) {
        if(strcmp(p->name, name) == 0) {
            return p->addr;
        }
    }
    return NULL;
}

file: reflect.h

#include <stdio.h>

struct sym_table_t {
    char *name;
    void *addr;
};

void * reflect_query_symbol(const char *name);

file: main.c

just #include "reflect.h" and call reflect_query_symbol

example:

#include <stdio.h>
#include "reflect.h"

void foo(void)
{
    printf("bar test\n");
}

int uninited_data;

int inited_data = 3;

int main(int argc, char *argv[])
{
    int i;
    void *addr;

    for(i=1; i<argc; i++) {
        addr = reflect_query_symbol(argv[i]);
        if(addr) {
            printf("%s lay at: %p\n", argv[i], addr);
        } else {
            printf("%s NOT found\n", argv[i], addr);
        }
    }

    return 0;
}

file:Makefile

objs = main.o reflect.o

main: $(objs)
        gcc -o $@ $^
        nm $@ | awk 'BEGIN{ print "#include <stdio.h>"; print "#include \"reflect.h\""; print "struct sym_table_t gbl_sym_table[]={" } { if(NF==3){print "{\"" $$3 "\", (void*)0x" $$1 "},"}} END{print "{NULL,NULL} };"}' > .reflect.real.c
        gcc -c .reflect.real.c -o .reflect.real.o
        gcc -o $@ $^ .reflect.real.o
        nm $@ | awk 'BEGIN{ print "#include <stdio.h>"; print "#include \"reflect.h\""; print "struct sym_table_t gbl_sym_table[]={" } { if(NF==3){print "{\"" $$3 "\", (void*)0x" $$1 "},"}} END{print "{NULL,NULL} };"}' > .reflect.real.c
        gcc -c .reflect.real.c -o .reflect.real.o
        gcc -o $@ $^ .reflect.real.o
like image 132
yang wen Avatar answered Sep 27 '22 03:09

yang wen