0.8.21.32: improvement for the space reservation mechanism on OS X
authorBrian Mastenbrook <bmastenb@cs.indiana.edu>
Sun, 10 Apr 2005 15:34:46 +0000 (15:34 +0000)
committerBrian Mastenbrook <bmastenb@cs.indiana.edu>
Sun, 10 Apr 2005 15:34:46 +0000 (15:34 +0000)
  * The C runtime is no longer relinked after running nm, which should avoid
    some cases where symbols moved when linking in the read-only space reservation
object. This was previously observed as segfaults in target-2 and could be worked
around by choosing a different C compiler.
  * Space is now reserved for each of our fixed-address spaces on OS X, currently:
      * read-only space
  * static space
  * dynamic-1 and dynamic-2 spaces
  * linkage table space
Should Apple ever decide to move the malloc heap again, none of these spaces will be picked
because their virtual memory ranges will have been reserved by the linker.

NEWS
src/runtime/Config.ppc-darwin
src/runtime/GNUmakefile
src/runtime/ppc-darwin-fix-rospace.c [new file with mode: 0644]
src/runtime/ppc-darwin-mkrospace.c
src/runtime/ppc-darwin-spacelist.h [new file with mode: 0644]
version.lisp-expr

diff --git a/NEWS b/NEWS
index b85bd54..9fc6eaf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,9 @@ changes in sbcl-0.8.22 relative to sbcl-0.8.21:
   * optimization: REPLACE on declared (UNSIGNED-BYTE 8) vectors, as well
     as other specialized array types, is much faster.  SUBSEQ and
     COPY-SEQ on such arrays have also been sped up.
+  * fixed bug: the runtime is now less vulnerable to changes in the
+    size of the SBCL object on OS X, and virtual memory is reserved for
+    all spaces that need to be at a fixed address.
   * fixed bug: finalizers are now thread-safe. (thanks to Gabor Mellis)
   * fixed bug: finalizers and after GC hooks that cause consing are now
     safe.
index 01ec5f6..4f47632 100644 (file)
@@ -2,6 +2,7 @@
 CFLAGS = -Dppc -g -Wall -O2 -no-cpp-precomp
 OS_SRC = bsd-os.c os-common.c ppc-darwin-os.c ppc-darwin-dlshim.c ppc-darwin-langinfo.c
 OS_LIBS = -lSystem -lc -lm
+OS_OBJS = ppc-darwin-rospace.o
 
 CC = gcc
 
@@ -14,32 +15,30 @@ CPP = cpp -no-cpp-precomp
 # expect our read-only space mapped. This hack causes the linker to
 # place a zero-fill-on-demand segment in the same place and size as
 # read-only-space, which is the only thing capable of keeping malloc
-# out of this range."
-#
-# FIXME: "-Wl,-segaddr,SBCLRO,0x1000000" is output from
-# ppc-darwin-mkrospace (it depends on READ_ONLY_SPACE I believe) but it
-# is hard-coded here!
-OS_LINK_FLAGS = -dynamic -Wl,-segaddr,SBCLRO,0x1000000 -Wl,-seg1addr,0x5000000 $(if $(AFTER_GROVEL_HEADERS),ppc-darwin-rospace.o)
+# out of this range.
+OS_LINK_FLAGS = -dynamic `cat ppc-darwin-link-flags`
 
 GC_SRC= cheneygc.c
 
-CLEAN_FILES += ppc-darwin-mkrospace
+CLEAN_FILES += ppc-darwin-mkrospace ppc-darwin-fix-rospace ppc-darwin-link-flags
 
 ppc-darwin-mkrospace: ppc-darwin-mkrospace.c
-       $(CC) -o $@ $<
+       $(CC) -g -Wall -pedantic -o $@ $<
 
-ppc-darwin-rospace.o: ppc-darwin-mkrospace
-       ./ppc-darwin-mkrospace
+ppc-darwin-fix-rospace: ppc-darwin-fix-rospace.c
+       $(CC) -g -Wall -pedantic -o $@ $<
+
+ppc-darwin-rospace.o ppc-darwin-link-flags: ppc-darwin-mkrospace
+       ./ppc-darwin-mkrospace > ppc-darwin-link-flags
 
 .PHONY: after-grovel-headers
 
-# Rebuild the sbcl runtime to avoid Panther placing the heap where
+# Fix the sbcl runtime to avoid Panther placing the heap where
 # it wants read only space (in the first 32 megabytes, where it
 # can be absolute-branched to with BA.)  Must be done after 
 # grovel-headers, because Apple's nm is broken.
-after-grovel-headers: ppc-darwin-rospace.o
-       rm -f sbcl
-       $(GNUMAKE) sbcl AFTER_GROVEL_HEADERS=1
+after-grovel-headers: ppc-darwin-fix-rospace
+       ./ppc-darwin-fix-rospace
 
 # Fortunatly make-target-1.sh does a make clean all the time.
 # Otherwise we would have to make sure that sbcl gets rebuilt without
index d60aeb9..c3e0a8f 100644 (file)
@@ -42,14 +42,14 @@ C_SRCS = alloc.c backtrace.c breakpoint.c coreparse.c \
 
 SRCS = $(C_SRCS) ${ARCH_SRC} ${ASSEM_SRC} ${OS_SRC} ${GC_SRC}
 
-OBJS = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(patsubst %.s,%.o,$(SRCS))))
+OBJS = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(patsubst %.s,%.o,$(SRCS)))) ${OS_OBJS}
 
 sbcl.nm: sbcl
        $(NM) sbcl | grep -v " F \| U " > ,$@
        mv -f ,$@ $@
 
 sbcl: ${OBJS} 
-       $(CC) ${LINKFLAGS} ${OS_LINK_FLAGS} -o $@ ${OBJS} ${OS_LIBS} -lm
+       $(CC) ${LINKFLAGS} ${OS_LINK_FLAGS} -o $@ ${OBJS} ${OS_OBJS} ${OS_LIBS} -lm
 
 
 .PHONY: clean all
diff --git a/src/runtime/ppc-darwin-fix-rospace.c b/src/runtime/ppc-darwin-fix-rospace.c
new file mode 100644 (file)
index 0000000..79a628e
--- /dev/null
@@ -0,0 +1,85 @@
+/* ppc-darwin-fix-rospace.c - fix the segment and section output by ppc-darwin-mkrospace.c to have the correct size */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <mach-o/loader.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "sbcl.h"
+#include "runtime.h"
+
+#include "ppc-darwin-spacelist.h"
+
+int main(int argc, char** argv)
+{
+  int fd;
+  int i, spacei;
+  struct stat filestat;
+  struct mach_header *header;
+  void* file_pointer;
+  size_t filesize;
+  size_t old_commands_size;
+  char* window;
+  size_t segments_size;
+
+  /* Open the SBCL binary */
+  fd = open("sbcl", O_RDWR, 0); /* wr unx prgrmmrs, we cn't spll */
+  if (fd == -1) {
+    perror(argv[0]);
+    return -1;
+  }
+  if (fstat(fd, &filestat) == -1) {
+    close(fd);
+    perror(argv[0]);
+    return -1;
+  }
+  filesize = filestat.st_size;
+  if ((int) (file_pointer = mmap(NULL, filesize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0)) == -1) {
+    perror(argv[0]);
+    close(fd);
+    return -1;
+  }
+
+  segments_size = 0;
+  spacei = 0;
+  header = (struct mach_header*) file_pointer;
+  window = (char*) (header + 1);
+  for (i = 0; i < header->ncmds; i++) {
+    struct load_command* current_segment;
+    current_segment = (struct load_command*) window;
+    segments_size += current_segment->cmdsize;
+    window += current_segment->cmdsize;
+    if (current_segment->cmd == LC_SEGMENT) {
+      int is_sbcl;
+      struct segment_command* seg = (struct segment_command*) current_segment;
+      struct section* sectptr;
+      int j, max;
+      max = seg->nsects;
+      if (strncmp("SBCL", seg->segname, 4) == 0) {
+       is_sbcl = 1;
+       seg->vmsize = space_sizes[spacei];
+      } else {
+       is_sbcl = 0;
+      }
+      seg++;
+      sectptr = (struct section*) seg;
+      for (j = 0; j < max; j++) {
+       if (is_sbcl) {
+         sectptr->size = space_sizes[spacei];
+         spacei++;
+       }
+       sectptr++;
+      }
+    }
+  }
+
+  munmap(file_pointer, filesize);
+  close(fd);
+  return 0;
+}
index 610e9cf..683808f 100644 (file)
@@ -7,53 +7,66 @@
 #include <sys/uio.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <stdio.h>
 
 #include "sbcl.h"
 #include "runtime.h"
 
+#include "ppc-darwin-spacelist.h"
+
 struct simple_object_file
 {
-  struct mach_header theheader;
   struct segment_command thesegment;
   struct section thesection;
 };
 
 int main(int argc, char** argv)
 {
+  struct mach_header *theheader;
   struct simple_object_file *theobj;
-  int fd;
-  theobj = (struct simple_object_file*) malloc(sizeof(struct simple_object_file));
-  theobj->theheader.magic = MH_MAGIC;
-  theobj->theheader.cputype = CPU_TYPE_POWERPC;
-  theobj->theheader.cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
-  theobj->theheader.filetype = MH_OBJECT;
-  theobj->theheader.ncmds = 1;
-  theobj->theheader.sizeofcmds = sizeof(struct segment_command) + sizeof(struct section);
-  theobj->theheader.flags = MH_NOUNDEFS;
-  theobj->thesegment.cmd = LC_SEGMENT;
-  theobj->thesegment.cmdsize = sizeof(struct segment_command) + sizeof(struct section);
-  memcpy(theobj->thesegment.segname, "", sizeof(char));
-  theobj->thesegment.fileoff = sizeof(struct mach_header);
-  theobj->thesegment.vmaddr = READ_ONLY_SPACE_START;
-  theobj->thesegment.vmsize = READ_ONLY_SPACE_END - READ_ONLY_SPACE_START;
-  theobj->thesegment.maxprot = VM_PROT_ALL;
-  theobj->thesegment.initprot = VM_PROT_ALL;
-  theobj->thesegment.nsects = 1;
-  theobj->thesegment.flags = 0;
-  memcpy(theobj->thesection.sectname, "core", 5);
-  memcpy(theobj->thesection.segname, "SBCLRO", 7);
-  theobj->thesection.addr = READ_ONLY_SPACE_START;
-  theobj->thesection.size = READ_ONLY_SPACE_END - READ_ONLY_SPACE_START;
-  theobj->thesection.offset = sizeof(struct mach_header) + sizeof(struct segment_command) + sizeof(struct section);
-  theobj->thesection.align = 0;
-  theobj->thesection.reloff = 0;
-  theobj->thesection.nreloc = 0;
-  theobj->thesection.flags = S_ZEROFILL | S_REGULAR | S_ATTR_SOME_INSTRUCTIONS;
-  theobj->thesection.reserved1 = 0;
-  theobj->thesection.reserved2 = 0;
+  int fd, i;
+
+  /* Produce the mach header */
+  theheader = (struct mach_header*) malloc(sizeof(struct mach_header));
+  theheader->magic = MH_MAGIC;
+  theheader->cputype = CPU_TYPE_POWERPC;
+  theheader->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+  theheader->filetype = MH_OBJECT;
+  theheader->ncmds = N_SEGMENTS_TO_PRODUCE;
+  theheader->sizeofcmds = N_SEGMENTS_TO_PRODUCE * (sizeof(struct segment_command) + sizeof(struct section));
+  theheader->flags = MH_NOUNDEFS;
+  printf("-Wl");
   fd = open("ppc-darwin-rospace.o", O_WRONLY | O_CREAT, 0644);
-  write(fd, theobj, sizeof(struct simple_object_file));
+  write(fd, theheader, sizeof(struct mach_header));
+
+  for (i = 0; i < N_SEGMENTS_TO_PRODUCE; i++) {
+    theobj = (struct simple_object_file*) malloc(sizeof(struct simple_object_file));
+    theobj->thesegment.cmd = LC_SEGMENT;
+    theobj->thesegment.cmdsize = sizeof(struct segment_command) + sizeof(struct section);
+    snprintf(theobj->thesegment.segname, 7, "SBCL%d", i);
+    theobj->thesegment.fileoff = sizeof(struct mach_header) + i * (sizeof(struct segment_command) + sizeof(struct section));
+    theobj->thesegment.vmaddr = space_start_locations[i];
+    theobj->thesegment.vmsize = 0;
+    theobj->thesegment.maxprot = VM_PROT_ALL;
+    theobj->thesegment.initprot = VM_PROT_ALL;
+    theobj->thesegment.nsects = 1;
+    theobj->thesegment.flags = 0;
+    snprintf(theobj->thesection.sectname, 7, "sect%d", i);
+    snprintf(theobj->thesection.segname, 7, "SBCL%d", i);
+    theobj->thesection.addr = space_start_locations[i];
+    theobj->thesection.size = 0;
+    theobj->thesection.offset = 0;
+    theobj->thesection.align = 0;
+    theobj->thesection.reloff = 0;
+    theobj->thesection.nreloc = 0;
+    theobj->thesection.flags = S_ZEROFILL | S_REGULAR | S_ATTR_SOME_INSTRUCTIONS;
+    theobj->thesection.reserved1 = 0;
+    theobj->thesection.reserved2 = 0;
+    write(fd, theobj, sizeof(struct simple_object_file));
+    printf(",-segaddr,SBCL%d,0x%x", i, space_start_locations[i]);
+    free(theobj);
+  }
+  printf("\n");
   close(fd);
-  printf("-Wl,-segaddr,SBCLRO,0x%x\n",READ_ONLY_SPACE_START);
   return 0;
 }
diff --git a/src/runtime/ppc-darwin-spacelist.h b/src/runtime/ppc-darwin-spacelist.h
new file mode 100644 (file)
index 0000000..e8b2f39
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef PPC_DARWIN_SPACELIST_H
+#define PPC_DARWIN_SPACELIST_H
+
+#define N_SEGMENTS_TO_PRODUCE 5
+
+unsigned int space_start_locations[N_SEGMENTS_TO_PRODUCE] =
+  { READ_ONLY_SPACE_START, STATIC_SPACE_START, DYNAMIC_0_SPACE_START, DYNAMIC_1_SPACE_START, LINKAGE_TABLE_SPACE_START};
+
+unsigned int space_sizes[N_SEGMENTS_TO_PRODUCE] =
+  { READ_ONLY_SPACE_END - READ_ONLY_SPACE_START,
+    STATIC_SPACE_END - STATIC_SPACE_START,
+    DYNAMIC_0_SPACE_END - DYNAMIC_0_SPACE_START,
+    DYNAMIC_1_SPACE_END - DYNAMIC_1_SPACE_START,
+    LINKAGE_TABLE_SPACE_END - LINKAGE_TABLE_SPACE_START};
+
+#endif
index c29142b..00a0ca5 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.21.31"
+"0.8.21.32"