Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Closed
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 import/object.di
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ extern (C)
void* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...);
}

extern (C) void _d_monitorenter(Object h);
extern (C) void _d_monitorexit(Object h);

struct AssociativeArray(Key, Value)
{
void* p;
Expand Down
100 changes: 75 additions & 25 deletions posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,40 @@ endif

DMD=dmd

MKDIR=mkdir

DOCDIR=doc
IMPDIR=import

MODEL=32

DFLAGS=-m$(MODEL) -O -release -inline -nofloat -w -d -Isrc -Iimport
UDFLAGS=-m$(MODEL) -O -release -nofloat -w -d -Isrc -Iimport
ifeq ($(BUILD),debug)
OPTFLAGS=-g
CFLAGS += -g
else
OPTFLAGS=-O -release -inline
endif

CFLAGS=-m$(MODEL) -O
DFLAGS=-m$(MODEL) $(OPTFLAGS) -nofloat -w -d -Isrc -Iimport
UDFLAGS=-m$(MODEL) $(OPTFLAGS) -nofloat -w -d -Isrc -Iimport

# Set CFLAGS
ifeq ($(CC),cc)
CFLAGS += -m$(MODEL)
ifneq ($(BUILD),debug)
CFLAGS += -O
endif
endif

OBJDIR=obj
LIBDIR=lib
JSONDIR=.
DRUNTIME_BASE=druntime
DRUNTIME=lib/lib$(DRUNTIME_BASE).a
ifeq (Windows_NT,$(OS))
DRUNTIME=$(LIBDIR)/$(DRUNTIME_BASE).lib
else
DRUNTIME=$(LIBDIR)/lib$(DRUNTIME_BASE).a
endif

DOCFMT=

Expand Down Expand Up @@ -263,12 +284,6 @@ SRC_D_MODULES = \
core/stdc/time \
core/stdc/wchar_ \
\
core/sys/posix/sys/select \
core/sys/posix/sys/socket \
core/sys/posix/sys/stat \
core/sys/posix/sys/wait \
core/sys/posix/netinet/in_ \
\
core/sync/barrier \
core/sync/condition \
core/sync/config \
Expand All @@ -287,7 +302,6 @@ SRC_D_MODULES = \
rt/aApply \
rt/aApplyR \
rt/adi \
rt/alloca \
rt/arrayassign \
rt/arraybyte \
rt/arraycast \
Expand All @@ -298,18 +312,14 @@ SRC_D_MODULES = \
rt/arrayreal \
rt/arrayshort \
rt/cast_ \
rt/cmath2 \
rt/cover \
rt/critical_ \
rt/deh2 \
rt/dmain2 \
rt/invariant \
rt/invariant_ \
rt/lifetime \
rt/llmath \
rt/memory \
rt/memset \
rt/monitor_ \
rt/obj \
rt/qsort \
rt/switch_ \
Expand Down Expand Up @@ -357,12 +367,43 @@ SRC_D_MODULES = \
rt/typeinfo/ti_void \
rt/typeinfo/ti_wchar

SRC_D_MODULES_POSIX = \
core/sys/posix/sys/select \
core/sys/posix/sys/socket \
core/sys/posix/sys/stat \
core/sys/posix/sys/wait \
core/sys/posix/netinet/in_ \
\
rt/alloca \
rt/cmath2 \
rt/critical_ \
rt/deh2 \
rt/monitor_ \

SRC_D_MODULES_WIN = \
core/sys/windows/_dll \
core/sys/windows/_thread \
core/sys/windows/dbghelp \
core/sys/windows/stacktrace \
core/sys/windows/windows \
\
rt/deh \

# NOTE: trace.d and cover.d are not necessary for a successful build
# as both are used for debugging features (profiling and coverage)
# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
# minit.asm is not used by dmd for Linux

OBJS= $(OBJDIR)/errno_c.o $(OBJDIR)/threadasm.o $(OBJDIR)/complex.o $(OBJDIR)/memory_osx.o
ifeq (Windows_NT,$(OS))
SRC_D_MODULES += $(SRC_D_MODULES_WIN)
O = obj
OBJS= $(OBJDIR)/errno_c.obj $(OBJDIR)/monitor.obj $(OBJDIR)/complex.obj $(OBJDIR)/critical.obj \
src\rt\minit.obj
else
SRC_D_MODULES += $(SRC_D_MODULES_POSIX)
O = o
OBJS= $(OBJDIR)/errno_c.o $(OBJDIR)/threadasm.o $(OBJDIR)/complex.o $(OBJDIR)/memory_osx.o
endif

DOCS=\
$(DOCDIR)/object.html \
Expand Down Expand Up @@ -499,22 +540,22 @@ $(IMPDIR)/core/%.di : src/core/%.d

################### C/ASM Targets ############################

$(OBJDIR)/%.o : src/rt/%.c
@mkdir -p $(OBJDIR)
$(OBJDIR)/%.$O : src/rt/%.c
@$(MKDIR) -p $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o$@

$(OBJDIR)/errno_c.o : src/core/stdc/errno.c
@mkdir -p $(OBJDIR)
$(OBJDIR)/errno_c.$O : src/core/stdc/errno.c
@$(MKDIR) -p $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o$@

$(OBJDIR)/threadasm.o : src/core/threadasm.S
@mkdir -p $(OBJDIR)
$(OBJDIR)/threadasm.$O : src/core/threadasm.S
@$(MKDIR) -p $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o$@

################### Library generation #########################

$(DRUNTIME): $(OBJS) $(SRCS) win32.mak
$(DMD) -lib -of$(DRUNTIME) -Xfdruntime.json $(DFLAGS) $(SRCS) $(OBJS)
$(DRUNTIME): $(OBJS) $(SRCS) posix.mak
$(DMD) -lib -of$(DRUNTIME) -Xf$(JSONDIR)\druntime.json $(DFLAGS) $(SRCS) $(OBJS)

unittest : $(addprefix $(OBJDIR)/,$(SRC_D_MODULES)) $(DRUNTIME) $(OBJDIR)/emptymain.d
@echo done
Expand All @@ -530,17 +571,26 @@ $(addprefix $(OBJDIR)/,$(DISABLED_TESTS)) :

$(OBJDIR)/% : src/%.d $(DRUNTIME) $(OBJDIR)/emptymain.d
@echo Testing $@
ifeq (Windows_NT,$(OS))
@$(DMD) $(UDFLAGS) -unittest $(subst /,\,-of$@ -map $@.map $(OBJDIR)/emptymain.d) $< -debuglib=$(DRUNTIME_BASE) -defaultlib=$(DRUNTIME_BASE)
@$(RUN) $@
else
@$(DMD) $(UDFLAGS) -unittest -of$@ $(OBJDIR)/emptymain.d $< -L-Llib -debuglib=$(DRUNTIME_BASE) -defaultlib=$(DRUNTIME_BASE)
# make the file very old so it builds and runs again if it fails
@touch -t 197001230123 $@
# run unittest in its own directory
@$(RUN) $@
# succeeded, render the file new again
@touch $@
endif

$(OBJDIR)/emptymain.d :
@mkdir -p $(OBJDIR)
@$(MKDIR) -p $(OBJDIR)
ifeq (Windows_NT,$(OS))
@echo void main(){} >$@
else
@echo 'void main(){}' >$@
endif

detab:
detab $(MANIFEST)
Expand Down
5 changes: 5 additions & 0 deletions src/core/demangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,11 @@ char[] demangle( const(char)[] buf, char[] dst = null )
return d();
}

char[] demangle( const(char)[] buf, bool addType_, char[] dst = null )
{
auto d = Demangle(buf, addType_ ? Demangle.AddType.yes : Demangle.AddType.no, dst);
return d();
}

unittest
{
Expand Down
82 changes: 63 additions & 19 deletions src/core/sys/windows/_dll.d
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ private:
alias extern(Windows)
void* fnRtlAllocateHeap(void* HeapHandle, uint Flags, uint Size);

// find a code sequence and return the (relative) address that follows
static void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative )
// find a code sequence and return the address after the sequence
static void* findCodeSequence( void* adr, int len, ref ubyte[] pattern )
{
if( !adr )
return null;
Expand All @@ -64,14 +64,28 @@ private:
if( code[ p .. p + pattern.length ] == pattern[ 0 .. $ ] )
{
ubyte* padr = code + p + pattern.length;
if( relative )
return padr + 4 + *cast(int*) padr;
return *cast(void**) padr;
return padr;
}
}
return null;
}

// find a code sequence and return the (relative) address that follows
static void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative )
{
if( !adr )
return null;

ubyte* padr = cast(ubyte*) findCodeSequence( adr, len, pattern );
if( padr )
{
if( relative )
return padr + 4 + *cast(int*) padr;
return *cast(void**) padr;
}
return null;
}

// crawl through ntdll to find function _LdrpAllocateTls@0 and references
// to _LdrpNumberOfTlsEntries, _NtdllBaseTag and _LdrpTlsList
// LdrInitializeThunk
Expand All @@ -87,11 +101,14 @@ private:

static __gshared ubyte[] jmp_LdrpInitialize = [ 0x33, 0xED, 0xE9 ]; // xor ebp,ebp; jmp _LdrpInitialize
static __gshared ubyte[] jmp__LdrpInitialize = [ 0x5D, 0xE9 ]; // pop ebp; jmp __LdrpInitialize
static __gshared ubyte[] jmp__LdrpInitialize_xp64 = [ 0x5D, 0x90, 0x90, 0x90, 0x90, 0x90 ]; // pop ebp; nop; nop; nop; nop; nop;
static __gshared ubyte[] call_LdrpInitializeThread = [ 0xFF, 0x75, 0x08, 0xE8 ]; // push [ebp+8]; call _LdrpInitializeThread
static __gshared ubyte[] call_LdrpAllocateTls = [ 0x00, 0x00, 0xE8 ]; // jne 0xc3; call _LdrpAllocateTls
static __gshared ubyte[] call_LdrpAllocateTls_svr03 = [ 0x65, 0xfc, 0x00, 0xE8 ]; // and [ebp+fc], 0; call _LdrpAllocateTls
static __gshared ubyte[] jne_LdrpAllocateTls = [ 0x0f, 0x85 ]; // jne body_LdrpAllocateTls
static __gshared ubyte[] mov_LdrpNumberOfTlsEntries = [ 0x8B, 0x0D ]; // mov ecx, _LdrpNumberOfTlsEntries
static __gshared ubyte[] mov_NtdllBaseTag = [ 0x51, 0x8B, 0x0D ]; // push ecx; mov ecx, _NtdllBaseTag
static __gshared ubyte[] mov_NtdllBaseTag_srv03 = [ 0x50, 0xA1 ]; // push eax; mov eax, _NtdllBaseTag
static __gshared ubyte[] mov_LdrpTlsList = [ 0x8B, 0x3D ]; // mov edi, _LdrpTlsList

static LdrpTlsListEntry* addTlsListEntry( void** peb, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
Expand All @@ -105,13 +122,19 @@ private:
{
void* pLdrpInitialize = findCodeReference( fn, 20, jmp_LdrpInitialize, true );
void* p_LdrpInitialize = findCodeReference( pLdrpInitialize, 40, jmp__LdrpInitialize, true );
if( !p_LdrpInitialize )
p_LdrpInitialize = findCodeSequence( pLdrpInitialize, 40, jmp__LdrpInitialize_xp64 );
void* pLdrpInitializeThread = findCodeReference( p_LdrpInitialize, 200, call_LdrpInitializeThread, true );
void* pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 40, call_LdrpAllocateTls, true );
if(!pLdrpAllocateTls)
pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 100, call_LdrpAllocateTls_svr03, true );
void* pBodyAllocateTls = findCodeReference( pLdrpAllocateTls, 40, jne_LdrpAllocateTls, true );

int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 20, mov_LdrpNumberOfTlsEntries, false );
int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 60, mov_LdrpNumberOfTlsEntries, false );
pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag, false );
LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 60, mov_LdrpTlsList, false );
if(!pNtdllBaseTag)
pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag_srv03, false );
LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 80, mov_LdrpTlsList, false );

if( !pLdrpNumberOfTlsEntries || !pNtdllBaseTag || !pLdrpTlsList )
return null;
Expand Down Expand Up @@ -346,8 +369,12 @@ public:
function (uint id, void* context) {
if( !thread_findByAddr( id ) )
{
thread_attachByAddr( id );
thread_moduleTlsCtor( id );
// if the OS has not prepared TLS for us, don't attach to the thread
if( GetTlsDataAddress( id ) )
{
thread_attachByAddr( id );
thread_moduleTlsCtor( id );
}
}
return true;
}, null );
Expand Down Expand Up @@ -382,22 +409,39 @@ public:
*/
static bool tlsCtorRun;
static this() { tlsCtorRun = true; }
static ~this() { tlsCtorRun = false; }

// to be called from DllMain with reason DLL_THREAD_ATTACH
void dll_thread_attach( bool attach_thread = true, bool initTls = true )
bool dll_thread_attach( bool attach_thread = true, bool initTls = true )
{
if( attach_thread && !thread_findByAddr( GetCurrentThreadId() ) )
thread_attachThis();
if( initTls && !tlsCtorRun ) // avoid duplicate calls
_moduleTlsCtor();
// if the OS has not prepared TLS for us, don't attach to the thread
// (happened when running under x64 OS)
if( !GetTlsDataAddress( GetCurrentThreadId() ) )
return false;
if( !thread_findByAddr( GetCurrentThreadId() ) )
{
// only attach to thread and initalize it if it is not in the thread list (so it's not created by "new Thread")
if( attach_thread )
thread_attachThis();
if( initTls && !tlsCtorRun ) // avoid duplicate calls
_moduleTlsCtor();
}
return true;
}

// to be called from DllMain with reason DLL_THREAD_DETACH
void dll_thread_detach( bool detach_thread = true, bool exitTls = true )
bool dll_thread_detach( bool detach_thread = true, bool exitTls = true )
{
if( exitTls )
_moduleTlsDtor();
if( detach_thread )
thread_detachThis();
// if the OS has not prepared TLS for us, we did not attach to the thread
if( !GetTlsDataAddress( GetCurrentThreadId() ) )
return false;
if( thread_findByAddr( GetCurrentThreadId() ) )
{
if( exitTls && tlsCtorRun ) // avoid dtors to be run twice
_moduleTlsDtor();
if( detach_thread )
thread_detachThis();
}
return true;
}
}
Loading