aboutsummaryrefslogtreecommitdiff
path: root/target/i386/gdbstub.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/i386/gdbstub.c')
-rw-r--r--target/i386/gdbstub.c102
1 files changed, 81 insertions, 21 deletions
diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c
index 4acf485..04c49e8 100644
--- a/target/i386/gdbstub.c
+++ b/target/i386/gdbstub.c
@@ -18,8 +18,13 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
+#include "accel/tcg/vcpu-state.h"
#include "cpu.h"
+#include "exec/gdbstub.h"
#include "gdbstub/helpers.h"
+#ifdef CONFIG_LINUX_USER
+#include "linux-user/qemu.h"
+#endif
#ifdef TARGET_X86_64
static const int gpr_map[16] = {
@@ -96,6 +101,19 @@ static int gdb_write_reg_cs64(uint32_t hflags, uint8_t *buf, target_ulong *val)
return 4;
}
+static int gdb_get_reg(CPUX86State *env, GByteArray *mem_buf, target_ulong val)
+{
+ if (TARGET_LONG_BITS == 64) {
+ if (env->hflags & HF_CS64_MASK) {
+ return gdb_get_reg64(mem_buf, val);
+ } else {
+ return gdb_get_reg64(mem_buf, val & 0xffffffffUL);
+ }
+ } else {
+ return gdb_get_reg32(mem_buf, val);
+ }
+}
+
int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
X86CPU *cpu = X86_CPU(cs);
@@ -137,15 +155,7 @@ int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
} else {
switch (n) {
case IDX_IP_REG:
- if (TARGET_LONG_BITS == 64) {
- if (env->hflags & HF_CS64_MASK) {
- return gdb_get_reg64(mem_buf, env->eip);
- } else {
- return gdb_get_reg64(mem_buf, env->eip & 0xffffffffUL);
- }
- } else {
- return gdb_get_reg32(mem_buf, env->eip);
- }
+ return gdb_get_reg(env, mem_buf, env->eip);
case IDX_FLAGS_REG:
return gdb_get_reg32(mem_buf, env->eflags);
@@ -248,6 +258,21 @@ static int x86_cpu_gdb_load_seg(X86CPU *cpu, X86Seg sreg, uint8_t *mem_buf)
return 4;
}
+static int gdb_write_reg(CPUX86State *env, uint8_t *mem_buf, target_ulong *val)
+{
+ if (TARGET_LONG_BITS == 64) {
+ if (env->hflags & HF_CS64_MASK) {
+ *val = ldq_p(mem_buf);
+ } else {
+ *val = ldq_p(mem_buf) & 0xffffffffUL;
+ }
+ return 8;
+ } else {
+ *val = (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
+}
+
int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
X86CPU *cpu = X86_CPU(cs);
@@ -288,18 +313,7 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
} else {
switch (n) {
case IDX_IP_REG:
- if (TARGET_LONG_BITS == 64) {
- if (env->hflags & HF_CS64_MASK) {
- env->eip = ldq_p(mem_buf);
- } else {
- env->eip = ldq_p(mem_buf) & 0xffffffffUL;
- }
- return 8;
- } else {
- env->eip &= ~0xffffffffUL;
- env->eip |= (uint32_t)ldl_p(mem_buf);
- return 4;
- }
+ return gdb_write_reg(env, mem_buf, &env->eip);
case IDX_FLAGS_REG:
env->eflags = ldl_p(mem_buf);
return 4;
@@ -397,3 +411,49 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
/* Unrecognised register. */
return 0;
}
+
+#ifdef CONFIG_LINUX_USER
+
+#define IDX_ORIG_AX 0
+
+static int x86_cpu_gdb_read_linux_register(CPUState *cs, GByteArray *mem_buf,
+ int n)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ switch (n) {
+ case IDX_ORIG_AX:
+ return gdb_get_reg(env, mem_buf, get_task_state(cs)->orig_ax);
+ }
+ return 0;
+}
+
+static int x86_cpu_gdb_write_linux_register(CPUState *cs, uint8_t *mem_buf,
+ int n)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ switch (n) {
+ case IDX_ORIG_AX:
+ return gdb_write_reg(env, mem_buf, &get_task_state(cs)->orig_ax);
+ }
+ return 0;
+}
+
+#endif
+
+void x86_cpu_gdb_init(CPUState *cs)
+{
+#ifdef CONFIG_LINUX_USER
+ gdb_register_coprocessor(cs, x86_cpu_gdb_read_linux_register,
+ x86_cpu_gdb_write_linux_register,
+#ifdef TARGET_X86_64
+ gdb_find_static_feature("i386-64bit-linux.xml"),
+#else
+ gdb_find_static_feature("i386-32bit-linux.xml"),
+#endif
+ 0);
+#endif
+}