diff options
-rw-r--r-- | gdb/aarch64-linux-tdep.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 9d082e883f..3ed26496f7 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -45,6 +45,7 @@ #include "record-full.h" #include "linux-record.h" +#include "linux-kthread.h" /* Signal frame handling. @@ -939,6 +940,92 @@ aarch64_linux_syscall_record (struct regcache *regcache, return 0; } +/* From arm64/include/asm/processor.h */ +struct cpu_context { + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long fp; + unsigned long sp; + unsigned long pc; +} cpu_cxt; + +static void +aarch64_linux_supply_thread (struct regcache *regcache, + int regnum, CORE_ADDR task_struct) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + CORE_ADDR sp = 0; + gdb_byte buf[8]; + int i; + uint32_t cpsr; + uint32_t thread_info_addr; + + DECLARE_FIELD (thread_info, cpu_context); + DECLARE_FIELD (task_struct, stack); + + gdb_assert (regnum >= -1); + + /*get thread_info address */ + thread_info_addr = read_unsigned_field (task_struct, task_struct, stack); + + /*get cpu_context as saved by scheduled */ + read_memory ((CORE_ADDR) thread_info_addr + + F_OFFSET (thread_info, cpu_context), + (gdb_byte *) & cpu_cxt, sizeof (struct cpu_context)); + + regcache_raw_supply (regcache, ARM_PC_REGNUM, &cpu_cxt.pc); + regcache_raw_supply (regcache, ARM_SP_REGNUM, &cpu_cxt.sp); + regcache_raw_supply (regcache, ARM_FP_REGNUM, &cpu_cxt.fp); + + /*general purpose registers */ + regcache_raw_supply (regcache, 10, &cpu_cxt.x28); + regcache_raw_supply (regcache, 9, &cpu_cxt.x27); + regcache_raw_supply (regcache, 8, &cpu_cxt.x26); + regcache_raw_supply (regcache, 7, &cpu_cxt.x25); + regcache_raw_supply (regcache, 6, &cpu_cxt.x24); + regcache_raw_supply (regcache, 5, &cpu_cxt.x23); + regcache_raw_supply (regcache, 4, &cpu_cxt.x22); + regcache_raw_supply (regcache, 4, &cpu_cxt.x21); + regcache_raw_supply (regcache, 4, &cpu_cxt.x20); + regcache_raw_supply (regcache, 4, &cpu_cxt.x19); + + /* Fake a value for cpsr:T bit. */ +#define IS_THUMB_ADDR(addr) ((addr) & 1) + cpsr = IS_THUMB_ADDR(cpu_cxt.pc) ? arm_psr_thumb_bit (target_gdbarch ()) : 0; + regcache_raw_supply (regcache, ARM_PS_REGNUM, &cpsr); + + for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++) + if (REG_VALID != regcache_register_status (regcache, i)) + /* Mark other registers as unavailable. */ + regcache_invalidate (regcache, i); +} + +static void +aarch64_linux_collect_thread (const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp = 0; + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + gdb_assert (0); + +} + static void aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -1163,6 +1250,10 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_displaced_step_location (gdbarch, linux_displaced_step_location); set_gdbarch_displaced_step_hw_singlestep (gdbarch, aarch64_displaced_step_hw_singlestep); + + /* Provide a Linux Kernel threads implementation. */ + linux_kthread_set_supply_thread (gdbarch, aarch64_linux_supply_thread); + linux_kthread_set_collect_thread (gdbarch, aarch64_linux_collect_thread); } /* Provide a prototype to silence -Wmissing-prototypes. */ |