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