1 /* Copyright (C) 2005-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
26 _identify_sighandler (unsigned long fp
, unsigned long pc
,
27 unsigned long *pprev_fp
, unsigned long *pprev_pc
,
28 unsigned long *retaddr
);
31 get_frame_size (unsigned long instr
)
33 return abs ((short signed) (instr
& 0xFFFF));
36 static unsigned long *
37 find_frame_creation (unsigned long *pc
)
41 /* NOTE: Distance to search is arbitrary.
42 250 works well for most things,
43 750 picks up things like tcp_recvmsg,
44 1000 needed for fat_fill_super. */
45 for (i
= 0; i
< 1000; i
++, pc
--)
48 unsigned long frame_size
;
52 /* Is the instruction of the form
53 addik r1, r1, foo ? */
54 if ((instr
& 0xFFFF0000) != 0x30210000)
57 frame_size
= get_frame_size (instr
);
59 if ((frame_size
< 8) || (frame_size
& 3))
68 lookup_prev_stack_frame (unsigned long fp
, unsigned long pc
,
69 unsigned long *pprev_fp
, unsigned long *pprev_pc
,
70 unsigned long *retaddr
)
72 unsigned long *prologue
= NULL
;
74 int is_signalhandler
= _identify_sighandler (fp
, pc
, pprev_fp
,
77 if (!is_signalhandler
)
79 prologue
= find_frame_creation ((unsigned long *) pc
);
83 long frame_size
= get_frame_size (*prologue
);
84 *pprev_fp
= fp
+ frame_size
;
88 *pprev_pc
= *(unsigned long *) fp
;
91 if (!*pprev_pc
|| (*pprev_pc
& 3))
101 return (!*pprev_pc
|| (*pprev_pc
& 3)) ? -1 : 0;
105 __backtrace (void **array
, int size
)
107 unsigned long pc
, fp
;
108 unsigned long ppc
, pfp
;
109 /* Return address(r15) is required in the signal handler case, since the
110 return address of the function which causes the signal may not be
111 recorded in the stack. */
112 unsigned long retaddr
;
120 __asm__
__volatile__ ("mfs %0, rpc"
123 __asm__
__volatile__ ("add %0, r1, r0"
126 array
[0] = (void *) pc
;
128 for (count
= 1; count
< size
; count
++)
130 rc
= lookup_prev_stack_frame (fp
, pc
, &pfp
, &ppc
, &retaddr
);
134 array
[count
] = (void *) pc
;
141 weak_alias (__backtrace
, backtrace
)
142 libc_hidden_def (__backtrace
)