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
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)
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.