2 * Copyright 2014 Google Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but without any warranty; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <exception.h>
17 #include <libpayload.h>
25 } __attribute__((packed
)) f
[8];
28 } __attribute__((packed
));
30 static const u8 type_to_signal
[] = {
31 [EXC_UNDEF
] = GDB_SIGILL
,
32 [EXC_SWI
] = GDB_SIGTRAP
,
33 [EXC_PABORT
] = GDB_SIGSEGV
,
34 [EXC_DABORT
] = GDB_SIGSEGV
,
37 /* Scratch value to write reentrant exception states to. We never read it. */
38 static struct exception_state sentinel_exception_state
;
40 static int gdb_exception_hook(u32 type
)
43 * If we were not resumed we are in deep trouble here. GDB probably told
44 * us to do something stupid and caused a reentrant exception. All we
45 * can do is just blindly send an error code and keep going. Eventually
46 * GDB will tell us to resume and we return right back to the original
47 * exception state ("jumping over" all the nested ones).
49 if (gdb_state
.connected
&& !gdb_state
.resumed
) {
50 static const char error_code
[] = "E22"; /* EINVAL? */
51 static const struct gdb_message tmp_reply
= {
52 .buf
= (u8
*)error_code
,
53 .used
= sizeof(error_code
),
54 .size
= sizeof(error_code
),
56 gdb_send_reply(&tmp_reply
);
57 gdb_command_loop(gdb_state
.signal
); /* preserve old signal */
59 if (type
>= ARRAY_SIZE(type_to_signal
) || !type_to_signal
[type
])
61 exception_state_ptr
= &sentinel_exception_state
;
62 gdb_command_loop(type_to_signal
[type
]);
65 exception_state_ptr
= &exception_state
;
69 void gdb_arch_init(void)
71 exception_install_hook(&gdb_exception_hook
);
74 void gdb_arch_enter(void)
78 asm volatile ("mov %0, %%sp" : "=r"(sp
) );
80 /* Avoid reentrant exceptions, just call the hook if in one already. */
81 if (sp
>= exception_stack
&& sp
<= exception_stack_end
)
82 gdb_exception_hook(EXC_SWI
);
84 asm volatile ("svc #0");
87 int gdb_arch_set_single_step(int on
)
89 /* GDB seems to only need this on x86, ARM works fine without it. */
93 void gdb_arch_encode_regs(struct gdb_message
*message
)
95 gdb_message_encode_bytes(message
, exception_state
.regs
,
96 sizeof(exception_state
.regs
));
97 gdb_message_encode_zero_bytes(message
,
98 offsetof(struct gdb_regs
, cpsr
) - offsetof(struct gdb_regs
, f
));
99 gdb_message_encode_bytes(message
, &exception_state
.cpsr
,
100 sizeof(exception_state
.cpsr
));
103 void gdb_arch_decode_regs(int offset
, struct gdb_message
*message
)
105 const int cpsr_hex_offset
= offsetof(struct gdb_regs
, cpsr
) * 2;
106 gdb_message_decode_bytes(message
, offset
,
107 exception_state
.regs
, sizeof(exception_state
.regs
));
108 gdb_message_decode_bytes(message
, offset
+ cpsr_hex_offset
,
109 &exception_state
.cpsr
, sizeof(exception_state
.cpsr
));