Fix build for #-relocatable-heap and fix printf format
[sbcl.git] / src / runtime / coreparse.c
blob650f50b06354342b102fd6e31c6685bbe0023165
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 adjust_code_refs(struct heap_adjust* adj, lispobj fixups, struct code* code)
335 struct varint_unpacker unpacker;
336 varint_unpacker_init(&unpacker, fixups);
337 char* instructions = (char*)((lispobj*)code + code_header_words(code->header));
338 int prev_loc = 0, loc;
339 while (varint_unpack(&unpacker, &loc) && loc != 0) {
340 // For extra compactness, each loc is relative to the prior,
341 // so that the magnitudes are smaller.
342 loc += prev_loc;
343 prev_loc = loc;
344 int* fixup_where = (int*)(instructions + loc);
345 lispobj ptr = (lispobj)(*fixup_where);
346 *fixup_where = (int)(ptr + calc_adjustment(adj, ptr));
350 #if defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER) && defined(LISP_FEATURE_64_BIT)
351 #define FIX_FUN_HEADER_LAYOUT(fun) \
352 set_function_layout(fun, adjust_word(adj, function_layout(fun)))
353 #else
354 #define FIX_FUN_HEADER_LAYOUT(f) {}
355 #endif
357 static void relocate_space(uword_t start, lispobj* end, struct heap_adjust* adj)
359 lispobj *where = (lispobj*)start;
360 lispobj header_word;
361 int widetag;
362 long nwords;
363 lispobj layout, adjusted_layout, bitmap;
364 struct code* code;
365 sword_t delta;
367 for ( ; where < end ; where += nwords ) {
368 header_word = *where;
369 if (is_cons_half(header_word)) {
370 adjust_pointers(where, 2, adj);
371 nwords = 2;
372 continue;
374 widetag = widetag_of(header_word);
375 nwords = sizetab[widetag](where);
376 switch (widetag) {
377 case FUNCALLABLE_INSTANCE_WIDETAG:
378 // Special note on the word at where[1] in funcallable instances:
379 // - If no immobile code, then the word points to read-only space,
380 /// hence needs no adjustment.
381 // - Otherwise, the word might point to a relocated range,
382 // either the instance itself, or a trampoline in immobile space.
383 where[1] = adjust_word(adj, where[1]);
384 case INSTANCE_WIDETAG:
385 layout = (widetag == FUNCALLABLE_INSTANCE_WIDETAG) ?
386 funinstance_layout(where) : instance_layout(where);
387 adjusted_layout = adjust_word(adj, layout);
388 // Do not alter the layout as stored in the instance if non-compact
389 // header. instance_scan() will do it if necessary.
390 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
391 if (adjusted_layout != layout)
392 instance_layout(where) = adjusted_layout;
393 #endif
394 bitmap = LAYOUT(adjusted_layout)->bitmap;
395 gc_assert(fixnump(bitmap)
396 || widetag_of(*native_pointer(bitmap))==BIGNUM_WIDETAG);
397 // If the post-adjustment address of 'layout' is higher than 'where',
398 // then the layout's pointer slots need adjusting.
399 // This is true regardless of whether the core was mapped at a higher
400 // or lower address than desired.
401 if (is_lisp_pointer(bitmap) && adjusted_layout > (lispobj)where) {
402 // Do not write back the adjusted bitmap pointer. Each heap word
403 // must be touched at most once. When the layout itself gets scanned,
404 // the bitmap slot will be rewritten if needed.
405 bitmap = adjust_word(adj, bitmap);
408 instance_scan((void(*)(lispobj*,sword_t,uword_t))adjust_pointers,
409 where+1, nwords-1, bitmap, (uintptr_t)adj);
410 continue;
411 case FDEFN_WIDETAG:
412 adjust_pointers(where+1, 2, adj);
413 // 'raw_addr' doesn't satisfy is_lisp_pointer() for x86,
414 // so adjust_pointers() would ignore it. Therefore we need to
415 // forcibly adjust it.
416 #ifndef LISP_FEATURE_IMMOBILE_CODE
417 where[3] = adjust_word(adj, where[3]);
418 #elif defined(LISP_FEATURE_X86_64)
419 // static space to immobile space JMP needs adjustment
420 if (STATIC_SPACE_START <= (uintptr_t)where && (uintptr_t)where < STATIC_SPACE_END) {
421 delta = calc_adjustment(adj, fdefn_callee_lispobj((struct fdefn*)where));
422 if (delta != 0)
423 *(int*)(1+(char*)(where+3)) += delta;
425 #endif
426 continue;
427 case CODE_HEADER_WIDETAG:
428 // Fixup the constant pool. The word at where+1 is a fixnum.
429 adjust_pointers(where+2, code_header_words(header_word)-2, adj);
430 // Fixup all embedded simple-funs
431 code = (struct code*)where;
432 for_each_simple_fun(i, f, code, 1, {
433 FIX_FUN_HEADER_LAYOUT((lispobj*)f);
434 f->self = adjust_word(adj, f->self);
435 adjust_pointers(SIMPLE_FUN_SCAV_START(f), SIMPLE_FUN_SCAV_NWORDS(f), adj);
437 // Compute the address where the code "was" as the first argument
438 // by negating the adjustment for 'where'.
439 // Can't call calc_adjustment to get the negative of the adjustment!
440 gencgc_apply_code_fixups((struct code*)((char*)where - adj->range[1].delta),
441 code);
442 #ifdef LISP_FEATURE_IMMOBILE_SPACE
443 // Now that the packed integer comprising the list of fixup locations
444 // has been fixed-up (if necessary), apply them to the code.
445 if (code->fixups != 0)
446 adjust_code_refs(adj, code->fixups, code);
447 #endif
448 continue;
449 case CLOSURE_WIDETAG:
450 FIX_FUN_HEADER_LAYOUT(where);
451 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
452 // For x86[-64], the closure fun appears to be a fixnum,
453 // and might need adjustment unless pointing to immobile code.
454 // Then fall into the general case; where[1] won't get re-adjusted
455 // because it doesn't satisfy is_lisp_pointer().
456 where[1] = adjust_word(adj, where[1]);
457 #endif
458 break;
459 // Vectors require extra care because of EQ-based hashing.
460 case SIMPLE_VECTOR_WIDETAG:
461 if ((HeaderValue(*where) & 0xFF) == subtype_VectorValidHashing) {
462 struct vector* v = (struct vector*)where;
463 gc_assert(v->length > 0 &&
464 !(fixnum_value(v->length) & 1) && // length must be even
465 lowtag_of(v->data[0]) == INSTANCE_POINTER_LOWTAG);
466 lispobj* data = (lispobj*)v->data;
467 adjust_pointers(&data[0], 1, adj); // adjust the hash-table structure
468 boolean needs_rehash = 0;
469 int i;
470 // Adjust the elements, checking for need to rehash.
471 // v->data[1] is the unbound marker (a non-pointer)
472 for (i = fixnum_value(v->length)-1 ; i>=2 ; --i) {
473 lispobj ptr = data[i];
474 if (is_lisp_pointer(ptr) && (delta = calc_adjustment(adj, ptr)) != 0) {
475 data[i] += delta;
476 needs_rehash = 1;
479 if (needs_rehash) {
480 struct hash_table *ht = (struct hash_table*)native_pointer(v->data[0]);
481 ht->needs_rehash_p = T;
483 continue;
485 // All the array header widetags.
486 case SIMPLE_ARRAY_WIDETAG:
487 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
488 case COMPLEX_CHARACTER_STRING_WIDETAG:
489 #endif
490 case COMPLEX_BASE_STRING_WIDETAG:
491 case COMPLEX_VECTOR_NIL_WIDETAG:
492 case COMPLEX_BIT_VECTOR_WIDETAG:
493 case COMPLEX_VECTOR_WIDETAG:
494 case COMPLEX_ARRAY_WIDETAG:
495 // And the rest of the purely descriptor objects.
496 case SYMBOL_WIDETAG:
497 case VALUE_CELL_WIDETAG:
498 case WEAK_POINTER_WIDETAG:
499 case RATIO_WIDETAG:
500 case COMPLEX_WIDETAG:
501 break;
503 // Other
504 case SAP_WIDETAG:
505 if ((delta = calc_adjustment(adj, where[1])) != 0) {
506 fprintf(stderr,
507 "WARNING: SAP at %p -> %p in relocatable core\n",
508 where, (void*)where[1]);
509 where[1] += delta;
511 continue;
512 case BIGNUM_WIDETAG:
513 #ifndef LISP_FEATURE_64_BIT
514 case SINGLE_FLOAT_WIDETAG:
515 #endif
516 case DOUBLE_FLOAT_WIDETAG:
517 case COMPLEX_SINGLE_FLOAT_WIDETAG:
518 case COMPLEX_DOUBLE_FLOAT_WIDETAG:
519 #ifdef SIMD_PACK_WIDETAG
520 case SIMD_PACK_WIDETAG:
521 #endif
522 continue;
523 default:
524 if (other_immediate_lowtag_p(widetag)
525 && specialized_vector_widetag_p(widetag))
526 continue;
527 else
528 lose("Unrecognized heap object: @%p: %lx\n", where, header_word);
530 adjust_pointers(where+1, nwords-1, adj);
534 #define SHOW_SPACE_RELOCATION 0
535 void relocate_heap(struct heap_adjust* adj)
537 if (SHOW_SPACE_RELOCATION) {
538 #ifdef LISP_FEATURE_IMMOBILE_SPACE
539 fprintf(stderr, "Relocating immobile space from [%p:%p] to [%p:%p]\n",
540 (char*)adj->range[0].start,
541 (char*)adj->range[0].end,
542 (char*)IMMOBILE_SPACE_START,
543 (char*)IMMOBILE_SPACE_START+(adj->range[0].end-adj->range[0].start));
544 #endif
545 fprintf(stderr, "Relocating dynamic space from [%p:%p] to [%p:%p]\n",
546 (char*)adj->range[1].start,
547 (char*)adj->range[1].end,
548 (char*)DYNAMIC_SPACE_START,
549 (char*)DYNAMIC_SPACE_START+(adj->range[1].end-adj->range[1].start));
551 relocate_space(STATIC_SPACE_START, static_space_free_pointer, adj);
552 #ifdef LISP_FEATURE_IMMOBILE_SPACE
553 relocate_space(IMMOBILE_SPACE_START, immobile_fixedobj_free_pointer, adj);
554 relocate_space(IMMOBILE_VARYOBJ_SUBSPACE_START, immobile_space_free_pointer, adj);
555 SYMBOL(FUNCTION_LAYOUT)->value = \
556 adjust_word(adj, SYMBOL(FUNCTION_LAYOUT)->value >> 32) << 32;
557 #endif
558 relocate_space(DYNAMIC_SPACE_START, dynamic_space_free_pointer, adj);
559 lispobj asmroutines = SYMBOL(ASSEMBLER_ROUTINES)->value;
560 if (lowtag_of(asmroutines) == INSTANCE_POINTER_LOWTAG) {
561 /* Adjust the values in SB-FASL::*ASSEMBLER-ROUTINES*.
562 * No need to frob the 'needs_rehash_p' slot on account of this */
563 struct hash_table *ht = (struct hash_table*)native_pointer(asmroutines);
564 struct vector *table = (struct vector*)native_pointer(ht->table);
565 int i;
566 for (i=fixnum_value(table->length)-1; i>=3; i -= 2) {
567 if (fixnump(table->data[i]))
568 table->data[i] = make_fixnum(adjust_word(adj, fixnum_value(table->data[i])));
572 #endif
574 int merge_core_pages = -1;
576 static void
577 process_directory(int count, struct ndir_entry *entry,
578 int fd, os_vm_offset_t file_offset,
579 struct heap_adjust* adj)
581 extern void immobile_space_coreparse(uword_t,uword_t);
583 struct {
584 uword_t len; // length in bytes, as an integral multiple of os_vm_page_size
585 uword_t base;
586 lispobj** pfree_pointer; // pointer to x_free_pointer
587 } spaces[MAX_CORE_SPACE_ID+1] = {
588 {0, 0, 0}, // blank for space ID 0
589 #ifdef LISP_FEATURE_GENCGC
590 {0, DYNAMIC_SPACE_START, 0},
591 #else
592 {0, 0, 0},
593 #endif
594 // This order is determined by constants in compiler/generic/genesis
595 {0, STATIC_SPACE_START, &static_space_free_pointer},
596 {0, READ_ONLY_SPACE_START, &read_only_space_free_pointer},
597 #ifdef LISP_FEATURE_IMMOBILE_SPACE
598 {0, IMMOBILE_SPACE_START, &immobile_fixedobj_free_pointer},
599 {0, IMMOBILE_VARYOBJ_SUBSPACE_START, &immobile_space_free_pointer}
600 #endif
603 for ( ; --count>= 0; ++entry) {
604 sword_t id = entry->identifier;
605 uword_t addr = (1024 * entry->address); // multiplier as per core.h
606 int compressed = id & DEFLATED_CORE_SPACE_ID_FLAG;
607 id -= compressed;
608 if (id < 1 || id > MAX_CORE_SPACE_ID)
609 lose("unknown space ID %ld addr %p\n", id, addr);
611 #ifndef LISP_FEATURE_RELOCATABLE_HEAP
612 int enforce_address = 1;
613 #else
614 // Only enforce other spaces' addresses
615 int enforce_address = id != DYNAMIC_CORE_SPACE_ID
616 && id != IMMOBILE_FIXEDOBJ_CORE_SPACE_ID;
617 #endif
618 if (enforce_address) {
619 int fail;
620 #ifdef LISP_FEATURE_CHENEYGC
621 if (id == DYNAMIC_CORE_SPACE_ID) {
622 if ((fail = (addr != DYNAMIC_0_SPACE_START) &&
623 (addr != DYNAMIC_1_SPACE_START)) != 0)
624 fprintf(stderr, "in core: %p; in runtime: %p or %p\n",
625 (void*)addr,
626 (void*)DYNAMIC_0_SPACE_START,
627 (void*)DYNAMIC_1_SPACE_START);
628 } else
629 #endif
630 if ((fail = (addr != spaces[id].base)) != 0)
631 fprintf(stderr, "in core: %p; in runtime: %p\n",
632 (void*)addr, (void*)spaces[id].base);
633 char *names[] = {
634 "DYNAMIC", "STATIC", "READ_ONLY", "IMMOBILE", "IMMOBILE"
636 if (fail)
637 lose("core/runtime address mismatch: %s_SPACE_START", names[id-1]);
639 spaces[id].base = addr;
640 uword_t len = os_vm_page_size * entry->page_count;
641 spaces[id].len = len;
642 if (id == DYNAMIC_CORE_SPACE_ID && len > dynamic_space_size) {
643 lose("dynamic space too small for core: %luKiB required, %luKiB available.\n",
644 (unsigned long)len >> 10,
645 (unsigned long)dynamic_space_size >> 10);
647 if (len != 0) {
648 uword_t __attribute__((unused)) aligned_start;
649 #ifdef LISP_FEATURE_RELOCATABLE_HEAP
650 // Try to map at address requested by the core file.
651 if (id == DYNAMIC_CORE_SPACE_ID) {
652 addr = (uword_t)os_validate(MOVABLE, (os_vm_address_t)addr,
653 dynamic_space_size);
654 aligned_start = CEILING(addr, GENCGC_CARD_BYTES);
655 /* Misalignment can happen only if card size exceeds OS page.
656 * Drop one card to avoid overrunning the allocated space */
657 if (aligned_start > addr) // not card-aligned
658 dynamic_space_size -= GENCGC_CARD_BYTES;
659 DYNAMIC_SPACE_START = addr = aligned_start;
660 # ifndef LISP_FEATURE_IMMOBILE_SPACE
662 # else
663 if (DYNAMIC_SPACE_START < IMMOBILE_SPACE_START)
664 lose("Won't map dynamic space below immobile space");
665 /* Assume presence of linkage-table space for this platform.
666 * An unusable gap may exist between the linkage table and immobile space
667 * but it's not important whether it does or doesn't. So we don't bother
668 * unmapping the alleged gap */
669 } else if (id == IMMOBILE_FIXEDOBJ_CORE_SPACE_ID) {
670 addr = (uword_t)os_validate(MOVABLE_LOW, (os_vm_address_t)addr,
671 IMMOBILE_SPACE_SIZE);
672 IMMOBILE_SPACE_START = addr;
673 if (IMMOBILE_SPACE_START + IMMOBILE_SPACE_SIZE > 0x80000000)
674 lose("Won't map immobile space above 2GB");
675 // varyobj subspace must be enforced to reside at a known offset
676 // from fixedobj subspace.
677 spaces[IMMOBILE_VARYOBJ_CORE_SPACE_ID].base =
678 spaces[id].base + IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE;
679 IMMOBILE_VARYOBJ_SUBSPACE_START = addr + IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE;
680 } else if (id == IMMOBILE_VARYOBJ_CORE_SPACE_ID) {
681 /* Ignore what the core file said */
682 addr = IMMOBILE_VARYOBJ_SUBSPACE_START;
684 # endif
686 #endif /* LISP_FEATURE_RELOCATABLE_HEAP */
688 sword_t offset = os_vm_page_size * (1 + entry->data_page);
689 if (compressed)
690 inflate_core_bytes(fd, offset + file_offset, (os_vm_address_t)addr, len);
691 else
692 load_core_bytes(fd, offset + file_offset, (os_vm_address_t)addr, len);
695 #ifdef MADV_MERGEABLE
696 if ((merge_core_pages == 1)
697 || ((merge_core_pages == -1) && compressed)) {
698 madvise((void *)addr, len, MADV_MERGEABLE);
700 #endif
702 lispobj *free_pointer = (lispobj *) addr + entry->nwords;
703 switch (id) {
704 default:
705 *spaces[id].pfree_pointer = free_pointer;
706 break;
707 case DYNAMIC_CORE_SPACE_ID:
708 #ifdef LISP_FEATURE_CHENEYGC
709 /* 'addr' is the actual address if relocatable.
710 * For cheneygc, this will be whatever the GC was using
711 * at the time the core was saved.
712 * For gencgc this is #defined as DYNAMIC_SPACE_START */
713 current_dynamic_space = (lispobj *)addr;
714 #endif
715 set_alloc_pointer((lispobj)free_pointer);
717 anon_dynamic_space_start = (os_vm_address_t)(addr + len);
718 /* This assertion safeguards the test in zero_pages_with_mmap()
719 * which trusts that if addr > anon_dynamic_space_start
720 * then addr did not come from any file mapping. */
721 gc_assert((lispobj)anon_dynamic_space_start > STATIC_SPACE_END);
725 #ifdef LISP_FEATURE_IMMOBILE_SPACE
726 if (IMMOBILE_SPACE_START != spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].base) {
727 adj->range[0].start = spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].base;
728 adj->range[0].end = adj->range[0].start + IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE
729 + spaces[IMMOBILE_VARYOBJ_CORE_SPACE_ID].len;
730 adj->range[0].delta = IMMOBILE_SPACE_START - adj->range[0].start;
732 #endif
733 if (DYNAMIC_SPACE_START != spaces[DYNAMIC_CORE_SPACE_ID].base) {
734 adj->range[1].start = spaces[DYNAMIC_CORE_SPACE_ID].base;
735 adj->range[1].end = adj->range[1].start + spaces[DYNAMIC_CORE_SPACE_ID].len;
736 adj->range[1].delta = DYNAMIC_SPACE_START - adj->range[1].start;
738 if (adj->range[0].delta | adj->range[1].delta)
739 relocate_heap(adj);
741 #ifdef LISP_FEATURE_IMMOBILE_SPACE
742 /* Now determine page characteristics (such as object spacing)
743 * after relocation, because we need to know which objects are layouts
744 * based on knowing layout-of-layout. The test for that is dependent
745 * on what it's address should be, not what it was in the file */
746 immobile_space_coreparse(spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].len,
747 spaces[IMMOBILE_VARYOBJ_CORE_SPACE_ID].len);
748 #endif
749 #ifdef LISP_FEATURE_X86_64
750 tune_asm_routines_for_microarch(); // before WPing immobile space
751 #endif
754 lispobj
755 load_core_file(char *file, os_vm_offset_t file_offset)
757 void *header;
758 core_entry_elt_t val, *ptr;
759 os_vm_size_t len, remaining_len;
760 int fd = open_binary(file, O_RDONLY);
761 ssize_t count;
762 lispobj initial_function = NIL;
763 struct heap_adjust adj;
764 memset(&adj, 0, sizeof adj);
766 FSHOW((stderr, "/entering load_core_file(%s)\n", file));
767 if (fd < 0) {
768 fprintf(stderr, "could not open file \"%s\"\n", file);
769 perror("open");
770 exit(1);
773 lseek(fd, file_offset, SEEK_SET);
774 header = calloc(os_vm_page_size, 1);
776 count = read(fd, header, os_vm_page_size);
777 if (count < (ssize_t) os_vm_page_size) {
778 lose("premature end of core file\n");
780 SHOW("successfully read first page of core");
782 ptr = header;
783 val = *ptr++;
785 if (val != CORE_MAGIC) {
786 lose("invalid magic number in core: 0x%lx should have been 0x%x.\n",
787 val,
788 CORE_MAGIC);
790 SHOW("found CORE_MAGIC");
792 #define WORD_FMTX OS_VM_SIZE_FMTX
793 for ( ; val != END_CORE_ENTRY_TYPE_CODE ; ptr += remaining_len) {
794 val = *ptr++;
795 len = *ptr++;
796 remaining_len = len - 2; /* (-2 to cancel the two ++ operations) */
797 FSHOW((stderr, "/val=0x%"WORD_FMTX", remaining_len=0x%"WORD_FMTX"\n",
798 val, remaining_len));
800 switch (val) {
802 case END_CORE_ENTRY_TYPE_CODE:
803 SHOW("END_CORE_ENTRY_TYPE_CODE case");
804 break;
806 case BUILD_ID_CORE_ENTRY_TYPE_CODE:
807 SHOW("BUILD_ID_CORE_ENTRY_TYPE_CODE case");
809 os_vm_size_t stringlen = *ptr++;
810 --remaining_len;
811 gc_assert(remaining_len * sizeof (core_entry_elt_t) >= stringlen);
812 if (sizeof build_id == stringlen+1 && !memcmp(ptr, build_id, stringlen))
813 break;
814 /* .core files are not binary-compatible between
815 * builds because we can't easily detect whether the
816 * sources were patched between the time the
817 * dumping-the-.core runtime was built and the time
818 * that the loading-the-.core runtime was built.
820 * (We could easily detect whether version.lisp-expr
821 * was changed, but people experimenting with patches
822 * don't necessarily update version.lisp-expr.) */
823 fprintf(stderr,
824 "core was built for runtime \"%.*s\" but this is \"%s\"\n",
825 (int)stringlen, (char*)ptr, build_id);
826 lose("can't load .core for different runtime, sorry\n");
829 case NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE:
830 SHOW("NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE case");
831 process_directory(remaining_len / NDIR_ENTRY_LENGTH,
832 (struct ndir_entry*)ptr, fd, file_offset,
833 &adj);
834 break;
836 case INITIAL_FUN_CORE_ENTRY_TYPE_CODE:
837 SHOW("INITIAL_FUN_CORE_ENTRY_TYPE_CODE case");
838 initial_function = adjust_word(&adj, (lispobj)*ptr);
839 break;
841 #ifdef LISP_FEATURE_GENCGC
842 case PAGE_TABLE_CORE_ENTRY_TYPE_CODE:
844 extern void gc_allocate_ptes();
845 // Allocation of PTEs is delayed 'til now so that calloc() doesn't
846 // consume addresses that would have been taken by a mapped space.
847 gc_allocate_ptes();
848 os_vm_size_t remaining = *ptr;
849 os_vm_size_t fdoffset = (*(ptr+1) + 1) * (os_vm_page_size);
850 page_index_t page = 0, npages;
851 ssize_t bytes_read;
852 char data[8192];
853 // A corefile_pte is 10 bytes for x86-64
854 // Process an integral number of ptes on each read.
855 os_vm_size_t chunksize = sizeof (struct corefile_pte)
856 * (sizeof data / sizeof (struct corefile_pte));
857 lseek(fd, fdoffset + file_offset, SEEK_SET);
858 bytes_read = read(fd, &npages, sizeof npages);
859 gc_assert(bytes_read == sizeof npages);
860 remaining -= sizeof npages;
861 while ((bytes_read = read(fd, data,
862 remaining < chunksize ? remaining : chunksize)) > 0) {
864 int i = 0;
865 remaining -= bytes_read;
866 while (bytes_read) {
867 bytes_read -= sizeof(struct corefile_pte);
868 /* Ignore all zeroes. The size of the page table
869 * core entry was rounded up to os_vm_page_size
870 * during the save, and might now have more
871 * elements than the page table.
873 * The low bits of each word are allocation flags.
875 struct corefile_pte pte;
876 memcpy(&pte, data+i*sizeof (struct corefile_pte), sizeof pte);
877 set_page_bytes_used(page, pte.bytes_used);
878 set_page_scan_start_offset(page, pte.sso & ~0x03);
879 page_table[page].allocated = pte.sso & 0x03;
880 if (++page == npages) // break out of both loops
881 goto done;
882 i++;
885 done:
887 gencgc_partial_pickup = 1;
888 break;
890 #endif
891 default:
892 lose("unknown core file entry: 0x%"WORD_FMTX"\n", val);
895 SHOW("about to free(header)");
896 free(header);
897 close(fd);
898 SHOW("returning from load_core_file(..)");
899 return initial_function;
902 #include "genesis/hash-table.h"
903 #include "genesis/vector.h"
904 os_vm_address_t get_asm_routine_by_name(const char* name)
906 lispobj routines = SYMBOL(ASSEMBLER_ROUTINES)->value;
907 if (lowtag_of(routines) == INSTANCE_POINTER_LOWTAG) {
908 struct hash_table* ht = (struct hash_table*)native_pointer(routines);
909 struct vector* table = VECTOR(ht->table);
910 lispobj sym;
911 int i;
912 for (i=2 ; i < fixnum_value(table->length) ; i += 2) {
913 sym = table->data[i];
914 if (lowtag_of(sym) == OTHER_POINTER_LOWTAG
915 && widetag_of(SYMBOL(sym)->header) == SYMBOL_WIDETAG
916 && !strcmp(name, (char*)(VECTOR(SYMBOL(sym)->name)->data)))
917 return (os_vm_address_t)fixnum_value(table->data[i+1]);
919 // Something is wrong if we have a hashtable but find nothing.
920 fprintf(stderr, "WARNING: get_asm_routine_by_name(%s) failed\n",
921 name);
923 return NULL;
926 void asm_routine_poke(const char* routine, int offset, char byte)
928 char *address = (char *)get_asm_routine_by_name(routine);
929 if (address)
930 address[offset] = byte;