Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
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: 2 additions & 1 deletion mak/SRCS
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ SRCS=\
src\rt\sections.d \
src\rt\sections_android.d \
src\rt\sections_elf_shared.d \
src\rt\sections_osx.d \
src\rt\sections_osx_x86.d \
src\rt\sections_osx_x86_64.d \
src\rt\sections_solaris.d \
src\rt\sections_win32.d \
src\rt\sections_win64.d \
Expand Down
6 changes: 6 additions & 0 deletions posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ SRCS:=$(subst \,/,$(SRCS))

OBJS= $(ROOT)/errno_c.o $(ROOT)/bss_section.o $(ROOT)/threadasm.o

ifeq ($(OS),osx)
ifeq ($(MODEL), 64)
OBJS+=$(ROOT)/osx_tls.o
endif
endif

# build with shared library support
SHARED=$(if $(findstring $(OS),linux freebsd),1,)

Expand Down
51 changes: 51 additions & 0 deletions src/rt/osx_tls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Helpers for determining TLS memory ranges on OS X.
*
* This unfortunately cannot be entirely done in D, as the OS X API uses
* the Apple-specific blocks C extension.
*
* Copyright: David Nadlinger, 2012.
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
* Authors: David Nadlinger
*/

#ifndef __APPLE__
#ifndef __BLOCKS__
#error "Need a C compiler with Apple Blocks support – not building on OS X with Clang?"
#endif
#endif

#include <assert.h>
#include <stddef.h>
#include <stdio.h>

/*
* Declarations from dyld_priv.h, available on 10.7+.
*/
enum dyld_tlv_states {
dyld_tlv_state_allocated = 10,
dyld_tlv_state_deallocated = 20
};
typedef struct {
size_t info_size;
void * tlv_addr;
size_t tlv_size;
} dyld_tlv_info;
typedef void (^dyld_tlv_state_change_handler)(enum dyld_tlv_states state, const dyld_tlv_info *info);
extern void dyld_register_tlv_state_change_handler(enum dyld_tlv_states state, dyld_tlv_state_change_handler handler);
extern void dyld_enumerate_tlv_storage(dyld_tlv_state_change_handler handler);

void _d_dyld_getTLSRange(void* arbitraryTLSSymbol, void** start, size_t* size) {
dyld_enumerate_tlv_storage(
^(enum dyld_tlv_states state, const dyld_tlv_info *info) {
assert(state == dyld_tlv_state_allocated);
if (info->tlv_addr <= arbitraryTLSSymbol &&
arbitraryTLSSymbol < (info->tlv_addr + info->tlv_size)
) {
// Found the range.
*start = info->tlv_addr;
*size = info->tlv_size;
}
}
);
}
9 changes: 8 additions & 1 deletion src/rt/sections.d
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ else version (FreeBSD)
else version (Solaris)
public import rt.sections_solaris;
else version (Darwin)
public import rt.sections_osx;
{
version (X86_64)
public import rt.sections_osx_x86_64;
else version (X86)
public import rt.sections_osx_x86;
else
static assert(0, "unimplemented");
}
else version (CRuntime_DigitalMars)
public import rt.sections_win32;
else version (CRuntime_Microsoft)
Expand Down
31 changes: 8 additions & 23 deletions src/rt/sections_osx.d → src/rt/sections_osx_x86.d
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
/**
* Written in the D programming language.
* This module provides OSX-specific support for sections.
* This module provides OS X x86 specific support for sections.
*
* Copyright: Copyright Digital Mars 2008 - 2012.
* Copyright: Copyright Digital Mars 2008 - 2016.
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Walter Bright, Sean Kelly, Martin Nowak
* Source: $(DRUNTIMESRC src/rt/_sections_osx.d)
* Authors: Walter Bright, Sean Kelly, Martin Nowak, Jacob Carlborg
* Source: $(DRUNTIMESRC src/rt/_sections_osx_x86.d)
*/

module rt.sections_osx;
module rt.sections_osx_x86;

version (OSX)
version = Darwin;
Expand All @@ -22,6 +21,7 @@ else version (WatchOS)
version = Darwin;

version(Darwin):
version(X86):

// debug = PRINTF;
import core.stdc.stdio;
Expand Down Expand Up @@ -189,7 +189,6 @@ ref void[] getTLSBlockAlloc()
return *pary;
}


__gshared SectionGroup _sections;

extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
Expand Down Expand Up @@ -263,22 +262,8 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
ubyte[] getSection(in mach_header* header, intptr_t slide,
in char* segmentName, in char* sectionName)
{
version (X86)
{
assert(header.magic == MH_MAGIC);
auto sect = getsectbynamefromheader(header,
segmentName,
sectionName);
}
else version (X86_64)
{
assert(header.magic == MH_MAGIC_64);
auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
segmentName,
sectionName);
}
else
static assert(0, "unimplemented");
assert(header.magic == MH_MAGIC);
auto sect = getsectbynamefromheader(header, segmentName, sectionName);

if (sect !is null && sect.size > 0)
return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size];
Expand Down
185 changes: 185 additions & 0 deletions src/rt/sections_osx_x86_64.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/**
* Written in the D programming language.
* This module provides OS X x86-64 specific support for sections.
*
* Copyright: Copyright Digital Mars 2016.
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Walter Bright, Sean Kelly, Martin Nowak, Jacob Carlborg
* Source: $(DRUNTIMESRC src/rt/_sections_osx_x86_64.d)
*/
module rt.sections_osx_x86_64;

version (OSX)
version = Darwin;
else version (iOS)
version = Darwin;
else version (TVOS)
version = Darwin;
else version (WatchOS)
version = Darwin;

version(Darwin):
version(X86_64):

// debug = PRINTF;
import core.stdc.stdio;
import core.stdc.string, core.stdc.stdlib;
import core.sys.posix.pthread;
import core.sys.osx.mach.dyld;
import core.sys.osx.mach.getsect;
import rt.deh, rt.minfo;
import rt.util.container.array;

struct SectionGroup
{
static int opApply(scope int delegate(ref SectionGroup) dg)
{
return dg(_sections);
}

static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
{
return dg(_sections);
}

@property immutable(ModuleInfo*)[] modules() const
{
return _moduleGroup.modules;
}

@property ref inout(ModuleGroup) moduleGroup() inout
{
return _moduleGroup;
}

@property inout(void[])[] gcRanges() inout
{
return _gcRanges[];
}

@property immutable(FuncTable)[] ehTables() const
{
return _ehTables[];
}

private:
immutable(FuncTable)[] _ehTables;
ModuleGroup _moduleGroup;
Array!(void[]) _gcRanges;
}

/****
* Boolean flag set to true while the runtime is initialized.
*/
__gshared bool _isRuntimeInitialized;

/****
* Gets called on program startup just before GC is initialized.
*/
void initSections()
{
_dyld_register_func_for_add_image(&sections_osx_onAddImage);
_isRuntimeInitialized = true;
}

/***
* Gets called on program shutdown just after GC is terminated.
*/
void finiSections()
{
_sections._gcRanges.reset();
_isRuntimeInitialized = false;
}

void[] initTLSRanges()
{
void* start = null;
size_t size = 0;
_d_dyld_getTLSRange(&dummyTlsSymbol, &start, &size);
assert(start && size, "Could not determine TLS range.");
return start[0 .. size];
}

void finiTLSRanges(void[] rng)
{

}

void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
{
dg(rng.ptr, rng.ptr + rng.length);
}

private:

extern(C) void _d_dyld_getTLSRange(void*, void**, size_t*);

__gshared SectionGroup _sections;
ubyte dummyTlsSymbol;

extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
{
foreach (e; dataSegs)
{
auto sect = getSection(h, slide, e.seg.ptr, e.sect.ptr);
if (sect != null)
_sections._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
}

auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
if (minfosect != null)
{
// no support for multiple images yet
// take the sections from the last static image which is the executable
if (_isRuntimeInitialized)
{
fprintf(stderr, "Loading shared libraries isn't yet supported on OSX.\n");
return;
}
else if (_sections.modules.ptr !is null)
{
fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
}

debug(PRINTF) printf(" minfodata\n");
auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
immutable len = minfosect.length / (*p).sizeof;

_sections._moduleGroup = ModuleGroup(p[0 .. len]);
}

auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
if (ehsect != null)
{
debug(PRINTF) printf(" deh_eh\n");
auto p = cast(immutable(FuncTable)*)ehsect.ptr;
immutable len = ehsect.length / (*p).sizeof;

_sections._ehTables = p[0 .. len];
}
}

struct SegRef
{
string seg;
string sect;
}

static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
{SEG_DATA, SECT_BSS},
{SEG_DATA, SECT_COMMON}];

ubyte[] getSection(in mach_header* header, intptr_t slide,
in char* segmentName, in char* sectionName)
{
assert(header.magic == MH_MAGIC_64);
auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
segmentName,
sectionName);

if (sect !is null && sect.size > 0)
return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size];
return null;
}