dlsym-like behaviour for static linked libraries
c, ld, linux
Solution
You can use BFD to get the addresses at runtime from symbol names.
#include <stdio.h>
#include <stdlib.h>
#include <bfd.h>
#include <string.h>
void func1(int n)
{
printf("%d\n", n);
}
void * addr_from_name(char * filename, char * symname)
{
bfd * ibfd;
asymbol ** symtab;
symbol_info info;
void * symaddress = NULL;
long size;
long syms;
unsigned int i;
bfd_init();
ibfd = bfd_openr(filename, NULL);
bfd_check_format(ibfd, bfd_object);
size = bfd_get_symtab_upper_bound(ibfd);
symtab = malloc(size);
syms = bfd_canonicalize_symtab(ibfd, symtab);
for(i = 0; i < syms; i++) {
if(strcmp(symtab[i]->name, symname) == 0) {
bfd_symbol_info(symtab[i], &info);
symaddress = (void *)info.value;
}
}
bfd_close(ibfd);
return symaddress;
}
int main(void)
{
void (*func)(int) = addr_from_name("/homes/mk08/Desktop/lala", "func1");
printf("%p\n", func);
func(5);
return EXIT_SUCCESS;
}
In this case, I hardcoded `filename`, but it is trivial to get it dynamically. Assuming your source/binary is called `lala`, you can compile and run like so:
gcc -Wall -std=gnu99 lala.c -o lala -lbfd && ./lala
On my system, this prints:
0x400814
5
Note that this method requires an intact symbol table. To reduce overhead, you can re-use the code above in an initialisation routine. In there, you would store a mapping from function names to addresses. This results in a one-off cost for generating a lookup table.
Problem
I am trying to write sort of a dispatch function in C that should receive a string consisting of a function name, and afterwards from inside the dispatch function to be able to call the function whose name is specified in the argument received. The whole point is that I do not want to define the function in a dynamically loaded library. The flow should be something like this. file1.c ``` void hello() { fprintf(stderr,"Hello world\n"); } void myfunc() { mydispatch("hello"); } ``` file2.c ``` void mydispatch(const char *function) { ... } ``` I know this structure may be sort of weird, but I was mainly wondering if one could do this.