Ticket #3807 (closed bug: fixed)

Opened 3 years ago

Last modified 3 years ago

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 Difficulty:
Test Case: T3807 Blocked By:
Blocking: Related Tickets:

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

Changed 3 years ago by igloo

  • milestone set to 6.12.2

Thanks for the report.

Changed 3 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?

Changed 3 years ago by igloo

  • priority changed from normal to high
  • milestone changed from 6.12.2 to 6.12.3

Changed 3 years ago by igloo

  • milestone changed from 6.12.3 to 6.14.1

Changed 3 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.

Changed 3 years ago by igloo

  • owner changed from duncan to igloo

Thanks Duncan

Changed 3 years ago by igloo

  • status changed from new to closed
  • testcase set to T3807
  • resolution set to fixed

Test added

Note: See TracTickets for help on using tickets.