unwind_prologue.c (4f2c0a4acffbec01079c28f839422e64ddeff004) unwind_prologue.c (4733f09d880745953b88c3358b49ad495aecd8e9)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
4 */
5#include <linux/kallsyms.h>
6
7#include <asm/inst.h>
8#include <asm/ptrace.h>
9#include <asm/unwind.h>
10
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
4 */
5#include <linux/kallsyms.h>
6
7#include <asm/inst.h>
8#include <asm/ptrace.h>
9#include <asm/unwind.h>
10
11static inline void unwind_state_fixup(struct unwind_state *state)
12{
13#ifdef CONFIG_DYNAMIC_FTRACE
14 static unsigned long ftrace = (unsigned long)ftrace_call + 4;
15
16 if (state->pc == ftrace)
17 state->is_ftrace = true;
18#endif
19}
20
11unsigned long unwind_get_return_address(struct unwind_state *state)
12{
13
14 if (unwind_done(state))
15 return 0;
16 else if (state->type)
17 return state->pc;
18 else if (state->first)

--- 17 unchanged lines hidden (view full) ---

36 return true;
37 }
38
39 return false;
40}
41
42static bool unwind_by_prologue(struct unwind_state *state)
43{
21unsigned long unwind_get_return_address(struct unwind_state *state)
22{
23
24 if (unwind_done(state))
25 return 0;
26 else if (state->type)
27 return state->pc;
28 else if (state->first)

--- 17 unchanged lines hidden (view full) ---

46 return true;
47 }
48
49 return false;
50}
51
52static bool unwind_by_prologue(struct unwind_state *state)
53{
44 struct stack_info *info = &state->stack_info;
45 union loongarch_instruction *ip, *ip_end;
46 long frame_ra = -1;
47 unsigned long frame_size = 0;
48 unsigned long size, offset, pc = state->pc;
54 long frame_ra = -1;
55 unsigned long frame_size = 0;
56 unsigned long size, offset, pc = state->pc;
57 struct pt_regs *regs;
58 struct stack_info *info = &state->stack_info;
59 union loongarch_instruction *ip, *ip_end;
49
50 if (state->sp >= info->end || state->sp < info->begin)
51 return false;
52
60
61 if (state->sp >= info->end || state->sp < info->begin)
62 return false;
63
64 if (state->is_ftrace) {
65 /*
66 * As we meet ftrace_regs_entry, reset first flag like first doing
67 * tracing. Prologue analysis will stop soon because PC is at entry.
68 */
69 regs = (struct pt_regs *)state->sp;
70 state->first = true;
71 state->is_ftrace = false;
72 state->pc = regs->csr_era;
73 state->ra = regs->regs[1];
74 state->sp = regs->regs[3];
75 return true;
76 }
77
53 if (!kallsyms_lookup_size_offset(pc, &size, &offset))
54 return false;
55
56 ip = (union loongarch_instruction *)(pc - offset);
57 ip_end = (union loongarch_instruction *)pc;
58
59 while (ip < ip_end) {
60 if (is_stack_alloc_ins(ip)) {

--- 29 unchanged lines hidden (view full) ---

90 return false;
91 }
92
93 if (state->first)
94 state->first = false;
95
96 state->pc = *(unsigned long *)(state->sp + frame_ra);
97 state->sp = state->sp + frame_size;
78 if (!kallsyms_lookup_size_offset(pc, &size, &offset))
79 return false;
80
81 ip = (union loongarch_instruction *)(pc - offset);
82 ip_end = (union loongarch_instruction *)pc;
83
84 while (ip < ip_end) {
85 if (is_stack_alloc_ins(ip)) {

--- 29 unchanged lines hidden (view full) ---

115 return false;
116 }
117
118 if (state->first)
119 state->first = false;
120
121 state->pc = *(unsigned long *)(state->sp + frame_ra);
122 state->sp = state->sp + frame_size;
98 return !!__kernel_text_address(state->pc);
123 goto out;
99
100first:
101 state->first = false;
102 if (state->pc == state->ra)
103 return false;
104
105 state->pc = state->ra;
106
124
125first:
126 state->first = false;
127 if (state->pc == state->ra)
128 return false;
129
130 state->pc = state->ra;
131
107 return !!__kernel_text_address(state->ra);
132out:
133 unwind_state_fixup(state);
134 return !!__kernel_text_address(state->pc);
108}
109
110void unwind_start(struct unwind_state *state, struct task_struct *task,
111 struct pt_regs *regs)
112{
113 memset(state, 0, sizeof(*state));
114
115 if (regs && __kernel_text_address(regs->csr_era)) {

--- 62 unchanged lines hidden ---
135}
136
137void unwind_start(struct unwind_state *state, struct task_struct *task,
138 struct pt_regs *regs)
139{
140 memset(state, 0, sizeof(*state));
141
142 if (regs && __kernel_text_address(regs->csr_era)) {

--- 62 unchanged lines hidden ---