diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 96f91dec0a..2cf0a271e8 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -28,7 +28,8 @@ struct rld_export { // runtime loader API export image_id (*load_add_on)(char const *path, uint32 flags); status_t (*unload_add_on)(image_id imageID); - image_id (*load_library)(char const *path, uint32 flags, void **_handle); + image_id (*load_library)(char const *path, uint32 flags, void* caller, + void **_handle); status_t (*unload_library)(void* handle); status_t (*get_image_symbol)(image_id imageID, char const *symbolName, int32 symbolType, bool recursive, image_id *_inImage, void **_location); diff --git a/src/system/libroot/posix/dlfcn.c b/src/system/libroot/posix/dlfcn.c index 6ba7855c06..cce1697623 100644 --- a/src/system/libroot/posix/dlfcn.c +++ b/src/system/libroot/posix/dlfcn.c @@ -25,7 +25,9 @@ void * dlopen(char const *name, int mode) { void* handle; - image_id imageID = __gRuntimeLoader->load_library(name, mode, &handle); + void* caller = __builtin_return_address(0); + image_id imageID = __gRuntimeLoader->load_library(name, mode, caller, + &handle); sStatus = imageID >= 0 ? B_OK : imageID; diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index 64b6f40eb9..88178fe317 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -600,11 +600,14 @@ err: image_id -load_library(char const *path, uint32 flags, bool addOn, void** _handle) +load_library(char const *path, uint32 flags, bool addOn, void* caller, + void** _handle) { image_t *image = NULL; image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); status_t status; + const char* rpath = NULL; + const char* requestingObjectPath = NULL; if (path == NULL && addOn) return B_BAD_VALUE; @@ -634,9 +637,24 @@ load_library(char const *path, uint32 flags, bool addOn, void** _handle) *_handle = image; return image->id; } + + // First of all, find the caller image. + image_t* callerImage = get_loaded_images().head; + for (; callerImage != NULL; callerImage = callerImage->next) { + elf_region_t& text = callerImage->regions[0]; + if ((addr_t)caller >= text.vmstart + && (addr_t)caller < text.vmstart + text.vmsize) { + // found the image + break; + } + } + if (callerImage != NULL) { + rpath = find_dt_rpath(callerImage); + requestingObjectPath = callerImage->path; + } } - status = load_image(path, type, NULL, NULL, &image); + status = load_image(path, type, rpath, requestingObjectPath, &image); if (status < B_OK) { KTRACE("rld: load_library(\"%s\") failed to load container: %s", path, strerror(status)); diff --git a/src/system/runtime_loader/export.cpp b/src/system/runtime_loader/export.cpp index 493ef5d5c5..70c742d006 100644 --- a/src/system/runtime_loader/export.cpp +++ b/src/system/runtime_loader/export.cpp @@ -18,7 +18,7 @@ static image_id export_load_add_on(char const *name, uint32 flags) { void* handle; - return load_library(name, flags, true, &handle); + return load_library(name, flags, true, NULL, &handle); } @@ -30,9 +30,10 @@ export_unload_add_on(image_id id) static image_id -export_load_library(char const *name, uint32 flags, void **_handle) +export_load_library(char const *name, uint32 flags, void* caller, + void **_handle) { - return load_library(name, flags, false, _handle); + return load_library(name, flags, false, caller, _handle); } diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index 816fc39006..857bc0227b 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -72,7 +72,7 @@ status_t get_executable_architecture(const char* path, void terminate_program(void); image_id load_program(char const* path, void** entry); image_id load_library(char const* path, uint32 flags, bool addOn, - void** _handle); + void* caller, void** _handle); status_t unload_library(void* handle, image_id imageID, bool addOn); status_t get_nth_symbol(image_id imageID, int32 num, char* nameBuffer, int32* _nameLength, int32* _type, void** _location);