]>
Commit | Line | Data |
---|---|---|
415dddc8 RK |
1 | /**************************************************************************** |
2 | * * | |
b3c33641 | 3 | * GNAT RUN-TIME COMPONENTS * |
415dddc8 RK |
4 | * * |
5 | * T R A C E B A C K * | |
6 | * * | |
7 | * C Implementation File * | |
8 | * * | |
8d0d46f4 | 9 | * Copyright (C) 2000-2021, Free Software Foundation, Inc. * |
415dddc8 RK |
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- * | |
b3c33641 | 13 | * ware Foundation; either version 3, or (at your option) any later ver- * |
415dddc8 RK |
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 * | |
b3c33641 | 16 | * or FITNESS FOR A PARTICULAR PURPOSE. * |
415dddc8 | 17 | * * |
b3c33641 AC |
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/>. * | |
415dddc8 RK |
26 | * * |
27 | * GNAT was originally developed by the GNAT team at New York University. * | |
fbf5a39b | 28 | * Extensive contributions were provided by Ada Core Technologies Inc. * |
415dddc8 RK |
29 | * * |
30 | ****************************************************************************/ | |
31 | ||
32 | /* This file contains low level support for stack unwinding using GCC intrinsic | |
33 | functions. | |
34 | It has been tested on the following configurations: | |
415dddc8 | 35 | PowerPC/AiX |
e7ad2039 | 36 | PowerPC/Darwin |
415dddc8 | 37 | PowerPC/VxWorks |
8ca1ee5d | 38 | PowerPC/LynxOS-178 |
ce2e12c2 | 39 | SPARC/Solaris |
5d1a9698 | 40 | i386/GNU/Linux |
415dddc8 RK |
41 | i386/Solaris |
42 | i386/NT | |
43 | i386/OS2 | |
44 | i386/LynxOS | |
45 | Alpha/VxWorks | |
fbf5a39b | 46 | Alpha/VMS |
415dddc8 RK |
47 | */ |
48 | ||
9e9bd455 LG |
49 | #ifdef __cplusplus |
50 | extern "C" { | |
51 | #endif | |
52 | ||
415dddc8 RK |
53 | #ifdef IN_RTS |
54 | #define POSIX | |
a6fc663e AC |
55 | #include "runtime.h" |
56 | #include <stddef.h> | |
415dddc8 RK |
57 | #else |
58 | #include "config.h" | |
59 | #include "system.h" | |
262e7125 RG |
60 | /* We don't want fancy_abort here. */ |
61 | #undef abort | |
415dddc8 RK |
62 | #endif |
63 | ||
9373164a | 64 | extern int __gnat_backtrace (void **, int, void *, void *, int); |
fbf5a39b | 65 | |
0da2c8ac AC |
66 | /* The point is to provide an implementation of the __gnat_backtrace function |
67 | above, called by the default implementation of the System.Traceback package. | |
fbf5a39b AC |
68 | |
69 | We first have a series of target specific implementations, each included | |
70 | from a separate C file for readability purposes. | |
71 | ||
0da2c8ac AC |
72 | Then come two flavors of a generic implementation: one relying on static |
73 | assumptions about the frame layout, and the other one using the GCC EH | |
74 | infrastructure. The former uses a whole set of macros and structures which | |
75 | may be tailored on a per target basis, and is activated as soon as | |
76 | USE_GENERIC_UNWINDER is defined. The latter uses a small subset of the | |
77 | macro definitions and is activated when USE_GCC_UNWINDER is defined. It is | |
78 | only available post GCC 3.3. | |
fbf5a39b AC |
79 | |
80 | Finally, there is a default dummy implementation, necessary to make the | |
81 | linker happy on platforms where the feature is not supported, but where the | |
82 | function is still referenced by the default System.Traceback. */ | |
83 | ||
415dddc8 | 84 | #define Lock_Task system__soft_links__lock_task |
9373164a | 85 | extern void (*Lock_Task) (void); |
415dddc8 RK |
86 | |
87 | #define Unlock_Task system__soft_links__unlock_task | |
9373164a | 88 | extern void (*Unlock_Task) (void); |
415dddc8 | 89 | |
fbf5a39b AC |
90 | /*-------------------------------------* |
91 | *-- Target specific implementations --* | |
92 | *-------------------------------------*/ | |
415dddc8 | 93 | |
24d4b3d5 | 94 | #if defined (_WIN64) && defined (__SEH__) |
22a83cea AC |
95 | |
96 | #include <windows.h> | |
97 | ||
08f52d9f AC |
98 | #define IS_BAD_PTR(ptr) (IsBadCodePtr((FARPROC)ptr)) |
99 | ||
22a83cea AC |
100 | int |
101 | __gnat_backtrace (void **array, | |
102 | int size, | |
103 | void *exclude_min, | |
104 | void *exclude_max, | |
105 | int skip_frames) | |
106 | { | |
107 | CONTEXT context; | |
108 | UNWIND_HISTORY_TABLE history; | |
109 | int i; | |
110 | ||
111 | /* Get the context. */ | |
112 | RtlCaptureContext (&context); | |
113 | ||
114 | /* Setup unwind history table (a cached to speed-up unwinding). */ | |
115 | memset (&history, 0, sizeof (history)); | |
116 | ||
117 | i = 0; | |
118 | while (1) | |
119 | { | |
120 | PRUNTIME_FUNCTION RuntimeFunction; | |
121 | KNONVOLATILE_CONTEXT_POINTERS NvContext; | |
122 | ULONG64 ImageBase; | |
123 | VOID *HandlerData; | |
124 | ULONG64 EstablisherFrame; | |
125 | ||
126 | /* Get function metadata. */ | |
127 | RuntimeFunction = RtlLookupFunctionEntry | |
128 | (context.Rip, &ImageBase, &history); | |
129 | ||
130 | if (!RuntimeFunction) | |
131 | { | |
132 | /* In case of failure, assume this is a leaf function. */ | |
d9819bbd | 133 | context.Rip = *(ULONG64 *) context.Rsp; |
22a83cea AC |
134 | context.Rsp += 8; |
135 | } | |
136 | else | |
137 | { | |
08f52d9f AC |
138 | /* If the last unwinding step failed somehow, stop here. */ |
139 | if (IS_BAD_PTR(context.Rip)) | |
140 | break; | |
141 | ||
22a83cea AC |
142 | /* Unwind. */ |
143 | memset (&NvContext, 0, sizeof (KNONVOLATILE_CONTEXT_POINTERS)); | |
144 | RtlVirtualUnwind (0, ImageBase, context.Rip, RuntimeFunction, | |
145 | &context, &HandlerData, &EstablisherFrame, | |
146 | &NvContext); | |
147 | } | |
148 | ||
149 | /* 0 means bottom of the stack. */ | |
150 | if (context.Rip == 0) | |
151 | break; | |
152 | ||
153 | /* Skip frames. */ | |
c1107fa3 | 154 | if (skip_frames > 1) |
22a83cea AC |
155 | { |
156 | skip_frames--; | |
157 | continue; | |
158 | } | |
159 | /* Excluded frames. */ | |
160 | if ((void *)context.Rip >= exclude_min | |
161 | && (void *)context.Rip <= exclude_max) | |
162 | continue; | |
163 | ||
d9819bbd | 164 | array[i++] = (void *)(context.Rip - 2); |
22a83cea AC |
165 | if (i >= size) |
166 | break; | |
167 | } | |
168 | return i; | |
169 | } | |
fbf5a39b | 170 | #else |
6d64bc37 | 171 | |
fbf5a39b AC |
172 | /* No target specific implementation. */ |
173 | ||
174 | /*----------------------------------------------------------------* | |
175 | *-- Target specific definitions for the generic implementation --* | |
176 | *----------------------------------------------------------------*/ | |
177 | ||
178 | /* The stack layout is specified by the target ABI. The "generic" scheme is | |
179 | based on the following assumption: | |
180 | ||
181 | The stack layout from some frame pointer is such that the information | |
182 | required to compute the backtrace is available at static offsets. | |
183 | ||
184 | For a given frame, the information we are interested in is the saved return | |
185 | address (somewhere after the call instruction in the caller) and a pointer | |
186 | to the caller's frame. The former is the base of the call chain information | |
187 | we store in the tracebacks array. The latter allows us to loop over the | |
188 | successive frames in the chain. | |
189 | ||
e7ad2039 | 190 | To initiate the process, we retrieve an initial frame address using the |
fbf5a39b AC |
191 | appropriate GCC builtin (__builtin_frame_address). |
192 | ||
193 | This scheme is unfortunately not applicable on every target because the | |
194 | stack layout is not necessarily regular (static) enough. On targets where | |
195 | this scheme applies, the implementation relies on the following items: | |
196 | ||
197 | o struct layout, describing the expected stack data layout relevant to the | |
198 | information we are interested in, | |
199 | ||
e7ad2039 EB |
200 | o FRAME_OFFSET, the offset, from a given frame address or frame pointer |
201 | value, at which this layout will be found, | |
fbf5a39b AC |
202 | |
203 | o FRAME_LEVEL, controls how many frames up we get at to start with, | |
204 | from the initial frame pointer we compute by way of the GCC builtin, | |
205 | ||
206 | 0 is most often the appropriate value. 1 may be necessary on targets | |
207 | where return addresses are saved by a function in it's caller's frame | |
208 | (e.g. PPC). | |
209 | ||
210 | o PC_ADJUST, to account for the difference between a call point (address | |
211 | of a call instruction), which is what we want in the output array, and | |
212 | the associated return address, which is what we retrieve from the stack. | |
213 | ||
3354f96d | 214 | o STOP_FRAME, to decide whether we reached the top of the call chain, and |
fbf5a39b AC |
215 | thus if the process shall stop. |
216 | ||
217 | : | |
218 | : stack | |
219 | | +----------------+ | |
220 | | +-------->| : | | |
221 | | | | (FRAME_OFFSET) | | |
222 | | | | : | (PC_ADJUST) | |
223 | | | layout:| return_address ----------------+ | |
224 | | | | .... | | | |
225 | +--------------- next_frame | | | |
226 | | | .... | | | |
227 | | | | | | |
228 | | +----------------+ | +-----+ | |
229 | | | : |<- Base fp | | : | | |
230 | | | (FRAME_OFFSET) | (FRAME_LEVEL) | | : | | |
231 | | | : | +---> | [1] | |
232 | | layout:| return_address --------------------> | [0] | |
233 | | | ... | (PC_ADJUST) +-----+ | |
234 | +---------- next_frame | traceback[] | |
235 | | ... | | |
236 | | | | |
237 | +----------------+ | |
238 | ||
239 | o BASE_SKIP, | |
240 | ||
241 | Since we inherently deal with return addresses, there is an implicit shift | |
242 | by at least one for the initial point we are able to observe in the chain. | |
243 | ||
244 | On some targets (e.g. sparc-solaris), the first return address we can | |
245 | easily get without special code is even our caller's return address, so | |
246 | there is a initial shift of two. | |
247 | ||
248 | BASE_SKIP represents this initial shift, which is the minimal "skip_frames" | |
249 | value we support. We could add special code for the skip_frames < BASE_SKIP | |
250 | cases. This is not done currently because there is virtually no situation | |
251 | in which this would be useful. | |
252 | ||
253 | Finally, to account for some ABI specificities, a target may (but does | |
254 | not have to) define: | |
255 | ||
256 | o FORCE_CALL, to force a call to a dummy function at the very beginning | |
257 | of the computation. See the PPC AIX target for an example where this | |
258 | is useful. | |
259 | ||
260 | o FETCH_UP_FRAME, to force an invocation of __builtin_frame_address with a | |
261 | positive argument right after a possibly forced call even if FRAME_LEVEL | |
ce2e12c2 | 262 | is 0. See the SPARC Solaris case for an example where this is useful. |
fbf5a39b AC |
263 | |
264 | */ | |
265 | ||
88b76013 IS |
266 | /*------------------- Darwin 8 (OSX 10.4) or newer ----------------------*/ |
267 | #if defined (__APPLE__) \ | |
268 | && defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \ | |
269 | && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 | |
b3c33641 | 270 | |
88b76013 IS |
271 | #define USE_GCC_UNWINDER |
272 | ||
273 | #if defined (__i386__) || defined (__x86_64__) | |
274 | #define PC_ADJUST -2 | |
275 | #elif defined (__ppc__) || defined (__ppc64__) | |
276 | #define PC_ADJUST -4 | |
a9bbfbd0 AC |
277 | #elif defined (__arm__) |
278 | #define PC_ADJUST -2 | |
6fa8f71c AC |
279 | #elif defined (__arm64__) |
280 | #define PC_ADJUST -4 | |
88b76013 IS |
281 | #else |
282 | #error Unhandled darwin architecture. | |
283 | #endif | |
fbf5a39b | 284 | |
90af5990 JM |
285 | /*---------------------------- x86 *BSD --------------------------------*/ |
286 | ||
287 | #elif defined (__i386__) && \ | |
288 | ( defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__) ) | |
289 | ||
290 | #define USE_GCC_UNWINDER | |
291 | /* The generic unwinder is not used for this target because the default | |
292 | implementation doesn't unwind on the BSD platforms. AMD64 targets use the | |
293 | gcc unwinder for all platforms, so let's keep i386 consistent with that. | |
294 | */ | |
295 | ||
296 | #define PC_ADJUST -2 | |
297 | /* The minimum size of call instructions on this architecture is 2 bytes */ | |
298 | ||
1e60643a AC |
299 | /*---------------------- ARM VxWorks ------------------------------------*/ |
300 | #elif (defined (ARMEL) && defined (__vxworks)) | |
301 | ||
302 | #include "vxWorks.h" | |
303 | #include "version.h" | |
304 | ||
305 | #define USE_GCC_UNWINDER | |
306 | #define PC_ADJUST -2 | |
307 | ||
1554ed7e | 308 | #if ((_WRS_VXWORKS_MAJOR >= 7) && (_VX_CPU != ARMARCH8A)) |
1e60643a AC |
309 | #define USING_ARM_UNWINDING 1 |
310 | #endif | |
311 | ||
e5e963ab DR |
312 | /*---------------------- ARM Linux ------------------------------------ -*/ |
313 | #elif (defined (__ARMEL__) && defined (__linux)) | |
314 | ||
315 | #define USE_GCC_UNWINDER | |
316 | #define PC_ADJUST -2 | |
317 | #define USING_ARM_UNWINDING 1 | |
318 | ||
1e60643a | 319 | /*---------------------- PPC AIX/PPC Lynx 178/Older Darwin --------------*/ |
88b76013 | 320 | #elif ((defined (_POWER) && defined (_AIX)) || \ |
8ca1ee5d AC |
321 | (defined (__powerpc__) && defined (__Lynx__) && !defined(__ELF__)) || \ |
322 | (defined (__ppc__) && defined (__APPLE__))) | |
0da2c8ac AC |
323 | |
324 | #define USE_GENERIC_UNWINDER | |
325 | ||
415dddc8 RK |
326 | struct layout |
327 | { | |
328 | struct layout *next; | |
329 | void *pad; | |
330 | void *return_address; | |
331 | }; | |
332 | ||
e7ad2039 | 333 | #define FRAME_OFFSET(FP) 0 |
415dddc8 | 334 | #define PC_ADJUST -4 |
3f5a8fee AC |
335 | |
336 | /* Eventhough the base PPC ABI states that a toplevel frame entry | |
337 | should to feature a null backchain, AIX might expose a null return | |
338 | address instead. */ | |
339 | ||
8ca1ee5d AC |
340 | /* Then LynxOS-178 features yet another variation, with return_address |
341 | == &<entrypoint>, with two possible entry points (one for the main | |
342 | process and one for threads). Beware that &bla returns the address | |
343 | of a descriptor when "bla" is a function. Getting the code address | |
344 | requires an extra dereference. */ | |
345 | ||
346 | #if defined (__Lynx__) | |
347 | extern void __start(); /* process entry point. */ | |
348 | extern void __runnit(); /* thread entry point. */ | |
349 | #define EXTRA_STOP_CONDITION(CURRENT) \ | |
350 | ((CURRENT)->return_address == *(void**)&__start \ | |
351 | || (CURRENT)->return_address == *(void**)&__runnit) | |
352 | #else | |
353 | #define EXTRA_STOP_CONDITION(CURRENT) (0) | |
354 | #endif | |
355 | ||
3f5a8fee AC |
356 | #define STOP_FRAME(CURRENT, TOP_STACK) \ |
357 | (((void *) (CURRENT) < (TOP_STACK)) \ | |
8ca1ee5d AC |
358 | || (CURRENT)->return_address == NULL \ |
359 | || EXTRA_STOP_CONDITION(CURRENT)) | |
415dddc8 | 360 | |
fbf5a39b AC |
361 | /* The PPC ABI has an interesting specificity: the return address saved by a |
362 | function is located in it's caller's frame, and the save operation only | |
363 | takes place if the function performs a call. | |
364 | ||
bde83138 | 365 | To have __gnat_backtrace retrieve its own return address, we then |
fbf5a39b AC |
366 | define ... */ |
367 | ||
7dc56b36 | 368 | #define FORCE_CALL 1 |
fbf5a39b AC |
369 | #define FRAME_LEVEL 1 |
370 | ||
371 | #define BASE_SKIP 1 | |
372 | ||
0310af44 | 373 | /*----------- PPC ELF (GNU/Linux & VxWorks & Lynx178e) -------------------*/ |
fbf5a39b | 374 | |
36cee502 | 375 | #elif (defined (_ARCH_PPC) && defined (__vxworks)) || \ |
0310af44 | 376 | (defined (__powerpc__) && defined (__Lynx__) && defined(__ELF__)) || \ |
329be64b | 377 | (defined (__linux__) && defined (__powerpc__)) |
0da2c8ac | 378 | |
967947ed PMR |
379 | #if defined (_ARCH_PPC64) && !defined (__USING_SJLJ_EXCEPTIONS__) |
380 | #define USE_GCC_UNWINDER | |
381 | #else | |
0da2c8ac | 382 | #define USE_GENERIC_UNWINDER |
967947ed | 383 | #endif |
0da2c8ac | 384 | |
415dddc8 RK |
385 | struct layout |
386 | { | |
387 | struct layout *next; | |
388 | void *return_address; | |
389 | }; | |
390 | ||
7dc56b36 | 391 | #define FORCE_CALL 1 |
415dddc8 | 392 | #define FRAME_LEVEL 1 |
fbf5a39b AC |
393 | /* See the PPC AIX case for an explanation of these values. */ |
394 | ||
e7ad2039 | 395 | #define FRAME_OFFSET(FP) 0 |
fbf5a39b | 396 | #define PC_ADJUST -4 |
c5f5123f AC |
397 | |
398 | /* According to the base PPC ABI, a toplevel frame entry should feature | |
399 | a null backchain. What happens at signal handler frontiers isn't so | |
400 | well specified, so we add a safety guard on top. */ | |
401 | ||
402 | #define STOP_FRAME(CURRENT, TOP_STACK) \ | |
403 | ((CURRENT)->next == 0 || ((long)(CURRENT)->next % __alignof__(void*)) != 0) | |
415dddc8 | 404 | |
fbf5a39b AC |
405 | #define BASE_SKIP 1 |
406 | ||
30f07d92 | 407 | /*-------------------------- SPARC Solaris -----------------------------*/ |
fbf5a39b | 408 | |
329be64b | 409 | #elif defined (__sun__) && defined (__sparc__) |
fbf5a39b | 410 | |
0da2c8ac AC |
411 | #define USE_GENERIC_UNWINDER |
412 | ||
fbf5a39b AC |
413 | /* These definitions are inspired from the Appendix D (Software |
414 | Considerations) of the SPARC V8 architecture manual. */ | |
415 | ||
415dddc8 RK |
416 | struct layout |
417 | { | |
418 | struct layout *next; | |
419 | void *return_address; | |
420 | }; | |
421 | ||
30f07d92 OH |
422 | #ifdef __arch64__ |
423 | #define STACK_BIAS 2047 /* V9 ABI */ | |
424 | #else | |
425 | #define STACK_BIAS 0 /* V8 ABI */ | |
426 | #endif | |
427 | ||
fbf5a39b | 428 | #define FRAME_LEVEL 0 |
e7ad2039 | 429 | #define FRAME_OFFSET(FP) (14 * sizeof (void*) + (FP ? STACK_BIAS : 0)) |
415dddc8 RK |
430 | #define PC_ADJUST 0 |
431 | #define STOP_FRAME(CURRENT, TOP_STACK) \ | |
432 | ((CURRENT)->return_address == 0|| (CURRENT)->next == 0 \ | |
433 | || (void *) (CURRENT) < (TOP_STACK)) | |
434 | ||
e7ad2039 | 435 | /* The SPARC register windows need to be flushed before we may access them |
fbf5a39b AC |
436 | from the stack. This is achieved by way of builtin_frame_address only |
437 | when the "count" argument is positive, so force at least one such call. */ | |
438 | #define FETCH_UP_FRAME_ADDRESS | |
439 | ||
440 | #define BASE_SKIP 2 | |
441 | /* From the frame pointer of frame N, we are accessing the flushed register | |
442 | window of frame N-1 (positive offset from fp), in which we retrieve the | |
443 | saved return address. We then end up with our caller's return address. */ | |
444 | ||
45fbea4f | 445 | /*---------------------------- x86 & x86_64 ---------------------------------*/ |
fbf5a39b | 446 | |
45fbea4f | 447 | #elif defined (__i386__) || defined (__x86_64__) |
0da2c8ac | 448 | |
2995ebee | 449 | #if defined (__WIN32) |
b194546e | 450 | #include <windows.h> |
7d00dca9 | 451 | #define IS_BAD_PTR(ptr) (IsBadCodePtr((FARPROC)ptr)) |
329be64b | 452 | #elif defined (__sun__) |
74c9e852 | 453 | #define IS_BAD_PTR(ptr) ((unsigned long)ptr == -1UL) |
b194546e PO |
454 | #else |
455 | #define IS_BAD_PTR(ptr) 0 | |
456 | #endif | |
457 | ||
45fbea4f AC |
458 | /* Use the dwarf2 unwinder when we expect to have dwarf2 tables at |
459 | hand. Backtraces will reliably stop on frames missing such tables, | |
460 | but our only alternative is the generic unwinder which requires | |
461 | compilation forcing a frame pointer to be reliable. */ | |
462 | ||
ccaca7e9 | 463 | #if (defined (__x86_64__) || defined (__linux__)) && !defined (__USING_SJLJ_EXCEPTIONS__) |
fbb12873 EB |
464 | #define USE_GCC_UNWINDER |
465 | #else | |
0da2c8ac | 466 | #define USE_GENERIC_UNWINDER |
fbb12873 | 467 | #endif |
0da2c8ac | 468 | |
415dddc8 RK |
469 | struct layout |
470 | { | |
471 | struct layout *next; | |
472 | void *return_address; | |
473 | }; | |
474 | ||
748d8778 | 475 | #define FRAME_LEVEL 1 |
45fbea4f AC |
476 | /* builtin_frame_address (1) is expected to work on this family of targets, |
477 | and (0) might return the soft stack pointer, which does not designate a | |
478 | location where a backchain and a return address might be found. */ | |
748d8778 | 479 | |
e7ad2039 | 480 | #define FRAME_OFFSET(FP) 0 |
415dddc8 RK |
481 | #define PC_ADJUST -2 |
482 | #define STOP_FRAME(CURRENT, TOP_STACK) \ | |
d15d61c6 | 483 | (IS_BAD_PTR((long)(CURRENT)) \ |
fe1db400 | 484 | || (void *) (CURRENT) < (TOP_STACK) \ |
d15d61c6 | 485 | || IS_BAD_PTR((long)(CURRENT)->return_address) \ |
7ae0d98c AC |
486 | || (CURRENT)->return_address == 0 \ |
487 | || (void *) ((CURRENT)->next) < (TOP_STACK) \ | |
fe1db400 | 488 | || EXTRA_STOP_CONDITION(CURRENT)) |
415dddc8 | 489 | |
748d8778 | 490 | #define BASE_SKIP (1+FRAME_LEVEL) |
fbf5a39b | 491 | |
07fc65c4 GB |
492 | /* On i386 architecture we check that at the call point we really have a call |
493 | insn. Possible call instructions are: | |
494 | ||
495 | call addr16 E8 xx xx xx xx | |
496 | call reg FF Dx | |
497 | call off(reg) FF xx xx | |
498 | lcall addr seg 9A xx xx xx xx xx xx | |
499 | ||
500 | This check will not catch all cases but it will increase the backtrace | |
501 | reliability on this architecture. | |
502 | */ | |
503 | ||
504 | #define VALID_STACK_FRAME(ptr) \ | |
b194546e PO |
505 | (!IS_BAD_PTR(ptr) \ |
506 | && (((*((ptr) - 3) & 0xff) == 0xe8) \ | |
507 | || ((*((ptr) - 5) & 0xff) == 0x9a) \ | |
508 | || ((*((ptr) - 1) & 0xff) == 0xff) \ | |
509 | || (((*(ptr) & 0xd0ff) == 0xd0ff)))) | |
07fc65c4 | 510 | |
fe1db400 FK |
511 | #if defined (__vxworks) && defined (__RTP__) |
512 | ||
513 | /* For VxWorks following backchains past the "main" frame gets us into the | |
514 | kernel space, where it can't be dereferenced. So lets stop at the main | |
515 | symbol. */ | |
516 | extern void main(); | |
517 | ||
518 | static int | |
519 | is_return_from(void *symbol_addr, void *ret_addr) | |
520 | { | |
521 | int ret = 0; | |
522 | char *ptr = (char *)ret_addr; | |
523 | ||
524 | if ((*(ptr - 5) & 0xff) == 0xe8) | |
525 | { | |
526 | /* call addr16 E8 xx xx xx xx */ | |
527 | int32_t offset = *(int32_t *)(ptr - 4); | |
528 | ret = (ptr + offset) == symbol_addr; | |
529 | } | |
530 | ||
531 | /* Others not implemented yet... But it is very likely that call addr16 | |
532 | is used here. */ | |
533 | return ret; | |
534 | } | |
535 | ||
536 | #define EXTRA_STOP_CONDITION(CURRENT) \ | |
537 | (is_return_from(&main, (CURRENT)->return_address)) | |
538 | #else /* not (defined (__vxworks) && defined (__RTP__)) */ | |
539 | #define EXTRA_STOP_CONDITION(CURRENT) (0) | |
540 | #endif /* not (defined (__vxworks) && defined (__RTP__)) */ | |
541 | ||
65e5747e PMR |
542 | /*----------------------------- qnx ----------------------------------*/ |
543 | ||
544 | #elif defined (__QNX__) | |
545 | ||
546 | #define USE_GCC_UNWINDER | |
547 | ||
548 | #if defined (__aarch64__) | |
549 | #define PC_ADJUST -4 | |
550 | #else | |
551 | #error Unhandled QNX architecture. | |
552 | #endif | |
553 | ||
621cccba PB |
554 | /*---------------------------- RTEMS ---------------------------------*/ |
555 | ||
556 | #elif defined (__rtems__) | |
557 | ||
558 | #define USE_GCC_UNWINDER | |
559 | ||
560 | #if defined (__aarch64__) | |
561 | #define PC_ADJUST -4 | |
562 | #else | |
563 | #error Unhandled RTEMS architecture. | |
564 | #endif | |
565 | ||
8ad3525a DR |
566 | /*------------------- aarch64-linux ----------------------------------*/ |
567 | ||
568 | #elif (defined (__aarch64__) && defined (__linux__)) | |
569 | ||
570 | #define USE_GCC_UNWINDER | |
571 | #define PC_ADJUST -4 | |
572 | ||
55d43609 MG |
573 | /*----------------------------- ia64 ---------------------------------*/ |
574 | ||
329be64b | 575 | #elif defined (__ia64__) && (defined (__linux__) || defined (__hpux__)) |
55d43609 MG |
576 | |
577 | #define USE_GCC_UNWINDER | |
748d8778 MG |
578 | /* Use _Unwind_Backtrace driven exceptions on ia64 HP-UX and ia64 |
579 | GNU/Linux, where _Unwind_Backtrace is provided by the system unwind | |
580 | library. On HP-UX 11.23 this requires patch PHSS_33352, which adds | |
581 | _Unwind_Backtrace to the system unwind library. */ | |
55d43609 | 582 | |
d72eef29 OH |
583 | #define PC_ADJUST -4 |
584 | ||
55d43609 | 585 | |
415dddc8 RK |
586 | #endif |
587 | ||
0da2c8ac AC |
588 | /*---------------------------------------------------------------------* |
589 | *-- The post GCC 3.3 infrastructure based implementation --* | |
590 | *---------------------------------------------------------------------*/ | |
591 | ||
592 | #if defined (USE_GCC_UNWINDER) && (__GNUC__ * 10 + __GNUC_MINOR__ > 33) | |
593 | ||
594 | /* Conditioning the inclusion on the GCC version is useful to avoid bootstrap | |
595 | path problems, since the included file refers to post 3.3 functions in | |
596 | libgcc, and the stage1 compiler is unlikely to be linked against a post 3.3 | |
597 | library. It actually disables the support for backtraces in this compiler | |
598 | for targets defining USE_GCC_UNWINDER, which is OK since we don't use the | |
45f7cb60 | 599 | traceback capability in the compiler anyway. |
0da2c8ac AC |
600 | |
601 | The condition is expressed the way above because we cannot reliably rely on | |
602 | any other macro from the base compiler when compiling stage1. */ | |
603 | ||
1e60643a AC |
604 | #ifdef USING_ARM_UNWINDING |
605 | /* This value is not part of the enumerated reason codes defined in unwind.h | |
606 | for ARM style unwinding, but is used in the included "C" code, so we | |
607 | define it to a reasonable value to avoid a compilation error. */ | |
608 | #define _URC_NORMAL_STOP 0 | |
609 | #endif | |
9f2e635d AC |
610 | |
611 | /* This is an implementation of the __gnat_backtrace routine using the | |
612 | underlying GCC unwinding support associated with the exception handling | |
613 | infrastructure. This will only work for ZCX based applications. */ | |
614 | ||
615 | #include <unwind.h> | |
616 | ||
617 | /* The implementation boils down to a call to _Unwind_Backtrace with a | |
618 | tailored callback and carried-on data structure to keep track of the | |
619 | input parameters we got as well as of the basic processing state. */ | |
620 | ||
621 | /****************** | |
622 | * trace_callback * | |
623 | ******************/ | |
624 | ||
625 | #if !defined (__USING_SJLJ_EXCEPTIONS__) | |
626 | ||
627 | typedef struct { | |
628 | void ** traceback; | |
629 | int max_len; | |
630 | void * exclude_min; | |
631 | void * exclude_max; | |
632 | int n_frames_to_skip; | |
633 | int n_frames_skipped; | |
634 | int n_entries_filled; | |
635 | } uw_data_t; | |
636 | ||
637 | #if defined (__ia64__) && defined (__hpux__) | |
638 | #include <uwx.h> | |
639 | #endif | |
640 | ||
641 | static _Unwind_Reason_Code | |
642 | trace_callback (struct _Unwind_Context * uw_context, uw_data_t * uw_data) | |
643 | { | |
644 | char * pc; | |
645 | ||
646 | #if defined (__ia64__) && defined (__hpux__) && defined (USE_LIBUNWIND_EXCEPTIONS) | |
647 | /* Work around problem with _Unwind_GetIP on ia64 HP-UX. */ | |
648 | uwx_get_reg ((struct uwx_env *) uw_context, UWX_REG_IP, (uint64_t *) &pc); | |
649 | #else | |
650 | pc = (char *) _Unwind_GetIP (uw_context); | |
651 | #endif | |
652 | ||
653 | if (uw_data->n_frames_skipped < uw_data->n_frames_to_skip) | |
654 | { | |
655 | uw_data->n_frames_skipped ++; | |
656 | return _URC_NO_REASON; | |
657 | } | |
658 | ||
659 | if (uw_data->n_entries_filled >= uw_data->max_len) | |
660 | return _URC_NORMAL_STOP; | |
661 | ||
662 | if (pc < (char *)uw_data->exclude_min || pc > (char *)uw_data->exclude_max) | |
663 | uw_data->traceback [uw_data->n_entries_filled ++] = pc + PC_ADJUST; | |
664 | ||
665 | return _URC_NO_REASON; | |
666 | } | |
667 | ||
668 | #endif | |
669 | ||
670 | /******************** | |
671 | * __gnat_backtrace * | |
672 | ********************/ | |
673 | ||
674 | int | |
675 | __gnat_backtrace (void ** traceback __attribute__((unused)), | |
676 | int max_len __attribute__((unused)), | |
677 | void * exclude_min __attribute__((unused)), | |
678 | void * exclude_max __attribute__((unused)), | |
679 | int skip_frames __attribute__((unused))) | |
680 | { | |
681 | #if defined (__USING_SJLJ_EXCEPTIONS__) | |
682 | /* We have no unwind material (tables) at hand with sjlj eh, and no | |
683 | way to retrieve complete and accurate call chain information from | |
684 | the context stack we maintain. */ | |
685 | return 0; | |
686 | #else | |
687 | uw_data_t uw_data; | |
688 | /* State carried over during the whole unwinding process. */ | |
689 | ||
690 | uw_data.traceback = traceback; | |
691 | uw_data.max_len = max_len; | |
692 | uw_data.exclude_min = exclude_min; | |
693 | uw_data.exclude_max = exclude_max; | |
694 | ||
695 | uw_data.n_frames_to_skip = skip_frames; | |
696 | ||
697 | uw_data.n_frames_skipped = 0; | |
698 | uw_data.n_entries_filled = 0; | |
699 | ||
700 | _Unwind_Backtrace ((_Unwind_Trace_Fn)trace_callback, &uw_data); | |
701 | ||
702 | return uw_data.n_entries_filled; | |
703 | #endif | |
704 | } | |
0da2c8ac AC |
705 | |
706 | /*------------------------------------------------------------------* | |
707 | *-- The generic implementation based on frame layout assumptions --* | |
708 | *------------------------------------------------------------------*/ | |
709 | ||
710 | #elif defined (USE_GENERIC_UNWINDER) | |
415dddc8 | 711 | |
0cb1b727 EB |
712 | /* No warning since the cases where FRAME_LEVEL > 0 are known to work. */ |
713 | #pragma GCC diagnostic ignored "-Wframe-address" | |
714 | ||
fbf5a39b AC |
715 | #ifndef CURRENT_STACK_FRAME |
716 | # define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) | |
415dddc8 RK |
717 | #endif |
718 | ||
07fc65c4 GB |
719 | #ifndef VALID_STACK_FRAME |
720 | #define VALID_STACK_FRAME(ptr) 1 | |
721 | #endif | |
722 | ||
e97c30aa | 723 | #ifndef MAX |
fbf5a39b | 724 | #define MAX(x,y) ((x) > (y) ? (x) : (y)) |
e97c30aa | 725 | #endif |
fbf5a39b | 726 | |
7dc56b36 EB |
727 | #ifndef FORCE_CALL |
728 | #define FORCE_CALL 0 | |
fbf5a39b AC |
729 | #endif |
730 | ||
7dc56b36 EB |
731 | /* Make sure the function is not inlined. */ |
732 | static void forced_callee (void) __attribute__ ((noinline)); | |
733 | ||
734 | static void forced_callee (void) | |
735 | { | |
736 | /* Make sure the function is not pure. */ | |
737 | volatile int i __attribute__ ((unused)) = 0; | |
738 | } | |
739 | ||
415dddc8 | 740 | int |
9373164a KC |
741 | __gnat_backtrace (void **array, |
742 | int size, | |
743 | void *exclude_min, | |
744 | void *exclude_max, | |
745 | int skip_frames) | |
415dddc8 RK |
746 | { |
747 | struct layout *current; | |
748 | void *top_frame; | |
d20cfbc2 | 749 | void *top_stack ATTRIBUTE_UNUSED; |
415dddc8 RK |
750 | int cnt = 0; |
751 | ||
7dc56b36 EB |
752 | if (FORCE_CALL) |
753 | forced_callee (); | |
415dddc8 | 754 | |
fbf5a39b | 755 | /* Force a call to builtin_frame_address with a positive argument |
e7ad2039 | 756 | if required. This is necessary e.g. on SPARC to have the register |
fbf5a39b AC |
757 | windows flushed before we attempt to access them on the stack. */ |
758 | #if defined (FETCH_UP_FRAME_ADDRESS) && (FRAME_LEVEL == 0) | |
759 | __builtin_frame_address (1); | |
415dddc8 RK |
760 | #endif |
761 | ||
762 | top_frame = __builtin_frame_address (FRAME_LEVEL); | |
763 | top_stack = CURRENT_STACK_FRAME; | |
e7ad2039 | 764 | current = (struct layout *) ((size_t) top_frame + FRAME_OFFSET (0)); |
415dddc8 | 765 | |
fbf5a39b AC |
766 | /* Skip the number of calls we have been requested to skip, accounting for |
767 | the BASE_SKIP parameter. | |
415dddc8 | 768 | |
fbf5a39b AC |
769 | FRAME_LEVEL is meaningless for the count adjustment. It impacts where we |
770 | start retrieving data from, but how many frames "up" we start at is in | |
771 | BASE_SKIP by definition. */ | |
415dddc8 | 772 | |
fbf5a39b AC |
773 | skip_frames = MAX (0, skip_frames - BASE_SKIP); |
774 | ||
775 | while (cnt < skip_frames) | |
415dddc8 | 776 | { |
e7ad2039 | 777 | current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1)); |
415dddc8 RK |
778 | cnt++; |
779 | } | |
780 | ||
781 | cnt = 0; | |
782 | while (cnt < size) | |
783 | { | |
fbf5a39b | 784 | if (STOP_FRAME (current, top_stack) || |
5b6d595b | 785 | !VALID_STACK_FRAME(((char *) current->return_address) + PC_ADJUST)) |
415dddc8 RK |
786 | break; |
787 | ||
788 | if (current->return_address < exclude_min | |
789 | || current->return_address > exclude_max) | |
5b6d595b | 790 | array[cnt++] = ((char *) current->return_address) + PC_ADJUST; |
415dddc8 | 791 | |
e7ad2039 | 792 | current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1)); |
415dddc8 RK |
793 | } |
794 | ||
415dddc8 RK |
795 | return cnt; |
796 | } | |
797 | ||
798 | #else | |
0da2c8ac | 799 | |
02be26e4 EB |
800 | /* No target specific implementation and neither USE_GCC_UNWINDER nor |
801 | USE_GENERIC_UNWINDER defined. */ | |
415dddc8 | 802 | |
fbf5a39b AC |
803 | /*------------------------------* |
804 | *-- The dummy implementation --* | |
805 | *------------------------------*/ | |
415dddc8 | 806 | |
fbf5a39b | 807 | int |
d8bf0ab8 LG |
808 | __gnat_backtrace (void **array ATTRIBUTE_UNUSED, |
809 | int size ATTRIBUTE_UNUSED, | |
810 | void *exclude_min ATTRIBUTE_UNUSED, | |
811 | void *exclude_max ATTRIBUTE_UNUSED, | |
812 | int skip_frames ATTRIBUTE_UNUSED) | |
415dddc8 | 813 | { |
415dddc8 RK |
814 | return 0; |
815 | } | |
816 | ||
415dddc8 RK |
817 | #endif |
818 | ||
415dddc8 | 819 | #endif |
9e9bd455 LG |
820 | |
821 | #ifdef __cplusplus | |
822 | } | |
823 | #endif |