replace transform: don't fall on NIL.
[sbcl.git] / src / runtime / coreparse.c
blobd6f122643e9822bde8adee7927b3c355aadb2c86
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 "genesis/sbcl.h"
19 #ifndef LISP_FEATURE_WIN32
20 #include <sys/mman.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/file.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
32 #include "os.h"
33 #include "runtime.h"
34 #include "globals.h"
35 #include "core.h"
36 #include "arch.h"
37 #include "interr.h"
38 #include "thread.h"
40 #include "validate.h"
41 #include "gc.h"
42 #include "code.h"
43 #include "graphvisit.h"
44 #include "genesis/instance.h"
45 #include "genesis/symbol.h"
47 #include <errno.h>
49 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
50 # include <zstd.h>
51 #endif
53 /* build_id must match between the C code and .core file because a core
54 * is only guaranteed to be compatible with the C runtime that created it.
55 * We can't easily detect whether the sources were patched after saving
56 * a core, but we can easily enforce a matching build_id.
57 * Note that fasls have a different way of ensuring compatibility with the
58 * core: the contents of version.lisp-expr are written into the fasl.
59 * Both checks avoid confusion for end-users, but the build_id test
60 * is more geared toward developers as it can change with each rebuild.
62 unsigned char build_id[] =
63 // The suffix added to build-id indicates which flavor of C compiler was used.
64 // This enforces that when you put :MSAN in your Lisp features, you don't
65 // omit "-fsanitize=memory -DMEMORY_SANITIZE" from CFLAGS and LINKFLAGS.
66 // (Some Lisp features affect C flags, but not this one.)
67 // It is important for out-of-tree builds: once they work, you can produce
68 // two trees of artifacts from identical sources *including* the build-id.inc
69 // (but not including "local-target-features.lisp-expr"), and end up with two
70 // Lisp cores and two C runtimes. The extra suffix avoids accidental mismatch.
71 #include "../../output/build-id.inc"
72 #ifdef MEMORY_SANITIZER
73 "-msan"
74 #endif
77 static int
78 open_binary(char *filename, int mode)
80 #ifdef LISP_FEATURE_WIN32
81 mode |= O_BINARY;
82 #endif
84 return open(filename, mode);
87 #if defined LISP_FEATURE_LINUX && (defined LISP_FEATURE_X86_64 || defined LISP_FEATURE_ARM64)
88 #define ELFCORE 1
89 #elif !defined(ELFCORE)
90 #define ELFCORE 0
91 #endif
93 #if !ELFCORE
94 int lisp_code_in_elf() { return 0; }
95 lispobj* get_alien_linkage_table_initializer() { return 0; }
96 #else
97 extern __attribute__((weak)) lispobj
98 lisp_code_start, lisp_jit_code, lisp_code_end, alien_linkage_values;
99 int lisp_code_in_elf() { return &lisp_code_start != 0; }
100 lispobj* get_alien_linkage_table_initializer() { return &alien_linkage_values; }
101 #endif
103 /* Search 'filename' for an embedded core. An SBCL core has, at the
104 * end of the file, a trailer containing optional saved runtime
105 * options, the start of the core (an os_vm_offset_t), and a final
106 * signature word (the lispobj CORE_MAGIC). If this trailer is found
107 * at the end of the file, the start of the core can be determined
108 * from the core size.
110 * If an embedded core is present, this returns the offset into the
111 * file to load the core from, or -1 if no core is present. */
112 os_vm_offset_t
113 search_for_embedded_core(char *filename, struct memsize_options *memsize_options)
115 extern os_vm_offset_t search_for_elf_core(int);
116 lispobj header = 0;
117 os_vm_offset_t lispobj_size = sizeof(lispobj);
118 int fd;
120 if ((fd = open_binary(filename, O_RDONLY)) < 0)
121 return -1;
123 if (read(fd, &header, lispobj_size) == lispobj_size && header == CORE_MAGIC) {
124 /* This file is a real core, not an embedded core. Return 0 to
125 * indicate where the core starts, and do not look for runtime
126 * options in this case. */
127 close(fd);
128 return 0;
131 os_vm_offset_t core_start = -1; // invalid value
132 if (lseek(fd, -lispobj_size, SEEK_END) < 0 ||
133 read(fd, &header, (size_t)lispobj_size) != lispobj_size)
134 goto lose;
136 if (header == CORE_MAGIC) {
137 // the last word in the file could be CORE_MAGIC by pure coincidence
138 if (lseek(fd, -(lispobj_size + sizeof(os_vm_offset_t)), SEEK_END) < 0 ||
139 read(fd, &core_start, sizeof(os_vm_offset_t)) != sizeof(os_vm_offset_t))
140 goto lose;
141 if (lseek(fd, core_start, SEEK_SET) != core_start ||
142 read(fd, &header, lispobj_size) != lispobj_size || header != CORE_MAGIC)
143 core_start = -1; // reset to invalid
145 #if ELFCORE && !defined(LISP_FEATURE_DARWIN)
146 // Specifying "--core" as an ELF file with a lisp.core section doesn't work.
147 // (There are bunch of reasons) So only search for a core section if this
148 // is an implicit search for a core embedded in an executable.
149 // The two cases can be distinguished based on whether the core is able
150 // to set the memsize_options. (Implicit can set them, explicit can't)
151 if (core_start < 0 && memsize_options) {
152 if (!(core_start = search_for_elf_core(fd)) ||
153 lseek(fd, core_start, SEEK_SET) != core_start ||
154 read(fd, &header, lispobj_size) != lispobj_size || header != CORE_MAGIC)
155 core_start = -1; // reset to invalid
157 #endif
158 if (core_start > 0 && memsize_options) {
159 core_entry_elt_t optarray[RUNTIME_OPTIONS_WORDS];
160 // file is already positioned to the first core header entry
161 if (read(fd, optarray, sizeof optarray) == sizeof optarray
162 && optarray[0] == RUNTIME_OPTIONS_MAGIC) {
163 memsize_options->dynamic_space_size = optarray[2];
164 memsize_options->thread_control_stack_size = optarray[3];
165 memsize_options->thread_tls_bytes = optarray[4];
166 memsize_options->present_in_core = 1;
169 lose:
170 close(fd);
171 return core_start;
174 #ifndef LISP_FEATURE_SB_CORE_COMPRESSION
175 # define inflate_core_bytes(fd,offset,addr,len) \
176 lose("This runtime was not built with zstd-compressed core support... aborting")
177 #else
178 static void inflate_core_bytes(int fd, os_vm_offset_t offset,
179 os_vm_address_t addr, uword_t len)
181 # ifdef LISP_FEATURE_WIN32
182 /* Ensure the memory is committed so zstd doesn't segfault trying
183 to inflate. */
184 os_commit_memory(addr, len);
185 # endif
186 if (-1 == lseek(fd, offset, SEEK_SET))
187 lose("Unable to lseek() on corefile");
189 int ret;
190 size_t buf_size = ZSTD_DStreamInSize();
191 unsigned char* buf = successful_malloc(buf_size);
192 ZSTD_inBuffer input;
193 input.src = buf;
194 input.pos = 0;
196 ZSTD_outBuffer output;
197 output.dst = (void*)addr;
198 output.size = len;
199 output.pos = 0;
201 ZSTD_DStream *stream = ZSTD_createDStream();
202 if (stream == NULL)
203 lose("unable to create zstd decompression context");
204 ret = ZSTD_initDStream(stream);
205 if (ZSTD_isError(ret))
206 lose("ZSTD_initDStream failed with error: %s", ZSTD_getErrorName(ret));
208 /* Read in exactly one frame. */
209 do {
210 ssize_t count = read(fd, buf, buf_size);
211 if (count < 0)
212 lose("unable to read core file (errno = %i)", errno);
213 input.size = count;
214 input.pos = 0;
215 ret = ZSTD_decompressStream(stream, &output, &input);
216 if (ZSTD_isError(ret))
217 lose("ZSTD_decompressStream failed with error: %s",
218 ZSTD_getErrorName(ret));
219 } while (ret != 0);
221 ZSTD_freeDStream(stream);
222 free(buf);
224 #endif
226 struct heap_adjust {
227 struct range {
228 lispobj start, end;
229 sword_t delta;
230 } range[MAX_CORE_SPACE_ID+1];
231 int n_ranges;
232 int n_relocs_abs; // absolute
233 int n_relocs_rel; // relative
236 #include "genesis/gc-tables.h"
237 #include "genesis/cons.h"
238 #include "genesis/hash-table.h"
239 #include "genesis/vector.h"
241 static inline sword_t calc_adjustment(struct heap_adjust* adj, lispobj x)
243 int j;
244 for (j = adj->n_ranges - 1 ; j >= 0 ; --j)
245 if (adj->range[j].start <= x && x < adj->range[j].end) return adj->range[j].delta;
246 return 0;
249 // Given a post-relocation object 'x', compute the address at which
250 // it was originally expected to have been placed as per the core file.
251 __attribute__((unused)) static inline lispobj
252 inverse_adjust(struct heap_adjust* adj, lispobj x)
254 int j;
255 for (j = adj->n_ranges - 1 ; j >= 0 ; --j)
256 if (adj->range[j].start + adj->range[j].delta <= x &&
257 x < adj->range[j].end + adj->range[j].delta)
258 return x - adj->range[j].delta;
259 return x;
262 // Return the adjusted value of 'word' without testing whether it looks
263 // like a pointer. But do test whether it points to a relocatable space.
264 static inline lispobj adjust_word(struct heap_adjust* adj, lispobj word) {
265 return word + calc_adjustment(adj, word);
268 struct coreparse_space {
269 int id;
270 size_t desired_size; // size wanted, ORed with 1 if addr must be <2GB
271 // Values from the core file:
272 uword_t len; // length in bytes, as an integral multiple of os_vm_page_size
273 uword_t base;
274 lispobj** pfree_pointer; // pointer to x_free_pointer
275 } spaces;
277 static void
278 set_adjustment(struct cons* pair, int id, uword_t actual_addr)
280 struct coreparse_space* spaces = (void*)pair->car;
281 struct heap_adjust* adj = (void*)pair->cdr;
282 uword_t desired_addr = spaces[id].base;
283 sword_t len = spaces[id].len;
284 sword_t delta = len ? actual_addr - desired_addr : 0;
285 if (!delta) return;
286 int j = adj->n_ranges;
287 adj->range[j].start = (lispobj)desired_addr;
288 adj->range[j].end = (lispobj)desired_addr + len;
289 adj->range[j].delta = delta;
290 adj->n_ranges = j+1;
293 #define SHOW_SPACE_RELOCATION 0
294 #if SHOW_SPACE_RELOCATION > 1
295 # define FIXUP(expr, addr) fprintf(stderr, "%p: (a) %lx", addr, *(long*)(addr)), \
296 expr, fprintf(stderr, " -> %lx\n", *(long*)(addr)), ++adj->n_relocs_abs
297 # define FIXUP32(expr, addr) fprintf(stderr, "%p: (a) %x", addr, *(int*)(addr)), \
298 expr, fprintf(stderr, " -> %x\n", *(int*)(addr)), ++adj->n_relocs_abs
299 # define FIXUP_rel(expr, addr) fprintf(stderr, "%p: (r) %x", addr, *(int*)(addr)), \
300 expr, fprintf(stderr, " -> %x\n", *(int*)(addr)), ++adj->n_relocs_rel
301 #elif SHOW_SPACE_RELOCATION
302 # define FIXUP(expr, addr) expr, ++adj->n_relocs_abs
303 # define FIXUP32(expr, addr) expr, ++adj->n_relocs_abs
304 # define FIXUP_rel(expr, addr) expr, ++adj->n_relocs_rel
305 #else
306 # define FIXUP(expr, addr) expr
307 # define FIXUP32(expr, addr) expr
308 # define FIXUP_rel(expr, addr) expr
309 #endif
311 // Fix the word at 'where' without testing whether it looks pointer-like.
312 // Avoid writing if there is no adjustment.
313 static inline void adjust_word_at(lispobj* where, struct heap_adjust* adj) {
314 lispobj word = *where;
315 sword_t adjustment = calc_adjustment(adj, word);
316 if (adjustment != 0)
317 FIXUP(*where = word + adjustment, where);
320 // Adjust the words in range [where,where+n_words)
321 // skipping any words that have non-pointer nature.
322 static void adjust_pointers(lispobj *where, sword_t n_words, struct heap_adjust* adj)
324 long i;
325 for (i=0;i<n_words;++i) {
326 lispobj word = where[i];
327 sword_t adjustment;
328 if (is_lisp_pointer(word) && (adjustment = calc_adjustment(adj, word)) != 0) {
329 FIXUP(where[i] = word + adjustment, where+i);
334 #include "var-io.h"
335 #include "align.h"
336 static void
337 adjust_code_refs(struct heap_adjust __attribute__((unused)) *adj,
338 struct code __attribute__((unused)) *code)
340 #if defined LISP_FEATURE_PERMGEN || defined LISP_FEATURE_IMMOBILE_SPACE
341 // Dynamic space always gets relocated before immobile space does,
342 // and dynamic space code does not use fixups (except on 32-bit x86).
343 // So if we're here, it must be to relocate an immobile object.
344 // If 'code->fixups' is a bignum, the pointer itself was already fixed up.
345 char* instructions = code_text_start(code);
346 struct varint_unpacker unpacker;
348 varint_unpacker_init(&unpacker, code->fixups);
349 skip_data_stream(&unpacker); // first data stream comprises the linkage indices
350 int prev_loc = 0, loc;
351 while (varint_unpack(&unpacker, &loc) && loc != 0) {
352 // For extra compactness, each loc is relative to the prior,
353 // so that the magnitudes are smaller.
354 loc += prev_loc;
355 prev_loc = loc;
356 void* fixup_where = instructions + loc;
357 lispobj ptr = UNALIGNED_LOAD32(fixup_where);
358 lispobj adjusted = ptr + calc_adjustment(adj, ptr);
359 if (!(adjusted <= UINT32_MAX))
360 lose("Absolute fixup @ %p exceeds 32 bits", fixup_where);
361 if (adjusted != ptr)
362 FIXUP32(UNALIGNED_STORE32(fixup_where, adjusted), fixup_where);
364 #endif
367 static inline void fix_fun_header_layout(lispobj __attribute__((unused)) *fun,
368 struct heap_adjust __attribute__((unused)) *adj)
370 #if defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER) && defined(LISP_FEATURE_64_BIT)
371 lispobj ptr = funinstance_layout(fun);
372 lispobj adjusted = adjust_word(adj, ptr);
373 if (adjusted != ptr) FIXUP(funinstance_layout(fun)=adjusted, fun);
374 #endif
377 static void fix_space(uword_t start, lispobj* end, struct heap_adjust* adj)
379 int widetag;
380 long nwords;
381 lispobj layout, adjusted_layout;
382 struct code* code;
383 sword_t delta;
384 int i;
386 adj->n_relocs_abs = adj->n_relocs_rel = 0;
387 lispobj *where = next_object((lispobj*)start, 0, end);
388 for ( ; where ; where = next_object(where, nwords, end) ) {
389 lispobj word = *where;
390 if (!is_header(word)) {
391 adjust_pointers(where, 2, adj);
392 nwords = 2;
393 continue;
395 widetag = header_widetag(word);
396 nwords = sizetab[widetag](where);
397 switch (widetag) {
398 case FUNCALLABLE_INSTANCE_WIDETAG:
399 /* If non-executable funinstance, then word index 1 points at read-only space,
400 * hence needs no adjustment. Otherwise, the word points within the funinstance.
401 * Either way, adjust_word_at will do the right thing */
402 adjust_word_at(where+1, adj);
403 /* FALLTHRU */
404 case INSTANCE_WIDETAG:
405 layout = layout_of(where);
406 adjusted_layout = adjust_word(adj, layout);
407 // writeback the layout if it changed. The layout is not a tagged slot
408 // so it would not be fixed up otherwise.
409 if (adjusted_layout != layout) layout_of(where) = adjusted_layout;
410 struct bitmap bitmap = get_layout_bitmap(LAYOUT(adjusted_layout));
412 lispobj* slots = where+1;
413 for (i=0; i<(nwords-1); ++i) // -1 from nwords because 'slots' is +1 from 'where'
414 if (bitmap_logbitp(i, bitmap)) adjust_pointers(slots+i, 1, adj);
416 continue;
417 case SYMBOL_WIDETAG: {
418 // Modeled on scav_symbol() in gc-common
419 struct symbol* s = (void*)where;
420 #ifdef LISP_FEATURE_64_BIT
421 lispobj name = decode_symbol_name(s->name);
422 lispobj adjusted_name = adjust_word(adj, name);
423 // writeback the name if it changed
424 if (adjusted_name != name) FIXUP(set_symbol_name(s, adjusted_name), &s->name);
425 adjust_pointers(&s->value, 1, adj);
426 adjust_pointers(&s->info, 1, adj);
427 adjust_pointers(&s->fdefn, 1, adj);
428 #else
429 adjust_pointers(&s->fdefn, 4, adj); // fdefn, value, info, name
430 #endif
431 continue;
433 case FDEFN_WIDETAG: {
434 struct fdefn* f = (void*)where;
435 adjust_pointers(&f->name, 1, adj);
436 adjust_pointers(&f->fun, 1, adj);
437 #ifndef LISP_FEATURE_LINKAGE_SPACE
438 // For most architectures, 'raw_addr' doesn't satisfy is_lisp_pointer()
439 // so adjust_pointers() would ignore it. Therefore we need to
440 // forcibly adjust it. This is correct whether or not there are tag bits.
441 adjust_word_at((lispobj*)&f->raw_addr, adj);
442 #endif
443 continue;
445 case CODE_HEADER_WIDETAG:
446 // Fixup the constant pool. The word at where+1 is a fixnum.
447 code = (struct code*)where;
448 adjust_pointers(where+2, code_header_words(code)-2, adj);
449 #ifdef LISP_FEATURE_UNTAGGED_FDEFNS
450 // Process each untagged fdefn pointer.
451 lispobj* fdefns_start = code->constants;
452 int i;
453 for (i=code_n_named_calls(code)-1; i>=0; --i)
454 adjust_word_at(fdefns_start+i, adj);
455 #endif
456 #if defined LISP_FEATURE_X86 || defined LISP_FEATURE_X86_64 || \
457 defined LISP_FEATURE_PPC || defined LISP_FEATURE_PPC64 || defined LISP_FEATURE_ARM64
458 // Fixup absolute jump table
459 lispobj* jump_table = code_jumptable_start(code);
460 int count = jumptable_count(jump_table);
461 for (i = 1; i < count; ++i) adjust_word_at(jump_table+i, adj);
462 #endif
463 // Fixup all embedded simple-funs
464 for_each_simple_fun(i, f, code, 1, {
465 fix_fun_header_layout((lispobj*)f, adj);
466 #if FUN_SELF_FIXNUM_TAGGED
467 if (f->self != (lispobj)f->insts)
468 FIXUP(f->self = (lispobj)f->insts, &f->self);
469 #else
470 adjust_pointers(&f->self, 1, adj);
471 #endif
473 // Now that the packed integer comprising the list of fixup locations
474 // has been fixed-up (if necessary), apply them to the code.
475 gencgc_apply_code_fixups((struct code*)inverse_adjust(adj, (lispobj)code),
476 code);
477 adjust_code_refs(adj, code);
478 continue;
479 case CLOSURE_WIDETAG:
480 fix_fun_header_layout(where, adj);
481 #if FUN_SELF_FIXNUM_TAGGED
482 // For x86[-64], arm64, the closure fun appears to be a fixnum,
483 // and might need adjustment unless pointing to immobile code.
484 // Then fall into the general case; where[1] won't get re-adjusted
485 // because it doesn't satisfy is_lisp_pointer().
486 adjust_word_at(where+1, adj);
487 #endif
488 break;
489 // Vectors require extra care because of address-based hashing.
490 case SIMPLE_VECTOR_WIDETAG:
491 if (vector_flagp(*where, VectorAddrHashing)) {
492 struct vector* v = (struct vector*)where;
493 // If you could make a hash-table vector with space for exactly 1 k/v pair,
494 // it would have length 5.
495 gc_assert(vector_len(v) >= 5); // KLUDGE: need a manifest constant for fixed overhead
496 lispobj* data = (lispobj*)v->data;
497 adjust_pointers(&data[vector_len(v)-1], 1, adj);
498 int hwm = KV_PAIRS_HIGH_WATER_MARK(data);
499 bool needs_rehash = 0;
500 lispobj *where = &data[2], *end = &data[2*(hwm+1)];
501 // Adjust the elements, checking for need to rehash.
502 for ( ; where < end ; where += 2) {
503 // Really we should use the hash values to figure out which
504 // keys were address-sensitive. This simply overapproximates
505 // by assuming that any change forces rehash.
506 // (Similar issue exists in 'fixup_space' in immobile-space.c)
507 lispobj ptr = *where; // key
508 if (is_lisp_pointer(ptr) && (delta = calc_adjustment(adj, ptr)) != 0) {
509 FIXUP(*where = ptr + delta, where);
510 needs_rehash = 1;
512 ptr = where[1]; // value
513 if (is_lisp_pointer(ptr) && (delta = calc_adjustment(adj, ptr)) != 0)
514 FIXUP(where[1] = ptr + delta, where+1);
516 if (needs_rehash) // set v->data[1], the need-to-rehash bit
517 KV_PAIRS_REHASH(data) |= make_fixnum(1);
518 continue;
520 // All the array header widetags.
521 case SIMPLE_ARRAY_WIDETAG:
522 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
523 case COMPLEX_CHARACTER_STRING_WIDETAG:
524 #endif
525 case COMPLEX_BASE_STRING_WIDETAG:
526 case COMPLEX_BIT_VECTOR_WIDETAG:
527 case COMPLEX_VECTOR_WIDETAG:
528 case COMPLEX_ARRAY_WIDETAG:
529 // And the rest of the purely descriptor objects.
530 case VALUE_CELL_WIDETAG:
531 case WEAK_POINTER_WIDETAG:
532 case RATIO_WIDETAG:
533 case COMPLEX_RATIONAL_WIDETAG:
534 break;
536 // Other
537 case SAP_WIDETAG:
538 if ((delta = calc_adjustment(adj, where[1])) != 0) {
539 fprintf(stderr,
540 "WARNING: SAP at %p -> %p in relocatable core\n",
541 where, (void*)where[1]);
542 FIXUP(where[1] += delta, where+1);
544 continue;
545 default:
546 if (other_immediate_lowtag_p(widetag) && leaf_obj_widetag_p(widetag))
547 continue;
548 else
549 lose("Unrecognized heap object: @%p: %"OBJ_FMTX, where, *where);
551 adjust_pointers(where+1, nwords-1, adj);
553 #if SHOW_SPACE_RELOCATION
554 if (end)
555 fprintf(stderr, "space @ %p..%p: fixed %d absolute + %d relative pointers\n",
556 (lispobj*)start, end, adj->n_relocs_abs, adj->n_relocs_rel);
557 #endif
560 uword_t* elf_linkage_space;
561 int elf_linkage_table_count;
562 static void relocate_heap(struct heap_adjust* adj)
564 #ifdef LISP_FEATURE_LINKAGE_SPACE
566 // Linkage space possibly needs altering even if all spaces were placed as requested
567 int i, n = linkage_table_count;
568 if (lisp_code_in_elf()) gc_assert(elf_linkage_space);
569 for (i=1; i<n; ++i) {
570 lispobj word = linkage_space[i];
571 // low bit on means it references code-in-ELF, otherwise dynamic space
572 if (word & 1) linkage_space[i] = word - 1 + TEXT_SPACE_START;
573 adjust_word_at(linkage_space+i, adj); // this is for ordinary space-relocation if needed
574 // And finally, if there is code-in-ELF, copy the entry
575 if (elf_linkage_space) elf_linkage_space[i] = linkage_space[i];
578 #endif
579 if (!adj->n_ranges) return;
580 if (!lisp_startup_options.noinform && SHOW_SPACE_RELOCATION) {
581 int i;
582 for (i = 0; i < adj->n_ranges; ++i)
583 if (adj->range[i].delta)
584 fprintf(stderr, "NOTE: Relocating [%p:%p] into [%p:%p]\n",
585 (char*)adj->range[i].start,
586 (char*)adj->range[i].end,
587 (char*)adj->range[i].start + adj->range[i].delta,
588 (char*)adj->range[i].end + adj->range[i].delta);
590 #ifdef LISP_FEATURE_RELOCATABLE_STATIC_SPACE
591 fix_space(READ_ONLY_SPACE_START, read_only_space_free_pointer, adj);
592 // Relocate the CAR slot of nil-as-a-list, which needs to point to
593 // itself.
594 adjust_pointers((void*)(NIL - LIST_POINTER_LOWTAG), 1, adj);
595 #endif
596 fix_space(NIL_SYMBOL_SLOTS_START, (lispobj*)NIL_SYMBOL_SLOTS_END, adj);
597 fix_space(STATIC_SPACE_OBJECTS_START, static_space_free_pointer, adj);
598 #ifdef LISP_FEATURE_PERMGEN
599 fix_space(PERMGEN_SPACE_START, permgen_space_free_pointer, adj);
600 #endif
601 #ifdef LISP_FEATURE_IMMOBILE_SPACE
602 fix_space(FIXEDOBJ_SPACE_START, fixedobj_free_pointer, adj);
603 #endif
604 fix_space(DYNAMIC_SPACE_START, (lispobj*)dynamic_space_highwatermark(), adj);
605 fix_space(TEXT_SPACE_START, text_space_highwatermark, adj);
608 #if defined(LISP_FEATURE_ELF) && defined(LISP_FEATURE_IMMOBILE_SPACE)
609 extern int apply_pie_relocs(long,long,int);
610 #else
611 # define apply_pie_relocs(dummy1,dummy2,dummy3) (0)
612 #endif
614 /// Compute the bounds of the lisp assembly routine code object
615 void calc_asm_routine_bounds()
617 #if defined LISP_FEATURE_IMMOBILE_CODE
618 asm_routines_start = TEXT_SPACE_START;
619 #else
620 if ((uword_t)read_only_space_free_pointer > READ_ONLY_SPACE_START &&
621 widetag_of((lispobj*)READ_ONLY_SPACE_START) == CODE_HEADER_WIDETAG) {
622 asm_routines_start = READ_ONLY_SPACE_START;
623 } else {
624 lispobj *where = (lispobj*)STATIC_SPACE_OBJECTS_START;
625 for (; where < static_space_free_pointer; where += object_size(where))
626 if (widetag_of(where) == CODE_HEADER_WIDETAG) {
627 asm_routines_start = (uword_t)where;
628 break;
630 /* I thought it would be possible to erase the static-space copy of asm routines
631 * after converting to text space but maybe not. So they'll still be here.
632 * But I want to erase them. This disabled block represents such aspiration */
633 if (0) { // !asm_routines_start && TEXT_SPACE_START != 0) {
634 lispobj *where = (lispobj*)TEXT_SPACE_START;
635 where += object_size(where);
636 gc_assert(widetag_of(where) == CODE_HEADER_WIDETAG);
637 asm_routines_start = (uword_t)where;
639 if (!asm_routines_start) lose("Can't find asm routines");
641 #endif
642 asm_routines_end = asm_routines_start +
643 N_WORD_BYTES * sizetab[CODE_HEADER_WIDETAG]((lispobj*)asm_routines_start);
646 #ifdef LISP_FEATURE_IMMOBILE_SPACE
647 void calc_immobile_space_bounds()
649 /* Suppose we have:
650 * A B C D
651 * | text space | .... other random stuff ... | fixedobj space | ...
652 * then the lower bound is A, the upper bound is D,
653 * the max_offset is the distance from A to D,
654 * and the excluded middle is the range spanned by B to C.
656 struct range {
657 uword_t start, end;
659 struct range range1 =
660 {FIXEDOBJ_SPACE_START, FIXEDOBJ_SPACE_START + FIXEDOBJ_SPACE_SIZE};
661 struct range range2 =
662 {TEXT_SPACE_START, TEXT_SPACE_START + text_space_size};
663 if (range2.start < range1.start) { // swap
664 struct range temp = range1;
665 range1 = range2;
666 range2 = temp;
668 immobile_space_lower_bound = range1.start;
669 immobile_space_max_offset = range2.end - range1.start;
670 immobile_range_1_max_offset = range1.end - range1.start;
671 immobile_range_2_min_offset = range2.start - range1.start;
673 #endif
675 __attribute__((unused)) static void check_dynamic_space_addr_ok(uword_t start, uword_t size)
677 #ifdef LISP_FEATURE_64_BIT // don't want a -Woverflow warning on 32-bit
678 uword_t end_word_addr = start + size - N_WORD_BYTES;
679 // Word-aligned pointers can't address more than 48 significant bits for now.
680 // If you want to lift that restriction, look at how SYMBOL-PACKAGE and
681 // SYMBOL-NAME are combined into one lispword.
682 uword_t unaddressable_bits = 0xFFFF000000000000;
683 if ((start & unaddressable_bits) || (end_word_addr & unaddressable_bits))
684 lose("Panic! This version of SBCL can not address memory\n"
685 "in the range %p:%p given by the OS.\nPlease report this as a bug.",
686 (void*)start, (void*)(start + size));
687 #endif
690 #ifdef LISP_FEATURE_LINKAGE_SPACE
691 #define LISP_LINKAGE_SPACE_SIZE (1<<(N_LINKAGE_INDEX_BITS+WORD_SHIFT))
692 #endif
694 #if defined LISP_FEATURE_IMMOBILE_SPACE && defined LISP_FEATURE_ARM64
695 #define LISP_LINKAGE_SPACE_SIZE 0
696 #endif
697 static os_vm_address_t reserve_space(int space_id, int attr,
698 os_vm_address_t addr, os_vm_size_t size)
700 __attribute__((unused)) int extra_request = 0;
701 #ifdef LISP_FEATURE_IMMOBILE_SPACE
702 if (space_id == IMMOBILE_TEXT_CORE_SPACE_ID) {
703 extra_request = ALIEN_LINKAGE_SPACE_SIZE + LISP_LINKAGE_SPACE_SIZE;
704 size += extra_request;
705 addr -= extra_request; // compensate to try to put text space start where expected
707 #endif
708 if (size == 0) return addr;
709 // 64-bit already allocated a trap page when the GC card mark table was made
710 #if defined(LISP_FEATURE_SB_SAFEPOINT) && !defined(LISP_FEATURE_X86_64)
711 if (space_id == STATIC_CORE_SPACE_ID) {
712 // Allocate space for the safepoint page.
713 addr = os_alloc_gc_space(space_id, attr, addr - BACKEND_PAGE_BYTES, size + BACKEND_PAGE_BYTES) + BACKEND_PAGE_BYTES;
715 else
716 #endif
717 addr = os_alloc_gc_space(space_id, attr, addr, size);
718 if (!addr) lose("Can't allocate %#"OBJ_FMTX" bytes for space %d", size, space_id);
719 #ifdef LISP_FEATURE_IMMOBILE_SPACE
720 if (space_id == IMMOBILE_TEXT_CORE_SPACE_ID) {
721 ALIEN_LINKAGE_SPACE_START = (uword_t)addr;
722 linkage_space = (void*)((char*)addr + ALIEN_LINKAGE_SPACE_SIZE);
723 addr += extra_request;
725 #endif
726 return addr;
729 static __attribute__((unused)) uword_t corespace_checksum(uword_t* base, int nwords)
731 uword_t result = 0;
732 int i;
733 for (i = 0; i<nwords; ++i)
734 result = ((result << 1) | (result >> (N_WORD_BITS-1))) ^ base[i];
735 return result;
738 /* TODO: If static + readonly were mapped as desired without disabling ASLR
739 * but one of the large spaces couldn't be mapped as desired, start over from
740 * the top, disabling ASLR. This should help to avoid relocating the heap
741 * if at all possible. It might make sense to parse the core header sooner in
742 * startup to avoid wasting time on all actions performed prior to re-exec.
745 lispobj* linkage_space;
746 int linkage_table_count;
748 static void
749 process_directory(int count, struct ndir_entry *entry,
750 __attribute__((unused)) sword_t linkage_table_data_page,
751 int fd, os_vm_offset_t file_offset,
752 int __attribute__((unused)) merge_core_pages,
753 struct coreparse_space *spaces,
754 struct heap_adjust *adj)
756 // If ELF core is supported, then test whether the weak symbol
757 // 'lisp_code_start' exists in this executable. If it does, then parse
758 // the ELF sections containing Lisp code and everything else.
759 #if ELFCORE
760 if (&lisp_code_start) {
761 TEXT_SPACE_START = (uword_t)&lisp_code_start;
762 text_space_highwatermark = &lisp_jit_code;
763 text_space_size = (uword_t)&lisp_code_end - TEXT_SPACE_START;
764 spaces[IMMOBILE_TEXT_CORE_SPACE_ID].len = text_space_size;
765 if (text_space_highwatermark < (lispobj*)TEXT_SPACE_START
766 || !PTR_IS_ALIGNED(&lisp_code_end, 4096))
767 lose("ELF core alignment bug. Check for proper padding in 'editcore'");
768 #ifdef DEBUG_COREPARSE
769 printf("Lisp code present in executable @ %lx:%lx (freeptr=%p)\n",
770 (uword_t)&lisp_code_start, (uword_t)&lisp_code_end,
771 text_space_highwatermark);
772 #endif
773 // unprotect the pages
774 os_protect((void*)TEXT_SPACE_START, text_space_size, OS_VM_PROT_ALL);
776 #ifdef LISP_FEATURE_IMMOBILE_SPACE
777 // ELF core without immobile space has alien linkage space below static space.
778 ALIEN_LINKAGE_SPACE_START =
779 (uword_t)os_alloc_gc_space(ALIEN_LINKAGE_TABLE_CORE_SPACE_ID, 0, 0,
780 ALIEN_LINKAGE_SPACE_SIZE);
781 #endif
782 } else
783 #endif
784 // NB: The preceding 'else', if it's there, needs at least an empty
785 // statement following it if there is no immobile space.
787 #ifdef LISP_FEATURE_IMMOBILE_SPACE
788 spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].desired_size +=
789 text_space_size + ALIEN_LINKAGE_SPACE_SIZE;
790 #endif
793 for ( ; --count >= 0 ; ++entry) {
794 long id = entry->identifier; // FIXME: is this 'long' and not 'int' for a reason?
795 uword_t addr = entry->address;
796 int compressed = id & DEFLATED_CORE_SPACE_ID_FLAG;
797 id -= compressed;
798 if (id < 1 || id > MAX_CORE_SPACE_ID)
799 lose("unknown space ID %ld addr %p", id, (void*)addr);
801 int enforce_address = 0;
802 #ifndef LISP_FEATURE_RELOCATABLE_STATIC_SPACE
803 enforce_address |= (id == STATIC_CORE_SPACE_ID);
804 #endif
806 // We'd like to enforce proper alignment of 'addr' but there's
807 // a problem: dynamic space has a stricter requirement (usually 32K)
808 // than code space (4K). So don't assert the alignment.
809 if (enforce_address && addr != spaces[id].base)
810 lose("core address mismatch: %s_SPACE_START=%p but runtime expects %p\n",
811 id==READ_ONLY_CORE_SPACE_ID?"READ_ONLY":"STATIC",
812 (void*)addr, (void*)spaces[id].base);
814 spaces[id].base = addr;
815 uword_t len = os_vm_page_size * entry->page_count;
816 if (id == DYNAMIC_CORE_SPACE_ID && len > dynamic_space_size) {
817 lose("dynamic space too small for core: %luKiB required, %luKiB available.",
818 (unsigned long)len >> 10,
819 (unsigned long)dynamic_space_size >> 10);
821 #ifdef LISP_FEATURE_RELOCATABLE_STATIC_SPACE
822 if (id == READ_ONLY_CORE_SPACE_ID || id == STATIC_CORE_SPACE_ID) {
823 #else
824 if (id == READ_ONLY_CORE_SPACE_ID) {
825 #endif
826 if (len) // There is no "nominal" size of static or
827 // readonly space, so give them a size
828 spaces[id].desired_size = len;
829 else { // Assign some address, so free_pointer does enclose [0 .. addr+0]
830 if (id == STATIC_CORE_SPACE_ID)
831 lose("Static space size is 0?");
832 READ_ONLY_SPACE_START = READ_ONLY_SPACE_END = addr;
835 if (len != 0) {
836 spaces[id].len = len;
837 size_t request = spaces[id].desired_size;
838 int sub_2gb_flag = (request & 1);
839 request &= ~(size_t)1;
840 // Try to map at address requested by the core file unless ASLR.
841 #ifdef LISP_FEATURE_ASLR
842 addr = 0;
843 #endif
844 addr = (uword_t)reserve_space(id, sub_2gb_flag ? MOVABLE_LOW : MOVABLE,
845 (os_vm_address_t)addr, request);
846 switch (id) {
847 case PERMGEN_CORE_SPACE_ID:
848 PERMGEN_SPACE_START = addr;
849 break;
850 case STATIC_CORE_SPACE_ID:
851 #ifdef LISP_FEATURE_RELOCATABLE_STATIC_SPACE
852 STATIC_SPACE_START = addr;
853 STATIC_SPACE_END = addr + len;
854 #endif
855 break;
856 case READ_ONLY_CORE_SPACE_ID:
857 READ_ONLY_SPACE_START = addr;
858 READ_ONLY_SPACE_END = addr + len;
859 break;
860 #ifdef LISP_FEATURE_IMMOBILE_SPACE
861 case IMMOBILE_FIXEDOBJ_CORE_SPACE_ID:
862 // arm64 does not care where this space is placed - it's not used
863 #ifdef LISP_FEATURE_X86_64
864 if (addr + request > 0x80000000) lose("Won't map immobile space above 2GB");
865 #endif
866 FIXEDOBJ_SPACE_START = addr;
867 break;
868 #endif
869 case IMMOBILE_TEXT_CORE_SPACE_ID:
870 TEXT_SPACE_START = addr;
871 break;
872 case DYNAMIC_CORE_SPACE_ID:
874 uword_t aligned_start = ALIGN_UP(addr, GENCGC_PAGE_BYTES);
875 /* Misalignment can happen only if GC page size exceeds OS page.
876 * Drop one GC page to avoid overrunning the allocated space */
877 if (aligned_start > addr) // not card-aligned
878 dynamic_space_size -= GENCGC_PAGE_BYTES;
879 DYNAMIC_SPACE_START = addr = aligned_start;
880 check_dynamic_space_addr_ok(addr, dynamic_space_size);
882 break;
885 sword_t offset = os_vm_page_size * (1 + entry->data_page);
886 #ifdef LISP_FEATURE_DARWIN_JIT
887 if (id == READ_ONLY_CORE_SPACE_ID)
888 os_protect((os_vm_address_t)addr, len, OS_VM_PROT_WRITE);
889 #endif
890 if (compressed) {
891 inflate_core_bytes(fd, offset + file_offset, (os_vm_address_t)addr, len);
893 else
894 #ifdef LISP_FEATURE_DARWIN_JIT
895 if (id == DYNAMIC_CORE_SPACE_ID || id == STATIC_CODE_CORE_SPACE_ID || id == READ_ONLY_CORE_SPACE_ID) {
896 load_core_bytes_jit(fd, offset + file_offset, (os_vm_address_t)addr, len);
897 } else
898 #endif
900 load_core_bytes(fd, offset + file_offset, (os_vm_address_t)addr, len, id == READ_ONLY_CORE_SPACE_ID);
903 #ifdef LISP_FEATURE_DARWIN_JIT
904 if (id == READ_ONLY_CORE_SPACE_ID)
905 os_protect((os_vm_address_t)addr, len, OS_VM_PROT_READ | OS_VM_PROT_EXECUTE);
906 #endif
907 #ifdef MADV_MERGEABLE
908 if ((merge_core_pages == 1)
909 || ((merge_core_pages == -1) && compressed)) {
910 madvise((void *)addr, len, MADV_MERGEABLE);
912 #endif
914 lispobj *free_pointer = (lispobj *) addr + entry->nwords;
915 switch (id) {
916 default:
917 // text free ptr is already nonzero if Lisp code in executable
918 if (!*spaces[id].pfree_pointer)
919 *spaces[id].pfree_pointer = free_pointer;
920 break;
921 case DYNAMIC_CORE_SPACE_ID:
922 next_free_page = ALIGN_UP(entry->nwords<<WORD_SHIFT, GENCGC_PAGE_BYTES)
923 / GENCGC_PAGE_BYTES;
924 anon_dynamic_space_start = (os_vm_address_t)(addr + len);
926 #ifdef DEBUG_COREPARSE
927 printf("space %d @ %10lx pg=%4d+%4d nwords=%9ld checksum=%lx\n",
928 (int)id, addr, (int)entry->data_page, (int)entry->page_count,
929 entry->nwords, corespace_checksum((void*)addr, entry->nwords));
930 #endif
933 #ifdef LISP_FEATURE_LINKAGE_SPACE
934 if (linkage_table_count) {
935 if (linkage_space == 0)
936 linkage_space = (void*)os_allocate(LISP_LINKAGE_SPACE_SIZE);
937 load_core_bytes(fd, file_offset+
938 (1 + linkage_table_data_page) * os_vm_page_size,
939 (char*)linkage_space,
940 ALIGN_UP(linkage_table_count*N_WORD_BYTES, os_vm_page_size),
943 #endif
945 calc_asm_routine_bounds();
946 struct cons spaceadj = {(lispobj)spaces, (lispobj)adj};
947 set_adjustment(&spaceadj, READ_ONLY_CORE_SPACE_ID, READ_ONLY_SPACE_START);
948 set_adjustment(&spaceadj, DYNAMIC_CORE_SPACE_ID, DYNAMIC_SPACE_START);
949 #ifdef LISP_FEATURE_RELOCATABLE_STATIC_SPACE
950 set_adjustment(&spaceadj, STATIC_CORE_SPACE_ID, STATIC_SPACE_START);
951 #endif
952 #ifdef LISP_FEATURE_PERMGEN
953 set_adjustment(&spaceadj, PERMGEN_CORE_SPACE_ID, PERMGEN_SPACE_START);
954 #endif
955 #ifdef LISP_FEATURE_IMMOBILE_SPACE
956 set_adjustment(&spaceadj, IMMOBILE_FIXEDOBJ_CORE_SPACE_ID, FIXEDOBJ_SPACE_START);
957 if (!apply_pie_relocs(TEXT_SPACE_START
958 - spaces[IMMOBILE_TEXT_CORE_SPACE_ID].base,
959 DYNAMIC_SPACE_START - spaces[DYNAMIC_CORE_SPACE_ID].base,
960 fd))
961 set_adjustment(&spaceadj, IMMOBILE_TEXT_CORE_SPACE_ID, TEXT_SPACE_START);
962 #endif
965 static void sanity_check_loaded_core(lispobj);
967 /** routines for loading a core using the heap organization of gencgc
968 ** or other GC that is compatible with it **/
970 bool gc_allocate_ptes()
972 /* Compute the number of pages needed for the dynamic space.
973 * Dynamic space size should be aligned on page size. */
974 page_table_pages = dynamic_space_size/GENCGC_PAGE_BYTES;
975 gc_assert(dynamic_space_size == npage_bytes(page_table_pages));
977 /* Assert that a cons whose car has MOST-POSITIVE-WORD
978 * can not be considered a valid cons, which is to say, even though
979 * MOST-POSITIVE-WORD seems to satisfy is_lisp_pointer(),
980 * it's OK to use as a filler marker. */
981 if (find_page_index((void*)(uword_t)-1) >= 0)
982 lose("dynamic space too large");
984 /* Default nursery size to 5% of the total dynamic space size,
985 * min 1Mb. */
986 bytes_consed_between_gcs = dynamic_space_size/(os_vm_size_t)20;
987 if (bytes_consed_between_gcs < (1024*1024))
988 bytes_consed_between_gcs = 1024*1024;
990 /* The page_table is allocated using "calloc" to zero-initialize it.
991 * The C library typically implements this efficiently with mmap() if the
992 * size is large enough. To further avoid touching each page structure
993 * until first use, FREE_PAGE_FLAG must be 0, statically asserted here:
995 #if FREE_PAGE_FLAG != 0
996 #error "FREE_PAGE_FLAG is not 0"
997 #endif
999 /* An extra 'struct page' exists at each end of the page table acting as
1000 * a sentinel.
1002 * For for leading sentinel:
1003 * - all fields are zero except that 'gen' has an illegal value
1004 * which makes from_space_p() and new_space_p() both return false
1006 * For the trailing sentinel:
1007 * - all fields are zero which makes page_ends_contiguous_block_p()
1008 * return true for the last in-range page index (so the "illegal"
1009 * index at 1+ appears to start a contiguous block even though
1010 * it corresponds to no page)
1012 page_table = calloc(page_table_pages+2, sizeof(struct page));
1013 gc_assert(page_table);
1014 page_table[0].gen = 9; // an arbitrary never-used value
1015 ++page_table;
1016 gc_page_pins = calloc(page_table_pages, 1);
1017 gc_assert(gc_page_pins);
1018 #ifdef LISP_FEATURE_DARWIN_JIT
1019 page_execp = calloc(page_table_pages, 1);
1020 #endif
1022 // The card table size is a power of 2 at *least* as large
1023 // as the number of cards. These are the default values.
1024 int nbits = 13;
1025 long num_gc_cards = 1L << nbits;
1027 // Sure there's a fancier way to round up to a power-of-2
1028 // but this is executed exactly once, so KISS.
1029 while (num_gc_cards < page_table_pages*CARDS_PER_PAGE) { ++nbits; num_gc_cards <<= 1; }
1030 // 2 Gigacards should suffice for now. That would span 2TiB of memory
1031 // using 1Kb card size, or more if larger card size.
1032 gc_assert(nbits < 32);
1033 // If the space size is less than or equal to the number of cards
1034 // that 'gc_card_table_nbits' cover, we're fine. Otherwise, problem.
1035 // 'nbits' is what we need, 'gc_card_table_nbits' is what the core was compiled for.
1036 int patch_card_index_mask_fixups = 0;
1037 if (nbits > gc_card_table_nbits) {
1038 gc_card_table_nbits = nbits;
1039 // The value needed based on dynamic space size exceeds the value that the
1040 // core was compiled for, so we need to patch all code blobs.
1041 patch_card_index_mask_fixups = 1;
1043 // Regardless of the mask implied by space size, it has to be gc_card_table_nbits wide
1044 // even if that is excessive - when the core is restarted using a _smaller_ dynamic space
1045 // size than saved at - otherwise lisp could overrun the mark table.
1046 num_gc_cards = 1L << gc_card_table_nbits;
1048 gc_card_table_mask = num_gc_cards - 1;
1049 #if defined LISP_FEATURE_SB_SAFEPOINT && defined LISP_FEATURE_X86_64
1050 /* The card table is hardware-page-aligned. Preceding it and occupying a whole
1051 * "backend page" - which by the way is overkill - is the global safepoint trap page.
1052 * The dummy TEST instruction for safepoints encodes shorter this way */
1053 void* result = os_alloc_gc_space(0, MOVABLE, 0,
1054 ALIGN_UP(num_gc_cards, BACKEND_PAGE_BYTES) + BACKEND_PAGE_BYTES);
1055 gc_card_mark = (unsigned char*)result + BACKEND_PAGE_BYTES;
1056 #else
1057 gc_card_mark = successful_malloc(num_gc_cards);
1058 #endif
1060 /* The mark array used to work "by accident" if the numeric value of CARD_MARKED
1061 * is 0 - or equivalently the "WP'ed" state - which is the value that calloc()
1062 * fills with. If using malloc() we have to fill with CARD_MARKED,
1063 * as I discovered when I changed that to a nonzero value */
1064 memset(gc_card_mark, CARD_MARKED, num_gc_cards);
1066 gc_common_init();
1068 /* Initialize the generations. */
1069 int i;
1070 for (i = 0; i < NUM_GENERATIONS; i++) {
1071 struct generation* gen = &generations[i];
1072 gen->bytes_allocated = 0;
1073 gen->gc_trigger = 2000000;
1074 gen->num_gc = 0;
1075 gen->cum_sum_bytes_allocated = 0;
1076 /* the tune-able parameters */
1077 gen->bytes_consed_between_gc
1078 = bytes_consed_between_gcs/(os_vm_size_t)HIGHEST_NORMAL_GENERATION;
1079 gen->number_of_gcs_before_promotion = 1;
1080 gen->minimum_age_before_gc = 0.75;
1083 /* Initialize gc_alloc. */
1084 gc_init_region(mixed_region);
1085 gc_init_region(small_mixed_region);
1086 gc_init_region(boxed_region);
1087 gc_init_region(unboxed_region);
1088 gc_init_region(code_region);
1089 gc_init_region(cons_region);
1090 return patch_card_index_mask_fixups;
1093 extern void gcbarrier_patch_code(void*, int);
1094 // Architectures that lack a method for gcbarrier_patch_code get this dummy stub.
1095 #if !(defined LISP_FEATURE_ARM64 || defined LISP_FEATURE_MIPS || defined LISP_FEATURE_PPC64 \
1096 || defined LISP_FEATURE_X86 || defined LISP_FEATURE_X86_64)
1097 void gcbarrier_patch_code(void* __attribute__((unused)) where, int __attribute__((unused)) nbits)
1100 #endif
1102 static void gengcbarrier_patch_code_range(uword_t start, lispobj* limit)
1104 struct varint_unpacker unpacker;
1105 lispobj *where = next_object((lispobj*)start, 0, limit);
1106 for ( ; where ; where = next_object(where, object_size(where), limit) ) {
1107 struct code* code = (void*)where;
1108 if (widetag_of(where) != CODE_HEADER_WIDETAG || !code->fixups) continue;
1109 varint_unpacker_init(&unpacker, code->fixups);
1110 #if defined LISP_FEATURE_X86 || defined LISP_FEATURE_X86_64
1111 // There are two other data streams preceding the one we want
1112 skip_data_stream(&unpacker);
1113 skip_data_stream(&unpacker);
1114 #endif
1115 char* instructions = code_text_start(code);
1116 int prev_loc = 0, loc;
1117 while (varint_unpack(&unpacker, &loc) && loc != 0) {
1118 loc += prev_loc;
1119 prev_loc = loc;
1120 gcbarrier_patch_code(instructions + loc, gc_card_table_nbits);
1125 #ifdef LISP_FEATURE_DARWIN_JIT
1126 /* Inexplicably, an executable page can generate spurious faults if
1127 * it's not written to after changing its protection flags.
1128 * Touch every page... */
1129 void darwin_jit_code_pages_kludge () {
1130 THREAD_JIT_WP(0);
1131 page_index_t page;
1132 for (page = 0; page < next_free_page; page++) {
1133 if(is_code(page_table[page].type)) {
1134 char* addr = page_address(page);
1135 for (unsigned i = 0; i < GENCGC_PAGE_BYTES; i+=4096) {
1136 volatile char* page_start = addr + i;
1137 page_start[0] = page_start[0];
1141 THREAD_JIT_WP(1);
1143 #endif
1145 /* Read corefile ptes from 'fd' which has already been positioned
1146 * and store into the page table */
1147 void gc_load_corefile_ptes(int card_table_nbits,
1148 core_entry_elt_t n_ptes,
1149 __attribute__((unused)) core_entry_elt_t total_bytes,
1150 os_vm_offset_t offset, int fd,
1151 __attribute__((unused)) struct coreparse_space *spaces,
1152 struct heap_adjust *adj)
1154 if (next_free_page != n_ptes)
1155 lose("n_PTEs=%"PAGE_INDEX_FMT" but expected %"PAGE_INDEX_FMT,
1156 (int)n_ptes, next_free_page);
1158 gc_card_table_nbits = card_table_nbits;
1159 bool patchp = gc_allocate_ptes();
1161 if (LSEEK(fd, offset, SEEK_SET) != offset) lose("failed seek");
1163 #ifdef LISP_FEATURE_MARK_REGION_GC
1164 sword_t bitmapsize = bitmap_size(n_ptes);
1165 if (read(fd, allocation_bitmap, bitmapsize) != bitmapsize)
1166 lose("failed to read allocation bitmap from core");
1167 total_bytes -= bitmapsize;
1168 #endif
1169 gc_assert(ALIGN_UP(n_ptes * sizeof (struct corefile_pte), N_WORD_BYTES)
1170 == (size_t)total_bytes);
1172 char data[8192];
1173 // Process an integral number of ptes on each read.
1174 // Parentheses around sizeof (type) are necessary to suppress a
1175 // clang warning (-Wsizeof-array-div) that we're dividing the array size
1176 // by a divisor that is not the size of one element in that array.
1177 page_index_t max_pages_per_read = sizeof data / (sizeof (struct corefile_pte));
1178 page_index_t page = 0;
1179 generation_index_t gen = CORE_PAGE_GENERATION;
1180 while (page < n_ptes) {
1181 page_index_t pages_remaining = n_ptes - page;
1182 page_index_t npages =
1183 pages_remaining < max_pages_per_read ? pages_remaining : max_pages_per_read;
1184 ssize_t bytes = npages * sizeof (struct corefile_pte);
1185 if (read(fd, data, bytes) != bytes) lose("failed read");
1186 int i;
1187 for ( i = 0 ; i < npages ; ++i, ++page ) {
1188 struct corefile_pte pte;
1189 memcpy(&pte, data+i*sizeof (struct corefile_pte), sizeof pte);
1190 // Low 3 bits of the scan_start hold the 'type' flags.
1191 // Low bit of words_used indicates a large (a/k/a single) object.
1192 char type = ((pte.words_used & 1) ? SINGLE_OBJECT_FLAG : 0)
1193 | (pte.sso & 0x07);
1194 page_table[page].type = type;
1195 pte.words_used &= ~1;
1196 /* It is possible, though rare, for the saved page table
1197 * to contain free pages below alloc_ptr. */
1198 if (type == FREE_PAGE_FLAG) continue;
1199 gc_assert(pte.words_used);
1200 page_table[page].words_used_ = pte.words_used;
1201 set_page_scan_start_offset(page, pte.sso & ~0x07);
1202 page_table[page].gen = gen;
1203 #ifdef LISP_FEATURE_MARK_REGION_GC
1204 if (!page_single_obj_p(page))
1205 for_lines_in_page(l, page) line_bytemap[l] = ENCODE_GEN(gen);
1206 #endif
1207 bytes_allocated += pte.words_used << WORD_SHIFT;
1210 generations[gen].bytes_allocated = bytes_allocated;
1211 gc_assert((ssize_t)bytes_allocated <= (ssize_t)(n_ptes * GENCGC_PAGE_BYTES));
1213 /* Record the demarcation point in permgen space between objects mapped from core
1214 * and new objects so that GC can potentially treat them differently.
1215 * (below it: visit only if touched, above it: always visit) */
1216 permgen_bounds[1] = (uword_t)permgen_space_free_pointer;
1218 // Adjust for discrepancies between actually-allocated space addresses
1219 // and desired addresses.
1220 relocate_heap(adj);
1222 #ifdef LISP_FEATURE_IMMOBILE_SPACE
1223 /* Now determine page characteristics such as object spacing
1224 * (tbh it would be better to output the immobile-space page tables to the core file).
1225 * This used to depend critically on space relocation already having been performed.
1226 * It doesn't any more, but this is an OK time to do it */
1227 extern void immobile_space_coreparse(uword_t,uword_t);
1228 immobile_space_coreparse(spaces[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID].len,
1229 spaces[IMMOBILE_TEXT_CORE_SPACE_ID].len);
1230 calc_immobile_space_bounds();
1231 #endif
1232 #ifdef LISP_FEATURE_X86_64
1233 tune_asm_routines_for_microarch();
1234 #endif
1235 #ifdef LISP_FEATURE_DARWIN_JIT
1236 if (!static_code_space_free_pointer)
1237 static_code_space_free_pointer = (lispobj *)STATIC_CODE_SPACE_START;
1238 #endif
1240 if (patchp) {
1241 gengcbarrier_patch_code_range(READ_ONLY_SPACE_START, read_only_space_free_pointer);
1242 gengcbarrier_patch_code_range(STATIC_SPACE_START, static_space_free_pointer);
1243 gengcbarrier_patch_code_range(DYNAMIC_SPACE_START, (lispobj*)dynamic_space_highwatermark());
1244 gengcbarrier_patch_code_range(TEXT_SPACE_START, text_space_highwatermark);
1247 // Toggle page protection bits as needed. There are essentially two major cases:
1248 // - when soft card marking is used, all cards are "clean" but since that's
1249 // not the default state of the mark bit, we have to set it.
1250 // Additionally, with darwin-jit the mapping type on on pages of code
1251 // needs to change from 'rw-' to 'rwx'
1252 // - when MMU-based marking is used, then all pages except code get
1253 // mprotected; but code pages writes are tracked with soft marking.
1255 if (gen != 0 && ENABLE_PAGE_PROTECTION) {
1256 #ifdef LISP_FEATURE_SOFT_CARD_MARKS
1257 page_index_t p;
1258 for (p = 0; p < next_free_page; ++p)
1259 if (page_words_used(p)) assign_page_card_marks(p, CARD_UNMARKED);
1261 #ifdef LISP_FEATURE_DARWIN_JIT
1262 page_index_t start = 0, end;
1263 while (start < next_free_page) {
1264 if (is_code(page_table[start].type)) {
1265 set_page_executable(start, 1);
1266 for (end = start + 1; end < next_free_page; end++) {
1267 if (!page_words_used(end) || !is_code(page_table[end].type))
1268 break;
1269 set_page_executable(end, 1);
1271 os_protect(page_address(start), npage_bytes(end - start), OS_VM_PROT_ALL);
1272 start = end+1;
1273 continue;
1275 ++start;
1277 #endif
1279 #else
1280 // coreparse can avoid hundreds to thousands of mprotect() calls by
1281 // treating the whole range from the corefile as protectable, except
1282 // that code pages must NOT be subject to mprotect.
1283 // So just watch out for empty pages and code.
1284 // Unboxed pages do not technically need to be mprotected since we don't
1285 // need to track writes, but they are lumped in with other pages for simplicity
1286 // of this loop. Optimistically assume that doing so won't cause too many
1287 // extra page faults if the unboxed pages do get written.
1288 #define non_protectable_page_p(x) !page_words_used(x) || is_code(page_table[x].type)
1289 page_index_t start = 0, end;
1290 // cf. write_protect_generation_pages()
1291 while (start < next_free_page) {
1292 if (non_protectable_page_p(start)) {
1293 ++start;
1294 continue;
1296 SET_PAGE_PROTECTED(start,1);
1297 for (end = start + 1; end < next_free_page; end++) {
1298 if (non_protectable_page_p(end))
1299 break;
1300 SET_PAGE_PROTECTED(end,1);
1302 os_protect(page_address(start), npage_bytes(end - start), OS_VM_PROT_READ);
1303 start = end;
1305 #endif
1308 #ifdef LISP_FEATURE_DARWIN_JIT
1309 darwin_jit_code_pages_kludge();
1310 /* For some reason doing an early pthread_jit_write_protect_np sometimes fails.
1311 Which is weird, because it's done many times in arch_write_linkage_table_entry later.
1312 Adding the executable bit here avoids calling pthread_jit_write_protect_np */
1313 os_protect((os_vm_address_t)STATIC_CODE_SPACE_START, STATIC_CODE_SPACE_SIZE, OS_VM_PROT_ALL);
1314 #endif
1317 static struct coreparse_space*
1318 init_coreparse_spaces(int n, struct coreparse_space* input)
1320 // Indexing of spaces[] by the space ID should conveniently just work,
1321 // so we have to leave an empty row for space ID 0 which doesn't exist.
1322 struct coreparse_space* output =
1323 successful_malloc(sizeof (struct coreparse_space)*(MAX_CORE_SPACE_ID+1));
1324 int i;
1325 for (i=0; i<n; ++i) {
1326 int id = input[i].id;
1327 memcpy(&output[id], &input[i], sizeof (struct coreparse_space));
1329 return output;
1332 /* 'merge_core_pages': Tri-state flag to determine whether we attempt to mark
1333 * pages as targets for virtual memory deduplication via MADV_MERGEABLE.
1334 * 1: Yes
1335 * 0: No
1336 * -1: default, yes for compressed cores, no otherwise.
1338 lispobj
1339 load_core_file(char *file, os_vm_offset_t file_offset, int merge_core_pages)
1341 void *header;
1342 core_entry_elt_t val, *ptr;
1343 os_vm_size_t len, remaining_len, stringlen;
1344 int fd = open_binary(file, O_RDONLY);
1345 ssize_t count;
1346 lispobj initial_function = NIL;
1347 struct heap_adjust adj;
1348 memset(&adj, 0, sizeof adj);
1349 sword_t linkage_table_data_page = -1;
1351 if (fd < 0) {
1352 fprintf(stderr, "could not open file \"%s\"\n", file);
1353 perror("open");
1354 exit(1);
1357 lseek(fd, file_offset, SEEK_SET);
1358 header = calloc(os_vm_page_size, 1);
1360 count = read(fd, header, os_vm_page_size);
1361 if (count < (ssize_t) os_vm_page_size) {
1362 lose("premature end of core file");
1365 ptr = header;
1366 val = *ptr++;
1368 if (val != CORE_MAGIC)
1369 lose("invalid magic number in core: %"OBJ_FMTX" should have been %x",
1370 (lispobj)val, CORE_MAGIC);
1372 struct coreparse_space defined_spaces[] = {
1373 {READ_ONLY_CORE_SPACE_ID, 0, 0, READ_ONLY_SPACE_START, &read_only_space_free_pointer},
1374 {STATIC_CORE_SPACE_ID, 0, 0, STATIC_SPACE_START, &static_space_free_pointer},
1375 #ifdef LISP_FEATURE_PERMGEN
1376 {PERMGEN_CORE_SPACE_ID, PERMGEN_SPACE_SIZE | 1, 0,
1377 PERMGEN_SPACE_START, &permgen_space_free_pointer},
1378 #endif
1379 #ifdef LISP_FEATURE_DARWIN_JIT
1380 {STATIC_CODE_CORE_SPACE_ID, 0, 0, STATIC_CODE_SPACE_START, &static_code_space_free_pointer},
1381 #endif
1382 #ifdef LISP_FEATURE_IMMOBILE_SPACE
1383 {IMMOBILE_FIXEDOBJ_CORE_SPACE_ID, FIXEDOBJ_SPACE_SIZE | 1, 0,
1384 0, &fixedobj_free_pointer},
1385 {IMMOBILE_TEXT_CORE_SPACE_ID, TEXT_SPACE_SIZE, 0, TEXT_SPACE_START,
1386 &text_space_highwatermark},
1387 #else
1388 // Without the immobile-space feature, immobile-text-space is nonetheless valid.
1389 // editcore can put all code there, and then convert the space to an ELF section.
1390 // Unlike static-code-core-space, this space _is_ a root for GC.
1391 {IMMOBILE_TEXT_CORE_SPACE_ID, 0, 0, 0, &text_space_highwatermark},
1392 #endif
1393 {DYNAMIC_CORE_SPACE_ID, dynamic_space_size, 0, 0, 0}
1395 // The initializer ensures that indexing into spaces[] is insensitive
1396 // to the space numbering and the order listed in defined_spaces.
1397 struct coreparse_space* spaces =
1398 init_coreparse_spaces(sizeof defined_spaces/sizeof (struct coreparse_space),
1399 defined_spaces);
1401 for ( ; ; ptr += remaining_len) {
1402 val = *ptr++;
1403 len = *ptr++;
1404 remaining_len = len - 2; /* (-2 to cancel the two ++ operations) */
1405 switch (val) {
1406 case BUILD_ID_CORE_ENTRY_TYPE_CODE:
1407 stringlen = *ptr++;
1408 --remaining_len;
1409 gc_assert(remaining_len * sizeof (core_entry_elt_t) >= stringlen);
1410 if (stringlen+1 != sizeof build_id || memcmp(ptr, build_id, stringlen))
1411 lose("core was built for runtime \"%.*s\" but this is \"%s\"",
1412 (int)stringlen, (char*)ptr, build_id);
1413 break;
1414 case DIRECTORY_CORE_ENTRY_TYPE_CODE:
1415 process_directory(remaining_len / NDIR_ENTRY_LENGTH,
1416 (struct ndir_entry*)ptr,
1417 linkage_table_data_page,
1418 fd, file_offset,
1419 merge_core_pages, spaces, &adj);
1420 break;
1421 case LISP_LINKAGE_SPACE_CORE_ENTRY_TYPE_CODE:
1422 linkage_table_count = ptr[0];
1423 linkage_table_data_page = ptr[1];
1424 if ((elf_linkage_space = (uword_t*)ptr[2]) != 0)
1425 elf_linkage_table_count = linkage_table_count;
1426 break;
1427 case PAGE_TABLE_CORE_ENTRY_TYPE_CODE:
1428 // elements = gencgc-card-table-index-nbits, n-ptes, nbytes, data-page
1429 gc_load_corefile_ptes(ptr[0], ptr[1], ptr[2],
1430 file_offset + (ptr[3] + 1) * os_vm_page_size, fd,
1431 spaces, &adj);
1432 break;
1433 case INITIAL_FUN_CORE_ENTRY_TYPE_CODE:
1434 initial_function = adjust_word(&adj, (lispobj)*ptr);
1435 break;
1436 case END_CORE_ENTRY_TYPE_CODE:
1437 free(header);
1438 close(fd);
1439 #ifdef LISP_FEATURE_SB_THREAD
1440 if ((int)SymbolValue(FREE_TLS_INDEX,0) >= dynamic_values_bytes) {
1441 dynamic_values_bytes = (int)SymbolValue(FREE_TLS_INDEX,0) * 2;
1442 // fprintf(stderr, "NOTE: TLS size increased to %x\n", dynamic_values_bytes);
1444 #else
1445 SYMBOL(FREE_TLS_INDEX)->value = sizeof (struct thread);
1446 #endif
1447 // simple-fun implies cold-init, not a warm core (it would be a closure then)
1448 if (widetag_of(native_pointer(initial_function)) == SIMPLE_FUN_WIDETAG
1449 && !lisp_startup_options.noinform) {
1450 fprintf(stderr, "Initial page table:\n");
1451 extern void print_generation_stats(void);
1452 print_generation_stats();
1454 sanity_check_loaded_core(initial_function);
1455 free(spaces);
1456 return initial_function;
1457 case RUNTIME_OPTIONS_MAGIC: break; // already processed
1458 default:
1459 lose("unknown core header entry: %"OBJ_FMTX, (lispobj)val);
1464 #include "genesis/hash-table.h"
1465 #include "genesis/split-ordered-list.h"
1466 #include "genesis/vector.h"
1467 #include "genesis/cons.h"
1468 char* get_asm_routine_by_name(const char* name, int *index)
1470 struct code* code = (struct code*)asm_routines_start;
1471 #ifdef LISP_FEATURE_DARWIN_JIT
1472 lispobj ht = CONS(code->debug_info)->car;
1473 #else
1474 lispobj ht = code->debug_info;
1475 #endif
1476 if (ht) {
1477 struct vector* table =
1478 VECTOR(((struct hash_table*)native_pointer(ht))->pairs);
1479 lispobj sym;
1480 int i;
1481 // ASSUMPTION: hash-table representation is known (same as in gc-common of course)
1482 for (i=2 ; i < vector_len(table) ; i += 2)
1483 if (lowtag_of(sym = table->data[i]) == OTHER_POINTER_LOWTAG
1484 && widetag_of(&SYMBOL(sym)->header) == SYMBOL_WIDETAG
1485 && !strcmp(name, (char*)(symbol_name(SYMBOL(sym))->data))) {
1486 lispobj value = table->data[i+1];
1487 // value = (start-address . (end-address . index))
1488 if (index)
1489 *index = fixnum_value(CONS(CONS(value)->cdr)->cdr); // take cddr
1490 return code_text_start(code) + fixnum_value(CONS(value)->car);
1492 // Something is wrong if we have a hashtable but find nothing.
1493 fprintf(stderr, "WARNING: get_asm_routine_by_name(%s) failed\n",
1494 name);
1496 if (index) *index = 0;
1497 return NULL;
1500 void asm_routine_poke(const char* routine, int offset, char byte)
1502 char *address = get_asm_routine_by_name(routine, 0);
1503 if (address)
1504 address[offset] = byte;
1507 static void trace_sym(lispobj, struct symbol*, struct grvisit_context*);
1509 #define RECURSE(x) if(is_lisp_pointer(x))graph_visit(ptr,x,context)
1511 /* Despite this being a nice concise expression of a pointer tracing algorithm,
1512 * it turns out to be almost unusable in any sufficiently complicated object graph
1513 * due to stack overflow. The pristine core alone hits a recursion depth of >8000. */
1514 static void graph_visit(lispobj referer, lispobj ptr, struct grvisit_context* context)
1516 #define ILLEGAL_WORD 0xFFFFFFFFDEADBEEF
1517 if (ptr == ILLEGAL_WORD) lose("object %"OBJ_FMTX" contains a garbage word", referer);
1518 if (lowtag_of(ptr) == FUN_POINTER_LOWTAG
1519 && widetag_of((lispobj*)FUNCTION(ptr)) == SIMPLE_FUN_WIDETAG)
1520 ptr = fun_code_tagged(FUNCTION(ptr));
1521 if (hopscotch_get(context->seen, ptr, 0)) return;
1522 if (++context->depth > context->maxdepth) context->maxdepth = context->depth;
1523 // TODO: add rejection function for off-heap objects as part of supplied context
1524 hopscotch_insert(context->seen, ptr, 1);
1525 if (context->action) context->action(ptr, context->data);
1526 lispobj layout, *obj;
1527 sword_t nwords, i;
1528 if (lowtag_of(ptr) == LIST_POINTER_LOWTAG) {
1529 RECURSE(CONS(ptr)->car);
1530 RECURSE(CONS(ptr)->cdr);
1531 } else switch (widetag_of(obj = native_pointer(ptr))) {
1532 case SIMPLE_VECTOR_WIDETAG:
1534 struct vector* v = (void*)obj;
1535 sword_t len = vector_len(v);
1536 for(i=0; i<len; ++i) RECURSE(v->data[i]);
1538 break;
1539 case INSTANCE_WIDETAG:
1540 case FUNCALLABLE_INSTANCE_WIDETAG:
1541 layout = layout_of(obj);
1542 graph_visit(ptr, layout, context);
1543 nwords = headerobj_size(obj);
1544 struct bitmap bitmap = get_layout_bitmap(LAYOUT(layout));
1545 for (i=0; i<(nwords-1); ++i)
1546 if (bitmap_logbitp(i, bitmap)) RECURSE(obj[1+i]);
1547 if (layout && finalizer_node_layout_p(LAYOUT(layout))) {
1548 struct solist_node* node = (void*)obj;
1549 // _node_next might have no lowtag, and so_key never does
1550 if (node->_node_next && !lowtag_of(node->_node_next))
1551 RECURSE(node->_node_next | INSTANCE_POINTER_LOWTAG);
1552 if (node->so_key)
1553 RECURSE(compute_lispobj((lispobj*)node->so_key));
1555 break;
1556 case CODE_HEADER_WIDETAG:
1557 nwords = code_header_words((struct code*)obj);
1558 for(i=2; i<nwords; ++i) RECURSE(obj[i]);
1559 break;
1560 // In all the remaining cases, 'nwords' is the count of payload words
1561 // (following the header), so we iterate up to and including that
1562 // word index. For example, if there are 2 payload words,
1563 // then we scan word indices 1 and 2 off the object base address.
1564 case CLOSURE_WIDETAG:
1565 // We must scan the closure's trampoline word.
1566 graph_visit(ptr, fun_taggedptr_from_self(obj[1]), context);
1567 // Closures can utilize one payload word beyond what the header
1568 // indicates. This is quite sucky and I don't know why I did that.
1569 // However, it is correctly accounted for by SHORT_BOXED_NWORDS
1570 // which gives you the right number of words to scan.
1571 nwords = SHORT_BOXED_NWORDS(*obj);
1572 for(i=2; i<=nwords; ++i) RECURSE(obj[i]);
1573 break;
1574 case SYMBOL_WIDETAG:
1575 trace_sym(ptr, SYMBOL(ptr), context);
1576 break;
1577 case FDEFN_WIDETAG:
1578 RECURSE(((struct fdefn*)obj)->name);
1579 RECURSE(((struct fdefn*)obj)->fun);
1580 RECURSE(decode_fdefn_rawfun((struct fdefn*)obj));
1581 break;
1582 default:
1583 // weak-pointer can be considered an ordinary boxed object.
1584 // the 'next' link looks like a fixnum.
1585 if (!leaf_obj_widetag_p(widetag_of(obj))) {
1586 sword_t size = headerobj_size(obj);
1587 for(i=1; i<size; ++i) RECURSE(obj[i]);
1590 --context->depth;
1593 static void trace_sym(lispobj ptr, struct symbol* sym, struct grvisit_context* context)
1595 RECURSE(decode_symbol_name(sym->name));
1596 RECURSE(sym->value);
1597 RECURSE(sym->info);
1598 RECURSE(sym->fdefn);
1601 /* Caller must provide an uninitialized hopscotch table.
1602 * This function will initialize it and perform a graph visit.
1603 * Caller may subsequently inspect the table and/or visit other objects as
1604 * dictated by thread stacks, etc. Caller may - but need not - provide
1605 * an 'action' to invoke on each object */
1606 struct grvisit_context*
1607 visit_heap_from_static_roots(struct hopscotch_table* reached,
1608 void (*action)(lispobj, void*),
1609 void* data)
1611 hopscotch_create(reached, HOPSCOTCH_HASH_FUN_DEFAULT,
1612 0, // no values
1613 1<<18, /* initial size */
1616 struct grvisit_context* context = malloc(sizeof (struct grvisit_context));
1617 context->seen = reached;
1618 context->action = action;
1619 context->data = data;
1620 context->depth = context->maxdepth = 0;
1621 trace_sym(NIL, SYMBOL(NIL), context);
1622 lispobj* where = (lispobj*)STATIC_SPACE_OBJECTS_START;
1623 lispobj* end = static_space_free_pointer;
1624 while (where<end) {
1625 graph_visit(0, compute_lispobj(where), context);
1626 where += object_size(where);
1628 return context;
1631 // Caution: use at your own risk
1632 #if defined DEBUG_CORE_LOADING && DEBUG_CORE_LOADING
1633 struct visitor {
1634 // one item per value of widetag>>2
1635 // element 0 is for conses, element 64 is for totals.
1636 struct {
1637 int count;
1638 int words;
1639 } headers[65], sv_subtypes[3];
1640 struct hopscotch_table *reached;
1643 static void tally(lispobj ptr, struct visitor* v)
1645 sword_t words;
1646 if (lowtag_of(ptr) == LIST_POINTER_LOWTAG)
1647 ++v->headers[0].count, words = 2;
1648 else {
1649 lispobj* obj = native_pointer(ptr);
1650 lispobj header = *obj;
1651 words = object_size2(obj, header);
1652 int widetag = header_widetag(header);
1653 int header_index = widetag>>2;
1654 ++v->headers[header_index].count;
1655 v->headers[header_index].words += words;
1656 if (widetag == SIMPLE_VECTOR_WIDETAG) {
1657 int subtype = 0;
1658 if (vector_flagp(header, VectorHashing))
1659 subtype = 2;
1660 else if (vector_flagp(header, VectorWeak))
1661 subtype = 1;
1662 ++v->sv_subtypes[subtype].count;
1663 v->sv_subtypes[subtype].words += words;
1668 /* This printing in here is useful, but it's too much to output in make-target-2,
1669 * because genesis dumps a ton of unreachable objects.
1670 * The reason is this: cold-load has no way of knowing if a literal loaded
1671 * from fasl and written to core is really supposed to be consumed by target.
1672 * e.g. if it's a string naming a foreign fixup, who reads that string?
1673 * Answer: The host, but it appears in the cold core as if the target will need it.
1674 * The only way to rectify this defect is just not worth doing - each literal
1675 * would have to be kept only as a host proxy until such time as we actually refer
1676 * to it from another object that is definitely in the cold core, via FOP-LOAD-CODE
1677 * and who know what else. Thus it remains a graph tracing problem in nature,
1678 * which is best left to GC */
1679 static uword_t visit_range(lispobj* where, lispobj* limit, uword_t arg)
1681 struct visitor* v = (struct visitor*)arg;
1682 lispobj* obj = next_object(where, 0, limit);
1683 while (obj) {
1684 if (widetag_of(obj) == FILLER_WIDETAG) {
1685 obj += object_size(obj);
1686 continue;
1688 lispobj ptr = compute_lispobj(obj);
1689 tally(ptr, v);
1690 // Perhaps it's reachable via some path that this slighty-deficient
1691 // tracer is unable to discover. e.g. installed Lisp signal handlers
1692 if (!hopscotch_get(v->reached, ptr, 0)) printf("unreached: %p\n", (void*)ptr);
1693 obj = next_object(obj, object_size(obj), limit);
1695 return 0;
1698 #define count_this_pointer_p(ptr) (find_page_index((void*)ptr) >= 0)
1700 static void sanity_check_loaded_core(lispobj initial_function)
1702 struct visitor v[2];
1703 struct hopscotch_table reached;
1704 memset(v, 0, sizeof v);
1705 // Pass 1: Count objects reachable from known roots.
1706 struct grvisit_context* c
1707 = visit_heap_from_static_roots(&reached, 0, 0);
1708 graph_visit(0, initial_function, c); // initfun is not otherwise reachable
1709 // having computed the reaching graph, tally up the dynamic space objects
1710 int key_index;
1711 lispobj ptr;
1712 for_each_hopscotch_key(key_index, ptr, reached)
1713 if (count_this_pointer_p(ptr)) tally(ptr, &v[0]);
1714 printf("graphvisit.maxdepth=%d\n", c->maxdepth);
1715 free(c);
1716 // Pass 2: Count all heap objects
1717 v[1].reached = &reached;
1718 walk_generation(visit_range, -1, (uword_t)&v[1]);
1720 // Pass 3: Compare
1721 // Start with the conses
1722 v[0].headers[0].words = v[0].headers[0].count * 2;
1723 v[1].headers[0].words = v[1].headers[0].count * 2;
1724 printf("-----------------------------------------------|\n");
1725 printf(" Graph walk | Actual |\n");
1726 printf("----------------------+------------------------|\n");
1727 int i;
1728 for(i=0; i<=64; ++i) {
1729 // print all valid widetags (not unknown) that aren't for immediates,
1730 // but always print if nonzero.
1731 if (v[1].headers[i].count ||
1732 ((strncmp(widetag_names[i], "unk", 3)
1733 && (i != CHARACTER_WIDETAG>>2)
1734 && (i != SIMPLE_FUN_WIDETAG>>2)
1735 && (i != UNBOUND_MARKER_WIDETAG>>2)))) {
1736 int mismatch = v[0].headers[i].count != v[1].headers[i].count;
1737 printf("%8d %11d | %8d %11d | %s%s\n",
1738 v[0].headers[i].count, v[0].headers[i].words,
1739 v[1].headers[i].count, v[1].headers[i].words,
1740 i<64 ? (i ? widetag_names[i] : "cons") : "TOTAL",
1741 mismatch ? " ****" : "");
1742 if (i == SIMPLE_VECTOR_WIDETAG>>2) {
1743 int j;
1744 for(j=1; j <= 2; ++j)
1745 printf("%8d %11d | %8d %11d | %s\n",
1746 v[0].sv_subtypes[j].count, v[0].sv_subtypes[j].words,
1747 v[1].sv_subtypes[j].count, v[1].sv_subtypes[j].words,
1748 j==1 ? "weak" : "hashing");
1751 v[0].headers[64].count += v[0].headers[i].count;
1752 v[1].headers[64].count += v[1].headers[i].count;
1753 v[0].headers[64].words += v[0].headers[i].words;
1754 v[1].headers[64].words += v[1].headers[i].words;
1757 hopscotch_destroy(&reached);
1759 #else
1760 static void sanity_check_loaded_core(lispobj __attribute__((unused)) initial_function) {}
1761 #endif
1763 /* Prepare the array of corefile_ptes for save */
1764 void gc_store_corefile_ptes(struct corefile_pte *ptes)
1766 page_index_t i;
1767 for (i = 0; i < next_free_page; i++) {
1768 /* Thanks to alignment requirements, the two three bits
1769 * are always zero, so we can use them to store the
1770 * allocation type -- region is always closed, so only
1771 * the three low bits of allocation flags matter. */
1772 uword_t word = page_scan_start_offset(i);
1773 gc_assert((word & 0x07) == 0);
1774 ptes[i].sso = word | (0x07 & page_table[i].type);
1775 int used = page_table[i].words_used_;
1776 gc_assert(!(used & 1));
1777 ptes[i].words_used = used | page_single_obj_p(i);