]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/powerpc/powerpc64/backtrace.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / backtrace.c
CommitLineData
cfc91acd 1/* Return backtrace of current program state.
04277e02 2 Copyright (C) 1998-2019 Free Software Foundation, Inc.
cfc91acd
RM
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
59ba27a6
PE
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, see <http://www.gnu.org/licenses/>. */
cfc91acd 18
cfc91acd 19#include <stddef.h>
d400dcac
AZ
20#include <string.h>
21#include <signal.h>
31073a53
AZ
22#include <stdint.h>
23
24#include <execinfo.h>
7bf8fb10 25#include <libc-vdso.h>
cfc91acd
RM
26
27/* This is the stack layout we see with every stack frame.
28 Note that every routine is required by the ABI to lay out the stack
29 like this.
30
31 +----------------+ +-----------------+
32 %r1 -> | %r1 last frame--------> | %r1 last frame--->... --> NULL
33 | | | |
34 | cr save | | cr save |
35 | | | |
36 | (unused) | | return address |
37 +----------------+ +-----------------+
38*/
39struct layout
40{
70d9946a 41 struct layout *next;
31073a53 42 long int condition_register;
70d9946a 43 void *return_address;
cfc91acd
RM
44};
45
d400dcac
AZ
46/* Since the signal handler is just like any other function it needs to
47 save/restore its LR and it will save it into callers stack frame.
48 Since a signal handler doesn't have a caller, the kernel creates a
49 dummy frame to make it look like it has a caller. */
50struct signal_frame_64 {
51#define SIGNAL_FRAMESIZE 128
31073a53 52 char dummy[SIGNAL_FRAMESIZE];
25128773 53 ucontext_t uc;
d400dcac
AZ
54 /* We don't care about the rest, since the IP value is at 'uc' field. */
55};
56
57static inline int
31073a53 58is_sigtramp_address (void *nip)
d400dcac
AZ
59{
60#ifdef SHARED
31073a53 61 if (nip == VDSO_SYMBOL (sigtramp_rt64))
d400dcac
AZ
62 return 1;
63#endif
64 return 0;
65}
66
cfc91acd
RM
67int
68__backtrace (void **array, int size)
69{
70 struct layout *current;
71 int count;
72
73 /* Force gcc to spill LR. */
74 asm volatile ("" : "=l"(current));
75
76 /* Get the address on top-of-stack. */
77 asm volatile ("ld %0,0(1)" : "=r"(current));
cfc91acd
RM
78
79 for ( count = 0;
80 current != NULL && count < size;
e782a927 81 current = current->next, count++)
d400dcac
AZ
82 {
83 array[count] = current->return_address;
84
85 /* Check if the symbol is the signal trampoline and get the interrupted
86 * symbol address from the trampoline saved area. */
31073a53 87 if (is_sigtramp_address (current->return_address))
d400dcac
AZ
88 {
89 struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
31073a53
AZ
90 array[++count] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
91 current = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_R1];
d400dcac
AZ
92 }
93 }
cfc91acd
RM
94
95 /* It's possible the second-last stack frame can't return
96 (that is, it's __libc_start_main), in which case
97 the CRT startup code will have set its LR to 'NULL'. */
98 if (count > 0 && array[count-1] == NULL)
99 count--;
100
101 return count;
102}
103weak_alias (__backtrace, backtrace)
0e66ade5 104libc_hidden_def (__backtrace)