mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-08 05:54:40 +00:00
154 lines
3.7 KiB
D
154 lines
3.7 KiB
D
import core.runtime;
|
|
import core.stdc.stdio;
|
|
import core.stdc.string;
|
|
import core.thread;
|
|
|
|
import core.sys.posix.dlfcn;
|
|
|
|
version (DragonFlyBSD) import core.sys.dragonflybsd.dlfcn : RTLD_NOLOAD;
|
|
version (FreeBSD) import core.sys.freebsd.dlfcn : RTLD_NOLOAD;
|
|
version (linux) import core.sys.linux.dlfcn : RTLD_NOLOAD;
|
|
version (NetBSD) import core.sys.netbsd.dlfcn : RTLD_NOLOAD;
|
|
version (OSX) import core.sys.darwin.dlfcn : RTLD_NOLOAD;
|
|
version (Solaris) import core.sys.solaris.dlfcn : RTLD_NOLOAD;
|
|
|
|
static assert(__traits(compiles, RTLD_NOLOAD), "unimplemented");
|
|
|
|
void loadSym(T)(void* handle, ref T val, const char* mangle)
|
|
{
|
|
val = cast(T).dlsym(handle, mangle);
|
|
}
|
|
|
|
void* openLib(string s)
|
|
{
|
|
auto h = Runtime.loadLibrary(s);
|
|
assert(h !is null);
|
|
|
|
loadSym(h, libThrowException, "_D3lib14throwExceptionFZv");
|
|
loadSym(h, libCollectException, "_D3lib16collectExceptionFDFZvZC9Exception");
|
|
|
|
loadSym(h, libAlloc, "_D3lib5allocFZv");
|
|
loadSym(h, libTlsAlloc, "_D3lib9tls_allocFZv");
|
|
loadSym(h, libAccess, "_D3lib6accessFZv");
|
|
loadSym(h, libTlsAccess, "_D3lib10tls_accessFZv");
|
|
loadSym(h, libFree, "_D3lib4freeFZv");
|
|
loadSym(h, libTlsFree, "_D3lib8tls_freeFZv");
|
|
|
|
loadSym(h, libSharedStaticCtor, "_D3lib18shared_static_ctorOk");
|
|
loadSym(h, libSharedStaticDtor, "_D3lib18shared_static_dtorOk");
|
|
loadSym(h, libStaticCtor, "_D3lib11static_ctorOk");
|
|
loadSym(h, libStaticDtor, "_D3lib11static_dtorOk");
|
|
|
|
return h;
|
|
}
|
|
|
|
void closeLib(void* h)
|
|
{
|
|
Runtime.unloadLibrary(h);
|
|
}
|
|
|
|
__gshared
|
|
{
|
|
void function() libThrowException;
|
|
Exception function(void delegate()) libCollectException;
|
|
|
|
void function() libAlloc;
|
|
void function() libTlsAlloc;
|
|
void function() libAccess;
|
|
void function() libTlsAccess;
|
|
void function() libFree;
|
|
void function() libTlsFree;
|
|
|
|
shared uint* libSharedStaticCtor;
|
|
shared uint* libSharedStaticDtor;
|
|
shared uint* libStaticCtor;
|
|
shared uint* libStaticDtor;
|
|
}
|
|
|
|
void testEH()
|
|
{
|
|
bool passed;
|
|
try
|
|
libThrowException();
|
|
catch (Exception e)
|
|
passed = true;
|
|
assert(passed); passed = false;
|
|
|
|
assert(libCollectException({throw new Exception(null);}) !is null);
|
|
assert(libCollectException({libThrowException();}) !is null);
|
|
}
|
|
|
|
void testGC()
|
|
{
|
|
import core.memory;
|
|
libAlloc();
|
|
libTlsAlloc();
|
|
libAccess();
|
|
libTlsAccess();
|
|
GC.collect();
|
|
libTlsAccess();
|
|
libAccess();
|
|
libTlsFree();
|
|
libFree();
|
|
}
|
|
|
|
void testInit()
|
|
{
|
|
|
|
assert(*libStaticCtor == 1);
|
|
assert(*libStaticDtor == 0);
|
|
static void run()
|
|
{
|
|
assert(*libSharedStaticCtor == 1);
|
|
assert(*libSharedStaticDtor == 0);
|
|
assert(*libStaticCtor == 2);
|
|
assert(*libStaticDtor == 0);
|
|
}
|
|
auto thr = new Thread(&run);
|
|
thr.start();
|
|
thr.join();
|
|
assert(*libSharedStaticCtor == 1);
|
|
assert(*libSharedStaticDtor == 0);
|
|
assert(*libStaticCtor == 2);
|
|
assert(*libStaticDtor == 1);
|
|
}
|
|
|
|
const(ModuleInfo)* findModuleInfo(string name)
|
|
{
|
|
foreach (m; ModuleInfo)
|
|
if (m.name == name) return m;
|
|
return null;
|
|
}
|
|
|
|
void runTests(string libName)
|
|
{
|
|
assert(findModuleInfo("lib") is null);
|
|
auto handle = openLib(libName);
|
|
assert(findModuleInfo("lib") !is null);
|
|
|
|
testEH();
|
|
testGC();
|
|
testInit();
|
|
|
|
closeLib(handle);
|
|
assert(findModuleInfo("lib") is null);
|
|
}
|
|
|
|
void main(string[] args)
|
|
{
|
|
auto name = args[0] ~ '\0';
|
|
const pathlen = strrchr(name.ptr, '/') - name.ptr + 1;
|
|
name = name[0 .. pathlen] ~ "lib.so";
|
|
|
|
runTests(name);
|
|
|
|
// lib is no longer resident
|
|
name ~= '\0';
|
|
assert(.dlopen(name.ptr, RTLD_LAZY | RTLD_NOLOAD) is null);
|
|
name = name[0 .. $-1];
|
|
|
|
auto thr = new Thread({runTests(name);});
|
|
thr.start();
|
|
thr.join();
|
|
}
|