comparison runtime/internal/memory.d @ 899:23d36edea021

Add wilsonk's static data segment finding code for x86-64 from #181. Thanks!
author Christian Kamm <kamm incasoftware de>
date Thu, 22 Jan 2009 18:23:30 +0100
parents 77a3d6945f81
children 177afbf5297b
comparison
equal deleted inserted replaced
898:db3f8e7d79d2 899:23d36edea021
28 version = GC_Use_Dynamic_Ranges; 28 version = GC_Use_Dynamic_Ranges;
29 29
30 // does Posix suffice? 30 // does Posix suffice?
31 version(Posix) 31 version(Posix)
32 { 32 {
33 //FIXME: proc map parsing is too naive to work on x86-64 33 version = GC_Use_Data_Proc_Maps;
34 version(X86)
35 {
36 version = GC_Use_Data_Proc_Maps;
37 }
38 } 34 }
39 35
40 version(GC_Use_Data_Proc_Maps) 36 version(GC_Use_Data_Proc_Maps)
41 { 37 {
42 version(Posix) {} else { 38 version(Posix) {} else {
277 version( Win32 ) 273 version( Win32 )
278 { 274 {
279 dataStart = adjust_up( &Data_Start ); 275 dataStart = adjust_up( &Data_Start );
280 dataEnd = adjust_down( &Data_End ); 276 dataEnd = adjust_down( &Data_End );
281 } 277 }
282 else version( GC_Use_Data_Proc_Maps ) 278 else version(linux)
279 {
280 dataStart = adjust_up( &Data_Start );
281 dataEnd = adjust_down( &Data_End );
282 }
283 else
284 {
285 static assert( false, "Operating system not supported." );
286 }
287
288 //TODO: This could use cleanup!
289 version( GC_Use_Data_Proc_Maps )
283 { 290 {
284 // TODO: Exclude zero-mapped regions 291 // TODO: Exclude zero-mapped regions
285 //FIXME: proc map parsing is too naive to work on x86-64
286 292
287 int fd = open("/proc/self/maps", O_RDONLY); 293 int fd = open("/proc/self/maps", O_RDONLY);
288 ptrdiff_t count; // %% need to configure ret for read.. 294 ptrdiff_t count; // %% need to configure ret for read..
289 char buf[2024]; 295 char buf[2024];
290 char* p; 296 char* p;
318 Addr_Len = 8, 324 Addr_Len = 8,
319 } 325 }
320 } 326 }
321 else static if( S == 8 ) 327 else static if( S == 8 )
322 { 328 {
323 enum Ofs 329 //X86-64 only has 12 bytes address space(in PAE mode) - not 16
330 //We also need the 32 bit offsets for 32 bit apps
331 version(X86_64) {
332 enum Ofs
333 {
334 Write_Prot = 27,
335 Start_Addr = 0,
336 End_Addr = 13,
337 Addr_Len = 12,
338 Write_Prot_32 = 19,
339 Start_Addr_32 = 0,
340 End_Addr_32 = 9,
341 Addr_Len_32 = 8,
342 }
343 }
344 else
324 { 345 {
325 Write_Prot = 35, 346 enum Ofs
326 Start_Addr = 0, 347 {
327 End_Addr = 9, 348 Write_Prot = 35,
328 Addr_Len = 17, 349 Start_Addr = 0,
350 End_Addr = 9,
351 Addr_Len = 17,
352 }
329 } 353 }
330 } 354 }
331 else 355 else
332 { 356 {
333 static assert( false ); 357 static assert( false );
334 } 358 }
335 359
336 // %% this is wrong for 64-bit: 360 // %% this is wrong for 64-bit:
337 // uint strtoul(char *,char **,int); 361 // long strtoul(const char*,char**,int);
362 // but seems to work on x86-64:
363 // probably because C's long is 64 bit there
338 364
339 if( s[Ofs.Write_Prot] == 'w' ) 365 if( s[Ofs.Write_Prot] == 'w' )
340 { 366 {
341 s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0'; 367 s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0';
342 s[Ofs.End_Addr + Ofs.Addr_Len] = '\0'; 368 s[Ofs.End_Addr + Ofs.Addr_Len] = '\0';
344 end = cast(void*) strtoul(s + Ofs.End_Addr, null, 16); 370 end = cast(void*) strtoul(s + Ofs.End_Addr, null, 16);
345 371
346 // 1. Exclude anything overlapping [dataStart, dataEnd) 372 // 1. Exclude anything overlapping [dataStart, dataEnd)
347 // 2. Exclude stack 373 // 2. Exclude stack
348 if ( ( !dataEnd || 374 if ( ( !dataEnd ||
349 !( dataStart >= start && dataEnd <= end ) ) && 375 !( dataStart >= start && dataEnd <= end ) ) &&
350 !( &buf[0] >= start && &buf[0] < end ) ) 376 !( &buf[0] >= start && &buf[0] < end ) )
351 { 377 {
352 // we already have static data from this region. anything else 378 // we already have static data from this region. anything else
353 // is heap (%% check) 379 // is heap (%% check)
354 debug (ProcMaps) printf("Adding map range %p 0%p\n", start, end); 380 debug (ProcMaps) printf("Adding map range %p 0%p\n", start, end);
355 _d_gc_add_range(start, end); 381 _d_gc_add_range(start, end);
356 } 382 }
357 } 383 }
384 version(X86_64)
385 {
386 //We need to check here for 32 bit apps like ldc produces
387 //and add them to the gc scan range
388 if( s[Ofs.Write_Prot_32] == 'w' )
389 {
390 s[Ofs.Start_Addr_32 + Ofs.Addr_Len_32] = '\0';
391 s[Ofs.End_Addr_32 + Ofs.Addr_Len_32] = '\0';
392 start = cast(void*) strtoul(s + Ofs.Start_Addr_32, null, 16);
393 end = cast(void*) strtoul(s + Ofs.End_Addr_32, null, 16);
394 if ( ( !dataEnd ||
395 !( dataStart >= start && dataEnd <= end ) ) &&
396 !( &buf[0] >= start && &buf[0] < end ) )
397 {
398 _d_gc_add_range(start, end);
399 }
400 }
401 }
402
358 p++; 403 p++;
359 } 404 }
360 else 405 else
361 { 406 {
362 count = p - s; 407 count = p - s;
367 } 412 }
368 } 413 }
369 close(fd); 414 close(fd);
370 } 415 }
371 } 416 }
372 else version(linux) 417 }
373 {
374 dataStart = adjust_up( &Data_Start );
375 dataEnd = adjust_down( &Data_End );
376 }
377 else
378 {
379 static assert( false, "Operating system not supported." );
380 }
381 }