Line data Source code
1 : /* $OpenBSD: db_output.c,v 1.32 2018/05/07 15:52:47 visa Exp $ */
2 : /* $NetBSD: db_output.c,v 1.13 1996/04/01 17:27:14 christos Exp $ */
3 :
4 : /*
5 : * Mach Operating System
6 : * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7 : * All Rights Reserved.
8 : *
9 : * Permission to use, copy, modify and distribute this software and its
10 : * documentation is hereby granted, provided that both the copyright
11 : * notice and this permission notice appear in all copies of the
12 : * software, derivative works or modified versions, and any portions
13 : * thereof, and that both notices appear in supporting documentation.
14 : *
15 : * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 : * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17 : * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 : *
19 : * Carnegie Mellon requests users of this software to return to
20 : *
21 : * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 : * School of Computer Science
23 : * Carnegie Mellon University
24 : * Pittsburgh PA 15213-3890
25 : *
26 : * any improvements or extensions that they make and grant Carnegie Mellon
27 : * the rights to redistribute these changes.
28 : */
29 :
30 : /*
31 : * Printf and character output for debugger.
32 : */
33 : #include <sys/param.h>
34 : #include <sys/stdarg.h>
35 : #include <sys/systm.h>
36 :
37 : #include <dev/cons.h>
38 :
39 : #include <machine/db_machdep.h>
40 :
41 : #include <ddb/db_command.h>
42 : #include <ddb/db_output.h>
43 : #include <ddb/db_access.h>
44 : #include <ddb/db_interface.h>
45 : #include <ddb/db_sym.h>
46 : #include <ddb/db_var.h>
47 :
48 : /*
49 : * Character output - tracks position in line.
50 : * To do this correctly, we should know how wide
51 : * the output device is - then we could zero
52 : * the line position when the output device wraps
53 : * around to the start of the next line.
54 : *
55 : * Instead, we count the number of spaces printed
56 : * since the last printing character so that we
57 : * don't print trailing spaces. This avoids most
58 : * of the wraparounds.
59 : */
60 :
61 : #ifndef DB_MAX_LINE
62 : #define DB_MAX_LINE 24 /* maximum line */
63 : #define DB_MAX_WIDTH 80 /* maximum width */
64 : #endif /* DB_MAX_LINE */
65 :
66 : #define DB_MIN_MAX_WIDTH 20 /* minimum max width */
67 : #define DB_MIN_MAX_LINE 3 /* minimum max line */
68 : #define CTRL(c) ((c) & 0xff)
69 :
70 : int db_output_position = 0; /* output column */
71 : int db_output_line = 0; /* output line number */
72 : int db_last_non_space = 0; /* last non-space character */
73 : int db_tab_stop_width = 8; /* how wide are tab stops? */
74 : #define NEXT_TAB(i) \
75 : ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
76 : int db_max_line = DB_MAX_LINE; /* output max lines */
77 : int db_max_width = DB_MAX_WIDTH; /* output line width */
78 : int db_radix = 16; /* output numbers radix */
79 :
80 : static void db_more(void);
81 :
82 : /*
83 : * Force pending whitespace.
84 : */
85 : void
86 0 : db_force_whitespace(void)
87 : {
88 : int last_print, next_tab;
89 :
90 0 : last_print = db_last_non_space;
91 0 : while (last_print < db_output_position) {
92 0 : next_tab = NEXT_TAB(last_print);
93 0 : if (next_tab <= db_output_position) {
94 0 : while (last_print < next_tab) { /* DON'T send a tab!!! */
95 0 : cnputc(' ');
96 0 : last_print++;
97 : }
98 : }
99 : else {
100 0 : cnputc(' ');
101 0 : last_print++;
102 : }
103 : }
104 0 : db_last_non_space = db_output_position;
105 0 : }
106 :
107 : static void
108 0 : db_more(void)
109 : {
110 : char *p;
111 : int quit_output = 0;
112 :
113 0 : for (p = "--db_more--"; *p; p++)
114 0 : cnputc(*p);
115 0 : switch(cngetc()) {
116 : case ' ':
117 0 : db_output_line = 0;
118 0 : break;
119 : case 'q':
120 : case CTRL('c'):
121 0 : db_output_line = 0;
122 : quit_output = 1;
123 0 : break;
124 : default:
125 0 : db_output_line--;
126 0 : break;
127 : }
128 : p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b";
129 0 : while (*p)
130 0 : cnputc(*p++);
131 0 : if (quit_output) {
132 0 : db_error(0);
133 : /* NOTREACHED */
134 0 : }
135 0 : }
136 :
137 : /*
138 : * Output character. Buffer whitespace.
139 : */
140 : void
141 0 : db_putchar(int c)
142 : {
143 0 : if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
144 0 : db_more();
145 :
146 0 : if (c > ' ' && c <= '~') {
147 : /*
148 : * Printing character.
149 : * If we have spaces to print, print them first.
150 : * Use tabs if possible.
151 : */
152 0 : db_force_whitespace();
153 0 : cnputc(c);
154 0 : db_output_position++;
155 0 : if (db_max_width >= DB_MIN_MAX_WIDTH
156 0 : && db_output_position >= db_max_width-1) {
157 : /* auto new line */
158 0 : cnputc('\n');
159 0 : db_output_position = 0;
160 0 : db_last_non_space = 0;
161 0 : db_output_line++;
162 0 : }
163 0 : db_last_non_space = db_output_position;
164 0 : }
165 0 : else if (c == '\n') {
166 : /* Return */
167 0 : cnputc(c);
168 0 : db_output_position = 0;
169 0 : db_last_non_space = 0;
170 0 : db_output_line++;
171 0 : }
172 0 : else if (c == '\t') {
173 : /* assume tabs every 8 positions */
174 0 : db_output_position = NEXT_TAB(db_output_position);
175 0 : }
176 0 : else if (c == ' ') {
177 : /* space */
178 0 : db_output_position++;
179 0 : }
180 0 : else if (c == '\007') {
181 : /* bell */
182 0 : cnputc(c);
183 0 : }
184 : /* other characters are assumed non-printing */
185 0 : }
186 :
187 : /*
188 : * Return output position
189 : */
190 : int
191 0 : db_print_position(void)
192 : {
193 0 : return (db_output_position);
194 : }
195 :
196 : /*
197 : * End line if too long.
198 : */
199 : void
200 0 : db_end_line(int space)
201 : {
202 0 : if (db_output_position >= db_max_width - space)
203 0 : db_printf("\n");
204 0 : }
205 :
206 : char *
207 0 : db_format(char *buf, size_t bufsize, long val, int format, int alt, int width)
208 : {
209 : const char *fmt;
210 :
211 0 : if (format == DB_FORMAT_Z || db_radix == 16)
212 0 : fmt = alt ? "-%#*lx" : "-%*lx";
213 0 : else if (db_radix == 8)
214 0 : fmt = alt ? "-%#*lo" : "-%*lo";
215 : else
216 0 : fmt = alt ? "-%#*lu" : "-%*lu";
217 :
218 : /* The leading '-' is a nasty (and beautiful) idea from NetBSD */
219 0 : if (val < 0 && format != DB_FORMAT_N)
220 0 : val = -val;
221 : else
222 0 : fmt++;
223 :
224 0 : snprintf(buf, bufsize, fmt, width, val);
225 :
226 0 : return (buf);
227 : }
228 :
229 : void
230 0 : db_stack_dump(void)
231 : {
232 : static volatile int intrace;
233 :
234 0 : if (intrace) {
235 0 : printf("Faulted in traceback, aborting...\n");
236 0 : return;
237 : }
238 :
239 0 : intrace = 1;
240 0 : printf("Starting stack trace...\n");
241 0 : db_stack_trace_print((db_expr_t)__builtin_frame_address(0), TRUE,
242 : 256 /* low limit */, "", printf);
243 0 : printf("End of stack trace.\n");
244 0 : intrace = 0;
245 0 : }
246 :
247 : void
248 0 : db_print_stack_trace(struct db_stack_trace *st, int (*pr)(const char *, ...))
249 : {
250 : unsigned int i;
251 :
252 0 : for (i = 0; i < st->st_count; i++) {
253 0 : (*pr)("#%-2u ", i);
254 0 : db_printsym(st->st_pc[i], DB_STGY_PROC, pr);
255 0 : (*pr)("\n");
256 : }
257 0 : if (st->st_count == 0)
258 0 : (*pr)("<empty stack trace>\n");
259 0 : }
|