1276c077fa3e36ffc94c689a023c6f17ae9e0a8d
[sbcl.git] / src / runtime / coreparse.c
1 /*
2  * A saved SBCL system is a .core file; the code here helps us accept
3  * such a file as input.
4  */
5   
6 /*
7  * This software is part of the SBCL system. See the README file for
8  * more information.
9  *
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.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/file.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #ifdef irix
24 #include <fcntl.h>
25 #endif
26
27 #include "os.h"
28 #include "runtime.h"
29 #include "globals.h"
30 #include "core.h"
31 #include "arch.h"
32 #include "interr.h"
33 #include "sbcl.h"
34
35 static void
36 process_directory(int fd, u32 *ptr, int count)
37 {
38     struct ndir_entry *entry;
39
40     FSHOW((stderr, "/process_directory(..), count=%d\n", count));
41     
42     for (entry = (struct ndir_entry *) ptr; --count>= 0; ++entry) {
43
44         long id = entry->identifier;
45         long offset = os_vm_page_size * (1 + entry->data_page);
46         os_vm_address_t addr =
47             (os_vm_address_t) (os_vm_page_size * entry->address);
48         lispobj *free_pointer = (lispobj *) addr + entry->nwords;
49         long len = os_vm_page_size * entry->page_count;
50         
51         if (len != 0) {
52             os_vm_address_t real_addr;
53             FSHOW((stderr, "/mapping %ld(0x%lx) bytes at 0x%lx\n",
54                    (long)len, (long)len, addr));
55             real_addr = os_map(fd, offset, addr, len);
56             if (real_addr != addr) {
57                 lose("file mapped in wrong place! "
58                      "(0x%08x != 0x%08lx)",
59                      real_addr,
60                      addr);
61             }
62         }
63
64         FSHOW((stderr, "/space id = %d, free pointer = 0x%08x\n",
65                id, (long)free_pointer));
66
67         switch (id) {
68         case DYNAMIC_SPACE_ID:
69 #ifdef GENCGC     
70             if (addr != (os_vm_address_t)DYNAMIC_SPACE_START) {
71                 fprintf(stderr, "in core: 0x%lx; in runtime: 0x%lx \n",
72                         (long)addr, (long)DYNAMIC_SPACE_START);
73                 lose("core/runtime address mismatch: DYNAMIC_SPACE_START");
74             }
75 #else
76             if ((addr != (os_vm_address_t)DYNAMIC_0_SPACE_START) &&
77                 (addr != (os_vm_address_t)DYNAMIC_1_SPACE_START)) {
78                 fprintf(stderr, "in core: 0x%lx; in runtime: 0x%lx or 0x%lx\n",
79                         (long)addr,
80                         (long)DYNAMIC_0_SPACE_START,
81                         (long)DYNAMIC_1_SPACE_START);
82                 lose("warning: core/runtime address mismatch: DYNAMIC_SPACE_START");
83             }
84 #endif
85 /* FIXME: Should the conditional here be reg_ALLOC instead of
86  *   defined(__i386__)
87  * ? */
88 #if defined(__i386__)
89             SetSymbolValue(ALLOCATION_POINTER, (lispobj)free_pointer);
90 #else
91             dynamic_space_free_pointer = free_pointer;
92 #endif
93             /* For stop-and-copy GC, this will be whatever the GC was
94              * using at the time. With GENCGC, this will always be
95              * space 0. (We checked above that for GENCGC,
96              * addr==DYNAMIC_SPACE_START.) */
97             current_dynamic_space = (lispobj *)addr;
98             break;
99         case STATIC_SPACE_ID:
100             if (addr != (os_vm_address_t)STATIC_SPACE_START) {
101                 fprintf(stderr, "in core: 0x%lx - in runtime: 0x%lx\n",
102                         (long)addr, (long)STATIC_SPACE_START);
103                 lose("core/runtime address mismatch: STATIC_SPACE_START");
104             }
105             break;
106         case READ_ONLY_SPACE_ID:
107             if (addr != (os_vm_address_t)READ_ONLY_SPACE_START) {
108                 fprintf(stderr, "in core: 0x%lx - in runtime: 0x%lx\n",
109                         (long)addr, (long)READ_ONLY_SPACE_START);
110                 lose("core/runtime address mismatch: READ_ONLY_SPACE_START");
111             }
112             break;
113         default:
114             lose("unknown space ID %ld addr 0x%p", id);
115         }
116     }
117 }
118
119 lispobj
120 load_core_file(char *file)
121 {
122     u32 *header, val, len, *ptr, remaining_len;
123     int fd = open(file, O_RDONLY), count;
124
125     lispobj initial_function = NIL;
126     FSHOW((stderr, "/entering load_core_file(%s)\n", file));
127     if (fd < 0) {
128         fprintf(stderr, "could not open file \"%s\"\n", file);
129         perror("open");
130         exit(1);
131     }
132
133     header = calloc(os_vm_page_size / sizeof(u32), sizeof(u32));
134
135     count = read(fd, header, os_vm_page_size);
136     if (count < os_vm_page_size) {
137         lose("premature end of core file");
138     }
139     SHOW("successfully read first page of core");
140
141     ptr = header;
142     val = *ptr++;
143
144     if (val != CORE_MAGIC) {
145         lose("invalid magic number in core: 0x%lx should have been 0x%x.",
146              val,
147              CORE_MAGIC);
148     }
149     SHOW("found CORE_MAGIC");
150
151     while (val != CORE_END) {
152         val = *ptr++;
153         len = *ptr++;
154         remaining_len = len - 2; /* (-2 to cancel the two ++ operations) */
155         FSHOW((stderr, "/val=0x%ld, remaining_len=0x%ld\n",
156                (long)val, (long)remaining_len));
157
158         switch (val) {
159
160         case CORE_END:
161             SHOW("CORE_END case");
162             break;
163
164         case CORE_VERSION:
165             SHOW("CORE_VERSION case");
166             if (*ptr != SBCL_CORE_VERSION_INTEGER) {
167                 lose("core file version (%d) != runtime library version (%d)",
168                      *ptr,
169                      SBCL_CORE_VERSION_INTEGER);
170             }
171             break;
172
173         case CORE_NDIRECTORY:
174             SHOW("CORE_NDIRECTORY case");
175             process_directory(fd,
176                               ptr,
177 #ifndef alpha
178                               remaining_len / (sizeof(struct ndir_entry) /
179                                                sizeof(long))
180 #else
181                               remaining_len / (sizeof(struct ndir_entry) /
182                                                sizeof(u32))
183 #endif
184                               );
185             break;
186
187         case CORE_INITIAL_FUNCTION:
188             SHOW("CORE_INITIAL_FUNCTION case");
189             initial_function = (lispobj)*ptr;
190             break;
191
192         default:
193             lose("unknown core file entry: %ld", (long)val);
194         }
195
196         ptr += remaining_len;
197         FSHOW((stderr, "/new ptr=%x\n", ptr));
198     }
199     SHOW("about to free(header)");
200     free(header);
201     SHOW("returning from load_core_file(..)");
202     return initial_function;
203 }