1 /* $OpenBSD: db_output.c,v 1.25 2006/07/06 18:14:14 miod 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/proc.h> 35 #include <sys/stdarg.h> 36 #include <sys/systm.h> 37 38 #include <dev/cons.h> 39 40 #include <uvm/uvm_extern.h> 41 42 #include <machine/db_machdep.h> 43 44 #include <ddb/db_command.h> 45 #include <ddb/db_output.h> 46 #include <ddb/db_interface.h> 47 #include <ddb/db_sym.h> 48 #include <ddb/db_var.h> 49 #include <ddb/db_extern.h> 50 51 /* 52 * Character output - tracks position in line. 53 * To do this correctly, we should know how wide 54 * the output device is - then we could zero 55 * the line position when the output device wraps 56 * around to the start of the next line. 57 * 58 * Instead, we count the number of spaces printed 59 * since the last printing character so that we 60 * don't print trailing spaces. This avoids most 61 * of the wraparounds. 62 */ 63 64 #ifndef DB_MAX_LINE 65 #define DB_MAX_LINE 24 /* maximum line */ 66 #define DB_MAX_WIDTH 80 /* maximum width */ 67 #endif /* DB_MAX_LINE */ 68 69 #define DB_MIN_MAX_WIDTH 20 /* minimum max width */ 70 #define DB_MIN_MAX_LINE 3 /* minimum max line */ 71 #define CTRL(c) ((c) & 0xff) 72 73 int db_output_position = 0; /* output column */ 74 int db_output_line = 0; /* output line number */ 75 int db_last_non_space = 0; /* last non-space character */ 76 int db_tab_stop_width = 8; /* how wide are tab stops? */ 77 #define NEXT_TAB(i) \ 78 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 79 int db_max_line = DB_MAX_LINE; /* output max lines */ 80 int db_max_width = DB_MAX_WIDTH; /* output line width */ 81 int db_radix = 16; /* output numbers radix */ 82 83 static void db_more(void); 84 85 /* 86 * Force pending whitespace. 87 */ 88 void 89 db_force_whitespace(void) 90 { 91 int last_print, next_tab; 92 93 last_print = db_last_non_space; 94 while (last_print < db_output_position) { 95 next_tab = NEXT_TAB(last_print); 96 if (next_tab <= db_output_position) { 97 while (last_print < next_tab) { /* DON'T send a tab!!! */ 98 cnputc(' '); 99 last_print++; 100 } 101 } 102 else { 103 cnputc(' '); 104 last_print++; 105 } 106 } 107 db_last_non_space = db_output_position; 108 } 109 110 static void 111 db_more(void) 112 { 113 char *p; 114 int quit_output = 0; 115 116 for (p = "--db_more--"; *p; p++) 117 cnputc(*p); 118 switch(cngetc()) { 119 case ' ': 120 db_output_line = 0; 121 break; 122 case 'q': 123 case CTRL('c'): 124 db_output_line = 0; 125 quit_output = 1; 126 break; 127 default: 128 db_output_line--; 129 break; 130 } 131 p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"; 132 while (*p) 133 cnputc(*p++); 134 if (quit_output) { 135 db_error(0); 136 /* NOTREACHED */ 137 } 138 } 139 140 /* 141 * Output character. Buffer whitespace. 142 */ 143 void 144 db_putchar(int c) 145 { 146 if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1) 147 db_more(); 148 149 if (c > ' ' && c <= '~') { 150 /* 151 * Printing character. 152 * If we have spaces to print, print them first. 153 * Use tabs if possible. 154 */ 155 db_force_whitespace(); 156 cnputc(c); 157 db_output_position++; 158 if (db_max_width >= DB_MIN_MAX_WIDTH 159 && db_output_position >= db_max_width-1) { 160 /* auto new line */ 161 cnputc('\n'); 162 db_output_position = 0; 163 db_last_non_space = 0; 164 db_output_line++; 165 } 166 db_last_non_space = db_output_position; 167 } 168 else if (c == '\n') { 169 /* Return */ 170 cnputc(c); 171 db_output_position = 0; 172 db_last_non_space = 0; 173 db_output_line++; 174 } 175 else if (c == '\t') { 176 /* assume tabs every 8 positions */ 177 db_output_position = NEXT_TAB(db_output_position); 178 } 179 else if (c == ' ') { 180 /* space */ 181 db_output_position++; 182 } 183 else if (c == '\007') { 184 /* bell */ 185 cnputc(c); 186 } 187 /* other characters are assumed non-printing */ 188 } 189 190 /* 191 * Return output position 192 */ 193 int 194 db_print_position(void) 195 { 196 return (db_output_position); 197 } 198 199 /* 200 * End line if too long. 201 */ 202 void 203 db_end_line(int space) 204 { 205 if (db_output_position >= db_max_width - space) 206 db_printf("\n"); 207 } 208 209 char * 210 db_format(char *buf, size_t bufsize, long val, int format, int alt, int width) 211 { 212 const char *fmt; 213 214 if (format == DB_FORMAT_Z || db_radix == 16) 215 fmt = alt ? "-%#*lx" : "-%*lx"; 216 else if (db_radix == 8) 217 fmt = alt ? "-%#*lo" : "-%*lo"; 218 else 219 fmt = alt ? "-%#*lu" : "-%*lu"; 220 221 /* The leading '-' is a nasty (and beautiful) idea from NetBSD */ 222 if (val < 0 && format != DB_FORMAT_N) 223 val = -val; 224 else 225 fmt++; 226 227 snprintf(buf, bufsize, fmt, width, val); 228 229 return (buf); 230 } 231 232 void 233 db_stack_dump(void) 234 { 235 static int intrace; 236 237 if (intrace) { 238 printf("Faulted in traceback, aborting...\n"); 239 return; 240 } 241 242 intrace = 1; 243 printf("Starting stack trace...\n"); 244 db_stack_trace_print((db_expr_t)__builtin_frame_address(0), TRUE, 245 256 /* low limit */, "", printf); 246 printf("End of stack trace.\n"); 247 intrace = 0; 248 } 249