xref: /freebsd/sys/ddb/db_pprint.c (revision c21bc6f3c2425de74141bfee07b609bf65b5a6b3)
1*c21bc6f3SBojan Novković /*-
2*c21bc6f3SBojan Novković  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*c21bc6f3SBojan Novković  *
4*c21bc6f3SBojan Novković  * Copyright (c) 2022 Bojan Novković <bnovkov@freebsd.org>
5*c21bc6f3SBojan Novković  *
6*c21bc6f3SBojan Novković  * Redistribution and use in source and binary forms, with or without
7*c21bc6f3SBojan Novković  * modification, are permitted provided that the following conditions
8*c21bc6f3SBojan Novković  * are met:
9*c21bc6f3SBojan Novković  * 1. Redistributions of source code must retain the above copyright
10*c21bc6f3SBojan Novković  *    notice, this list of conditions and the following disclaimer.
11*c21bc6f3SBojan Novković  * 2. Redistributions in binary form must reproduce the above copyright
12*c21bc6f3SBojan Novković  *    notice, this list of conditions and the following disclaimer in the
13*c21bc6f3SBojan Novković  *    documentation and/or other materials provided with the distribution.
14*c21bc6f3SBojan Novković  *
15*c21bc6f3SBojan Novković  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*c21bc6f3SBojan Novković  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*c21bc6f3SBojan Novković  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*c21bc6f3SBojan Novković  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*c21bc6f3SBojan Novković  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*c21bc6f3SBojan Novković  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*c21bc6f3SBojan Novković  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*c21bc6f3SBojan Novković  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*c21bc6f3SBojan Novković  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*c21bc6f3SBojan Novković  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*c21bc6f3SBojan Novković  * SUCH DAMAGE.
26*c21bc6f3SBojan Novković  */
27*c21bc6f3SBojan Novković 
28*c21bc6f3SBojan Novković #include <sys/param.h>
29*c21bc6f3SBojan Novković #include <sys/systm.h>
30*c21bc6f3SBojan Novković #include <sys/ctype.h>
31*c21bc6f3SBojan Novković #include <sys/linker.h>
32*c21bc6f3SBojan Novković 
33*c21bc6f3SBojan Novković #include <machine/stdarg.h>
34*c21bc6f3SBojan Novković 
35*c21bc6f3SBojan Novković #include <ddb/ddb.h>
36*c21bc6f3SBojan Novković #include <ddb/db_ctf.h>
37*c21bc6f3SBojan Novković #include <ddb/db_lex.h>
38*c21bc6f3SBojan Novković #include <ddb/db_sym.h>
39*c21bc6f3SBojan Novković #include <ddb/db_access.h>
40*c21bc6f3SBojan Novković 
41*c21bc6f3SBojan Novković #define DB_PPRINT_DEFAULT_DEPTH 1
42*c21bc6f3SBojan Novković 
43*c21bc6f3SBojan Novković static void db_pprint_type(db_addr_t addr, struct ctf_type_v3 *type,
44*c21bc6f3SBojan Novković     u_int depth);
45*c21bc6f3SBojan Novković 
46*c21bc6f3SBojan Novković static u_int max_depth = DB_PPRINT_DEFAULT_DEPTH;
47*c21bc6f3SBojan Novković static struct db_ctf_sym_data sym_data;
48*c21bc6f3SBojan Novković 
49*c21bc6f3SBojan Novković /*
50*c21bc6f3SBojan Novković  * Pretty-prints a CTF_INT type.
51*c21bc6f3SBojan Novković  */
52*c21bc6f3SBojan Novković static inline void
53*c21bc6f3SBojan Novković db_pprint_int(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
54*c21bc6f3SBojan Novković {
55*c21bc6f3SBojan Novković 	uint32_t data;
56*c21bc6f3SBojan Novković 	size_t type_struct_size;
57*c21bc6f3SBojan Novković 
58*c21bc6f3SBojan Novković 	type_struct_size = (type->ctt_size == CTF_V3_LSIZE_SENT) ?
59*c21bc6f3SBojan Novković 		sizeof(struct ctf_type_v3) :
60*c21bc6f3SBojan Novković 		sizeof(struct ctf_stype_v3);
61*c21bc6f3SBojan Novković 
62*c21bc6f3SBojan Novković 	data = db_get_value((db_expr_t)type + type_struct_size,
63*c21bc6f3SBojan Novković 		sizeof(uint32_t), 0);
64*c21bc6f3SBojan Novković 	u_int bits = CTF_INT_BITS(data);
65*c21bc6f3SBojan Novković 	boolean_t sign = !!(CTF_INT_ENCODING(data) & CTF_INT_SIGNED);
66*c21bc6f3SBojan Novković 
67*c21bc6f3SBojan Novković 	if (db_pager_quit) {
68*c21bc6f3SBojan Novković 		return;
69*c21bc6f3SBojan Novković 	}
70*c21bc6f3SBojan Novković 	if (bits > 64) {
71*c21bc6f3SBojan Novković 		db_printf("Invalid size '%d' found for integer type\n", bits);
72*c21bc6f3SBojan Novković 		return;
73*c21bc6f3SBojan Novković 	}
74*c21bc6f3SBojan Novković 	db_printf("0x%lx",
75*c21bc6f3SBojan Novković 	    db_get_value(addr, (bits / 8) ? (bits / 8) : 1, sign));
76*c21bc6f3SBojan Novković }
77*c21bc6f3SBojan Novković 
78*c21bc6f3SBojan Novković /*
79*c21bc6f3SBojan Novković  * Pretty-prints a struct. Nested structs are pretty-printed up 'depth' nested
80*c21bc6f3SBojan Novković  * levels.
81*c21bc6f3SBojan Novković  */
82*c21bc6f3SBojan Novković static inline void
83*c21bc6f3SBojan Novković db_pprint_struct(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
84*c21bc6f3SBojan Novković {
85*c21bc6f3SBojan Novković 	size_t type_struct_size;
86*c21bc6f3SBojan Novković 	size_t struct_size;
87*c21bc6f3SBojan Novković 	struct ctf_type_v3 *mtype;
88*c21bc6f3SBojan Novković 	const char *mname;
89*c21bc6f3SBojan Novković 	db_addr_t maddr;
90*c21bc6f3SBojan Novković 	u_int vlen;
91*c21bc6f3SBojan Novković 
92*c21bc6f3SBojan Novković 	type_struct_size = (type->ctt_size == CTF_V3_LSIZE_SENT) ?
93*c21bc6f3SBojan Novković 		sizeof(struct ctf_type_v3) :
94*c21bc6f3SBojan Novković 		sizeof(struct ctf_stype_v3);
95*c21bc6f3SBojan Novković 	struct_size = ((type->ctt_size == CTF_V3_LSIZE_SENT) ?
96*c21bc6f3SBojan Novković 		CTF_TYPE_LSIZE(type) :
97*c21bc6f3SBojan Novković 		type->ctt_size);
98*c21bc6f3SBojan Novković 	vlen = CTF_V3_INFO_VLEN(type->ctt_info);
99*c21bc6f3SBojan Novković 
100*c21bc6f3SBojan Novković 	if (db_pager_quit) {
101*c21bc6f3SBojan Novković 		return;
102*c21bc6f3SBojan Novković 	}
103*c21bc6f3SBojan Novković 	if (depth > max_depth) {
104*c21bc6f3SBojan Novković 		db_printf("{ ... }");
105*c21bc6f3SBojan Novković 		return;
106*c21bc6f3SBojan Novković 	}
107*c21bc6f3SBojan Novković 	db_printf("{\n");
108*c21bc6f3SBojan Novković 
109*c21bc6f3SBojan Novković 	if (struct_size < CTF_V3_LSTRUCT_THRESH) {
110*c21bc6f3SBojan Novković 		struct ctf_member_v3 *mp, *endp;
111*c21bc6f3SBojan Novković 
112*c21bc6f3SBojan Novković 		mp = (struct ctf_member_v3 *)((db_addr_t)type +
113*c21bc6f3SBojan Novković 		    type_struct_size);
114*c21bc6f3SBojan Novković 		endp = mp + vlen;
115*c21bc6f3SBojan Novković 		for (; mp < endp; mp++) {
116*c21bc6f3SBojan Novković 			if (db_pager_quit) {
117*c21bc6f3SBojan Novković 				return;
118*c21bc6f3SBojan Novković 			}
119*c21bc6f3SBojan Novković 			mtype = db_ctf_typeid_to_type(&sym_data, mp->ctm_type);
120*c21bc6f3SBojan Novković 			maddr = addr + mp->ctm_offset;
121*c21bc6f3SBojan Novković 			mname = db_ctf_stroff_to_str(&sym_data, mp->ctm_name);
122*c21bc6f3SBojan Novković 			db_indent = depth;
123*c21bc6f3SBojan Novković 			if (mname != NULL) {
124*c21bc6f3SBojan Novković 				db_iprintf("%s = ", mname);
125*c21bc6f3SBojan Novković 			} else {
126*c21bc6f3SBojan Novković 				db_iprintf("");
127*c21bc6f3SBojan Novković 			}
128*c21bc6f3SBojan Novković 
129*c21bc6f3SBojan Novković 			db_pprint_type(maddr, mtype, depth + 1);
130*c21bc6f3SBojan Novković 			db_printf(",\n");
131*c21bc6f3SBojan Novković 		}
132*c21bc6f3SBojan Novković 	} else {
133*c21bc6f3SBojan Novković 		struct ctf_lmember_v3 *mp, *endp;
134*c21bc6f3SBojan Novković 
135*c21bc6f3SBojan Novković 		mp = (struct ctf_lmember_v3 *)((db_addr_t)type +
136*c21bc6f3SBojan Novković 		    type_struct_size);
137*c21bc6f3SBojan Novković 		endp = mp + vlen;
138*c21bc6f3SBojan Novković 		for (; mp < endp; mp++) {
139*c21bc6f3SBojan Novković 			if (db_pager_quit) {
140*c21bc6f3SBojan Novković 				return;
141*c21bc6f3SBojan Novković 			}
142*c21bc6f3SBojan Novković 			mtype = db_ctf_typeid_to_type(&sym_data, mp->ctlm_type);
143*c21bc6f3SBojan Novković 			maddr = addr + CTF_LMEM_OFFSET(mp);
144*c21bc6f3SBojan Novković 			mname = db_ctf_stroff_to_str(&sym_data, mp->ctlm_name);
145*c21bc6f3SBojan Novković 			db_indent = depth;
146*c21bc6f3SBojan Novković 			if (mname != NULL) {
147*c21bc6f3SBojan Novković 				db_iprintf("%s = ", mname);
148*c21bc6f3SBojan Novković 			} else {
149*c21bc6f3SBojan Novković 				db_iprintf("");
150*c21bc6f3SBojan Novković 			}
151*c21bc6f3SBojan Novković 
152*c21bc6f3SBojan Novković 			db_pprint_type(maddr, mtype, depth + 1);
153*c21bc6f3SBojan Novković 			db_printf(",");
154*c21bc6f3SBojan Novković 		}
155*c21bc6f3SBojan Novković 	}
156*c21bc6f3SBojan Novković 	db_indent = depth - 1;
157*c21bc6f3SBojan Novković 	db_iprintf("}");
158*c21bc6f3SBojan Novković }
159*c21bc6f3SBojan Novković 
160*c21bc6f3SBojan Novković /*
161*c21bc6f3SBojan Novković  * Pretty-prints an array. Each array member is printed out in a separate line
162*c21bc6f3SBojan Novković  * indented with 'depth' spaces.
163*c21bc6f3SBojan Novković  */
164*c21bc6f3SBojan Novković static inline void
165*c21bc6f3SBojan Novković db_pprint_arr(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
166*c21bc6f3SBojan Novković {
167*c21bc6f3SBojan Novković 	struct ctf_type_v3 *elem_type;
168*c21bc6f3SBojan Novković 	struct ctf_array_v3 *arr;
169*c21bc6f3SBojan Novković 	db_addr_t elem_addr, end;
170*c21bc6f3SBojan Novković 	size_t type_struct_size;
171*c21bc6f3SBojan Novković 	size_t elem_size;
172*c21bc6f3SBojan Novković 
173*c21bc6f3SBojan Novković 	type_struct_size = (type->ctt_size == CTF_V3_LSIZE_SENT) ?
174*c21bc6f3SBojan Novković 		sizeof(struct ctf_type_v3) :
175*c21bc6f3SBojan Novković 		sizeof(struct ctf_stype_v3);
176*c21bc6f3SBojan Novković 	arr = (struct ctf_array_v3 *)((db_addr_t)type + type_struct_size);
177*c21bc6f3SBojan Novković 	elem_type = db_ctf_typeid_to_type(&sym_data, arr->cta_contents);
178*c21bc6f3SBojan Novković 	elem_size = ((elem_type->ctt_size == CTF_V3_LSIZE_SENT) ?
179*c21bc6f3SBojan Novković 		CTF_TYPE_LSIZE(elem_type) :
180*c21bc6f3SBojan Novković 		elem_type->ctt_size);
181*c21bc6f3SBojan Novković 	elem_addr = addr;
182*c21bc6f3SBojan Novković 	end = addr + (arr->cta_nelems * elem_size);
183*c21bc6f3SBojan Novković 
184*c21bc6f3SBojan Novković 	db_indent = depth;
185*c21bc6f3SBojan Novković 	db_printf("[\n");
186*c21bc6f3SBojan Novković 	/* Loop through and print individual elements. */
187*c21bc6f3SBojan Novković 	for (; elem_addr < end; elem_addr += elem_size) {
188*c21bc6f3SBojan Novković 		if (db_pager_quit) {
189*c21bc6f3SBojan Novković 			return;
190*c21bc6f3SBojan Novković 		}
191*c21bc6f3SBojan Novković 		db_iprintf("");
192*c21bc6f3SBojan Novković 		db_pprint_type(elem_addr, elem_type, depth);
193*c21bc6f3SBojan Novković 		if ((elem_addr + elem_size) < end) {
194*c21bc6f3SBojan Novković 			db_printf(",\n");
195*c21bc6f3SBojan Novković 		}
196*c21bc6f3SBojan Novković 	}
197*c21bc6f3SBojan Novković 	db_printf("\n");
198*c21bc6f3SBojan Novković 	db_indent = depth - 1;
199*c21bc6f3SBojan Novković 	db_iprintf("]");
200*c21bc6f3SBojan Novković }
201*c21bc6f3SBojan Novković 
202*c21bc6f3SBojan Novković /*
203*c21bc6f3SBojan Novković  * Pretty-prints an enum value. Also prints out symbolic name of value, if any.
204*c21bc6f3SBojan Novković  */
205*c21bc6f3SBojan Novković static inline void
206*c21bc6f3SBojan Novković db_pprint_enum(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
207*c21bc6f3SBojan Novković {
208*c21bc6f3SBojan Novković 	struct ctf_enum *ep, *endp;
209*c21bc6f3SBojan Novković 	size_t type_struct_size;
210*c21bc6f3SBojan Novković 	const char *valname;
211*c21bc6f3SBojan Novković 	db_expr_t val;
212*c21bc6f3SBojan Novković 	u_int vlen;
213*c21bc6f3SBojan Novković 
214*c21bc6f3SBojan Novković 	type_struct_size = (type->ctt_size == CTF_V3_LSIZE_SENT) ?
215*c21bc6f3SBojan Novković 		sizeof(struct ctf_type_v3) :
216*c21bc6f3SBojan Novković 		sizeof(struct ctf_stype_v3);
217*c21bc6f3SBojan Novković 	vlen = CTF_V3_INFO_VLEN(type->ctt_info);
218*c21bc6f3SBojan Novković 	val = db_get_value(addr, sizeof(int), 0);
219*c21bc6f3SBojan Novković 
220*c21bc6f3SBojan Novković 	if (db_pager_quit) {
221*c21bc6f3SBojan Novković 		return;
222*c21bc6f3SBojan Novković 	}
223*c21bc6f3SBojan Novković 	ep = (struct ctf_enum *)((db_addr_t)type + type_struct_size);
224*c21bc6f3SBojan Novković 	endp = ep + vlen;
225*c21bc6f3SBojan Novković 	for (; ep < endp; ep++) {
226*c21bc6f3SBojan Novković 		if (val == ep->cte_value) {
227*c21bc6f3SBojan Novković 			valname = db_ctf_stroff_to_str(&sym_data, ep->cte_name);
228*c21bc6f3SBojan Novković 			if (valname != NULL)
229*c21bc6f3SBojan Novković 				db_printf("%s (0x%lx)", valname, val);
230*c21bc6f3SBojan Novković 			else
231*c21bc6f3SBojan Novković 				db_printf("(0x%lx)", val);
232*c21bc6f3SBojan Novković 			break;
233*c21bc6f3SBojan Novković 		}
234*c21bc6f3SBojan Novković 	}
235*c21bc6f3SBojan Novković }
236*c21bc6f3SBojan Novković 
237*c21bc6f3SBojan Novković /*
238*c21bc6f3SBojan Novković  * Pretty-prints a pointer. If the 'depth' parameter is less than the
239*c21bc6f3SBojan Novković  * 'max_depth' global var, the pointer is "dereference", i.e. the contents of
240*c21bc6f3SBojan Novković  * the memory it points to are also printed. The value of the pointer is printed
241*c21bc6f3SBojan Novković  * otherwise.
242*c21bc6f3SBojan Novković  */
243*c21bc6f3SBojan Novković static inline void
244*c21bc6f3SBojan Novković db_pprint_ptr(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
245*c21bc6f3SBojan Novković {
246*c21bc6f3SBojan Novković 	struct ctf_type_v3 *ref_type;
247*c21bc6f3SBojan Novković 	const char *qual = "";
248*c21bc6f3SBojan Novković 	const char *name;
249*c21bc6f3SBojan Novković 	db_addr_t val;
250*c21bc6f3SBojan Novković 	u_int kind;
251*c21bc6f3SBojan Novković 
252*c21bc6f3SBojan Novković 	ref_type = db_ctf_typeid_to_type(&sym_data, type->ctt_type);
253*c21bc6f3SBojan Novković 	kind = CTF_V3_INFO_KIND(ref_type->ctt_info);
254*c21bc6f3SBojan Novković 	switch (kind) {
255*c21bc6f3SBojan Novković 	case CTF_K_STRUCT:
256*c21bc6f3SBojan Novković 		qual = "struct ";
257*c21bc6f3SBojan Novković 		break;
258*c21bc6f3SBojan Novković 	case CTF_K_VOLATILE:
259*c21bc6f3SBojan Novković 		qual = "volatile ";
260*c21bc6f3SBojan Novković 		break;
261*c21bc6f3SBojan Novković 	case CTF_K_CONST:
262*c21bc6f3SBojan Novković 		qual = "const ";
263*c21bc6f3SBojan Novković 		break;
264*c21bc6f3SBojan Novković 	default:
265*c21bc6f3SBojan Novković 		break;
266*c21bc6f3SBojan Novković 	}
267*c21bc6f3SBojan Novković 
268*c21bc6f3SBojan Novković 	val = db_get_value(addr, sizeof(db_addr_t), false);
269*c21bc6f3SBojan Novković 	if (depth < max_depth) {
270*c21bc6f3SBojan Novković 		/* Print contents of memory pointed to by this pointer. */
271*c21bc6f3SBojan Novković 		db_pprint_type(addr, ref_type, depth + 1);
272*c21bc6f3SBojan Novković 	} else {
273*c21bc6f3SBojan Novković 		name = db_ctf_stroff_to_str(&sym_data, ref_type->ctt_name);
274*c21bc6f3SBojan Novković 		db_indent = depth;
275*c21bc6f3SBojan Novković 		if (name != NULL)
276*c21bc6f3SBojan Novković 			db_printf("(%s%s *) 0x%lx", qual, name, val);
277*c21bc6f3SBojan Novković 		else
278*c21bc6f3SBojan Novković 			db_printf("0x%lx", val);
279*c21bc6f3SBojan Novković 	}
280*c21bc6f3SBojan Novković }
281*c21bc6f3SBojan Novković 
282*c21bc6f3SBojan Novković /*
283*c21bc6f3SBojan Novković  * Pretty-print dispatching function.
284*c21bc6f3SBojan Novković  */
285*c21bc6f3SBojan Novković static void
286*c21bc6f3SBojan Novković db_pprint_type(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
287*c21bc6f3SBojan Novković {
288*c21bc6f3SBojan Novković 
289*c21bc6f3SBojan Novković 	if (db_pager_quit) {
290*c21bc6f3SBojan Novković 		return;
291*c21bc6f3SBojan Novković 	}
292*c21bc6f3SBojan Novković 	if (type == NULL) {
293*c21bc6f3SBojan Novković 		db_printf("unknown type");
294*c21bc6f3SBojan Novković 		return;
295*c21bc6f3SBojan Novković 	}
296*c21bc6f3SBojan Novković 
297*c21bc6f3SBojan Novković 	switch (CTF_V3_INFO_KIND(type->ctt_info)) {
298*c21bc6f3SBojan Novković 	case CTF_K_INTEGER:
299*c21bc6f3SBojan Novković 		db_pprint_int(addr, type, depth);
300*c21bc6f3SBojan Novković 		break;
301*c21bc6f3SBojan Novković 	case CTF_K_UNION:
302*c21bc6f3SBojan Novković 	case CTF_K_STRUCT:
303*c21bc6f3SBojan Novković 		db_pprint_struct(addr, type, depth);
304*c21bc6f3SBojan Novković 		break;
305*c21bc6f3SBojan Novković 	case CTF_K_FUNCTION:
306*c21bc6f3SBojan Novković 	case CTF_K_FLOAT:
307*c21bc6f3SBojan Novković 		db_indent = depth;
308*c21bc6f3SBojan Novković 		db_iprintf("0x%lx", addr);
309*c21bc6f3SBojan Novković 		break;
310*c21bc6f3SBojan Novković 	case CTF_K_POINTER:
311*c21bc6f3SBojan Novković 		db_pprint_ptr(addr, type, depth);
312*c21bc6f3SBojan Novković 		break;
313*c21bc6f3SBojan Novković 	case CTF_K_TYPEDEF:
314*c21bc6f3SBojan Novković 	case CTF_K_VOLATILE:
315*c21bc6f3SBojan Novković 	case CTF_K_RESTRICT:
316*c21bc6f3SBojan Novković 	case CTF_K_CONST: {
317*c21bc6f3SBojan Novković 		struct ctf_type_v3 *ref_type = db_ctf_typeid_to_type(&sym_data,
318*c21bc6f3SBojan Novković 		    type->ctt_type);
319*c21bc6f3SBojan Novković 		db_pprint_type(addr, ref_type, depth);
320*c21bc6f3SBojan Novković 		break;
321*c21bc6f3SBojan Novković 	}
322*c21bc6f3SBojan Novković 	case CTF_K_ENUM:
323*c21bc6f3SBojan Novković 		db_pprint_enum(addr, type, depth);
324*c21bc6f3SBojan Novković 		break;
325*c21bc6f3SBojan Novković 	case CTF_K_ARRAY:
326*c21bc6f3SBojan Novković 		db_pprint_arr(addr, type, depth);
327*c21bc6f3SBojan Novković 		break;
328*c21bc6f3SBojan Novković 	case CTF_K_UNKNOWN:
329*c21bc6f3SBojan Novković 	case CTF_K_FORWARD:
330*c21bc6f3SBojan Novković 	default:
331*c21bc6f3SBojan Novković 		break;
332*c21bc6f3SBojan Novković 	}
333*c21bc6f3SBojan Novković }
334*c21bc6f3SBojan Novković 
335*c21bc6f3SBojan Novković /*
336*c21bc6f3SBojan Novković  * Symbol pretty-printing command.
337*c21bc6f3SBojan Novković  * Syntax: pprint [/d depth] <sym_name>
338*c21bc6f3SBojan Novković  */
339*c21bc6f3SBojan Novković static void
340*c21bc6f3SBojan Novković db_pprint_symbol_cmd(const char *name)
341*c21bc6f3SBojan Novković {
342*c21bc6f3SBojan Novković 	db_addr_t addr;
343*c21bc6f3SBojan Novković 	int db_indent_old;
344*c21bc6f3SBojan Novković 	const char *type_name = NULL;
345*c21bc6f3SBojan Novković 	struct ctf_type_v3 *type = NULL;
346*c21bc6f3SBojan Novković 
347*c21bc6f3SBojan Novković 	if (db_pager_quit) {
348*c21bc6f3SBojan Novković 		return;
349*c21bc6f3SBojan Novković 	}
350*c21bc6f3SBojan Novković 	/* Clear symbol and CTF info */
351*c21bc6f3SBojan Novković 	memset(&sym_data, 0, sizeof(struct db_ctf_sym_data));
352*c21bc6f3SBojan Novković 	if (db_ctf_find_symbol(name, &sym_data) != 0) {
353*c21bc6f3SBojan Novković 		db_error("Symbol not found\n");
354*c21bc6f3SBojan Novković 	}
355*c21bc6f3SBojan Novković 	if (ELF_ST_TYPE(sym_data.sym->st_info) != STT_OBJECT) {
356*c21bc6f3SBojan Novković 		db_error("Symbol is not a variable\n");
357*c21bc6f3SBojan Novković 	}
358*c21bc6f3SBojan Novković 	addr = sym_data.sym->st_value;
359*c21bc6f3SBojan Novković 	type = db_ctf_sym_to_type(&sym_data);
360*c21bc6f3SBojan Novković 	if (type == NULL) {
361*c21bc6f3SBojan Novković 		db_error("Can't find CTF type info\n");
362*c21bc6f3SBojan Novković 	}
363*c21bc6f3SBojan Novković 	type_name = db_ctf_stroff_to_str(&sym_data, type->ctt_name);
364*c21bc6f3SBojan Novković 	if (type_name != NULL)
365*c21bc6f3SBojan Novković 		db_printf("%s ", type_name);
366*c21bc6f3SBojan Novković 	db_printf("%s = ", name);
367*c21bc6f3SBojan Novković 
368*c21bc6f3SBojan Novković 	db_indent_old = db_indent;
369*c21bc6f3SBojan Novković 	db_pprint_type(addr, type, 0);
370*c21bc6f3SBojan Novković 	db_indent = db_indent_old;
371*c21bc6f3SBojan Novković }
372*c21bc6f3SBojan Novković 
373*c21bc6f3SBojan Novković /*
374*c21bc6f3SBojan Novković  * Command for pretty-printing arbitrary addresses.
375*c21bc6f3SBojan Novković  * Syntax: pprint [/d depth] struct <struct_name> <addr>
376*c21bc6f3SBojan Novković  */
377*c21bc6f3SBojan Novković static void
378*c21bc6f3SBojan Novković db_pprint_struct_cmd(db_expr_t addr, const char *struct_name)
379*c21bc6f3SBojan Novković {
380*c21bc6f3SBojan Novković 	int db_indent_old;
381*c21bc6f3SBojan Novković 	struct ctf_type_v3 *type = NULL;
382*c21bc6f3SBojan Novković 
383*c21bc6f3SBojan Novković 	type = db_ctf_find_typename(&sym_data, struct_name);
384*c21bc6f3SBojan Novković 	if (type == NULL) {
385*c21bc6f3SBojan Novković 		db_error("Can't find CTF type info\n");
386*c21bc6f3SBojan Novković 		return;
387*c21bc6f3SBojan Novković 	}
388*c21bc6f3SBojan Novković 
389*c21bc6f3SBojan Novković 	db_printf("struct %s ", struct_name);
390*c21bc6f3SBojan Novković 	db_printf("%p = ", (void *)addr);
391*c21bc6f3SBojan Novković 
392*c21bc6f3SBojan Novković 	db_indent_old = db_indent;
393*c21bc6f3SBojan Novković 	db_pprint_type(addr, type, 0);
394*c21bc6f3SBojan Novković 	db_indent = db_indent_old;
395*c21bc6f3SBojan Novković }
396*c21bc6f3SBojan Novković 
397*c21bc6f3SBojan Novković /*
398*c21bc6f3SBojan Novković  * Pretty print an address or a symbol.
399*c21bc6f3SBojan Novković  */
400*c21bc6f3SBojan Novković void
401*c21bc6f3SBojan Novković db_pprint_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
402*c21bc6f3SBojan Novković {
403*c21bc6f3SBojan Novković 	int t = 0;
404*c21bc6f3SBojan Novković 	const char *name;
405*c21bc6f3SBojan Novković 
406*c21bc6f3SBojan Novković 	/* Set default depth */
407*c21bc6f3SBojan Novković 	max_depth = DB_PPRINT_DEFAULT_DEPTH;
408*c21bc6f3SBojan Novković 	/* Parse print modifiers */
409*c21bc6f3SBojan Novković 	t = db_read_token();
410*c21bc6f3SBojan Novković 	if (t == tSLASH) {
411*c21bc6f3SBojan Novković 		t = db_read_token();
412*c21bc6f3SBojan Novković 		if (t != tIDENT) {
413*c21bc6f3SBojan Novković 			db_error("Invalid flag passed\n");
414*c21bc6f3SBojan Novković 		}
415*c21bc6f3SBojan Novković 		/* Parse desired depth level */
416*c21bc6f3SBojan Novković 		if (strcmp(db_tok_string, "d") == 0) {
417*c21bc6f3SBojan Novković 			t = db_read_token();
418*c21bc6f3SBojan Novković 			if (t != tNUMBER) {
419*c21bc6f3SBojan Novković 				db_error("Invalid depth provided\n");
420*c21bc6f3SBojan Novković 			}
421*c21bc6f3SBojan Novković 			max_depth = db_tok_number;
422*c21bc6f3SBojan Novković 		} else {
423*c21bc6f3SBojan Novković 			db_error("Invalid flag passed\n");
424*c21bc6f3SBojan Novković 		}
425*c21bc6f3SBojan Novković 		/* Fetch next token */
426*c21bc6f3SBojan Novković 		t = db_read_token();
427*c21bc6f3SBojan Novković 	}
428*c21bc6f3SBojan Novković 	/* Parse subcomannd */
429*c21bc6f3SBojan Novković 	if (t == tIDENT) {
430*c21bc6f3SBojan Novković 		if (strcmp(db_tok_string, "struct") == 0) {
431*c21bc6f3SBojan Novković 			t = db_read_token();
432*c21bc6f3SBojan Novković 
433*c21bc6f3SBojan Novković 			if (t != tIDENT) {
434*c21bc6f3SBojan Novković 				db_error("Invalid struct type name provided\n");
435*c21bc6f3SBojan Novković 			}
436*c21bc6f3SBojan Novković 			name = db_tok_string;
437*c21bc6f3SBojan Novković 
438*c21bc6f3SBojan Novković 			if (db_expression(&addr) == 0) {
439*c21bc6f3SBojan Novković 				db_error("Address not provided\n");
440*c21bc6f3SBojan Novković 			}
441*c21bc6f3SBojan Novković 			db_pprint_struct_cmd(addr, name);
442*c21bc6f3SBojan Novković 		} else {
443*c21bc6f3SBojan Novković 			name = db_tok_string;
444*c21bc6f3SBojan Novković 			db_pprint_symbol_cmd(name);
445*c21bc6f3SBojan Novković 		}
446*c21bc6f3SBojan Novković 	} else {
447*c21bc6f3SBojan Novković 		db_error("Invalid subcommand\n");
448*c21bc6f3SBojan Novković 	}
449*c21bc6f3SBojan Novković 	db_skip_to_eol();
450*c21bc6f3SBojan Novković }
451