Commit | Line | Data |
---|---|---|
eb1efbca | 1 | static char sccsid[] = "@(#)setup.c 4.11 (Berkeley) 87/12/21"; |
af975fa6 BJ |
2 | /* |
3 | * adb - routines to read a.out+core at startup | |
4 | */ | |
5 | #include "defs.h" | |
ab398a39 SL |
6 | #include <frame.h> |
7 | #include <ctype.h> | |
6094e621 | 8 | #include <sys/stat.h> |
ab398a39 SL |
9 | #include <sys/file.h> |
10 | #include <vax/rpb.h> | |
af975fa6 BJ |
11 | |
12 | off_t datbas; /* offset of the base of the data segment */ | |
13 | off_t stksiz; /* stack size in the core image */ | |
14 | INT sigcode; /* belongs in head.h */ | |
15 | ||
16 | char *symfil = "a.out"; | |
17 | char *corfil = "core"; | |
18 | ||
19 | setsym() | |
20 | { | |
21 | off_t loc; | |
22 | struct exec hdr; | |
23 | register struct nlist *sp; | |
24 | int ssiz; | |
25 | char *strtab; | |
26 | ||
27 | fsym = getfile(symfil, 1); | |
28 | txtmap.ufd = fsym; | |
29 | if (read(fsym, (char *)&hdr, sizeof hdr) != sizeof hdr || | |
30 | N_BADMAG(hdr)) { | |
31 | txtmap.e1 = MAXFILE; | |
32 | return; | |
33 | } | |
34 | filhdr = hdr; | |
35 | loc = filhdr.a_text+filhdr.a_data; | |
36 | txtmap.f1 = txtmap.f2 = N_TXTOFF(filhdr); | |
37 | txtmap.b1 = 0; | |
38 | switch (filhdr.a_magic) { | |
39 | ||
40 | case OMAGIC: | |
41 | txtmap.b1 = txtmap.e1 = 0; | |
42 | txtmap.b2 = datbas = 0; | |
43 | txtmap.e2 = loc; | |
44 | break; | |
45 | ||
46 | case ZMAGIC: | |
47 | case NMAGIC: | |
48 | txtmap.e1 = filhdr.a_text; | |
49 | txtmap.b2 = datbas = round(filhdr.a_text, PAGSIZ); | |
50 | txtmap.e2 = datbas + filhdr.a_data; | |
51 | txtmap.f2 += txtmap.e1; | |
52 | } | |
53 | loc = N_SYMOFF(filhdr); | |
54 | symtab = (struct nlist *) malloc(filhdr.a_syms); | |
55 | esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)]; | |
56 | if (symtab == NULL) | |
57 | goto nospac; | |
ab398a39 | 58 | lseek(fsym, loc, L_SET); |
af975fa6 BJ |
59 | if (filhdr.a_syms == 0) |
60 | goto nosymt; | |
61 | /* SHOULD SQUISH OUT STABS HERE!!! */ | |
62 | if (read(fsym, symtab, filhdr.a_syms) != filhdr.a_syms) | |
63 | goto readerr; | |
64 | if (read(fsym, &ssiz, sizeof (ssiz)) != sizeof (ssiz)) | |
65 | goto oldfmt; | |
66 | strtab = (char *) malloc(ssiz); | |
67 | if (strtab == 0) | |
68 | goto nospac; | |
69 | *(int *)strtab = ssiz; | |
70 | ssiz -= sizeof (ssiz); | |
71 | if (read(fsym, strtab + sizeof (ssiz), ssiz) != ssiz) | |
72 | goto readerr; | |
73 | for (sp = symtab; sp < esymtab; sp++) | |
eb1efbca | 74 | if (sp->n_un.n_strx) |
af975fa6 BJ |
75 | /* SHOULD PERFORM RANGE CHECK HERE */ |
76 | sp->n_un.n_name = strtab + sp->n_un.n_strx; | |
77 | nosymt: | |
78 | if (INKERNEL(filhdr.a_entry)) { | |
79 | txtmap.b1 += KERNOFF; | |
80 | txtmap.e1 += KERNOFF; | |
81 | txtmap.b2 += KERNOFF; | |
82 | txtmap.e2 += KERNOFF; | |
83 | } | |
84 | return; | |
85 | readerr: | |
86 | printf("Error reading symbol|string table\n"); | |
87 | exit(1); | |
88 | nospac: | |
89 | printf("Not enough space for symbol|string table\n"); | |
90 | exit(1); | |
91 | oldfmt: | |
92 | printf("Old format a.out - no string table\n"); | |
93 | exit(1); | |
94 | } | |
95 | ||
96 | setcor() | |
97 | { | |
98 | ||
99 | fcor = datmap.ufd = getfile(corfil,2); | |
52bff713 | 100 | if (kernel && fcor != -1 && INKERNEL(filhdr.a_entry)) { |
af975fa6 BJ |
101 | struct stat stb; |
102 | ||
128eca8b | 103 | kcore = 1; |
af975fa6 BJ |
104 | fstat(fcor, &stb); |
105 | datmap.b1 = 0; | |
106 | datmap.e1 = -1; | |
6d4468aa BJ |
107 | if (kernel == 0 && (stb.st_mode & S_IFREG)) |
108 | datmap.b1 = 0x80000000; | |
6eadceb1 BJ |
109 | lookup("_Sysmap"); |
110 | sbr = cursym->n_value; | |
111 | lookup("_Syssize"); | |
112 | slr = cursym->n_value; | |
7de0b1f0 | 113 | printf("sbr %x slr %x\n", sbr, slr); |
52bff713 | 114 | lookup("_masterpaddr"); |
f81bba3d SL |
115 | physrw(fcor, KVTOPH(cursym->n_value), &masterpcbb, 1); |
116 | masterpcbb = (masterpcbb&PG_PFNUM)*NBPG; | |
6eadceb1 | 117 | getpcb(); |
ab398a39 | 118 | findstackframe(); |
af975fa6 BJ |
119 | return; |
120 | } | |
121 | if (read(fcor, (char *)&u, ctob(UPAGES))!=ctob(UPAGES) || | |
122 | !INUDOT(u.u_pcb.pcb_ksp) || !INSTACK(u.u_pcb.pcb_usp)) { | |
123 | datmap.e1 = MAXFILE; | |
124 | return; | |
125 | } | |
126 | signo = u.u_arg[0]; | |
127 | sigcode = u.u_code; | |
128 | filhdr.a_text = ctob(u.u_tsize); | |
129 | filhdr.a_data = ctob(u.u_dsize); | |
130 | stksiz = ctob(u.u_ssize); | |
131 | switch (filhdr.a_magic) { | |
132 | ||
133 | case OMAGIC: | |
134 | datmap.b1 = 0; | |
135 | datmap.e1 = filhdr.a_text+filhdr.a_data; | |
136 | datmap.f2 = ctob(UPAGES) + datmap.e1; | |
137 | break; | |
138 | ||
139 | case NMAGIC: | |
140 | case ZMAGIC: | |
141 | datmap.b1 = round(filhdr.a_text, PAGSIZ); | |
142 | datmap.e1 = datmap.b1 + filhdr.a_data; | |
143 | datmap.f2 = ctob(UPAGES) + filhdr.a_data; | |
144 | break; | |
145 | } | |
146 | datbas = datmap.b1; | |
147 | datmap.f1 = ctob(UPAGES); | |
148 | datmap.b2 = MAXSTOR - stksiz; | |
149 | datmap.e2 = MAXSTOR; | |
af975fa6 BJ |
150 | } |
151 | ||
6eadceb1 BJ |
152 | getpcb() |
153 | { | |
128eca8b | 154 | |
f81bba3d | 155 | lseek(fcor, KVTOPH(masterpcbb), L_SET); |
6eadceb1 | 156 | read(fcor, &pcb, sizeof (struct pcb)); |
128eca8b | 157 | pcb.pcb_p0lr &= ~AST_CLR; |
7de0b1f0 | 158 | printf("p0br %x p0lr %x p1br %x p1lr %x\n", |
6eadceb1 | 159 | pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr); |
6eadceb1 BJ |
160 | } |
161 | ||
ab398a39 SL |
162 | caddr_t rpb, scb; |
163 | caddr_t intstack, eintstack; | |
164 | caddr_t ustack, eustack; | |
165 | struct frame *getframe(); | |
166 | struct frame *checkintstack(); | |
167 | ||
168 | /* | |
169 | * Find the current stack frame when debugging the kernel. | |
170 | * If we're looking at a crash dump and this was not a ``clean'' | |
171 | * crash, then we must search the interrupt stack carefully | |
172 | * looking for a valid frame. | |
173 | */ | |
174 | findstackframe() | |
175 | { | |
176 | char *panicstr, buf[256]; | |
177 | register struct frame *fp; | |
178 | caddr_t addr; | |
179 | register char *cp; | |
180 | int mask; | |
181 | ||
182 | if (lookup("_panicstr") == 0) | |
183 | return; | |
f81bba3d | 184 | lseek(fcor, KVTOPH(cursym->n_value), L_SET); |
ab398a39 SL |
185 | read(fcor, &panicstr, sizeof (panicstr)); |
186 | if (panicstr == 0) | |
187 | return; | |
f81bba3d | 188 | lseek(fcor, KVTOPH((off_t)panicstr), L_SET); |
ab398a39 SL |
189 | read(fcor, buf, sizeof (buf)); |
190 | for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++) | |
f81bba3d | 191 | if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp))) |
ab398a39 SL |
192 | *cp = '?'; |
193 | if (*cp) | |
194 | *cp = '\0'; | |
195 | printf("panic: %s\n", buf); | |
196 | /* | |
197 | * After a panic, look at the top of the rpb stack to | |
198 | * find a stack frame. If this was a clean crash, | |
199 | * i.e. one which left the interrupt and kernel stacks | |
200 | * in a reasonable state, then we should find a pointer | |
201 | * to the proper stack frame here (at location scb-4). | |
202 | * If we don't find a reasonable frame here, then we | |
203 | * must search down through the interrupt stack. | |
204 | */ | |
205 | intstack = lookup("_intstack")->n_value; | |
206 | #define NISP 3 /* from locore.s */ | |
207 | eintstack = intstack + NISP*NBPG; | |
208 | rpb = lookup("_rpb")->n_value; | |
209 | scb = lookup("_scb")->n_value; | |
210 | lookup("_u"); | |
211 | ustack = cursym->n_value + (int)&((struct user *)0)->u_stack[0]; | |
212 | eustack = cursym->n_value + ctob(UPAGES); | |
f81bba3d | 213 | physrw(fcor, KVTOPH((int)scb - sizeof (caddr_t)), &addr, 1); |
ab398a39 SL |
214 | fp = getframe(fcor, addr); |
215 | if (fp == 0) | |
216 | fp = checkintstack(); | |
217 | /* search kernel stack? */ | |
218 | if (fp == 0) { | |
219 | printf("can't locate stack frame\n"); | |
220 | return; | |
221 | } | |
222 | /* probably shouldn't clobber pcb, but for now this is easy */ | |
223 | pcb.pcb_fp = addr; | |
224 | pcb.pcb_pc = fp->fr_savpc; | |
225 | pcb.pcb_ap = addr + sizeof (struct frame) + fp->fr_spa; | |
226 | for (mask = fp->fr_mask; mask; mask >>= 1) | |
227 | if (mask & 01) | |
228 | pcb.pcb_ap += sizeof (caddr_t); | |
229 | } | |
230 | ||
231 | /* | |
232 | * Search interrupt stack for a valid frame. | |
233 | */ | |
234 | struct frame * | |
235 | checkintstack(fcor) | |
236 | { | |
237 | char stack[NISP*NBPG]; | |
238 | off_t off = vtophys(intstack); | |
239 | struct frame *fp; | |
240 | register caddr_t addr; | |
241 | ||
242 | if (off == -1 || lseek(fcor, off, L_SET) != off || | |
243 | read(fcor, stack, sizeof (stack)) != sizeof (stack)) | |
244 | return ((struct frame *)0); | |
245 | addr = eintstack; | |
246 | do { | |
247 | addr -= sizeof (caddr_t); | |
248 | fp = (struct frame *)&stack[addr - intstack]; | |
249 | } while (addr >= intstack + sizeof (struct frame) && | |
250 | !checkframe(fp)); | |
251 | return (addr < intstack+sizeof (struct frame) ? (struct frame *)0 : fp); | |
252 | } | |
253 | ||
254 | /* | |
255 | * Get a stack frame and verify it looks like | |
256 | * something which might be on a kernel stack. | |
257 | */ | |
258 | struct frame * | |
259 | getframe(fcor, fp) | |
260 | int fcor; | |
261 | caddr_t fp; | |
262 | { | |
263 | static struct frame frame; | |
264 | off_t off; | |
265 | ||
266 | if (!kstackaddr(fp) || (off = vtophys(fp)) == -1) | |
267 | return ((struct frame *)0); | |
268 | if (lseek(fcor, off, L_SET) != off || | |
269 | read(fcor, &frame, sizeof (frame)) != sizeof (frame)) | |
270 | return ((struct frame *)0); | |
271 | if (!checkframe(&frame)) | |
272 | return ((struct frame *)0); | |
273 | return (&frame); | |
274 | } | |
275 | ||
276 | /* | |
277 | * Check a call frame to see if it's ok as | |
278 | * a kernel stack frame. | |
279 | */ | |
280 | checkframe(fp) | |
281 | register struct frame *fp; | |
282 | { | |
283 | ||
284 | if (fp->fr_handler != 0 || fp->fr_s == 0) | |
285 | return (0); | |
286 | if (!kstackaddr(fp->fr_savap) || !kstackaddr(fp->fr_savfp)) | |
287 | return (0); | |
288 | return (within(fp->fr_savpc, txtmap.b1, txtmap.e1)); | |
289 | } | |
290 | ||
291 | /* | |
292 | * Check if an address is in one of the kernel's stacks: | |
293 | * interrupt stack, rpb stack (during restart sequence), | |
294 | * or u. stack. | |
295 | */ | |
296 | kstackaddr(addr) | |
297 | caddr_t addr; | |
298 | { | |
299 | ||
300 | return (within(addr, intstack, eintstack) || | |
301 | within(addr, rpb + sizeof (struct rpb), scb) || | |
302 | within(addr, ustack, eustack)); | |
303 | } | |
304 | ||
af975fa6 BJ |
305 | create(f) |
306 | char *f; | |
307 | { | |
308 | register int fd; | |
309 | ||
310 | fd = creat(f, 0644); | |
311 | if (fd < 0) | |
312 | return (-1); | |
313 | close(fd); | |
314 | return (open(f, wtflag)); | |
315 | } | |
316 | ||
317 | getfile(filnam, cnt) | |
318 | char *filnam; | |
319 | { | |
320 | register int fsym; | |
321 | ||
322 | if (eqstr(filnam, "-")) | |
323 | return (-1); | |
324 | fsym = open(filnam, wtflag); | |
325 | if (fsym < 0 && xargc > cnt) { | |
326 | if (wtflag) | |
327 | fsym = create(filnam); | |
328 | if (fsym < 0) | |
329 | printf("cannot open `%s'\n", filnam); | |
330 | } | |
331 | return (fsym); | |
332 | } | |
333 | ||
334 | setvar() | |
335 | { | |
336 | ||
337 | var[varchk('b')] = datbas; | |
338 | var[varchk('d')] = filhdr.a_data; | |
339 | var[varchk('e')] = filhdr.a_entry; | |
340 | var[varchk('m')] = filhdr.a_magic; | |
341 | var[varchk('s')] = stksiz; | |
342 | var[varchk('t')] = filhdr.a_text; | |
343 | } |