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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [raise-gcc.c] - Blame information for rev 414

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

Line No. Rev Author Line
1 281 jeremybenn
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                            R A I S E - G C C                             *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *             Copyright (C) 1992-2009, Free Software Foundation, Inc.      *
10
 *                                                                          *
11
 * GNAT is free software;  you can  redistribute it  and/or modify it under *
12
 * terms of the  GNU General Public License as published  by the Free Soft- *
13
 * ware  Foundation;  either version 3,  or (at your option) any later ver- *
14
 * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15
 * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16
 * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
17
 *                                                                          *
18
 * As a special exception under Section 7 of GPL version 3, you are granted *
19
 * additional permissions described in the GCC Runtime Library Exception,   *
20
 * version 3.1, as published by the Free Software Foundation.               *
21
 *                                                                          *
22
 * You should have received a copy of the GNU General Public License and    *
23
 * a copy of the GCC Runtime Library Exception along with this program;     *
24
 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
25
 * <http://www.gnu.org/licenses/>.                                          *
26
 *                                                                          *
27
 * GNAT was originally developed  by the GNAT team at  New York University. *
28
 * Extensive contributions were provided by Ada Core Technologies Inc.      *
29
 *                                                                          *
30
 ****************************************************************************/
31
 
32
/* Code related to the integration of the GCC mechanism for exception
33
   handling.  */
34
 
35
#ifdef IN_RTS
36
#include "tconfig.h"
37
#include "tsystem.h"
38
/* In the top-of-tree GCC, tconfig does not include tm.h, but in GCC 3.2
39
   it does.  To avoid branching raise.c just for that purpose, we kludge by
40
   looking for a symbol always defined by tm.h and if it's not defined,
41
   we include it.  */
42
#ifndef FIRST_PSEUDO_REGISTER
43
#include "coretypes.h"
44
#include "tm.h"
45
#endif
46
#include <sys/stat.h>
47
#include <stdarg.h>
48
typedef char bool;
49
# define true 1
50
# define false 0
51
#else
52
#include "config.h"
53
#include "system.h"
54
#endif
55
 
56
#include "adaint.h"
57
#include "raise.h"
58
 
59
#ifdef __APPLE__
60
/* On MacOS X, versions older than 10.5 don't export _Unwind_GetIPInfo.  */
61
#undef HAVE_GETIPINFO
62
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
63
#define HAVE_GETIPINFO 1
64
#endif
65
#endif
66
 
67
/* The names of a couple of "standard" routines for unwinding/propagation
68
   actually vary depending on the underlying GCC scheme for exception handling
69
   (SJLJ or DWARF). We need a consistently named interface to import from
70
   a-except, so wrappers are defined here.
71
 
72
   Besides, even though the compiler is never setup to use the GCC propagation
73
   circuitry, it still relies on exceptions internally and part of the sources
74
   to handle to exceptions are shared with the run-time library.  We need
75
   dummy definitions for the wrappers to satisfy the linker in this case.
76
 
77
   The types to be used by those wrappers in the run-time library are target
78
   types exported by unwind.h.  We used to piggyback on them for the compiler
79
   stubs, but there is no guarantee that unwind.h is always in sight so we
80
   define our own set below.  These are dummy types as the wrappers are never
81
   called in the compiler case.  */
82
 
83
#ifdef IN_RTS
84
 
85
#include "unwind.h"
86
 
87
typedef struct _Unwind_Context _Unwind_Context;
88
typedef struct _Unwind_Exception _Unwind_Exception;
89
 
90
#else
91
 
92
typedef void _Unwind_Context;
93
typedef void _Unwind_Exception;
94
typedef int  _Unwind_Reason_Code;
95
 
96
#endif
97
 
98
_Unwind_Reason_Code
99
__gnat_Unwind_RaiseException (_Unwind_Exception *);
100
 
101
_Unwind_Reason_Code
102
__gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *);
103
 
104
 
105
#ifdef IN_RTS   /* For eh personality routine */
106
 
107
#include "dwarf2.h"
108
#include "unwind-dw2-fde.h"
109
#include "unwind-pe.h"
110
 
111
 
112
/* --------------------------------------------------------------
113
   -- The DB stuff below is there for debugging purposes only. --
114
   -------------------------------------------------------------- */
115
 
116
#define DB_PHASES     0x1
117
#define DB_CSITE      0x2
118
#define DB_ACTIONS    0x4
119
#define DB_REGIONS    0x8
120
 
121
#define DB_ERR        0x1000
122
 
123
/* The "action" stuff below is also there for debugging purposes only.  */
124
 
125
typedef struct
126
{
127
  _Unwind_Action phase;
128
  char * description;
129
} phase_descriptor;
130
 
131
static phase_descriptor phase_descriptors[]
132
  = {{ _UA_SEARCH_PHASE,  "SEARCH_PHASE" },
133
     { _UA_CLEANUP_PHASE, "CLEANUP_PHASE" },
134
     { _UA_HANDLER_FRAME, "HANDLER_FRAME" },
135
     { _UA_FORCE_UNWIND,  "FORCE_UNWIND" },
136
     { -1, 0}};
137
 
138
static int
139
db_accepted_codes (void)
140
{
141
  static int accepted_codes = -1;
142
 
143
  if (accepted_codes == -1)
144
    {
145
      char * db_env = (char *) getenv ("EH_DEBUG");
146
 
147
      accepted_codes = db_env ? (atoi (db_env) | DB_ERR) : 0;
148
      /* Arranged for ERR stuff to always be visible when the variable
149
         is defined. One may just set the variable to 0 to see the ERR
150
         stuff only.  */
151
    }
152
 
153
  return accepted_codes;
154
}
155
 
156
#define DB_INDENT_INCREASE 0x01
157
#define DB_INDENT_DECREASE 0x02
158
#define DB_INDENT_OUTPUT   0x04
159
#define DB_INDENT_NEWLINE  0x08
160
#define DB_INDENT_RESET    0x10
161
 
162
#define DB_INDENT_UNIT     8
163
 
164
static void
165
db_indent (int requests)
166
{
167
  static int current_indentation_level = 0;
168
 
169
  if (requests & DB_INDENT_RESET)
170
    {
171
      current_indentation_level = 0;
172
    }
173
 
174
  if (requests & DB_INDENT_INCREASE)
175
    {
176
      current_indentation_level ++;
177
    }
178
 
179
  if (requests & DB_INDENT_DECREASE)
180
    {
181
      current_indentation_level --;
182
    }
183
 
184
  if (requests & DB_INDENT_NEWLINE)
185
    {
186
      fprintf (stderr, "\n");
187
    }
188
 
189
  if (requests & DB_INDENT_OUTPUT)
190
    {
191
      fprintf (stderr, "%*s",
192
               current_indentation_level * DB_INDENT_UNIT, " ");
193
    }
194
 
195
}
196
 
197
static void ATTRIBUTE_PRINTF_2
198
db (int db_code, char * msg_format, ...)
199
{
200
  if (db_accepted_codes () & db_code)
201
    {
202
      va_list msg_args;
203
 
204
      db_indent (DB_INDENT_OUTPUT);
205
 
206
      va_start (msg_args, msg_format);
207
      vfprintf (stderr, msg_format, msg_args);
208
      va_end (msg_args);
209
    }
210
}
211
 
212
static void
213
db_phases (int phases)
214
{
215
  phase_descriptor *a = phase_descriptors;
216
 
217
  if (! (db_accepted_codes() & DB_PHASES))
218
    return;
219
 
220
  db (DB_PHASES, "\n");
221
 
222
  for (; a->description != 0; a++)
223
    if (phases & a->phase)
224
      db (DB_PHASES, "%s ", a->description);
225
 
226
  db (DB_PHASES, " :\n");
227
}
228
 
229
 
230
/* ---------------------------------------------------------------
231
   --  Now come a set of useful structures and helper routines. --
232
   --------------------------------------------------------------- */
233
 
234
/* There are three major runtime tables involved, generated by the
235
   GCC back-end. Contents slightly vary depending on the underlying
236
   implementation scheme (dwarf zero cost / sjlj).
237
 
238
   =======================================
239
   * Tables for the dwarf zero cost case *
240
   =======================================
241
 
242
   call_site []
243
   -------------------------------------------------------------------
244
   * region-start | region-length | landing-pad | first-action-index *
245
   -------------------------------------------------------------------
246
 
247
   Identify possible actions to be taken and where to resume control
248
   for that when an exception propagates through a pc inside the region
249
   delimited by start and length.
250
 
251
   A null landing-pad indicates that nothing is to be done.
252
 
253
   Otherwise, first-action-index provides an entry into the action[]
254
   table which heads a list of possible actions to be taken (see below).
255
 
256
   If it is determined that indeed an action should be taken, that
257
   is, if one action filter matches the exception being propagated,
258
   then control should be transfered to landing-pad.
259
 
260
   A null first-action-index indicates that there are only cleanups
261
   to run there.
262
 
263
   action []
264
   -------------------------------
265
   * action-filter | next-action *
266
   -------------------------------
267
 
268
   This table contains lists (called action chains) of possible actions
269
   associated with call-site entries described in the call-site [] table.
270
   There is at most one action list per call-site entry.
271
 
272
   A null action-filter indicates a cleanup.
273
 
274
   Non null action-filters provide an index into the ttypes [] table
275
   (see below), from which information may be retrieved to check if it
276
   matches the exception being propagated.
277
 
278
   action-filter > 0  means there is a regular handler to be run,
279
 
280
   action-filter < 0  means there is a some "exception_specification"
281
                      data to retrieve, which is only relevant for C++
282
                      and should never show up for Ada.
283
 
284
   next-action indexes the next entry in the list. 0 indicates there is
285
   no other entry.
286
 
287
   ttypes []
288
   ---------------
289
   * ttype-value *
290
   ---------------
291
 
292
   A null value indicates a catch-all handler in C++, and an "others"
293
   handler in Ada.
294
 
295
   Non null values are used to match the exception being propagated:
296
   In C++ this is a pointer to some rtti data, while in Ada this is an
297
   exception id.
298
 
299
   The special id value 1 indicates an "all_others" handler.
300
 
301
   For C++, this table is actually also used to store "exception
302
   specification" data. The differentiation between the two kinds
303
   of entries is made by the sign of the associated action filter,
304
   which translates into positive or negative offsets from the
305
   so called base of the table:
306
 
307
   Exception Specification data is stored at positive offsets from
308
   the ttypes table base, which Exception Type data is stored at
309
   negative offsets:
310
 
311
   ---------------------------------------------------------------------------
312
 
313
   Here is a quick summary of the tables organization:
314
 
315
          +-- Unwind_Context (pc, ...)
316
          |
317
          |(pc)
318
          |
319
          |   CALL-SITE[]
320
          |
321
          |   +=============================================================+
322
          |   | region-start + length |  landing-pad   | first-action-index |
323
          |   +=============================================================+
324
          +-> |       pc range          0 => no-action   0 => cleanups only |
325
              |                         !0 => jump @              N --+     |
326
              +====================================================== | ====+
327
                                                                      |
328
                                                                      |
329
       ACTION []                                                      |
330
                                                                      |
331
       +==========================================================+   |
332
       |              action-filter           |   next-action     |   |
333
       +==========================================================+   |
334
       |  0 => cleanup                                            |   |
335
       | >0 => ttype index for handler ------+  0 => end of chain | <-+
336
       | <0 => ttype index for spec data     |                    |
337
       +==================================== | ===================+
338
                                             |
339
                                             |
340
       TTYPES []                             |
341
                                             |  Offset negated from
342
                 +=====================+     |  the actual base.
343
                 |     ttype-value     |     |
344
    +============+=====================+     |
345
    |            |  0 => "others"      |     |
346
    |    ...     |  1 => "all others"  | <---+
347
    |            |  X => exception id  |
348
    |  handlers  +---------------------+
349
    |            |        ...          |
350
    |    ...     |        ...          |
351
    |            |        ...          |
352
    +============+=====================+ <<------ Table base
353
    |    ...     |        ...          |
354
    |   specs    |        ...          | (should not see negative filter
355
    |    ...     |        ...          |  values for Ada).
356
    +============+=====================+
357
 
358
 
359
   ============================
360
   * Tables for the sjlj case *
361
   ============================
362
 
363
   So called "function contexts" are pushed on a context stack by calls to
364
   _Unwind_SjLj_Register on function entry, and popped off at exit points by
365
   calls to _Unwind_SjLj_Unregister. The current call_site for a function is
366
   updated in the function context as the function's code runs along.
367
 
368
   The generic unwinding engine in _Unwind_RaiseException walks the function
369
   context stack and not the actual call chain.
370
 
371
   The ACTION and TTYPES tables remain unchanged, which allows to search them
372
   during the propagation phase to determine whether or not the propagated
373
   exception is handled somewhere. When it is, we only "jump" up once directly
374
   to the context where the handler will be found. Besides, this allows "break
375
   exception unhandled" to work also
376
 
377
   The CALL-SITE table is setup differently, though: the pc attached to the
378
   unwind context is a direct index into the table, so the entries in this
379
   table do not hold region bounds any more.
380
 
381
   A special index (-1) is used to indicate that no action is possibly
382
   connected with the context at hand, so null landing pads cannot appear
383
   in the table.
384
 
385
   Additionally, landing pad values in the table do not represent code address
386
   to jump at, but so called "dispatch" indices used by a common landing pad
387
   for the function to switch to the appropriate post-landing-pad.
388
 
389
   +-- Unwind_Context (pc, ...)
390
   |
391
   | pc = call-site index
392
   |  0 => terminate (should not see this for Ada)
393
   | -1 => no-action
394
   |
395
   |   CALL-SITE[]
396
   |
397
   |   +=====================================+
398
   |   |  landing-pad   | first-action-index |
399
   |   +=====================================+
400
   +-> |                  0 => cleanups only |
401
       | dispatch index             N        |
402
       +=====================================+
403
 
404
 
405
   ===================================
406
   * Basic organization of this unit *
407
   ===================================
408
 
409
   The major point of this unit is to provide an exception propagation
410
   personality routine for Ada. This is __gnat_eh_personality.
411
 
412
   It is provided with a pointer to the propagated exception, an unwind
413
   context describing a location the propagation is going through, and a
414
   couple of other arguments including a description of the current
415
   propagation phase.
416
 
417
   It shall return to the generic propagation engine what is to be performed
418
   next, after possible context adjustments, depending on what it finds in the
419
   traversed context (a handler for the exception, a cleanup, nothing, ...),
420
   and on the propagation phase.
421
 
422
   A number of structures and subroutines are used for this purpose, as
423
   sketched below:
424
 
425
   o region_descriptor: General data associated with the context (base pc,
426
     call-site table, action table, ttypes table, ...)
427
 
428
   o action_descriptor: Data describing the action to be taken for the
429
     propagated exception in the provided context (kind of action: nothing,
430
     handler, cleanup; pointer to the action table entry, ...).
431
 
432
   raise
433
     |
434
    ... (a-except.adb)
435
     |
436
   Propagate_Exception (a-exexpr.adb)
437
     |
438
     |
439
   _Unwind_RaiseException (libgcc)
440
     |
441
     |   (Ada frame)
442
     |
443
     +--> __gnat_eh_personality (context, exception)
444
           |
445
           +--> get_region_descriptor_for (context)
446
           |
447
           +--> get_action_descriptor_for (context, exception, region)
448
           |       |
449
           |       +--> get_call_site_action_for (context, region)
450
           |            (one version for each underlying scheme)
451
           |
452
           +--> setup_to_install (context)
453
 
454
   This unit is inspired from the C++ version found in eh_personality.cc,
455
   part of libstdc++-v3.
456
 
457
*/
458
 
459
 
460
/* This is an incomplete "proxy" of the structure of exception objects as
461
   built by the GNAT runtime library. Accesses to other fields than the common
462
   header are performed through subprogram calls to alleviate the need of an
463
   exact counterpart here and potential alignment/size issues for the common
464
   header. See a-exexpr.adb.  */
465
 
466
typedef struct
467
{
468
  _Unwind_Exception common;
469
  /* ABI header, maximally aligned. */
470
} _GNAT_Exception;
471
 
472
/* The two constants below are specific ttype identifiers for special
473
   exception ids.  Their type should match what a-exexpr exports.  */
474
 
475
extern const int __gnat_others_value;
476
#define GNAT_OTHERS      ((_Unwind_Ptr) &__gnat_others_value)
477
 
478
extern const int __gnat_all_others_value;
479
#define GNAT_ALL_OTHERS  ((_Unwind_Ptr) &__gnat_all_others_value)
480
 
481
/* Describe the useful region data associated with an unwind context.  */
482
 
483
typedef struct
484
{
485
  /* The base pc of the region.  */
486
  _Unwind_Ptr base;
487
 
488
  /* Pointer to the Language Specific Data for the region.  */
489
  _Unwind_Ptr lsda;
490
 
491
  /* Call-Site data associated with this region.  */
492
  unsigned char call_site_encoding;
493
  const unsigned char *call_site_table;
494
 
495
  /* The base to which are relative landing pad offsets inside the call-site
496
     entries .  */
497
  _Unwind_Ptr lp_base;
498
 
499
  /* Action-Table associated with this region.  */
500
  const unsigned char *action_table;
501
 
502
  /* Ttype data associated with this region.  */
503
  unsigned char ttype_encoding;
504
  const unsigned char *ttype_table;
505
  _Unwind_Ptr ttype_base;
506
 
507
} region_descriptor;
508
 
509
static void
510
db_region_for (region_descriptor *region, _Unwind_Context *uw_context)
511
{
512
  int ip_before_insn = 0;
513
#ifdef HAVE_GETIPINFO
514
  _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn);
515
#else
516
  _Unwind_Ptr ip = _Unwind_GetIP (uw_context);
517
#endif
518
  if (!ip_before_insn)
519
    ip--;
520
 
521
  if (! (db_accepted_codes () & DB_REGIONS))
522
    return;
523
 
524
  db (DB_REGIONS, "For ip @ 0x%08x => ", ip);
525
 
526
  if (region->lsda)
527
    db (DB_REGIONS, "lsda @ 0x%x", region->lsda);
528
  else
529
    db (DB_REGIONS, "no lsda");
530
 
531
  db (DB_REGIONS, "\n");
532
}
533
 
534
/* Retrieve the ttype entry associated with FILTER in the REGION's
535
   ttype table.  */
536
 
537
static const _Unwind_Ptr
538
get_ttype_entry_for (region_descriptor *region, long filter)
539
{
540
  _Unwind_Ptr ttype_entry;
541
 
542
  filter *= size_of_encoded_value (region->ttype_encoding);
543
  read_encoded_value_with_base
544
    (region->ttype_encoding, region->ttype_base,
545
     region->ttype_table - filter, &ttype_entry);
546
 
547
  return ttype_entry;
548
}
549
 
550
/* Fill out the REGION descriptor for the provided UW_CONTEXT.  */
551
 
552
static void
553
get_region_description_for (_Unwind_Context *uw_context,
554
                            region_descriptor *region)
555
{
556
  const unsigned char * p;
557
  _uleb128_t tmp;
558
  unsigned char lpbase_encoding;
559
 
560
  /* Get the base address of the lsda information. If the provided context
561
     is null or if there is no associated language specific data, there's
562
     nothing we can/should do.  */
563
  region->lsda
564
    = (_Unwind_Ptr) (uw_context
565
                     ? _Unwind_GetLanguageSpecificData (uw_context) : 0);
566
 
567
  if (! region->lsda)
568
    return;
569
 
570
  /* Parse the lsda and fill the region descriptor.  */
571
  p = (char *)region->lsda;
572
 
573
  region->base = _Unwind_GetRegionStart (uw_context);
574
 
575
  /* Find @LPStart, the base to which landing pad offsets are relative.  */
576
  lpbase_encoding = *p++;
577
  if (lpbase_encoding != DW_EH_PE_omit)
578
    p = read_encoded_value
579
      (uw_context, lpbase_encoding, p, &region->lp_base);
580
  else
581
    region->lp_base = region->base;
582
 
583
  /* Find @TType, the base of the handler and exception spec type data.  */
584
  region->ttype_encoding = *p++;
585
  if (region->ttype_encoding != DW_EH_PE_omit)
586
    {
587
      p = read_uleb128 (p, &tmp);
588
      region->ttype_table = p + tmp;
589
    }
590
   else
591
     region->ttype_table = 0;
592
 
593
  region->ttype_base
594
    = base_of_encoded_value (region->ttype_encoding, uw_context);
595
 
596
  /* Get the encoding and length of the call-site table; the action table
597
     immediately follows.  */
598
  region->call_site_encoding = *p++;
599
  region->call_site_table = read_uleb128 (p, &tmp);
600
 
601
  region->action_table = region->call_site_table + tmp;
602
}
603
 
604
 
605
/* Describe an action to be taken when propagating an exception up to
606
   some context.  */
607
 
608
typedef enum
609
{
610
  /* Found some call site base data, but need to analyze further
611
     before being able to decide.  */
612
  unknown,
613
 
614
  /* There is nothing relevant in the context at hand. */
615
  nothing,
616
 
617
  /* There are only cleanups to run in this context.  */
618
  cleanup,
619
 
620
  /* There is a handler for the exception in this context.  */
621
  handler
622
} action_kind;
623
 
624
/* filter value for cleanup actions.  */
625
const int cleanup_filter = 0;
626
 
627
typedef struct
628
{
629
  /* The kind of action to be taken.  */
630
  action_kind kind;
631
 
632
  /* A pointer to the action record entry.  */
633
  const unsigned char *table_entry;
634
 
635
  /* Where we should jump to actually take an action (trigger a cleanup or an
636
     exception handler).  */
637
  _Unwind_Ptr landing_pad;
638
 
639
  /* If we have a handler matching our exception, these are the filter to
640
     trigger it and the corresponding id.  */
641
  _Unwind_Sword ttype_filter;
642
  _Unwind_Ptr   ttype_entry;
643
 
644
} action_descriptor;
645
 
646
static void
647
db_action_for (action_descriptor *action, _Unwind_Context *uw_context)
648
{
649
  int ip_before_insn = 0;
650
#ifdef HAVE_GETIPINFO
651
  _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn);
652
#else
653
  _Unwind_Ptr ip = _Unwind_GetIP (uw_context);
654
#endif
655
  if (!ip_before_insn)
656
    ip--;
657
 
658
  db (DB_ACTIONS, "For ip @ 0x%08x => ", ip);
659
 
660
  switch (action->kind)
661
     {
662
     case unknown:
663
       db (DB_ACTIONS, "lpad @ 0x%x, record @ 0x%x\n",
664
           action->landing_pad, action->table_entry);
665
       break;
666
 
667
     case nothing:
668
       db (DB_ACTIONS, "Nothing\n");
669
       break;
670
 
671
     case cleanup:
672
       db (DB_ACTIONS, "Cleanup\n");
673
       break;
674
 
675
     case handler:
676
       db (DB_ACTIONS, "Handler, filter = %d\n", action->ttype_filter);
677
       break;
678
 
679
     default:
680
       db (DB_ACTIONS, "Err? Unexpected action kind !\n");
681
       break;
682
    }
683
 
684
  return;
685
}
686
 
687
/* Search the call_site_table of REGION for an entry appropriate for the
688
   UW_CONTEXT's IP.  If one is found, store the associated landing_pad
689
   and action_table entry, and set the ACTION kind to unknown for further
690
   analysis.  Otherwise, set the ACTION kind to nothing.
691
 
692
   There are two variants of this routine, depending on the underlying
693
   mechanism (DWARF/SJLJ), which account for differences in the tables.  */
694
 
695
#ifdef __USING_SJLJ_EXCEPTIONS__
696
 
697
#define __builtin_eh_return_data_regno(x) x
698
 
699
static void
700
get_call_site_action_for (_Unwind_Context *uw_context,
701
                          region_descriptor *region,
702
                          action_descriptor *action)
703
{
704
  int ip_before_insn = 0;
705
#ifdef HAVE_GETIPINFO
706
  _Unwind_Ptr call_site = _Unwind_GetIPInfo (uw_context, &ip_before_insn);
707
#else
708
  _Unwind_Ptr call_site = _Unwind_GetIP (uw_context);
709
#endif
710
  /* Subtract 1 if necessary because GetIPInfo returns the actual call site
711
     value + 1 in this case.  */
712
  if (!ip_before_insn)
713
    call_site--;
714
 
715
  /* call_site is a direct index into the call-site table, with two special
716
     values : -1 for no-action and 0 for "terminate".  The latter should never
717
     show up for Ada.  To test for the former, beware that _Unwind_Ptr might
718
     be unsigned.  */
719
 
720
  if ((int)call_site < 0)
721
    {
722
      action->kind = nothing;
723
      return;
724
    }
725
  else if (call_site == 0)
726
    {
727
      db (DB_ERR, "========> Err, null call_site for Ada/sjlj\n");
728
      action->kind = nothing;
729
      return;
730
    }
731
  else
732
    {
733
      _uleb128_t cs_lp, cs_action;
734
 
735
      /* Let the caller know there may be an action to take, but let it
736
         determine the kind.  */
737
      action->kind = unknown;
738
 
739
      /* We have a direct index into the call-site table, but this table is
740
         made of leb128 values, the encoding length of which is variable.  We
741
         can't merely compute an offset from the index, then, but have to read
742
         all the entries before the one of interest.  */
743
 
744
      const unsigned char *p = region->call_site_table;
745
 
746
      do {
747
        p = read_uleb128 (p, &cs_lp);
748
        p = read_uleb128 (p, &cs_action);
749
      } while (--call_site);
750
 
751
      action->landing_pad = cs_lp + 1;
752
 
753
      if (cs_action)
754
        action->table_entry = region->action_table + cs_action - 1;
755
      else
756
        action->table_entry = 0;
757
 
758
      return;
759
    }
760
}
761
 
762
#else /* !__USING_SJLJ_EXCEPTIONS__  */
763
 
764
static void
765
get_call_site_action_for (_Unwind_Context *uw_context,
766
                          region_descriptor *region,
767
                          action_descriptor *action)
768
{
769
  const unsigned char *p = region->call_site_table;
770
  int ip_before_insn = 0;
771
#ifdef HAVE_GETIPINFO
772
  _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn);
773
#else
774
  _Unwind_Ptr ip = _Unwind_GetIP (uw_context);
775
#endif
776
  /* Subtract 1 if necessary because GetIPInfo yields a call return address
777
     in this case, while we are interested in information for the call point.
778
     This does not always yield the exact call instruction address but always
779
     brings the IP back within the corresponding region.  */
780
  if (!ip_before_insn)
781
    ip--;
782
 
783
  /* Unless we are able to determine otherwise...  */
784
  action->kind = nothing;
785
 
786
  db (DB_CSITE, "\n");
787
 
788
  while (p < region->action_table)
789
    {
790
      _Unwind_Ptr cs_start, cs_len, cs_lp;
791
      _uleb128_t cs_action;
792
 
793
      /* Note that all call-site encodings are "absolute" displacements.  */
794
      p = read_encoded_value (0, region->call_site_encoding, p, &cs_start);
795
      p = read_encoded_value (0, region->call_site_encoding, p, &cs_len);
796
      p = read_encoded_value (0, region->call_site_encoding, p, &cs_lp);
797
      p = read_uleb128 (p, &cs_action);
798
 
799
      db (DB_CSITE,
800
          "c_site @ 0x%08x (+0x%03x), len = %3d, lpad @ 0x%08x (+0x%03x)\n",
801
          region->base+cs_start, cs_start, cs_len,
802
          region->lp_base+cs_lp, cs_lp);
803
 
804
      /* The table is sorted, so if we've passed the IP, stop.  */
805
      if (ip < region->base + cs_start)
806
        break;
807
 
808
      /* If we have a match, fill the ACTION fields accordingly.  */
809
      else if (ip < region->base + cs_start + cs_len)
810
        {
811
          /* Let the caller know there may be an action to take, but let it
812
             determine the kind.  */
813
          action->kind = unknown;
814
 
815
          if (cs_lp)
816
            action->landing_pad = region->lp_base + cs_lp;
817
          else
818
            action->landing_pad = 0;
819
 
820
          if (cs_action)
821
            action->table_entry = region->action_table + cs_action - 1;
822
          else
823
            action->table_entry = 0;
824
 
825
          db (DB_CSITE, "+++\n");
826
          return;
827
        }
828
    }
829
 
830
  db (DB_CSITE, "---\n");
831
}
832
 
833
#endif /* __USING_SJLJ_EXCEPTIONS__  */
834
 
835
/* With CHOICE an exception choice representing an "exception - when"
836
   argument, and PROPAGATED_EXCEPTION a pointer to the currently propagated
837
   occurrence, return true if the latter matches the former, that is, if
838
   PROPAGATED_EXCEPTION is caught by the handling code controlled by CHOICE.
839
   This takes care of the special Non_Ada_Error case on VMS.  */
840
 
841
#define Is_Handled_By_Others  __gnat_is_handled_by_others
842
#define Language_For          __gnat_language_for
843
#define Import_Code_For       __gnat_import_code_for
844
#define EID_For               __gnat_eid_for
845
#define Adjust_N_Cleanups_For __gnat_adjust_n_cleanups_for
846
 
847
extern bool Is_Handled_By_Others (_Unwind_Ptr eid);
848
extern char Language_For (_Unwind_Ptr eid);
849
 
850
extern Exception_Code Import_Code_For (_Unwind_Ptr eid);
851
 
852
extern Exception_Id EID_For (_GNAT_Exception * e);
853
extern void Adjust_N_Cleanups_For (_GNAT_Exception * e, int n);
854
 
855
static int
856
is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception)
857
{
858
  /* Pointer to the GNAT exception data corresponding to the propagated
859
     occurrence.  */
860
  _Unwind_Ptr E = (_Unwind_Ptr) EID_For (propagated_exception);
861
 
862
  /* Base matching rules: An exception data (id) matches itself, "when
863
     all_others" matches anything and "when others" matches anything unless
864
     explicitly stated otherwise in the propagated occurrence.  */
865
 
866
  bool is_handled =
867
    choice == E
868
    || choice == GNAT_ALL_OTHERS
869
    || (choice == GNAT_OTHERS && Is_Handled_By_Others (E));
870
 
871
  /* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we
872
     may have different exception data pointers that should match for the
873
     same condition code, if both an export and an import have been
874
     registered.  The import code for both the choice and the propagated
875
     occurrence are expected to have been masked off regarding severity
876
     bits already (at registration time for the former and from within the
877
     low level exception vector for the latter).  */
878
#ifdef VMS
879
  #define Non_Ada_Error system__aux_dec__non_ada_error
880
  extern struct Exception_Data Non_Ada_Error;
881
 
882
  is_handled |=
883
    (Language_For (E) == 'V'
884
     && choice != GNAT_OTHERS && choice != GNAT_ALL_OTHERS
885
     && ((Language_For (choice) == 'V' && Import_Code_For (choice) != 0
886
          && Import_Code_For (choice) == Import_Code_For (E))
887
         || choice == (_Unwind_Ptr)&Non_Ada_Error));
888
#endif
889
 
890
  return is_handled;
891
}
892
 
893
/* Fill out the ACTION to be taken from propagating UW_EXCEPTION up to
894
   UW_CONTEXT in REGION.  */
895
 
896
static void
897
get_action_description_for (_Unwind_Context *uw_context,
898
                            _Unwind_Exception *uw_exception,
899
                            region_descriptor *region,
900
                            action_descriptor *action)
901
{
902
  _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception;
903
 
904
  /* Search the call site table first, which may get us a landing pad as well
905
     as the head of an action record list.  */
906
  get_call_site_action_for (uw_context, region, action);
907
  db_action_for (action, uw_context);
908
 
909
  /* If there is not even a call_site entry, we are done.  */
910
  if (action->kind == nothing)
911
    return;
912
 
913
  /* Otherwise, check what we have at the place of the call site.  */
914
 
915
  /* No landing pad => no cleanups or handlers.  */
916
  if (action->landing_pad == 0)
917
    {
918
      action->kind = nothing;
919
      return;
920
    }
921
 
922
  /* Landing pad + null table entry => only cleanups.  */
923
  else if (action->table_entry == 0)
924
    {
925
      action->kind = cleanup;
926
      action->ttype_filter = cleanup_filter;
927
      /* The filter initialization is not strictly necessary, as cleanup-only
928
         landing pads don't look at the filter value.  It is there to ensure
929
         we don't pass random values and so trigger potential confusion when
930
         installing the context later on.  */
931
      return;
932
    }
933
 
934
  /* Landing pad + Table entry => handlers + possible cleanups.  */
935
  else
936
    {
937
      const unsigned char * p = action->table_entry;
938
 
939
      _sleb128_t ar_filter, ar_disp;
940
 
941
      action->kind = nothing;
942
 
943
      while (1)
944
        {
945
          p = read_sleb128 (p, &ar_filter);
946
          read_sleb128 (p, &ar_disp);
947
          /* Don't assign p here, as it will be incremented by ar_disp
948
             below.  */
949
 
950
          /* Null filters are for cleanups. */
951
          if (ar_filter == cleanup_filter)
952
            {
953
              action->kind = cleanup;
954
              action->ttype_filter = cleanup_filter;
955
              /* The filter initialization is required here, to ensure
956
                 the target landing pad branches to the cleanup code if
957
                 we happen not to find a matching handler.  */
958
            }
959
 
960
          /* Positive filters are for regular handlers.  */
961
          else if (ar_filter > 0)
962
            {
963
              /* See if the filter we have is for an exception which matches
964
                 the one we are propagating.  */
965
              _Unwind_Ptr choice = get_ttype_entry_for (region, ar_filter);
966
 
967
              if (is_handled_by (choice, gnat_exception))
968
                {
969
                  action->kind = handler;
970
                  action->ttype_filter = ar_filter;
971
                  action->ttype_entry = choice;
972
                  return;
973
                }
974
            }
975
 
976
          /* Negative filter values are for C++ exception specifications.
977
             Should not be there for Ada :/  */
978
          else
979
            db (DB_ERR, "========> Err, filter < 0 for Ada/dwarf\n");
980
 
981
          if (ar_disp == 0)
982
            return;
983
 
984
          p += ar_disp;
985
        }
986
    }
987
}
988
 
989
/* Setup in UW_CONTEXT the eh return target IP and data registers, which will
990
   be restored with the others and retrieved by the landing pad once the jump
991
   occurred.  */
992
 
993
static void
994
setup_to_install (_Unwind_Context *uw_context,
995
                  _Unwind_Exception *uw_exception,
996
                  _Unwind_Ptr uw_landing_pad,
997
                  int uw_filter)
998
{
999
#ifndef EH_RETURN_DATA_REGNO
1000
  /* We should not be called if the appropriate underlying support is not
1001
     there.  */
1002
  abort ();
1003
#else
1004
  /* 1/ exception object pointer, which might be provided back to
1005
     _Unwind_Resume (and thus to this personality routine) if we are jumping
1006
     to a cleanup.  */
1007
  _Unwind_SetGR (uw_context, __builtin_eh_return_data_regno (0),
1008
                 (_Unwind_Word)uw_exception);
1009
 
1010
  /* 2/ handler switch value register, which will also be used by the target
1011
     landing pad to decide what action it shall take.  */
1012
  _Unwind_SetGR (uw_context, __builtin_eh_return_data_regno (1),
1013
                 (_Unwind_Word)uw_filter);
1014
 
1015
  /* Setup the address we should jump at to reach the code where there is the
1016
     "something" we found.  */
1017
  _Unwind_SetIP (uw_context, uw_landing_pad);
1018
#endif
1019
}
1020
 
1021
/* The following is defined from a-except.adb. Its purpose is to enable
1022
   automatic backtraces upon exception raise, as provided through the
1023
   GNAT.Traceback facilities.  */
1024
extern void __gnat_notify_handled_exception (void);
1025
extern void __gnat_notify_unhandled_exception (void);
1026
 
1027
/* Below is the eh personality routine per se. We currently assume that only
1028
   GNU-Ada exceptions are met.  */
1029
 
1030
#ifdef __USING_SJLJ_EXCEPTIONS__
1031
#define PERSONALITY_FUNCTION    __gnat_eh_personality_sj
1032
#else
1033
#define PERSONALITY_FUNCTION    __gnat_eh_personality
1034
#endif
1035
 
1036
/* Major tweak for ia64-vms : the CHF propagation phase calls this personality
1037
   routine with sigargs/mechargs arguments and has very specific expectations
1038
   on possible return values.
1039
 
1040
   We handle this with a number of specific tricks:
1041
 
1042
   1. We tweak the personality routine prototype to have the "version" and
1043
      "phases" two first arguments be void * instead of int and _Unwind_Action
1044
      as nominally expected in the GCC context.
1045
 
1046
      This allows us to access the full range of bits passed in every case and
1047
      has no impact on the callers side since each argument remains assigned
1048
      the same single 64bit slot.
1049
 
1050
   2. We retrieve the corresponding int and _Unwind_Action values within the
1051
      routine for regular use with truncating conversions. This is a noop when
1052
      called from the libgcc unwinder.
1053
 
1054
   3. We assume we're called by the VMS CHF when unexpected bits are set in
1055
      both those values. The incoming arguments are then real sigargs and
1056
      mechargs pointers, which we then redirect to __gnat_handle_vms_condition
1057
      for proper processing.
1058
*/
1059
#if defined (VMS) && defined (__IA64)
1060
typedef void * version_arg_t;
1061
typedef void * phases_arg_t;
1062
#else
1063
typedef int version_arg_t;
1064
typedef _Unwind_Action phases_arg_t;
1065
#endif
1066
 
1067
_Unwind_Reason_Code
1068
PERSONALITY_FUNCTION (version_arg_t version_arg,
1069
                      phases_arg_t phases_arg,
1070
                      _Unwind_Exception_Class uw_exception_class,
1071
                      _Unwind_Exception *uw_exception,
1072
                      _Unwind_Context *uw_context)
1073
{
1074
  /* Fetch the version and phases args with their nominal ABI types for later
1075
     use. This is a noop everywhere except on ia64-vms when called from the
1076
     Condition Handling Facility.  */
1077
  int uw_version = (int) version_arg;
1078
  _Unwind_Action uw_phases = (_Unwind_Action) phases_arg;
1079
 
1080
  _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception;
1081
 
1082
  region_descriptor region;
1083
  action_descriptor action;
1084
 
1085
  /* Check that we're called from the ABI context we expect, with a major
1086
     possible variation on VMS for IA64.  */
1087
  if (uw_version != 1)
1088
    {
1089
      #if defined (VMS) && defined (__IA64)
1090
 
1091
      /* Assume we're called with sigargs/mechargs arguments if really
1092
         unexpected bits are set in our first two formals.  Redirect to the
1093
         GNAT condition handling code in this case.  */
1094
 
1095
      extern long __gnat_handle_vms_condition (void *, void *);
1096
 
1097
      unsigned int version_unexpected_bits_mask = 0xffffff00U;
1098
      unsigned int phases_unexpected_bits_mask  = 0xffffff00U;
1099
 
1100
      if ((unsigned int)uw_version & version_unexpected_bits_mask
1101
          && (unsigned int)uw_phases & phases_unexpected_bits_mask)
1102
        return __gnat_handle_vms_condition (version_arg, phases_arg);
1103
      #endif
1104
 
1105
      return _URC_FATAL_PHASE1_ERROR;
1106
    }
1107
 
1108
  db_indent (DB_INDENT_RESET);
1109
  db_phases (uw_phases);
1110
  db_indent (DB_INDENT_INCREASE);
1111
 
1112
  /* Get the region description for the context we were provided with. This
1113
     will tell us if there is some lsda, call_site, action and/or ttype data
1114
     for the associated ip.  */
1115
  get_region_description_for (uw_context, &region);
1116
  db_region_for (&region, uw_context);
1117
 
1118
  /* No LSDA => no handlers or cleanups => we shall unwind further up.  */
1119
  if (! region.lsda)
1120
    return _URC_CONTINUE_UNWIND;
1121
 
1122
  /* Search the call-site and action-record tables for the action associated
1123
     with this IP.  */
1124
  get_action_description_for (uw_context, uw_exception, &region, &action);
1125
  db_action_for (&action, uw_context);
1126
 
1127
  /* Whatever the phase, if there is nothing relevant in this frame,
1128
     unwinding should just go on.  */
1129
  if (action.kind == nothing)
1130
    return _URC_CONTINUE_UNWIND;
1131
 
1132
  /* If we found something in search phase, we should return a code indicating
1133
     what to do next depending on what we found. If we only have cleanups
1134
     around, we shall try to unwind further up to find a handler, otherwise,
1135
     tell we have a handler, which will trigger the second phase.  */
1136
  if (uw_phases & _UA_SEARCH_PHASE)
1137
    {
1138
      if (action.kind == cleanup)
1139
        {
1140
          Adjust_N_Cleanups_For (gnat_exception, 1);
1141
          return _URC_CONTINUE_UNWIND;
1142
        }
1143
      else
1144
        {
1145
          /* Trigger the appropriate notification routines before the second
1146
             phase starts, which ensures the stack is still intact. */
1147
          __gnat_notify_handled_exception ();
1148
 
1149
          return _URC_HANDLER_FOUND;
1150
        }
1151
    }
1152
 
1153
  /* We found something in cleanup/handler phase, which might be the handler
1154
     or a cleanup for a handled occurrence, or a cleanup for an unhandled
1155
     occurrence (we are in a FORCED_UNWIND phase in this case). Install the
1156
     context to get there.  */
1157
 
1158
  /* If we are going to install a cleanup context, decrement the cleanup
1159
     count.  This is required in a FORCED_UNWINDing phase (for an unhandled
1160
     exception), as this is used from the forced unwinding handler in
1161
     Ada.Exceptions.Exception_Propagation to decide whether unwinding should
1162
     proceed further or Unhandled_Exception_Terminate should be called.  */
1163
  if (action.kind == cleanup)
1164
    Adjust_N_Cleanups_For (gnat_exception, -1);
1165
 
1166
  setup_to_install
1167
    (uw_context, uw_exception, action.landing_pad, action.ttype_filter);
1168
 
1169
  return _URC_INSTALL_CONTEXT;
1170
}
1171
 
1172
/* Define the consistently named wrappers imported by Propagate_Exception.  */
1173
 
1174
#ifdef __USING_SJLJ_EXCEPTIONS__
1175
 
1176
#undef _Unwind_RaiseException
1177
 
1178
_Unwind_Reason_Code
1179
__gnat_Unwind_RaiseException (_Unwind_Exception *e)
1180
{
1181
  return _Unwind_SjLj_RaiseException (e);
1182
}
1183
 
1184
 
1185
#undef _Unwind_ForcedUnwind
1186
 
1187
_Unwind_Reason_Code
1188
__gnat_Unwind_ForcedUnwind (_Unwind_Exception *e,
1189
                            void * handler,
1190
                            void * argument)
1191
{
1192
  return _Unwind_SjLj_ForcedUnwind (e, handler, argument);
1193
}
1194
 
1195
 
1196
#else /* __USING_SJLJ_EXCEPTIONS__ */
1197
 
1198
_Unwind_Reason_Code
1199
__gnat_Unwind_RaiseException (_Unwind_Exception *e)
1200
{
1201
  return _Unwind_RaiseException (e);
1202
}
1203
 
1204
_Unwind_Reason_Code
1205
__gnat_Unwind_ForcedUnwind (_Unwind_Exception *e,
1206
                            void * handler,
1207
                            void * argument)
1208
{
1209
  return _Unwind_ForcedUnwind (e, handler, argument);
1210
}
1211
 
1212
#endif /* __USING_SJLJ_EXCEPTIONS__ */
1213
 
1214
#else
1215
/* ! IN_RTS  */
1216
 
1217
/* Define the corresponding stubs for the compiler.  */
1218
 
1219
/* We don't want fancy_abort here.  */
1220
#undef abort
1221
 
1222
_Unwind_Reason_Code
1223
__gnat_Unwind_RaiseException (_Unwind_Exception *e ATTRIBUTE_UNUSED)
1224
{
1225
  abort ();
1226
}
1227
 
1228
 
1229
_Unwind_Reason_Code
1230
__gnat_Unwind_ForcedUnwind (_Unwind_Exception *e ATTRIBUTE_UNUSED,
1231
                            void * handler ATTRIBUTE_UNUSED,
1232
                            void * argument ATTRIBUTE_UNUSED)
1233
{
1234
  abort ();
1235
}
1236
 
1237
#endif /* IN_RTS */

powered by: WebSVN 2.1.0

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