]>
Commit | Line | Data |
---|---|---|
6f1e2b25 | 1 | /**************************************************************************** |
2 | * * | |
3 | * GNAT COMPILER COMPONENTS * | |
4 | * * | |
5 | * T R A C E B A C K * | |
6 | * * | |
7 | * C Implementation File * | |
8 | * * | |
9dfe12ae | 9 | * Copyright (C) 2000-2003 Ada Core Technologies, Inc. * |
6f1e2b25 | 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 you link this file with other files to * | |
23 | * produce an executable, this file does not by itself cause the resulting * | |
24 | * executable to be covered by the GNU General Public License. This except- * | |
25 | * ion does not however invalidate any other reasons why the executable * | |
26 | * file might be covered by the GNU Public License. * | |
27 | * * | |
28 | * GNAT was originally developed by the GNAT team at New York University. * | |
9dfe12ae | 29 | * Extensive contributions were provided by Ada Core Technologies Inc. * |
6f1e2b25 | 30 | * * |
31 | ****************************************************************************/ | |
32 | ||
33 | /* This file contains low level support for stack unwinding using GCC intrinsic | |
34 | functions. | |
35 | It has been tested on the following configurations: | |
6f1e2b25 | 36 | PowerPC/AiX |
37 | PowerPC/VxWorks | |
38 | Sparc/Solaris | |
f9c9d5d3 | 39 | i386/GNU/Linux |
6f1e2b25 | 40 | i386/Solaris |
41 | i386/NT | |
42 | i386/OS2 | |
43 | i386/LynxOS | |
44 | Alpha/VxWorks | |
9dfe12ae | 45 | Alpha/VMS |
6f1e2b25 | 46 | */ |
47 | ||
48 | #ifdef __alpha_vxworks | |
49 | #include "vxWorks.h" | |
50 | #endif | |
51 | ||
52 | #ifdef IN_RTS | |
53 | #define POSIX | |
54 | #include "tconfig.h" | |
55 | #include "tsystem.h" | |
56 | #else | |
57 | #include "config.h" | |
58 | #include "system.h" | |
59 | #endif | |
60 | ||
9dfe12ae | 61 | extern int __gnat_backtrace PARAMS ((void **, int, void *, void *, int)); |
62 | ||
63 | /* The point is to provide an implementation of the __gnat_bactrace function | |
64 | above, called by the default implementation of the System.Traceback | |
65 | package. | |
66 | ||
67 | We first have a series of target specific implementations, each included | |
68 | from a separate C file for readability purposes. | |
69 | ||
70 | Then comes a somewhat generic implementation based on a set of macro and | |
71 | structure definitions which may be tailored on a per target basis. The | |
72 | presence of a definition for one of these macros (PC_ADJUST) controls | |
73 | wether or not the generic implementation is included. | |
74 | ||
75 | Finally, there is a default dummy implementation, necessary to make the | |
76 | linker happy on platforms where the feature is not supported, but where the | |
77 | function is still referenced by the default System.Traceback. */ | |
78 | ||
6f1e2b25 | 79 | #define Lock_Task system__soft_links__lock_task |
0f13b49d | 80 | extern void (*Lock_Task) PARAMS ((void)); |
6f1e2b25 | 81 | |
82 | #define Unlock_Task system__soft_links__unlock_task | |
0f13b49d | 83 | extern void (*Unlock_Task) PARAMS ((void)); |
6f1e2b25 | 84 | |
9dfe12ae | 85 | /*-------------------------------------* |
86 | *-- Target specific implementations --* | |
87 | *-------------------------------------*/ | |
6f1e2b25 | 88 | |
9dfe12ae | 89 | #if defined (__alpha_vxworks) |
6f1e2b25 | 90 | |
9dfe12ae | 91 | #include "tb-alvxw.c" |
6f1e2b25 | 92 | |
9dfe12ae | 93 | #elif defined (__ALPHA) && defined (__VMS__) |
6f1e2b25 | 94 | |
9dfe12ae | 95 | #include "tb-alvms.c" |
6f1e2b25 | 96 | |
9dfe12ae | 97 | #else |
98 | /* No target specific implementation. */ | |
99 | ||
100 | /*----------------------------------------------------------------* | |
101 | *-- Target specific definitions for the generic implementation --* | |
102 | *----------------------------------------------------------------*/ | |
103 | ||
104 | /* The stack layout is specified by the target ABI. The "generic" scheme is | |
105 | based on the following assumption: | |
106 | ||
107 | The stack layout from some frame pointer is such that the information | |
108 | required to compute the backtrace is available at static offsets. | |
109 | ||
110 | For a given frame, the information we are interested in is the saved return | |
111 | address (somewhere after the call instruction in the caller) and a pointer | |
112 | to the caller's frame. The former is the base of the call chain information | |
113 | we store in the tracebacks array. The latter allows us to loop over the | |
114 | successive frames in the chain. | |
115 | ||
116 | To initiate the process, we retrieve an initial frame pointer using the | |
117 | appropriate GCC builtin (__builtin_frame_address). | |
118 | ||
119 | This scheme is unfortunately not applicable on every target because the | |
120 | stack layout is not necessarily regular (static) enough. On targets where | |
121 | this scheme applies, the implementation relies on the following items: | |
122 | ||
123 | o struct layout, describing the expected stack data layout relevant to the | |
124 | information we are interested in, | |
125 | ||
126 | o FRAME_OFFSET, the offset, from a given frame pointer, at which this | |
127 | layout will be found, | |
128 | ||
129 | o FRAME_LEVEL, controls how many frames up we get at to start with, | |
130 | from the initial frame pointer we compute by way of the GCC builtin, | |
131 | ||
132 | 0 is most often the appropriate value. 1 may be necessary on targets | |
133 | where return addresses are saved by a function in it's caller's frame | |
134 | (e.g. PPC). | |
135 | ||
136 | o PC_ADJUST, to account for the difference between a call point (address | |
137 | of a call instruction), which is what we want in the output array, and | |
138 | the associated return address, which is what we retrieve from the stack. | |
139 | ||
140 | o STOP_FRAME, to decide wether we reached the top of the call chain, and | |
141 | thus if the process shall stop. | |
142 | ||
143 | : | |
144 | : stack | |
145 | | +----------------+ | |
146 | | +-------->| : | | |
147 | | | | (FRAME_OFFSET) | | |
148 | | | | : | (PC_ADJUST) | |
149 | | | layout:| return_address ----------------+ | |
150 | | | | .... | | | |
151 | +--------------- next_frame | | | |
152 | | | .... | | | |
153 | | | | | | |
154 | | +----------------+ | +-----+ | |
155 | | | : |<- Base fp | | : | | |
156 | | | (FRAME_OFFSET) | (FRAME_LEVEL) | | : | | |
157 | | | : | +---> | [1] | |
158 | | layout:| return_address --------------------> | [0] | |
159 | | | ... | (PC_ADJUST) +-----+ | |
160 | +---------- next_frame | traceback[] | |
161 | | ... | | |
162 | | | | |
163 | +----------------+ | |
164 | ||
165 | o BASE_SKIP, | |
166 | ||
167 | Since we inherently deal with return addresses, there is an implicit shift | |
168 | by at least one for the initial point we are able to observe in the chain. | |
169 | ||
170 | On some targets (e.g. sparc-solaris), the first return address we can | |
171 | easily get without special code is even our caller's return address, so | |
172 | there is a initial shift of two. | |
173 | ||
174 | BASE_SKIP represents this initial shift, which is the minimal "skip_frames" | |
175 | value we support. We could add special code for the skip_frames < BASE_SKIP | |
176 | cases. This is not done currently because there is virtually no situation | |
177 | in which this would be useful. | |
178 | ||
179 | Finally, to account for some ABI specificities, a target may (but does | |
180 | not have to) define: | |
181 | ||
182 | o FORCE_CALL, to force a call to a dummy function at the very beginning | |
183 | of the computation. See the PPC AIX target for an example where this | |
184 | is useful. | |
185 | ||
186 | o FETCH_UP_FRAME, to force an invocation of __builtin_frame_address with a | |
187 | positive argument right after a possibly forced call even if FRAME_LEVEL | |
188 | is 0. See the Sparc Solaris case for an example where this is useful. | |
189 | ||
190 | */ | |
191 | ||
192 | /*------------------------------ PPC AIX -------------------------------*/ | |
193 | ||
194 | #if defined (_AIX) | |
6f1e2b25 | 195 | struct layout |
196 | { | |
197 | struct layout *next; | |
198 | void *pad; | |
199 | void *return_address; | |
200 | }; | |
201 | ||
6f1e2b25 | 202 | #define FRAME_OFFSET 0 |
6f1e2b25 | 203 | #define PC_ADJUST -4 |
204 | #define STOP_FRAME(CURRENT, TOP_STACK) ((void *) (CURRENT) < (TOP_STACK)) | |
205 | ||
9dfe12ae | 206 | /* The PPC ABI has an interesting specificity: the return address saved by a |
207 | function is located in it's caller's frame, and the save operation only | |
208 | takes place if the function performs a call. | |
209 | ||
210 | To have __gnat_backtrace retrieve it's own return address, we then | |
211 | define ... */ | |
212 | ||
213 | #define FORCE_CALL | |
214 | #define FRAME_LEVEL 1 | |
215 | ||
216 | #define BASE_SKIP 1 | |
217 | ||
218 | /*---------------------------- PPC VxWorks------------------------------*/ | |
219 | ||
6f1e2b25 | 220 | #elif defined (_ARCH_PPC) && defined (__vxworks) |
221 | struct layout | |
222 | { | |
223 | struct layout *next; | |
224 | void *return_address; | |
225 | }; | |
226 | ||
9dfe12ae | 227 | #define FORCE_CALL |
6f1e2b25 | 228 | #define FRAME_LEVEL 1 |
9dfe12ae | 229 | /* See the PPC AIX case for an explanation of these values. */ |
230 | ||
6f1e2b25 | 231 | #define FRAME_OFFSET 0 |
9dfe12ae | 232 | #define PC_ADJUST -4 |
6f1e2b25 | 233 | #define STOP_FRAME(CURRENT, TOP_STACK) ((CURRENT)->return_address == 0) |
234 | ||
9dfe12ae | 235 | #define BASE_SKIP 1 |
236 | ||
237 | /*-------------------------- Sparc Solaris -----------------------------*/ | |
238 | ||
6f1e2b25 | 239 | #elif defined (sun) && defined (sparc) |
9dfe12ae | 240 | |
241 | /* These definitions are inspired from the Appendix D (Software | |
242 | Considerations) of the SPARC V8 architecture manual. */ | |
243 | ||
6f1e2b25 | 244 | struct layout |
245 | { | |
246 | struct layout *next; | |
247 | void *return_address; | |
248 | }; | |
249 | ||
9dfe12ae | 250 | #define FRAME_LEVEL 0 |
251 | #define FRAME_OFFSET (14 * (sizeof (void*))) | |
6f1e2b25 | 252 | #define PC_ADJUST 0 |
253 | #define STOP_FRAME(CURRENT, TOP_STACK) \ | |
254 | ((CURRENT)->return_address == 0|| (CURRENT)->next == 0 \ | |
255 | || (void *) (CURRENT) < (TOP_STACK)) | |
256 | ||
9dfe12ae | 257 | /* The sparc register windows need to be flushed before we may access them |
258 | from the stack. This is achieved by way of builtin_frame_address only | |
259 | when the "count" argument is positive, so force at least one such call. */ | |
260 | #define FETCH_UP_FRAME_ADDRESS | |
261 | ||
262 | #define BASE_SKIP 2 | |
263 | /* From the frame pointer of frame N, we are accessing the flushed register | |
264 | window of frame N-1 (positive offset from fp), in which we retrieve the | |
265 | saved return address. We then end up with our caller's return address. */ | |
266 | ||
267 | /*------------------------------- x86 ----------------------------------*/ | |
268 | ||
6f1e2b25 | 269 | #elif defined (i386) |
270 | struct layout | |
271 | { | |
272 | struct layout *next; | |
273 | void *return_address; | |
274 | }; | |
275 | ||
f15731c4 | 276 | #ifdef _WIN32 |
277 | /* _image_base__ is the image starting address, no stack addresses should be | |
278 | under this value */ | |
279 | extern unsigned int _image_base__; | |
280 | #define LOWEST_ADDR ((unsigned int) (&_image_base__)) | |
281 | #else | |
282 | #define LOWEST_ADDR 0 | |
283 | #endif | |
284 | ||
6f1e2b25 | 285 | #define FRAME_LEVEL 0 |
286 | #define FRAME_OFFSET 0 | |
6f1e2b25 | 287 | #define PC_ADJUST -2 |
288 | #define STOP_FRAME(CURRENT, TOP_STACK) \ | |
f15731c4 | 289 | ((unsigned int)(CURRENT)->return_address < LOWEST_ADDR \ |
290 | || (CURRENT)->return_address == 0|| (CURRENT)->next == 0 \ | |
6f1e2b25 | 291 | || (void *) (CURRENT) < (TOP_STACK)) |
292 | ||
9dfe12ae | 293 | #define BASE_SKIP 1 |
294 | ||
f15731c4 | 295 | /* On i386 architecture we check that at the call point we really have a call |
296 | insn. Possible call instructions are: | |
297 | ||
298 | call addr16 E8 xx xx xx xx | |
299 | call reg FF Dx | |
300 | call off(reg) FF xx xx | |
301 | lcall addr seg 9A xx xx xx xx xx xx | |
302 | ||
303 | This check will not catch all cases but it will increase the backtrace | |
304 | reliability on this architecture. | |
305 | */ | |
306 | ||
307 | #define VALID_STACK_FRAME(ptr) \ | |
308 | (((*((ptr) - 3) & 0xff) == 0xe8) \ | |
9dfe12ae | 309 | || ((*((ptr) - 5) & 0xff) == 0x9a) \ |
310 | || ((*((ptr) - 1) & 0xff) == 0xff) \ | |
311 | || (((*(ptr) & 0xd0ff) == 0xd0ff))) | |
f15731c4 | 312 | |
6f1e2b25 | 313 | #endif |
314 | ||
9dfe12ae | 315 | /*---------------------------------------* |
316 | *-- The generic implementation per se --* | |
317 | *---------------------------------------*/ | |
6f1e2b25 | 318 | |
9dfe12ae | 319 | #if defined (PC_ADJUST) |
6f1e2b25 | 320 | |
9dfe12ae | 321 | #ifndef CURRENT_STACK_FRAME |
322 | # define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) | |
6f1e2b25 | 323 | #endif |
324 | ||
9dfe12ae | 325 | |
f15731c4 | 326 | #ifndef VALID_STACK_FRAME |
327 | #define VALID_STACK_FRAME(ptr) 1 | |
328 | #endif | |
329 | ||
9dfe12ae | 330 | #define MAX(x,y) ((x) > (y) ? (x) : (y)) |
331 | ||
332 | /* Define a dummy function to call if FORCE_CALL is defined. Don't | |
333 | define it otherwise, as this could lead to "defined but not used" | |
334 | warnings. */ | |
335 | #if defined (FORCE_CALL) | |
336 | static void forced_callee () {} | |
337 | #endif | |
338 | ||
6f1e2b25 | 339 | int |
9dfe12ae | 340 | __gnat_backtrace (array, size, exclude_min, exclude_max, skip_frames) |
6f1e2b25 | 341 | void **array; |
342 | int size; | |
343 | void *exclude_min; | |
344 | void *exclude_max; | |
9dfe12ae | 345 | int skip_frames; |
6f1e2b25 | 346 | { |
347 | struct layout *current; | |
348 | void *top_frame; | |
349 | void *top_stack; | |
6f1e2b25 | 350 | int cnt = 0; |
351 | ||
9dfe12ae | 352 | /* Honor FORCE_CALL when defined. */ |
353 | #if defined (FORCE_CALL) | |
354 | forced_callee (); | |
355 | #endif | |
6f1e2b25 | 356 | |
9dfe12ae | 357 | /* Force a call to builtin_frame_address with a positive argument |
358 | if required. This is necessary e.g. on sparc to have the register | |
359 | windows flushed before we attempt to access them on the stack. */ | |
360 | #if defined (FETCH_UP_FRAME_ADDRESS) && (FRAME_LEVEL == 0) | |
361 | __builtin_frame_address (1); | |
6f1e2b25 | 362 | #endif |
363 | ||
364 | top_frame = __builtin_frame_address (FRAME_LEVEL); | |
365 | top_stack = CURRENT_STACK_FRAME; | |
366 | current = (struct layout *) ((size_t) top_frame + FRAME_OFFSET); | |
367 | ||
9dfe12ae | 368 | /* Skip the number of calls we have been requested to skip, accounting for |
369 | the BASE_SKIP parameter. | |
6f1e2b25 | 370 | |
9dfe12ae | 371 | FRAME_LEVEL is meaningless for the count adjustment. It impacts where we |
372 | start retrieving data from, but how many frames "up" we start at is in | |
373 | BASE_SKIP by definition. */ | |
6f1e2b25 | 374 | |
9dfe12ae | 375 | skip_frames = MAX (0, skip_frames - BASE_SKIP); |
376 | ||
377 | while (cnt < skip_frames) | |
6f1e2b25 | 378 | { |
379 | current = (struct layout *) ((size_t) current->next + FRAME_OFFSET); | |
380 | cnt++; | |
381 | } | |
382 | ||
383 | cnt = 0; | |
384 | while (cnt < size) | |
385 | { | |
9dfe12ae | 386 | if (STOP_FRAME (current, top_stack) || |
f15731c4 | 387 | !VALID_STACK_FRAME((char *)(current->return_address + PC_ADJUST))) |
6f1e2b25 | 388 | break; |
389 | ||
390 | if (current->return_address < exclude_min | |
391 | || current->return_address > exclude_max) | |
392 | array[cnt++] = current->return_address + PC_ADJUST; | |
393 | ||
394 | current = (struct layout *) ((size_t) current->next + FRAME_OFFSET); | |
395 | } | |
396 | ||
6f1e2b25 | 397 | return cnt; |
398 | } | |
399 | ||
400 | #else | |
9dfe12ae | 401 | /* No target specific implementation and PC_ADJUST not defined. */ |
6f1e2b25 | 402 | |
9dfe12ae | 403 | /*------------------------------* |
404 | *-- The dummy implementation --* | |
405 | *------------------------------*/ | |
6f1e2b25 | 406 | |
9dfe12ae | 407 | int |
408 | __gnat_backtrace (array, size, exclude_min, exclude_max, skip_frames) | |
409 | void **array ATTRIBUTE_UNUSED; | |
410 | int size ATTRIBUTE_UNUSED; | |
411 | void *exclude_min ATTRIBUTE_UNUSED; | |
412 | void *exclude_max ATTRIBUTE_UNUSED; | |
413 | int skip_frames ATTRIBUTE_UNUSED; | |
6f1e2b25 | 414 | { |
6f1e2b25 | 415 | return 0; |
416 | } | |
417 | ||
6f1e2b25 | 418 | #endif |
419 | ||
6f1e2b25 | 420 | #endif |