OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [exceptions.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2
 
3
   Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
4
   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
5
   2009, 2010 Free Software Foundation, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include "defs.h"
23
#include "exceptions.h"
24
#include "breakpoint.h"
25
#include "target.h"
26
#include "inferior.h"
27
#include "annotate.h"
28
#include "ui-out.h"
29
#include "gdb_assert.h"
30
#include "gdb_string.h"
31
#include "serial.h"
32
#include "gdbthread.h"
33
 
34
const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL };
35
 
36
/* Possible catcher states.  */
37
enum catcher_state {
38
  /* Initial state, a new catcher has just been created.  */
39
  CATCHER_CREATED,
40
  /* The catch code is running.  */
41
  CATCHER_RUNNING,
42
  CATCHER_RUNNING_1,
43
  /* The catch code threw an exception.  */
44
  CATCHER_ABORTING
45
};
46
 
47
/* Possible catcher actions.  */
48
enum catcher_action {
49
  CATCH_ITER,
50
  CATCH_ITER_1,
51
  CATCH_THROWING
52
};
53
 
54
struct catcher
55
{
56
  enum catcher_state state;
57
  /* Jump buffer pointing back at the exception handler.  */
58
  EXCEPTIONS_SIGJMP_BUF buf;
59
  /* Status buffer belonging to the exception handler.  */
60
  volatile struct gdb_exception *exception;
61
  /* Saved/current state.  */
62
  int mask;
63
  struct ui_out *saved_uiout;
64
  struct cleanup *saved_cleanup_chain;
65
  /* Back link.  */
66
  struct catcher *prev;
67
};
68
 
69
/* Where to go for throw_exception().  */
70
static struct catcher *current_catcher;
71
 
72
EXCEPTIONS_SIGJMP_BUF *
73
exceptions_state_mc_init (struct ui_out *func_uiout,
74
                          volatile struct gdb_exception *exception,
75
                          return_mask mask)
76
{
77
  struct catcher *new_catcher = XZALLOC (struct catcher);
78
 
79
  /* Start with no exception, save it's address.  */
80
  exception->reason = 0;
81
  exception->error = GDB_NO_ERROR;
82
  exception->message = NULL;
83
  new_catcher->exception = exception;
84
 
85
  new_catcher->mask = mask;
86
 
87
  /* Override the global ``struct ui_out'' builder.  */
88
  new_catcher->saved_uiout = uiout;
89
  uiout = func_uiout;
90
 
91
  /* Prevent error/quit during FUNC from calling cleanups established
92
     prior to here. */
93
  new_catcher->saved_cleanup_chain = save_cleanups ();
94
 
95
  /* Push this new catcher on the top.  */
96
  new_catcher->prev = current_catcher;
97
  current_catcher = new_catcher;
98
  new_catcher->state = CATCHER_CREATED;
99
 
100
  return &new_catcher->buf;
101
}
102
 
103
static void
104
catcher_pop (void)
105
{
106
  struct catcher *old_catcher = current_catcher;
107
  current_catcher = old_catcher->prev;
108
 
109
  /* Restore the cleanup chain, the error/quit messages, and the uiout
110
     builder, to their original states. */
111
 
112
  restore_cleanups (old_catcher->saved_cleanup_chain);
113
 
114
  uiout = old_catcher->saved_uiout;
115
 
116
  xfree (old_catcher);
117
}
118
 
119
/* Catcher state machine.  Returns non-zero if the m/c should be run
120
   again, zero if it should abort.  */
121
 
122
static int
123
exceptions_state_mc (enum catcher_action action)
124
{
125
  switch (current_catcher->state)
126
    {
127
    case CATCHER_CREATED:
128
      switch (action)
129
        {
130
        case CATCH_ITER:
131
          /* Allow the code to run the catcher.  */
132
          current_catcher->state = CATCHER_RUNNING;
133
          return 1;
134
        default:
135
          internal_error (__FILE__, __LINE__, _("bad state"));
136
        }
137
    case CATCHER_RUNNING:
138
      switch (action)
139
        {
140
        case CATCH_ITER:
141
          /* No error/quit has occured.  Just clean up.  */
142
          catcher_pop ();
143
          return 0;
144
        case CATCH_ITER_1:
145
          current_catcher->state = CATCHER_RUNNING_1;
146
          return 1;
147
        case CATCH_THROWING:
148
          current_catcher->state = CATCHER_ABORTING;
149
          /* See also throw_exception.  */
150
          return 1;
151
        default:
152
          internal_error (__FILE__, __LINE__, _("bad switch"));
153
        }
154
    case CATCHER_RUNNING_1:
155
      switch (action)
156
        {
157
        case CATCH_ITER:
158
          /* The did a "break" from the inner while loop.  */
159
          catcher_pop ();
160
          return 0;
161
        case CATCH_ITER_1:
162
          current_catcher->state = CATCHER_RUNNING;
163
          return 0;
164
        case CATCH_THROWING:
165
          current_catcher->state = CATCHER_ABORTING;
166
          /* See also throw_exception.  */
167
          return 1;
168
        default:
169
          internal_error (__FILE__, __LINE__, _("bad switch"));
170
        }
171
    case CATCHER_ABORTING:
172
      switch (action)
173
        {
174
        case CATCH_ITER:
175
          {
176
            struct gdb_exception exception = *current_catcher->exception;
177
            if (current_catcher->mask & RETURN_MASK (exception.reason))
178
              {
179
                /* Exit normally if this catcher can handle this
180
                   exception.  The caller analyses the func return
181
                   values.  */
182
                catcher_pop ();
183
                return 0;
184
              }
185
            /* The caller didn't request that the event be caught,
186
               relay the event to the next containing
187
               catch_errors(). */
188
            catcher_pop ();
189
            throw_exception (exception);
190
          }
191
        default:
192
          internal_error (__FILE__, __LINE__, _("bad state"));
193
        }
194
    default:
195
      internal_error (__FILE__, __LINE__, _("bad switch"));
196
    }
197
}
198
 
199
int
200
exceptions_state_mc_action_iter (void)
201
{
202
  return exceptions_state_mc (CATCH_ITER);
203
}
204
 
205
int
206
exceptions_state_mc_action_iter_1 (void)
207
{
208
  return exceptions_state_mc (CATCH_ITER_1);
209
}
210
 
211
/* Return EXCEPTION to the nearest containing catch_errors().  */
212
 
213
NORETURN void
214
throw_exception (struct gdb_exception exception)
215
{
216
  struct thread_info *tp = NULL;
217
 
218
  quit_flag = 0;
219
  immediate_quit = 0;
220
 
221
  if (!ptid_equal (inferior_ptid, null_ptid))
222
    tp = find_thread_ptid (inferior_ptid);
223
 
224
  /* Perhaps it would be cleaner to do this via the cleanup chain (not sure
225
     I can think of a reason why that is vital, though).  */
226
  if (tp != NULL)
227
    bpstat_clear_actions (tp->stop_bpstat);     /* Clear queued breakpoint commands */
228
 
229
  disable_current_display ();
230
  do_cleanups (ALL_CLEANUPS);
231
 
232
  /* Jump to the containing catch_errors() call, communicating REASON
233
     to that call via setjmp's return value.  Note that REASON can't
234
     be zero, by definition in defs.h. */
235
  exceptions_state_mc (CATCH_THROWING);
236
  *current_catcher->exception = exception;
237
  EXCEPTIONS_SIGLONGJMP (current_catcher->buf, exception.reason);
238
}
239
 
240
static char *last_message;
241
 
242
NORETURN void
243
deprecated_throw_reason (enum return_reason reason)
244
{
245
  struct gdb_exception exception;
246
  memset (&exception, 0, sizeof exception);
247
 
248
  exception.reason = reason;
249
  switch (reason)
250
    {
251
    case RETURN_QUIT:
252
      break;
253
    case RETURN_ERROR:
254
      exception.error = GENERIC_ERROR;
255
      break;
256
    default:
257
      internal_error (__FILE__, __LINE__, _("bad switch"));
258
    }
259
 
260
  throw_exception (exception);
261
}
262
 
263
static void
264
print_flush (void)
265
{
266
  struct serial *gdb_stdout_serial;
267
 
268
  if (deprecated_error_begin_hook)
269
    deprecated_error_begin_hook ();
270
  target_terminal_ours ();
271
 
272
  /* We want all output to appear now, before we print the error.  We
273
     have 3 levels of buffering we have to flush (it's possible that
274
     some of these should be changed to flush the lower-level ones
275
     too):  */
276
 
277
  /* 1.  The _filtered buffer.  */
278
  wrap_here ("");
279
 
280
  /* 2.  The stdio buffer.  */
281
  gdb_flush (gdb_stdout);
282
  gdb_flush (gdb_stderr);
283
 
284
  /* 3.  The system-level buffer.  */
285
  gdb_stdout_serial = serial_fdopen (1);
286
  if (gdb_stdout_serial)
287
    {
288
      serial_drain_output (gdb_stdout_serial);
289
      serial_un_fdopen (gdb_stdout_serial);
290
    }
291
 
292
  annotate_error_begin ();
293
}
294
 
295
static void
296
print_exception (struct ui_file *file, struct gdb_exception e)
297
{
298
  /* KLUGE: cagney/2005-01-13: Write the string out one line at a time
299
     as that way the MI's behavior is preserved.  */
300
  const char *start;
301
  const char *end;
302
  for (start = e.message; start != NULL; start = end)
303
    {
304
      end = strchr (start, '\n');
305
      if (end == NULL)
306
        fputs_filtered (start, file);
307
      else
308
        {
309
          end++;
310
          ui_file_write (file, start, end - start);
311
        }
312
    }
313
  fprintf_filtered (file, "\n");
314
 
315
  /* Now append the annotation.  */
316
  switch (e.reason)
317
    {
318
    case RETURN_QUIT:
319
      annotate_quit ();
320
      break;
321
    case RETURN_ERROR:
322
      /* Assume that these are all errors.  */
323
      annotate_error ();
324
      break;
325
    default:
326
      internal_error (__FILE__, __LINE__, _("Bad switch."));
327
    }
328
}
329
 
330
void
331
exception_print (struct ui_file *file, struct gdb_exception e)
332
{
333
  if (e.reason < 0 && e.message != NULL)
334
    {
335
      print_flush ();
336
      print_exception (file, e);
337
    }
338
}
339
 
340
void
341
exception_fprintf (struct ui_file *file, struct gdb_exception e,
342
                   const char *prefix, ...)
343
{
344
  if (e.reason < 0 && e.message != NULL)
345
    {
346
      va_list args;
347
 
348
      print_flush ();
349
 
350
      /* Print the prefix.  */
351
      va_start (args, prefix);
352
      vfprintf_filtered (file, prefix, args);
353
      va_end (args);
354
 
355
      print_exception (file, e);
356
    }
357
}
358
 
359
static void
360
print_any_exception (struct ui_file *file, const char *prefix,
361
                     struct gdb_exception e)
362
{
363
  if (e.reason < 0 && e.message != NULL)
364
    {
365
      target_terminal_ours ();
366
      wrap_here ("");           /* Force out any buffered output */
367
      gdb_flush (gdb_stdout);
368
      annotate_error_begin ();
369
 
370
      /* Print the prefix.  */
371
      if (prefix != NULL && prefix[0] != '\0')
372
        fputs_filtered (prefix, file);
373
      print_exception (file, e);
374
    }
375
}
376
 
377
NORETURN static void ATTR_NORETURN ATTR_FORMAT (printf, 3, 0)
378
throw_it (enum return_reason reason, enum errors error, const char *fmt,
379
          va_list ap)
380
{
381
  struct gdb_exception e;
382
  char *new_message;
383
 
384
  /* Save the message.  Create the new message before deleting the
385
     old, the new message may include the old message text.  */
386
  new_message = xstrvprintf (fmt, ap);
387
  xfree (last_message);
388
  last_message = new_message;
389
 
390
  /* Create the exception.  */
391
  e.reason = reason;
392
  e.error = error;
393
  e.message = last_message;
394
 
395
  /* Throw the exception.  */
396
  throw_exception (e);
397
}
398
 
399
NORETURN void
400
throw_verror (enum errors error, const char *fmt, va_list ap)
401
{
402
  throw_it (RETURN_ERROR, error, fmt, ap);
403
}
404
 
405
NORETURN void
406
throw_vfatal (const char *fmt, va_list ap)
407
{
408
  throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
409
}
410
 
411
NORETURN void
412
throw_error (enum errors error, const char *fmt, ...)
413
{
414
  va_list args;
415
  va_start (args, fmt);
416
  throw_it (RETURN_ERROR, error, fmt, args);
417
  va_end (args);
418
}
419
 
420
/* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
421
   handler.  If an exception (enum return_reason) is thrown using
422
   throw_exception() than all cleanups installed since
423
   catch_exceptions() was entered are invoked, the (-ve) exception
424
   value is then returned by catch_exceptions.  If FUNC() returns
425
   normally (with a positive or zero return value) then that value is
426
   returned by catch_exceptions().  It is an internal_error() for
427
   FUNC() to return a negative value.
428
 
429
   See exceptions.h for further usage details.
430
 
431
   Must not be called with immediate_quit in effect (bad things might
432
   happen, say we got a signal in the middle of a memcpy to quit_return).
433
   This is an OK restriction; with very few exceptions immediate_quit can
434
   be replaced by judicious use of QUIT.  */
435
 
436
/* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with
437
   error() et.al. could maintain a set of flags that indicate the the
438
   current state of each of the longjmp buffers.  This would give the
439
   longjmp code the chance to detect a longjmp botch (before it gets
440
   to longjmperror()).  Prior to 1999-11-05 this wasn't possible as
441
   code also randomly used a SET_TOP_LEVEL macro that directly
442
   initialize the longjmp buffers. */
443
 
444
int
445
catch_exceptions (struct ui_out *uiout,
446
                  catch_exceptions_ftype *func,
447
                  void *func_args,
448
                  return_mask mask)
449
{
450
  return catch_exceptions_with_msg (uiout, func, func_args, NULL, mask);
451
}
452
 
453
struct gdb_exception
454
catch_exception (struct ui_out *uiout,
455
                 catch_exception_ftype *func,
456
                 void *func_args,
457
                 return_mask mask)
458
{
459
  volatile struct gdb_exception exception;
460
  TRY_CATCH (exception, mask)
461
    {
462
      (*func) (uiout, func_args);
463
    }
464
  return exception;
465
}
466
 
467
int
468
catch_exceptions_with_msg (struct ui_out *uiout,
469
                           catch_exceptions_ftype *func,
470
                           void *func_args,
471
                           char **gdberrmsg,
472
                           return_mask mask)
473
{
474
  volatile struct gdb_exception exception;
475
  volatile int val = 0;
476
  TRY_CATCH (exception, mask)
477
    {
478
      val = (*func) (uiout, func_args);
479
    }
480
  print_any_exception (gdb_stderr, NULL, exception);
481
  gdb_assert (val >= 0);
482
  gdb_assert (exception.reason <= 0);
483
  if (exception.reason < 0)
484
    {
485
      /* If caller wants a copy of the low-level error message, make
486
         one.  This is used in the case of a silent error whereby the
487
         caller may optionally want to issue the message.  */
488
      if (gdberrmsg != NULL)
489
        {
490
          if (exception.message != NULL)
491
            *gdberrmsg = xstrdup (exception.message);
492
          else
493
            *gdberrmsg = NULL;
494
        }
495
      return exception.reason;
496
    }
497
  return val;
498
}
499
 
500
/* This function is superseded by catch_exceptions().  */
501
 
502
int
503
catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
504
              return_mask mask)
505
{
506
  volatile int val = 0;
507
  volatile struct gdb_exception exception;
508
  TRY_CATCH (exception, mask)
509
    {
510
      val = func (func_args);
511
    }
512
  print_any_exception (gdb_stderr, errstring, exception);
513
  if (exception.reason != 0)
514
    return 0;
515
  return val;
516
}
517
 
518
int
519
catch_command_errors (catch_command_errors_ftype * command,
520
                      char *arg, int from_tty, return_mask mask)
521
{
522
  volatile struct gdb_exception e;
523
  TRY_CATCH (e, mask)
524
    {
525
      command (arg, from_tty);
526
    }
527
  print_any_exception (gdb_stderr, NULL, e);
528
  if (e.reason < 0)
529
    return 0;
530
  return 1;
531
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.