OSDN Git Service

938f04b06e6843e914d4665fd3b401b778c19628
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-exextr.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                      ADA.EXCEPTIONS.EXCEPTION_TRACES                     --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2003 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 2,  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.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- As a special exception,  if other files  instantiate  generics from this --
23 -- unit, or you link  this unit with other files  to produce an executable, --
24 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
25 -- covered  by the  GNU  General  Public  License.  This exception does not --
26 -- however invalidate  any other reasons why  the executable file  might be --
27 -- covered by the  GNU Public License.                                      --
28 --                                                                          --
29 -- GNAT was originally developed  by the GNAT team at  New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
31 --                                                                          --
32 ------------------------------------------------------------------------------
33
34 with Unchecked_Conversion;
35
36 pragma Warnings (Off);
37 with Ada.Exceptions.Last_Chance_Handler;
38 pragma Warnings (On);
39 --  Bring last chance handler into closure
40
41 separate (Ada.Exceptions)
42 package body Exception_Traces is
43
44    Nline : constant String := String'(1 => ASCII.LF);
45    --  Convenient shortcut
46
47    type Exception_Action is access procedure (E : Exception_Occurrence);
48    Global_Action : Exception_Action := null;
49    pragma Export
50      (Ada, Global_Action, "__gnat_exception_actions_global_action");
51    --  Global action, executed whenever an exception is raised.  Changing the
52    --  export name must be coordinated with code in g-excact.adb.
53
54    Raise_Hook_Initialized : Boolean := False;
55    pragma Export
56      (Ada, Raise_Hook_Initialized, "__gnat_exception_actions_initialized");
57
58    procedure Last_Chance_Handler
59      (Except :  Exception_Occurrence);
60    pragma Import
61      (C, Last_Chance_Handler, "__gnat_last_chance_handler");
62    pragma No_Return (Last_Chance_Handler);
63    --  Users can replace the default version of this routine,
64    --  Ada.Exceptions.Last_Chance_Handler.
65
66    function To_Action is new Unchecked_Conversion
67      (Raise_Action, Exception_Action);
68
69    -----------------------
70    -- Local Subprograms --
71    -----------------------
72
73    procedure Notify_Exception (Excep : EOA; Is_Unhandled : Boolean);
74    --  Factorizes the common processing for Notify_Handled_Exception and
75    --  Notify_Unhandled_Exception. Is_Unhandled is set to True only in the
76    --  latter case because Notify_Handled_Exception may be called for an
77    --  actually unhandled occurrence in the Front-End-SJLJ case.
78
79    procedure To_Stderr (S : String);
80    pragma Export (Ada, To_Stderr, "__gnat_to_stderr");
81    --  Little routine to output string to stderr that is also used
82    --  in the tasking run time.
83
84    ---------------------------------
85    -- Debugger Interface Routines --
86    ---------------------------------
87
88    --  The routines here are null routines that normally have no effect.
89    --  They are provided for the debugger to place breakpoints on their
90    --  entry points to get control on an exception.
91
92    procedure Unhandled_Exception;
93    pragma Export (C, Unhandled_Exception, "__gnat_unhandled_exception");
94    --  Hook for GDB to support "break exception unhandled".
95
96    --  For "break exception", GDB uses __gnat_raise_nodefer_with_msg, which
97    --  is not in this section because it fullfills other purposes than a mere
98    --  debugger interface.
99
100    --------------------------------
101    -- Import Run-Time C Routines --
102    --------------------------------
103
104    --  The purpose of the following pragma Import is to ensure that we
105    --  generate appropriate subprogram descriptors for all C routines in
106    --  the standard GNAT library that can raise exceptions. This ensures
107    --  that the exception propagation can properly find these routines
108
109    pragma Propagate_Exceptions;
110
111    ----------------------
112    -- Notify_Exception --
113    ----------------------
114
115    procedure Notify_Exception (Excep : EOA; Is_Unhandled : Boolean) is
116    begin
117       --  Output the exception information required by the Exception_Trace
118       --  configuration. Take care not to output information about internal
119       --  exceptions.
120
121       --  ??? In the Front-End ZCX case, the traceback entries we have at this
122       --  point only include the ones we stored while walking up the stack *up
123       --  to the handler*. All the frames above the subprogram in which the
124       --  handler is found are missing.
125
126       if not Excep.Id.Not_Handled_By_Others
127         and then
128         (Exception_Trace = Every_Raise
129          or else (Exception_Trace = Unhandled_Raise and then Is_Unhandled))
130       then
131          To_Stderr (Nline);
132
133          if Is_Unhandled then
134             To_Stderr ("Unhandled ");
135          end if;
136
137          To_Stderr ("Exception raised");
138          To_Stderr (Nline);
139          To_Stderr (Tailored_Exception_Information (Excep.all));
140       end if;
141
142       --  Call the user-specific actions
143       --  ??? We should presumably look at the reraise status here.
144
145       if Raise_Hook_Initialized
146         and then Exception_Data_Ptr (Excep.Id).Raise_Hook /= null
147       then
148          To_Action (Exception_Data_Ptr (Excep.Id).Raise_Hook) (Excep.all);
149       end if;
150
151       if Global_Action /= null then
152          Global_Action (Excep.all);
153       end if;
154    end Notify_Exception;
155
156    ------------------------------
157    -- Notify_Handled_Exception --
158    ------------------------------
159
160    procedure Notify_Handled_Exception is
161    begin
162       Notify_Exception (Get_Current_Excep.all, Is_Unhandled => False);
163    end Notify_Handled_Exception;
164
165    --------------------------------
166    -- Notify_Unhandled_Exception --
167    --------------------------------
168
169    procedure Notify_Unhandled_Exception is
170    begin
171       Notify_Exception (Get_Current_Excep.all, Is_Unhandled => True);
172       Unhandled_Exception;
173    end Notify_Unhandled_Exception;
174
175    -------------------------
176    -- Unhandled_Exception --
177    -------------------------
178
179    procedure Unhandled_Exception is
180    begin
181       null;
182    end Unhandled_Exception;
183
184    -----------------------------------
185    -- Unhandled_Exception_Terminate --
186    -----------------------------------
187
188    type int is new Integer;
189
190    procedure Unhandled_Exception_Terminate is
191       Excep : constant EOA := Save_Occurrence (Get_Current_Excep.all.all);
192       --  This occurrence will be used to display a message after finalization.
193       --  It is necessary to save a copy here, or else the designated value
194       --  could be overwritten if an exception is raised during finalization
195       --  (even if that exception is caught).
196
197    begin
198       Last_Chance_Handler (Excep.all);
199    end Unhandled_Exception_Terminate;
200
201    ---------------
202    -- To_Stderr --
203    ---------------
204
205    procedure To_Stderr (S : String) is
206       procedure put_char_stderr (C : int);
207       pragma Import (C, put_char_stderr, "put_char_stderr");
208
209    begin
210       for J in 1 .. S'Length loop
211          if S (J) /= ASCII.CR then
212             put_char_stderr (Character'Pos (S (J)));
213          end if;
214       end loop;
215    end To_Stderr;
216
217
218    ------------------------------------
219    -- Handling GNAT.Exception_Traces --
220    ------------------------------------
221
222    --  The bulk of exception traces output is centralized in Notify_Exception,
223    --  for both the Handled and Unhandled cases. Extra task specific output is
224    --  triggered in the task wrapper for unhandled occurrences in tasks. It is
225    --  not performed in this unit to avoid dragging dependencies against the
226    --  tasking units here.
227
228    --  We used to rely on the output performed by Unhanded_Exception_Terminate
229    --  for the case of an unhandled occurrence in the environment thread, and
230    --  the task wrapper was responsible for the whole output in the tasking
231    --  case.
232
233    --  This initial scheme had a drawback: the output from Terminate only
234    --  occurs after finalization is done, which means possibly never if some
235    --  tasks keep hanging around.
236
237    --  The first "presumably obvious" fix consists in moving the Terminate
238    --  output before the finalization. It has not been retained because it
239    --  introduces annoying changes in output orders when the finalization
240    --  itself issues outputs, this also in "regular" cases not resorting to
241    --  Exception_Traces.
242
243    --  Today's solution has the advantage of simplicity and better isolates
244    --  the Exception_Traces machinery.
245
246    --  It currently outputs the information about unhandled exceptions twice
247    --  in the environment thread, once in the notification routine and once in
248    --  the termination routine. Avoiding the second output is possible but so
249    --  far has been considered undesirable. It would mean changing the order
250    --  of outputs between the two runs with or without exception traces, while
251    --  it seems preferrable to only have additional outputs in the former
252    --  case.
253
254 end Exception_Traces;