Mercurial > projects > ldc
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 } |