# HG changeset patch # User Christian Kamm # Date 1232753586 -3600 # Node ID bd000a7fab18a4add0b5b06adf95869a4cbcfda7 # Parent 01d9ece9982aecda261d4e55353ae0e4f7d13af4 Applied doob's patch to port GDC's Dyld data segment tracking for Mac. diff -r 01d9ece9982a -r bd000a7fab18 runtime/internal/memory.d --- a/runtime/internal/memory.d Fri Jan 23 13:41:03 2009 +0100 +++ b/runtime/internal/memory.d Sat Jan 24 00:33:06 2009 +0100 @@ -27,11 +27,16 @@ version = GC_Use_Dynamic_Ranges; -version(Posix) +version(darwin) +{ + version = GC_Use_Data_Dyld; + version = GC_Use_Dynamic_Ranges; +} +else version(Posix) { version = GC_Use_Data_Proc_Maps; } -version(solaris) +else version(solaris) { version = GC_Use_Data_Proc_Maps; } @@ -299,6 +304,10 @@ dataStart = adjust_up( &Data_Start ); dataEnd = adjust_down( &Data_End ); } + else version(GC_Use_Data_Dyld) + { + _d_dyld_start(); + } else { static assert( false, "Operating system not supported." ); @@ -497,3 +506,113 @@ } } } + +/* + * GDC dyld memory module: + * http://www.dsource.org/projects/tango/browser/trunk/lib/compiler/gdc/memory_dyld.c + * Port to the D programming language: Jacob Carlborg + */ +version (GC_Use_Data_Dyld) +{ + private + { + const char* SEG_DATA = "__DATA".ptr; + const char* SECT_DATA = "__data".ptr; + const char* SECT_BSS = "__bss".ptr; + const char* SECT_COMMON = "__common".ptr; + + struct SegmentSection + { + const char* segment; + const char* section; + } + + struct mach_header + { + uint magic; + int cputype; + int cpusubtype; + uint filetype; + uint ncmds; + uint sizeofcmds; + uint flags; + } + + struct section + { + char[16] sectname; + char[16] segname; + uint addr; + uint size; + uint offset; + uint align_; + uint reloff; + uint nreloc; + uint flags; + uint reserved1; + uint reserved2; + } + + alias extern (C) void function (mach_header* mh, ptrdiff_t vmaddr_slide) DyldFuncPointer; + + extern (C) /*const*/ section* getsectbynamefromheader(/*const*/ mach_header* mhp, /*const*/ char* segname, /*const*/ char* sectname); + extern (C) void _dyld_register_func_for_add_image(DyldFuncPointer func); + extern (C) void _dyld_register_func_for_remove_image(DyldFuncPointer func); + + const SegmentSection[3] GC_dyld_sections = [SegmentSection(SEG_DATA, SECT_DATA), SegmentSection(SEG_DATA, SECT_BSS), SegmentSection(SEG_DATA, SECT_COMMON)]; + + extern (C) void on_dyld_add_image (/*const*/ mach_header* hdr, ptrdiff_t slide) + { + void* start; + void* end; + /*const*/ section* sec; + + foreach (s ; GC_dyld_sections) + { + sec = getsectbynamefromheader(hdr, s.segment, s.section); + + if (sec == null || sec.size == 0) + continue; + + start = cast(void*) (sec.addr + slide); + end = cast(void*) (start + sec.size); + + _d_gc_add_range(start, end); + } + } + + extern (C) void on_dyld_remove_image (/*const*/ mach_header* hdr, ptrdiff_t slide) + { + void* start; + void* end; + /*const*/ section* sec; + + foreach (s ; GC_dyld_sections) + { + sec = getsectbynamefromheader(hdr, s.segment, s.section); + + if (sec == null || sec.size == 0) + continue; + + start = cast(void*) (sec.addr + slide); + end = cast(void*) (start + sec.size); + + _d_gc_remove_range(start); + } + } + + void _d_dyld_start () + { + static bool started; + + if (!started) + { + started = true; + + _dyld_register_func_for_add_image(&on_dyld_add_image); + _dyld_register_func_for_remove_image(&on_dyld_remove_image); + } + } + } +} +