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