1 /* Exception (throw catch) mechanism, for GDB, the GNU debugger. 2 3 Copyright (C) 1986-2017 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "exceptions.h" 22 #include "breakpoint.h" 23 #include "target.h" 24 #include "inferior.h" 25 #include "annotate.h" 26 #include "ui-out.h" 27 #include "serial.h" 28 #include "gdbthread.h" 29 #include "top.h" 30 31 static void 32 print_flush (void) 33 { 34 struct ui *ui = current_ui; 35 struct serial *gdb_stdout_serial; 36 struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); 37 38 if (deprecated_error_begin_hook) 39 deprecated_error_begin_hook (); 40 41 if (target_supports_terminal_ours ()) 42 { 43 make_cleanup_restore_target_terminal (); 44 target_terminal_ours_for_output (); 45 } 46 47 /* We want all output to appear now, before we print the error. We 48 have 3 levels of buffering we have to flush (it's possible that 49 some of these should be changed to flush the lower-level ones 50 too): */ 51 52 /* 1. The _filtered buffer. */ 53 if (filtered_printing_initialized ()) 54 wrap_here (""); 55 56 /* 2. The stdio buffer. */ 57 gdb_flush (gdb_stdout); 58 gdb_flush (gdb_stderr); 59 60 /* 3. The system-level buffer. */ 61 gdb_stdout_serial = serial_fdopen (fileno (ui->outstream)); 62 if (gdb_stdout_serial) 63 { 64 serial_drain_output (gdb_stdout_serial); 65 serial_un_fdopen (gdb_stdout_serial); 66 } 67 68 annotate_error_begin (); 69 70 do_cleanups (old_chain); 71 } 72 73 static void 74 print_exception (struct ui_file *file, struct gdb_exception e) 75 { 76 /* KLUGE: cagney/2005-01-13: Write the string out one line at a time 77 as that way the MI's behavior is preserved. */ 78 const char *start; 79 const char *end; 80 81 for (start = e.message; start != NULL; start = end) 82 { 83 end = strchr (start, '\n'); 84 if (end == NULL) 85 fputs_filtered (start, file); 86 else 87 { 88 end++; 89 ui_file_write (file, start, end - start); 90 } 91 } 92 fprintf_filtered (file, "\n"); 93 94 /* Now append the annotation. */ 95 switch (e.reason) 96 { 97 case RETURN_QUIT: 98 annotate_quit (); 99 break; 100 case RETURN_ERROR: 101 /* Assume that these are all errors. */ 102 annotate_error (); 103 break; 104 default: 105 internal_error (__FILE__, __LINE__, _("Bad switch.")); 106 } 107 } 108 109 void 110 exception_print (struct ui_file *file, struct gdb_exception e) 111 { 112 if (e.reason < 0 && e.message != NULL) 113 { 114 print_flush (); 115 print_exception (file, e); 116 } 117 } 118 119 void 120 exception_fprintf (struct ui_file *file, struct gdb_exception e, 121 const char *prefix, ...) 122 { 123 if (e.reason < 0 && e.message != NULL) 124 { 125 va_list args; 126 127 print_flush (); 128 129 /* Print the prefix. */ 130 va_start (args, prefix); 131 vfprintf_filtered (file, prefix, args); 132 va_end (args); 133 134 print_exception (file, e); 135 } 136 } 137 138 /* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception 139 handler. If an exception (enum return_reason) is thrown using 140 throw_exception() than all cleanups installed since 141 catch_exceptions() was entered are invoked, the (-ve) exception 142 value is then returned by catch_exceptions. If FUNC() returns 143 normally (with a positive or zero return value) then that value is 144 returned by catch_exceptions(). It is an internal_error() for 145 FUNC() to return a negative value. 146 147 See exceptions.h for further usage details. */ 148 149 /* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with 150 error() et al. could maintain a set of flags that indicate the 151 current state of each of the longjmp buffers. This would give the 152 longjmp code the chance to detect a longjmp botch (before it gets 153 to longjmperror()). Prior to 1999-11-05 this wasn't possible as 154 code also randomly used a SET_TOP_LEVEL macro that directly 155 initialized the longjmp buffers. */ 156 157 int 158 catch_exceptions (struct ui_out *uiout, 159 catch_exceptions_ftype *func, 160 void *func_args, 161 return_mask mask) 162 { 163 return catch_exceptions_with_msg (uiout, func, func_args, NULL, mask); 164 } 165 166 int 167 catch_exceptions_with_msg (struct ui_out *func_uiout, 168 catch_exceptions_ftype *func, 169 void *func_args, 170 char **gdberrmsg, 171 return_mask mask) 172 { 173 struct gdb_exception exception = exception_none; 174 volatile int val = 0; 175 struct ui_out *saved_uiout; 176 177 /* Save and override the global ``struct ui_out'' builder. */ 178 saved_uiout = current_uiout; 179 current_uiout = func_uiout; 180 181 TRY 182 { 183 val = (*func) (current_uiout, func_args); 184 } 185 CATCH (ex, RETURN_MASK_ALL) 186 { 187 exception = ex; 188 } 189 END_CATCH 190 191 /* Restore the global builder. */ 192 current_uiout = saved_uiout; 193 194 if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0) 195 { 196 /* The caller didn't request that the event be caught. 197 Rethrow. */ 198 throw_exception (exception); 199 } 200 201 exception_print (gdb_stderr, exception); 202 gdb_assert (val >= 0); 203 gdb_assert (exception.reason <= 0); 204 if (exception.reason < 0) 205 { 206 /* If caller wants a copy of the low-level error message, make 207 one. This is used in the case of a silent error whereby the 208 caller may optionally want to issue the message. */ 209 if (gdberrmsg != NULL) 210 { 211 if (exception.message != NULL) 212 *gdberrmsg = xstrdup (exception.message); 213 else 214 *gdberrmsg = NULL; 215 } 216 return exception.reason; 217 } 218 return val; 219 } 220 221 /* This function is superseded by catch_exceptions(). */ 222 223 int 224 catch_errors (catch_errors_ftype *func, void *func_args, 225 const char *errstring, return_mask mask) 226 { 227 struct gdb_exception exception = exception_none; 228 volatile int val = 0; 229 struct ui_out *saved_uiout; 230 231 /* Save the global ``struct ui_out'' builder. */ 232 saved_uiout = current_uiout; 233 234 TRY 235 { 236 val = func (func_args); 237 } 238 CATCH (ex, RETURN_MASK_ALL) 239 { 240 exception = ex; 241 } 242 END_CATCH 243 244 /* Restore the global builder. */ 245 current_uiout = saved_uiout; 246 247 if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0) 248 { 249 /* The caller didn't request that the event be caught. 250 Rethrow. */ 251 throw_exception (exception); 252 } 253 254 exception_fprintf (gdb_stderr, exception, "%s", errstring); 255 if (exception.reason != 0) 256 return 0; 257 return val; 258 } 259 260 /* See exceptions.h. */ 261 262 int 263 exception_print_same (struct gdb_exception e1, struct gdb_exception e2) 264 { 265 const char *msg1 = e1.message; 266 const char *msg2 = e2.message; 267 268 if (msg1 == NULL) 269 msg1 = ""; 270 if (msg2 == NULL) 271 msg2 = ""; 272 273 return (e1.reason == e2.reason 274 && e1.error == e2.error 275 && strcmp (msg1, msg2) == 0); 276 } 277