18 |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 |
Boston, MA 02111-1307, USA. */ |
Boston, MA 02111-1307, USA. */ |
20 |
|
|
21 |
|
/* |
22 |
|
|
23 |
|
This file is part of GNU Common Lisp, herein referred to as GCL |
24 |
|
|
25 |
|
GCL is free software; you can redistribute it and/or modify it under |
26 |
|
the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE as published by |
27 |
|
the Free Software Foundation; either version 2, or (at your option) |
28 |
|
any later version. |
29 |
|
|
30 |
|
GCL is distributed in the hope that it will be useful, but WITHOUT |
31 |
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
32 |
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
33 |
|
License for more details. |
34 |
|
|
35 |
|
You should have received a copy of the GNU Library General Public License |
36 |
|
along with GCL; see the file COPYING. If not, write to the Free Software |
37 |
|
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
38 |
|
|
39 |
|
*/ |
40 |
|
|
41 |
/* Contributed by Andrew Choi (akochoi@mac.com). */ |
/* Contributed by Andrew Choi (akochoi@mac.com). */ |
42 |
|
|
43 |
/* Documentation note. |
/* Documentation note. |
115 |
#include <sys/types.h> |
#include <sys/types.h> |
116 |
#include <unistd.h> |
#include <unistd.h> |
117 |
#include <mach/mach.h> |
#include <mach/mach.h> |
118 |
|
#include <mach/mach_error.h> |
119 |
#include <mach-o/loader.h> |
#include <mach-o/loader.h> |
120 |
|
#include <mach-o/nlist.h> |
121 |
#include <objc/malloc.h> |
#include <objc/malloc.h> |
122 |
|
|
123 |
#include <sys/mman.h> |
#include <sys/mman.h> |
133 |
#define VM_DATA_TOP (20 * 1024 * 1024) |
#define VM_DATA_TOP (20 * 1024 * 1024) |
134 |
|
|
135 |
/* Used by malloc_freezedry and malloc_jumpstart. */ |
/* Used by malloc_freezedry and malloc_jumpstart. */ |
136 |
int malloc_cookie; |
extern int malloc_cookie; |
137 |
|
|
138 |
/* Type of an element on the list of regions to be dumped. */ |
/* Type of an element on the list of regions to be dumped. */ |
139 |
struct region_t { |
struct region_t { |
184 |
|
|
185 |
malloc_zone_t *gcl_zone = 0L; |
malloc_zone_t *gcl_zone = 0L; |
186 |
|
|
187 |
unsigned num_marked_regions; |
#define MAX_MARKED_REGIONS 1024 |
188 |
|
|
189 |
#include <mach/mach_error.h> |
vm_range_t marked_regions [MAX_MARKED_REGIONS]; |
|
#include <mach-o/nlist.h> |
|
190 |
|
|
191 |
#ifndef BIG_HEAP_SIZE |
unsigned num_marked_regions; |
192 |
#define BIG_HEAP_SIZE 0x50000000 |
|
193 |
#endif |
/* Size of the heap. */ |
194 |
|
int big_heap = BIG_HEAP_SIZE; |
195 |
|
|
196 |
int big_heap = BIG_HEAP_SIZE; |
/* Start of the heap. */ |
197 |
|
char *mach_mapstart = 0; |
198 |
|
|
199 |
char *mach_maplimit = 0; |
/* End of the heap. */ |
200 |
char *mach_brkpt = 0; |
char *mach_maplimit = 0; |
|
char *mach_mapstart = 0; |
|
201 |
|
|
202 |
|
/* Position ot the break within the heap. */ |
203 |
|
char *mach_brkpt = 0; |
204 |
|
|
205 |
/* Read n bytes from infd into memory starting at address dest. |
/* Read n bytes from infd into memory starting at address dest. |
206 |
Return true if successful, false otherwise. */ |
Return true if successful, false otherwise. */ |
932 |
unexec_error ("cannot write final header contents"); |
unexec_error ("cannot write final header contents"); |
933 |
} |
} |
934 |
|
|
935 |
#define MAX_MARKED_REGIONS 1024 |
/* Mark a range of virtual memory to be dumped upon unexec()'ing. */ |
|
|
|
|
vm_range_t marked_regions[MAX_MARKED_REGIONS]; |
|
936 |
|
|
937 |
void |
void |
938 |
mark_region (unsigned long address, unsigned long size) |
mark_region (unsigned long address, unsigned long size) |
939 |
{ |
{ |
940 |
if (num_marked_regions < MAX_MARKED_REGIONS) |
if (num_marked_regions < MAX_MARKED_REGIONS) |
941 |
{ |
{ |
942 |
marked_regions[num_marked_regions].address = address; |
marked_regions[num_marked_regions].address = address; |
943 |
marked_regions[num_marked_regions].size = size; |
marked_regions[num_marked_regions].size = size; |
944 |
|
|
945 |
num_marked_regions++; |
num_marked_regions++; |
946 |
} |
} |
947 |
else { |
else { |
948 |
printf ("warning: too many marked regions\n"); |
fprintf (stderr, "warning: too many marked regions\n"); |
949 |
|
fflush (stderr); |
950 |
} |
} |
951 |
} |
} |
952 |
|
|
971 |
unexec (char *outfile, char *infile, void *start_data, void *start_bss, |
unexec (char *outfile, char *infile, void *start_data, void *start_bss, |
972 |
void *entry_address) |
void *entry_address) |
973 |
{ |
{ |
|
/*extern malloc_zone_t *debug_zone __attribute__((weak_import));*/ |
|
|
|
|
974 |
infd = open (infile, O_RDONLY, 0); |
infd = open (infile, O_RDONLY, 0); |
975 |
if (infd < 0) |
if (infd < 0) |
976 |
{ |
{ |
999 |
/*find_gcl_zone_regions ();*/ |
/*find_gcl_zone_regions ();*/ |
1000 |
add_marked_regions (); |
add_marked_regions (); |
1001 |
|
|
|
/* |
|
|
if (debug_zone != NULL) |
|
|
debug_zone->introspect->enumerator (mach_task_self(), 0, |
|
|
MALLOC_PTR_REGION_RANGE_TYPE |
|
|
| MALLOC_ADMIN_REGION_RANGE_TYPE, |
|
|
(vm_address_t) debug_zone, |
|
|
unexec_reader, |
|
|
unexec_regions_recorder); |
|
|
*/ |
|
|
|
|
1002 |
in_dumped_exec = 1; |
in_dumped_exec = 1; |
1003 |
|
|
1004 |
dump_it (); |
dump_it (); |
1049 |
my_free (ptr); |
my_free (ptr); |
1050 |
} |
} |
1051 |
|
|
1052 |
|
/* Create a new zone to accommodate GCL's heap and make it the default zone. */ |
1053 |
|
|
1054 |
void init_darwin_zone_compat () |
void init_darwin_zone_compat () |
1055 |
{ |
{ |
1056 |
extern unsigned malloc_num_zones; |
extern unsigned malloc_num_zones; |
1057 |
malloc_zone_t *default_zone; |
extern malloc_zone_t **malloc_zones; |
1058 |
|
unsigned malloc_num_zones_copy; |
1059 |
default_zone = malloc_default_zone (); |
malloc_zone_t **malloc_zones_copy; |
1060 |
|
malloc_zone_t *default_zone; |
1061 |
gcl_zone = malloc_create_zone (0,0); |
kern_return_t rtn; |
1062 |
|
vm_size_t s; |
1063 |
gcl_zone->size = (void *) stub_size; |
unsigned i; |
1064 |
gcl_zone->malloc = (void *) stub_malloc; |
|
1065 |
gcl_zone->calloc = (void *) stub_calloc; |
default_zone = malloc_default_zone (); |
1066 |
gcl_zone->valloc = (void *) stub_valloc; |
|
1067 |
gcl_zone->realloc = (void *) stub_realloc; |
if ((gcl_zone = malloc_create_zone (0,0)) == NULL) { |
1068 |
gcl_zone->free = (void *) stub_free; |
fprintf (stderr, "init_darwin_zone_compat(): malloc_create_zone() failed\n"); |
1069 |
/* if the zone introspector is ever called, the program will crash */ |
exit (1); |
1070 |
|
} |
|
/* we could support any number of zones, but I'm being lazy */ |
|
|
assert (malloc_num_zones <= 2); |
|
1071 |
|
|
1072 |
if (default_zone) |
gcl_zone->size = (void *) stub_size; |
1073 |
{ |
gcl_zone->malloc = (void *) stub_malloc; |
1074 |
malloc_zone_unregister (default_zone); |
gcl_zone->calloc = (void *) stub_calloc; |
1075 |
malloc_zone_unregister (gcl_zone); |
gcl_zone->valloc = (void *) stub_valloc; |
1076 |
|
gcl_zone->realloc = (void *) stub_realloc; |
1077 |
malloc_zone_register (gcl_zone); |
gcl_zone->free = (void *) stub_free; |
1078 |
malloc_zone_register (default_zone); |
|
1079 |
} |
/* Maybe we'll want to implement the zone introspector some day. */ |
1080 |
|
|
1081 |
malloc_set_zone_name (gcl_zone, "GNU Common Lisp"); |
malloc_num_zones_copy = malloc_num_zones; |
1082 |
|
s = malloc_num_zones * sizeof (malloc_zone_t *); |
1083 |
|
|
1084 |
|
if ((rtn = vm_allocate (mach_task_self (), (vm_address_t *) &malloc_zones_copy, s, 1)) != KERN_SUCCESS) { |
1085 |
|
mach_error ("init_darwin_zone_compat(): vm_allocate() failed", rtn); |
1086 |
|
exit (1); |
1087 |
|
} |
1088 |
|
|
1089 |
|
memcpy (malloc_zones_copy, malloc_zones, s); |
1090 |
|
|
1091 |
|
for (i=0 ; i < malloc_num_zones_copy ; i++) { |
1092 |
|
malloc_zone_unregister (malloc_zones_copy [i]); |
1093 |
|
} |
1094 |
|
|
1095 |
|
/* Make our zone the default zone. */ |
1096 |
|
malloc_zone_register (gcl_zone); |
1097 |
|
|
1098 |
|
for (i=0 ; i < malloc_num_zones_copy ; i++) { |
1099 |
|
if (malloc_zones_copy [i] != gcl_zone) |
1100 |
|
malloc_zone_register (malloc_zones_copy [i]); |
1101 |
|
} |
1102 |
|
|
1103 |
|
vm_deallocate (mach_task_self (), (vm_address_t) malloc_zones_copy, s); |
1104 |
|
|
1105 |
|
malloc_set_zone_name (gcl_zone, "GNU Common Lisp"); |
1106 |
} |
} |
1107 |
|
|
1108 |
|
/* Replacement for broken sbrk(2). */ |
1109 |
|
|
1110 |
char *my_sbrk (int incr) |
char *my_sbrk (int incr) |
1111 |
{ |
{ |
1112 |
char *temp, *ptr; |
char *temp, *ptr; |
1113 |
kern_return_t rtn; |
kern_return_t rtn; |
1114 |
|
|
1115 |
if (mach_brkpt == 0) { |
if (mach_brkpt == 0) { |
1116 |
if ((rtn = vm_allocate(mach_task_self(), (vm_address_t *) &mach_brkpt, big_heap, 1)) != KERN_SUCCESS) { |
if ((rtn = vm_allocate (mach_task_self (), (vm_address_t *) &mach_brkpt, big_heap, 1)) != KERN_SUCCESS) { |
1117 |
mach_error ("my_sbrk(): vm_allocate() failed", rtn); |
mach_error ("my_sbrk(): vm_allocate() failed", rtn); |
1118 |
return ((char *)-1); |
return ((char *)-1); |
1119 |
} |
} |
1120 |
if (!mach_brkpt) { |
if (!mach_brkpt) { |
1121 |
/* FIX-ME: this fprintf call will most probably fail because memory isn't initialized */ |
/* Call this instead of fprintf() because no allocation is performed. */ |
1122 |
fprintf (stderr, "my_sbrk(): cannot allocate heap\n"); |
malloc_printf ("my_sbrk(): cannot allocate heap\n"); |
1123 |
return ((char *)-1); |
return ((char *)-1); |
1124 |
} |
} |
1125 |
mark_region ((unsigned long) mach_brkpt, (unsigned long) big_heap); |
mark_region ((unsigned long) mach_brkpt, (unsigned long) big_heap); |
1136 |
mach_brkpt = ptr; |
mach_brkpt = ptr; |
1137 |
return (temp); |
return (temp); |
1138 |
} else { |
} else { |
1139 |
fprintf (stderr, "my_sbrk(): no more memory\n"); |
malloc_printf ("my_sbrk(): no more memory\n"); |
|
fflush (stderr); |
|
1140 |
return ((char *)-1); |
return ((char *)-1); |
1141 |
} |
} |
1142 |
} |
} |
1143 |
} |
} |
1144 |
|
|
1145 |
|
/* The file has non Mach-O stuff appended. We need to now where the Mach-O stuff ends. |
1146 |
|
Put this here, although it pertains to fasload()'ing, because we'll stop using sfaslmacosx.c. */ |
1147 |
|
|
1148 |
|
int seek_to_end_ofile (FILE *fp) |
1149 |
|
{ |
1150 |
|
struct mach_header mach_header; |
1151 |
|
char *hdrbuf; |
1152 |
|
struct load_command *load_command; |
1153 |
|
struct segment_command *segment_command; |
1154 |
|
struct section *section; |
1155 |
|
struct symtab_command *symtab_command; |
1156 |
|
struct symseg_command *symseg_command; |
1157 |
|
int len, cmd, seg; |
1158 |
|
int end_sec, end_ofile; |
1159 |
|
|
1160 |
|
end_ofile = 0; |
1161 |
|
fseek(fp, 0L, 0); |
1162 |
|
len = fread((char *)&mach_header, sizeof(struct mach_header), 1, fp); |
1163 |
|
if (len == 1 && mach_header.magic == MH_MAGIC) { |
1164 |
|
hdrbuf = (char *)malloc(mach_header.sizeofcmds); |
1165 |
|
len = fread(hdrbuf, mach_header.sizeofcmds, 1, fp); |
1166 |
|
if (len != 1) { |
1167 |
|
fprintf(stderr, "seek_to_end_ofile(): failure reading Mach-O load commands\n"); |
1168 |
|
return 0; |
1169 |
|
} |
1170 |
|
load_command = (struct load_command *) hdrbuf; |
1171 |
|
for (cmd = 0; cmd < mach_header.ncmds; ++cmd) { |
1172 |
|
switch (load_command->cmd) { |
1173 |
|
case LC_SEGMENT: |
1174 |
|
segment_command = (struct segment_command *) load_command; |
1175 |
|
section = (struct section *) ((char *)(segment_command + 1)); |
1176 |
|
for (seg = 0; seg < segment_command->nsects; ++seg, ++section) { |
1177 |
|
end_sec = section->offset + section->size; |
1178 |
|
if (end_sec > end_ofile) |
1179 |
|
end_ofile = end_sec; |
1180 |
|
} |
1181 |
|
break; |
1182 |
|
case LC_SYMTAB: |
1183 |
|
symtab_command = (struct symtab_command *) load_command; |
1184 |
|
end_sec = symtab_command->symoff + symtab_command->nsyms * sizeof(struct nlist); |
1185 |
|
if (end_sec > end_ofile) |
1186 |
|
end_ofile = end_sec; |
1187 |
|
end_sec = symtab_command->stroff + symtab_command->strsize; |
1188 |
|
if (end_sec > end_ofile) |
1189 |
|
end_ofile = end_sec; |
1190 |
|
break; |
1191 |
|
case LC_SYMSEG: |
1192 |
|
symseg_command = (struct symseg_command *) load_command; |
1193 |
|
end_sec = symseg_command->offset + symseg_command->size; |
1194 |
|
if (end_sec > end_ofile) |
1195 |
|
end_ofile = end_sec; |
1196 |
|
break; |
1197 |
|
} |
1198 |
|
load_command = (struct load_command *) |
1199 |
|
((char *)load_command + load_command->cmdsize); |
1200 |
|
} |
1201 |
|
free(hdrbuf); |
1202 |
|
fseek(fp, end_ofile, 0); |
1203 |
|
return 1; |
1204 |
|
} |
1205 |
|
return 0; |
1206 |
|
} |
1207 |
|
|
1208 |
#ifdef UNIXSAVE |
#ifdef UNIXSAVE |
1209 |
#include "save.c" |
#include "save.c" |
1210 |
#endif |
#endif |