summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2013-03-22 17:48:51 +0100
committerBernd Schmidt <bernds@codesourcery.com>2013-03-22 18:01:33 +0100
commit6239e4c69d7fb09fb2313c0947a28127e1321631 (patch)
tree05b1f8d65d63495489c6aa715b49ab8807debe06
parent697427cc42ca3c6794dc26f3a379866de71bb91b (diff)
Fix some fragileness in dlopen/do_dlopen wrapper & worker pair.
do_dlopen contains __builtin_return_address to determine from whence it was called, and uses that to determine which dynamic object's data it should use to start the search. (In the bug I was tracking, this related to whether the application's RPATH was used or not.) For that to work, it has to have been inlined into the wrapper function. As it happens, it wasn't being inlined. That's an unfortunate compiler behaviour, but it isn't wrong and shouldn't have caused dlopen to fail. This patch changes things so the wrapper function determines the return address, and passes it to the worker. If the worker's inlined, the generated code should be exactly the same as before. Signed-off-by: Nathan Sidwell <nathan@codesourcery.com> Signed-off-by: Bernd Schmidt <bernds@codesourcery.com>
-rw-r--r--ldso/libdl/libdl.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 233722382..4630a5942 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -296,11 +296,10 @@ static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
return p - list;
}
-static void *do_dlopen(const char *libname, int flag)
+static void *do_dlopen(const char *libname, int flag, ElfW(Addr) from)
{
struct elf_resolve *tpnt, *tfrom;
struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
- ElfW(Addr) from;
struct elf_resolve *tpnt1;
void (*dl_brk) (void);
int now_flag;
@@ -320,8 +319,6 @@ static void *do_dlopen(const char *libname, int flag)
return NULL;
}
- from = (ElfW(Addr)) __builtin_return_address(0);
-
if (!_dl_init) {
_dl_init = true;
_dl_malloc_function = malloc;
@@ -661,7 +658,8 @@ void *dlopen(const char *libname, int flag)
void *ret;
__UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
- ret = do_dlopen(libname, flag);
+ ret = do_dlopen(libname, flag,
+ (ElfW(Addr)) __builtin_return_address(0));
__UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
return ret;