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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [raise-gcc.c] - Blame information for rev 749

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

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

powered by: WebSVN 2.1.0

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