1 | /*
|
---|
2 | * core.c for mdb
|
---|
3 | *
|
---|
4 | * reads information from 'core' file
|
---|
5 | * Partly derived from 'adb' by D. Dugger.
|
---|
6 | */
|
---|
7 | #include <pm/const.h>
|
---|
8 |
|
---|
9 | #include "mdb.h"
|
---|
10 |
|
---|
11 | #include <signal.h>
|
---|
12 | #include <fcntl.h>
|
---|
13 | #include <stdlib.h>
|
---|
14 | #include <unistd.h>
|
---|
15 | #include <stdio.h>
|
---|
16 | #include <string.h>
|
---|
17 | #include <sys/ptrace.h>
|
---|
18 |
|
---|
19 | #include <pm/type.h>
|
---|
20 | #include <pm/mproc.h>
|
---|
21 |
|
---|
22 | #include <kernel/const.h>
|
---|
23 | #include <kernel/type.h>
|
---|
24 | #include <kernel/proc.h>
|
---|
25 |
|
---|
26 | /* defined in kernel.c */
|
---|
27 | extern struct proc *prc;
|
---|
28 |
|
---|
29 | #include "proto.h"
|
---|
30 |
|
---|
31 | #define BSIZE 512
|
---|
32 | #define LOGBS 9
|
---|
33 |
|
---|
34 | PRIVATE struct file {
|
---|
35 | int fid;
|
---|
36 | char *name;
|
---|
37 | long cblock;
|
---|
38 | long tmap[3];
|
---|
39 | long dmap[3];
|
---|
40 | long smap[3];
|
---|
41 | char buf[BSIZE + BSIZE];
|
---|
42 | } Core_File, *core_file;
|
---|
43 |
|
---|
44 | #define b1 tmap[0]
|
---|
45 | #define e1 tmap[1]
|
---|
46 | #define f1 tmap[2]
|
---|
47 | #define b2 dmap[0]
|
---|
48 | #define e2 dmap[1]
|
---|
49 | #define f2 dmap[2]
|
---|
50 | #define b3 smap[0]
|
---|
51 | #define e3 smap[1]
|
---|
52 | #define f3 smap[2]
|
---|
53 |
|
---|
54 | PRIVATE long cnt[3]; /* Sizes of segments */
|
---|
55 | PRIVATE int h_size; /* Size of core header */
|
---|
56 | PRIVATE char def_name[] = "core"; /* Default core name */
|
---|
57 |
|
---|
58 | #define SIZE_MP_SEG (sizeof(struct mem_map) * NR_LOCAL_SEGS)
|
---|
59 | #define SIZE_KINFO sizeof(struct proc)
|
---|
60 | #define SIZE_HEADER SIZE_MP_SEG
|
---|
61 |
|
---|
62 | FORWARD _PROTOTYPE( int kernel_info , (int fd ));
|
---|
63 | FORWARD _PROTOTYPE( void setmap , (struct file *fp ));
|
---|
64 | FORWARD _PROTOTYPE( void read_info , (struct file *fp ));
|
---|
65 | FORWARD _PROTOTYPE( void ill_addr , (long d , int segment ));
|
---|
66 | FORWARD _PROTOTYPE( long map_addr , (long d , int segment ));
|
---|
67 | FORWARD _PROTOTYPE( unsigned long c_status, (void));
|
---|
68 | FORWARD _PROTOTYPE( long getn, (long d, int s) );
|
---|
69 |
|
---|
70 | /*
|
---|
71 | * set and display mapping for core file
|
---|
72 | */
|
---|
73 | PRIVATE void setmap(fp)
|
---|
74 | struct file *fp;
|
---|
75 | {
|
---|
76 | long h = (long) h_size;
|
---|
77 |
|
---|
78 | fp->b1 = st_addr;
|
---|
79 | fp->e1 = st_addr + cnt[T];
|
---|
80 | fp->f1 = h;
|
---|
81 |
|
---|
82 | fp->b2 = sd_addr;
|
---|
83 | fp->e2 = sd_addr + cnt[D];
|
---|
84 | fp->f2 = cnt[T] + h;
|
---|
85 |
|
---|
86 | fp->b3 = sk_addr;
|
---|
87 | fp->e3 = sk_addr + cnt[S];
|
---|
88 | fp->f3 = cnt[T] + cnt[D] + h;
|
---|
89 |
|
---|
90 | #ifdef MINIX_PC
|
---|
91 | if(is_separate) {
|
---|
92 | if ( end_addr < et_addr ) end_addr = et_addr;
|
---|
93 | }
|
---|
94 | else {
|
---|
95 | fp->b2 = st_addr;
|
---|
96 | fp->e2 = st_addr + cnt[T] + cnt[D];
|
---|
97 | fp->f2 = h;
|
---|
98 | end_addr = fp->e2;
|
---|
99 |
|
---|
100 | fp->b1 = 0;
|
---|
101 | fp->e1 = -1;
|
---|
102 | fp->f1 = 0;
|
---|
103 | }
|
---|
104 | #endif
|
---|
105 | Printf("From core file:\n");
|
---|
106 | Printf("T\t%8lx %8lx %8lx\n", core_file->b1, core_file->e1, core_file->f1);
|
---|
107 | Printf("D\t%8lx %8lx %8lx\n", core_file->b2, core_file->e2, core_file->f2);
|
---|
108 | Printf("S\t%8lx %8lx %8lx\n", core_file->b3, core_file->e3, core_file->f3);
|
---|
109 | Printf("\n");
|
---|
110 |
|
---|
111 | }
|
---|
112 |
|
---|
113 | /* Print mapping */
|
---|
114 | PUBLIC void prtmap()
|
---|
115 | {
|
---|
116 | Printf("%s I & D space\t", (is_separate) ? "Separate " : "Combined ");
|
---|
117 | if (corepid > 0) {
|
---|
118 | Printf("File: %s\n\n", core_file->name);
|
---|
119 | setmap(core_file);
|
---|
120 | disp_maps();
|
---|
121 | }
|
---|
122 | else {
|
---|
123 | Printf("Pid: %d\n\n", curpid);
|
---|
124 | update();
|
---|
125 | disp_maps();
|
---|
126 | }
|
---|
127 | }
|
---|
128 |
|
---|
129 | /* Illegal address */
|
---|
130 | PRIVATE void ill_addr(d, segment)
|
---|
131 | long d;
|
---|
132 | int segment;
|
---|
133 | {
|
---|
134 | Printf("Bad addr=%lx seg=%d",d,segment);
|
---|
135 | mdb_error("\n");
|
---|
136 | }
|
---|
137 |
|
---|
138 | /* Map virtual address -> core file addresses
|
---|
139 | * depends on current segment if Separate I & D
|
---|
140 | */
|
---|
141 | PRIVATE long map_addr(d, segment)
|
---|
142 | long d;
|
---|
143 | int segment;
|
---|
144 | {
|
---|
145 | #ifdef MINIX_PC
|
---|
146 | if (is_separate)
|
---|
147 | switch (segment) {
|
---|
148 | case T:
|
---|
149 | if (d >= core_file->b1 && d < core_file->e1)
|
---|
150 | d += core_file->f1 - core_file->b1;
|
---|
151 | else
|
---|
152 | ill_addr(d,segment);
|
---|
153 | break;
|
---|
154 | case D:
|
---|
155 | case S:
|
---|
156 | if (d >= core_file->b2 && d < core_file->e2)
|
---|
157 | d += core_file->f2 - core_file->b2;
|
---|
158 | else if (d >= core_file->b3 && d < core_file->e3)
|
---|
159 | d += core_file->f3 - core_file->b3;
|
---|
160 | else
|
---|
161 | ill_addr(d,segment);
|
---|
162 | break;
|
---|
163 | }
|
---|
164 | else {
|
---|
165 | #endif
|
---|
166 | if (d >= core_file->b1 && d < core_file->e1)
|
---|
167 | d += core_file->f1 - core_file->b1;
|
---|
168 | else if (d >= core_file->b2 && d < core_file->e2)
|
---|
169 | d += core_file->f2 - core_file->b2;
|
---|
170 | else if (d >= core_file->b3 && d < core_file->e3)
|
---|
171 | d += core_file->f3 - core_file->b3;
|
---|
172 | else
|
---|
173 | ill_addr(d,segment);
|
---|
174 | #ifdef MINIX_PC
|
---|
175 | }
|
---|
176 | #endif
|
---|
177 | return d;
|
---|
178 | }
|
---|
179 |
|
---|
180 |
|
---|
181 | /* Get value with address d and segment s */
|
---|
182 | PRIVATE long getn(d, s)
|
---|
183 | long d;
|
---|
184 | int s;
|
---|
185 | {
|
---|
186 | long b;
|
---|
187 | register int o,i;
|
---|
188 | union {
|
---|
189 | unsigned long l;
|
---|
190 | unsigned char c[4];
|
---|
191 | } data;
|
---|
192 |
|
---|
193 | /* Map address */
|
---|
194 | d = map_addr(d, s);
|
---|
195 |
|
---|
196 | b = d >> LOGBS;
|
---|
197 | o = d & (BSIZE - 1);
|
---|
198 |
|
---|
199 | if (core_file->cblock != b) {
|
---|
200 | core_file->cblock = b;
|
---|
201 | lseek(core_file->fid, b << LOGBS, 0);
|
---|
202 | read(core_file->fid, core_file->buf, sizeof(core_file->buf));
|
---|
203 | }
|
---|
204 |
|
---|
205 | for(i = 0; i<4; i++)
|
---|
206 | data.c[i] = core_file->buf[o+i];
|
---|
207 |
|
---|
208 | #ifdef DEBUG
|
---|
209 | if (debug)
|
---|
210 | Printf("getn at %8lx val %8lx\n", d, data.l);
|
---|
211 | #endif
|
---|
212 | return data.l;
|
---|
213 | }
|
---|
214 |
|
---|
215 | /* Read kernel info from core file into lbuf[] */
|
---|
216 | PRIVATE int kernel_info(fd)
|
---|
217 | int fd;
|
---|
218 | {
|
---|
219 | int r;
|
---|
220 | int ks;
|
---|
221 |
|
---|
222 | /* Round SIZE_KINFO to multiple of sizeof(long) */
|
---|
223 | /* See mm/signal.c to see how a 'core' file is written */
|
---|
224 | ks = ( SIZE_KINFO / sizeof(long) ) * sizeof(long);
|
---|
225 | r = read(fd, (char *)lbuf, ks);
|
---|
226 | return(r == ks) ? ks : -1;
|
---|
227 | }
|
---|
228 |
|
---|
229 | /*
|
---|
230 | * Print status info from core - returns PC
|
---|
231 | */
|
---|
232 | PRIVATE unsigned long c_status()
|
---|
233 | {
|
---|
234 | fprintf(stderr, "WARNING: don't know pid from core; using proc nr for pid.\n");
|
---|
235 |
|
---|
236 | Printf("Proc = %6d\n", prc->p_nr);
|
---|
237 |
|
---|
238 | /* Set current pid to that of core */
|
---|
239 | curpid = corepid = prc->p_nr;
|
---|
240 | disp_maps();
|
---|
241 | Printf("\nPC = 0x%0*lx\t", 2 * ADDRSIZE, PC_MEMBER(prc) & MASK(ADDRSIZE));
|
---|
242 | symbolic((long) PC_MEMBER(prc), '\n');
|
---|
243 | dasm((long) PC_MEMBER(prc), 1, 1);
|
---|
244 | return PC_MEMBER(prc);
|
---|
245 | }
|
---|
246 |
|
---|
247 | /* Read memory maps and kernel info from core file */
|
---|
248 | PRIVATE void read_info(fp)
|
---|
249 | struct file *fp;
|
---|
250 | {
|
---|
251 | struct mproc mm_info;
|
---|
252 | struct mproc *rmp;
|
---|
253 | int r;
|
---|
254 | int i;
|
---|
255 |
|
---|
256 | rmp = &mm_info;
|
---|
257 | lseek(fp->fid, 0L, 0L);
|
---|
258 |
|
---|
259 | /* First read memory map of all segments. */
|
---|
260 | if (read(fp->fid, (char *) rmp->mp_seg, (int) SIZE_MP_SEG) < 0) {
|
---|
261 | close(fp->fid);
|
---|
262 | Printf("mdb: cannot read core header\n");
|
---|
263 | fp->fid = -1;
|
---|
264 | return;
|
---|
265 | }
|
---|
266 | h_size = SIZE_HEADER;
|
---|
267 |
|
---|
268 | /* Read kernel dependent info */
|
---|
269 | r = kernel_info(fp->fid);
|
---|
270 | if (r < 0) {
|
---|
271 | close(fp->fid);
|
---|
272 | Printf("mdb: cannot read kernel info from 'core' file\n");
|
---|
273 | fp->fid = -1;
|
---|
274 | return;
|
---|
275 | } else
|
---|
276 | h_size += r;
|
---|
277 |
|
---|
278 | /* copy info */
|
---|
279 | for (i = T; i <= S; i++)
|
---|
280 | cnt[i] = (long) rmp->mp_seg[i].mem_len << CLICK_SHIFT;
|
---|
281 |
|
---|
282 | /* This needs to be set for map_addr() below */
|
---|
283 | if(coreonly && cnt[T] != 0) is_separate = TRUE;
|
---|
284 |
|
---|
285 | st_addr = (long) rmp->mp_seg[T].mem_vir << CLICK_SHIFT;
|
---|
286 | et_addr = st_addr + ((long) rmp->mp_seg[T].mem_len << CLICK_SHIFT);
|
---|
287 |
|
---|
288 | sd_addr = (long) rmp->mp_seg[D].mem_vir << CLICK_SHIFT;
|
---|
289 | end_addr = ed_addr =
|
---|
290 | sd_addr + ((long) rmp->mp_seg[D].mem_len << CLICK_SHIFT);
|
---|
291 |
|
---|
292 | sk_addr = (long) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
|
---|
293 | sk_size = (long) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
|
---|
294 |
|
---|
295 | setmap(fp);
|
---|
296 | }
|
---|
297 |
|
---|
298 | /* initialization for core files
|
---|
299 | * returns PC address from core file
|
---|
300 | */
|
---|
301 | PUBLIC unsigned long core_init(filename)
|
---|
302 | char *filename;
|
---|
303 | {
|
---|
304 | core_file = &Core_File;
|
---|
305 | core_file->name = (filename != NULL) ? filename : def_name;
|
---|
306 |
|
---|
307 | core_file->fid = open(core_file->name, 0);
|
---|
308 | if (filename != NULL && core_file->fid < 0) {
|
---|
309 | Printf("mdb - warning cannot open: %s\n", core_file->name);
|
---|
310 | return -1;
|
---|
311 | }
|
---|
312 |
|
---|
313 | core_file->b1 = core_file->b2 = core_file->b3 = 0;
|
---|
314 | core_file->e1 = core_file->e2 = core_file->e3 = -1;
|
---|
315 | core_file->f1 = core_file->f2 = core_file->f3 = 0;
|
---|
316 | core_file->cblock = -1;
|
---|
317 |
|
---|
318 | if (core_file->fid > 0) {
|
---|
319 | read_info(core_file);
|
---|
320 | return c_status();
|
---|
321 | }
|
---|
322 | return 0;
|
---|
323 | }
|
---|
324 |
|
---|
325 |
|
---|
326 | /* initialization for a file ( -f option )
|
---|
327 | * always returns 0
|
---|
328 | * Similar to core files.
|
---|
329 | */
|
---|
330 | PUBLIC unsigned long file_init(filename)
|
---|
331 | char *filename;
|
---|
332 | {
|
---|
333 | core_file = &Core_File;
|
---|
334 | core_file->name = (filename != NULL) ? filename : def_name;
|
---|
335 |
|
---|
336 | core_file->fid = open(core_file->name, 0);
|
---|
337 | if (filename != NULL && core_file->fid < 0) {
|
---|
338 | Printf("mdb - warning cannot open: %s\n", core_file->name);
|
---|
339 | return -1;
|
---|
340 | }
|
---|
341 |
|
---|
342 | core_file->b1 = core_file->b2 = core_file->b3 = 0;
|
---|
343 | core_file->e1 = core_file->e2 = core_file->e3 = -1;
|
---|
344 | core_file->f1 = core_file->f2 = core_file->f3 = 0;
|
---|
345 | core_file->cblock = -1;
|
---|
346 |
|
---|
347 | is_separate = FALSE;
|
---|
348 | core_file->e1 = file_size(core_file->fid);
|
---|
349 | curpid = corepid = 1;
|
---|
350 | return 0;
|
---|
351 |
|
---|
352 | }
|
---|
353 |
|
---|
354 | /*
|
---|
355 | * Read from core file
|
---|
356 | * Called by mdbtrace()
|
---|
357 | */
|
---|
358 | PUBLIC long read_core(req, addr, data)
|
---|
359 | int req;
|
---|
360 | long addr, data;
|
---|
361 | {
|
---|
362 | int i;
|
---|
363 | int segment;
|
---|
364 | long val;
|
---|
365 |
|
---|
366 | switch (req) {
|
---|
367 | case T_GETINS:
|
---|
368 | case T_GETDATA:
|
---|
369 | /* Check segment and address - call getn to read core file */
|
---|
370 | segment = (req == T_GETINS) ? T : D;
|
---|
371 | addr &= MASK(ADDRSIZE);
|
---|
372 | val = getn(addr, segment);
|
---|
373 | #ifdef DEBUG
|
---|
374 | if (debug) Printf("val=>%lx\n", val);
|
---|
375 | #endif
|
---|
376 | return val;
|
---|
377 | break;
|
---|
378 | case T_GETUSER:
|
---|
379 | /* Convert addr to index to long array */
|
---|
380 | i = (int) (addr >> 2);
|
---|
381 | #ifdef DEBUG
|
---|
382 | if (debug) Printf("lbuf[%d] %lx\n", i, lbuf[i]);
|
---|
383 | #endif
|
---|
384 | return lbuf[i];
|
---|
385 | break;
|
---|
386 | case T_OK:
|
---|
387 | case T_EXIT:
|
---|
388 | return 0L;
|
---|
389 | break;
|
---|
390 | default:
|
---|
391 | mdb_error("Not supported with 'core' files\n");
|
---|
392 | }
|
---|
393 | }
|
---|
394 |
|
---|