160 |
|
|
161 |
int in_dumped_exec = 0; |
int in_dumped_exec = 0; |
162 |
|
|
163 |
malloc_zone_t *emacs_zone = 0L; |
malloc_zone_t *gcl_zone = 0L; |
164 |
|
|
165 |
unsigned num_marked_regions; |
unsigned num_marked_regions; |
166 |
|
|
168 |
#include <mach-o/nlist.h> |
#include <mach-o/nlist.h> |
169 |
|
|
170 |
#ifndef BIG_HEAP_SIZE |
#ifndef BIG_HEAP_SIZE |
171 |
#define BIG_HEAP_SIZE 0x5000000 |
#define BIG_HEAP_SIZE 0x50000000 |
172 |
#endif |
#endif |
173 |
|
|
174 |
int big_heap = BIG_HEAP_SIZE; |
int big_heap = BIG_HEAP_SIZE; |
297 |
{ |
{ |
298 |
zone = malloc_zone_from_ptr ((void *) address); |
zone = malloc_zone_from_ptr ((void *) address); |
299 |
|
|
300 |
print_region (address, size, info.protection, info.max_protection, zone ? zone->zone_name : "n/a"); |
print_region (address, size, info.protection, info.max_protection, zone ? zone->zone_name : "(no zone)"); |
301 |
|
|
302 |
if (object_name != MACH_PORT_NULL) |
if (object_name != MACH_PORT_NULL) |
303 |
mach_port_deallocate (target_task, object_name); |
mach_port_deallocate (target_task, object_name); |
339 |
break; |
break; |
340 |
|
|
341 |
zone = malloc_zone_from_ptr ((void *) address); |
zone = malloc_zone_from_ptr ((void *) address); |
342 |
zone_name = zone ? (zone->zone_name ? zone->zone_name : "n/a") : "n/a"; |
zone_name = zone ? (zone->zone_name ? zone->zone_name : "(no zone name)") : "(no zone)"; |
343 |
|
|
344 |
#if VERBOSE |
#if VERBOSE |
345 |
print_region (address, size, info.protection, info.max_protection, zone_name); |
print_region (address, size, info.protection, info.max_protection, zone_name); |
424 |
} |
} |
425 |
|
|
426 |
void |
void |
427 |
find_emacs_zone_regions () |
find_gcl_zone_regions () |
428 |
{ |
{ |
429 |
num_unexec_regions = 0; |
num_unexec_regions = 0; |
430 |
|
|
431 |
emacs_zone->introspect->enumerator (mach_task_self(), 0, |
gcl_zone->introspect->enumerator (mach_task_self(), 0, |
432 |
MALLOC_PTR_REGION_RANGE_TYPE |
MALLOC_PTR_REGION_RANGE_TYPE |
433 |
| MALLOC_ADMIN_REGION_RANGE_TYPE, |
| MALLOC_ADMIN_REGION_RANGE_TYPE, |
434 |
(vm_address_t) emacs_zone, |
(vm_address_t) gcl_zone, |
435 |
unexec_reader, |
unexec_reader, |
436 |
unexec_regions_recorder); |
unexec_regions_recorder); |
437 |
} |
} |
724 |
sc.vmsize = unexec_regions[j].size; |
sc.vmsize = unexec_regions[j].size; |
725 |
sc.fileoff = file_offset; |
sc.fileoff = file_offset; |
726 |
sc.filesize = unexec_regions[j].size; |
sc.filesize = unexec_regions[j].size; |
727 |
sc.maxprot = VM_PROT_READ | VM_PROT_WRITE; |
/* the heap will contain executable code, so promote maxprot to allow execution */ |
728 |
sc.initprot = VM_PROT_READ | VM_PROT_WRITE; |
sc.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; |
729 |
|
sc.initprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; |
730 |
sc.nsects = 1; |
sc.nsects = 1; |
731 |
sc.flags = 0; |
sc.flags = 0; |
732 |
|
|
743 |
strncpy (section.sectname,SECT_DATA,sizeof(section.sectname)); |
strncpy (section.sectname,SECT_DATA,sizeof(section.sectname)); |
744 |
strncpy (section.segname,SEG_DATA,sizeof(section.segname)); |
strncpy (section.segname,SEG_DATA,sizeof(section.segname)); |
745 |
section.addr = unexec_regions[j].address; |
section.addr = unexec_regions[j].address; |
746 |
section.size = sc.filesize /* unexec_regions[j].size */; |
section.size = sc.filesize; |
747 |
section.offset = file_offset; |
section.offset = file_offset; |
748 |
section.align = 4; |
section.align = 4; |
749 |
section.reloff = 0; |
section.reloff = 0; |
912 |
|
|
913 |
vm_range_t marked_regions[MAX_MARKED_REGIONS]; |
vm_range_t marked_regions[MAX_MARKED_REGIONS]; |
914 |
|
|
915 |
void mark_region (unsigned long address, unsigned long size) |
void |
916 |
|
mark_region (unsigned long address, unsigned long size) |
917 |
{ |
{ |
918 |
if (num_marked_regions < MAX_MARKED_REGIONS) |
if (num_marked_regions < MAX_MARKED_REGIONS) |
919 |
{ |
{ |
927 |
} |
} |
928 |
} |
} |
929 |
|
|
930 |
void add_marked_regions () |
static void |
931 |
|
add_marked_regions () |
932 |
{ |
{ |
933 |
unsigned n; |
unsigned n; |
934 |
|
|
947 |
void |
void |
948 |
unexec (char *outfile, char *infile, void *start_data, void *start_bss, |
unexec (char *outfile, char *infile, void *start_data, void *start_bss, |
949 |
void *entry_address) |
void *entry_address) |
950 |
{ |
{ |
951 |
|
/*extern malloc_zone_t *debug_zone __attribute__((weak_import));*/ |
952 |
|
|
953 |
infd = open (infile, O_RDONLY, 0); |
infd = open (infile, O_RDONLY, 0); |
954 |
if (infd < 0) |
if (infd < 0) |
955 |
{ |
{ |
975 |
build_region_list (); |
build_region_list (); |
976 |
read_load_commands (); |
read_load_commands (); |
977 |
|
|
978 |
/*find_emacs_zone_regions ();*/ |
/*find_gcl_zone_regions ();*/ |
979 |
add_marked_regions (); |
add_marked_regions (); |
980 |
|
|
981 |
|
/* |
982 |
|
if (debug_zone != NULL) |
983 |
|
debug_zone->introspect->enumerator (mach_task_self(), 0, |
984 |
|
MALLOC_PTR_REGION_RANGE_TYPE |
985 |
|
| MALLOC_ADMIN_REGION_RANGE_TYPE, |
986 |
|
(vm_address_t) debug_zone, |
987 |
|
unexec_reader, |
988 |
|
unexec_regions_recorder); |
989 |
|
*/ |
990 |
|
|
991 |
in_dumped_exec = 1; |
in_dumped_exec = 1; |
992 |
|
|
993 |
dump_it (); |
dump_it (); |
995 |
close (outfd); |
close (outfd); |
996 |
} |
} |
997 |
|
|
|
void |
|
|
unexec_init_emacs_zone () |
|
|
{ |
|
|
if (!emacs_zone) { |
|
|
emacs_zone = malloc_create_zone (0, 0); |
|
|
malloc_set_zone_name (emacs_zone, "EmacsZone"); |
|
|
} |
|
|
else { |
|
|
if (!malloc_zone_check (emacs_zone)) |
|
|
unexec_error ("emacs_zone is smashed\n"); |
|
|
malloc_zone_register (emacs_zone); |
|
|
} |
|
|
} |
|
|
|
|
998 |
static size_t stub_size (malloc_zone_t *zone, const void *ptr) |
static size_t stub_size (malloc_zone_t *zone, const void *ptr) |
999 |
{ |
{ |
|
object *p; |
|
1000 |
extern object malloc_list; |
extern object malloc_list; |
1001 |
|
object *p; |
1002 |
|
|
1003 |
for (p = &malloc_list ; *p && !endp(*p) ; p = &((*p)->c.c_cdr)) { |
for (p = &malloc_list ; *p && !endp(*p) ; p = &((*p)->c.c_cdr)) { |
1004 |
if ((*p)->c.c_car->st.st_self == ptr) { |
if ((*p)->c.c_car->st.st_self == ptr) { |
1045 |
|
|
1046 |
default_zone = malloc_default_zone (); |
default_zone = malloc_default_zone (); |
1047 |
|
|
1048 |
emacs_zone = malloc_create_zone (0,0); |
gcl_zone = malloc_create_zone (0,0); |
1049 |
|
|
1050 |
emacs_zone->size = (void *) stub_size; |
gcl_zone->size = (void *) stub_size; |
1051 |
emacs_zone->malloc = (void *) stub_malloc; |
gcl_zone->malloc = (void *) stub_malloc; |
1052 |
emacs_zone->calloc = (void *) stub_calloc; |
gcl_zone->calloc = (void *) stub_calloc; |
1053 |
emacs_zone->valloc = (void *) stub_valloc; |
gcl_zone->valloc = (void *) stub_valloc; |
1054 |
emacs_zone->realloc = (void *) stub_realloc; |
gcl_zone->realloc = (void *) stub_realloc; |
1055 |
emacs_zone->free = (void *) stub_free; |
gcl_zone->free = (void *) stub_free; |
1056 |
/* if the zone introspector is ever called, the program will crash */ |
/* if the zone introspector is ever called, the program will crash */ |
1057 |
|
|
1058 |
/* we could support any number of zones, but I'm being lazy */ |
/* we could support any number of zones, but I'm being lazy */ |
1061 |
if (default_zone) |
if (default_zone) |
1062 |
{ |
{ |
1063 |
malloc_zone_unregister (default_zone); |
malloc_zone_unregister (default_zone); |
1064 |
malloc_zone_unregister (emacs_zone); |
malloc_zone_unregister (gcl_zone); |
1065 |
|
|
1066 |
malloc_zone_register (emacs_zone); |
malloc_zone_register (gcl_zone); |
1067 |
malloc_zone_register (default_zone); |
malloc_zone_register (default_zone); |
1068 |
} |
} |
|
} |
|
|
|
|
|
void term_darwin_zone_compat () |
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
static void dump_regionXXX (vm_address_t start, vm_size_t size) |
|
|
{ |
|
|
task_t target_task = mach_task_self (); |
|
|
kern_return_t rtn; |
|
|
struct vm_region_basic_info info; |
|
|
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; |
|
|
mach_port_t object_name; |
|
|
vm_prot_t prot, maxprot; |
|
|
|
|
|
fprintf (stderr, "introspecting between %x and %x\n", start, start+size); |
|
|
|
|
|
fflush (stderr); |
|
|
|
|
|
rtn = vm_region (target_task, &start, &size, VM_REGION_BASIC_INFO, |
|
|
(vm_region_info_t) &info, &info_count, &object_name); |
|
|
|
|
|
if (rtn != KERN_SUCCESS || info_count != VM_REGION_BASIC_INFO_COUNT) { |
|
|
mach_error ("[dump_regionXXX] vm_region() failed: ", rtn); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (object_name != MACH_PORT_NULL) |
|
|
mach_port_deallocate (target_task, object_name); |
|
|
|
|
|
prot = info.protection; |
|
|
maxprot = info.max_protection; |
|
1069 |
|
|
1070 |
fprintf (stderr, "region_start=%x region_size=%x region_end=%x prot=%c%c%c maxprot=%c%c%c\n", |
malloc_set_zone_name (gcl_zone, "GNU Common Lisp"); |
|
start, size, start+size, prot & VM_PROT_READ ? 'r' : '-', prot & VM_PROT_WRITE ? 'w' : '-', |
|
|
prot & VM_PROT_EXECUTE ? 'x' : '-', maxprot & VM_PROT_READ ? 'r' : '-', |
|
|
maxprot & VM_PROT_WRITE ? 'w' : '-', maxprot & VM_PROT_EXECUTE ? 'x' : '-'); |
|
|
|
|
|
fflush (stderr); |
|
1071 |
} |
} |
1072 |
|
|
1073 |
char *my_sbrk (int incr) |
char *my_sbrk (int incr) |
1106 |
} |
} |
1107 |
} |
} |
1108 |
|
|
|
void prot_debug () { |
|
|
if (mach_brkpt >= mach_mapstart+0x2000) { |
|
|
dump_regionXXX ((vm_address_t) (mach_mapstart+0x1000),(vm_size_t) 0x1000); |
|
|
} |
|
|
else { |
|
|
printf ("mach_brkpt < mach_mapstart+0x2000\n"); fflush (stdout); |
|
|
} |
|
|
} |
|
|
|
|
1109 |
#ifdef UNIXSAVE |
#ifdef UNIXSAVE |
1110 |
#include "save.c" |
#include "save.c" |
1111 |
#endif |
#endif |