1 /* 2 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. 3 * Copyright (c) 1997 by Silicon Graphics. All rights reserved. 4 * 5 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 6 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 7 * 8 * Permission is hereby granted to use or copy this program 9 * for any purpose, provided the above notices are retained on all copies. 10 * Permission to modify the code and to distribute modified code is granted, 11 * provided the above notices are retained, and a notice that the code was 12 * modified is included with the above copyright notice. 13 */ 14 15 #include "private/gc_priv.h" 16 17 /* 18 * This is incredibly OS specific code for tracking down data sections in 19 * dynamic libraries. There appears to be no way of doing this quickly 20 * without groveling through undocumented data structures. We would argue 21 * that this is a bug in the design of the dlopen interface. THIS CODE 22 * MAY BREAK IN FUTURE OS RELEASES. If this matters to you, don't hesitate 23 * to let your vendor know ... 24 * 25 * None of this is safe with dlclose and incremental collection. 26 * But then not much of anything is safe in the presence of dlclose. 27 */ 28 29 #if !defined(MACOS) && !defined(_WIN32_WCE) && !defined(__CC_ARM) 30 # include <sys/types.h> 31 #endif 32 33 /* BTL: avoid circular redefinition of dlopen if GC_SOLARIS_THREADS defined */ 34 #undef GC_MUST_RESTORE_REDEFINED_DLOPEN 35 #if defined(GC_PTHREADS) && !defined(GC_NO_DLOPEN) \ 36 && !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP) 37 /* To support threads in Solaris, gc.h interposes on dlopen by */ 38 /* defining "dlopen" to be "GC_dlopen", which is implemented below. */ 39 /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */ 40 /* real system dlopen() in their implementation. We first remove */ 41 /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */ 42 # undef dlopen 43 # define GC_MUST_RESTORE_REDEFINED_DLOPEN 44 #endif /* !GC_NO_DLOPEN */ 45 46 /* A user-supplied routine (custom filter) that might be called to */ 47 /* determine whether a DSO really needs to be scanned by the GC. */ 48 /* 0 means no filter installed. May be unused on some platforms. */ 49 /* FIXME: Add filter support for more platforms. */ 50 STATIC GC_has_static_roots_func GC_has_static_roots = 0; 51 52 #if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ 53 || defined(CYGWIN32)) && !defined(PCR) 54 55 #if !defined(SOLARISDL) && !defined(IRIX5) && \ 56 !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) && \ 57 !(defined(ALPHA) && defined(OSF1)) && \ 58 !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ 59 !defined(AIX) && !defined(SCO_ELF) && !defined(DGUX) && \ 60 !(defined(FREEBSD) && defined(__ELF__)) && \ 61 !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) && \ 62 !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \ 63 !defined(DARWIN) && !defined(CYGWIN32) 64 --> We only know how to find data segments of dynamic libraries for the 65 --> above. Additional SVR4 variants might not be too 66 --> hard to add. 67 #endif 68 69 #include <stdio.h> 70 #ifdef SOLARISDL 71 # include <sys/elf.h> 72 # include <dlfcn.h> 73 # include <link.h> 74 #endif 75 76 #if defined(NETBSD) 77 # include <sys/param.h> 78 # include <dlfcn.h> 79 # include <machine/elf_machdep.h> 80 # define ELFSIZE ARCH_ELFSIZE 81 #endif 82 83 #if defined(OPENBSD) 84 # include <sys/param.h> 85 # if OpenBSD >= 200519 86 # define HAVE_DL_ITERATE_PHDR 87 # endif 88 #endif /* OPENBSD */ 89 90 #if defined(SCO_ELF) || defined(DGUX) || defined(HURD) \ 91 || (defined(__ELF__) && (defined(LINUX) || defined(FREEBSD) \ 92 || defined(NETBSD) || defined(OPENBSD))) 93 # include <stddef.h> 94 # if !defined(OPENBSD) && !defined(PLATFORM_ANDROID) 95 /* OpenBSD does not have elf.h file; link.h below is sufficient. */ 96 /* Exclude Android because linker.h below includes its own version. */ 97 # include <elf.h> 98 # endif 99 # ifdef PLATFORM_ANDROID 100 /* If you don't need the "dynamic loading" feature, you may build */ 101 /* the collector with -D IGNORE_DYNAMIC_LOADING. */ 102 # ifdef BIONIC_ELFDATA_REDEF_BUG 103 /* Workaround a problem in Bionic (as of Android 4.2) which has */ 104 /* mismatching ELF_DATA definitions in sys/exec_elf.h and */ 105 /* asm/elf.h included from linker.h file (similar to EM_ALPHA). */ 106 # include <asm/elf.h> 107 # include <linux/elf-em.h> 108 # undef ELF_DATA 109 # undef EM_ALPHA 110 # endif 111 # include <link.h> 112 # if !defined(GC_DONT_DEFINE_LINK_MAP) && !(__ANDROID_API__ >= 21) 113 /* link_map and r_debug are defined in link.h of NDK r10+. */ 114 /* bionic/linker/linker.h defines them too but the header */ 115 /* itself is a C++ one starting from Android 4.3. */ 116 struct link_map { 117 uintptr_t l_addr; 118 char* l_name; 119 uintptr_t l_ld; 120 struct link_map* l_next; 121 struct link_map* l_prev; 122 }; 123 struct r_debug { 124 int32_t r_version; 125 struct link_map* r_map; 126 void (*r_brk)(void); 127 int32_t r_state; 128 uintptr_t r_ldbase; 129 }; 130 # endif 131 # else 132 # include <link.h> 133 # endif 134 #endif 135 136 /* Newer versions of GNU/Linux define this macro. We 137 * define it similarly for any ELF systems that don't. */ 138 # ifndef ElfW 139 # if defined(FREEBSD) 140 # if __ELF_WORD_SIZE == 32 141 # define ElfW(type) Elf32_##type 142 # else 143 # define ElfW(type) Elf64_##type 144 # endif 145 # elif defined(NETBSD) || defined(OPENBSD) 146 # if ELFSIZE == 32 147 # define ElfW(type) Elf32_##type 148 # else 149 # define ElfW(type) Elf64_##type 150 # endif 151 # else 152 # if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32 153 # define ElfW(type) Elf32_##type 154 # else 155 # define ElfW(type) Elf64_##type 156 # endif 157 # endif 158 # endif 159 160 #if defined(SOLARISDL) && !defined(USE_PROC_FOR_LIBRARIES) 161 162 #ifdef LINT 163 Elf32_Dyn _DYNAMIC; 164 #endif 165 166 STATIC struct link_map * 167 GC_FirstDLOpenedLinkMap(void) 168 { 169 extern ElfW(Dyn) _DYNAMIC; 170 ElfW(Dyn) *dp; 171 static struct link_map * cachedResult = 0; 172 static ElfW(Dyn) *dynStructureAddr = 0; 173 /* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */ 174 175 # ifdef SUNOS53_SHARED_LIB 176 /* BTL: Avoid the Solaris 5.3 bug that _DYNAMIC isn't being set */ 177 /* up properly in dynamically linked .so's. This means we have */ 178 /* to use its value in the set of original object files loaded */ 179 /* at program startup. */ 180 if( dynStructureAddr == 0 ) { 181 void* startupSyms = dlopen(0, RTLD_LAZY); 182 dynStructureAddr = (ElfW(Dyn)*)dlsym(startupSyms, "_DYNAMIC"); 183 } 184 # else 185 dynStructureAddr = &_DYNAMIC; 186 # endif 187 188 if (dynStructureAddr == 0) { 189 /* _DYNAMIC symbol not resolved. */ 190 return(0); 191 } 192 if( cachedResult == 0 ) { 193 int tag; 194 for( dp = ((ElfW(Dyn) *)(&_DYNAMIC)); (tag = dp->d_tag) != 0; dp++ ) { 195 if( tag == DT_DEBUG ) { 196 struct link_map *lm 197 = ((struct r_debug *)(dp->d_un.d_ptr))->r_map; 198 if( lm != 0 ) cachedResult = lm->l_next; /* might be NULL */ 199 break; 200 } 201 } 202 } 203 return cachedResult; 204 } 205 206 #endif /* SOLARISDL ... */ 207 208 /* BTL: added to fix circular dlopen definition if GC_SOLARIS_THREADS defined */ 209 # ifdef GC_MUST_RESTORE_REDEFINED_DLOPEN 210 # define dlopen GC_dlopen 211 # endif 212 213 # if defined(SOLARISDL) 214 215 /* Add dynamic library data sections to the root set. */ 216 # if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS) 217 --> fix mutual exclusion with dlopen 218 # endif 219 220 # ifndef USE_PROC_FOR_LIBRARIES 221 GC_INNER void GC_register_dynamic_libraries(void) 222 { 223 struct link_map *lm; 224 225 for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) { 226 ElfW(Ehdr) * e; 227 ElfW(Phdr) * p; 228 unsigned long offset; 229 char * start; 230 int i; 231 232 e = (ElfW(Ehdr) *) lm->l_addr; 233 p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff)); 234 offset = ((unsigned long)(lm->l_addr)); 235 for( i = 0; i < (int)e->e_phnum; i++, p++ ) { 236 switch( p->p_type ) { 237 case PT_LOAD: 238 { 239 if( !(p->p_flags & PF_W) ) break; 240 start = ((char *)(p->p_vaddr)) + offset; 241 GC_add_roots_inner( 242 start, 243 start + p->p_memsz, 244 TRUE 245 ); 246 } 247 break; 248 default: 249 break; 250 } 251 } 252 } 253 } 254 255 # endif /* !USE_PROC ... */ 256 # endif /* SOLARISDL */ 257 258 #if defined(SCO_ELF) || defined(DGUX) || defined(HURD) \ 259 || (defined(__ELF__) && (defined(LINUX) || defined(FREEBSD) \ 260 || defined(NETBSD) || defined(OPENBSD))) 261 262 #ifdef USE_PROC_FOR_LIBRARIES 263 264 #include <string.h> 265 266 #include <sys/stat.h> 267 #include <fcntl.h> 268 #include <unistd.h> 269 270 #define MAPS_BUF_SIZE (32*1024) 271 272 /* Sort an array of HeapSects by start address. */ 273 /* Unfortunately at least some versions of */ 274 /* Linux qsort end up calling malloc by way of sysconf, and hence can't */ 275 /* be used in the collector. Hence we roll our own. Should be */ 276 /* reasonably fast if the array is already mostly sorted, as we expect */ 277 /* it to be. */ 278 static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements) 279 { 280 signed_word n = (signed_word)number_of_elements; 281 signed_word nsorted = 1; 282 signed_word i; 283 284 while (nsorted < n) { 285 while (nsorted < n && 286 (word)base[nsorted-1].hs_start < (word)base[nsorted].hs_start) 287 ++nsorted; 288 if (nsorted == n) break; 289 GC_ASSERT((word)base[nsorted-1].hs_start > (word)base[nsorted].hs_start); 290 i = nsorted - 1; 291 while (i >= 0 && (word)base[i].hs_start > (word)base[i+1].hs_start) { 292 struct HeapSect tmp = base[i]; 293 base[i] = base[i+1]; 294 base[i+1] = tmp; 295 --i; 296 } 297 GC_ASSERT((word)base[nsorted-1].hs_start < (word)base[nsorted].hs_start); 298 ++nsorted; 299 } 300 } 301 302 STATIC word GC_register_map_entries(char *maps) 303 { 304 char *prot; 305 char *buf_ptr = maps; 306 ptr_t start, end; 307 unsigned int maj_dev; 308 ptr_t least_ha, greatest_ha; 309 unsigned i; 310 ptr_t datastart; 311 312 # ifdef DATASTART_IS_FUNC 313 static ptr_t datastart_cached = (ptr_t)(word)-1; 314 315 /* Evaluate DATASTART only once. */ 316 if (datastart_cached == (ptr_t)(word)-1) { 317 datastart_cached = (ptr_t)(DATASTART); 318 } 319 datastart = datastart_cached; 320 # else 321 datastart = (ptr_t)(DATASTART); 322 # endif 323 324 GC_ASSERT(I_HOLD_LOCK()); 325 sort_heap_sects(GC_our_memory, GC_n_memory); 326 least_ha = GC_our_memory[0].hs_start; 327 greatest_ha = GC_our_memory[GC_n_memory-1].hs_start 328 + GC_our_memory[GC_n_memory-1].hs_bytes; 329 330 for (;;) { 331 buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, 332 &maj_dev, 0); 333 if (buf_ptr == NULL) return 1; 334 if (prot[1] == 'w') { 335 /* This is a writable mapping. Add it to */ 336 /* the root set unless it is already otherwise */ 337 /* accounted for. */ 338 if ((word)start <= (word)GC_stackbottom 339 && (word)end >= (word)GC_stackbottom) { 340 /* Stack mapping; discard */ 341 continue; 342 } 343 # ifdef THREADS 344 /* This may fail, since a thread may already be */ 345 /* unregistered, but its thread stack may still be there. */ 346 /* That can fail because the stack may disappear while */ 347 /* we're marking. Thus the marker is, and has to be */ 348 /* prepared to recover from segmentation faults. */ 349 350 if (GC_segment_is_thread_stack(start, end)) continue; 351 352 /* FIXME: NPTL squirrels */ 353 /* away pointers in pieces of the stack segment that we */ 354 /* don't scan. We work around this */ 355 /* by treating anything allocated by libpthread as */ 356 /* uncollectible, as we do in some other cases. */ 357 /* A specifically identified problem is that */ 358 /* thread stacks contain pointers to dynamic thread */ 359 /* vectors, which may be reused due to thread caching. */ 360 /* They may not be marked if the thread is still live. */ 361 /* This specific instance should be addressed by */ 362 /* INCLUDE_LINUX_THREAD_DESCR, but that doesn't quite */ 363 /* seem to suffice. */ 364 /* We currently trace entire thread stacks, if they are */ 365 /* are currently cached but unused. This is */ 366 /* very suboptimal for performance reasons. */ 367 # endif 368 /* We no longer exclude the main data segment. */ 369 if ((word)end <= (word)least_ha 370 || (word)start >= (word)greatest_ha) { 371 /* The easy case; just trace entire segment */ 372 GC_add_roots_inner((char *)start, (char *)end, TRUE); 373 continue; 374 } 375 /* Add sections that don't belong to us. */ 376 i = 0; 377 while ((word)(GC_our_memory[i].hs_start 378 + GC_our_memory[i].hs_bytes) < (word)start) 379 ++i; 380 GC_ASSERT(i < GC_n_memory); 381 if ((word)GC_our_memory[i].hs_start <= (word)start) { 382 start = GC_our_memory[i].hs_start 383 + GC_our_memory[i].hs_bytes; 384 ++i; 385 } 386 while (i < GC_n_memory 387 && (word)GC_our_memory[i].hs_start < (word)end 388 && (word)start < (word)end) { 389 if ((word)start < (word)GC_our_memory[i].hs_start) 390 GC_add_roots_inner((char *)start, 391 GC_our_memory[i].hs_start, TRUE); 392 start = GC_our_memory[i].hs_start 393 + GC_our_memory[i].hs_bytes; 394 ++i; 395 } 396 if ((word)start < (word)end) 397 GC_add_roots_inner((char *)start, (char *)end, TRUE); 398 } 399 } 400 return 1; 401 } 402 403 GC_INNER void GC_register_dynamic_libraries(void) 404 { 405 if (!GC_register_map_entries(GC_get_maps())) 406 ABORT("Failed to read /proc for library registration"); 407 } 408 409 /* We now take care of the main data segment ourselves: */ 410 GC_INNER GC_bool GC_register_main_static_data(void) 411 { 412 return FALSE; 413 } 414 415 # define HAVE_REGISTER_MAIN_STATIC_DATA 416 417 #else /* !USE_PROC_FOR_LIBRARIES */ 418 419 /* The following is the preferred way to walk dynamic libraries */ 420 /* for glibc 2.2.4+. Unfortunately, it doesn't work for older */ 421 /* versions. Thanks to Jakub Jelinek for most of the code. */ 422 423 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ 424 || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)) \ 425 || defined(PLATFORM_ANDROID) /* Are others OK here, too? */ 426 /* We have the header files for a glibc that includes dl_iterate_phdr. */ 427 /* It may still not be available in the library on the target system. */ 428 /* Thus we also treat it as a weak symbol. */ 429 # define HAVE_DL_ITERATE_PHDR 430 # ifdef PLATFORM_ANDROID 431 /* Android headers might have no such definition for some targets. */ 432 int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), 433 void *data); 434 # endif 435 # pragma weak dl_iterate_phdr 436 #endif 437 438 #if (defined(FREEBSD) && __FreeBSD__ >= 7) 439 /* On the FreeBSD system, any target system at major version 7 shall */ 440 /* have dl_iterate_phdr; therefore, we need not make it weak as above. */ 441 # define HAVE_DL_ITERATE_PHDR 442 # define DL_ITERATE_PHDR_STRONG 443 #endif 444 445 #if defined(HAVE_DL_ITERATE_PHDR) 446 447 # ifdef PT_GNU_RELRO 448 /* Instead of registering PT_LOAD sections directly, we keep them */ 449 /* in a temporary list, and filter them by excluding PT_GNU_RELRO */ 450 /* segments. Processing PT_GNU_RELRO sections with */ 451 /* GC_exclude_static_roots instead would be superficially cleaner. But */ 452 /* it runs into trouble if a client registers an overlapping segment, */ 453 /* which unfortunately seems quite possible. */ 454 455 # define MAX_LOAD_SEGS MAX_ROOT_SETS 456 457 static struct load_segment { 458 ptr_t start; 459 ptr_t end; 460 /* Room for a second segment if we remove a RELRO segment */ 461 /* from the middle. */ 462 ptr_t start2; 463 ptr_t end2; 464 } load_segs[MAX_LOAD_SEGS]; 465 466 static int n_load_segs; 467 # endif /* PT_GNU_RELRO */ 468 469 STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info, 470 size_t size, void * ptr) 471 { 472 const ElfW(Phdr) * p; 473 ptr_t start, end; 474 int i; 475 476 /* Make sure struct dl_phdr_info is at least as big as we need. */ 477 if (size < offsetof (struct dl_phdr_info, dlpi_phnum) 478 + sizeof (info->dlpi_phnum)) 479 return -1; 480 481 p = info->dlpi_phdr; 482 for( i = 0; i < (int)info->dlpi_phnum; i++, p++ ) { 483 switch( p->p_type ) { 484 # ifdef PT_GNU_RELRO 485 case PT_GNU_RELRO: 486 /* This entry is known to be constant and will eventually be remapped 487 read-only. However, the address range covered by this entry is 488 typically a subset of a previously encountered "LOAD" segment, so 489 we need to exclude it. */ 490 { 491 int j; 492 493 start = ((ptr_t)(p->p_vaddr)) + info->dlpi_addr; 494 end = start + p->p_memsz; 495 for (j = n_load_segs; --j >= 0; ) { 496 if ((word)start >= (word)load_segs[j].start 497 && (word)start < (word)load_segs[j].end) { 498 if (load_segs[j].start2 != 0) { 499 WARN("More than one GNU_RELRO segment per load seg\n",0); 500 } else { 501 GC_ASSERT((word)end <= (word)load_segs[j].end); 502 /* Remove from the existing load segment */ 503 load_segs[j].end2 = load_segs[j].end; 504 load_segs[j].end = start; 505 load_segs[j].start2 = end; 506 } 507 break; 508 } 509 if (j == 0) WARN("Failed to find PT_GNU_RELRO segment" 510 " inside PT_LOAD region", 0); 511 } 512 } 513 514 break; 515 # endif 516 517 case PT_LOAD: 518 { 519 GC_has_static_roots_func callback = GC_has_static_roots; 520 if( !(p->p_flags & PF_W) ) break; 521 start = ((char *)(p->p_vaddr)) + info->dlpi_addr; 522 end = start + p->p_memsz; 523 524 if (callback != 0 && !callback(info->dlpi_name, start, p->p_memsz)) 525 break; 526 # ifdef PT_GNU_RELRO 527 if (n_load_segs >= MAX_LOAD_SEGS) ABORT("Too many PT_LOAD segs"); 528 # if CPP_WORDSZ == 64 529 /* FIXME: GC_push_all eventually does the correct */ 530 /* rounding to the next multiple of ALIGNMENT, so, most */ 531 /* probably, we should remove the corresponding assertion */ 532 /* check in GC_add_roots_inner along with this code line. */ 533 /* start pointer value may require aligning */ 534 start = (ptr_t)((word)start & ~(sizeof(word) - 1)); 535 # endif 536 load_segs[n_load_segs].start = start; 537 load_segs[n_load_segs].end = end; 538 load_segs[n_load_segs].start2 = 0; 539 load_segs[n_load_segs].end2 = 0; 540 ++n_load_segs; 541 # else 542 GC_add_roots_inner(start, end, TRUE); 543 # endif /* PT_GNU_RELRO */ 544 } 545 break; 546 default: 547 break; 548 } 549 } 550 551 *(int *)ptr = 1; /* Signal that we were called */ 552 return 0; 553 } 554 555 /* Do we need to separately register the main static data segment? */ 556 GC_INNER GC_bool GC_register_main_static_data(void) 557 { 558 # ifdef DL_ITERATE_PHDR_STRONG 559 /* If dl_iterate_phdr is not a weak symbol then don't test against */ 560 /* zero (otherwise a compiler might issue a warning). */ 561 return FALSE; 562 # else 563 return (dl_iterate_phdr == 0); /* implicit conversion to function ptr */ 564 # endif 565 } 566 567 /* Return TRUE if we succeed, FALSE if dl_iterate_phdr wasn't there. */ 568 STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) 569 { 570 int did_something; 571 if (GC_register_main_static_data()) 572 return FALSE; 573 574 # ifdef PT_GNU_RELRO 575 { 576 static GC_bool excluded_segs = FALSE; 577 n_load_segs = 0; 578 if (!EXPECT(excluded_segs, TRUE)) { 579 GC_exclude_static_roots_inner((ptr_t)load_segs, 580 (ptr_t)load_segs + sizeof(load_segs)); 581 excluded_segs = TRUE; 582 } 583 } 584 # endif 585 586 did_something = 0; 587 dl_iterate_phdr(GC_register_dynlib_callback, &did_something); 588 if (did_something) { 589 # ifdef PT_GNU_RELRO 590 int i; 591 592 for (i = 0; i < n_load_segs; ++i) { 593 if ((word)load_segs[i].end > (word)load_segs[i].start) { 594 GC_add_roots_inner(load_segs[i].start, load_segs[i].end, TRUE); 595 } 596 if ((word)load_segs[i].end2 > (word)load_segs[i].start2) { 597 GC_add_roots_inner(load_segs[i].start2, load_segs[i].end2, TRUE); 598 } 599 } 600 # endif 601 } else { 602 char *datastart; 603 char *dataend; 604 # ifdef DATASTART_IS_FUNC 605 static ptr_t datastart_cached = (ptr_t)(word)-1; 606 607 /* Evaluate DATASTART only once. */ 608 if (datastart_cached == (ptr_t)(word)-1) { 609 datastart_cached = (ptr_t)(DATASTART); 610 } 611 datastart = (char *)datastart_cached; 612 # else 613 datastart = DATASTART; 614 # endif 615 # ifdef DATAEND_IS_FUNC 616 { 617 static ptr_t dataend_cached = 0; 618 /* Evaluate DATAEND only once. */ 619 if (dataend_cached == 0) { 620 dataend_cached = (ptr_t)(DATAEND); 621 } 622 dataend = (char *)dataend_cached; 623 } 624 # else 625 dataend = DATAEND; 626 # endif 627 628 /* dl_iterate_phdr may forget the static data segment in */ 629 /* statically linked executables. */ 630 GC_add_roots_inner(datastart, dataend, TRUE); 631 # if defined(DATASTART2) 632 GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE); 633 # endif 634 } 635 return TRUE; 636 } 637 638 # define HAVE_REGISTER_MAIN_STATIC_DATA 639 640 #else /* !HAVE_DL_ITERATE_PHDR */ 641 642 /* Dynamic loading code for Linux running ELF. Somewhat tested on 643 * Linux/x86, untested but hopefully should work on Linux/Alpha. 644 * This code was derived from the Solaris/ELF support. Thanks to 645 * whatever kind soul wrote that. - Patrick Bridges */ 646 647 /* This doesn't necessarily work in all cases, e.g. with preloaded 648 * dynamic libraries. */ 649 650 # if defined(NETBSD) || defined(OPENBSD) 651 # include <sys/exec_elf.h> 652 /* for compatibility with 1.4.x */ 653 # ifndef DT_DEBUG 654 # define DT_DEBUG 21 655 # endif 656 # ifndef PT_LOAD 657 # define PT_LOAD 1 658 # endif 659 # ifndef PF_W 660 # define PF_W 2 661 # endif 662 # elif !defined(PLATFORM_ANDROID) 663 # include <elf.h> 664 # endif 665 666 # ifndef PLATFORM_ANDROID 667 # include <link.h> 668 # endif 669 670 #endif /* !HAVE_DL_ITERATE_PHDR */ 671 672 #ifdef __GNUC__ 673 # pragma weak _DYNAMIC 674 #endif 675 extern ElfW(Dyn) _DYNAMIC[]; 676 677 STATIC struct link_map * 678 GC_FirstDLOpenedLinkMap(void) 679 { 680 ElfW(Dyn) *dp; 681 static struct link_map *cachedResult = 0; 682 683 if (0 == (ptr_t)_DYNAMIC) { 684 /* _DYNAMIC symbol not resolved. */ 685 return(0); 686 } 687 if( cachedResult == 0 ) { 688 # if defined(NETBSD) && defined(RTLD_DI_LINKMAP) 689 struct link_map *lm = NULL; 690 if (!dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lm) && lm != NULL) { 691 /* Now lm points link_map object of libgc. Since it */ 692 /* might not be the first dynamically linked object, */ 693 /* try to find it (object next to the main object). */ 694 while (lm->l_prev != NULL) { 695 lm = lm->l_prev; 696 } 697 cachedResult = lm->l_next; 698 } 699 # else 700 int tag; 701 for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) { 702 if( tag == DT_DEBUG ) { 703 struct link_map *lm 704 = ((struct r_debug *)(dp->d_un.d_ptr))->r_map; 705 if( lm != 0 ) cachedResult = lm->l_next; /* might be NULL */ 706 break; 707 } 708 } 709 # endif /* !NETBSD || !RTLD_DI_LINKMAP */ 710 } 711 return cachedResult; 712 } 713 714 GC_INNER void GC_register_dynamic_libraries(void) 715 { 716 struct link_map *lm; 717 718 # ifdef HAVE_DL_ITERATE_PHDR 719 if (GC_register_dynamic_libraries_dl_iterate_phdr()) { 720 return; 721 } 722 # endif 723 for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) 724 { 725 ElfW(Ehdr) * e; 726 ElfW(Phdr) * p; 727 unsigned long offset; 728 char * start; 729 int i; 730 731 e = (ElfW(Ehdr) *) lm->l_addr; 732 # ifdef PLATFORM_ANDROID 733 if (e == NULL) 734 continue; 735 # endif 736 p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff)); 737 offset = ((unsigned long)(lm->l_addr)); 738 for( i = 0; i < (int)e->e_phnum; i++, p++ ) { 739 switch( p->p_type ) { 740 case PT_LOAD: 741 { 742 if( !(p->p_flags & PF_W) ) break; 743 start = ((char *)(p->p_vaddr)) + offset; 744 GC_add_roots_inner(start, start + p->p_memsz, TRUE); 745 } 746 break; 747 default: 748 break; 749 } 750 } 751 } 752 } 753 754 #endif /* !USE_PROC_FOR_LIBRARIES */ 755 756 #endif /* LINUX */ 757 758 #if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX)) 759 760 #include <sys/procfs.h> 761 #include <sys/stat.h> 762 #include <fcntl.h> 763 #include <elf.h> 764 #include <errno.h> 765 #include <signal.h> /* Only for the following test. */ 766 #ifndef _sigargs 767 # define IRIX6 768 #endif 769 770 /* We use /proc to track down all parts of the address space that are */ 771 /* mapped by the process, and throw out regions we know we shouldn't */ 772 /* worry about. This may also work under other SVR4 variants. */ 773 GC_INNER void GC_register_dynamic_libraries(void) 774 { 775 static int fd = -1; 776 char buf[30]; 777 static prmap_t * addr_map = 0; 778 static int current_sz = 0; /* Number of records currently in addr_map */ 779 static int needed_sz; /* Required size of addr_map */ 780 int i; 781 long flags; 782 ptr_t start; 783 ptr_t limit; 784 ptr_t heap_start = HEAP_START; 785 ptr_t heap_end = heap_start; 786 787 # ifdef SOLARISDL 788 # define MA_PHYS 0 789 # endif /* SOLARISDL */ 790 791 if (fd < 0) { 792 (void)snprintf(buf, sizeof(buf), "/proc/%ld", (long)getpid()); 793 buf[sizeof(buf) - 1] = '\0'; 794 /* The above generates a lint complaint, since pid_t varies. */ 795 /* It's unclear how to improve this. */ 796 fd = open(buf, O_RDONLY); 797 if (fd < 0) { 798 ABORT("/proc open failed"); 799 } 800 } 801 if (ioctl(fd, PIOCNMAP, &needed_sz) < 0) { 802 ABORT_ARG2("/proc PIOCNMAP ioctl failed", 803 ": fd = %d, errno = %d", fd, errno); 804 } 805 if (needed_sz >= current_sz) { 806 current_sz = needed_sz * 2 + 1; 807 /* Expansion, plus room for 0 record */ 808 addr_map = (prmap_t *)GC_scratch_alloc( 809 (word)current_sz * sizeof(prmap_t)); 810 if (addr_map == NULL) 811 ABORT("Insufficient memory for address map"); 812 } 813 if (ioctl(fd, PIOCMAP, addr_map) < 0) { 814 ABORT_ARG3("/proc PIOCMAP ioctl failed", 815 ": errcode= %d, needed_sz= %d, addr_map= %p", 816 errno, needed_sz, addr_map); 817 }; 818 if (GC_n_heap_sects > 0) { 819 heap_end = GC_heap_sects[GC_n_heap_sects-1].hs_start 820 + GC_heap_sects[GC_n_heap_sects-1].hs_bytes; 821 if ((word)heap_end < (word)GC_scratch_last_end_ptr) 822 heap_end = GC_scratch_last_end_ptr; 823 } 824 for (i = 0; i < needed_sz; i++) { 825 flags = addr_map[i].pr_mflags; 826 if ((flags & (MA_BREAK | MA_STACK | MA_PHYS 827 | MA_FETCHOP | MA_NOTCACHED)) != 0) goto irrelevant; 828 if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE)) 829 goto irrelevant; 830 /* The latter test is empirically useless in very old Irix */ 831 /* versions. Other than the */ 832 /* main data and stack segments, everything appears to be */ 833 /* mapped readable, writable, executable, and shared(!!). */ 834 /* This makes no sense to me. - HB */ 835 start = (ptr_t)(addr_map[i].pr_vaddr); 836 if (GC_roots_present(start)) goto irrelevant; 837 if ((word)start < (word)heap_end && (word)start >= (word)heap_start) 838 goto irrelevant; 839 840 limit = start + addr_map[i].pr_size; 841 /* The following seemed to be necessary for very old versions */ 842 /* of Irix, but it has been reported to discard relevant */ 843 /* segments under Irix 6.5. */ 844 # ifndef IRIX6 845 if (addr_map[i].pr_off == 0 && strncmp(start, ELFMAG, 4) == 0) { 846 /* Discard text segments, i.e. 0-offset mappings against */ 847 /* executable files which appear to have ELF headers. */ 848 caddr_t arg; 849 int obj; 850 # define MAP_IRR_SZ 10 851 static ptr_t map_irr[MAP_IRR_SZ]; 852 /* Known irrelevant map entries */ 853 static int n_irr = 0; 854 struct stat buf; 855 register int j; 856 857 for (j = 0; j < n_irr; j++) { 858 if (map_irr[j] == start) goto irrelevant; 859 } 860 arg = (caddr_t)start; 861 obj = ioctl(fd, PIOCOPENM, &arg); 862 if (obj >= 0) { 863 fstat(obj, &buf); 864 close(obj); 865 if ((buf.st_mode & 0111) != 0) { 866 if (n_irr < MAP_IRR_SZ) { 867 map_irr[n_irr++] = start; 868 } 869 goto irrelevant; 870 } 871 } 872 } 873 # endif /* !IRIX6 */ 874 GC_add_roots_inner(start, limit, TRUE); 875 irrelevant: ; 876 } 877 /* Don't keep cached descriptor, for now. Some kernels don't like us */ 878 /* to keep a /proc file descriptor around during kill -9. */ 879 if (close(fd) < 0) ABORT("Couldn't close /proc file"); 880 fd = -1; 881 } 882 883 # endif /* USE_PROC || IRIX5 */ 884 885 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) 886 887 # ifndef WIN32_LEAN_AND_MEAN 888 # define WIN32_LEAN_AND_MEAN 1 889 # endif 890 # define NOSERVICE 891 # include <windows.h> 892 # include <stdlib.h> 893 894 /* We traverse the entire address space and register all segments */ 895 /* that could possibly have been written to. */ 896 STATIC void GC_cond_add_roots(char *base, char * limit) 897 { 898 # ifdef GC_WIN32_THREADS 899 char * curr_base = base; 900 char * next_stack_lo; 901 char * next_stack_hi; 902 903 if (base == limit) return; 904 for(;;) { 905 GC_get_next_stack(curr_base, limit, &next_stack_lo, &next_stack_hi); 906 if ((word)next_stack_lo >= (word)limit) break; 907 if ((word)next_stack_lo > (word)curr_base) 908 GC_add_roots_inner(curr_base, next_stack_lo, TRUE); 909 curr_base = next_stack_hi; 910 } 911 if ((word)curr_base < (word)limit) 912 GC_add_roots_inner(curr_base, limit, TRUE); 913 # else 914 char * stack_top 915 = (char *)((word)GC_approx_sp() & 916 ~(GC_sysinfo.dwAllocationGranularity - 1)); 917 918 if (base == limit) return; 919 if ((word)limit > (word)stack_top 920 && (word)base < (word)GC_stackbottom) { 921 /* Part of the stack; ignore it. */ 922 return; 923 } 924 GC_add_roots_inner(base, limit, TRUE); 925 # endif 926 } 927 928 #ifdef DYNAMIC_LOADING 929 /* GC_register_main_static_data is not needed unless DYNAMIC_LOADING. */ 930 GC_INNER GC_bool GC_register_main_static_data(void) 931 { 932 # if defined(MSWINCE) || defined(CYGWIN32) 933 /* Do we need to separately register the main static data segment? */ 934 return FALSE; 935 # else 936 return GC_no_win32_dlls; 937 # endif 938 } 939 # define HAVE_REGISTER_MAIN_STATIC_DATA 940 #endif /* DYNAMIC_LOADING */ 941 942 # ifdef DEBUG_VIRTUALQUERY 943 void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf) 944 { 945 GC_printf("BaseAddress = 0x%lx, AllocationBase = 0x%lx," 946 " RegionSize = 0x%lx(%lu)\n", buf -> BaseAddress, 947 buf -> AllocationBase, buf -> RegionSize, buf -> RegionSize); 948 GC_printf("\tAllocationProtect = 0x%lx, State = 0x%lx, Protect = 0x%lx, " 949 "Type = 0x%lx\n", buf -> AllocationProtect, buf -> State, 950 buf -> Protect, buf -> Type); 951 } 952 # endif /* DEBUG_VIRTUALQUERY */ 953 954 # if defined(MSWINCE) || defined(CYGWIN32) 955 /* FIXME: Should we really need to scan MEM_PRIVATE sections? */ 956 /* For now, we don't add MEM_PRIVATE sections to the data roots for */ 957 /* WinCE because otherwise SEGV fault sometimes happens to occur in */ 958 /* GC_mark_from() (and, even if we use WRAP_MARK_SOME, WinCE prints */ 959 /* a "Data Abort" message to the debugging console). */ 960 /* To workaround that, use -DGC_REGISTER_MEM_PRIVATE. */ 961 # define GC_wnt TRUE 962 # endif 963 964 GC_INNER void GC_register_dynamic_libraries(void) 965 { 966 MEMORY_BASIC_INFORMATION buf; 967 size_t result; 968 DWORD protect; 969 LPVOID p; 970 char * base; 971 char * limit, * new_limit; 972 973 # ifdef MSWIN32 974 if (GC_no_win32_dlls) return; 975 # endif 976 base = limit = p = GC_sysinfo.lpMinimumApplicationAddress; 977 while ((word)p < (word)GC_sysinfo.lpMaximumApplicationAddress) { 978 result = VirtualQuery(p, &buf, sizeof(buf)); 979 # ifdef MSWINCE 980 if (result == 0) { 981 /* Page is free; advance to the next possible allocation base */ 982 new_limit = (char *) 983 (((DWORD) p + GC_sysinfo.dwAllocationGranularity) 984 & ~(GC_sysinfo.dwAllocationGranularity-1)); 985 } else 986 # endif 987 /* else */ { 988 if (result != sizeof(buf)) { 989 ABORT("Weird VirtualQuery result"); 990 } 991 new_limit = (char *)p + buf.RegionSize; 992 protect = buf.Protect; 993 if (buf.State == MEM_COMMIT 994 && (protect == PAGE_EXECUTE_READWRITE 995 || protect == PAGE_READWRITE) 996 && (buf.Type == MEM_IMAGE 997 # ifdef GC_REGISTER_MEM_PRIVATE 998 || (protect == PAGE_READWRITE && buf.Type == MEM_PRIVATE) 999 # else 1000 /* There is some evidence that we cannot always */ 1001 /* ignore MEM_PRIVATE sections under Windows ME */ 1002 /* and predecessors. Hence we now also check for */ 1003 /* that case. */ 1004 || (!GC_wnt && buf.Type == MEM_PRIVATE) 1005 # endif 1006 ) 1007 && !GC_is_heap_base(buf.AllocationBase)) { 1008 # ifdef DEBUG_VIRTUALQUERY 1009 GC_dump_meminfo(&buf); 1010 # endif 1011 if ((char *)p != limit) { 1012 GC_cond_add_roots(base, limit); 1013 base = p; 1014 } 1015 limit = new_limit; 1016 } 1017 } 1018 if ((word)p > (word)new_limit /* overflow */) break; 1019 p = (LPVOID)new_limit; 1020 } 1021 GC_cond_add_roots(base, limit); 1022 } 1023 1024 #endif /* MSWIN32 || MSWINCE || CYGWIN32 */ 1025 1026 #if defined(ALPHA) && defined(OSF1) 1027 1028 #include <loader.h> 1029 1030 extern char *sys_errlist[]; 1031 extern int sys_nerr; 1032 extern int errno; 1033 1034 GC_INNER void GC_register_dynamic_libraries(void) 1035 { 1036 int status; 1037 ldr_process_t mypid; 1038 1039 /* module */ 1040 ldr_module_t moduleid = LDR_NULL_MODULE; 1041 ldr_module_info_t moduleinfo; 1042 size_t moduleinfosize = sizeof(moduleinfo); 1043 size_t modulereturnsize; 1044 1045 /* region */ 1046 ldr_region_t region; 1047 ldr_region_info_t regioninfo; 1048 size_t regioninfosize = sizeof(regioninfo); 1049 size_t regionreturnsize; 1050 1051 /* Obtain id of this process */ 1052 mypid = ldr_my_process(); 1053 1054 /* For each module */ 1055 while (TRUE) { 1056 1057 /* Get the next (first) module */ 1058 status = ldr_next_module(mypid, &moduleid); 1059 1060 /* Any more modules? */ 1061 if (moduleid == LDR_NULL_MODULE) 1062 break; /* No more modules */ 1063 1064 /* Check status AFTER checking moduleid because */ 1065 /* of a bug in the non-shared ldr_next_module stub. */ 1066 if (status != 0) { 1067 ABORT_ARG3("ldr_next_module failed", 1068 ": status= %d, errcode= %d (%s)", status, errno, 1069 errno < sys_nerr ? sys_errlist[errno] : ""); 1070 } 1071 1072 /* Get the module information */ 1073 status = ldr_inq_module(mypid, moduleid, &moduleinfo, 1074 moduleinfosize, &modulereturnsize); 1075 if (status != 0 ) 1076 ABORT("ldr_inq_module failed"); 1077 1078 /* is module for the main program (i.e. nonshared portion)? */ 1079 if (moduleinfo.lmi_flags & LDR_MAIN) 1080 continue; /* skip the main module */ 1081 1082 # ifdef DL_VERBOSE 1083 GC_log_printf("---Module---\n"); 1084 GC_log_printf("Module ID\t = %16ld\n", moduleinfo.lmi_modid); 1085 GC_log_printf("Count of regions = %16d\n", moduleinfo.lmi_nregion); 1086 GC_log_printf("flags for module = %16lx\n", moduleinfo.lmi_flags); 1087 GC_log_printf("module pathname\t = \"%s\"\n", moduleinfo.lmi_name); 1088 # endif 1089 1090 /* For each region in this module */ 1091 for (region = 0; region < moduleinfo.lmi_nregion; region++) { 1092 /* Get the region information */ 1093 status = ldr_inq_region(mypid, moduleid, region, ®ioninfo, 1094 regioninfosize, ®ionreturnsize); 1095 if (status != 0 ) 1096 ABORT("ldr_inq_region failed"); 1097 1098 /* only process writable (data) regions */ 1099 if (! (regioninfo.lri_prot & LDR_W)) 1100 continue; 1101 1102 # ifdef DL_VERBOSE 1103 GC_log_printf("--- Region ---\n"); 1104 GC_log_printf("Region number\t = %16ld\n", 1105 regioninfo.lri_region_no); 1106 GC_log_printf("Protection flags = %016x\n", regioninfo.lri_prot); 1107 GC_log_printf("Virtual address\t = %16p\n", regioninfo.lri_vaddr); 1108 GC_log_printf("Mapped address\t = %16p\n", 1109 regioninfo.lri_mapaddr); 1110 GC_log_printf("Region size\t = %16ld\n", regioninfo.lri_size); 1111 GC_log_printf("Region name\t = \"%s\"\n", regioninfo.lri_name); 1112 # endif 1113 1114 /* register region as a garbage collection root */ 1115 GC_add_roots_inner((char *)regioninfo.lri_mapaddr, 1116 (char *)regioninfo.lri_mapaddr + regioninfo.lri_size, 1117 TRUE); 1118 1119 } 1120 } 1121 } 1122 #endif 1123 1124 #if defined(HPUX) 1125 1126 #include <errno.h> 1127 #include <dl.h> 1128 1129 extern char *sys_errlist[]; 1130 extern int sys_nerr; 1131 1132 GC_INNER void GC_register_dynamic_libraries(void) 1133 { 1134 int status; 1135 int index = 1; /* Ordinal position in shared library search list */ 1136 struct shl_descriptor *shl_desc; /* Shared library info, see dl.h */ 1137 1138 /* For each dynamic library loaded */ 1139 while (TRUE) { 1140 1141 /* Get info about next shared library */ 1142 status = shl_get(index, &shl_desc); 1143 1144 /* Check if this is the end of the list or if some error occurred */ 1145 if (status != 0) { 1146 # ifdef GC_HPUX_THREADS 1147 /* I've seen errno values of 0. The man page is not clear */ 1148 /* as to whether errno should get set on a -1 return. */ 1149 break; 1150 # else 1151 if (errno == EINVAL) { 1152 break; /* Moved past end of shared library list --> finished */ 1153 } else { 1154 ABORT_ARG3("shl_get failed", 1155 ": status= %d, errcode= %d (%s)", status, errno, 1156 errno < sys_nerr ? sys_errlist[errno] : ""); 1157 } 1158 # endif 1159 } 1160 1161 # ifdef DL_VERBOSE 1162 GC_log_printf("---Shared library---\n"); 1163 GC_log_printf("\tfilename\t= \"%s\"\n", shl_desc->filename); 1164 GC_log_printf("\tindex\t\t= %d\n", index); 1165 GC_log_printf("\thandle\t\t= %08x\n", 1166 (unsigned long) shl_desc->handle); 1167 GC_log_printf("\ttext seg.start\t= %08x\n", shl_desc->tstart); 1168 GC_log_printf("\ttext seg.end\t= %08x\n", shl_desc->tend); 1169 GC_log_printf("\tdata seg.start\t= %08x\n", shl_desc->dstart); 1170 GC_log_printf("\tdata seg.end\t= %08x\n", shl_desc->dend); 1171 GC_log_printf("\tref.count\t= %lu\n", shl_desc->ref_count); 1172 # endif 1173 1174 /* register shared library's data segment as a garbage collection root */ 1175 GC_add_roots_inner((char *) shl_desc->dstart, 1176 (char *) shl_desc->dend, TRUE); 1177 1178 index++; 1179 } 1180 } 1181 #endif /* HPUX */ 1182 1183 #ifdef AIX 1184 # pragma alloca 1185 # include <sys/ldr.h> 1186 # include <sys/errno.h> 1187 GC_INNER void GC_register_dynamic_libraries(void) 1188 { 1189 int len; 1190 char *ldibuf; 1191 int ldibuflen; 1192 struct ld_info *ldi; 1193 1194 ldibuf = alloca(ldibuflen = 8192); 1195 1196 while ( (len = loadquery(L_GETINFO,ldibuf,ldibuflen)) < 0) { 1197 if (errno != ENOMEM) { 1198 ABORT("loadquery failed"); 1199 } 1200 ldibuf = alloca(ldibuflen *= 2); 1201 } 1202 1203 ldi = (struct ld_info *)ldibuf; 1204 while (ldi) { 1205 len = ldi->ldinfo_next; 1206 GC_add_roots_inner( 1207 ldi->ldinfo_dataorg, 1208 (ptr_t)(unsigned long)ldi->ldinfo_dataorg 1209 + ldi->ldinfo_datasize, 1210 TRUE); 1211 ldi = len ? (struct ld_info *)((char *)ldi + len) : 0; 1212 } 1213 } 1214 #endif /* AIX */ 1215 1216 #ifdef DARWIN 1217 1218 /* __private_extern__ hack required for pre-3.4 gcc versions. */ 1219 #ifndef __private_extern__ 1220 # define __private_extern__ extern 1221 # include <mach-o/dyld.h> 1222 # undef __private_extern__ 1223 #else 1224 # include <mach-o/dyld.h> 1225 #endif 1226 #include <mach-o/getsect.h> 1227 1228 /*#define DARWIN_DEBUG*/ 1229 1230 /* Writable sections generally available on Darwin. */ 1231 STATIC const struct { 1232 const char *seg; 1233 const char *sect; 1234 } GC_dyld_sections[] = { 1235 { SEG_DATA, SECT_DATA }, 1236 /* Used by FSF GCC, but not by OS X system tools, so far. */ 1237 { SEG_DATA, "__static_data" }, 1238 { SEG_DATA, SECT_BSS }, 1239 { SEG_DATA, SECT_COMMON }, 1240 /* FSF GCC - zero-sized object sections for targets */ 1241 /*supporting section anchors. */ 1242 { SEG_DATA, "__zobj_data" }, 1243 { SEG_DATA, "__zobj_bss" } 1244 }; 1245 1246 /* Additional writable sections: */ 1247 /* GCC on Darwin constructs aligned sections "on demand", where */ 1248 /* the alignment size is embedded in the section name. */ 1249 /* Furthermore, there are distinctions between sections */ 1250 /* containing private vs. public symbols. It also constructs */ 1251 /* sections specifically for zero-sized objects, when the */ 1252 /* target supports section anchors. */ 1253 STATIC const char * const GC_dyld_add_sect_fmts[] = { 1254 "__bss%u", 1255 "__pu_bss%u", 1256 "__zo_bss%u", 1257 "__zo_pu_bss%u" 1258 }; 1259 1260 /* Currently, mach-o will allow up to the max of 2^15 alignment */ 1261 /* in an object file. */ 1262 #ifndef L2_MAX_OFILE_ALIGNMENT 1263 # define L2_MAX_OFILE_ALIGNMENT 15 1264 #endif 1265 1266 STATIC const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) 1267 { 1268 unsigned long i, c; 1269 c = _dyld_image_count(); 1270 for (i = 0; i < c; i++) 1271 if ((const struct GC_MACH_HEADER *)_dyld_get_image_header(i) == hdr) 1272 return _dyld_get_image_name(i); 1273 return NULL; 1274 } 1275 1276 /* This should never be called by a thread holding the lock. */ 1277 STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, 1278 intptr_t slide) 1279 { 1280 unsigned long start, end; 1281 unsigned i, j; 1282 const struct GC_MACH_SECTION *sec; 1283 const char *name; 1284 GC_has_static_roots_func callback = GC_has_static_roots; 1285 char secnam[16]; 1286 const char *fmt; 1287 DCL_LOCK_STATE; 1288 1289 if (GC_no_dls) return; 1290 # ifdef DARWIN_DEBUG 1291 name = GC_dyld_name_for_hdr(hdr); 1292 # else 1293 name = callback != 0 ? GC_dyld_name_for_hdr(hdr) : NULL; 1294 # endif 1295 for (i = 0; i < sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++) { 1296 sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg, 1297 GC_dyld_sections[i].sect); 1298 if (sec == NULL || sec->size < sizeof(word)) 1299 continue; 1300 start = slide + sec->addr; 1301 end = start + sec->size; 1302 LOCK(); 1303 /* The user callback is called holding the lock. */ 1304 if (callback == 0 || callback(name, (void*)start, (size_t)sec->size)) { 1305 # ifdef DARWIN_DEBUG 1306 GC_log_printf( 1307 "Adding section __DATA,%s at %p-%p (%lu bytes) from image %s\n", 1308 GC_dyld_sections[i].sect, (void*)start, (void*)end, 1309 (unsigned long)sec->size, name); 1310 # endif 1311 GC_add_roots_inner((ptr_t)start, (ptr_t)end, FALSE); 1312 } 1313 UNLOCK(); 1314 } 1315 1316 /* Sections constructed on demand. */ 1317 for (j = 0; j < sizeof(GC_dyld_add_sect_fmts) / sizeof(char *); j++) { 1318 fmt = GC_dyld_add_sect_fmts[j]; 1319 /* Add our manufactured aligned BSS sections. */ 1320 for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) { 1321 (void)snprintf(secnam, sizeof(secnam), fmt, (unsigned)i); 1322 secnam[sizeof(secnam) - 1] = '\0'; 1323 sec = GC_GETSECTBYNAME(hdr, SEG_DATA, secnam); 1324 if (sec == NULL || sec->size == 0) 1325 continue; 1326 start = slide + sec->addr; 1327 end = start + sec->size; 1328 # ifdef DARWIN_DEBUG 1329 GC_log_printf("Adding on-demand section __DATA,%s at" 1330 " %p-%p (%lu bytes) from image %s\n", 1331 secnam, (void*)start, (void*)end, 1332 (unsigned long)sec->size, name); 1333 # endif 1334 GC_add_roots((char*)start, (char*)end); 1335 } 1336 } 1337 1338 # ifdef DARWIN_DEBUG 1339 GC_print_static_roots(); 1340 # endif 1341 } 1342 1343 /* This should never be called by a thread holding the lock. */ 1344 STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, 1345 intptr_t slide) 1346 { 1347 unsigned long start, end; 1348 unsigned i, j; 1349 const struct GC_MACH_SECTION *sec; 1350 char secnam[16]; 1351 const char *fmt; 1352 1353 for (i = 0; i < sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++) { 1354 sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg, 1355 GC_dyld_sections[i].sect); 1356 if (sec == NULL || sec->size == 0) 1357 continue; 1358 start = slide + sec->addr; 1359 end = start + sec->size; 1360 # ifdef DARWIN_DEBUG 1361 GC_log_printf( 1362 "Removing section __DATA,%s at %p-%p (%lu bytes) from image %s\n", 1363 GC_dyld_sections[i].sect, (void*)start, (void*)end, 1364 (unsigned long)sec->size, GC_dyld_name_for_hdr(hdr)); 1365 # endif 1366 GC_remove_roots((char*)start, (char*)end); 1367 } 1368 1369 /* Remove our on-demand sections. */ 1370 for (j = 0; j < sizeof(GC_dyld_add_sect_fmts) / sizeof(char *); j++) { 1371 fmt = GC_dyld_add_sect_fmts[j]; 1372 for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) { 1373 (void)snprintf(secnam, sizeof(secnam), fmt, (unsigned)i); 1374 secnam[sizeof(secnam) - 1] = '\0'; 1375 sec = GC_GETSECTBYNAME(hdr, SEG_DATA, secnam); 1376 if (sec == NULL || sec->size == 0) 1377 continue; 1378 start = slide + sec->addr; 1379 end = start + sec->size; 1380 # ifdef DARWIN_DEBUG 1381 GC_log_printf("Removing on-demand section __DATA,%s at" 1382 " %p-%p (%lu bytes) from image %s\n", secnam, 1383 (void*)start, (void*)end, (unsigned long)sec->size, 1384 GC_dyld_name_for_hdr(hdr)); 1385 # endif 1386 GC_remove_roots((char*)start, (char*)end); 1387 } 1388 } 1389 1390 # ifdef DARWIN_DEBUG 1391 GC_print_static_roots(); 1392 # endif 1393 } 1394 1395 GC_INNER void GC_register_dynamic_libraries(void) 1396 { 1397 /* Currently does nothing. The callbacks are setup by GC_init_dyld() 1398 The dyld library takes it from there. */ 1399 } 1400 1401 /* The _dyld_* functions have an internal lock so no _dyld functions 1402 can be called while the world is stopped without the risk of a deadlock. 1403 Because of this we MUST setup callbacks BEFORE we ever stop the world. 1404 This should be called BEFORE any thread in created and WITHOUT the 1405 allocation lock held. */ 1406 1407 GC_INNER void GC_init_dyld(void) 1408 { 1409 static GC_bool initialized = FALSE; 1410 1411 if (initialized) return; 1412 1413 # ifdef DARWIN_DEBUG 1414 GC_log_printf("Registering dyld callbacks...\n"); 1415 # endif 1416 1417 /* Apple's Documentation: 1418 When you call _dyld_register_func_for_add_image, the dynamic linker 1419 runtime calls the specified callback (func) once for each of the images 1420 that is currently loaded into the program. When a new image is added to 1421 the program, your callback is called again with the mach_header for the 1422 new image, and the virtual memory slide amount of the new image. 1423 1424 This WILL properly register already linked libraries and libraries 1425 linked in the future. 1426 */ 1427 1428 _dyld_register_func_for_add_image(GC_dyld_image_add); 1429 _dyld_register_func_for_remove_image(GC_dyld_image_remove); 1430 /* Ignore 2 compiler warnings here: passing argument 1 of */ 1431 /* '_dyld_register_func_for_add/remove_image' from incompatible */ 1432 /* pointer type. */ 1433 1434 /* Set this early to avoid reentrancy issues. */ 1435 initialized = TRUE; 1436 1437 # ifdef NO_DYLD_BIND_FULLY_IMAGE 1438 /* FIXME: What should we do in this case? */ 1439 # else 1440 if (GC_no_dls) return; /* skip main data segment registration */ 1441 1442 /* When the environment variable is set, the dynamic linker binds */ 1443 /* all undefined symbols the application needs at launch time. */ 1444 /* This includes function symbols that are normally bound lazily at */ 1445 /* the time of their first invocation. */ 1446 if (GETENV("DYLD_BIND_AT_LAUNCH") == 0) { 1447 /* The environment variable is unset, so we should bind manually. */ 1448 # ifdef DARWIN_DEBUG 1449 GC_log_printf("Forcing full bind of GC code...\n"); 1450 # endif 1451 /* FIXME: '_dyld_bind_fully_image_containing_address' is deprecated. */ 1452 if (!_dyld_bind_fully_image_containing_address( 1453 (unsigned long *)GC_malloc)) 1454 ABORT("_dyld_bind_fully_image_containing_address failed"); 1455 } 1456 # endif 1457 } 1458 1459 #define HAVE_REGISTER_MAIN_STATIC_DATA 1460 GC_INNER GC_bool GC_register_main_static_data(void) 1461 { 1462 /* Already done through dyld callbacks */ 1463 return FALSE; 1464 } 1465 1466 #endif /* DARWIN */ 1467 1468 #elif defined(PCR) 1469 1470 # include "il/PCR_IL.h" 1471 # include "th/PCR_ThCtl.h" 1472 # include "mm/PCR_MM.h" 1473 1474 GC_INNER void GC_register_dynamic_libraries(void) 1475 { 1476 /* Add new static data areas of dynamically loaded modules. */ 1477 PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile(); 1478 PCR_IL_LoadedSegment * q; 1479 1480 /* Skip uncommitted files */ 1481 while (p != NIL && !(p -> lf_commitPoint)) { 1482 /* The loading of this file has not yet been committed */ 1483 /* Hence its description could be inconsistent. */ 1484 /* Furthermore, it hasn't yet been run. Hence its data */ 1485 /* segments can't possibly reference heap allocated */ 1486 /* objects. */ 1487 p = p -> lf_prev; 1488 } 1489 for (; p != NIL; p = p -> lf_prev) { 1490 for (q = p -> lf_ls; q != NIL; q = q -> ls_next) { 1491 if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK) 1492 == PCR_IL_SegFlags_Traced_on) { 1493 GC_add_roots_inner((char *)(q -> ls_addr), 1494 (char *)(q -> ls_addr) + q -> ls_bytes, TRUE); 1495 } 1496 } 1497 } 1498 } 1499 #endif /* PCR && !DYNAMIC_LOADING && !MSWIN32 */ 1500 1501 #if !defined(HAVE_REGISTER_MAIN_STATIC_DATA) && defined(DYNAMIC_LOADING) 1502 /* Do we need to separately register the main static data segment? */ 1503 GC_INNER GC_bool GC_register_main_static_data(void) 1504 { 1505 return TRUE; 1506 } 1507 #endif /* HAVE_REGISTER_MAIN_STATIC_DATA */ 1508 1509 /* Register a routine to filter dynamic library registration. */ 1510 GC_API void GC_CALL GC_register_has_static_roots_callback( 1511 GC_has_static_roots_func callback) 1512 { 1513 GC_has_static_roots = callback; 1514 } 1515