sync
[bitrig.git] / sys / ddb / db_struct.c
blob373cd2c53ebe26be680fa01217927c193b817e80
1 /* $OpenBSD: db_struct.c,v 1.1 2009/08/09 23:04:49 miod Exp $ */
3 /*
4 * Copyright (c) 2009 Miodrag Vallat.
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * ddb routines to describe struct information
23 #include <sys/param.h>
24 #include <sys/systm.h>
26 #include <machine/db_machdep.h>
28 #include <ddb/db_lex.h>
29 #include <ddb/db_output.h>
30 #include <ddb/db_access.h>
31 #include <ddb/db_command.h>
32 #include <ddb/db_extern.h>
33 #include <ddb/db_interface.h>
34 #include <ddb/db_var.h>
36 #include "db_structinfo.h"
38 void db_struct_print_field(uint, int, db_expr_t);
41 * Flags to pass db_struct_printf().
44 #define DBSP_STRUCT_NAME 0x01 /* prepend struct name */
45 #define DBSP_VALUE 0x02 /* display field value */
47 void
48 db_struct_print_field(uint fidx, int flags, db_expr_t baseaddr)
50 const struct ddb_field_info *field;
51 const struct ddb_struct_info *struc;
52 db_expr_t value;
53 uint tmp;
54 size_t namelen;
55 int width, basecol, curcol;
56 char tmpfmt[28];
58 field = &ddb_field_info[fidx];
59 basecol = 0;
61 if (ISSET(flags, DBSP_STRUCT_NAME)) {
62 struc = &ddb_struct_info[field->sidx];
63 namelen = strlen(struc->name);
64 db_printf("%-30s ", struc->name);
65 if (namelen > 30)
66 basecol += namelen + 1;
67 else
68 basecol += 30 + 1;
71 namelen = strlen(field->name);
72 if (field->nitems == 1) {
73 db_printf("%-30s ", field->name);
74 if (namelen > 30)
75 basecol += namelen + 1;
76 else
77 basecol += 30 + 1;
78 } else {
79 width = 30 - 2;
80 tmp = field->nitems;
81 while (tmp != 0) {
82 width--;
83 tmp /= 10;
85 if (namelen >= width) {
86 db_printf("%s[%zu] ", field->name, field->nitems);
87 basecol += namelen + (30 - width) + 1;
88 } else {
89 db_printf("%s[%zu]%*s ", field->name, field->nitems,
90 width - (int)namelen, "");
91 /* namelen + (30-width) + (width-namelen) + 1 */
92 basecol += 30 + 1;
96 if (field->size == 0) {
97 db_printf("bitfield");
98 /* basecol irrelevant from there on */
99 } else {
100 snprintf(tmpfmt, sizeof tmpfmt, "%zu", field->size);
101 basecol += strlen(tmpfmt) + 1;
102 db_printf("%s ", tmpfmt);
105 if (ISSET(flags, DBSP_VALUE)) {
106 /* only print the field value if it has a friendly size. */
107 switch (field->size) {
108 case 1:
109 width = 4;
110 break;
111 case 2:
112 width = 8;
113 break;
114 case 4:
115 width = 12;
116 break;
117 #ifdef __LP64__
118 case 8:
119 width = 20;
120 break;
121 #endif
122 default:
123 width = 0;
125 if (width != 0) {
126 baseaddr += field->offs;
127 curcol = basecol;
128 for (tmp = field->nitems; tmp != 0; tmp--) {
129 value = db_get_value(baseaddr, field->size,
130 FALSE); /* assume unsigned */
131 db_format(tmpfmt, sizeof tmpfmt, (long)value,
132 DB_FORMAT_N, 0, width);
133 if (field->nitems > 1)
134 db_printf("%s", tmpfmt);
135 else
136 db_printf("%20s", tmpfmt);
137 baseaddr += field->size;
140 * Try to fit array elements on as few lines
141 * as possible.
143 if (field->nitems > 1 && tmp > 1) {
144 curcol += width + 1;
145 if (basecol >= db_max_width ||
146 curcol + width >= db_max_width) {
147 /* new line */
148 db_printf("\n");
149 if (basecol + width >=
150 db_max_width) {
151 db_printf("\t");
152 curcol = 8;
153 } else {
154 db_printf("%*s",
155 basecol, "");
156 curcol = basecol;
158 } else
159 db_printf(" ");
165 db_printf("\n");
170 * show offset <value>: displays the list of struct fields which exist
171 * at that particular offset from the beginning of the struct.
173 void
174 db_struct_offset_cmd(db_expr_t addr, int have_addr, db_expr_t count,
175 char *modifiers)
177 db_expr_t offset = 0;
178 const struct ddb_field_offsets *field;
179 const uint *fidx;
180 uint oidx;
181 int width;
182 char tmpfmt[28];
185 * Read the offset from the debuggger input.
186 * We don't want to get it from the standard parsing code, because
187 * this would set `dot' to this value, which doesn't make sense.
190 if (!db_expression(&offset) || offset < 0) {
191 db_printf("not a valid offset\n");
192 db_flush_lex();
193 return;
196 db_skip_to_eol();
198 for (field = ddb_field_offsets, oidx = 0; oidx < NOFFS; field++, oidx++)
199 if (field->offs == (size_t)offset)
200 break;
202 if (oidx == NOFFS) {
203 db_format(tmpfmt, sizeof tmpfmt, (long)offset,
204 DB_FORMAT_N, 0, width);
205 db_printf("no known structure element at offset %-*s\n",
206 width, tmpfmt);
207 db_flush_lex();
208 return;
211 db_printf("%-30s %-30s size\n", "struct", "member");
212 for (fidx = field->list; *fidx != 0; fidx++)
213 db_struct_print_field(*fidx, DBSP_STRUCT_NAME, 0);
217 * show struct <struct name> [addr]: displays the data starting at addr
218 * (`dot' if unspecified) as a struct of the given type.
220 void
221 db_struct_layout_cmd(db_expr_t addr, int have_addr, db_expr_t count,
222 char *modifiers)
224 const struct ddb_struct_info *struc;
225 uint sidx, fidx;
226 int t;
229 * Read the struct name from the debugger input.
232 t = db_read_token();
233 if (t != tIDENT) {
234 db_printf("Bad struct name\n");
235 db_flush_lex();
236 return;
239 for (struc = ddb_struct_info, sidx = 0; sidx < NSTRUCT;
240 struc++, sidx++)
241 if (strcmp(struc->name, db_tok_string) == 0)
242 break;
244 if (sidx == NSTRUCT) {
245 db_printf("unknown struct %s\n", db_tok_string);
246 db_flush_lex();
247 return;
251 * Read the address, if any, from the debugger input.
252 * In that case, update `dot' value.
255 if (db_expression(&addr)) {
256 db_dot = (db_addr_t)addr;
257 db_last_addr = db_dot;
258 } else
259 addr = (db_expr_t)db_dot;
261 db_skip_to_eol();
264 * Display the structure contents.
267 db_printf("struct %s at %p (%zu bytes)\n", struc->name, (vaddr_t)addr,
268 struc->size);
269 for (fidx = struc->fmin; fidx <= struc->fmax; fidx++)
270 db_struct_print_field(fidx, DBSP_VALUE, addr);