[GHC] #8935: Obscure linker bug leads to crash in GHCi
GHC
ghc-devs at haskell.org
Wed May 7 18:57:31 UTC 2014
#8935: Obscure linker bug leads to crash in GHCi
-------------------------------------+------------------------------------
Reporter: simonmar | Owner: simonmar
Type: bug | Status: patch
Priority: high | Milestone: 7.8.3
Component: Runtime System | Version: 7.8.1-rc2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture: Unknown/Multiple
Type of failure: GHCi crash | Difficulty: Rocket Science
Test Case: | Blocked By:
Blocking: | Related Tickets:
-------------------------------------+------------------------------------
Comment (by dagit):
After playing with your example a bit I see what you mean about the copy
semantics. I found this article:
http://netwinder.osuosl.org/users/p/patb/public_html/elf_relocs.html
Interestingly, [http://src.gnu-darwin.org/src/libexec/rtld-
elf/amd64/reloc.c.html glibc] has these comments:
{{{
/*
* Process the special R_X86_64_COPY relocations in the main program.
These
* copy data from a shared object into a region in the main program's BSS
* segment.
*
* Returns 0 on success, -1 on failure.
*/
int
do_copy_relocations(Obj_Entry *dstobj)
}}}
And:
{{{
case R_X86_64_COPY:
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are
allowed
* only in executable files.
*/
}}}
The elf interpreter delays processing of the `R_COPY`'s so that it gets
the correct behavior. I think this supports your earlier hypothesis.
At this point, I noticed that I can switch `environ` in the executable
between `R_X86_64_GLOB_DAT` and `R_X86_64_COPY` by adding `-fPIC` (you
probably already knew that). Specifically, without `-fPIC` I get copy and
with it I get glob dat.
Test program again:
{{{
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
extern char**environ;
char envname[] = "environ";
void dlsym_check(void *handle, char * lib, char * sym){
void * e = dlsym(handle,sym);
fprintf(stderr, "dlsym(\"%s\", \"%s\") = %p\n", lib, sym, e);
char * error = dlerror();
if( error != NULL )
fprintf(stderr, "Errors: %s\n", error);
}
int main(int argc, char *argv[])
{
if( argc < 2 ){
printf("usage: ./check-environ <path to shared object>\n");
exit(1);
}
char* so = argv[1];
void *deflt, *hdl;
fprintf(stderr, "environ = %p\n", &environ);
deflt = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
fprintf(stderr, "\nFind a symbol after passing NULL to dlopen:\n");
dlsym_check(deflt, NULL, envname);
hdl = dlopen(so, RTLD_LAZY | RTLD_GLOBAL);
if( hdl == NULL ){
fprintf(stderr, "Error: %s", dlerror());
exit(1);
}
fprintf(stderr, "\nFind a symbol that is located here and libc (handle
comes from dlopen on %s)\n", so);
dlsym_check(hdl, so, envname);
}
}}}
{{{
$ ./check-environ-without-pic /usr/lib64/libgmp.so.10
environ = 0x601070
Find a symbol after passing NULL to dlopen:
dlsym("(null)", "environ") = 0x601070
Find a symbol that is located here and libc (handle comes from dlopen on
/usr/lib64/libgmp.so.10)
dlsym("/usr/lib64/libgmp.so.10", "environ") = 0x31e45bd508
$ ./check-environ-with-pic /usr/lib64/libgmp.so.10
environ = 0x31e45bd508
Find a symbol after passing NULL to dlopen:
dlsym("(null)", "environ") = 0x31e45bd508
Find a symbol that is located here and libc (handle comes from dlopen on
/usr/lib64/libgmp.so.10)
dlsym("/usr/lib64/libgmp.so.10", "environ") = 0x31e45bd508
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8935#comment:39>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list