2 * Debugger ARM specific functions
4 * Copyright 2000-2003 Marcus Meissner
6 * 2010, 2011 André Hentschel
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 static unsigned be_arm_get_addr(HANDLE hThread
, const CONTEXT
* ctx
,
28 enum be_cpu_addr bca
, ADDRESS64
* addr
)
33 return be_cpu_build_addr(hThread
, ctx
, addr
, 0, ctx
->Pc
);
34 case be_cpu_addr_stack
:
35 return be_cpu_build_addr(hThread
, ctx
, addr
, 0, ctx
->Sp
);
36 case be_cpu_addr_frame
:
37 return be_cpu_build_addr(hThread
, ctx
, addr
, 0, ctx
->Fp
);
42 static unsigned be_arm_get_register_info(int regno
, enum be_cpu_addr
* kind
)
46 case CV_ARM_PC
: *kind
= be_cpu_addr_pc
; return TRUE
;
47 case CV_ARM_R0
+ 11: *kind
= be_cpu_addr_frame
; return TRUE
;
48 case CV_ARM_SP
: *kind
= be_cpu_addr_stack
; return TRUE
;
53 static void be_arm_single_step(CONTEXT
* ctx
, unsigned enable
)
55 dbg_printf("be_arm_single_step: not done\n");
58 static void be_arm_print_context(HANDLE hThread
, const CONTEXT
* ctx
, int all_regs
)
60 static const char condflags
[] = "NZCV";
64 switch (ctx
->Cpsr
& 0x1F)
66 case 0: strcpy(buf
, "User26"); break;
67 case 1: strcpy(buf
, "FIQ26"); break;
68 case 2: strcpy(buf
, "IRQ26"); break;
69 case 3: strcpy(buf
, "SVC26"); break;
70 case 16: strcpy(buf
, "User"); break;
71 case 17: strcpy(buf
, "FIQ"); break;
72 case 18: strcpy(buf
, "IRQ"); break;
73 case 19: strcpy(buf
, "SVC"); break;
74 case 23: strcpy(buf
, "ABT"); break;
75 case 27: strcpy(buf
, "UND"); break;
76 default: strcpy(buf
, "UNKNWN"); break;
79 dbg_printf("Register dump:\n");
80 dbg_printf("%s %s Mode\n", (ctx
->Cpsr
& 0x20) ? "Thumb" : "ARM", buf
);
82 strcpy(buf
, condflags
);
83 for (i
= 0; buf
[i
]; i
++)
84 if (!((ctx
->Cpsr
>> 26) & (1 << (sizeof(condflags
) - i
))))
87 dbg_printf(" Pc:%04x Sp:%04x Lr:%04x Cpsr:%04x(%s)\n",
88 ctx
->Pc
, ctx
->Sp
, ctx
->Lr
, ctx
->Cpsr
, buf
);
89 dbg_printf(" r0:%04x r1:%04x r2:%04x r3:%04x\n",
90 ctx
->R0
, ctx
->R1
, ctx
->R2
, ctx
->R3
);
91 dbg_printf(" r4:%04x r5:%04x r6:%04x r7:%04x r8:%04x\n",
92 ctx
->R4
, ctx
->R5
, ctx
->R6
, ctx
->R7
, ctx
->R8
);
93 dbg_printf(" r9:%04x r10:%04x Fp:%04x Ip:%04x\n",
94 ctx
->R9
, ctx
->R10
, ctx
->Fp
, ctx
->Ip
);
96 if (all_regs
) dbg_printf( "Floating point ARM dump not implemented\n" );
99 static void be_arm_print_segment_info(HANDLE hThread
, const CONTEXT
* ctx
)
103 static struct dbg_internal_var be_arm_ctx
[] =
105 {CV_ARM_R0
+ 0, "r0", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R0
), dbg_itype_unsigned_int
},
106 {CV_ARM_R0
+ 1, "r1", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R1
), dbg_itype_unsigned_int
},
107 {CV_ARM_R0
+ 2, "r2", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R2
), dbg_itype_unsigned_int
},
108 {CV_ARM_R0
+ 3, "r3", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R3
), dbg_itype_unsigned_int
},
109 {CV_ARM_R0
+ 4, "r4", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R4
), dbg_itype_unsigned_int
},
110 {CV_ARM_R0
+ 5, "r5", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R5
), dbg_itype_unsigned_int
},
111 {CV_ARM_R0
+ 6, "r6", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R6
), dbg_itype_unsigned_int
},
112 {CV_ARM_R0
+ 7, "r7", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R7
), dbg_itype_unsigned_int
},
113 {CV_ARM_R0
+ 8, "r8", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R8
), dbg_itype_unsigned_int
},
114 {CV_ARM_R0
+ 9, "r9", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R9
), dbg_itype_unsigned_int
},
115 {CV_ARM_R0
+ 10, "r10", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R10
), dbg_itype_unsigned_int
},
116 {CV_ARM_R0
+ 11, "r11", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Fp
), dbg_itype_unsigned_int
},
117 {CV_ARM_R0
+ 12, "r12", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Ip
), dbg_itype_unsigned_int
},
118 {CV_ARM_SP
, "sp", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Sp
), dbg_itype_unsigned_int
},
119 {CV_ARM_LR
, "lr", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Lr
), dbg_itype_unsigned_int
},
120 {CV_ARM_PC
, "pc", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Pc
), dbg_itype_unsigned_int
},
121 {CV_ARM_CPSR
, "cpsr", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Cpsr
), dbg_itype_unsigned_int
},
122 {0, NULL
, 0, dbg_itype_none
}
125 static unsigned be_arm_is_step_over_insn(const void* insn
)
127 dbg_printf("be_arm_is_step_over_insn: not done\n");
131 static unsigned be_arm_is_function_return(const void* insn
)
133 dbg_printf("be_arm_is_function_return: not done\n");
137 static unsigned be_arm_is_break_insn(const void* insn
)
139 dbg_printf("be_arm_is_break_insn: not done\n");
143 static unsigned be_arm_is_func_call(const void* insn
, ADDRESS64
* callee
)
148 static unsigned be_arm_is_jump(const void* insn
, ADDRESS64
* jumpee
)
153 static void be_arm_disasm_one_insn(ADDRESS64
* addr
, int display
)
155 dbg_printf("Disasm NIY\n");
158 static unsigned be_arm_insert_Xpoint(HANDLE hProcess
, const struct be_process_io
* pio
,
159 CONTEXT
* ctx
, enum be_xpoint_type type
,
160 void* addr
, unsigned long* val
, unsigned size
)
166 case be_xpoint_break
:
168 if (!pio
->read(hProcess
, addr
, val
, 4, &sz
) || sz
!= 4) return 0;
170 dbg_printf("Unknown/unsupported bp type %c\n", type
);
176 static unsigned be_arm_remove_Xpoint(HANDLE hProcess
, const struct be_process_io
* pio
,
177 CONTEXT
* ctx
, enum be_xpoint_type type
,
178 void* addr
, unsigned long val
, unsigned size
)
184 case be_xpoint_break
:
186 if (!pio
->write(hProcess
, addr
, &val
, 4, &sz
) || sz
== 4) return 0;
189 dbg_printf("Unknown/unsupported bp type %c\n", type
);
195 static unsigned be_arm_is_watchpoint_set(const CONTEXT
* ctx
, unsigned idx
)
197 dbg_printf("be_arm_is_watchpoint_set: not done\n");
201 static void be_arm_clear_watchpoint(CONTEXT
* ctx
, unsigned idx
)
203 dbg_printf("be_arm_clear_watchpoint: not done\n");
206 static int be_arm_adjust_pc_for_break(CONTEXT
* ctx
, BOOL way
)
217 static int be_arm_fetch_integer(const struct dbg_lvalue
* lvalue
, unsigned size
,
218 unsigned ext_sign
, LONGLONG
* ret
)
220 if (size
!= 1 && size
!= 2 && size
!= 4 && size
!= 8) return FALSE
;
222 memset(ret
, 0, sizeof(*ret
)); /* clear unread bytes */
223 /* FIXME: this assumes that debuggee and debugger use the same
224 * integral representation
226 if (!memory_read_value(lvalue
, size
, ret
)) return FALSE
;
228 /* propagate sign information */
229 if (ext_sign
&& size
< 8 && (*ret
>> (size
* 8 - 1)) != 0)
232 *ret
|= neg
<< (size
* 8);
237 static int be_arm_fetch_float(const struct dbg_lvalue
* lvalue
, unsigned size
,
240 dbg_printf("be_arm_fetch_float: not done\n");
244 struct backend_cpu be_arm
=
246 IMAGE_FILE_MACHINE_ARM
,
251 be_arm_get_register_info
,
253 be_arm_print_context
,
254 be_arm_print_segment_info
,
256 be_arm_is_step_over_insn
,
257 be_arm_is_function_return
,
258 be_arm_is_break_insn
,
261 be_arm_disasm_one_insn
,
262 be_arm_insert_Xpoint
,
263 be_arm_remove_Xpoint
,
264 be_arm_is_watchpoint_set
,
265 be_arm_clear_watchpoint
,
266 be_arm_adjust_pc_for_break
,
267 be_arm_fetch_integer
,