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.
19 #ifndef LISP_FEATURE_WIN32
20 #ifdef LISP_FEATURE_LINUX
34 #include <sys/types.h>
48 #include "gc-internal.h"
49 #include "runtime-options.h"
50 #include "pseudo-atomic.h"
54 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
58 unsigned char build_id
[] =
59 // The suffix added to build-id indicates which flavor of C compiler was used.
60 // This enforces that when you put :MSAN in your Lisp features, you don't
61 // omit "-fsanitize=memory -DMEMORY_SANITIZE" from CFLAGS and LINKFLAGS.
62 // (Some Lisp features affect C flags, but not this one.)
63 // It is important for out-of-tree builds: once they work, you can produce
64 // two trees of artifacts from identical sources *including* the build-id.inc
65 // (but not including "local-target-features.lisp-expr"), and end up with two
66 // Lisp cores and two C runtimes. The extra suffix avoids accidental mismatch.
67 #include "../../output/build-id.inc"
68 #ifdef MEMORY_SANITIZER
74 open_binary(char *filename
, int mode
)
76 #ifdef LISP_FEATURE_WIN32
80 return open(filename
, mode
);
84 static struct runtime_options
*
85 read_runtime_options(int fd
)
87 os_vm_size_t optarray
[RUNTIME_OPTIONS_WORDS
];
88 struct runtime_options
*options
= NULL
;
90 if (read(fd
, optarray
, RUNTIME_OPTIONS_WORDS
* sizeof(os_vm_size_t
)) !=
91 RUNTIME_OPTIONS_WORDS
* sizeof(size_t)) {
95 if ((RUNTIME_OPTIONS_MAGIC
!= optarray
[0]) || (0 == optarray
[1])) {
99 options
= successful_malloc(sizeof(struct runtime_options
));
101 options
->dynamic_space_size
= optarray
[2];
102 options
->thread_control_stack_size
= optarray
[3];
108 maybe_initialize_runtime_options(int fd
)
110 struct runtime_options
*new_runtime_options
;
111 off_t end_offset
= sizeof(lispobj
) +
112 sizeof(os_vm_offset_t
) +
113 (RUNTIME_OPTIONS_WORDS
* sizeof(size_t));
115 lseek(fd
, -end_offset
, SEEK_END
);
117 if ((new_runtime_options
= read_runtime_options(fd
))) {
118 runtime_options
= new_runtime_options
;
122 /* Search 'filename' for an embedded core. An SBCL core has, at the
123 * end of the file, a trailer containing optional saved runtime
124 * options, the start of the core (an os_vm_offset_t), and a final
125 * signature word (the lispobj CORE_MAGIC). If this trailer is found
126 * at the end of the file, the start of the core can be determined
127 * from the core size.
129 * If an embedded core is present, this returns the offset into the
130 * file to load the core from, or -1 if no core is present. */
132 search_for_embedded_core(char *filename
)
135 os_vm_offset_t lispobj_size
= sizeof(lispobj
);
136 os_vm_offset_t trailer_size
= lispobj_size
+ sizeof(os_vm_offset_t
);
137 os_vm_offset_t core_start
, pos
;
140 if ((fd
= open_binary(filename
, O_RDONLY
)) < 0)
143 if (read(fd
, &header
, (size_t)lispobj_size
) < lispobj_size
)
145 if (header
== CORE_MAGIC
) {
146 /* This file is a real core, not an embedded core. Return 0 to
147 * indicate where the core starts, and do not look for runtime
148 * options in this case. */
152 if (lseek(fd
, -lispobj_size
, SEEK_END
) < 0)
154 if (read(fd
, &header
, (size_t)lispobj_size
) < lispobj_size
)
157 if (header
== CORE_MAGIC
) {
158 if (lseek(fd
, -trailer_size
, SEEK_END
) < 0)
160 if (read(fd
, &core_start
, sizeof(os_vm_offset_t
)) < 0)
163 if (lseek(fd
, core_start
, SEEK_SET
) < 0)
165 pos
= lseek(fd
, 0, SEEK_CUR
);
167 if (read(fd
, &header
, (size_t)lispobj_size
) < lispobj_size
)
170 if (header
!= CORE_MAGIC
)
173 maybe_initialize_runtime_options(fd
);
186 #ifndef LISP_FEATURE_HPUX
187 #define load_core_bytes(fd, where, addr, len) os_map(fd, where, addr, len)
189 #define load_core_bytes(fd, where, addr, len) copy_core_bytes(fd, where, addr, len)
190 /* If more platforms don't support overlapping mmap rename this
191 * def to something like ifdef nommapoverlap */
192 /* currently hpux only */
193 static void copy_core_bytes(int fd
, os_vm_offset_t offset
,
194 os_vm_address_t addr
, int len
)
196 unsigned char buf
[4096];
198 int old_fd
= lseek(fd
, 0, SEEK_CUR
);
201 fprintf(stderr
, "cant copy a slice of core because slice-length is not of page size(4096)\n");
205 fprintf(stderr
, "cant perform lseek() on corefile\n");
207 lseek(fd
, offset
, SEEK_SET
);
209 fprintf(stderr
, "cant perform lseek(%u,%lu,SEEK_SET) on corefile\n", fd
, offset
);
211 for(x
= 0; x
< len
; x
+= 4096){
212 c
= read(fd
, buf
, 4096);
214 fprintf(stderr
, "cant read memory area from corefile at position %lu, got %d\n", offset
+ x
, c
);
217 memcpy(addr
+x
, buf
, 4096);
219 os_flush_icache(addr
, len
);
223 #ifndef LISP_FEATURE_SB_CORE_COMPRESSION
224 # define inflate_core_bytes(fd,offset,addr,len) \
225 lose("This runtime was not built with zlib-compressed core support... aborting\n")
227 # define ZLIB_BUFFER_SIZE (1u<<16)
228 static void inflate_core_bytes(int fd
, os_vm_offset_t offset
,
229 os_vm_address_t addr
, int len
)
232 unsigned char* buf
= successful_malloc(ZLIB_BUFFER_SIZE
);
235 # ifdef LISP_FEATURE_WIN32
236 /* Ensure the memory is committed so zlib doesn't segfault trying to
238 os_validate_recommit(addr
, len
);
241 if (-1 == lseek(fd
, offset
, SEEK_SET
)) {
242 lose("Unable to lseek() on corefile\n");
245 stream
.zalloc
= NULL
;
247 stream
.opaque
= NULL
;
249 stream
.next_in
= buf
;
251 ret
= inflateInit(&stream
);
253 lose("zlib error %i\n", ret
);
255 stream
.next_out
= (void*)addr
;
256 stream
.avail_out
= len
;
258 ssize_t count
= read(fd
, buf
, ZLIB_BUFFER_SIZE
);
260 lose("unable to read core file (errno = %i)\n", errno
);
261 stream
.next_in
= buf
;
262 stream
.avail_in
= count
;
263 if (count
== 0) break;
264 ret
= inflate(&stream
, Z_NO_FLUSH
);
269 if (stream
.avail_out
== 0)
270 lose("Runaway gzipped core directory... aborting\n");
271 if (stream
.avail_in
> 0)
272 lose("zlib inflate returned without fully"
273 "using up input buffer... aborting\n");
276 lose("zlib inflate error: %i\n", ret
);
279 } while (ret
!= Z_STREAM_END
);
281 if (stream
.avail_out
> 0) {
282 if (stream
.avail_out
>= os_vm_page_size
)
283 fprintf(stderr
, "Warning: gzipped core directory significantly"
284 "shorter than expected (%lu bytes)", (unsigned long)stream
.avail_out
);
285 /* Is this needed? */
286 memset(stream
.next_out
, 0, stream
.avail_out
);
292 # undef ZLIB_BUFFER_SIZE
296 /* range[0] is immobile space, range [1] is dynamic space */
303 #ifndef LISP_FEATURE_RELOCATABLE_HEAP
304 #define adjust_word(ignore,thing) thing
305 #define relocate_heap(ignore)
307 #include "genesis/gc-tables.h"
308 #include "genesis/hash-table.h"
309 #include "genesis/layout.h"
310 #include "genesis/vector.h"
312 static inline sword_t
calc_adjustment(struct heap_adjust
* adj
, lispobj x
)
314 #ifdef LISP_FEATURE_IMMOBILE_SPACE
315 if (adj
->range
[0].start
<= x
&& x
< adj
->range
[0].end
)
316 return adj
->range
[0].delta
;
318 if (adj
->range
[1].start
<= x
&& x
< adj
->range
[1].end
)
319 return adj
->range
[1].delta
;
323 // Return the adjusted value of 'word' without testing whether it looks
324 // like a pointer. But do test whether it points to a relocatable space.
325 static inline lispobj
adjust_word(struct heap_adjust
* adj
, lispobj word
) {
326 return word
+ calc_adjustment(adj
, word
);
329 // Adjust the words in range [where,where+n_words)
330 // skipping any words that have non-pointer nature.
331 static void adjust_pointers(lispobj
*where
, sword_t n_words
, struct heap_adjust
* adj
)
334 for (i
=0;i
<n_words
;++i
) {
335 lispobj word
= where
[i
];
337 if (is_lisp_pointer(word
) && (adjustment
= calc_adjustment(adj
, word
)) != 0) {
338 where
[i
] += adjustment
;
344 #include "unaligned.h"
345 static void __attribute__((unused
))
346 adjust_code_refs(struct heap_adjust
* adj
, lispobj fixups
, struct code
* code
)
348 struct varint_unpacker unpacker
;
349 varint_unpacker_init(&unpacker
, fixups
);
350 char* instructions
= (char*)((lispobj
*)code
+ code_header_words(code
->header
));
351 int prev_loc
= 0, loc
;
352 while (varint_unpack(&unpacker
, &loc
) && loc
!= 0) {
353 // For extra compactness, each loc is relative to the prior,
354 // so that the magnitudes are smaller.
357 int* fixup_where
= (int*)(instructions
+ loc
);
358 lispobj ptr
= UNALIGNED_LOAD32(fixup_where
);
359 UNALIGNED_STORE32(fixup_where
, ptr
+ calc_adjustment(adj
, ptr
));
363 #if defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER) && defined(LISP_FEATURE_64_BIT)
364 #define FIX_FUN_HEADER_LAYOUT(fun) \
365 set_function_layout(fun, adjust_word(adj, function_layout(fun)))
367 #define FIX_FUN_HEADER_LAYOUT(f) {}
370 static void relocate_space(uword_t start
, lispobj
* end
, struct heap_adjust
* adj
)
372 lispobj
*where
= (lispobj
*)start
;
376 lispobj layout
, adjusted_layout
, bitmap
;
380 for ( ; where
< end
; where
+= nwords
) {
381 header_word
= *where
;
382 if (is_cons_half(header_word
)) {
383 adjust_pointers(where
, 2, adj
);
387 widetag
= widetag_of(header_word
);
388 nwords
= sizetab
[widetag
](where
);
390 case FUNCALLABLE_INSTANCE_WIDETAG
:
391 // Special note on the word at where[1] in funcallable instances:
392 // - If no immobile code, then the word points to read-only space,
393 /// hence needs no adjustment.
394 // - Otherwise, the word might point to a relocated range,
395 // either the instance itself, or a trampoline in immobile space.
396 where
[1] = adjust_word(adj
, where
[1]);
397 case INSTANCE_WIDETAG
:
398 layout
= (widetag
== FUNCALLABLE_INSTANCE_WIDETAG
) ?
399 funinstance_layout(where
) : instance_layout(where
);
400 adjusted_layout
= adjust_word(adj
, layout
);
401 // Do not alter the layout as stored in the instance if non-compact
402 // header. instance_scan() will do it if necessary.
403 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
404 if (adjusted_layout
!= layout
)
405 instance_layout(where
) = adjusted_layout
;
407 bitmap
= LAYOUT(adjusted_layout
)->bitmap
;
408 gc_assert(fixnump(bitmap
)
409 || widetag_of(*native_pointer(bitmap
))==BIGNUM_WIDETAG
);
410 // If the post-adjustment address of 'layout' is higher than 'where',
411 // then the layout's pointer slots need adjusting.
412 // This is true regardless of whether the core was mapped at a higher
413 // or lower address than desired.
414 if (is_lisp_pointer(bitmap
) && adjusted_layout
> (lispobj
)where
) {
415 // Do not write back the adjusted bitmap pointer. Each heap word
416 // must be touched at most once. When the layout itself gets scanned,
417 // the bitmap slot will be rewritten if needed.
418 bitmap
= adjust_word(adj
, bitmap
);
421 instance_scan((void(*)(lispobj
*,sword_t
,uword_t
))adjust_pointers
,
422 where
+1, nwords
-1, bitmap
, (uintptr_t)adj
);
425 adjust_pointers(where
+1, 2, adj
);
426 // 'raw_addr' doesn't satisfy is_lisp_pointer() for x86,
427 // so adjust_pointers() would ignore it. Therefore we need to
428 // forcibly adjust it.
429 #ifndef LISP_FEATURE_IMMOBILE_CODE
430 where
[3] = adjust_word(adj
, where
[3]);
431 #elif defined(LISP_FEATURE_X86_64)
432 // static space to immobile space JMP needs adjustment
433 if (STATIC_SPACE_START
<= (uintptr_t)where
&& (uintptr_t)where
< STATIC_SPACE_END
) {
434 delta
= calc_adjustment(adj
, fdefn_callee_lispobj((struct fdefn
*)where
));
436 *(int*)(1+(char*)(where
+3)) += delta
;
440 case CODE_HEADER_WIDETAG
:
441 // Fixup the constant pool. The word at where+1 is a fixnum.
442 adjust_pointers(where
+2, code_header_words(header_word
)-2, adj
);
443 // Fixup all embedded simple-funs
444 code
= (struct code
*)where
;
445 for_each_simple_fun(i
, f
, code
, 1, {
446 FIX_FUN_HEADER_LAYOUT((lispobj
*)f
);
447 f
->self
= adjust_word(adj
, f
->self
);
448 adjust_pointers(SIMPLE_FUN_SCAV_START(f
), SIMPLE_FUN_SCAV_NWORDS(f
), adj
);
450 // Compute the address where the code "was" as the first argument
451 // by negating the adjustment for 'where'.
452 // Can't call calc_adjustment to get the negative of the adjustment!
453 gencgc_apply_code_fixups((struct code
*)((char*)where
- adj
->range
[1].delta
),
455 #ifdef LISP_FEATURE_IMMOBILE_SPACE
456 // Now that the packed integer comprising the list of fixup locations
457 // has been fixed-up (if necessary), apply them to the code.
458 if (code
->fixups
!= 0)
459 adjust_code_refs(adj
, code
->fixups
, code
);
462 case CLOSURE_WIDETAG
:
463 FIX_FUN_HEADER_LAYOUT(where
);
464 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
465 // For x86[-64], the closure fun appears to be a fixnum,
466 // and might need adjustment unless pointing to immobile code.
467 // Then fall into the general case; where[1] won't get re-adjusted
468 // because it doesn't satisfy is_lisp_pointer().
469 where
[1] = adjust_word(adj
, where
[1]);
472 // Vectors require extra care because of EQ-based hashing.
473 case SIMPLE_VECTOR_WIDETAG
:
474 if (is_vector_subtype(*where
, VectorValidHashing
)) {
475 struct vector
* v
= (struct vector
*)where
;
476 gc_assert(v
->length
> 0 &&
477 !(v
->length
& make_fixnum(1)) && // length must be even
478 lowtag_of(v
->data
[0]) == INSTANCE_POINTER_LOWTAG
);
479 lispobj
* data
= (lispobj
*)v
->data
;
480 adjust_pointers(&data
[0], 1, adj
); // adjust the hash-table structure
481 boolean needs_rehash
= 0;
483 // Adjust the elements, checking for need to rehash.
484 // v->data[1] is the unbound marker (a non-pointer)
485 for (i
= fixnum_value(v
->length
)-1 ; i
>=2 ; --i
) {
486 lispobj ptr
= data
[i
];
487 if (is_lisp_pointer(ptr
) && (delta
= calc_adjustment(adj
, ptr
)) != 0) {
493 data
[1] = make_fixnum(1);
496 // All the array header widetags.
497 case SIMPLE_ARRAY_WIDETAG
:
498 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
499 case COMPLEX_CHARACTER_STRING_WIDETAG
:
501 case COMPLEX_BASE_STRING_WIDETAG
:
502 case COMPLEX_VECTOR_NIL_WIDETAG
:
503 case COMPLEX_BIT_VECTOR_WIDETAG
:
504 case COMPLEX_VECTOR_WIDETAG
:
505 case COMPLEX_ARRAY_WIDETAG
:
506 // And the rest of the purely descriptor objects.
508 case VALUE_CELL_WIDETAG
:
509 case WEAK_POINTER_WIDETAG
:
511 case COMPLEX_WIDETAG
:
516 if ((delta
= calc_adjustment(adj
, where
[1])) != 0) {
518 "WARNING: SAP at %p -> %p in relocatable core\n",
519 where
, (void*)where
[1]);
524 #ifndef LISP_FEATURE_64_BIT
525 case SINGLE_FLOAT_WIDETAG
:
527 case DOUBLE_FLOAT_WIDETAG
:
528 case COMPLEX_SINGLE_FLOAT_WIDETAG
:
529 case COMPLEX_DOUBLE_FLOAT_WIDETAG
:
530 #ifdef SIMD_PACK_WIDETAG
531 case SIMD_PACK_WIDETAG
:
535 if (other_immediate_lowtag_p(widetag
)
536 && specialized_vector_widetag_p(widetag
))
539 lose("Unrecognized heap object: @%p: %lx\n", where
, header_word
);
541 adjust_pointers(where
+1, nwords
-1, adj
);
545 #define SHOW_SPACE_RELOCATION 0
546 void relocate_heap(struct heap_adjust
* adj
)
548 if (SHOW_SPACE_RELOCATION
) {
549 #ifdef LISP_FEATURE_IMMOBILE_SPACE
550 fprintf(stderr
, "Relocating immobile space from [%p:%p] to [%p:%p]\n",
551 (char*)adj
->range
[0].start
,
552 (char*)adj
->range
[0].end
,
553 (char*)FIXEDOBJ_SPACE_START
,
554 (char*)FIXEDOBJ_SPACE_START
+(adj
->range
[0].end
-adj
->range
[0].start
));
556 fprintf(stderr
, "Relocating dynamic space from [%p:%p] to [%p:%p]\n",
557 (char*)adj
->range
[1].start
,
558 (char*)adj
->range
[1].end
,
559 (char*)DYNAMIC_SPACE_START
,
560 (char*)DYNAMIC_SPACE_START
+(adj
->range
[1].end
-adj
->range
[1].start
));
562 relocate_space(STATIC_SPACE_START
, static_space_free_pointer
, adj
);
563 #ifdef LISP_FEATURE_IMMOBILE_SPACE
564 relocate_space(FIXEDOBJ_SPACE_START
, fixedobj_free_pointer
, adj
);
565 relocate_space(VARYOBJ_SPACE_START
, varyobj_free_pointer
, adj
);
566 SYMBOL(FUNCTION_LAYOUT
)->value
= \
567 adjust_word(adj
, SYMBOL(FUNCTION_LAYOUT
)->value
>> 32) << 32;
569 relocate_space(DYNAMIC_SPACE_START
, (lispobj
*)get_alloc_pointer(), adj
);
570 lispobj asmroutines
= SYMBOL(ASSEMBLER_ROUTINES
)->value
;
571 if (lowtag_of(asmroutines
) == INSTANCE_POINTER_LOWTAG
) {
572 /* Adjust the values in SB-FASL::*ASSEMBLER-ROUTINES*.
573 * No need to frob the 'needs_rehash_p' slot on account of this */
574 struct hash_table
*ht
= (struct hash_table
*)native_pointer(asmroutines
);
575 struct vector
*table
= (struct vector
*)native_pointer(ht
->table
);
577 for (i
=fixnum_value(table
->length
)-1; i
>=3; i
-= 2) {
578 if (fixnump(table
->data
[i
]))
579 table
->data
[i
] = make_fixnum(adjust_word(adj
, fixnum_value(table
->data
[i
])));
585 int merge_core_pages
= -1;
588 process_directory(int count
, struct ndir_entry
*entry
,
589 int fd
, os_vm_offset_t file_offset
,
590 struct heap_adjust
* adj
)
592 extern void immobile_space_coreparse(uword_t
,uword_t
);
595 uword_t len
; // length in bytes, as an integral multiple of os_vm_page_size
597 lispobj
** pfree_pointer
; // pointer to x_free_pointer
598 } spaces
[MAX_CORE_SPACE_ID
+1] = {
599 {0, 0, 0}, // blank for space ID 0
600 #ifdef LISP_FEATURE_GENCGC
601 {0, DYNAMIC_SPACE_START
, 0},
605 // This order is determined by constants in compiler/generic/genesis
606 {0, STATIC_SPACE_START
, &static_space_free_pointer
},
607 {0, READ_ONLY_SPACE_START
, &read_only_space_free_pointer
},
608 #ifdef LISP_FEATURE_IMMOBILE_SPACE
609 {0, FIXEDOBJ_SPACE_START
, &fixedobj_free_pointer
},
610 {0, VARYOBJ_SPACE_START
, &varyobj_free_pointer
}
614 for ( ; --count
>= 0; ++entry
) {
615 sword_t id
= entry
->identifier
;
616 uword_t addr
= (1024 * entry
->address
); // multiplier as per core.h
617 int compressed
= id
& DEFLATED_CORE_SPACE_ID_FLAG
;
619 if (id
< 1 || id
> MAX_CORE_SPACE_ID
)
620 lose("unknown space ID %ld addr %p\n", id
, addr
);
622 #ifndef LISP_FEATURE_RELOCATABLE_HEAP
623 int enforce_address
= 1;
624 #elif defined(LISP_FEATURE_IMMOBILE_SPACE)
625 // Enforce address of readonly, static, immobile varyobj
626 int enforce_address
= id
!= DYNAMIC_CORE_SPACE_ID
627 && id
!= IMMOBILE_FIXEDOBJ_CORE_SPACE_ID
;
629 // Enforce address of readonly and static spaces.
630 int enforce_address
= id
!= DYNAMIC_CORE_SPACE_ID
;
632 if (enforce_address
) {
634 #ifdef LISP_FEATURE_CHENEYGC
635 if (id
== DYNAMIC_CORE_SPACE_ID
) {
636 if ((fail
= (addr
!= DYNAMIC_0_SPACE_START
) &&
637 (addr
!= DYNAMIC_1_SPACE_START
)) != 0)
638 fprintf(stderr
, "in core: %p; in runtime: %p or %p\n",
640 (void*)DYNAMIC_0_SPACE_START
,
641 (void*)DYNAMIC_1_SPACE_START
);
644 if ((fail
= (addr
!= spaces
[id
].base
)) != 0)
645 fprintf(stderr
, "in core: %p; in runtime: %p\n",
646 (void*)addr
, (void*)spaces
[id
].base
);
648 "DYNAMIC", "STATIC", "READ_ONLY", "IMMOBILE", "IMMOBILE"
651 lose("core/runtime address mismatch: %s_SPACE_START", names
[id
-1]);
653 spaces
[id
].base
= addr
;
654 uword_t len
= os_vm_page_size
* entry
->page_count
;
655 spaces
[id
].len
= len
;
656 if (id
== DYNAMIC_CORE_SPACE_ID
&& len
> dynamic_space_size
) {
657 lose("dynamic space too small for core: %luKiB required, %luKiB available.\n",
658 (unsigned long)len
>> 10,
659 (unsigned long)dynamic_space_size
>> 10);
662 uword_t
__attribute__((unused
)) aligned_start
;
663 #ifdef LISP_FEATURE_RELOCATABLE_HEAP
664 // Try to map at address requested by the core file.
665 if (id
== DYNAMIC_CORE_SPACE_ID
) {
666 addr
= (uword_t
)os_validate(MOVABLE
, (os_vm_address_t
)addr
,
668 aligned_start
= ALIGN_UP(addr
, GENCGC_CARD_BYTES
);
669 /* Misalignment can happen only if card size exceeds OS page.
670 * Drop one card to avoid overrunning the allocated space */
671 if (aligned_start
> addr
) // not card-aligned
672 dynamic_space_size
-= GENCGC_CARD_BYTES
;
673 DYNAMIC_SPACE_START
= addr
= aligned_start
;
674 # ifndef LISP_FEATURE_IMMOBILE_SPACE
677 if (DYNAMIC_SPACE_START
< FIXEDOBJ_SPACE_START
)
678 lose("Won't map dynamic space below immobile space");
679 /* Assume presence of linkage-table space for this platform.
680 * An unusable gap may exist between the linkage table and immobile space
681 * but it's not important whether it does or doesn't. So we don't bother
682 * unmapping the alleged gap */
683 } else if (id
== IMMOBILE_FIXEDOBJ_CORE_SPACE_ID
) {
684 addr
= (uword_t
)os_validate(MOVABLE_LOW
, (os_vm_address_t
)addr
,
685 IMMOBILE_SPACE_TOTAL_SIZE
);
686 FIXEDOBJ_SPACE_START
= addr
;
687 if (FIXEDOBJ_SPACE_START
+ IMMOBILE_SPACE_TOTAL_SIZE
> 0x80000000)
688 lose("Won't map immobile space above 2GB");
689 // varyobj subspace must be enforced to reside at a known offset
690 // from fixedobj subspace.
691 spaces
[IMMOBILE_VARYOBJ_CORE_SPACE_ID
].base
=
692 spaces
[id
].base
+ FIXEDOBJ_SPACE_SIZE
;
693 VARYOBJ_SPACE_START
= addr
+ FIXEDOBJ_SPACE_SIZE
;
694 } else if (id
== IMMOBILE_VARYOBJ_CORE_SPACE_ID
) {
695 /* Ignore what the core file said */
696 addr
= VARYOBJ_SPACE_START
;
700 #endif /* LISP_FEATURE_RELOCATABLE_HEAP */
702 sword_t offset
= os_vm_page_size
* (1 + entry
->data_page
);
704 inflate_core_bytes(fd
, offset
+ file_offset
, (os_vm_address_t
)addr
, len
);
706 load_core_bytes(fd
, offset
+ file_offset
, (os_vm_address_t
)addr
, len
);
709 #ifdef MADV_MERGEABLE
710 if ((merge_core_pages
== 1)
711 || ((merge_core_pages
== -1) && compressed
)) {
712 madvise((void *)addr
, len
, MADV_MERGEABLE
);
716 lispobj
*free_pointer
= (lispobj
*) addr
+ entry
->nwords
;
719 *spaces
[id
].pfree_pointer
= free_pointer
;
721 case DYNAMIC_CORE_SPACE_ID
:
722 #ifdef LISP_FEATURE_CHENEYGC
723 /* 'addr' is the actual address if relocatable.
724 * For cheneygc, this will be whatever the GC was using
725 * at the time the core was saved.
726 * For gencgc this is #defined as DYNAMIC_SPACE_START */
727 current_dynamic_space
= (lispobj
*)addr
;
729 set_alloc_pointer((lispobj
)free_pointer
);
731 anon_dynamic_space_start
= (os_vm_address_t
)(addr
+ len
);
732 /* This assertion safeguards the test in zero_pages_with_mmap()
733 * which trusts that if addr > anon_dynamic_space_start
734 * then addr did not come from any file mapping. */
735 gc_assert((lispobj
)anon_dynamic_space_start
> STATIC_SPACE_END
);
739 #ifdef LISP_FEATURE_RELOCATABLE_HEAP
740 #ifdef LISP_FEATURE_IMMOBILE_SPACE
741 if (FIXEDOBJ_SPACE_START
!= spaces
[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID
].base
) {
742 adj
->range
[0].start
= spaces
[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID
].base
;
743 adj
->range
[0].end
= adj
->range
[0].start
+ FIXEDOBJ_SPACE_SIZE
744 + spaces
[IMMOBILE_VARYOBJ_CORE_SPACE_ID
].len
;
745 adj
->range
[0].delta
= FIXEDOBJ_SPACE_START
- adj
->range
[0].start
;
748 if (DYNAMIC_SPACE_START
!= spaces
[DYNAMIC_CORE_SPACE_ID
].base
) {
749 adj
->range
[1].start
= spaces
[DYNAMIC_CORE_SPACE_ID
].base
;
750 adj
->range
[1].end
= adj
->range
[1].start
+ spaces
[DYNAMIC_CORE_SPACE_ID
].len
;
751 adj
->range
[1].delta
= DYNAMIC_SPACE_START
- adj
->range
[1].start
;
753 if (adj
->range
[0].delta
| adj
->range
[1].delta
)
757 #ifdef LISP_FEATURE_IMMOBILE_SPACE
758 /* Now determine page characteristics (such as object spacing)
759 * after relocation, because we need to know which objects are layouts
760 * based on knowing layout-of-layout. The test for that is dependent
761 * on what it's address should be, not what it was in the file */
762 immobile_space_coreparse(spaces
[IMMOBILE_FIXEDOBJ_CORE_SPACE_ID
].len
,
763 spaces
[IMMOBILE_VARYOBJ_CORE_SPACE_ID
].len
);
765 #ifdef LISP_FEATURE_X86_64
766 tune_asm_routines_for_microarch(); // before WPing immobile space
771 load_core_file(char *file
, os_vm_offset_t file_offset
)
774 core_entry_elt_t val
, *ptr
;
775 os_vm_size_t len
, remaining_len
;
776 int fd
= open_binary(file
, O_RDONLY
);
778 lispobj initial_function
= NIL
;
779 struct heap_adjust adj
;
780 memset(&adj
, 0, sizeof adj
);
782 FSHOW((stderr
, "/entering load_core_file(%s)\n", file
));
784 fprintf(stderr
, "could not open file \"%s\"\n", file
);
789 lseek(fd
, file_offset
, SEEK_SET
);
790 header
= calloc(os_vm_page_size
, 1);
792 count
= read(fd
, header
, os_vm_page_size
);
793 if (count
< (ssize_t
) os_vm_page_size
) {
794 lose("premature end of core file\n");
796 SHOW("successfully read first page of core");
801 if (val
!= CORE_MAGIC
) {
802 lose("invalid magic number in core: 0x%lx should have been 0x%x.\n",
806 SHOW("found CORE_MAGIC");
808 #define WORD_FMTX OS_VM_SIZE_FMTX
809 for ( ; ; ptr
+= remaining_len
) {
812 remaining_len
= len
- 2; /* (-2 to cancel the two ++ operations) */
813 FSHOW((stderr
, "/val=0x%"WORD_FMTX
", remaining_len=0x%"WORD_FMTX
"\n",
814 val
, remaining_len
));
818 case END_CORE_ENTRY_TYPE_CODE
:
821 return initial_function
;
823 case BUILD_ID_CORE_ENTRY_TYPE_CODE
:
824 SHOW("BUILD_ID_CORE_ENTRY_TYPE_CODE case");
826 os_vm_size_t stringlen
= *ptr
++;
828 gc_assert(remaining_len
* sizeof (core_entry_elt_t
) >= stringlen
);
829 if (sizeof build_id
== stringlen
+1 && !memcmp(ptr
, build_id
, stringlen
))
831 /* .core files are not binary-compatible between
832 * builds because we can't easily detect whether the
833 * sources were patched between the time the
834 * dumping-the-.core runtime was built and the time
835 * that the loading-the-.core runtime was built.
837 * (We could easily detect whether version.lisp-expr
838 * was changed, but people experimenting with patches
839 * don't necessarily update version.lisp-expr.) */
841 "core was built for runtime \"%.*s\" but this is \"%s\"\n",
842 (int)stringlen
, (char*)ptr
, build_id
);
843 lose("can't load .core for different runtime, sorry\n");
846 case NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE
:
847 SHOW("NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE case");
848 process_directory(remaining_len
/ NDIR_ENTRY_LENGTH
,
849 (struct ndir_entry
*)ptr
, fd
, file_offset
,
853 case INITIAL_FUN_CORE_ENTRY_TYPE_CODE
:
854 SHOW("INITIAL_FUN_CORE_ENTRY_TYPE_CODE case");
855 initial_function
= adjust_word(&adj
, (lispobj
)*ptr
);
858 #ifdef LISP_FEATURE_GENCGC
859 case PAGE_TABLE_CORE_ENTRY_TYPE_CODE
:
861 extern void gc_allocate_ptes();
862 extern boolean
gc_load_corefile_ptes(char data
[], ssize_t
,
863 page_index_t
, page_index_t
*);
864 // Allocation of PTEs is delayed 'til now so that calloc() doesn't
865 // consume addresses that would have been taken by a mapped space.
867 os_vm_size_t remaining
= *ptr
;
868 os_vm_size_t fdoffset
= (*(ptr
+1) + 1) * (os_vm_page_size
);
869 page_index_t page
= 0, npages
;
872 // A corefile_pte is 10 bytes for x86-64
873 // Process an integral number of ptes on each read.
874 os_vm_size_t chunksize
= sizeof (struct corefile_pte
)
875 * (sizeof data
/ sizeof (struct corefile_pte
));
876 lseek(fd
, fdoffset
+ file_offset
, SEEK_SET
);
877 bytes_read
= read(fd
, &npages
, sizeof npages
);
878 gc_assert(bytes_read
== sizeof npages
);
879 remaining
-= sizeof npages
;
880 while ((bytes_read
= read(fd
, data
,
881 remaining
< chunksize
? remaining
: chunksize
)) > 0
882 && gc_load_corefile_ptes(data
, bytes_read
, npages
, &page
))
883 remaining
-= bytes_read
;
885 gencgc_partial_pickup
= 1;
890 lose("unknown core file entry: 0x%"WORD_FMTX
"\n", val
);
895 #include "genesis/hash-table.h"
896 #include "genesis/vector.h"
897 os_vm_address_t
get_asm_routine_by_name(const char* name
)
899 lispobj routines
= SYMBOL(ASSEMBLER_ROUTINES
)->value
;
900 if (lowtag_of(routines
) == INSTANCE_POINTER_LOWTAG
) {
901 struct hash_table
* ht
= (struct hash_table
*)native_pointer(routines
);
902 struct vector
* table
= VECTOR(ht
->table
);
905 for (i
=2 ; i
< fixnum_value(table
->length
) ; i
+= 2) {
906 sym
= table
->data
[i
];
907 if (lowtag_of(sym
) == OTHER_POINTER_LOWTAG
908 && widetag_of(SYMBOL(sym
)->header
) == SYMBOL_WIDETAG
909 && !strcmp(name
, (char*)(VECTOR(SYMBOL(sym
)->name
)->data
)))
910 return (os_vm_address_t
)fixnum_value(table
->data
[i
+1]);
912 // Something is wrong if we have a hashtable but find nothing.
913 fprintf(stderr
, "WARNING: get_asm_routine_by_name(%s) failed\n",
919 void asm_routine_poke(const char* routine
, int offset
, char byte
)
921 char *address
= (char *)get_asm_routine_by_name(routine
);
923 address
[offset
] = byte
;