Release 4.20.
[wine.git] / programs / winedbg / be_arm64.c
blobbca86b825740c8616eb7e7dd729cef52b968dc20
1 /*
2 * Debugger ARM64 specific functions
4 * Copyright 2010-2013 André Hentschel
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "debugger.h"
23 #if defined(__aarch64__) && !defined(__AARCH64EB__)
25 static BOOL be_arm64_get_addr(HANDLE hThread, const dbg_ctx_t *ctx,
26 enum be_cpu_addr bca, ADDRESS64* addr)
28 switch (bca)
30 case be_cpu_addr_pc:
31 return be_cpu_build_addr(hThread, ctx, addr, 0, ctx->ctx.Pc);
32 case be_cpu_addr_stack:
33 return be_cpu_build_addr(hThread, ctx, addr, 0, ctx->ctx.Sp);
34 case be_cpu_addr_frame:
35 return be_cpu_build_addr(hThread, ctx, addr, 0, ctx->ctx.u.s.Fp);
36 break;
38 return FALSE;
41 static BOOL be_arm64_get_register_info(int regno, enum be_cpu_addr* kind)
43 switch (regno)
45 case CV_ARM64_PC: *kind = be_cpu_addr_pc; return TRUE;
46 case CV_ARM64_SP: *kind = be_cpu_addr_stack; return TRUE;
47 case CV_ARM64_FP: *kind = be_cpu_addr_frame; return TRUE;
49 return FALSE;
52 static void be_arm64_single_step(dbg_ctx_t *ctx, BOOL enable)
54 dbg_printf("be_arm64_single_step: not done\n");
57 static void be_arm64_print_context(HANDLE hThread, const dbg_ctx_t *ctx, int all_regs)
59 static const char condflags[] = "NZCV";
60 int i;
61 char buf[8];
63 switch (ctx->ctx.Cpsr & 0x0f)
65 case 0: strcpy(buf, "EL0t"); break;
66 case 4: strcpy(buf, "EL1t"); break;
67 case 5: strcpy(buf, "EL1t"); break;
68 case 8: strcpy(buf, "EL2t"); break;
69 case 9: strcpy(buf, "EL2t"); break;
70 case 12: strcpy(buf, "EL3t"); break;
71 case 13: strcpy(buf, "EL3t"); break;
72 default: strcpy(buf, "UNKNWN"); break;
75 dbg_printf("Register dump:\n");
76 dbg_printf("%s %s Mode\n", (ctx->ctx.Cpsr & 0x10) ? "ARM" : "ARM64", buf);
78 strcpy(buf, condflags);
79 for (i = 0; buf[i]; i++)
80 if (!((ctx->ctx.Cpsr >> 26) & (1 << (sizeof(condflags) - i))))
81 buf[i] = '-';
83 dbg_printf(" Pc:%016lx Sp:%016lx Lr:%016lx Cpsr:%08x(%s)\n",
84 ctx->ctx.Pc, ctx->ctx.Sp, ctx->ctx.u.s.Lr, ctx->ctx.Cpsr, buf);
85 dbg_printf(" x0: %016lx x1: %016lx x2: %016lx x3: %016lx x4: %016lx\n",
86 ctx->ctx.u.s.X0, ctx->ctx.u.s.X1, ctx->ctx.u.s.X2, ctx->ctx.u.s.X3, ctx->ctx.u.s.X4);
87 dbg_printf(" x5: %016lx x6: %016lx x7: %016lx x8: %016lx x9: %016lx\n",
88 ctx->ctx.u.s.X5, ctx->ctx.u.s.X6, ctx->ctx.u.s.X7, ctx->ctx.u.s.X8, ctx->ctx.u.s.X9);
89 dbg_printf(" x10:%016lx x11:%016lx x12:%016lx x13:%016lx x14:%016lx\n",
90 ctx->ctx.u.s.X10, ctx->ctx.u.s.X11, ctx->ctx.u.s.X12, ctx->ctx.u.s.X13, ctx->ctx.u.s.X14);
91 dbg_printf(" x15:%016lx ip0:%016lx ip1:%016lx x18:%016lx x19:%016lx\n",
92 ctx->ctx.u.s.X15, ctx->ctx.u.s.X16, ctx->ctx.u.s.X17, ctx->ctx.u.s.X18, ctx->ctx.u.s.X19);
93 dbg_printf(" x20:%016lx x21:%016lx x22:%016lx x23:%016lx x24:%016lx\n",
94 ctx->ctx.u.s.X20, ctx->ctx.u.s.X21, ctx->ctx.u.s.X22, ctx->ctx.u.s.X23, ctx->ctx.u.s.X24);
95 dbg_printf(" x25:%016lx x26:%016lx x27:%016lx x28:%016lx Fp:%016lx\n",
96 ctx->ctx.u.s.X25, ctx->ctx.u.s.X26, ctx->ctx.u.s.X27, ctx->ctx.u.s.X28, ctx->ctx.u.s.Fp);
98 if (all_regs) dbg_printf( "Floating point ARM64 dump not implemented\n" );
101 static void be_arm64_print_segment_info(HANDLE hThread, const dbg_ctx_t *ctx)
105 static struct dbg_internal_var be_arm64_ctx[] =
107 {CV_ARM64_PSTATE, "cpsr", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, Cpsr), dbg_itype_unsigned_int},
108 {CV_ARM64_X0 + 0, "x0", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X0), dbg_itype_unsigned_long_int},
109 {CV_ARM64_X0 + 1, "x1", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X1), dbg_itype_unsigned_long_int},
110 {CV_ARM64_X0 + 2, "x2", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X2), dbg_itype_unsigned_long_int},
111 {CV_ARM64_X0 + 3, "x3", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X3), dbg_itype_unsigned_long_int},
112 {CV_ARM64_X0 + 4, "x4", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X4), dbg_itype_unsigned_long_int},
113 {CV_ARM64_X0 + 5, "x5", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X5), dbg_itype_unsigned_long_int},
114 {CV_ARM64_X0 + 6, "x6", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X6), dbg_itype_unsigned_long_int},
115 {CV_ARM64_X0 + 7, "x7", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X7), dbg_itype_unsigned_long_int},
116 {CV_ARM64_X0 + 8, "x8", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X8), dbg_itype_unsigned_long_int},
117 {CV_ARM64_X0 + 9, "x9", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X9), dbg_itype_unsigned_long_int},
118 {CV_ARM64_X0 + 10, "x10", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X10), dbg_itype_unsigned_long_int},
119 {CV_ARM64_X0 + 11, "x11", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X11), dbg_itype_unsigned_long_int},
120 {CV_ARM64_X0 + 12, "x12", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X12), dbg_itype_unsigned_long_int},
121 {CV_ARM64_X0 + 13, "x13", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X13), dbg_itype_unsigned_long_int},
122 {CV_ARM64_X0 + 14, "x14", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X14), dbg_itype_unsigned_long_int},
123 {CV_ARM64_X0 + 15, "x15", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X15), dbg_itype_unsigned_long_int},
124 {CV_ARM64_X0 + 16, "x16", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X16), dbg_itype_unsigned_long_int},
125 {CV_ARM64_X0 + 17, "x17", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X17), dbg_itype_unsigned_long_int},
126 {CV_ARM64_X0 + 18, "x18", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X18), dbg_itype_unsigned_long_int},
127 {CV_ARM64_X0 + 19, "x19", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X19), dbg_itype_unsigned_long_int},
128 {CV_ARM64_X0 + 20, "x20", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X20), dbg_itype_unsigned_long_int},
129 {CV_ARM64_X0 + 21, "x21", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X21), dbg_itype_unsigned_long_int},
130 {CV_ARM64_X0 + 22, "x22", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X22), dbg_itype_unsigned_long_int},
131 {CV_ARM64_X0 + 23, "x23", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X23), dbg_itype_unsigned_long_int},
132 {CV_ARM64_X0 + 24, "x24", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X24), dbg_itype_unsigned_long_int},
133 {CV_ARM64_X0 + 25, "x25", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X25), dbg_itype_unsigned_long_int},
134 {CV_ARM64_X0 + 26, "x26", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X26), dbg_itype_unsigned_long_int},
135 {CV_ARM64_X0 + 27, "x27", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X27), dbg_itype_unsigned_long_int},
136 {CV_ARM64_X0 + 28, "x28", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.X28), dbg_itype_unsigned_long_int},
137 {CV_ARM64_FP, "fp", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.Fp), dbg_itype_unsigned_long_int},
138 {CV_ARM64_LR, "lr", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, u.s.Lr), dbg_itype_unsigned_long_int},
139 {CV_ARM64_SP, "sp", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, Sp), dbg_itype_unsigned_long_int},
140 {CV_ARM64_PC, "pc", (DWORD_PTR*)FIELD_OFFSET(CONTEXT, Pc), dbg_itype_unsigned_long_int},
141 {0, NULL, 0, dbg_itype_none}
144 static BOOL be_arm64_is_step_over_insn(const void* insn)
146 dbg_printf("be_arm64_is_step_over_insn: not done\n");
147 return FALSE;
150 static BOOL be_arm64_is_function_return(const void* insn)
152 dbg_printf("be_arm64_is_function_return: not done\n");
153 return FALSE;
156 static BOOL be_arm64_is_break_insn(const void* insn)
158 dbg_printf("be_arm64_is_break_insn: not done\n");
159 return FALSE;
162 static BOOL be_arm64_is_func_call(const void* insn, ADDRESS64* callee)
164 return FALSE;
167 static BOOL be_arm64_is_jump(const void* insn, ADDRESS64* jumpee)
169 return FALSE;
172 static BOOL be_arm64_insert_Xpoint(HANDLE hProcess, const struct be_process_io* pio,
173 dbg_ctx_t *ctx, enum be_xpoint_type type,
174 void* addr, unsigned long* val, unsigned size)
176 SIZE_T sz;
178 switch (type)
180 case be_xpoint_break:
181 if (!size) return FALSE;
182 if (!pio->read(hProcess, addr, val, 4, &sz) || sz != 4) return FALSE;
183 default:
184 dbg_printf("Unknown/unsupported bp type %c\n", type);
185 return FALSE;
187 return TRUE;
190 static BOOL be_arm64_remove_Xpoint(HANDLE hProcess, const struct be_process_io* pio,
191 dbg_ctx_t *ctx, enum be_xpoint_type type,
192 void* addr, unsigned long val, unsigned size)
194 SIZE_T sz;
196 switch (type)
198 case be_xpoint_break:
199 if (!size) return FALSE;
200 if (!pio->write(hProcess, addr, &val, 4, &sz) || sz == 4) return FALSE;
201 break;
202 default:
203 dbg_printf("Unknown/unsupported bp type %c\n", type);
204 return FALSE;
206 return TRUE;
209 static BOOL be_arm64_is_watchpoint_set(const dbg_ctx_t *ctx, unsigned idx)
211 dbg_printf("be_arm64_is_watchpoint_set: not done\n");
212 return FALSE;
215 static void be_arm64_clear_watchpoint(dbg_ctx_t *ctx, unsigned idx)
217 dbg_printf("be_arm64_clear_watchpoint: not done\n");
220 static int be_arm64_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way)
222 if (way)
224 ctx->ctx.Pc -= 4;
225 return -4;
227 ctx->ctx.Pc += 4;
228 return 4;
231 static BOOL be_arm64_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size,
232 BOOL is_signed, LONGLONG* ret)
234 if (size != 1 && size != 2 && size != 4 && size != 8) return FALSE;
236 memset(ret, 0, sizeof(*ret)); /* clear unread bytes */
237 /* FIXME: this assumes that debuggee and debugger use the same
238 * integral representation
240 if (!memory_read_value(lvalue, size, ret)) return FALSE;
242 /* propagate sign information */
243 if (is_signed && size < 8 && (*ret >> (size * 8 - 1)) != 0)
245 ULONGLONG neg = -1;
246 *ret |= neg << (size * 8);
248 return TRUE;
251 static BOOL be_arm64_fetch_float(const struct dbg_lvalue* lvalue, unsigned size,
252 long double* ret)
254 char tmp[sizeof(long double)];
256 /* FIXME: this assumes that debuggee and debugger use the same
257 * representation for reals
259 if (!memory_read_value(lvalue, size, tmp)) return FALSE;
261 if (size == sizeof(float)) *ret = *(float*)tmp;
262 else if (size == sizeof(double)) *ret = *(double*)tmp;
263 else if (size == sizeof(long double)) *ret = *(long double*)tmp;
264 else return FALSE;
266 return TRUE;
269 static BOOL be_arm64_store_integer(const struct dbg_lvalue* lvalue, unsigned size,
270 BOOL is_signed, LONGLONG val)
272 /* this is simple if we're on a little endian CPU */
273 return memory_write_value(lvalue, size, &val);
276 void be_arm64_disasm_one_insn(ADDRESS64 *addr, int display)
278 dbg_printf("be_arm64_disasm_one_insn: not done\n");
281 static BOOL be_arm64_get_context(HANDLE thread, dbg_ctx_t *ctx)
283 ctx->ctx.ContextFlags = CONTEXT_ALL;
284 return GetThreadContext(thread, &ctx->ctx);
287 static BOOL be_arm64_set_context(HANDLE thread, const dbg_ctx_t *ctx)
289 return SetThreadContext(thread, &ctx->ctx);
292 #define REG(r,gs) {FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r), gs}
294 static struct gdb_register be_arm64_gdb_register_map[] = {
295 REG(Cpsr, 4),
296 REG(u.s.X0, 8),
297 REG(u.s.X1, 8),
298 REG(u.s.X2, 8),
299 REG(u.s.X3, 8),
300 REG(u.s.X4, 8),
301 REG(u.s.X5, 8),
302 REG(u.s.X6, 8),
303 REG(u.s.X7, 8),
304 REG(u.s.X8, 8),
305 REG(u.s.X9, 8),
306 REG(u.s.X10, 8),
307 REG(u.s.X11, 8),
308 REG(u.s.X12, 8),
309 REG(u.s.X13, 8),
310 REG(u.s.X14, 8),
311 REG(u.s.X15, 8),
312 REG(u.s.X16, 8),
313 REG(u.s.X17, 8),
314 REG(u.s.X18, 8),
315 REG(u.s.X19, 8),
316 REG(u.s.X20, 8),
317 REG(u.s.X21, 8),
318 REG(u.s.X22, 8),
319 REG(u.s.X23, 8),
320 REG(u.s.X24, 8),
321 REG(u.s.X25, 8),
322 REG(u.s.X26, 8),
323 REG(u.s.X27, 8),
324 REG(u.s.X28, 8),
325 REG(u.s.Fp, 8),
326 REG(u.s.Lr, 8),
327 REG(Sp, 8),
328 REG(Pc, 8),
331 struct backend_cpu be_arm64 =
333 IMAGE_FILE_MACHINE_ARM64,
335 be_cpu_linearize,
336 be_cpu_build_addr,
337 be_arm64_get_addr,
338 be_arm64_get_register_info,
339 be_arm64_single_step,
340 be_arm64_print_context,
341 be_arm64_print_segment_info,
342 be_arm64_ctx,
343 be_arm64_is_step_over_insn,
344 be_arm64_is_function_return,
345 be_arm64_is_break_insn,
346 be_arm64_is_func_call,
347 be_arm64_is_jump,
348 be_arm64_disasm_one_insn,
349 be_arm64_insert_Xpoint,
350 be_arm64_remove_Xpoint,
351 be_arm64_is_watchpoint_set,
352 be_arm64_clear_watchpoint,
353 be_arm64_adjust_pc_for_break,
354 be_arm64_fetch_integer,
355 be_arm64_fetch_float,
356 be_arm64_store_integer,
357 be_arm64_get_context,
358 be_arm64_set_context,
359 be_arm64_gdb_register_map,
360 ARRAY_SIZE(be_arm64_gdb_register_map),
362 #endif