Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions mak/COPY
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ COPY=\
$(IMPDIR)\core\internal\array\operations.d \
$(IMPDIR)\core\internal\array\utils.d \
\
$(IMPDIR)\core\internal\elf\dl.d \
$(IMPDIR)\core\internal\elf\io.d \
\
$(IMPDIR)\core\internal\util\array.d \
\
$(IMPDIR)\core\stdc\assert_.d \
Expand Down
4 changes: 4 additions & 0 deletions mak/SRCS
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ SRCS=\
src\core\internal\array\concatenation.d \
src\core\internal\array\operations.d \
src\core\internal\array\utils.d \
\
src\core\internal\elf\dl.d \
src\core\internal\elf\io.d \
\
src\core\internal\util\array.d \
\
src\core\stdc\assert_.d \
Expand Down
6 changes: 6 additions & 0 deletions mak/WINDOWS
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ $(IMPDIR)\core\internal\array\utils.d : src\core\internal\array\utils.d
$(IMPDIR)\core\internal\array\operations.d : src\core\internal\array\operations.d
copy $** $@

$(IMPDIR)\core\internal\elf\dl.d : src\core\internal\elf\dl.d
copy $** $@

$(IMPDIR)\core\internal\elf\io.d : src\core\internal\elf\io.d
copy $** $@

$(IMPDIR)\core\internal\util\array.d : src\core\internal\util\array.d
copy $** $@

Expand Down
3 changes: 3 additions & 0 deletions posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ $(DOCDIR)/core_gc_%.html : src/core/gc/%.d $(DMD)
$(DOCDIR)/core_internal_%.html : src/core/internal/%.d $(DMD)
$(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $<

$(DOCDIR)/core_internal_elf_%.html : src/core/internal/elf/%.d $(DMD)
$(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $<

$(DOCDIR)/core_stdc_%.html : src/core/stdc/%.d $(DMD)
$(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $<

Expand Down
162 changes: 162 additions & 0 deletions src/core/internal/elf/dl.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/**
* Simplifies working with shared ELF objects of the current process.
*
* Reference: http://www.dwarfstd.org/
*
* Copyright: Copyright Digital Mars 2015 - 2018.
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Martin Kinkelin
* Source: $(DRUNTIMESRC core/elf/dl.d)
*/

module core.internal.elf.dl;

version (linux)
{
import core.sys.linux.link;
version = LinuxOrBSD;
}
else version (FreeBSD)
{
import core.sys.freebsd.sys.link_elf;
version = LinuxOrBSD;
}
else version (DragonFlyBSD)
{
import core.sys.dragonflybsd.sys.link_elf;
version = LinuxOrBSD;
}

version (LinuxOrBSD):

alias Elf_Ehdr = ElfW!"Ehdr";
alias Elf_Phdr = ElfW!"Phdr";

/**
* Enables iterating over the process' currently loaded shared objects.
*/
struct SharedObjects
{
@nogc nothrow:
///
alias Callback = int delegate(SharedObject);

///
static int opApply(scope Callback dg)
{
extern(C) int nativeCallback(dl_phdr_info* info, size_t, void* data)
{
auto dg = *cast(Callback*) data;
return dg(SharedObject(*info));
}

return dl_iterate_phdr(&nativeCallback, &dg);
}
}

/**
* A loaded shared ELF object/binary, i.e., executable or shared library.
*/
struct SharedObject
{
@nogc nothrow:
/**
* Tries to find the shared object containing the specified address in one of its segments.
* Returns: True on success.
*/
static bool findForAddress(const scope void* address, out SharedObject result)
{
version (linux) enum IterateManually = true;
else version (NetBSD) enum IterateManually = true;
else enum IterateManually = false;

static if (IterateManually)
{
foreach (object; SharedObjects)
{
const(Elf_Phdr)* segment;
if (object.findSegmentForAddress(address, segment))
{
result = object;
return true;
}
}
return false;
}
else
{
return !!_rtld_addr_phdr(address, &result.info);
}
}

/// OS-dependent info structure.
dl_phdr_info info;

/// Returns the base address of the object.
@property void* baseAddress() const
{
return cast(void*) info.dlpi_addr;
}

/// Returns the name of (usually: path to) the object.
const(char)[] name() const
{
import core.stdc.string : strlen;

const(char)* cstr = info.dlpi_name;

// the main executable has an empty name
if (cstr[0] == 0)
cstr = getprogname();

return cstr[0 .. strlen(cstr)];
}

/// Iterates over this object's segments.
int opApply(scope int delegate(ref const Elf_Phdr) @nogc nothrow dg) const
{
foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
{
const r = dg(phdr);
if (r != 0)
return r;
}
return 0;
}

/**
* Tries to find the segment containing the specified address.
* Returns: True on success.
*/
bool findSegmentForAddress(const scope void* address, out const(Elf_Phdr)* result) const
{
if (address < baseAddress)
return false;

foreach (ref phdr; this)
{
const begin = baseAddress + phdr.p_vaddr;
if (cast(size_t)(address - begin) < phdr.p_memsz)
{
result = &phdr;
return true;
}
}
return false;
}
}

private @nogc nothrow:

version (linux)
{
const(char)* getprogname()
{
import core.sys.linux.errno;
return program_invocation_name;
}
}
else
{
extern(C) const(char)* getprogname();
}
Loading