forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Demos: Add a dynamic linking demo to show off dlfcn methods
The LinkDemo program calls dlopen/dlsym/dlclose to try and load a dyanmic library from /usr/lib. It read a global variable and calls a global function (extern "C" of course :) ). There a few hacks left in the LinkLib dynamic library, however. In order to get the linker to stop complaining, we have to use -nostartfiles -ffreestanding otherwise it will link crt0.o to our shared object, which is definitely not right as the _init function for a main program (that calls main) is not suitable for our lib
- Loading branch information
1 parent
2116134
commit b6590b7
Showing
7 changed files
with
179 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
*.o | ||
*.ao | ||
*.a | ||
|
||
*.so | ||
*.d | ||
|
||
*.swp | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
OBJS = \ | ||
main.o | ||
|
||
PROGRAM = LinkDemo | ||
|
||
include ../../../Makefile.common |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#include <AK/String.h> | ||
|
||
#include <dlfcn.h> | ||
#include <stdio.h> | ||
|
||
int main() | ||
{ | ||
void* handle = dlopen("/usr/lib/libDynamicLib.so", RTLD_LAZY | RTLD_GLOBAL); | ||
|
||
if (!handle) { | ||
printf("Failed to dlopen! %s\n", dlerror()); | ||
return 1; | ||
} | ||
|
||
// Test getting an external variable from the library and read it out | ||
int* ptr_global = (int*)dlsym(handle, "global_lib_variable"); | ||
|
||
if (!ptr_global) { | ||
printf("Failed to dlsym for \"global_lib_variable\"! %s\n", dlerror()); | ||
return 2; | ||
} | ||
|
||
printf("Found global lib variable address: %p\n", ptr_global); | ||
|
||
printf("Global lib variable is %d\n", *ptr_global); | ||
|
||
// Test getting a method from the library and calling it | ||
void (*lib_func)(void) = (void (*)(void))dlsym(handle, "global_lib_function"); | ||
|
||
printf("Found global lib function address: %p\n", lib_func); | ||
|
||
if (!lib_func) { | ||
printf("Failed to dlsym for \"global_lib_function\"! %s\n", dlerror()); | ||
return 2; | ||
} | ||
|
||
lib_func(); | ||
|
||
printf("I think I called my lib function!\n"); | ||
|
||
// Test getting a method that takes and returns arugments now | ||
const char* (*other_func)(int) = (const char* (*)(int))dlsym(handle, "other_lib_function"); | ||
|
||
printf("Found other lib function address %p\n", other_func); | ||
|
||
if (!other_func) { | ||
printf("Failed to dlsym for \"other_lib_function\"! %s\n", dlerror()); | ||
return 2; | ||
} | ||
|
||
// Call it twice with different arguments | ||
String formatted_result = other_func(10); | ||
|
||
printf("(%d + %d = %d) %s\n", *ptr_global, 10, *ptr_global + 10, formatted_result.characters()); | ||
|
||
*ptr_global = 17; | ||
|
||
formatted_result = other_func(5); | ||
|
||
printf("(%d + %d = %d) %s\n", *ptr_global, 5, *ptr_global + 5, formatted_result.characters()); | ||
|
||
int ret = dlclose(handle); | ||
|
||
if (ret < 0) { | ||
printf("Failed to dlclose! %s\n", dlerror()); | ||
return 3; | ||
} | ||
|
||
printf("Bye for now!\n"); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#include <AK/kstdio.h> | ||
#include <AK/String.h> | ||
#include <assert.h> | ||
#include <stdio.h> | ||
|
||
// FIXME: See Makefile. We need -ffreestanding and -nostartfiles to | ||
// Get GCC to stop linking crt0.o w/our .so. | ||
// So, we need __dso_handle. ... Yikes | ||
extern void* __dso_handle __attribute__((__section__(".sdata"))); | ||
extern void* __dso_handle __attribute__((__visibility__("hidden"))); | ||
void* __dso_handle = (void*)1234; // FIXME: Is the dynamic linker supposed to set this value? | ||
|
||
// FIXME: Things defined in crt0 >:( | ||
__thread int errno; | ||
char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds.. | ||
char** environ = __static_environ; | ||
bool __environ_is_malloced = false; | ||
extern unsigned __stack_chk_guard; | ||
unsigned __stack_chk_guard = (unsigned)0xc0000c13; | ||
|
||
[[noreturn]] void __stack_chk_fail() | ||
{ | ||
ASSERT_NOT_REACHED(); | ||
} | ||
|
||
// FIXME: Because we need to call printf, and we don't have access to the stout file descriptor | ||
// from the main executable, we need to create our own copy in __stdio_init :/ | ||
// Same deal for malloc init. We're essentially manually calling __libc_init here. | ||
extern "C" void __stdio_init(); | ||
extern "C" void __malloc_init(); | ||
|
||
class Global { | ||
public: | ||
Global(int i) | ||
: m_i(i) | ||
{ | ||
__malloc_init(); | ||
__stdio_init(); | ||
} | ||
|
||
int get_i() const { return m_i; } | ||
|
||
private: | ||
int m_i = 0; | ||
}; | ||
|
||
// This object exists to call __stdio_init and __malloc_init. Also to show that global vars work | ||
Global g_glob { 5 }; | ||
|
||
extern "C" { | ||
int global_lib_variable = 1234; | ||
|
||
void global_lib_function() | ||
{ | ||
printf("Hello from Dynamic Lib! g_glob::m_i == %d\n", g_glob.get_i()); | ||
} | ||
|
||
const char* other_lib_function(int my_argument) | ||
{ | ||
dbgprintf("Hello from Dynamic Lib, now from the debug port! g_glob::m_i == %d\n", g_glob.get_i()); | ||
|
||
int sum = my_argument + global_lib_variable; | ||
|
||
// FIXME: We can't just return AK::String::format across the lib boundary here. | ||
// It will use malloc from our DSO's copy of LibC, and then probably be free'd into | ||
// the malloc of the main program which would be what they call 'very crash'. | ||
// Feels very Windows :) | ||
static String s_string; | ||
s_string = String::format("Here's your string! Sum of argument and global_lib_variable: %d", sum); | ||
return s_string.characters(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
|
||
include ../../../Makefile.common | ||
|
||
DYNLIBRARY = libDynamicLib.so | ||
|
||
.PHONY: clean all | ||
|
||
all: $(DYNLIBRARY) | ||
|
||
DynamicLib.o: DynamicLib.cpp | ||
$(CXX) -DDEBUG -fPIC -isystem../../../ -o $@ -c $< | ||
|
||
# FIXME: Why do I need -nostartfiles and -nofreestanding? | ||
# GCC isn't smart enough to not link crt0 against this dynamic lib | ||
# which is clearly wrong. Isn't it? We don't want _start... | ||
$(DYNLIBRARY): DynamicLib.o | ||
$(CXX) -shared -nostartfiles -ffreestanding -o $(DYNLIBRARY) $< | ||
|
||
clean: | ||
rm -f *.o *.d *.so |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
SUBDIRS := $(wildcard */.) | ||
|
||
include ../../Makefile.subdir |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters