Opened 8 years ago

Closed 7 years ago

#3807 closed bug (fixed)

Test for correct shared library generation

Reported by: asuffield Owned by: igloo
Priority: high Milestone: 7.0.1
Component: Test Suite Version: 6.12.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: T3807
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

There doesn't seem to be a test that verifies shared libraries are correctly created. It's not immediately obvious how to get the test suite driver to run this sort of thing, so I don't have a full patch for it, but this illustrates how it should work on ELF and ELF-like platforms:

asuffield@cyclone:~/work/ghc-test$ cat TestExport.hs
module Test where
asuffield@cyclone:~/work/ghc-test$ cat test-export.c
#include <HsFFI.h>

extern void __stginit_Test(void);

void
test_init (void)
{
  static char *argv[] = { "test.so", 0 }, **argv_ = argv;
  static int argc = 1;

  hs_init (&argc, &argv_);
  hs_add_root (__stginit_Test);
}

void
test_exit (void)
{
  hs_exit ();
}
asuffield@cyclone:~/work/ghc-test$ cat testload.c
#include <dlfcn.h>
#include <stdio.h>

int main(void) {
  void *dh = dlopen("./test.so", RTLD_NOW | RTLD_GLOBAL);
  if (!dh) {
    printf("%s\n", dlerror());
    return 1;
  }

  void (*test_init)(void) = dlsym(dh, "test_init");
  void (*test_exit)(void) = dlsym(dh, "test_exit");

  test_init();
  test_exit();

  return 0;
}
asuffield@cyclone:~/work/ghc-test$ ghc --make -dynamic -fPIC -shared TestExport.hs test-export.c -o test.so
[1 of 1] Compiling Test             ( TestExport.hs, TestExport.o )
Linking test.so ...
asuffield@cyclone:~/work/ghc-test$ gcc -o testload testload.c -ldl
asuffield@cyclone:~/work/ghc-test$ ./testload
/usr/lib/ghc-6.12.0.20091126/ghc-prim-0.2.0.0/libHSghc-prim-0.2.0.0-ghc6.12.0.20091126.so: undefined symbol: stg_newByteArrayzh

You'll note that the test failed here, in a way which illustrates why the current FFI tests don't properly exercise this: the shared library references symbols from libHSrts*.so, but does not link to it. If testload had been compiled with ghc instead of gcc (like all the current FFI tests) then the binary itself would have picked up that library and caused a false pass; doing it this way verifies that shared libraries can be loaded into foreign programs. The use of dlopen here is simply to force strict loading of the shared library in a reasonably portable manner, since linking directly to it is lazily evaluated on many platforms.

Incidentally, I suspect this will fail on current versions.

Change History (7)

comment:1 Changed 8 years ago by igloo

Milestone: 6.12.2

Thanks for the report.

comment:2 Changed 8 years ago by igloo

Owner: set to duncan

Duncan, can you please say how this should be done, and I'll add a testcase for it to the testsuite?

comment:3 Changed 8 years ago by igloo

Milestone: 6.12.26.12.3
Priority: normalhigh

comment:4 Changed 7 years ago by igloo

Milestone: 6.12.36.14.1

comment:5 Changed 7 years ago by duncan

It is right that we currently do not automatically link shared libs to the rts. This is because we have not got round to sorting that out yet. Currently people making shared libs to be dlopen()ed have to add the link to a specific flavour of the rts themselves. The plan is to have a scheme where we link to the rts but do not commit to which flavour, so that one can override the choice later either during a final link of an executable, or e.g. at runtime with LD_PRELOAD. This is so that the same lib can be used with the normal, threaded or profiling versions of the runtime.

For a test then, at the moment it would have to add a -l link flag for the rts, e.g. the normal rts way. The dlopen test is a good idea. It just needs the extra step at the moment of manually adding a link flag for the rts.

See: http://www.well-typed.com/blog/30

I thought we also had a ticket about the rts linking issue but I cannot find it. If we don't, we should. The idea is to have all the rts ways use the sane SONAME but to live in different directories. Then we link things to the rts soname and give an rpath to one rts flavour, but the top level binary can use its own rpath, also any LD_PRELOADed rts will take precedence.

comment:6 Changed 7 years ago by igloo

Owner: changed from duncan to igloo

Thanks Duncan

comment:7 Changed 7 years ago by igloo

Resolution: fixed
Status: newclosed
Test Case: T3807

Test added

Note: See TracTickets for help on using tickets.