xref: /dragonfly/sbin/jscan/dump_debug.c (revision 2ee85085)
1 /*
2  * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $DragonFly: src/sbin/jscan/dump_debug.c,v 1.3 2005/07/05 00:26:03 dillon Exp $
35  */
36 
37 #include "jscan.h"
38 
39 static void dump_debug_stream(struct jstream *js);
40 static int dump_debug_subrecord(struct jstream *js, off_t *off,
41 				off_t recsize, int level);
42 
43 void
44 dump_debug(struct jfile *jf)
45 {
46     struct jstream *js;
47 
48     while ((js = jscan_stream(jf)) != NULL) {
49 	dump_debug_stream(js);
50 	jscan_dispose(js);
51     }
52 }
53 
54 static void
55 dump_debug_stream(struct jstream *js)
56 {
57 	struct journal_rawrecbeg head;
58 	int16_t sid;
59 
60 	jsread(js, 0, &head, sizeof(head));
61 
62 	sid = head.streamid & JREC_STREAMID_MASK;
63 	printf("STREAM %04x {\n", (int)(u_int16_t)head.streamid);
64 	if (sid >= JREC_STREAMID_JMIN && sid < JREC_STREAMID_JMAX) {
65 	    off_t off = sizeof(head);
66 
67 	    dump_debug_subrecord(js, &off,
68 			js->js_normalized_total - sizeof(head),
69 			1);
70 	} else {
71 	    switch(head.streamid & JREC_STREAMID_MASK) {
72 	    case JREC_STREAMID_SYNCPT & JREC_STREAMID_MASK:
73 		printf("    SYNCPT\n");
74 		break;
75 	    case JREC_STREAMID_PAD & JREC_STREAMID_MASK:
76 		printf("    PAD\n");
77 		break;
78 	    case JREC_STREAMID_DISCONT & JREC_STREAMID_MASK:
79 		printf("    DISCONT\n");
80 		break;
81 	    case JREC_STREAMID_ANNOTATE & JREC_STREAMID_MASK:
82 		printf("    ANNOTATION\n");
83 		break;
84 	    default:
85 		printf("    UNKNOWN\n");
86 		break;
87 	    }
88 	}
89 	printf("}\n");
90 }
91 
92 static int
93 dump_debug_subrecord(struct jstream *js, off_t *off, off_t recsize, int level)
94 {
95     struct journal_subrecord sub;
96     int payload;
97     int subsize;
98     int error;
99     off_t base = *off;
100 
101     error = 0;
102     while (recsize > 0) {
103 	if ((error = jsread(js, base, &sub, sizeof(sub))) != 0) {
104 	    break;
105 	}
106 	printf("%*.*s", level * 4, level * 4, "");
107 	printf("@%lld ", base);
108 	printf("RECORD %s [%04x/%d]", type_to_name(sub.rectype),
109 				(int)(u_int16_t)sub.rectype, sub.recsize);
110 	if (sub.recsize == -1) {
111 	    if ((sub.rectype & JMASK_NESTED) == 0) {
112 		printf("Record size of -1 only works for nested records\n");
113 		error = -1;
114 		break;
115 	    }
116 	    payload = 0x7FFFFFFF;
117 	    subsize = 0x7FFFFFFF;
118 	} else {
119 	    payload = sub.recsize - sizeof(sub);
120 	    subsize = (sub.recsize + 7) & ~7;
121 	}
122 	if (sub.rectype & JMASK_NESTED) {
123 	    printf(" {\n");
124 	    if (payload) {
125 		*off = base + sizeof(sub);
126 		error = dump_debug_subrecord(js, off, payload, level + 1);
127 	    }
128 	    printf("%*.*s}\n", level * 4, level * 4, "");
129 	} else if (sub.rectype & JMASK_SUBRECORD) {
130 	    printf(" DATA (%d)", payload);
131 	    error = dump_debug_payload(sub.rectype, js, base + sizeof(sub), payload, level);
132 	    *off = base + sizeof(sub) + payload;
133 	    printf("\n");
134 	} else {
135 	    printf("[%d bytes of unknown content]\n", sub.recsize);
136 	}
137 	if (error)
138 	    break;
139 	if (sub.recsize == -1) {
140 	    recsize -= ((*off + 7) & ~7) - base;
141 	    base = (*off + 7) & ~7;
142 	} else {
143 	    if (subsize == 0)
144 		subsize = sizeof(sub);
145 	    recsize -= subsize;
146 	    base += subsize;
147 	}
148 	if (sub.rectype & JMASK_LAST)
149 		break;
150     }
151     *off = base;
152     return(error);
153 }
154 
155 int
156 dump_debug_payload(int16_t rectype, struct jstream *js, off_t off,
157 	     int recsize, int level)
158 {
159     enum { DT_NONE, DT_STRING, DT_DEC, DT_HEX, DT_OCT,
160 	   DT_DATA, DT_TIMESTAMP } dt = DT_DATA;
161     const char *buf;
162     int error;
163     int i;
164     int j;
165 
166     error = jsreadp(js, off, (const void **)&buf, recsize);
167     if (error)
168 	return (error);
169 
170     switch(rectype & ~JMASK_LAST) {
171     case JLEAF_PAD:
172     case JLEAF_ABORT:
173 	break;
174     case JLEAF_FILEDATA:
175 	break;
176     case JLEAF_PATH1:
177     case JLEAF_PATH2:
178     case JLEAF_PATH3:
179     case JLEAF_PATH4:
180 	dt = DT_STRING;
181 	break;
182     case JLEAF_UID:
183     case JLEAF_GID:
184     case JLEAF_VTYPE:
185 	dt = DT_DEC;
186 	break;
187     case JLEAF_MODES:
188 	dt = DT_OCT;
189 	break;
190     case JLEAF_FFLAGS:
191 	dt = DT_HEX;
192 	break;
193     case JLEAF_PID:
194     case JLEAF_PPID:
195 	dt = DT_DEC;
196 	break;
197     case JLEAF_COMM:
198 	dt = DT_STRING;
199 	break;
200     case JLEAF_ATTRNAME:
201 	dt = DT_STRING;
202 	break;
203     case JLEAF_PATH_REF:
204 	dt = DT_STRING;
205 	break;
206     case JLEAF_RESERVED_0F:
207 	break;
208     case JLEAF_SYMLINKDATA:
209 	dt = DT_STRING;
210 	break;
211     case JLEAF_SEEKPOS:
212 	dt = DT_HEX;
213 	break;
214     case JLEAF_INUM:
215 	dt = DT_HEX;
216 	break;
217     case JLEAF_NLINK:
218 	dt = DT_DEC;
219 	break;
220     case JLEAF_FSID:
221 	dt = DT_HEX;
222 	break;
223     case JLEAF_SIZE:
224 	dt = DT_HEX;
225 	break;
226     case JLEAF_ATIME:
227     case JLEAF_MTIME:
228     case JLEAF_CTIME:
229 	dt = DT_TIMESTAMP;
230 	break;
231     case JLEAF_GEN:
232 	dt = DT_HEX;
233 	break;
234     case JLEAF_FLAGS:
235 	dt = DT_HEX;
236 	break;
237     case JLEAF_UDEV:
238 	dt = DT_HEX;
239 	break;
240     case JLEAF_FILEREV:
241 	dt = DT_HEX;
242 	break;
243     default:
244 	break;
245     }
246     switch(dt) {
247     case DT_NONE:
248 	break;
249     case DT_STRING:
250 	printf(" \"");
251 	for (i = 0; i < recsize; ++i)
252 	    stringout(stdout, buf[i], 1);
253 	printf("\"");
254 	break;
255     case DT_DEC:
256 	switch(recsize) {
257 	case 1:
258 	    printf(" %d", (int)*(const u_int8_t *)buf);
259 	    break;
260 	case 2:
261 	    printf(" %d", (int)*(const u_int16_t *)buf);
262 	    break;
263 	case 4:
264 	    printf(" %d", (int)*(const u_int32_t *)buf);
265 	    break;
266 	case 8:
267 	    printf(" %lld", (int64_t)*(const u_int64_t *)buf);
268 	    break;
269 	default:
270 	    printf(" ?");
271 	    break;
272 	}
273 	break;
274     case DT_HEX:
275 	switch(recsize) {
276 	case 1:
277 	    printf(" 0x%02x", (int)*(const u_int8_t *)buf);
278 	    break;
279 	case 2:
280 	    printf(" 0x%04x", (int)*(const u_int16_t *)buf);
281 	    break;
282 	case 4:
283 	    printf(" 0x%08x", (int)*(const u_int32_t *)buf);
284 	    break;
285 	case 8:
286 	    printf(" 0x%016llx", (int64_t)*(const u_int64_t *)buf);
287 	    break;
288 	default:
289 	    printf(" ?");
290 	    break;
291 	}
292 	break;
293     case DT_OCT:
294 	switch(recsize) {
295 	case 1:
296 	    printf(" %03o", (int)*(const u_int8_t *)buf);
297 	    break;
298 	case 2:
299 	    printf(" %06o", (int)*(const u_int16_t *)buf);
300 	    break;
301 	case 4:
302 	    printf(" %011o", (int)*(const u_int32_t *)buf);
303 	    break;
304 	case 8:
305 	    printf(" %022llo", (int64_t)*(const u_int64_t *)buf);
306 	    break;
307 	default:
308 	    printf(" ?");
309 	    break;
310 	}
311 	break;
312     case DT_TIMESTAMP:
313 	{
314 	    struct tm *tp;
315 	    time_t t = ((const struct timespec *)buf)->tv_sec;
316 	    char outbuf[64];
317 
318 	    tp = localtime(&t);
319 	    strftime(outbuf, sizeof(outbuf), " <%d-%b-%Y %H:%M:%S>", tp);
320 	    printf("%s", outbuf);
321 	}
322 	break;
323     case DT_DATA:
324     default:
325 	if (recsize < 16) {
326 	    for (i = 0; i < recsize; ++i)
327 		printf(" %02x", (int)(unsigned char)buf[i]);
328 	    printf(" \"");
329 	    for (i = 0; i < recsize; ++i)
330 		stringout(stdout, buf[i], 0);
331 	    printf("\"");
332 	} else {
333 	    printf(" {\n");
334 	    for (i = 0; i < recsize; i += 16) {
335 		printf("%*.*s", level * 4 + 4, level * 4 + 4, "");
336 		for (j = i; j < i + 16 && j < recsize; ++j)
337 		    printf(" %02x", (int)(unsigned char)buf[j]);
338 		for (; j < i + 16; ++j)
339 		    printf("   ");
340 		printf(" \"");
341 		for (j = i; j < i + 16 && j < recsize; ++j)
342 		    stringout(stdout, buf[j], 0);
343 		printf("\"\n");
344 	    }
345 	    printf("%*.*s}", level * 4, level * 4, "");
346 	}
347 	break;
348     }
349     return (0);
350 }
351 
352