aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/backtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel/backtrace.c')
-rw-r--r--arch/tile/kernel/backtrace.c81
1 files changed, 34 insertions, 47 deletions
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c
index 1b0a410ef5e7..77265f3b58d6 100644
--- a/arch/tile/kernel/backtrace.c
+++ b/arch/tile/kernel/backtrace.c
@@ -30,18 +30,18 @@
30 30
31 31
32/** A decoded bundle used for backtracer analysis. */ 32/** A decoded bundle used for backtracer analysis. */
33typedef struct { 33struct BacktraceBundle {
34 tile_bundle_bits bits; 34 tile_bundle_bits bits;
35 int num_insns; 35 int num_insns;
36 struct tile_decoded_instruction 36 struct tile_decoded_instruction
37 insns[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]; 37 insns[TILE_MAX_INSTRUCTIONS_PER_BUNDLE];
38} BacktraceBundle; 38};
39 39
40 40
41/* This implementation only makes sense for native tools. */ 41/* This implementation only makes sense for native tools. */
42/** Default function to read memory. */ 42/** Default function to read memory. */
43static bool 43static bool bt_read_memory(void *result, VirtualAddress addr,
44bt_read_memory(void *result, VirtualAddress addr, size_t size, void *extra) 44 size_t size, void *extra)
45{ 45{
46 /* FIXME: this should do some horrible signal stuff to catch 46 /* FIXME: this should do some horrible signal stuff to catch
47 * SEGV cleanly and fail. 47 * SEGV cleanly and fail.
@@ -58,11 +58,11 @@ bt_read_memory(void *result, VirtualAddress addr, size_t size, void *extra)
58 * has the specified mnemonic, and whose first 'num_operands_to_match' 58 * has the specified mnemonic, and whose first 'num_operands_to_match'
59 * operands exactly match those in 'operand_values'. 59 * operands exactly match those in 'operand_values'.
60 */ 60 */
61static const struct tile_decoded_instruction* 61static const struct tile_decoded_instruction *find_matching_insn(
62find_matching_insn(const BacktraceBundle *bundle, 62 const struct BacktraceBundle *bundle,
63 tile_mnemonic mnemonic, 63 tile_mnemonic mnemonic,
64 const int *operand_values, 64 const int *operand_values,
65 int num_operands_to_match) 65 int num_operands_to_match)
66{ 66{
67 int i, j; 67 int i, j;
68 bool match; 68 bool match;
@@ -90,8 +90,7 @@ find_matching_insn(const BacktraceBundle *bundle,
90} 90}
91 91
92/** Does this bundle contain an 'iret' instruction? */ 92/** Does this bundle contain an 'iret' instruction? */
93static inline bool 93static inline bool bt_has_iret(const struct BacktraceBundle *bundle)
94bt_has_iret(const BacktraceBundle *bundle)
95{ 94{
96 return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL; 95 return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL;
97} 96}
@@ -99,8 +98,7 @@ bt_has_iret(const BacktraceBundle *bundle)
99/** Does this bundle contain an 'addi sp, sp, OFFSET' or 98/** Does this bundle contain an 'addi sp, sp, OFFSET' or
100 * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET? 99 * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET?
101 */ 100 */
102static bool 101static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust)
103bt_has_addi_sp(const BacktraceBundle *bundle, int *adjust)
104{ 102{
105 static const int vals[2] = { TREG_SP, TREG_SP }; 103 static const int vals[2] = { TREG_SP, TREG_SP };
106 104
@@ -120,8 +118,7 @@ bt_has_addi_sp(const BacktraceBundle *bundle, int *adjust)
120 * as an unsigned value by this code since that's what the caller wants. 118 * as an unsigned value by this code since that's what the caller wants.
121 * Returns the number of info ops found. 119 * Returns the number of info ops found.
122 */ 120 */
123static int 121static int bt_get_info_ops(const struct BacktraceBundle *bundle,
124bt_get_info_ops(const BacktraceBundle *bundle,
125 int operands[MAX_INFO_OPS_PER_BUNDLE]) 122 int operands[MAX_INFO_OPS_PER_BUNDLE])
126{ 123{
127 int num_ops = 0; 124 int num_ops = 0;
@@ -143,8 +140,7 @@ bt_get_info_ops(const BacktraceBundle *bundle,
143/** Does this bundle contain a jrp instruction, and if so, to which 140/** Does this bundle contain a jrp instruction, and if so, to which
144 * register is it jumping? 141 * register is it jumping?
145 */ 142 */
146static bool 143static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg)
147bt_has_jrp(const BacktraceBundle *bundle, int *target_reg)
148{ 144{
149 const struct tile_decoded_instruction *insn = 145 const struct tile_decoded_instruction *insn =
150 find_matching_insn(bundle, TILE_OPC_JRP, NULL, 0); 146 find_matching_insn(bundle, TILE_OPC_JRP, NULL, 0);
@@ -156,8 +152,7 @@ bt_has_jrp(const BacktraceBundle *bundle, int *target_reg)
156} 152}
157 153
158/** Does this bundle modify the specified register in any way? */ 154/** Does this bundle modify the specified register in any way? */
159static bool 155static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg)
160bt_modifies_reg(const BacktraceBundle *bundle, int reg)
161{ 156{
162 int i, j; 157 int i, j;
163 for (i = 0; i < bundle->num_insns; i++) { 158 for (i = 0; i < bundle->num_insns; i++) {
@@ -177,30 +172,26 @@ bt_modifies_reg(const BacktraceBundle *bundle, int reg)
177} 172}
178 173
179/** Does this bundle modify sp? */ 174/** Does this bundle modify sp? */
180static inline bool 175static inline bool bt_modifies_sp(const struct BacktraceBundle *bundle)
181bt_modifies_sp(const BacktraceBundle *bundle)
182{ 176{
183 return bt_modifies_reg(bundle, TREG_SP); 177 return bt_modifies_reg(bundle, TREG_SP);
184} 178}
185 179
186/** Does this bundle modify lr? */ 180/** Does this bundle modify lr? */
187static inline bool 181static inline bool bt_modifies_lr(const struct BacktraceBundle *bundle)
188bt_modifies_lr(const BacktraceBundle *bundle)
189{ 182{
190 return bt_modifies_reg(bundle, TREG_LR); 183 return bt_modifies_reg(bundle, TREG_LR);
191} 184}
192 185
193/** Does this bundle contain the instruction 'move fp, sp'? */ 186/** Does this bundle contain the instruction 'move fp, sp'? */
194static inline bool 187static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle)
195bt_has_move_r52_sp(const BacktraceBundle *bundle)
196{ 188{
197 static const int vals[2] = { 52, TREG_SP }; 189 static const int vals[2] = { 52, TREG_SP };
198 return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; 190 return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL;
199} 191}
200 192
201/** Does this bundle contain the instruction 'sw sp, lr'? */ 193/** Does this bundle contain the instruction 'sw sp, lr'? */
202static inline bool 194static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle)
203bt_has_sw_sp_lr(const BacktraceBundle *bundle)
204{ 195{
205 static const int vals[2] = { TREG_SP, TREG_LR }; 196 static const int vals[2] = { TREG_SP, TREG_LR };
206 return find_matching_insn(bundle, TILE_OPC_SW, vals, 2) != NULL; 197 return find_matching_insn(bundle, TILE_OPC_SW, vals, 2) != NULL;
@@ -209,11 +200,10 @@ bt_has_sw_sp_lr(const BacktraceBundle *bundle)
209/** Locates the caller's PC and SP for a program starting at the 200/** Locates the caller's PC and SP for a program starting at the
210 * given address. 201 * given address.
211 */ 202 */
212static void 203static void find_caller_pc_and_caller_sp(CallerLocation *location,
213find_caller_pc_and_caller_sp(CallerLocation *location, 204 const VirtualAddress start_pc,
214 const VirtualAddress start_pc, 205 BacktraceMemoryReader read_memory_func,
215 BacktraceMemoryReader read_memory_func, 206 void *read_memory_func_extra)
216 void *read_memory_func_extra)
217{ 207{
218 /* Have we explicitly decided what the sp is, 208 /* Have we explicitly decided what the sp is,
219 * rather than just the default? 209 * rather than just the default?
@@ -253,7 +243,7 @@ find_caller_pc_and_caller_sp(CallerLocation *location,
253 243
254 for (pc = start_pc;; pc += sizeof(tile_bundle_bits)) { 244 for (pc = start_pc;; pc += sizeof(tile_bundle_bits)) {
255 245
256 BacktraceBundle bundle; 246 struct BacktraceBundle bundle;
257 int num_info_ops, info_operands[MAX_INFO_OPS_PER_BUNDLE]; 247 int num_info_ops, info_operands[MAX_INFO_OPS_PER_BUNDLE];
258 int one_ago, jrp_reg; 248 int one_ago, jrp_reg;
259 bool has_jrp; 249 bool has_jrp;
@@ -475,12 +465,11 @@ find_caller_pc_and_caller_sp(CallerLocation *location,
475 } 465 }
476} 466}
477 467
478void 468void backtrace_init(BacktraceIterator *state,
479backtrace_init(BacktraceIterator *state, 469 BacktraceMemoryReader read_memory_func,
480 BacktraceMemoryReader read_memory_func, 470 void *read_memory_func_extra,
481 void *read_memory_func_extra, 471 VirtualAddress pc, VirtualAddress lr,
482 VirtualAddress pc, VirtualAddress lr, 472 VirtualAddress sp, VirtualAddress r52)
483 VirtualAddress sp, VirtualAddress r52)
484{ 473{
485 CallerLocation location; 474 CallerLocation location;
486 VirtualAddress fp, initial_frame_caller_pc; 475 VirtualAddress fp, initial_frame_caller_pc;
@@ -558,8 +547,7 @@ backtrace_init(BacktraceIterator *state,
558 state->read_memory_func_extra = read_memory_func_extra; 547 state->read_memory_func_extra = read_memory_func_extra;
559} 548}
560 549
561bool 550bool backtrace_next(BacktraceIterator *state)
562backtrace_next(BacktraceIterator *state)
563{ 551{
564 VirtualAddress next_fp, next_pc, next_frame[2]; 552 VirtualAddress next_fp, next_pc, next_frame[2];
565 553
@@ -614,12 +602,11 @@ backtrace_next(BacktraceIterator *state)
614 602
615#else /* TILE_CHIP < 10 */ 603#else /* TILE_CHIP < 10 */
616 604
617void 605void backtrace_init(BacktraceIterator *state,
618backtrace_init(BacktraceIterator *state, 606 BacktraceMemoryReader read_memory_func,
619 BacktraceMemoryReader read_memory_func, 607 void *read_memory_func_extra,
620 void *read_memory_func_extra, 608 VirtualAddress pc, VirtualAddress lr,
621 VirtualAddress pc, VirtualAddress lr, 609 VirtualAddress sp, VirtualAddress r52)
622 VirtualAddress sp, VirtualAddress r52)
623{ 610{
624 state->pc = pc; 611 state->pc = pc;
625 state->sp = sp; 612 state->sp = sp;