# HG changeset patch # User Christian Kamm # Date 1232645010 -3600 # Node ID 23d36edea021b3a8ed8c6b8d04c0bf110dd03854 # Parent db3f8e7d79d24077755c3cb890ad0acdea63b1ac Add wilsonk's static data segment finding code for x86-64 from #181. Thanks! diff -r db3f8e7d79d2 -r 23d36edea021 runtime/internal/memory.d --- a/runtime/internal/memory.d Thu Jan 22 17:57:38 2009 +0100 +++ b/runtime/internal/memory.d Thu Jan 22 18:23:30 2009 +0100 @@ -30,11 +30,7 @@ // does Posix suffice? version(Posix) { - //FIXME: proc map parsing is too naive to work on x86-64 - version(X86) - { - version = GC_Use_Data_Proc_Maps; - } + version = GC_Use_Data_Proc_Maps; } version(GC_Use_Data_Proc_Maps) @@ -279,10 +275,20 @@ dataStart = adjust_up( &Data_Start ); dataEnd = adjust_down( &Data_End ); } - else version( GC_Use_Data_Proc_Maps ) + else version(linux) + { + dataStart = adjust_up( &Data_Start ); + dataEnd = adjust_down( &Data_End ); + } + else + { + static assert( false, "Operating system not supported." ); + } + + //TODO: This could use cleanup! + version( GC_Use_Data_Proc_Maps ) { // TODO: Exclude zero-mapped regions - //FIXME: proc map parsing is too naive to work on x86-64 int fd = open("/proc/self/maps", O_RDONLY); ptrdiff_t count; // %% need to configure ret for read.. @@ -320,12 +326,30 @@ } else static if( S == 8 ) { - enum Ofs + //X86-64 only has 12 bytes address space(in PAE mode) - not 16 + //We also need the 32 bit offsets for 32 bit apps + version(X86_64) { + enum Ofs + { + Write_Prot = 27, + Start_Addr = 0, + End_Addr = 13, + Addr_Len = 12, + Write_Prot_32 = 19, + Start_Addr_32 = 0, + End_Addr_32 = 9, + Addr_Len_32 = 8, + } + } + else { - Write_Prot = 35, - Start_Addr = 0, - End_Addr = 9, - Addr_Len = 17, + enum Ofs + { + Write_Prot = 35, + Start_Addr = 0, + End_Addr = 9, + Addr_Len = 17, + } } } else @@ -334,7 +358,9 @@ } // %% this is wrong for 64-bit: - // uint strtoul(char *,char **,int); + // long strtoul(const char*,char**,int); + // but seems to work on x86-64: + // probably because C's long is 64 bit there if( s[Ofs.Write_Prot] == 'w' ) { @@ -346,8 +372,8 @@ // 1. Exclude anything overlapping [dataStart, dataEnd) // 2. Exclude stack if ( ( !dataEnd || - !( dataStart >= start && dataEnd <= end ) ) && - !( &buf[0] >= start && &buf[0] < end ) ) + !( dataStart >= start && dataEnd <= end ) ) && + !( &buf[0] >= start && &buf[0] < end ) ) { // we already have static data from this region. anything else // is heap (%% check) @@ -355,6 +381,25 @@ _d_gc_add_range(start, end); } } + version(X86_64) + { + //We need to check here for 32 bit apps like ldc produces + //and add them to the gc scan range + if( s[Ofs.Write_Prot_32] == 'w' ) + { + s[Ofs.Start_Addr_32 + Ofs.Addr_Len_32] = '\0'; + s[Ofs.End_Addr_32 + Ofs.Addr_Len_32] = '\0'; + start = cast(void*) strtoul(s + Ofs.Start_Addr_32, null, 16); + end = cast(void*) strtoul(s + Ofs.End_Addr_32, null, 16); + if ( ( !dataEnd || + !( dataStart >= start && dataEnd <= end ) ) && + !( &buf[0] >= start && &buf[0] < end ) ) + { + _d_gc_add_range(start, end); + } + } + } + p++; } else @@ -369,13 +414,4 @@ close(fd); } } - else version(linux) - { - dataStart = adjust_up( &Data_Start ); - dataEnd = adjust_down( &Data_End ); - } - else - { - static assert( false, "Operating system not supported." ); - } }