Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 48 additions & 52 deletions src/rt/sections_elf_shared.d
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ private:
Array!(DSO*) _deps; // D libraries needed by this DSO
void* _handle; // corresponding handle
}

// get the TLS range for the executing thread
void[] tlsRange() const nothrow @nogc
{
return getTLSRange(_tlsMod, _tlsSize);
}
}

/****
Expand Down Expand Up @@ -302,7 +308,7 @@ version (Shared)
// update the _tlsRange for the executing thread
void updateTLSRange() nothrow @nogc
{
_tlsRange = getTLSRange(_pdso._tlsMod, _pdso._tlsSize);
_tlsRange = _pdso.tlsRange();
}
}
Array!(ThreadDSO) _loadedDSOs;
Expand Down Expand Up @@ -404,15 +410,14 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
* thread with a refCnt of 1 and call the TlsCtors.
*/
immutable ushort refCnt = 1, addCnt = 0;
auto tlsRng = getTLSRange(pdso._tlsMod, pdso._tlsSize);
_loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, tlsRng));
_loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, pdso.tlsRange()));
}
}
else
{
foreach (p; _loadedDSOs) assert(p !is pdso);
_loadedDSOs.insertBack(pdso);
_tlsRanges.insertBack(getTLSRange(pdso._tlsMod, pdso._tlsSize));
_tlsRanges.insertBack(pdso.tlsRange());
}

// don't initialize modules before rt_init was called (see Bugzilla 11378)
Expand Down Expand Up @@ -509,8 +514,7 @@ version (Shared)
foreach (dep; pdso._deps)
incThreadRef(dep, false);
immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
auto tlsRng = getTLSRange(pdso._tlsMod, pdso._tlsSize);
_loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, tlsRng));
_loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, pdso.tlsRange()));
pdso._moduleGroup.runTlsCtors();
}
}
Expand Down Expand Up @@ -623,22 +627,22 @@ void freeDSO(DSO* pdso) nothrow @nogc
version (Shared)
{
@nogc nothrow:
link_map* linkMapForHandle(void* handle) nothrow @nogc
link_map* linkMapForHandle(void* handle)
{
link_map* map;
dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0 || assert(0);
return map;
}

link_map* exeLinkMap(link_map* map) nothrow @nogc
link_map* exeLinkMap(link_map* map)
{
assert(map);
while (map.l_prev !is null)
map = map.l_prev;
return map;
}

DSO* dsoForHandle(void* handle) nothrow @nogc
DSO* dsoForHandle(void* handle)
{
DSO* pdso;
!pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
Expand All @@ -648,23 +652,23 @@ version (Shared)
return pdso;
}

void setDSOForHandle(DSO* pdso, void* handle) nothrow @nogc
void setDSOForHandle(DSO* pdso, void* handle)
{
!pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
assert(handle !in _handleToDSO);
_handleToDSO[handle] = pdso;
!pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
}

void unsetDSOForHandle(DSO* pdso, void* handle) nothrow @nogc
void unsetDSOForHandle(DSO* pdso, void* handle)
{
!pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
assert(_handleToDSO[handle] == pdso);
_handleToDSO.remove(handle);
!pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
}

void getDependencies(in ref dl_phdr_info info, ref Array!(DSO*) deps) nothrow @nogc
void getDependencies(in ref dl_phdr_info info, ref Array!(DSO*) deps)
{
// get the entries of the .dynamic section
ElfW!"Dyn"[] dyns;
Expand Down Expand Up @@ -716,7 +720,7 @@ version (Shared)
}
}

void* handleForName(const char* name) nothrow @nogc
void* handleForName(const char* name)
{
auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY);
if (handle !is null) .dlclose(handle); // drop reference count
Expand Down Expand Up @@ -770,59 +774,51 @@ void scanSegments(in ref dl_phdr_info info, DSO* pdso) nothrow @nogc

/**************************
* Input:
* result where the output is to be written; dl_phdr_info is a Linux struct
* result where the output is to be written; dl_phdr_info is an OS struct
* Returns:
* true if found, and *result is filled in
* References:
* http://linux.die.net/man/3/dl_iterate_phdr
*/
version (linux) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
{
static struct DG { const(void)* addr; dl_phdr_info* result; }
version (linux) enum IterateManually = true;
else version (NetBSD) enum IterateManually = true;
else enum IterateManually = false;

extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc
static if (IterateManually)
{
auto p = cast(DG*)arg;
if (findSegmentForAddr(*info, p.addr))
static struct DG { const(void)* addr; dl_phdr_info* result; }

extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc
{
if (p.result !is null) *p.result = *info;
return 1; // break;
auto p = cast(DG*)arg;
if (findSegmentForAddr(*info, p.addr))
{
if (p.result !is null) *p.result = *info;
return 1; // break;
}
return 0; // continue iteration
}
return 0; // continue iteration
}

auto dg = DG(addr, result);
auto dg = DG(addr, result);

/* Linux function that walks through the list of an application's shared objects and
* calls 'callback' once for each object, until either all shared objects
* have been processed or 'callback' returns a nonzero value.
*/
return dl_iterate_phdr(&callback, &dg) != 0;
}
else version (FreeBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
{
return !!_rtld_addr_phdr(addr, result);
}
else version (NetBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
{
static struct DG { const(void)* addr; dl_phdr_info* result; }

extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc
/* OS function that walks through the list of an application's shared objects and
* calls 'callback' once for each object, until either all shared objects
* have been processed or 'callback' returns a nonzero value.
*/
return dl_iterate_phdr(&callback, &dg) != 0;
}
else version (FreeBSD)
{
auto p = cast(DG*)arg;
if (findSegmentForAddr(*info, p.addr))
{
if (p.result !is null) *p.result = *info;
return 1; // break;
}
return 0; // continue iteration
return !!_rtld_addr_phdr(addr, result);
}
auto dg = DG(addr, result);
return dl_iterate_phdr(&callback, &dg) != 0;
}
else version (DragonFlyBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
{
return !!_rtld_addr_phdr(addr, result);
else version (DragonFlyBSD)
{
return !!_rtld_addr_phdr(addr, result);
}
else
static assert(0, "unimplemented");
}

/*********************************
Expand Down