say I have a parent and a child, the child calls a function "hello" in the child with dlopen. Can the child then call a function "world" in the parent? I keep getting symbol lookup error: ./child.so: undefined symbol: world
here are the files. parent.c
#include <dlfcn.h>
typedef void (*fptr)();
#include <stdio.h>
int main () {
void*handle=dlopen("./child.so",RTLD_LAZY);
fptr f=dlsym(handle,"hello");
f();
return 0;
}
void world() {
printf ("world");
}
and child.c
#include <stdio.h>
void hello () {
printf ("hello");
world();
}
Yes, it a dlopen-ed module can call functions from the calling program, provided that the calling program has been linked with the -rdynamic option.
BTW, most plugins need that feature: a firefox plugin obviously wants to call firefox functions.
Read also about visibility function __attribute__ ... Read also Drepper's How to Write Shared Libraries long paper and dlopen(3) man page.
I found the answer on google
http://www.justskins.com/forums/dlopen-calling-functions-other-104185.html
gcc -rdynamic hello.c -ldl
Surprisingly it can. I've personally seen it happen.
You may need to link to the executable with -rdynamic
Related
So everyone probably knows that glibc's /lib/libc.so.6 can be executed in the shell like a normal executable in which cases it prints its version information and exits. This is done via defining an entry point in the .so. For some cases it could be interesting to use this for other projects too. Unfortunately, the low-level entry point you can set by ld's -e option is a bit too low-level: the dynamic loader is not available so you cannot call any proper library functions. glibc for this reason implements the write() system call via a naked system call in this entry point.
My question now is, can anyone think of a nice way how one could bootstrap a full dynamic linker from that entry point so that one could access functions from other .so's?
Update 2: see Andrew G Morgan's slightly more complicated solution which does work for any GLIBC (that solution is also used in libc.so.6 itself (since forever), which is why you can run it as ./libc.so.6 (it prints version info when invoked that way)).
Update 1: this no longer works with newer GLIBC versions:
./a.out: error while loading shared libraries: ./pie.so: cannot dynamically load position-independent executable
Original answer from 2009:
Building your shared library with -pie option appears to give you everything you want:
/* pie.c */
#include <stdio.h>
int foo()
{
printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);
return 42;
}
int main()
{
printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);
return foo();
}
/* main.c */
#include <stdio.h>
extern int foo(void);
int main()
{
printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);
return foo();
}
$ gcc -fPIC -pie -o pie.so pie.c -Wl,-E
$ gcc main.c ./pie.so
$ ./pie.so
in main pie.c:9
in foo pie.c:4
$ ./a.out
in main main.c:6
in foo pie.c:4
$
P.S. glibc implements write(3) via system call because it doesn't have anywhere else to call (it is the lowest level already). This has nothing to do with being able to execute libc.so.6.
I have been looking to add support for this to pam_cap.so, and found this question. As #EmployedRussian notes in a follow-up to their own post, the accepted answer stopped working at some point. It took a while to figure out how to make this work again, so here is a worked example.
This worked example involves 5 files to show how things work with some corresponding tests.
First, consider this trivial program (call it empty.c):
int main(int argc, char **argv) { return 0; }
Compiling it, we can see how it resolves the dynamic symbols on my system as follows:
$ gcc -o empty empty.c
$ objcopy --dump-section .interp=/dev/stdout empty ; echo
/lib64/ld-linux-x86-64.so.2
$ DL_LOADER=/lib64/ld-linux-x86-64.so.2
That last line sets a shell variable for use later.
Here are the two files that build my example shared library:
/* multi.h */
void multi_main(void);
void multi(const char *caller);
and
/* multi.c */
#include <stdio.h>
#include <stdlib.h>
#include "multi.h"
void multi(const char *caller) {
printf("called from %s\n", caller);
}
__attribute__((force_align_arg_pointer))
void multi_main(void) {
multi(__FILE__);
exit(42);
}
const char dl_loader[] __attribute__((section(".interp"))) =
DL_LOADER ;
(Update 2021-11-13: The forced alignment is to help __i386__ code be SSE compatible - without it we get hard to debug glibc SIGSEGV crashes.)
We can compile and run it as follows:
$ gcc -fPIC -shared -o multi.so -DDL_LOADER="\"${DL_LOADER}\"" multi.c -Wl,-e,multi_main
$ ./multi.so
called from multi.c
$ echo $?
42
So, this is a .so that can be executed as a stand alone binary. Next, we validate that it can be loaded as shared object.
/* opener.c */
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
void *handle = dlopen("./multi.so", RTLD_NOW);
if (handle == NULL) {
perror("no multi.so load");
exit(1);
}
void (*multi)(const char *) = dlsym(handle, "multi");
multi(__FILE__);
}
That is we dynamically load the shared-object and run a function from it:
$ gcc -o opener opener.c -ldl
$ ./opener
called from opener.c
Finally, we link against this shared object:
/* main.c */
#include "multi.h"
int main(int argc, char **argv) {
multi(__FILE__);
}
Where we compile and run it as follows:
$ gcc main.c -o main multi.so
$ LD_LIBRARY_PATH=./ ./main
called from main.c
(Note, because multi.so isn't in a standard system library location, we need to override where the runtime looks for the shared object file with the LD_LIBRARY_PATH environment variable.)
I suppose you'd have your ld -e point to an entry point which would then use the dlopen() family of functions to find and bootstrap the rest of the dynamic linker. Of course you'd have to ensure that dlopen() itself was either statically linked or you might have to implement enough of your own linker stub to get at it (using system call interfaces such as mmap() just as libc itself is doing.
None of that sounds "nice" to me. In fact just the thought of reading the glibc sources (and the ld-linux source code, as one example) enough to assess the size of the job sounds pretty hoary to me. It might also be a portability nightmare. There may be major differences between how Linux implements ld-linux and how the linkages are done under OpenSolaris, FreeBSD, and so on. (I don't know).
I'm dynamically overriding malloc() with a fast_malloc() implementation of mine in a glibc benchmark malloc speed test (glibc/benchtests/bench-malloc-thread.c), by writing these functions in my fast_malloc.c file:
// Override malloc() and free(); see: https://stackoverflow.com/a/262481/4561887
inline void* malloc(size_t num_bytes)
{
static bool first_call = true;
if (first_call)
{
first_call = false;
fast_malloc_error_t error = fast_malloc_init();
assert(error == FAST_MALLOC_ERROR_OK);
}
return fast_malloc(num_bytes);
}
inline void free(void* ptr)
{
fast_free(ptr);
}
Notice that I have this inefficient addition to my malloc() wrapper to ensure fast_malloc_init() gets called first on just the first call, to initialize some memory pools. I'd like to get rid of that and dynamically insert that init call into the start of main(), without modifying the glibc code, if possible. Is this possible?
The downside of how I've written my malloc() wrapper so far is it skews my benchtest results making it look like my fast_malloc() is slower than it really is, because the init func gets timed by glibc/benchtests/bench-malloc-thread.c, and I have this extraneous if (first_call) which gets checked every malloc call.
Currently I dynamically override malloc() and free(), while calling the bench-malloc-thread executable, like this:
LD_PRELOAD='/home/gabriel/GS/dev/fast_malloc/build/libfast_malloc.so' \
glibc-build/benchtests/bench-malloc-thread 1
Plot I will be adding my fast_malloc() speed tests to (using this repo):
LinkedIn post I made about this: https://www.linkedin.com/posts/gabriel-staples_software-engineering-tradeoffs-activity-6815412255325339648-_c8L.
Related:
[my repo fork] https://github.com/ElectricRCAircraftGuy/malloc-benchmarks
[how I learned how to generate *.so dynamic libraries in gcc] https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
Create a wrapper function for malloc and free in C
Is this possible?
Yes. You are building and LD_PRELOADing a shared library, and shared libraries can have special initializer and finalizer functions, which are called by the dynamic loader when the library is loaded and unloaded respectively.
As kaylum commented, to create such a constructor, you would use __attribute__((constructor)), like so:
__attribute__((constructor))
void fast_malloc_init_ctor()
{
fast_malloc_error_t error = fast_malloc_init();
assert(error == FAST_MALLOC_ERROR_OK);
}
// ... the rest of implementation here.
P.S.
it skews my benchtest results making it look like my fast_malloc() is slower than it really is, because the init func gets timed
You are comparing with multi-threaded benchmarks. Note that your static bool fist_call is not thread-safe. In practice this will not matter, because malloc is normally called long before any threads (other than the main thread) exist.
I doubt that this single comparison actually makes your fast_malloc() slower. It probably is slower even after you remove the comparison -- writing a fast heap allocator takes a lot of effort, and smart people have spent many man-years optimizing GLIBC malloc, TCMalloc and jemalloc.
How to dynamically inject function calls before and after another executable's main() function.
Here is a full, runnable example for anyone wanting to test this on their own. Tested on Linux Ubuntu 20.04.
This code is all part of my eRCaGuy_hello_world repo.
hello_world_basic.c:
#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h> // For `uint8_t`, `int8_t`, etc.
#include <stdio.h> // For `printf()`
// int main(int argc, char *argv[]) // alternative prototype
int main()
{
printf("This is the start of `main()`.\n");
printf(" Hello world.\n");
printf("This is the end of `main()`.\n");
return 0;
}
dynamic_func_call_before_and_after_main.c:
#include <assert.h>
#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h> // For `uint8_t`, `int8_t`, etc.
#include <stdio.h> // For `printf()`
#include <stdlib.h> // For `atexit()`
/// 3. This function gets attached as a post-main() callback (a sort of program "destructor")
/// via the C <stdlib.h> `atexit()` call below
void also_called_after_main()
{
printf("`atexit()`-registered callback functions are also called AFTER `main()`.\n");
}
/// 1. Functions with gcc function attribute, `constructor`, get automatically called **before**
/// `main()`; see:
/// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
__attribute__((__constructor__))
void called_before_main()
{
printf("gcc constructors are called BEFORE `main()`.\n");
// 3. Optional way to register a function call for AFTER main(), although
// I prefer the simpler gcc `destructor` attribute technique below, instead.
int retcode = atexit(also_called_after_main);
assert(retcode == 0); // ensure the `atexit()` call to register the callback function succeeds
}
/// 2. Functions with gcc function attribute, `destructor`, get automatically called **after**
/// `main()`; see:
/// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
__attribute__((__destructor__))
void called_after_main()
{
printf("gcc destructors are called AFTER `main()`.\n");
}
How to build and run the dynamic lib*.so shared-object library and dynamically load it with LD_PRELOAD as you run another program (see "dynamic_func_call_before_and_after_main__build_and_run.sh from my eRCaGuy_hello_world repo"):
# 1. Build the other program (hello_world_basic.c) that has `main()` in it which we want to use
mkdir -p bin && gcc -Wall -Wextra -Werror -O3 -std=c11 -save-temps=obj hello_world_basic.c \
-o bin/hello_world_basic
# 2. Create a .o object file of this program, compiling with Position Independent Code (PIC); see
# here: https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
gcc -Wall -Wextra -Werror -O3 -std=c11 -fpic -c dynamic_func_call_before_and_after_main.c \
-o bin/dynamic_func_call_before_and_after_main.o
# 3. Link the above PIC object file into a dynamic shared library (`lib*.so` file); link above shows
# we must use `-shared`
gcc -shared bin/dynamic_func_call_before_and_after_main.o -o \
bin/libdynamic_func_call_before_and_after_main.so
# 4. Call the other program with `main()` in it, dynamically injecting this code into that other
# program via this code's .so shared object file, and via Linux's `LD_PRELOAD` trick
LD_PRELOAD='bin/libdynamic_func_call_before_and_after_main.so' bin/hello_world_basic
Sample output. Notice that we have injected some special function calls both before AND after the main() function found in "hello_world_basic.c":
gcc constructors are called BEFORE `main()`.
This is the start of `main()`.
Hello world.
This is the end of `main()`.
gcc destructors are called AFTER `main()`.
`atexit()`-registered callback functions are also called AFTER `main()`.
References:
How to build dynamic lib*.so libraries in Linux: https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
#kaylum's comment
#Employed Russian's answer
#Lundin's comment
gcc constructor and destructor function attributes!:
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
c atexit() func to register functions to be called AFTER main() returns or exits!:
https://en.cppreference.com/w/c/program/atexit
I am using dlsym to look up symbols in my program, but it always returns NULL, which I am not expecting. According to the manpage, dlsym may return NULL if there was an error somehow, or if the symbol indeed is NULL. In my case, I am getting an error. I will show you the MCVE I have made this evening.
Here is the contents of instr.c:
#include <stdio.h>
void * testing(int i) {
printf("You called testing(%d)\n", i);
return 0;
}
A very simple thing containing only an unremarkable example function.
Here is the contents of test.c:
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
typedef void * (*dltest)(int);
int main(int argc, char ** argv) {
/* Declare and set a pointer to a function in the executable */
void * handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
dlerror();
dltest fn = dlsym(handle, "testing");
if(fn == NULL) {
printf("%s\n", dlerror());
dlclose(handle);
return 1;
}
dlclose(handle);
return 0;
}
As I step through the code with the debugger, I see the dlopen is returning a handle. According to the manpage, If filename is NULL, then the returned handle is for the main program. So if I link a symbol called testing into the main program, dlsym should find it, right?
Here is the way that I am compiling and linking the program:
all: test
instr.o: instr.c
gcc -ggdb -Wall -c instr.c
test.o: test.c
gcc -ggdb -Wall -c test.c
test: test.o instr.o
gcc -ldl -o test test.o instr.o
clean:
rm -f *.o test
And when I build this program, and then do objdump -t test | grep testing, I see that the symbol testing is indeed there:
08048632 g F .text 00000020 testing
Yet the output of my program is the error:
./test: undefined symbol: testing
I am not sure what I am doing wrong. I would appreciate if someone could shed some light on this problem.
I don't think you can do that, dlsym works on exported symbols. Because you're doing dlsym on NULL (current image), even though the symbols are present in the executable ELF image, they're not exported (since it's not a shared library).
Why not call it directly and let the linker take care of it? There's no point in using dlsym to get symbols from the same image as your dlsym call. If your testing symbol was in a shared library that you either linked against or loaded using dlopen then you would be able to retrieve it.
I believe there's also a way of exporting symbols when building executables (-Wl,--export-dynamic as mentioned in a comment by Brandon) but I'm not sure why you'd want to do that.
I faced the similar issue in my code.
I did the following to export symbols
#ifndef EXPORT_API
#define EXPORT_API __attribute__ ((visibility("default")))
#endif
Now for each of the function definition I used the above attribute.
For example the earlier code was
int func() { printf(" I am a func %s ", __FUNCTION__ ) ;
I changed to
EXPORT_API int func() { printf(" I am a func %s ", __FUNCTION__ ) ;
Now it works.
dlsym gives no issues after this.
Hope this works for you as well.
Is there an equivalent of the following on Windows?
#include <dlfcn.h>
#include <stdio.h>
void main_greeting(void)
{
printf("%s\n", "hello world");
}
void lib_func(void)
{
void (*greeting)(void) = dlsym(RTLD_MAIN_ONLY, "main_greeting");
greeting ? greeting() : printf("%s\n", dlerror());
}
int main(void)
{
lib_func();
return 0;
}
This is a short snippet, the real purpose is to call a function know to exist at a main process (main_greeting), from inside a function (lib_func) from a dynamic loaded library. The main process is not modifiable, and so cannot be rewritten to pass callbacks.
On Windows, executables and DLLs are of the same format (PE nowadays), so an executable can export functions too. GetProcAddress(GetModuleHandle(NULL),TEXT("main_greeting")) will do what you want if the function is exported from the executable. It's done by -Wl,-export-all-symbols for mingw GCC.
I believe there is no equivalent option for Microsoft's linker, so if you use their toolchain, you have to:
export every function with __declspec(dllexport) in source files,
or write a module definition file listing every exported function, passing it to linker,
or generate module definition file automatically.
I'm writing a program in C which allows users to implement custom "functions" to be run by an interpreter of sorts. I also want to allow users to write these custom functions in plain C, and then be loaded in dynamically. In order to do this, I created two structs, one for interpreted functions, and one for native ones.
Here's a simplified example:
struct func_lang {
bool is_native;
char* identifier;
// various other properties
}
typedef void (*func_native_ptr)(int);
struct func_native {
bool is_native;
char* identifier;
func_native_ptr func_ptr;
}
I then use the identifier property of each struct to put them in a hashtable, which I can then use to execute them at runtime.
My problem is actually from the other end, the loaded libraries. I'd like to be able to allow the loaded libraries to "publish" which functions they want inserted into the list. For example, maybe with a function like this:
void register_func_native(char* identifer, func_native_ptr func_ptr);
Then, when I would call an init function from the library, they could call this function to insert the functions into the hashtable.
Will this work? I'm a little confused about how the register_func_native function would be linked, since it's needed by the loaded library, but would have to be defined by the loader itself. Does my loader function need to be implemented in another shared library, which could then be linked at runtime?
This will depend on the platform, but on Linux and all the Unixes I've seen, this will work. Example:
$ cat dll.c
void print(char const *);
void foo()
{
print("Hello!");
}
$ gcc -Wall -shared -fPIC -o dll.so dll.c
$ cat main.c
#include <dlfcn.h>
#include <stdio.h>
void print(char const *msg)
{
puts(msg);
}
int main()
{
void *lib = dlopen("./dll.so", RTLD_NOW);
void (*foo)() = (void (*)())dlsym(lib, "foo");
foo();
return 0;
}
$ cc -fPIC -rdynamic main.c -ldl
$ ./a.out
Hello!
It will work. The shared library sees all the global symbols you have in your main program.
In the main program you'll need dlopen() and dlsym() to call the initialization function.