hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *  linux/arch/arm/lib/backtrace.S
 *
 *  Copyright (C) 1995, 1996 Russell King
 *
 * 27/03/03 Ian Molton Clean up CONFIG_CPU
 */
#include <linux/kern_levels.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
       .text
 
@ fp is 0 or stack frame
 
#define frame    r4
#define sv_fp    r5
#define sv_pc    r6
#define mask    r7
#define offset    r8
#define loglvl    r9
 
ENTRY(c_backtrace)
 
#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
       ret    lr
ENDPROC(c_backtrace)
#else
       stmfd    sp!, {r4 - r9, lr}    @ Save an extra register so we have a location...
       movs    frame, r0        @ if frame pointer is zero
       beq    no_frame        @ we have no stack frames
       mov    loglvl, r2
 
       tst    r1, #0x10        @ 26 or 32-bit mode?
 ARM(        moveq    mask, #0xfc000003    )
 THUMB(        moveq    mask, #0xfc000000    )
 THUMB(        orreq    mask, #0x03        )
       movne    mask, #0        @ mask for 32-bit
 
1:        stmfd    sp!, {pc}        @ calculate offset of PC stored
       ldr    r0, [sp], #4        @ by stmfd for this CPU
       adr    r1, 1b
       sub    offset, r0, r1
 
/*
 * Stack frame layout:
 *             optionally saved caller registers (r4 - r10)
 *             saved fp
 *             saved sp
 *             saved lr
 *    frame => saved pc
 *             optionally saved arguments (r0 - r3)
 * saved sp => <next word>
 *
 * Functions start with the following code sequence:
 *                  mov   ip, sp
 *                  stmfd sp!, {r0 - r3} (optional)
 * corrected pc =>  stmfd sp!, {..., fp, ip, lr, pc}
 */
for_each_frame:    tst    frame, mask        @ Check for address exceptions
       bne    no_frame
 
1001:        ldr    sv_pc, [frame, #0]    @ get saved pc
1002:        ldr    sv_fp, [frame, #-12]    @ get saved fp
 
       sub    sv_pc, sv_pc, offset    @ Correct PC for prefetching
       bic    sv_pc, sv_pc, mask    @ mask PC/LR for the mode
 
1003:        ldr    r2, [sv_pc, #-4]    @ if stmfd sp!, {args} exists,
       ldr    r3, .Ldsi+4        @ adjust saved 'pc' back one
       teq    r3, r2, lsr #11        @ instruction
       subne    r0, sv_pc, #4        @ allow for mov
       subeq    r0, sv_pc, #8        @ allow for mov + stmia
 
       ldr    r1, [frame, #-4]    @ get saved lr
       mov    r2, frame
       bic    r1, r1, mask        @ mask PC/LR for the mode
       mov    r3, loglvl
       bl    dump_backtrace_entry
 
       ldr    r1, [sv_pc, #-4]    @ if stmfd sp!, {args} exists,
       ldr    r3, .Ldsi+4
       teq    r3, r1, lsr #11
       ldreq    r0, [frame, #-8]    @ get sp
       subeq    r0, r0, #4        @ point at the last arg
       mov    r2, loglvl
       bleq    dump_backtrace_stm    @ dump saved registers
 
1004:        ldr    r1, [sv_pc, #0]        @ if stmfd sp!, {..., fp, ip, lr, pc}
       ldr    r3, .Ldsi        @ instruction exists,
       teq    r3, r1, lsr #11
       subeq    r0, frame, #16
       mov    r2, loglvl
       bleq    dump_backtrace_stm    @ dump saved registers
 
       teq    sv_fp, #0        @ zero saved fp means
       beq    no_frame        @ no further frames
 
       cmp    sv_fp, frame        @ next frame must be
       mov    frame, sv_fp        @ above the current frame
       bhi    for_each_frame
 
1006:        adr    r0, .Lbad
       mov    r1, loglvl
       mov    r2, frame
       bl    printk
no_frame:    ldmfd    sp!, {r4 - r9, pc}
ENDPROC(c_backtrace)
       
       .pushsection __ex_table,"a"
       .align    3
       .long    1001b, 1006b
       .long    1002b, 1006b
       .long    1003b, 1006b
       .long    1004b, 1006b
       .popsection
 
.Lbad:        .asciz    "%sBacktrace aborted due to bad frame pointer <%p>\n"
       .align
.Ldsi:        .word    0xe92dd800 >> 11    @ stmfd sp!, {... fp, ip, lr, pc}
       .word    0xe92d0000 >> 11    @ stmfd sp!, {}
 
#endif