X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fxtensa-linux-nat.c;h=097d7bd6f968cc9e1b014c8b406cfffa293de9b9;hb=4f83758119ddf0f114477760d79bdde7bbc76835;hp=5d27173fd5daff87a3400089ec4ad7fcbdd99ac5;hpb=94a0e877111421d300d26b858bd3a0a27078d1e8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/xtensa-linux-nat.c b/gdb/xtensa-linux-nat.c index 5d27173fd5..097d7bd6f9 100644 --- a/gdb/xtensa-linux-nat.c +++ b/gdb/xtensa-linux-nat.c @@ -1,6 +1,6 @@ /* Xtensa GNU/Linux native support. - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -18,43 +18,42 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_string.h" #include "frame.h" #include "inferior.h" #include "gdbcore.h" #include "regcache.h" -#include "gdb_assert.h" #include "target.h" #include "linux-nat.h" - -#include #include -#include #include #include #include -#include "gdb_wait.h" +#include "gdbsupport/gdb_wait.h" #include #include -#include +#include "nat/gdb_ptrace.h" +#include #include "gregset.h" #include "xtensa-tdep.h" +/* Defines ps_err_e, struct ps_prochandle. */ +#include "gdb_proc_service.h" + /* Extended register set depends on hardware configs. Keeping these definitions separately allows to introduce hardware-specific overlays. */ #include "xtensa-xtregs.c" -int -get_thread_id (ptid_t ptid) +class xtensa_linux_nat_target final : public linux_nat_target { - int tid = TIDGET (ptid); - if (0 == tid) - tid = PIDGET (ptid); - return tid; -} -#define GET_THREAD_ID(PTID) get_thread_id (PTID) +public: + /* Add our register access methods. */ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; +}; + +static xtensa_linux_nat_target the_xtensa_linux_nat_target; void fill_gregset (const struct regcache *regcache, @@ -62,101 +61,119 @@ fill_gregset (const struct regcache *regcache, { int i; xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1) - regcache_raw_collect (regcache, gdbarch_pc_regnum (gdbarch), ®s->pc); + regcache->raw_collect (gdbarch_pc_regnum (gdbarch), ®s->pc); if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1) - regcache_raw_collect (regcache, gdbarch_ps_regnum (gdbarch), ®s->ps); + regcache->raw_collect (gdbarch_ps_regnum (gdbarch), ®s->ps); if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->wb_regnum, - ®s->windowbase); + regcache->raw_collect (gdbarch_tdep (gdbarch)->wb_regnum, + ®s->windowbase); if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->ws_regnum, - ®s->windowstart); + regcache->raw_collect (gdbarch_tdep (gdbarch)->ws_regnum, + ®s->windowstart); if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->lbeg_regnum, - ®s->lbeg); + regcache->raw_collect (gdbarch_tdep (gdbarch)->lbeg_regnum, + ®s->lbeg); if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->lend_regnum, - ®s->lend); + regcache->raw_collect (gdbarch_tdep (gdbarch)->lend_regnum, + ®s->lend); if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->lcount_regnum, - ®s->lcount); + regcache->raw_collect (gdbarch_tdep (gdbarch)->lcount_regnum, + ®s->lcount); if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->sar_regnum, - ®s->sar); + regcache->raw_collect (gdbarch_tdep (gdbarch)->sar_regnum, + ®s->sar); + if (regnum == gdbarch_tdep (gdbarch)->threadptr_regnum || regnum == -1) + regcache->raw_collect (gdbarch_tdep (gdbarch)->threadptr_regnum, + ®s->threadptr); if (regnum >=gdbarch_tdep (gdbarch)->ar_base && regnum < gdbarch_tdep (gdbarch)->ar_base + gdbarch_tdep (gdbarch)->num_aregs) - regcache_raw_collect (regcache,regnum, - ®s->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]); + regcache->raw_collect (regnum, + ®s->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]); else if (regnum == -1) { for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i) - regcache_raw_collect (regcache, - gdbarch_tdep (gdbarch)->ar_base + i, - ®s->ar[i]); + regcache->raw_collect (gdbarch_tdep (gdbarch)->ar_base + i, + ®s->ar[i]); + } + if (regnum >= gdbarch_tdep (gdbarch)->a0_base + && regnum < gdbarch_tdep (gdbarch)->a0_base + C0_NREGS) + regcache->raw_collect (regnum, + ®s->ar[(4 * regs->windowbase + regnum + - gdbarch_tdep (gdbarch)->a0_base) + % gdbarch_tdep (gdbarch)->num_aregs]); + else if (regnum == -1) + { + for (i = 0; i < C0_NREGS; ++i) + regcache->raw_collect (gdbarch_tdep (gdbarch)->a0_base + i, + (®s->ar[(4 * regs->windowbase + i) + % gdbarch_tdep (gdbarch)->num_aregs])); } } -void +static void supply_gregset_reg (struct regcache *regcache, const gdb_gregset_t *gregsetp, int regnum) { int i; xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1) - regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), ®s->pc); + regcache->raw_supply (gdbarch_pc_regnum (gdbarch), ®s->pc); if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1) - regcache_raw_supply (regcache, gdbarch_ps_regnum (gdbarch), ®s->ps); + regcache->raw_supply (gdbarch_ps_regnum (gdbarch), ®s->ps); if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->wb_regnum, + regcache->raw_supply (gdbarch_tdep (gdbarch)->wb_regnum, ®s->windowbase); if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->ws_regnum, + regcache->raw_supply (gdbarch_tdep (gdbarch)->ws_regnum, ®s->windowstart); if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->lbeg_regnum, + regcache->raw_supply (gdbarch_tdep (gdbarch)->lbeg_regnum, ®s->lbeg); if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->lend_regnum, + regcache->raw_supply (gdbarch_tdep (gdbarch)->lend_regnum, ®s->lend); if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->lcount_regnum, + regcache->raw_supply (gdbarch_tdep (gdbarch)->lcount_regnum, ®s->lcount); if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->sar_regnum, + regcache->raw_supply (gdbarch_tdep (gdbarch)->sar_regnum, ®s->sar); + if (regnum == gdbarch_tdep (gdbarch)->threadptr_regnum || regnum == -1) + regcache->raw_supply (gdbarch_tdep (gdbarch)->threadptr_regnum, + ®s->threadptr); if (regnum >=gdbarch_tdep (gdbarch)->ar_base && regnum < gdbarch_tdep (gdbarch)->ar_base + gdbarch_tdep (gdbarch)->num_aregs) - regcache_raw_supply (regcache,regnum, + regcache->raw_supply (regnum, ®s->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]); else if (regnum == -1) { for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i) - regcache_raw_supply (regcache, - gdbarch_tdep (gdbarch)->ar_base + i, + regcache->raw_supply (gdbarch_tdep (gdbarch)->ar_base + i, ®s->ar[i]); } + if (regnum >= gdbarch_tdep (gdbarch)->a0_base + && regnum < gdbarch_tdep (gdbarch)->a0_base + C0_NREGS) + regcache->raw_supply (regnum, + ®s->ar[(4 * regs->windowbase + regnum + - gdbarch_tdep (gdbarch)->a0_base) + % gdbarch_tdep (gdbarch)->num_aregs]); + else if (regnum == -1) + { + for (i = 0; i < C0_NREGS; ++i) + regcache->raw_supply (gdbarch_tdep (gdbarch)->a0_base + i, + ®s->ar[(4 * regs->windowbase + i) + % gdbarch_tdep (gdbarch)->num_aregs]); + } } void @@ -185,8 +202,8 @@ supply_fpregset (struct regcache *regcache, static void fetch_gregs (struct regcache *regcache, int regnum) { - int tid = GET_THREAD_ID (inferior_ptid); - const gdb_gregset_t regs; + int tid = regcache->ptid ().lwp (); + gdb_gregset_t regs; int areg; if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0) @@ -204,7 +221,7 @@ fetch_gregs (struct regcache *regcache, int regnum) static void store_gregs (struct regcache *regcache, int regnum) { - int tid = GET_THREAD_ID (inferior_ptid); + int tid = regcache->ptid ().lwp (); gdb_gregset_t regs; int areg; @@ -232,7 +249,7 @@ static int xtreg_high; static void fetch_xtregs (struct regcache *regcache, int regnum) { - int tid = GET_THREAD_ID (inferior_ptid); + int tid = regcache->ptid ().lwp (); const xtensa_regtable_t *ptr; char xtregs [XTENSA_ELF_XTREG_SIZE]; @@ -241,14 +258,13 @@ fetch_xtregs (struct regcache *regcache, int regnum) for (ptr = xtensa_regmap_table; ptr->name; ptr++) if (regnum == ptr->gdb_regnum || regnum == -1) - regcache_raw_supply (regcache, ptr->gdb_regnum, - xtregs + ptr->ptrace_offset); + regcache->raw_supply (ptr->gdb_regnum, xtregs + ptr->ptrace_offset); } static void store_xtregs (struct regcache *regcache, int regnum) { - int tid = GET_THREAD_ID (inferior_ptid); + int tid = regcache->ptid ().lwp (); const xtensa_regtable_t *ptr; char xtregs [XTENSA_ELF_XTREG_SIZE]; @@ -257,15 +273,15 @@ store_xtregs (struct regcache *regcache, int regnum) for (ptr = xtensa_regmap_table; ptr->name; ptr++) if (regnum == ptr->gdb_regnum || regnum == -1) - regcache_raw_collect (regcache, ptr->gdb_regnum, - xtregs + ptr->ptrace_offset); + regcache->raw_collect (ptr->gdb_regnum, xtregs + ptr->ptrace_offset); if (ptrace (PTRACE_SETXTREGS, tid, 0, (long)&xtregs) < 0) perror_with_name (_("Couldn't write extended registers")); } void -xtensa_linux_fetch_inferior_registers (struct regcache *regcache, int regnum) +xtensa_linux_nat_target::fetch_registers (struct regcache *regcache, + int regnum) { if (regnum == -1) { @@ -279,7 +295,8 @@ xtensa_linux_fetch_inferior_registers (struct regcache *regcache, int regnum) } void -xtensa_linux_store_inferior_registers (struct regcache *regcache, int regnum) +xtensa_linux_nat_target::store_registers (struct regcache *regcache, + int regnum) { if (regnum == -1) { @@ -292,12 +309,28 @@ xtensa_linux_store_inferior_registers (struct regcache *regcache, int regnum) store_xtregs (regcache, regnum); } -void _initialize_xtensa_linux_nat (void); +/* Called by libthread_db. */ + +ps_err_e +ps_get_thread_area (struct ps_prochandle *ph, + lwpid_t lwpid, int idx, void **base) +{ + xtensa_elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, lwpid, NULL, ®s) != 0) + return PS_ERR; + + /* IDX is the bias from the thread pointer to the beginning of the + thread descriptor. It has to be subtracted due to implementation + quirks in libthread_db. */ + *base = (void *) ((char *) regs.threadptr - idx); + + return PS_OK; +} void _initialize_xtensa_linux_nat (void) { - struct target_ops *t; const xtensa_regtable_t *ptr; /* Calculate the number range for extended registers. */ @@ -311,12 +344,6 @@ _initialize_xtensa_linux_nat (void) xtreg_high = ptr->gdb_regnum; } - /* Fill in the generic GNU/Linux methods. */ - t = linux_target (); - - /* Add our register access methods. */ - t->to_fetch_registers = xtensa_linux_fetch_inferior_registers; - t->to_store_registers = xtensa_linux_store_inferior_registers; - - linux_nat_add_target (t); + linux_target = &the_xtensa_linux_nat_target; + add_inf_child_target (&the_xtensa_linux_nat_target); }