Avoid unnecessary write to hash-table instances during gc.
[sbcl.git] / src / runtime / coreparse.c
blob4b29814d008e49d678b2a7f2c198109477768e5f
1 /*
2 * A saved SBCL system is a .core file; the code here helps us accept
3 * such a file as input.
4 */
6 /*
7 * This software is part of the SBCL system. See the README file for
8 * more information.
10 * This software is derived from the CMU CL system, which was
11 * written at Carnegie Mellon University and released into the
12 * public domain. The software is in the public domain and is
13 * provided with absolutely no warranty. See the COPYING and CREDITS
14 * files for more information.
17 #include "sbcl.h"
19 #ifndef LISP_FEATURE_WIN32
20 #ifdef LISP_FEATURE_LINUX
21 /* For madvise */
22 #define _BSD_SOURCE
23 #include <sys/mman.h>
24 #undef _BSD_SOURCE
25 #else
26 #include <sys/mman.h>
27 #endif
28 #endif
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/file.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <unistd.h>
39 #include "os.h"
40 #include "runtime.h"
41 #include "globals.h"
42 #include "core.h"
43 #include "arch.h"
44 #include "interr.h"
45 #include "thread.h"
47 #include "validate.h"
48 #include "gc-internal.h"
49 #include "runtime-options.h"
50 #include "pseudo-atomic.h"
52 #include <errno.h>
54 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
55 # include <zlib.h>
56 #endif
58 unsigned char build_id[] =
59 #include "../../output/build-id.inc"
62 int
63 open_binary(char *filename, int mode)
65 #ifdef LISP_FEATURE_WIN32
66 mode |= O_BINARY;
67 #endif
69 return open(filename, mode);
73 static struct runtime_options *
74 read_runtime_options(int fd)
76 os_vm_size_t optarray[RUNTIME_OPTIONS_WORDS];
77 struct runtime_options *options = NULL;
79 if (read(fd, optarray, RUNTIME_OPTIONS_WORDS * sizeof(os_vm_size_t)) !=
80 RUNTIME_OPTIONS_WORDS * sizeof(size_t)) {
81 return NULL;
84 if ((RUNTIME_OPTIONS_MAGIC != optarray[0]) || (0 == optarray[1])) {
85 return NULL;
88 options = successful_malloc(sizeof(struct runtime_options));
90 options->dynamic_space_size = optarray[2];
91 options->thread_control_stack_size = optarray[3];
93 return options;
96 void
97 maybe_initialize_runtime_options(int fd)
99 struct runtime_options *new_runtime_options;
100 off_t end_offset = sizeof(lispobj) +
101 sizeof(os_vm_offset_t) +
102 (RUNTIME_OPTIONS_WORDS * sizeof(size_t));
104 lseek(fd, -end_offset, SEEK_END);
106 if ((new_runtime_options = read_runtime_options(fd))) {
107 runtime_options = new_runtime_options;
111 /* Search 'filename' for an embedded core. An SBCL core has, at the
112 * end of the file, a trailer containing optional saved runtime
113 * options, the start of the core (an os_vm_offset_t), and a final
114 * signature word (the lispobj CORE_MAGIC). If this trailer is found
115 * at the end of the file, the start of the core can be determined
116 * from the core size.
118 * If an embedded core is present, this returns the offset into the
119 * file to load the core from, or -1 if no core is present. */
120 os_vm_offset_t
121 search_for_embedded_core(char *filename)
123 lispobj header;
124 os_vm_offset_t lispobj_size = sizeof(lispobj);
125 os_vm_offset_t trailer_size = lispobj_size + sizeof(os_vm_offset_t);
126 os_vm_offset_t core_start, pos;
127 int fd = -1;
129 if ((fd = open_binary(filename, O_RDONLY)) < 0)
130 goto lose;
132 if (read(fd, &header, (size_t)lispobj_size) < lispobj_size)
133 goto lose;
134 if (header == CORE_MAGIC) {
135 /* This file is a real core, not an embedded core. Return 0 to
136 * indicate where the core starts, and do not look for runtime
137 * options in this case. */
138 return 0;
141 if (lseek(fd, -lispobj_size, SEEK_END) < 0)
142 goto lose;
143 if (read(fd, &header, (size_t)lispobj_size) < lispobj_size)
144 goto lose;
146 if (header == CORE_MAGIC) {
147 if (lseek(fd, -trailer_size, SEEK_END) < 0)
148 goto lose;
149 if (read(fd, &core_start, sizeof(os_vm_offset_t)) < 0)
150 goto lose;
152 if (lseek(fd, core_start, SEEK_SET) < 0)
153 goto lose;
154 pos = lseek(fd, 0, SEEK_CUR);
156 if (read(fd, &header, (size_t)lispobj_size) < lispobj_size)
157 goto lose;
159 if (header != CORE_MAGIC)
160 goto lose;
162 maybe_initialize_runtime_options(fd);
164 close(fd);
165 return pos;
168 lose:
169 if (fd != -1)
170 close(fd);
172 return -1;
175 #ifndef LISP_FEATURE_HPUX
176 #define load_core_bytes(fd, where, addr, len) os_map(fd, where, addr, len)
177 #else
178 #define load_core_bytes(fd, where, addr, len) copy_core_bytes(fd, where, addr, len)
179 /* If more platforms don't support overlapping mmap rename this
180 * def to something like ifdef nommapoverlap */
181 /* currently hpux only */
182 static void copy_core_bytes(int fd, os_vm_offset_t offset,
183 os_vm_address_t addr, int len)
185 unsigned char buf[4096];
186 int c,x;
187 int old_fd = lseek(fd, 0, SEEK_CUR);
189 if(len & (4096-1)){
190 fprintf(stderr, "cant copy a slice of core because slice-length is not of page size(4096)\n");
191 exit(-1);
193 if(old_fd < 0){
194 fprintf(stderr, "cant perform lseek() on corefile\n");
196 lseek(fd, offset, SEEK_SET);
197 if(fd < 0){
198 fprintf(stderr, "cant perform lseek(%u,%lu,SEEK_SET) on corefile\n", fd, offset);
200 for(x = 0; x < len; x += 4096){
201 c = read(fd, buf, 4096);
202 if(c != 4096){
203 fprintf(stderr, "cant read memory area from corefile at position %lu, got %d\n", offset + x, c);
204 exit(-1);
206 memcpy(addr+x, buf, 4096);
208 os_flush_icache(addr, len);
210 #endif
212 #ifndef LISP_FEATURE_SB_CORE_COMPRESSION
213 # define inflate_core_bytes(fd,offset,addr,len) \
214 lose("This runtime was not built with zlib-compressed core support... aborting\n")
215 #else
216 # define ZLIB_BUFFER_SIZE (1u<<16)
217 static void inflate_core_bytes(int fd, os_vm_offset_t offset,
218 os_vm_address_t addr, int len)
220 z_stream stream;
221 unsigned char* buf = successful_malloc(ZLIB_BUFFER_SIZE);
222 int ret;
224 # ifdef LISP_FEATURE_WIN32
225 /* Ensure the memory is committed so zlib doesn't segfault trying to
226 inflate. */
227 os_validate_recommit(addr, len);
228 # endif
230 if (-1 == lseek(fd, offset, SEEK_SET)) {
231 lose("Unable to lseek() on corefile\n");
234 stream.zalloc = NULL;
235 stream.zfree = NULL;
236 stream.opaque = NULL;
237 stream.avail_in = 0;
238 stream.next_in = buf;
240 ret = inflateInit(&stream);
241 if (ret != Z_OK)
242 lose("zlib error %i\n", ret);
244 stream.next_out = (void*)addr;
245 stream.avail_out = len;
246 do {
247 ssize_t count = read(fd, buf, ZLIB_BUFFER_SIZE);
248 if (count < 0)
249 lose("unable to read core file (errno = %i)\n", errno);
250 stream.next_in = buf;
251 stream.avail_in = count;
252 if (count == 0) break;
253 ret = inflate(&stream, Z_NO_FLUSH);
254 switch (ret) {
255 case Z_STREAM_END:
256 break;
257 case Z_OK:
258 if (stream.avail_out == 0)
259 lose("Runaway gzipped core directory... aborting\n");
260 if (stream.avail_in > 0)
261 lose("zlib inflate returned without fully"
262 "using up input buffer... aborting\n");
263 break;
264 default:
265 lose("zlib inflate error: %i\n", ret);
266 break;
268 } while (ret != Z_STREAM_END);
270 if (stream.avail_out > 0) {
271 if (stream.avail_out >= os_vm_page_size)
272 fprintf(stderr, "Warning: gzipped core directory significantly"
273 "shorter than expected (%lu bytes)", (unsigned long)stream.avail_out);
274 /* Is this needed? */
275 memset(stream.next_out, 0, stream.avail_out);
278 inflateEnd(&stream);
279 free(buf);
281 # undef ZLIB_BUFFER_SIZE
282 #endif
284 struct heap_adjust {
285 /* range[0] is immobile space, range [1] is dynamic space */
286 struct range {
287 lispobj start, end;
288 sword_t delta;
289 } range[2];
292 #ifndef LISP_FEATURE_RELOCATABLE_HEAP
293 #define adjust_word(ignore,thing) thing
294 #define relocate_heap(ignore)
295 #else
296 #include "genesis/gc-tables.h"
297 #include "genesis/hash-table.h"
298 #include "genesis/layout.h"
299 #include "genesis/vector.h"
301 static inline sword_t calc_adjustment(struct heap_adjust* adj, lispobj x)
303 #ifdef LISP_FEATURE_IMMOBILE_SPACE
304 if (adj->range[0].start <= x && x < adj->range[0].end)
305 return adj->range[0].delta;
306 #endif
307 if (adj->range[1].start <= x && x < adj->range[1].end)
308 return adj->range[1].delta;
309 return 0;
312 // Return the adjusted value of 'word' without testing whether it looks
313 // like a pointer. But do test whether it points to a relocatable space.
314 static inline lispobj adjust_word(struct heap_adjust* adj, lispobj word) {
315 return word + calc_adjustment(adj, word);
318 // Adjust the words in range [where,where+n_words)
319 // skipping any words that have non-pointer nature.
320 static void adjust_pointers(lispobj *where, sword_t n_words, struct heap_adjust* adj)
322 long i;
323 for (i=0;i<n_words;++i) {
324 lispobj word = where[i];
325 sword_t adjustment;
326 if (is_lisp_pointer(word) && (adjustment = calc_adjustment(adj, word)) != 0) {
327 where[i] += adjustment;
332 #include "var-io.h"
333 static void __attribute__((unused))
334 adjust_code_refs(struct heap_adjust* adj, lispobj fixups, struct code* code)
336 struct varint_unpacker unpacker;
337 varint_unpacker_init(&unpacker, fixups);
338 char* instructions = (char*)((lispobj*)code + code_header_words(code->header));
339 int prev_loc = 0, loc;
340 while (varint_unpack(&unpacker, &loc) && loc != 0) {
341 // For extra compactness, each loc is relative to the prior,
342 // so that the magnitudes are smaller.
343 loc += prev_loc;
344 prev_loc = loc;
345 int* fixup_where = (int*)(instructions + loc);
346 lispobj ptr = (lispobj)(*fixup_where);
347 *fixup_where = (int)(ptr + calc_adjustment(adj, ptr));
351 #if defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER) && defined(LISP_FEATURE_64_BIT)
352 #define FIX_FUN_HEADER_LAYOUT(fun) \
353 set_function_layout(fun, adjust_word(adj, function_layout(fun)))
354 #else
355 #define FIX_FUN_HEADER_LAYOUT(f) {}
356 #endif
358 static void relocate_space(uword_t start, lispobj* end, struct heap_adjust* adj)
360 lispobj *where = (lispobj*)start;
361 lispobj header_word;
362 int widetag;
363 long nwords;
364 lispobj layout, adjusted_layout, bitmap;
365 struct code* code;
366 sword_t delta;
368 for ( ; where < end ; where += nwords ) {
369 header_word = *where;
370 if (is_cons_half(header_word)) {
371 adjust_pointers(where, 2, adj);
372 nwords = 2;
373 continue;
375 widetag = widetag_of(header_word);
376 nwords = sizetab[widetag](where);
377 switch (widetag) {
378 case FUNCALLABLE_INSTANCE_WIDETAG:
379 // Special note on the word at where[1] in funcallable instances:
380 // - If no immobile code, then the word points to read-only space,
381 /// hence needs no adjustment.
382 // - Otherwise, the word might point to a relocated range,
383 // either the instance itself, or a trampoline in immobile space.
384 where[1] = adjust_word(adj, where[1]);
385 case INSTANCE_WIDETAG:
386 layout = (widetag == FUNCALLABLE_INSTANCE_WIDETAG) ?
387 funinstance_layout(where) : instance_layout(where);
388 adjusted_layout = adjust_word(adj, layout);
389 // Do not alter the layout as stored in the instance if non-compact
390 // header. instance_scan() will do it if necessary.
391 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
392 if (adjusted_layout != layout)
393 instance_layout(where) = adjusted_layout;
394 #endif
395 bitmap = LAYOUT(adjusted_layout)->bitmap;
396 gc_assert(fixnump(bitmap)
397 || widetag_of(*native_pointer(bitmap))==BIGNUM_WIDETAG);
398 // If the post-adjustment address of 'layout' is higher than 'where',
399 // then the layout's pointer slots need adjusting.
400 // This is true regardless of whether the core was mapped at a higher
401 // or lower address than desired.
402 if (is_lisp_pointer(bitmap) && adjusted_layout > (lispobj)where) {
403 // Do not write back the adjusted bitmap pointer. Each heap word
404 // must be touched at most once. When the layout itself gets scanned,
405 // the bitmap slot will be rewritten if needed.
406 bitmap = adjust_word(adj, bitmap);
409 instance_scan((void(*)(lispobj*,sword_t,uword_t))adjust_pointers,
410 where+1, nwords-1, bitmap, (uintptr_t)adj);
411 continue;
412 case FDEFN_WIDETAG:
413 adjust_pointers(where+1, 2, adj);
414 // 'raw_addr' doesn't satisfy is_lisp_pointer() for x86,
415 // so adjust_pointers() would ignore it. Therefore we need to
416 // forcibly adjust it.
417 #ifndef LISP_FEATURE_IMMOBILE_CODE
418 where[3] = adjust_word(adj, where[3]);
419 #elif defined(LISP_FEATURE_X86_64)
420 // static space to immobile space JMP needs adjustment
421 if (STATIC_SPACE_START <= (uintptr_t)where && (uintptr_t)where < STATIC_SPACE_END) {
422 delta = calc_adjustment(adj, fdefn_callee_lispobj((struct fdefn*)where));
423 if (delta != 0)
424 *(int*)(1+(char*)(where+3)) += delta;
426 #endif
427 continue;
428 case CODE_HEADER_WIDETAG:
429 // Fixup the constant pool. The word at where+1 is a fixnum.
430 adjust_pointers(where+2, code_header_words(header_word)-2, adj);
431 // Fixup all embedded simple-funs
432 code = (struct code*)where;
433 for_each_simple_fun(i, f, code, 1, {
434 FIX_FUN_HEADER_LAYOUT((lispobj*)f);
435 f->self = adjust_word(adj, f->self);
436 adjust_pointers(SIMPLE_FUN_SCAV_START(f), SIMPLE_FUN_SCAV_NWORDS(f), adj);
438 // Compute the address where the code "was" as the first argument
439 // by negating the adjustment for 'where'.
440 // Can't call calc_adjustment to get the negative of the adjustment!
441 gencgc_apply_code_fixups((struct code*)((char*)where - adj->range[1].delta),
442 code);
443 #ifdef LISP_FEATURE_IMMOBILE_SPACE
444 // Now that the packed integer comprising the list of fixup locations
445 // has been fixed-up (if necessary), apply them to the code.
446 if (code->fixups != 0)
447 adjust_code_refs(adj, code->fixups, code);
448 #endif
449 continue;
450 case CLOSURE_WIDETAG:
451 FIX_FUN_HEADER_LAYOUT(where);
452 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
453 // For x86[-64], the closure fun appears to be a fixnum,
454 // and might need adjustment unless pointing to immobile code.
455 // Then fall into the general case; where[1] won't get re-adjusted
456 // because it doesn't satisfy is_lisp_pointer().
457 where[1] = adjust_word(adj, where[1]);
458 #endif
459 break;
460 // Vectors require extra care because of EQ-based hashing.
461 case SIMPLE_VECTOR_WIDETAG:
462 if (is_vector_subtype(*where, VectorValidHashing)) {
463 struct vector* v = (struct vector*)where;
464 gc_assert(v->length > 0 &&
465 !(v->length & make_fixnum(1)) && // length must be even
466 lowtag_of(v->data[0]) == INSTANCE_POINTER_LOWTAG);
467 lispobj* data = (lispobj*)v->data;
468 adjust_pointers(&data[0], 1, adj); // adjust the hash-table structure
469 boolean needs_rehash = 0;
470 int i;
471 // Adjust the elements, checking for need to rehash.
472 // v->data[1] is the unbound marker (a non-pointer)
473 for (i = fixnum_value(v->length)-1 ; i>=2 ; --i) {
474 lispobj ptr = data[i];
475 if (is_lisp_pointer(ptr) && (delta = calc_adjustment(adj, ptr)) != 0) {
476 data[i] += delta;
477 needs_rehash = 1;
480 if (needs_rehash)
481 data[1] = make_fixnum(1);
482 continue;
484 // All the array header widetags.
485 case SIMPLE_ARRAY_WIDETAG:
486 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
487 case COMPLEX_CHARACTER_STRING_WIDETAG:
488 #endif
489 case COMPLEX_BASE_STRING_WIDETAG:
490 case COMPLEX_VECTOR_NIL_WIDETAG:
491 case COMPLEX_BIT_VECTOR_WIDETAG:
492 case COMPLEX_VECTOR_WIDETAG:
493 case COMPLEX_ARRAY_WIDETAG:
494 // And the rest of the purely descriptor objects.
495 case SYMBOL_WIDETAG:
496 case VALUE_CELL_WIDETAG:
497 case WEAK_POINTER_WIDETAG:
498 case RATIO_WIDETAG:
499 case COMPLEX_WIDETAG:
500 break;
502 // Other
503 case SAP_WIDETAG:
504 if ((delta = calc_adjustment(adj, where[1])) != 0) {
505 fprintf(stderr,
506 "WARNING: SAP at %p -> %p in relocatable core\n",
507 where, (void*)where[1]);
508 where[1] += delta;
510 continue;
511 case BIGNUM_WIDETAG:
512 #ifndef LISP_FEATURE_64_BIT
513 case SINGLE_FLOAT_WIDETAG:
514 #endif
515 case DOUBLE_FLOAT_WIDETAG:
516 case COMPLEX_SINGLE_FLOAT_WIDETAG:
517 case COMPLEX_DOUBLE_FLOAT_WIDETAG:
518 #ifdef SIMD_PACK_WIDETAG
519 case SIMD_PACK_WIDETAG:
520 #endif
521 continue;
522 default:
523 if (other_immediate_lowtag_p(widetag)
524 && specialized_vector_widetag_p(widetag))
525 continue;
526 else
527 lose("Unrecognized heap object: @%p: %lx\n", where, header_word);
529 adjust_pointers(where+1, nwords-1, adj);
533 #define SHOW_SPACE_RELOCATION 0
534 void relocate_heap(struct heap_adjust* adj)
536 if (SHOW_SPACE_RELOCATION) {
537 #ifdef LISP_FEATURE_IMMOBILE_SPACE
538 fprintf(stderr, "Relocating immobile space from [%p:%p] to [%p:%p]\n",
539 (char*)adj->range[0].start,
540 (char*)adj->range[0].end,
541 (char*)IMMOBILE_SPACE_START,
542 (char*)IMMOBILE_SPACE_START+(adj->range[0].end-adj->range[0].start));
543 #endif
544 fprintf(stderr, "Relocating dynamic space from [%p:%p] to [%p:%p]\n",
545 (char*)adj->range[1].start,
546 (char*)adj->range[1].end,
547 (char*)DYNAMIC_SPACE_START,
548 (char*)DYNAMIC_SPACE_START+(adj->range[1].end-adj->range[1].start));
550 relocate_space(STATIC_SPACE_START, static_space_free_pointer, adj);
551 #ifdef LISP_FEATURE_IMMOBILE_SPACE
552 relocate_space(IMMOBILE_SPACE_START, immobile_fixedobj_free_pointer, adj);
553 relocate_space(IMMOBILE_VARYOBJ_SUBSPACE_START, immobile_space_free_pointer, adj);
554 SYMBOL(FUNCTION_LAYOUT)->value = \
555 adjust_word(adj, SYMBOL(FUNCTION_LAYOUT)->value >> 32) << 32;
556 #endif
557 relocate_space(DYNAMIC_SPACE_START, (lispobj*)get_alloc_pointer(), adj);
558 lispobj asmroutines = SYMBOL(ASSEMBLER_ROUTINES)->value;
559 if (lowtag_of(asmroutines) == INSTANCE_POINTER_LOWTAG) {
560 /* Adjust the values in SB-FASL::*ASSEMBLER-ROUTINES*.
561 * No need to frob the 'needs_rehash_p' slot on account of this */
562 struct hash_table *ht = (struct hash_table*)native_pointer(asmroutines);
563 struct vector *table = (struct vector*)native_pointer(ht->table);
564 int i;
565 for (i=fixnum_value(table->length)-1; i>=3; i -= 2) {
566 if (fixnump(table->data[i]))
567 table->data[i] = make_fixnum(adjust_word(adj, fixnum_value(table->data[i])));
571 #endif
573 int merge_core_pages = -1;
575 static void
576 process_directory(int count, struct ndir_entry *entry,
577 int fd, os_vm_offset_t file_offset,
578 struct heap_adjust* adj)
580 extern void immobile_space_coreparse(uword_t,uword_t);
582 struct {
583 uword_t len; // length in bytes, as an integral multiple of os_vm_page_size
584 uword_t base;
585 lispobj** pfree_pointer; // pointer to x_free_pointer
586 } spaces[MAX_CORE_SPACE_ID+1] = {
587 {0, 0, 0}, // blank for space ID 0
588 #ifdef LISP_FEATURE_GENCGC
589 {0, DYNAMIC_SPACE_START, 0},
590 #else
591 {0, 0, 0},
592 #endif
593 // This order is determined by constants in compiler/generic/genesis
594 {0, STATIC_SPACE_START, &static_space_free_pointer},
595 {0, READ_ONLY_SPACE_START, &read_only_space_free_pointer},
596 #ifdef LISP_FEATURE_IMMOBILE_SPACE
597 {0, IMMOBILE_SPACE_START, &immobile_fixedobj_free_pointer},
598 {0, IMMOBILE_VARYOBJ_SUBSPACE_START, &immobile_space_free_pointer}
599 #endif
602 for ( ; --count>= 0; ++entry) {
603 sword_t id = entry->identifier;
604 uword_t addr = (1024 * entry->address); // multiplier as per core.h
605 int compressed = id & DEFLATED_CORE_SPACE_ID_FLAG;
606 id -= compressed;
607 if (id < 1 || id > MAX_CORE_SPACE_ID)
608 lose("unknown space ID %ld addr %p\n", id, addr);
610 #ifndef LISP_FEATURE_RELOCATABLE_HEAP
611 int enforce_address = 1;
612 #elif defined(LISP_FEATURE_IMMOBILE_SPACE)
613 // Enforce address of readonly, static, immobile varyobj
614 int enforce_address = id != DYNAMIC_CORE_SPACE_ID
615 && id != IMMOBILE_FIXEDOBJ_CORE_SPACE_ID;
616 #else
617 // Enforce address of readonly and static spaces.
618 int enforce_address = id != DYNAMIC_CORE_SPACE_ID;
619 #endif
620 if (enforce_address) {
621 int fail;
622 #ifdef LISP_FEATURE_CHENEYGC
623 if (id == DYNAMIC_CORE_SPACE_ID) {
624 if ((fail = (addr != DYNAMIC_0_SPACE_START) &&
625 (addr != DYNAMIC_1_SPACE_START)) != 0)
626 fprintf(stderr, "in core: %p; in runtime: %p or %p\n",
627 (void*)addr,
628 (void*)DYNAMIC_0_SPACE_START,
629 (void*)DYNAMIC_1_SPACE_START);
630 } else
631 #endif
632 if ((fail = (addr != spaces[id].base)) != 0)
633 fprintf(stderr, "in core: %p; in runtime: %p\n",
634 (void*)addr, (void*)spaces[id].base);
635 char *names[] = {
636 "DYNAMIC", "STATIC", "READ_ONLY", "IMMOBILE", "IMMOBILE"
638 if (fail)
639 lose("core/runtime address mismatch: %s_SPACE_START", names[id-1]);
641 spaces[id].base = addr;
642 uword_t len = os_vm_page_size * entry->page_count;
643 spaces[id].len = len;
644 if (id == DYNAMIC_CORE_SPACE_ID && len > dynamic_space_size) {
645 lose("dynamic space too small for core: %luKiB required, %luKiB available.\n",
646 (unsigned long)len >> 10,
647 (unsigned long)dynamic_space_size >> 10);
649 if (len != 0) {
650 uword_t __attribute__((unused)) aligned_start;
651 #ifdef LISP_FEATURE_RELOCATABLE_HEAP
652 // Try to map at address requested by the core file.
653 if (id == DYNAMIC_CORE_SPACE_ID) {
654 addr = (uword_t)os_validate(MOVABLE, (os_vm_address_t)addr,
655 dynamic_space_size);
656 aligned_start = ALIGN_UP(addr, GENCGC_CARD_BYTES);
657 /* Misalignment can happen only if card size exceeds OS page.
658 * Drop one card to avoid overrunning the allocated space */
659 if (aligned_start > addr) // not card-aligned
660 dynamic_space_size -= GENCGC_CARD_BYTES;
661 DYNAMIC_SPACE_START = addr = aligned_start;
662 # ifndef LISP_FEATURE_IMMOBILE_SPACE
664 # else
665 if (DYNAMIC_SPACE_START < IMMOBILE_SPACE_START)
666 lose("Won't map dynamic space below immobile space");
667 /* Assume presence of linkage-table space for this platform.
668 * An unusable gap may exist between the linkage table and immobile space
669 * but it's not important whether it does or doesn't. So we don't bother
670 * unmapping the alleged gap */
671 } else if (id == IMMOBILE_FIXEDOBJ_CORE_SPACE_ID) {
672 addr = (uword_t)os_validate(MOVABLE_LOW, (os_vm_address_t)addr,
673 IMMOBILE_SPACE_SIZE);
674 IMMOBILE_SPACE_START = addr;
675 if (IMMOBILE_SPACE_START + IMMOBILE_SPACE_SIZE > 0x80000000)
676 lose("Won't map immobile space above 2GB");
677 // varyobj subspace must be enforced to reside at a known offset
678 // from fixedobj subspace.
679 spaces[IMMOBILE_VARYOBJ_CORE_SPACE_ID].base =
680 spaces[id].base + IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE;
681 IMMOBILE_VARYOBJ_SUBSPACE_START = addr + IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE;
682 } else if (id == IMMOBILE_VARYOBJ_CORE_SPACE_ID) {
683 /* Ignore what the core file said */
684 addr = IMMOBILE_VARYOBJ_SUBSPACE_START;
686 # endif
688 #endif /* LISP_FEATURE_RELOCATABLE_HEAP */
690 sword_t offset = os_vm_page_size * (1 + entry->data_page);
691 if (compressed)
692 inflate_core_bytes(fd, offset + file_offset, (os_vm_address_t)addr, len);
693 else
694 load_core_bytes(fd, offset + file_offset, (os_vm_address_t)addr, len);
697 #ifdef MADV_MERGEABLE
698 if ((merge_core_pages == 1)
699 || ((merge_core_pages == -1) && compressed)) {
700 madvise((void *)addr, len, MADV_MERGEABLE);
702 #endif
704 lispobj *free_pointer = (lispobj *) addr + entry->nwords;
705 switch (id) {
706 default:
707 *spaces[id].pfree_pointer = free_pointer;
708 break;
709 case DYNAMIC_CORE_SPACE_ID:
710 #ifdef LISP_FEATURE_CHENEYGC
711 /* 'addr' is the actual address if relocatable.
712 * For cheneygc, this will be whatever the GC was using
713 * at the time the core was saved.
714 * For gencgc this is #defined as DYNAMIC_SPACE_START */
715 current_dynamic_space = (lispobj *)addr;
716 #endif
717 set_alloc_pointer((lispobj)free_pointer);
719 anon_dynamic_space_start = (os_vm_address_t)(addr + len);
720 /* This assertion safeguards the test in zero_pages_with_mmap()
721 * which trusts that if addr > anon_dynamic_space_start
722 * then addr did not come from any file mapping. */
723 gc_assert((lispobj)anon_dynamic_space_start > STATIC_SPACE_END);
727 #ifdef LISP_FEATURE_RELOCATABLE_HEAP
728 #ifdef LISP_FEATURE_IMMOBILE_SPACE
729 if (IMMOBILE_SPACE_START != spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].base) {
730 adj->range[0].start = spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].base;
731 adj->range[0].end = adj->range[0].start + IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE
732 + spaces[IMMOBILE_VARYOBJ_CORE_SPACE_ID].len;
733 adj->range[0].delta = IMMOBILE_SPACE_START - adj->range[0].start;
735 #endif
736 if (DYNAMIC_SPACE_START != spaces[DYNAMIC_CORE_SPACE_ID].base) {
737 adj->range[1].start = spaces[DYNAMIC_CORE_SPACE_ID].base;
738 adj->range[1].end = adj->range[1].start + spaces[DYNAMIC_CORE_SPACE_ID].len;
739 adj->range[1].delta = DYNAMIC_SPACE_START - adj->range[1].start;
741 if (adj->range[0].delta | adj->range[1].delta)
742 relocate_heap(adj);
743 #endif
745 #ifdef LISP_FEATURE_IMMOBILE_SPACE
746 /* Now determine page characteristics (such as object spacing)
747 * after relocation, because we need to know which objects are layouts
748 * based on knowing layout-of-layout. The test for that is dependent
749 * on what it's address should be, not what it was in the file */
750 immobile_space_coreparse(spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].len,
751 spaces[IMMOBILE_VARYOBJ_CORE_SPACE_ID].len);
752 #endif
753 #ifdef LISP_FEATURE_X86_64
754 tune_asm_routines_for_microarch(); // before WPing immobile space
755 #endif
758 lispobj
759 load_core_file(char *file, os_vm_offset_t file_offset)
761 void *header;
762 core_entry_elt_t val, *ptr;
763 os_vm_size_t len, remaining_len;
764 int fd = open_binary(file, O_RDONLY);
765 ssize_t count;
766 lispobj initial_function = NIL;
767 struct heap_adjust adj;
768 memset(&adj, 0, sizeof adj);
770 FSHOW((stderr, "/entering load_core_file(%s)\n", file));
771 if (fd < 0) {
772 fprintf(stderr, "could not open file \"%s\"\n", file);
773 perror("open");
774 exit(1);
777 lseek(fd, file_offset, SEEK_SET);
778 header = calloc(os_vm_page_size, 1);
780 count = read(fd, header, os_vm_page_size);
781 if (count < (ssize_t) os_vm_page_size) {
782 lose("premature end of core file\n");
784 SHOW("successfully read first page of core");
786 ptr = header;
787 val = *ptr++;
789 if (val != CORE_MAGIC) {
790 lose("invalid magic number in core: 0x%lx should have been 0x%x.\n",
791 val,
792 CORE_MAGIC);
794 SHOW("found CORE_MAGIC");
796 #define WORD_FMTX OS_VM_SIZE_FMTX
797 for ( ; val != END_CORE_ENTRY_TYPE_CODE ; ptr += remaining_len) {
798 val = *ptr++;
799 len = *ptr++;
800 remaining_len = len - 2; /* (-2 to cancel the two ++ operations) */
801 FSHOW((stderr, "/val=0x%"WORD_FMTX", remaining_len=0x%"WORD_FMTX"\n",
802 val, remaining_len));
804 switch (val) {
806 case END_CORE_ENTRY_TYPE_CODE:
807 SHOW("END_CORE_ENTRY_TYPE_CODE case");
808 break;
810 case BUILD_ID_CORE_ENTRY_TYPE_CODE:
811 SHOW("BUILD_ID_CORE_ENTRY_TYPE_CODE case");
813 os_vm_size_t stringlen = *ptr++;
814 --remaining_len;
815 gc_assert(remaining_len * sizeof (core_entry_elt_t) >= stringlen);
816 if (sizeof build_id == stringlen+1 && !memcmp(ptr, build_id, stringlen))
817 break;
818 /* .core files are not binary-compatible between
819 * builds because we can't easily detect whether the
820 * sources were patched between the time the
821 * dumping-the-.core runtime was built and the time
822 * that the loading-the-.core runtime was built.
824 * (We could easily detect whether version.lisp-expr
825 * was changed, but people experimenting with patches
826 * don't necessarily update version.lisp-expr.) */
827 fprintf(stderr,
828 "core was built for runtime \"%.*s\" but this is \"%s\"\n",
829 (int)stringlen, (char*)ptr, build_id);
830 lose("can't load .core for different runtime, sorry\n");
833 case NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE:
834 SHOW("NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE case");
835 process_directory(remaining_len / NDIR_ENTRY_LENGTH,
836 (struct ndir_entry*)ptr, fd, file_offset,
837 &adj);
838 break;
840 case INITIAL_FUN_CORE_ENTRY_TYPE_CODE:
841 SHOW("INITIAL_FUN_CORE_ENTRY_TYPE_CODE case");
842 initial_function = adjust_word(&adj, (lispobj)*ptr);
843 break;
845 #ifdef LISP_FEATURE_GENCGC
846 case PAGE_TABLE_CORE_ENTRY_TYPE_CODE:
848 extern void gc_allocate_ptes();
849 extern boolean gc_load_corefile_ptes(char data[], ssize_t,
850 page_index_t, page_index_t*);
851 // Allocation of PTEs is delayed 'til now so that calloc() doesn't
852 // consume addresses that would have been taken by a mapped space.
853 gc_allocate_ptes();
854 os_vm_size_t remaining = *ptr;
855 os_vm_size_t fdoffset = (*(ptr+1) + 1) * (os_vm_page_size);
856 page_index_t page = 0, npages;
857 ssize_t bytes_read;
858 char data[8192];
859 // A corefile_pte is 10 bytes for x86-64
860 // Process an integral number of ptes on each read.
861 os_vm_size_t chunksize = sizeof (struct corefile_pte)
862 * (sizeof data / sizeof (struct corefile_pte));
863 lseek(fd, fdoffset + file_offset, SEEK_SET);
864 bytes_read = read(fd, &npages, sizeof npages);
865 gc_assert(bytes_read == sizeof npages);
866 remaining -= sizeof npages;
867 while ((bytes_read = read(fd, data,
868 remaining < chunksize ? remaining : chunksize)) > 0
869 && gc_load_corefile_ptes(data, bytes_read, npages, &page))
870 remaining -= bytes_read;
872 gencgc_partial_pickup = 1;
873 break;
875 #endif
876 default:
877 lose("unknown core file entry: 0x%"WORD_FMTX"\n", val);
880 SHOW("about to free(header)");
881 free(header);
882 close(fd);
883 SHOW("returning from load_core_file(..)");
884 return initial_function;
887 #include "genesis/hash-table.h"
888 #include "genesis/vector.h"
889 os_vm_address_t get_asm_routine_by_name(const char* name)
891 lispobj routines = SYMBOL(ASSEMBLER_ROUTINES)->value;
892 if (lowtag_of(routines) == INSTANCE_POINTER_LOWTAG) {
893 struct hash_table* ht = (struct hash_table*)native_pointer(routines);
894 struct vector* table = VECTOR(ht->table);
895 lispobj sym;
896 int i;
897 for (i=2 ; i < fixnum_value(table->length) ; i += 2) {
898 sym = table->data[i];
899 if (lowtag_of(sym) == OTHER_POINTER_LOWTAG
900 && widetag_of(SYMBOL(sym)->header) == SYMBOL_WIDETAG
901 && !strcmp(name, (char*)(VECTOR(SYMBOL(sym)->name)->data)))
902 return (os_vm_address_t)fixnum_value(table->data[i+1]);
904 // Something is wrong if we have a hashtable but find nothing.
905 fprintf(stderr, "WARNING: get_asm_routine_by_name(%s) failed\n",
906 name);
908 return NULL;
911 void asm_routine_poke(const char* routine, int offset, char byte)
913 char *address = (char *)get_asm_routine_by_name(routine);
914 if (address)
915 address[offset] = byte;