diff options
author | Guy Martin <gmsoft@tuxicoman.be> | 2013-11-21 13:23:16 -0500 |
---|---|---|
committer | Carlos O'Donell <carlos@redhat.com> | 2013-11-21 15:52:31 -0500 |
commit | daf75146de07303ea0c5ad700ec5ef703ec114a1 (patch) | |
tree | ed307e39a90288cbcdf727a7c07addb9f38f65d8 /ports/sysdeps/ia64/dl-lookupcfg.h | |
parent | d33cafadfe365befa4ca6e0463fa926d56144046 (diff) | |
download | glibc-daf75146de07303ea0c5ad700ec5ef703ec114a1.tar.gz glibc-daf75146de07303ea0c5ad700ec5ef703ec114a1.tar.xz glibc-daf75146de07303ea0c5ad700ec5ef703ec114a1.zip |
Don't use broken DL_AUTO_FUNCTION_ADDRESS()
On hppa and ia64, the macro DL_AUTO_FUNCTION_ADDRESS() uses the variable fptr[2] in it's own scope. The content of fptr[] is thus undefined right after the macro exits. Newer gcc's (>= 4.7) reuse the stack space of this variable triggering a segmentation fault in dl-init.c:69. To fix this we rewrite the macros to make the call directly to init and fini without needing to pass back a constructed function pointer.
Diffstat (limited to 'ports/sysdeps/ia64/dl-lookupcfg.h')
-rw-r--r-- | ports/sysdeps/ia64/dl-lookupcfg.h | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/ports/sysdeps/ia64/dl-lookupcfg.h b/ports/sysdeps/ia64/dl-lookupcfg.h index 4da12635c8..cfaa2520b3 100644 --- a/ports/sysdeps/ia64/dl-lookupcfg.h +++ b/ports/sysdeps/ia64/dl-lookupcfg.h @@ -39,24 +39,28 @@ extern void _dl_unmap (struct link_map *map); #define DL_UNMAP(map) _dl_unmap (map) -#define DL_AUTO_FUNCTION_ADDRESS(map, addr) \ -({ \ - unsigned long int fptr[2]; \ - fptr[0] = (unsigned long int) (addr); \ - fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr; \ - (Elf64_Addr) fptr; \ -}) - -#define DL_STATIC_FUNCTION_ADDRESS(map, addr) \ -({ \ - static unsigned long int fptr[2]; \ - fptr[0] = (unsigned long int) (addr); \ - fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr; \ - (Elf64_Addr) fptr; \ -}) - -#define DL_DT_INIT_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr) -#define DL_DT_FINI_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr) +#define DL_DT_FUNCTION_ADDRESS(map, start, attr, addr) \ + attr volatile unsigned long int fptr[2]; \ + fptr[0] = (unsigned long int) (start); \ + fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr; \ + addr = (ElfW(Addr)) fptr; \ + +#define DL_CALL_DT_INIT(map, start, argc, argv, env) \ +{ \ + ElfW(Addr) addr; \ + DL_DT_FUNCTION_ADDRESS(map, start, , addr) \ + init_t init = (init_t) addr; \ + init (argc, argv, env); \ +} + +#define DL_CALL_DT_FINI(map, start) \ +{ \ + ElfW(Addr) addr; \ + DL_DT_FUNCTION_ADDRESS(map, start, , addr) \ + fini_t fini = (fini_t) addr; \ + fini (); \ +} + /* The type of the return value of fixup/profile_fixup. */ #define DL_FIXUP_VALUE_TYPE struct fdesc /* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address |