[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/gc/dyn_load.c [Boehm-GC]
From: |
Dave Love |
Subject: |
[Emacs-diffs] Changes to emacs/gc/dyn_load.c [Boehm-GC] |
Date: |
Mon, 16 Jun 2003 11:41:52 -0400 |
Index: emacs/gc/dyn_load.c
diff -c emacs/gc/dyn_load.c:1.2.2.1 emacs/gc/dyn_load.c:1.2.2.2
*** emacs/gc/dyn_load.c:1.2.2.1 Thu Jun 5 14:23:04 2003
--- emacs/gc/dyn_load.c Mon Jun 16 11:41:51 2003
***************
*** 58,64 ****
!defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
!(defined(FREEBSD) && defined(__ELF__)) && \
!(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
! !defined(MACOSX)
--> We only know how to find data segments of dynamic libraries for the
--> above. Additional SVR4 variants might not be too
--> hard to add.
--- 58,64 ----
!defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
!(defined(FREEBSD) && defined(__ELF__)) && \
!(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
! !defined(DARWIN)
--> We only know how to find data segments of dynamic libraries for the
--> above. Additional SVR4 variants might not be too
--> hard to add.
***************
*** 283,338 ****
/* Repeatedly read until buffer is filled, or EOF is encountered */
/* Defined in os_dep.c. */
! static char *parse_map_entry(char *buf_ptr, word *start, word *end,
! char *prot_buf, unsigned int *maj_dev);
! void GC_register_dynamic_libraries()
{
- int f;
- int result;
char prot_buf[5];
! int maps_size;
! char maps_temp[32768];
! char *maps_buf;
! char *buf_ptr;
int count;
word start, end;
! unsigned int maj_dev, min_dev;
word least_ha, greatest_ha;
unsigned i;
word datastart = (word)(DATASTART);
! /* Read /proc/self/maps */
! /* Note that we may not allocate, and thus can't use stdio. */
! f = open("/proc/self/maps", O_RDONLY);
! if (-1 == f) ABORT("Couldn't open /proc/self/maps");
! /* stat() doesn't work for /proc/self/maps, so we have to
! read it to find out how large it is... */
! maps_size = 0;
! do {
! result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
! if (result <= 0) ABORT("Couldn't read /proc/self/maps");
! maps_size += result;
! } while (result == sizeof(maps_temp));
!
! if (maps_size > sizeof(maps_temp)) {
! /* If larger than our buffer, close and re-read it. */
! close(f);
! f = open("/proc/self/maps", O_RDONLY);
! if (-1 == f) ABORT("Couldn't open /proc/self/maps");
! maps_buf = alloca(maps_size);
! if (NULL == maps_buf) ABORT("/proc/self/maps alloca failed");
! result = GC_repeat_read(f, maps_buf, maps_size);
! if (result <= 0) ABORT("Couldn't read /proc/self/maps");
! } else {
! /* Otherwise use the fixed size buffer */
! maps_buf = maps_temp;
! }
!
! close(f);
! maps_buf[result] = '\0';
! buf_ptr = maps_buf;
! /* Compute heap bounds. Should be done by add_to_heap? */
least_ha = (word)(-1);
greatest_ha = 0;
for (i = 0; i < GC_n_heap_sects; ++i) {
--- 283,305 ----
/* Repeatedly read until buffer is filled, or EOF is encountered */
/* Defined in os_dep.c. */
! char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
! char *prot_buf, unsigned int *maj_dev);
! word GC_apply_to_maps(word (*fn)(char *));
! /* From os_dep.c */
! word GC_register_map_entries(char *maps)
{
char prot_buf[5];
! char *buf_ptr = maps;
int count;
word start, end;
! unsigned int maj_dev;
word least_ha, greatest_ha;
unsigned i;
word datastart = (word)(DATASTART);
! /* Compute heap bounds. FIXME: Should be done by add_to_heap? */
least_ha = (word)(-1);
greatest_ha = 0;
for (i = 0; i < GC_n_heap_sects; ++i) {
***************
*** 343,353 ****
}
if (greatest_ha < (word)GC_scratch_last_end_ptr)
greatest_ha = (word)GC_scratch_last_end_ptr;
- for (;;) {
-
- buf_ptr = parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
- if (buf_ptr == NULL) return;
if (prot_buf[1] == 'w') {
/* This is a writable mapping. Add it to */
/* the root set unless it is already otherwise */
--- 310,319 ----
}
if (greatest_ha < (word)GC_scratch_last_end_ptr)
greatest_ha = (word)GC_scratch_last_end_ptr;
+ for (;;) {
+ buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf,
&maj_dev);
+ if (buf_ptr == NULL) return 1;
if (prot_buf[1] == 'w') {
/* This is a writable mapping. Add it to */
/* the root set unless it is already otherwise */
***************
*** 359,374 ****
# ifdef THREADS
if (GC_segment_is_thread_stack(start, end)) continue;
# endif
! /* The rest of this assumes that there is no mapping */
! /* spanning the beginning of the data segment, or extending */
! /* beyond the entire heap at both ends. */
! /* Empirically these assumptions hold. */
!
! if (start < (word)DATAEND && end > (word)DATAEND) {
! /* Rld may use space at the end of the main data */
! /* segment. Thus we add that in. */
! start = (word)DATAEND;
! }
if (start < least_ha && end > least_ha) {
end = least_ha;
}
--- 325,331 ----
# ifdef THREADS
if (GC_segment_is_thread_stack(start, end)) continue;
# endif
! /* We no longer exclude the main data segment. */
if (start < least_ha && end > least_ha) {
end = least_ha;
}
***************
*** 378,384 ****
if (start >= least_ha && end <= greatest_ha) continue;
GC_add_roots_inner((char *)start, (char *)end, TRUE);
}
! }
}
/* We now take care of the main data segment ourselves: */
--- 335,348 ----
if (start >= least_ha && end <= greatest_ha) continue;
GC_add_roots_inner((char *)start, (char *)end, TRUE);
}
! }
! return 1;
! }
!
! void GC_register_dynamic_libraries()
! {
! if (!GC_apply_to_maps(GC_register_map_entries))
! ABORT("Failed to read /proc for library registration.");
}
/* We now take care of the main data segment ourselves: */
***************
*** 388,460 ****
}
# define HAVE_REGISTER_MAIN_STATIC_DATA
- //
- // parse_map_entry parses an entry from /proc/self/maps so we can
- // locate all writable data segments that belong to shared libraries.
- // The format of one of these entries and the fields we care about
- // is as follows:
- // XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
- // ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
- // start end prot maj_dev
- // 0 9 18 32
- //
- // For 64 bit ABIs:
- // 0 17 34 56
- //
- // The parser is called with a pointer to the entry and the return value
- // is either NULL or is advanced to the next entry(the byte after the
- // trailing '\n'.)
- //
- #if CPP_WORDSZ == 32
- # define OFFSET_MAP_START 0
- # define OFFSET_MAP_END 9
- # define OFFSET_MAP_PROT 18
- # define OFFSET_MAP_MAJDEV 32
- # define ADDR_WIDTH 8
- #endif
-
- #if CPP_WORDSZ == 64
- # define OFFSET_MAP_START 0
- # define OFFSET_MAP_END 17
- # define OFFSET_MAP_PROT 34
- # define OFFSET_MAP_MAJDEV 56
- # define ADDR_WIDTH 16
- #endif
-
- static char *parse_map_entry(char *buf_ptr, word *start, word *end,
- char *prot_buf, unsigned int *maj_dev)
- {
- int i;
- char *tok;
-
- if (buf_ptr == NULL || *buf_ptr == '\0') {
- return NULL;
- }
-
- memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4); // do the protections first
- prot_buf[4] = '\0';
-
- if (prot_buf[1] == 'w') { // we can skip all of this if it's not writable
-
- tok = buf_ptr;
- buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
- *start = strtoul(tok, NULL, 16);
-
- tok = buf_ptr+OFFSET_MAP_END;
- buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
- *end = strtoul(tok, NULL, 16);
-
- buf_ptr += OFFSET_MAP_MAJDEV;
- tok = buf_ptr;
- while (*buf_ptr != ':') buf_ptr++;
- *buf_ptr++ = '\0';
- *maj_dev = strtoul(tok, NULL, 16);
- }
-
- while (*buf_ptr && *buf_ptr++ != '\n');
-
- return buf_ptr;
- }
#endif /* USE_PROC_FOR_LIBRARIES */
--- 352,357 ----
***************
*** 1064,1070 ****
len = ldi->ldinfo_next;
GC_add_roots_inner(
ldi->ldinfo_dataorg,
! (unsigned long)ldi->ldinfo_dataorg
+ ldi->ldinfo_datasize,
TRUE);
ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
--- 961,967 ----
len = ldi->ldinfo_next;
GC_add_roots_inner(
ldi->ldinfo_dataorg,
! (ptr_t)(unsigned long)ldi->ldinfo_dataorg
+ ldi->ldinfo_datasize,
TRUE);
ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
***************
*** 1072,1134 ****
}
#endif /* RS6000 */
! #ifdef MACOSX
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
! /*#define MACOSX_DEBUG */
! void GC_register_dynamic_libraries()
! {
! unsigned long image_count;
! const struct mach_header *mach_header;
! const struct section *sec;
! unsigned long slide;
! unsigned long filetype;
! int i,j;
! unsigned long start;
! unsigned long end;
!
! static struct {
const char *seg;
const char *sect;
! } sections[] = {
{ SEG_DATA, SECT_DATA },
{ SEG_DATA, SECT_BSS },
{ SEG_DATA, SECT_COMMON }
! };
! image_count = _dyld_image_count();
! for(i=0;i<image_count;i++)
! {
! mach_header = _dyld_get_image_header(i);
! slide = _dyld_get_image_vmaddr_slide(i);
! filetype = mach_header->filetype;
! for(j=0;j<sizeof(sections)/sizeof(sections[0]);j++) {
! sec =
getsectbynamefromheader(mach_header,sections[j].seg,sections[j].sect);
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
! # ifdef MACOSX_DEBUG
GC_printf4("Adding section at %p-%p (%lu bytes) from image
%s\n",
! start,end,sec->size,_dyld_get_image_name(i));
# endif
!
! GC_add_roots_inner((char*)start,(char*)end,
! filetype == MH_EXECUTE ? FALSE : TRUE);
}
! }
}
#define HAVE_REGISTER_MAIN_STATIC_DATA
GC_bool GC_register_main_static_data()
{
return FALSE;
}
! #endif /* MACOSX */
#else /* !DYNAMIC_LOADING */
--- 969,1090 ----
}
#endif /* RS6000 */
! #ifdef DARWIN
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
! /*#define DARWIN_DEBUG*/
! const static struct {
const char *seg;
const char *sect;
! } GC_dyld_sections[] = {
{ SEG_DATA, SECT_DATA },
{ SEG_DATA, SECT_BSS },
{ SEG_DATA, SECT_COMMON }
! };
! #ifdef DARWIN_DEBUG
! static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
! unsigned long i,c;
! c = _dyld_image_count();
! for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr)
! return _dyld_get_image_name(i);
! return NULL;
! }
! #endif
! /* This should never be called by a thread holding the lock */
! static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
! unsigned long start,end,i;
! const struct section *sec;
! for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
! sec = getsectbynamefromheader(
! hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
! # ifdef DARWIN_DEBUG
GC_printf4("Adding section at %p-%p (%lu bytes) from image
%s\n",
! start,end,sec->size,GC_dyld_name_for_hdr(hdr));
# endif
! GC_add_roots((char*)start,(char*)end);
}
! # ifdef DARWIN_DEBUG
! GC_print_static_roots();
! # endif
! }
!
! /* This should never be called by a thread holding the lock */
! static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long
slide) {
! unsigned long start,end,i;
! const struct section *sec;
! for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
! sec = getsectbynamefromheader(
! hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
! if(sec == NULL || sec->size == 0) continue;
! start = slide + sec->addr;
! end = start + sec->size;
! # ifdef DARWIN_DEBUG
! GC_printf4("Removing section at %p-%p (%lu bytes) from image
%s\n",
! start,end,sec->size,GC_dyld_name_for_hdr(hdr));
! # endif
! GC_remove_roots((char*)start,(char*)end);
! }
! # ifdef DARWIN_DEBUG
! GC_print_static_roots();
! # endif
! }
!
! void GC_register_dynamic_libraries() {
! /* Currently does nothing. The callbacks are setup by GC_init_dyld()
! The dyld library takes it from there. */
! }
!
! /* The _dyld_* functions have an internal lock so no _dyld functions
! can be called while the world is stopped without the risk of a deadlock.
! Because of this we MUST setup callbacks BEFORE we ever stop the world.
! This should be called BEFORE any thread in created and WITHOUT the
! allocation lock held. */
!
! void GC_init_dyld() {
! static GC_bool initialized = FALSE;
!
! if(initialized) return;
!
! # ifdef DARWIN_DEBUG
! GC_printf0("Forcing full bind of GC code...\n");
! # endif
! if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
! GC_abort("_dyld_bind_fully_image_containing_addres failed");
!
! # ifdef DARWIN_DEBUG
! GC_printf0("Registering dyld callbacks...\n");
! # endif
!
! /* Apple's Documentation:
! When you call _dyld_register_func_for_add_image, the dynamic linker
runtime
! calls the specified callback (func) once for each of the images that is
! currently loaded into the program. When a new image is added to the
program,
! your callback is called again with the mach_header for the new image, and
the virtual memory slide amount of the new image.
!
! This WILL properly register existing and all future libraries
! */
!
! _dyld_register_func_for_add_image(GC_dyld_image_add);
! _dyld_register_func_for_remove_image(GC_dyld_image_remove);
! initialized = TRUE;
}
#define HAVE_REGISTER_MAIN_STATIC_DATA
GC_bool GC_register_main_static_data()
{
+ /* Already done through dyld callbacks */
return FALSE;
}
! #endif /* DARWIN */
#else /* !DYNAMIC_LOADING */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] Changes to emacs/gc/dyn_load.c [Boehm-GC],
Dave Love <=