1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <stdbool.h>
9*54fd6939SJiyong Park #include <stdint.h>
10*54fd6939SJiyong Park
11*54fd6939SJiyong Park #include <arch_helpers.h>
12*54fd6939SJiyong Park #include <common/debug.h>
13*54fd6939SJiyong Park #include <drivers/console.h>
14*54fd6939SJiyong Park
15*54fd6939SJiyong Park /* Maximum number of entries in the backtrace to display */
16*54fd6939SJiyong Park #define UNWIND_LIMIT 20U
17*54fd6939SJiyong Park
18*54fd6939SJiyong Park /*
19*54fd6939SJiyong Park * If -fno-omit-frame-pointer is used:
20*54fd6939SJiyong Park *
21*54fd6939SJiyong Park * - AArch64: The AAPCS defines the format of the frame records and mandates the
22*54fd6939SJiyong Park * usage of r29 as frame pointer.
23*54fd6939SJiyong Park *
24*54fd6939SJiyong Park * - AArch32: The format of the frame records is not defined in the AAPCS.
25*54fd6939SJiyong Park * However, at least GCC and Clang use the same format. When they are forced
26*54fd6939SJiyong Park * to only generate A32 code (with -marm), they use r11 as frame pointer and a
27*54fd6939SJiyong Park * similar format as in AArch64. If interworking with T32 is enabled, the
28*54fd6939SJiyong Park * frame pointer is r7 and the format is different. This is not supported by
29*54fd6939SJiyong Park * this implementation of backtrace, so it is needed to use -marm.
30*54fd6939SJiyong Park */
31*54fd6939SJiyong Park
32*54fd6939SJiyong Park /* Frame records form a linked list in the stack */
33*54fd6939SJiyong Park struct frame_record {
34*54fd6939SJiyong Park /* Previous frame record in the list */
35*54fd6939SJiyong Park struct frame_record *parent;
36*54fd6939SJiyong Park /* Return address of the function at this level */
37*54fd6939SJiyong Park uintptr_t return_addr;
38*54fd6939SJiyong Park };
39*54fd6939SJiyong Park
get_el_str(unsigned int el)40*54fd6939SJiyong Park const char *get_el_str(unsigned int el)
41*54fd6939SJiyong Park {
42*54fd6939SJiyong Park if (el == 3U) {
43*54fd6939SJiyong Park return "EL3";
44*54fd6939SJiyong Park } else if (el == 2U) {
45*54fd6939SJiyong Park return "EL2";
46*54fd6939SJiyong Park } else {
47*54fd6939SJiyong Park return "S-EL1";
48*54fd6939SJiyong Park }
49*54fd6939SJiyong Park }
50*54fd6939SJiyong Park
51*54fd6939SJiyong Park /*
52*54fd6939SJiyong Park * Returns true if the address points to a virtual address that can be read at
53*54fd6939SJiyong Park * the current EL, false otherwise.
54*54fd6939SJiyong Park */
55*54fd6939SJiyong Park #ifdef __aarch64__
is_address_readable(uintptr_t addr)56*54fd6939SJiyong Park static bool is_address_readable(uintptr_t addr)
57*54fd6939SJiyong Park {
58*54fd6939SJiyong Park unsigned int el = get_current_el();
59*54fd6939SJiyong Park
60*54fd6939SJiyong Park #if ENABLE_PAUTH
61*54fd6939SJiyong Park /*
62*54fd6939SJiyong Park * When pointer authentication is enabled, the LR value saved on the
63*54fd6939SJiyong Park * stack contains a PAC. It must be stripped to retrieve the return
64*54fd6939SJiyong Park * address.
65*54fd6939SJiyong Park */
66*54fd6939SJiyong Park xpaci(addr);
67*54fd6939SJiyong Park #endif
68*54fd6939SJiyong Park if (el == 3U) {
69*54fd6939SJiyong Park ats1e3r(addr);
70*54fd6939SJiyong Park } else if (el == 2U) {
71*54fd6939SJiyong Park ats1e2r(addr);
72*54fd6939SJiyong Park } else {
73*54fd6939SJiyong Park AT(ats1e1r, addr);
74*54fd6939SJiyong Park }
75*54fd6939SJiyong Park
76*54fd6939SJiyong Park isb();
77*54fd6939SJiyong Park
78*54fd6939SJiyong Park /* If PAR.F == 1 the address translation was aborted. */
79*54fd6939SJiyong Park if ((read_par_el1() & PAR_F_MASK) != 0U)
80*54fd6939SJiyong Park return false;
81*54fd6939SJiyong Park
82*54fd6939SJiyong Park return true;
83*54fd6939SJiyong Park }
84*54fd6939SJiyong Park #else /* !__aarch64__ */
is_address_readable(uintptr_t addr)85*54fd6939SJiyong Park static bool is_address_readable(uintptr_t addr)
86*54fd6939SJiyong Park {
87*54fd6939SJiyong Park unsigned int el = get_current_el();
88*54fd6939SJiyong Park
89*54fd6939SJiyong Park if (el == 3U) {
90*54fd6939SJiyong Park write_ats1cpr(addr);
91*54fd6939SJiyong Park } else if (el == 2U) {
92*54fd6939SJiyong Park write_ats1hr(addr);
93*54fd6939SJiyong Park } else {
94*54fd6939SJiyong Park write_ats1cpr(addr);
95*54fd6939SJiyong Park }
96*54fd6939SJiyong Park
97*54fd6939SJiyong Park isb();
98*54fd6939SJiyong Park
99*54fd6939SJiyong Park /* If PAR.F == 1 the address translation was aborted. */
100*54fd6939SJiyong Park if ((read64_par() & PAR_F_MASK) != 0U)
101*54fd6939SJiyong Park return false;
102*54fd6939SJiyong Park
103*54fd6939SJiyong Park return true;
104*54fd6939SJiyong Park }
105*54fd6939SJiyong Park #endif /* __aarch64__ */
106*54fd6939SJiyong Park
107*54fd6939SJiyong Park /*
108*54fd6939SJiyong Park * Returns true if all the bytes in a given object are in mapped memory and an
109*54fd6939SJiyong Park * LDR using this pointer would succeed, false otherwise.
110*54fd6939SJiyong Park */
is_valid_object(uintptr_t addr,size_t size)111*54fd6939SJiyong Park static bool is_valid_object(uintptr_t addr, size_t size)
112*54fd6939SJiyong Park {
113*54fd6939SJiyong Park assert(size > 0U);
114*54fd6939SJiyong Park
115*54fd6939SJiyong Park if (addr == 0U)
116*54fd6939SJiyong Park return false;
117*54fd6939SJiyong Park
118*54fd6939SJiyong Park /* Detect overflows */
119*54fd6939SJiyong Park if ((addr + size) < addr)
120*54fd6939SJiyong Park return false;
121*54fd6939SJiyong Park
122*54fd6939SJiyong Park /* A pointer not aligned properly could trigger an alignment fault. */
123*54fd6939SJiyong Park if ((addr & (sizeof(uintptr_t) - 1U)) != 0U)
124*54fd6939SJiyong Park return false;
125*54fd6939SJiyong Park
126*54fd6939SJiyong Park /* Check that all the object is readable */
127*54fd6939SJiyong Park for (size_t i = 0; i < size; i++) {
128*54fd6939SJiyong Park if (!is_address_readable(addr + i))
129*54fd6939SJiyong Park return false;
130*54fd6939SJiyong Park }
131*54fd6939SJiyong Park
132*54fd6939SJiyong Park return true;
133*54fd6939SJiyong Park }
134*54fd6939SJiyong Park
135*54fd6939SJiyong Park /*
136*54fd6939SJiyong Park * Returns true if the specified address is correctly aligned and points to a
137*54fd6939SJiyong Park * valid memory region.
138*54fd6939SJiyong Park */
is_valid_jump_address(uintptr_t addr)139*54fd6939SJiyong Park static bool is_valid_jump_address(uintptr_t addr)
140*54fd6939SJiyong Park {
141*54fd6939SJiyong Park if (addr == 0U)
142*54fd6939SJiyong Park return false;
143*54fd6939SJiyong Park
144*54fd6939SJiyong Park /* Check alignment. Both A64 and A32 use 32-bit opcodes */
145*54fd6939SJiyong Park if ((addr & (sizeof(uint32_t) - 1U)) != 0U)
146*54fd6939SJiyong Park return false;
147*54fd6939SJiyong Park
148*54fd6939SJiyong Park if (!is_address_readable(addr))
149*54fd6939SJiyong Park return false;
150*54fd6939SJiyong Park
151*54fd6939SJiyong Park return true;
152*54fd6939SJiyong Park }
153*54fd6939SJiyong Park
154*54fd6939SJiyong Park /*
155*54fd6939SJiyong Park * Returns true if the pointer points at a valid frame record, false otherwise.
156*54fd6939SJiyong Park */
is_valid_frame_record(struct frame_record * fr)157*54fd6939SJiyong Park static bool is_valid_frame_record(struct frame_record *fr)
158*54fd6939SJiyong Park {
159*54fd6939SJiyong Park return is_valid_object((uintptr_t)fr, sizeof(struct frame_record));
160*54fd6939SJiyong Park }
161*54fd6939SJiyong Park
162*54fd6939SJiyong Park /*
163*54fd6939SJiyong Park * Adjust the frame-pointer-register value by 4 bytes on AArch32 to have the
164*54fd6939SJiyong Park * same layout as AArch64.
165*54fd6939SJiyong Park */
adjust_frame_record(struct frame_record * fr)166*54fd6939SJiyong Park static struct frame_record *adjust_frame_record(struct frame_record *fr)
167*54fd6939SJiyong Park {
168*54fd6939SJiyong Park #ifdef __aarch64__
169*54fd6939SJiyong Park return fr;
170*54fd6939SJiyong Park #else
171*54fd6939SJiyong Park return (struct frame_record *)((uintptr_t)fr - 4U);
172*54fd6939SJiyong Park #endif
173*54fd6939SJiyong Park }
174*54fd6939SJiyong Park
unwind_stack(struct frame_record * fr,uintptr_t current_pc,uintptr_t link_register)175*54fd6939SJiyong Park static void unwind_stack(struct frame_record *fr, uintptr_t current_pc,
176*54fd6939SJiyong Park uintptr_t link_register)
177*54fd6939SJiyong Park {
178*54fd6939SJiyong Park uintptr_t call_site;
179*54fd6939SJiyong Park static const char *backtrace_str = "%u: %s: 0x%lx\n";
180*54fd6939SJiyong Park const char *el_str = get_el_str(get_current_el());
181*54fd6939SJiyong Park
182*54fd6939SJiyong Park if (!is_valid_frame_record(fr)) {
183*54fd6939SJiyong Park printf("ERROR: Corrupted frame pointer (frame record address = %p)\n",
184*54fd6939SJiyong Park fr);
185*54fd6939SJiyong Park return;
186*54fd6939SJiyong Park }
187*54fd6939SJiyong Park
188*54fd6939SJiyong Park if (fr->return_addr != link_register) {
189*54fd6939SJiyong Park printf("ERROR: Corrupted stack (frame record address = %p)\n",
190*54fd6939SJiyong Park fr);
191*54fd6939SJiyong Park return;
192*54fd6939SJiyong Park }
193*54fd6939SJiyong Park
194*54fd6939SJiyong Park /* The level 0 of the backtrace is the current backtrace function */
195*54fd6939SJiyong Park printf(backtrace_str, 0U, el_str, current_pc);
196*54fd6939SJiyong Park
197*54fd6939SJiyong Park /*
198*54fd6939SJiyong Park * The last frame record pointer in the linked list at the beginning of
199*54fd6939SJiyong Park * the stack should be NULL unless stack is corrupted.
200*54fd6939SJiyong Park */
201*54fd6939SJiyong Park for (unsigned int i = 1U; i < UNWIND_LIMIT; i++) {
202*54fd6939SJiyong Park /* If an invalid frame record is found, exit. */
203*54fd6939SJiyong Park if (!is_valid_frame_record(fr))
204*54fd6939SJiyong Park return;
205*54fd6939SJiyong Park /*
206*54fd6939SJiyong Park * A32 and A64 are fixed length so the address from where the
207*54fd6939SJiyong Park * call was made is the instruction before the return address,
208*54fd6939SJiyong Park * which is always 4 bytes before it.
209*54fd6939SJiyong Park */
210*54fd6939SJiyong Park call_site = fr->return_addr - 4U;
211*54fd6939SJiyong Park
212*54fd6939SJiyong Park #if ENABLE_PAUTH
213*54fd6939SJiyong Park /*
214*54fd6939SJiyong Park * When pointer authentication is enabled, the LR value saved on
215*54fd6939SJiyong Park * the stack contains a PAC. It must be stripped to retrieve the
216*54fd6939SJiyong Park * return address.
217*54fd6939SJiyong Park */
218*54fd6939SJiyong Park xpaci(call_site);
219*54fd6939SJiyong Park #endif
220*54fd6939SJiyong Park /*
221*54fd6939SJiyong Park * If the address is invalid it means that the frame record is
222*54fd6939SJiyong Park * probably corrupted.
223*54fd6939SJiyong Park */
224*54fd6939SJiyong Park if (!is_valid_jump_address(call_site))
225*54fd6939SJiyong Park return;
226*54fd6939SJiyong Park
227*54fd6939SJiyong Park printf(backtrace_str, i, el_str, call_site);
228*54fd6939SJiyong Park
229*54fd6939SJiyong Park fr = adjust_frame_record(fr->parent);
230*54fd6939SJiyong Park }
231*54fd6939SJiyong Park
232*54fd6939SJiyong Park printf("ERROR: Max backtrace depth reached\n");
233*54fd6939SJiyong Park }
234*54fd6939SJiyong Park
235*54fd6939SJiyong Park /*
236*54fd6939SJiyong Park * Display a backtrace. The cookie string parameter is displayed along the
237*54fd6939SJiyong Park * trace to help filter the log messages.
238*54fd6939SJiyong Park *
239*54fd6939SJiyong Park * Many things can prevent displaying the expected backtrace. For example,
240*54fd6939SJiyong Park * compiler optimizations can use a branch instead of branch with link when it
241*54fd6939SJiyong Park * detects a tail call. The backtrace level for this caller will not be
242*54fd6939SJiyong Park * displayed, as it does not appear in the call stack anymore. Also, assembly
243*54fd6939SJiyong Park * functions will not be displayed unless they setup AAPCS compliant frame
244*54fd6939SJiyong Park * records on AArch64 and compliant with GCC-specific frame record format on
245*54fd6939SJiyong Park * AArch32.
246*54fd6939SJiyong Park *
247*54fd6939SJiyong Park * Usage of the trace: addr2line can be used to map the addresses to function
248*54fd6939SJiyong Park * and source code location when given the ELF file compiled with debug
249*54fd6939SJiyong Park * information. The "-i" flag is highly recommended to improve display of
250*54fd6939SJiyong Park * inlined function. The *.dump files generated when building each image can
251*54fd6939SJiyong Park * also be used.
252*54fd6939SJiyong Park *
253*54fd6939SJiyong Park * WARNING: In case of corrupted stack, this function could display security
254*54fd6939SJiyong Park * sensitive information past the beginning of the stack so it must not be used
255*54fd6939SJiyong Park * in production build. This function is only compiled in when ENABLE_BACKTRACE
256*54fd6939SJiyong Park * is set to 1.
257*54fd6939SJiyong Park */
backtrace(const char * cookie)258*54fd6939SJiyong Park void backtrace(const char *cookie)
259*54fd6939SJiyong Park {
260*54fd6939SJiyong Park uintptr_t return_address = (uintptr_t)__builtin_return_address(0U);
261*54fd6939SJiyong Park struct frame_record *fr = __builtin_frame_address(0U);
262*54fd6939SJiyong Park
263*54fd6939SJiyong Park /* Printing the backtrace may crash the system, flush before starting */
264*54fd6939SJiyong Park console_flush();
265*54fd6939SJiyong Park
266*54fd6939SJiyong Park fr = adjust_frame_record(fr);
267*54fd6939SJiyong Park
268*54fd6939SJiyong Park printf("BACKTRACE: START: %s\n", cookie);
269*54fd6939SJiyong Park
270*54fd6939SJiyong Park unwind_stack(fr, (uintptr_t)&backtrace, return_address);
271*54fd6939SJiyong Park
272*54fd6939SJiyong Park printf("BACKTRACE: END: %s\n", cookie);
273*54fd6939SJiyong Park }
274