2 * A saved SBCL system is a .core file; the code here helps us accept
3 * such a file as input.
7 * This software is part of the SBCL system. See the README file for
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
27 #include <sys/types.h>
43 #include "graphvisit.h"
44 #include "genesis/instance.h"
45 #include "genesis/symbol.h"
49 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
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
78 open_binary(char *filename
, int mode
)
80 #ifdef LISP_FEATURE_WIN32
84 return open(filename
, mode
);
87 #if defined LISP_FEATURE_LINUX && (defined LISP_FEATURE_X86_64 || defined LISP_FEATURE_ARM64)
89 #elif !defined(ELFCORE)
94 int lisp_code_in_elf() { return 0; }
95 lispobj
* get_alien_linkage_table_initializer() { return 0; }
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
; }
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. */
113 search_for_embedded_core(char *filename
, struct memsize_options
*memsize_options
)
115 extern os_vm_offset_t
search_for_elf_core(int);
117 os_vm_offset_t lispobj_size
= sizeof(lispobj
);
120 if ((fd
= open_binary(filename
, O_RDONLY
)) < 0)
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. */
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
)
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
))
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
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;
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")
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
184 os_commit_memory(addr
, len
);
186 if (-1 == lseek(fd
, offset
, SEEK_SET
))
187 lose("Unable to lseek() on corefile");
190 size_t buf_size
= ZSTD_DStreamInSize();
191 unsigned char* buf
= successful_malloc(buf_size
);
196 ZSTD_outBuffer output
;
197 output
.dst
= (void*)addr
;
201 ZSTD_DStream
*stream
= ZSTD_createDStream();
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. */
210 ssize_t count
= read(fd
, buf
, buf_size
);
212 lose("unable to read core file (errno = %i)", errno
);
215 ret
= ZSTD_decompressStream(stream
, &output
, &input
);
216 if (ZSTD_isError(ret
))
217 lose("ZSTD_decompressStream failed with error: %s",
218 ZSTD_getErrorName(ret
));
221 ZSTD_freeDStream(stream
);
230 } range
[MAX_CORE_SPACE_ID
+1];
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
)
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
;
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
)
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
;
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
{
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
274 lispobj
** pfree_pointer
; // pointer to x_free_pointer
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;
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
;
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
306 # define FIXUP(expr, addr) expr
307 # define FIXUP32(expr, addr) expr
308 # define FIXUP_rel(expr, addr) expr
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
);
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
)
325 for (i
=0;i
<n_words
;++i
) {
326 lispobj word
= where
[i
];
328 if (is_lisp_pointer(word
) && (adjustment
= calc_adjustment(adj
, word
)) != 0) {
329 FIXUP(where
[i
] = word
+ adjustment
, where
+i
);
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.
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
);
362 FIXUP32(UNALIGNED_STORE32(fixup_where
, adjusted
), fixup_where
);
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
);
377 static void fix_space(uword_t start
, lispobj
* end
, struct heap_adjust
* adj
)
381 lispobj layout
, adjusted_layout
;
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
);
395 widetag
= header_widetag(word
);
396 nwords
= sizetab
[widetag
](where
);
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
);
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
);
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
);
429 adjust_pointers(&s
->fdefn
, 4, adj
); // fdefn, value, info, name
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
);
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
;
453 for (i
=code_n_named_calls(code
)-1; i
>=0; --i
)
454 adjust_word_at(fdefns_start
+i
, adj
);
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
);
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
);
470 adjust_pointers(&f
->self
, 1, adj
);
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
),
477 adjust_code_refs(adj
, code
);
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
);
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
);
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);
520 // All the array header widetags.
521 case SIMPLE_ARRAY_WIDETAG
:
522 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
523 case COMPLEX_CHARACTER_STRING_WIDETAG
:
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
:
533 case COMPLEX_RATIONAL_WIDETAG
:
538 if ((delta
= calc_adjustment(adj
, where
[1])) != 0) {
540 "WARNING: SAP at %p -> %p in relocatable core\n",
541 where
, (void*)where
[1]);
542 FIXUP(where
[1] += delta
, where
+1);
546 if (other_immediate_lowtag_p(widetag
) && leaf_obj_widetag_p(widetag
))
549 lose("Unrecognized heap object: @%p: %"OBJ_FMTX
, where
, *where
);
551 adjust_pointers(where
+1, nwords
-1, adj
);
553 #if SHOW_SPACE_RELOCATION
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
);
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
];
579 if (!adj
->n_ranges
) return;
580 if (!lisp_startup_options
.noinform
&& SHOW_SPACE_RELOCATION
) {
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
594 adjust_pointers((void*)(NIL
- LIST_POINTER_LOWTAG
), 1, adj
);
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
);
601 #ifdef LISP_FEATURE_IMMOBILE_SPACE
602 fix_space(FIXEDOBJ_SPACE_START
, fixedobj_free_pointer
, adj
);
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);
611 # define apply_pie_relocs(dummy1,dummy2,dummy3) (0)
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
;
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
;
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
;
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");
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()
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.
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
;
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
;
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
));
690 #ifdef LISP_FEATURE_LINKAGE_SPACE
691 #define LISP_LINKAGE_SPACE_SIZE (1<<(N_LINKAGE_INDEX_BITS+WORD_SHIFT))
694 #if defined LISP_FEATURE_IMMOBILE_SPACE && defined LISP_FEATURE_ARM64
695 #define LISP_LINKAGE_SPACE_SIZE 0
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
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
;
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
;
729 static __attribute__((unused
)) uword_t
corespace_checksum(uword_t
* base
, int nwords
)
733 for (i
= 0; i
<nwords
; ++i
)
734 result
= ((result
<< 1) | (result
>> (N_WORD_BITS
-1))) ^ base
[i
];
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
;
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.
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
);
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
);
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
;
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
;
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
);
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
) {
824 if (id
== READ_ONLY_CORE_SPACE_ID
) {
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
;
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
844 addr
= (uword_t
)reserve_space(id
, sub_2gb_flag
? MOVABLE_LOW
: MOVABLE
,
845 (os_vm_address_t
)addr
, request
);
847 case PERMGEN_CORE_SPACE_ID
:
848 PERMGEN_SPACE_START
= addr
;
850 case STATIC_CORE_SPACE_ID
:
851 #ifdef LISP_FEATURE_RELOCATABLE_STATIC_SPACE
852 STATIC_SPACE_START
= addr
;
853 STATIC_SPACE_END
= addr
+ len
;
856 case READ_ONLY_CORE_SPACE_ID
:
857 READ_ONLY_SPACE_START
= addr
;
858 READ_ONLY_SPACE_END
= addr
+ len
;
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");
866 FIXEDOBJ_SPACE_START
= addr
;
869 case IMMOBILE_TEXT_CORE_SPACE_ID
:
870 TEXT_SPACE_START
= addr
;
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
);
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
);
891 inflate_core_bytes(fd
, offset
+ file_offset
, (os_vm_address_t
)addr
, len
);
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
);
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
);
907 #ifdef MADV_MERGEABLE
908 if ((merge_core_pages
== 1)
909 || ((merge_core_pages
== -1) && compressed
)) {
910 madvise((void *)addr
, len
, MADV_MERGEABLE
);
914 lispobj
*free_pointer
= (lispobj
*) addr
+ entry
->nwords
;
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
;
921 case DYNAMIC_CORE_SPACE_ID
:
922 next_free_page
= ALIGN_UP(entry
->nwords
<<WORD_SHIFT
, 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
));
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
),
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
);
952 #ifdef LISP_FEATURE_PERMGEN
953 set_adjustment(&spaceadj
, PERMGEN_CORE_SPACE_ID
, PERMGEN_SPACE_START
);
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
,
961 set_adjustment(&spaceadj
, IMMOBILE_TEXT_CORE_SPACE_ID
, TEXT_SPACE_START
);
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,
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"
999 /* An extra 'struct page' exists at each end of the page table acting as
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
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);
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.
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
;
1057 gc_card_mark
= successful_malloc(num_gc_cards
);
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
);
1068 /* Initialize the generations. */
1070 for (i
= 0; i
< NUM_GENERATIONS
; i
++) {
1071 struct generation
* gen
= &generations
[i
];
1072 gen
->bytes_allocated
= 0;
1073 gen
->gc_trigger
= 2000000;
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
)
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
);
1115 char* instructions
= code_text_start(code
);
1116 int prev_loc
= 0, loc
;
1117 while (varint_unpack(&unpacker
, &loc
) && loc
!= 0) {
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 () {
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];
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
;
1169 gc_assert(ALIGN_UP(n_ptes
* sizeof (struct corefile_pte
), N_WORD_BYTES
)
1170 == (size_t)total_bytes
);
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");
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)
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
);
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.
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();
1232 #ifdef LISP_FEATURE_X86_64
1233 tune_asm_routines_for_microarch();
1235 #ifdef LISP_FEATURE_DARWIN_JIT
1236 if (!static_code_space_free_pointer
)
1237 static_code_space_free_pointer
= (lispobj
*)STATIC_CODE_SPACE_START
;
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
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
))
1269 set_page_executable(end
, 1);
1271 os_protect(page_address(start
), npage_bytes(end
- start
), OS_VM_PROT_ALL
);
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
)) {
1296 SET_PAGE_PROTECTED(start
,1);
1297 for (end
= start
+ 1; end
< next_free_page
; end
++) {
1298 if (non_protectable_page_p(end
))
1300 SET_PAGE_PROTECTED(end
,1);
1302 os_protect(page_address(start
), npage_bytes(end
- start
), OS_VM_PROT_READ
);
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
);
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));
1325 for (i
=0; i
<n
; ++i
) {
1326 int id
= input
[i
].id
;
1327 memcpy(&output
[id
], &input
[i
], sizeof (struct coreparse_space
));
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.
1336 * -1: default, yes for compressed cores, no otherwise.
1339 load_core_file(char *file
, os_vm_offset_t file_offset
, int merge_core_pages
)
1342 core_entry_elt_t val
, *ptr
;
1343 os_vm_size_t len
, remaining_len
, stringlen
;
1344 int fd
= open_binary(file
, O_RDONLY
);
1346 lispobj initial_function
= NIL
;
1347 struct heap_adjust adj
;
1348 memset(&adj
, 0, sizeof adj
);
1349 sword_t linkage_table_data_page
= -1;
1352 fprintf(stderr
, "could not open file \"%s\"\n", file
);
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");
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
},
1379 #ifdef LISP_FEATURE_DARWIN_JIT
1380 {STATIC_CODE_CORE_SPACE_ID
, 0, 0, STATIC_CODE_SPACE_START
, &static_code_space_free_pointer
},
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
},
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
},
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
),
1401 for ( ; ; ptr
+= remaining_len
) {
1404 remaining_len
= len
- 2; /* (-2 to cancel the two ++ operations) */
1406 case BUILD_ID_CORE_ENTRY_TYPE_CODE
:
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
);
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
,
1419 merge_core_pages
, spaces
, &adj
);
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
;
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
,
1433 case INITIAL_FUN_CORE_ENTRY_TYPE_CODE
:
1434 initial_function
= adjust_word(&adj
, (lispobj
)*ptr
);
1436 case END_CORE_ENTRY_TYPE_CODE
:
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);
1445 SYMBOL(FREE_TLS_INDEX
)->value
= sizeof (struct thread
);
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
);
1456 return initial_function
;
1457 case RUNTIME_OPTIONS_MAGIC
: break; // already processed
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
;
1474 lispobj ht
= code
->debug_info
;
1477 struct vector
* table
=
1478 VECTOR(((struct hash_table
*)native_pointer(ht
))->pairs
);
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))
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",
1496 if (index
) *index
= 0;
1500 void asm_routine_poke(const char* routine
, int offset
, char byte
)
1502 char *address
= get_asm_routine_by_name(routine
, 0);
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
;
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
]);
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
);
1553 RECURSE(compute_lispobj((lispobj
*)node
->so_key
));
1556 case CODE_HEADER_WIDETAG
:
1557 nwords
= code_header_words((struct code
*)obj
);
1558 for(i
=2; i
<nwords
; ++i
) RECURSE(obj
[i
]);
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
]);
1574 case SYMBOL_WIDETAG
:
1575 trace_sym(ptr
, SYMBOL(ptr
), context
);
1578 RECURSE(((struct fdefn
*)obj
)->name
);
1579 RECURSE(((struct fdefn
*)obj
)->fun
);
1580 RECURSE(decode_fdefn_rawfun((struct fdefn
*)obj
));
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
]);
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
);
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*),
1611 hopscotch_create(reached
, HOPSCOTCH_HASH_FUN_DEFAULT
,
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
;
1625 graph_visit(0, compute_lispobj(where
), context
);
1626 where
+= object_size(where
);
1631 // Caution: use at your own risk
1632 #if defined DEBUG_CORE_LOADING && DEBUG_CORE_LOADING
1634 // one item per value of widetag>>2
1635 // element 0 is for conses, element 64 is for totals.
1639 } headers
[65], sv_subtypes
[3];
1640 struct hopscotch_table
*reached
;
1643 static void tally(lispobj ptr
, struct visitor
* v
)
1646 if (lowtag_of(ptr
) == LIST_POINTER_LOWTAG
)
1647 ++v
->headers
[0].count
, words
= 2;
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
) {
1658 if (vector_flagp(header
, VectorHashing
))
1660 else if (vector_flagp(header
, VectorWeak
))
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
);
1684 if (widetag_of(obj
) == FILLER_WIDETAG
) {
1685 obj
+= object_size(obj
);
1688 lispobj ptr
= compute_lispobj(obj
);
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
);
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
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
);
1716 // Pass 2: Count all heap objects
1717 v
[1].reached
= &reached
;
1718 walk_generation(visit_range
, -1, (uword_t
)&v
[1]);
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");
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) {
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
);
1760 static void sanity_check_loaded_core(lispobj
__attribute__((unused
)) initial_function
) {}
1763 /* Prepare the array of corefile_ptes for save */
1764 void gc_store_corefile_ptes(struct corefile_pte
*ptes
)
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
);