Commit | Line | Data |
---|---|---|
442fe3bf DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
77e05717 | 6 | |
442fe3bf DF |
7 | #ifndef lint |
8 | static char sccsid[] = "@(#)coredump.c 5.1 (Berkeley) %G%"; | |
9 | #endif not lint | |
0022c355 ML |
10 | |
11 | static char rcsid[] = "$Header: coredump.c,v 1.5 84/12/26 10:38:56 linton Exp $"; | |
77e05717 ML |
12 | |
13 | /* | |
14 | * Deal with the core dump anachronism. | |
77e05717 ML |
15 | */ |
16 | ||
17 | #include "defs.h" | |
18 | #include "coredump.h" | |
19 | #include "machine.h" | |
20 | #include "object.h" | |
21 | #include "main.h" | |
22 | #include <sys/param.h> | |
23 | #include <sys/dir.h> | |
4c25ec87 ML |
24 | #include <machine/psl.h> |
25 | #include <machine/pte.h> | |
77e05717 ML |
26 | #include <sys/user.h> |
27 | #include <sys/vm.h> | |
4c25ec87 | 28 | #include <machine/reg.h> |
77e05717 ML |
29 | #include <a.out.h> |
30 | ||
31 | #ifndef public | |
32 | #define coredump_readin(m, r, s) coredump_xreadin(&(m), r, &(s)) | |
33 | ||
34 | #include "machine.h" | |
35 | #endif | |
36 | ||
37 | #define MAXSTKADDR (0x80000000 - ctob(UPAGES)) /* highest stack address */ | |
38 | ||
39 | typedef struct { | |
40 | Address begin; | |
41 | Address end; | |
42 | Address seekaddr; | |
43 | } Map; | |
44 | ||
45 | private Map datamap, stkmap; | |
46 | private File objfile; | |
47 | private struct exec hdr; | |
48 | ||
49 | /* | |
0022c355 | 50 | * Special variables for debugging the kernel. |
77e05717 ML |
51 | */ |
52 | ||
0022c355 ML |
53 | private integer masterpcbb; |
54 | private integer slr; | |
55 | private struct pte *sbr; | |
56 | private struct pcb pcb; | |
57 | ||
58 | private getpcb () | |
77e05717 | 59 | { |
0022c355 ML |
60 | fseek(corefile, masterpcbb & ~0x80000000, 0); |
61 | get(corefile, pcb); | |
62 | pcb.pcb_p0lr &= ~AST_CLR; | |
63 | printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", | |
64 | pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr | |
65 | ); | |
66 | setreg(0, pcb.pcb_r0); | |
67 | setreg(1, pcb.pcb_r1); | |
68 | setreg(2, pcb.pcb_r2); | |
69 | setreg(3, pcb.pcb_r3); | |
70 | setreg(4, pcb.pcb_r4); | |
71 | setreg(5, pcb.pcb_r5); | |
72 | setreg(6, pcb.pcb_r6); | |
73 | setreg(7, pcb.pcb_r7); | |
74 | setreg(8, pcb.pcb_r8); | |
75 | setreg(9, pcb.pcb_r9); | |
76 | setreg(10, pcb.pcb_r10); | |
77 | setreg(11, pcb.pcb_r11); | |
78 | setreg(ARGP, pcb.pcb_ap); | |
79 | setreg(FRP, pcb.pcb_fp); | |
80 | setreg(STKP, pcb.pcb_ksp); | |
81 | setreg(PROGCTR, pcb.pcb_pc); | |
82 | } | |
77e05717 | 83 | |
0022c355 ML |
84 | public coredump_getkerinfo () |
85 | { | |
86 | Symbol s; | |
87 | ||
88 | s = lookup(identname("Sysmap", true)); | |
89 | if (s == nil) { | |
90 | panic("can't find 'Sysmap'"); | |
77e05717 | 91 | } |
0022c355 ML |
92 | sbr = (struct pte *) (s->symvalue.offset); |
93 | s = lookup(identname("Syssize", true)); | |
94 | if (s == nil) { | |
95 | panic("can't find 'Syssize'"); | |
96 | } | |
97 | slr = (integer) (s->symvalue.offset); | |
98 | printf("sbr %lx slr %lx\n", sbr, slr); | |
99 | s = lookup(identname("masterpaddr", true)); | |
100 | if (s == nil) { | |
101 | panic("can't find 'masterpaddr'"); | |
102 | } | |
103 | fseek( | |
104 | corefile, | |
105 | datamap.seekaddr + s->symvalue.offset&0x7fffffff - datamap.begin, | |
106 | 0 | |
107 | ); | |
108 | get(corefile, masterpcbb); | |
109 | masterpcbb = (masterpcbb&PG_PFNUM)*512; | |
110 | getpcb(); | |
111 | } | |
112 | ||
113 | private copyregs (savreg, reg) | |
114 | Word savreg[], reg[]; | |
115 | { | |
77e05717 ML |
116 | reg[0] = savreg[R0]; |
117 | reg[1] = savreg[R1]; | |
118 | reg[2] = savreg[R2]; | |
119 | reg[3] = savreg[R3]; | |
120 | reg[4] = savreg[R4]; | |
121 | reg[5] = savreg[R5]; | |
122 | reg[6] = savreg[R6]; | |
123 | reg[7] = savreg[R7]; | |
124 | reg[8] = savreg[R8]; | |
125 | reg[9] = savreg[R9]; | |
126 | reg[10] = savreg[R10]; | |
127 | reg[11] = savreg[R11]; | |
128 | reg[ARGP] = savreg[AP]; | |
129 | reg[FRP] = savreg[FP]; | |
130 | reg[STKP] = savreg[SP]; | |
131 | reg[PROGCTR] = savreg[PC]; | |
0022c355 | 132 | } |
77e05717 | 133 | |
0022c355 ML |
134 | /* |
135 | * Read the user area information from the core dump. | |
136 | */ | |
77e05717 | 137 | |
0022c355 ML |
138 | public coredump_xreadin(mask, reg, signo) |
139 | int *mask; | |
140 | Word reg[]; | |
141 | int *signo; | |
142 | { | |
143 | register struct user *up; | |
144 | register Word *savreg; | |
145 | union { | |
146 | struct user u; | |
147 | char dummy[ctob(UPAGES)]; | |
148 | } ustruct; | |
149 | Symbol s; | |
150 | ||
151 | objfile = fopen(objname, "r"); | |
152 | if (objfile == nil) { | |
153 | fatal("can't read \"%s\"", objname); | |
154 | } | |
155 | get(objfile, hdr); | |
156 | if (vaddrs) { | |
157 | datamap.begin = 0; | |
158 | datamap.end = 0xffffffff; | |
159 | stkmap.begin = 0xffffffff; | |
160 | stkmap.end = 0xffffffff; | |
161 | } else { | |
162 | up = &(ustruct.u); | |
163 | fread(up, ctob(UPAGES), 1, corefile); | |
164 | savreg = (Word *) &(ustruct.dummy[ctob(UPAGES)]); | |
165 | *mask = savreg[PS]; | |
166 | copyregs(savreg, reg); | |
167 | *signo = up->u_arg[0]; | |
168 | datamap.seekaddr = ctob(UPAGES); | |
169 | stkmap.begin = MAXSTKADDR - ctob(up->u_ssize); | |
170 | stkmap.end = MAXSTKADDR; | |
171 | stkmap.seekaddr = datamap.seekaddr + ctob(up->u_dsize); | |
172 | switch (hdr.a_magic) { | |
173 | case OMAGIC: | |
174 | datamap.begin = 0; | |
175 | datamap.end = ctob(up->u_tsize) + ctob(up->u_dsize); | |
176 | break; | |
177 | ||
178 | case NMAGIC: | |
179 | case ZMAGIC: | |
180 | datamap.begin = (Address) ptob(btop(ctob(up->u_tsize) - 1) + 1); | |
181 | datamap.end = datamap.begin + ctob(up->u_dsize); | |
182 | break; | |
183 | ||
184 | default: | |
185 | fatal("bad magic number 0x%x", hdr.a_magic); | |
186 | } | |
187 | #ifdef UXMAG | |
188 | /* | |
189 | * Core dump not from this object file? | |
190 | */ | |
191 | if (hdr.a_magic != 0 and up->u_exdata.ux_mag != 0 and | |
192 | hdr.a_magic != up->u_exdata.ux_mag) { | |
193 | warning("core dump ignored"); | |
194 | coredump = false; | |
195 | fclose(corefile); | |
196 | fclose(objfile); | |
197 | start(nil, nil, nil); | |
198 | } | |
199 | #endif | |
77e05717 | 200 | } |
77e05717 ML |
201 | } |
202 | ||
203 | public coredump_close() | |
204 | { | |
205 | fclose(objfile); | |
206 | } | |
207 | ||
208 | public coredump_readtext(buff, addr, nbytes) | |
209 | char *buff; | |
210 | Address addr; | |
211 | int nbytes; | |
212 | { | |
0022c355 | 213 | if (hdr.a_magic == OMAGIC or vaddrs) { |
77e05717 ML |
214 | coredump_readdata(buff, addr, nbytes); |
215 | } else { | |
216 | fseek(objfile, N_TXTOFF(hdr) + addr, 0); | |
217 | fread(buff, nbytes, sizeof(Byte), objfile); | |
218 | } | |
219 | } | |
220 | ||
0022c355 ML |
221 | /* |
222 | * Map a virtual address to a physical address. | |
223 | */ | |
224 | ||
225 | private Address vmap (addr) | |
226 | Address addr; | |
227 | { | |
228 | Address r; | |
229 | integer v, n; | |
230 | struct pte pte; | |
231 | ||
232 | r = addr & ~0xc0000000; | |
233 | v = btop(r); | |
234 | switch (addr&0xc0000000) { | |
235 | case 0xc0000000: | |
236 | case 0x80000000: | |
237 | /* | |
238 | * In system space, so get system pte. | |
239 | * If it is valid or reclaimable then the physical address | |
240 | * is the combination of its page number and the page offset | |
241 | * of the original address. | |
242 | */ | |
243 | if (v >= slr) { | |
244 | error("address %x out of segment", addr); | |
245 | } | |
246 | r = ((long) (sbr + v)) & ~0x80000000; | |
247 | goto simple; | |
248 | ||
249 | case 0x40000000: | |
250 | /* | |
251 | * In p1 space, must not be in shadow region. | |
252 | */ | |
253 | if (v < pcb.pcb_p1lr) { | |
254 | error("address %x out of segment", addr); | |
255 | } | |
256 | r = (Address) (pcb.pcb_p1br + v); | |
257 | break; | |
258 | ||
259 | case 0x00000000: | |
260 | /* | |
261 | * In p0 space, must not be off end of region. | |
262 | */ | |
263 | if (v >= pcb.pcb_p0lr) { | |
264 | error("address %x out of segment", addr); | |
265 | } | |
266 | r = (Address) (pcb.pcb_p0br + v); | |
267 | break; | |
268 | ||
269 | default: | |
270 | /* do nothing */ | |
271 | break; | |
272 | } | |
273 | /* | |
274 | * For p0/p1 address, user-level page table should be in | |
275 | * kernel virtual memory. Do second-level indirect by recursing. | |
276 | */ | |
277 | if ((r & 0x80000000) == 0) { | |
278 | error("bad p0br or p1br in pcb"); | |
279 | } | |
280 | r = vmap(r); | |
281 | simple: | |
282 | /* | |
283 | * "r" is now the address of the pte of the page | |
284 | * we are interested in; get the pte and paste up the physical address. | |
285 | */ | |
286 | fseek(corefile, r, 0); | |
287 | n = fread(&pte, sizeof(pte), 1, corefile); | |
288 | if (n != 1) { | |
289 | error("page table botch (fread at %x returns %d)", r, n); | |
290 | } | |
291 | if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { | |
292 | error("page no valid or reclamable"); | |
293 | } | |
294 | return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); | |
295 | } | |
296 | ||
77e05717 ML |
297 | public coredump_readdata(buff, addr, nbytes) |
298 | char *buff; | |
299 | Address addr; | |
300 | int nbytes; | |
301 | { | |
0022c355 ML |
302 | Address a; |
303 | ||
304 | a = addr; | |
305 | if (a < datamap.begin) { | |
2fd0f574 | 306 | if (hdr.a_magic == OMAGIC) { |
0022c355 ML |
307 | error("[data address 0x%x too low (lb = 0x%x)]", a, datamap.begin); |
308 | } else { | |
309 | coredump_readtext(buff, a, nbytes); | |
310 | } | |
311 | } else if (a > stkmap.end) { | |
312 | error("data address 0x%x too high (ub = 0x%x)", a, stkmap.end); | |
313 | } else { | |
314 | if (vaddrs) { | |
315 | vreadfromfile(corefile, a, buff, nbytes); | |
2fd0f574 | 316 | } else { |
0022c355 | 317 | readfromfile(corefile, a, buff, nbytes); |
2fd0f574 | 318 | } |
0022c355 ML |
319 | } |
320 | } | |
321 | ||
322 | /* | |
323 | * Read a block of data from a memory image, mapping virtual addresses. | |
324 | * Have to watch out for page boundaries. | |
325 | */ | |
326 | ||
327 | private vreadfromfile (corefile, v, buff, nbytes) | |
328 | File corefile; | |
329 | Address v; | |
330 | char *buff; | |
331 | integer nbytes; | |
332 | { | |
333 | Address a; | |
334 | integer i, remainder, pagesize; | |
335 | char *bufp; | |
336 | ||
337 | a = v; | |
338 | pagesize = (integer) ptob(1); | |
339 | remainder = pagesize - (a mod pagesize); | |
340 | if (remainder >= nbytes) { | |
341 | readfromfile(corefile, vmap(a), buff, nbytes); | |
342 | } else { | |
343 | readfromfile(corefile, vmap(a), buff, remainder); | |
344 | a += remainder; | |
345 | i = nbytes - remainder; | |
346 | bufp = buff + remainder; | |
347 | while (i > pagesize) { | |
348 | readfromfile(corefile, vmap(a), bufp, pagesize); | |
349 | a += pagesize; | |
350 | bufp += pagesize; | |
351 | i -= pagesize; | |
352 | } | |
353 | readfromfile(corefile, vmap(a), bufp, i); | |
354 | } | |
355 | } | |
356 | ||
357 | private readfromfile (f, a, buff, nbytes) | |
358 | File f; | |
359 | Address a; | |
360 | char *buff; | |
361 | integer nbytes; | |
362 | { | |
363 | integer fileaddr; | |
364 | ||
365 | if (a < stkmap.begin) { | |
366 | fileaddr = datamap.seekaddr + a - datamap.begin; | |
77e05717 | 367 | } else { |
0022c355 | 368 | fileaddr = stkmap.seekaddr + a - stkmap.begin; |
77e05717 | 369 | } |
0022c355 ML |
370 | fseek(f, fileaddr, 0); |
371 | fread(buff, nbytes, sizeof(Byte), f); | |
77e05717 | 372 | } |