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
115 changes: 115 additions & 0 deletions src/core/sys/netbsd/dlfcn.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* D header file for NetBSD.
*
* Copyright: Copyright Martin Nowak 2012.
* License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Martin Nowak
*
* http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/include/dlfcn.h
*/
module core.sys.netbsd.dlfcn;

public import core.sys.posix.dlfcn;

version (NetBSD):
extern (C):
nothrow:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FreeBSD file has @nogc attribute here, missing in yours. Why not add that attribute to all the header files?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, my fault - fixed

@nogc:

enum __BSD_VISIBLE = true;

/*
* Modes and flags for dlopen().
*/
static assert(RTLD_LAZY == 1);
static assert(RTLD_NOW == 2);
static assert(RTLD_GLOBAL == 0x100);
static assert(RTLD_LOCAL == 0x200);
//enum RTLD_TRACE = 0x200;
enum RTLD_NODELETE = 0x01000;
enum RTLD_NOLOAD = 0x02000;

/*
* Request arguments for dlinfo().
*/
enum RTLD_DI_LINKMAP = 3; /* Obtain link map. */
enum RTLD_DI_SERINFO = 5; /* Obtain search path info. */
enum RTLD_DI_SERINFOSIZE = 6; /* ... query for required space. */
enum RTLD_DI_ORIGIN = 7; /* Obtain object origin */
enum RTLD_DI_MAX = RTLD_DI_ORIGIN;

/*
* Special handle arguments for dlsym()/dlinfo().
*/
enum RTLD_NEXT = cast(void *)-1; /* Search subsequent objects. */
enum RTLD_DEFAULT = cast(void *)-2; /* Use default search algorithm. */
enum RTLD_SELF = cast(void *)-3; /* Search the caller itself. */

static if (__BSD_VISIBLE)
{
/*
* Structure filled in by dladdr().
*/
struct Dl_info {
const(char) *dli_fname; /* Pathname of shared object. */
void *dli_fbase; /* Base address of shared object. */
const(char) *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Address of nearest symbol. */
};

/*-
* The actual type declared by this typedef is immaterial, provided that
* it is a function pointer. Its purpose is to provide a return type for
* dlfunc() which can be cast to a function pointer type without depending
* on behavior undefined by the C standard, which might trigger a compiler
* diagnostic. We intentionally declare a unique type signature to force
* a diagnostic should the application not cast the return value of dlfunc()
* appropriately.
*/
struct __dlfunc_arg {
int __dlfunc_dummy;
};

alias dlfunc_t = void function(__dlfunc_arg);

/*
* Structures, returned by the RTLD_DI_SERINFO dlinfo() request.
*/
struct Dl_serpath {
char * dls_name; /* single search path entry */
uint dls_flags; /* path information */
};

struct Dl_serinfo {
size_t dls_size; /* total buffer size */
uint dls_cnt; /* number of path entries */
Dl_serpath[1] dls_serpath; /* there may be more than one */
};
}

private template __externC(RT, P...)
{
alias __externC = extern(C) RT function(P) nothrow @nogc;
}

/* XSI functions first. */
static assert(is(typeof(&dlclose) == __externC!(int, void*)));
static assert(is(typeof(&dlerror) == __externC!(char*)));
static assert(is(typeof(&dlopen) == __externC!(void*, const char*, int)));
static assert(is(typeof(&dlsym) == __externC!(void*, void*, const char*)));

static if (__BSD_VISIBLE)
{
//void* fdlopen(int, int);
int dladdr(const(void)*, Dl_info*);
//dlfunc_t dlfunc(void*, const(char)*);
//int dlinfo(void*, int, void*);
/+void dllockinit(void* _context,
void* function(void* _context) _lock_create,
void function(void* _lock) _rlock_acquire,
void function(void* _lock) _wlock_acquire,
void function(void* _lock) _lock_release,
void function(void* _lock) _lock_destroy,
void function(void* _context) _context_destroy);+/
void* dlvsym(void*, const(char)*, const(char)*);
}
133 changes: 133 additions & 0 deletions src/core/sys/netbsd/execinfo.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* NetBSD implementation of glibc's $(LINK2 http://www.gnu.org/software/libc/manual/html_node/Backtraces.html backtrace) facility.
*
* Copyright: Copyright Martin Nowak 2012.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Martin Nowak
* Source: $(DRUNTIMESRC core/sys/netbsd/_execinfo.d)
*/
module core.sys.netbsd.execinfo;

version (NetBSD):
extern (C):
nothrow:

import core.sys.netbsd.dlfcn;

// Use extern (D) so that these functions don't collide with libexecinfo.

extern (D) int backtrace(void** buffer, int size)
{
import core.thread : thread_stackBottom;

void** p, pend=cast(void**)thread_stackBottom();
version (D_InlineAsm_X86)
asm nothrow @trusted { mov p[EBP], EBP; }
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");

int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
}


extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
{
static void* realloc(void* p, size_t len) nothrow
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
}

if (size <= 0) return null;

size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;

Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);

immutable len = formatStackFrame(null, 0, addr, info);
assert(len > 0);

p = cast(char**)realloc(p, pos + len);
if (p is null) return null;

formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);

p[i] = cast(char*)pos;
pos += len;
}
foreach (i; 0 .. size)
{
pos = cast(size_t)p[i];
p[i] = cast(char*)p + pos;
}
return p;
}


extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd)
{
import core.sys.posix.unistd : write;
import core.stdc.stdlib : alloca;

if (size <= 0) return;

Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);

enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
assert(len > 0);

auto p = cast(char*)alloca(len);
if (p is null) return;

formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
}
}


private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{
if (info.dli_fname is null) info.dli_fname = "???";
if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}


private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
import core.stdc.stdio : snprintf;

immutable off = addr - info.dli_saddr;
immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
addr, info.dli_sname, off, info.dli_fname);
assert(len > 0);
return cast(size_t)len + 1; // + '\0'
}
10 changes: 10 additions & 0 deletions src/core/sys/netbsd/sys/elf.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* D header file for NetBSD.
*
*/
module core.sys.netbsd.sys.elf;

version (NetBSD):

public import core.sys.netbsd.sys.elf32;
public import core.sys.netbsd.sys.elf64;
Loading