X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fppc-linux-nat.c;h=7e96032d4c028bc78abe9a90e217b0ff5e4fa780;hb=2e077f5e67aeff78e096a250bd225cd4658a35dc;hp=45c8903ef68d219765d6450ae1b783fe5473a14b;hpb=481695ed5f6e0a8a9c9c50bfac1cdd2b3151e6c9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 45c8903ef6..7e96032d4c 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -1,6 +1,6 @@ /* PPC GNU/Linux native support. - Copyright (C) 1988-2017 Free Software Foundation, Inc. + Copyright (C) 1988-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -18,7 +18,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "observer.h" +#include "observable.h" #include "frame.h" #include "inferior.h" #include "gdbthread.h" @@ -45,6 +45,8 @@ #include "elf/common.h" #include "auxv.h" +#include "arch/ppc-linux-common.h" +#include "arch/ppc-linux-tdesc.h" #include "nat/ppc-linux.h" /* Similarly for the hardware watchpoint support. These requests are used @@ -267,6 +269,60 @@ int have_ptrace_getsetregs = 1; them and gotten an error. */ int have_ptrace_getsetfpregs = 1; +struct ppc_linux_nat_target final : public linux_nat_target +{ + /* Add our register access methods. */ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; + + /* Add our breakpoint/watchpoint methods. */ + int can_use_hw_breakpoint (enum bptype, int, int) override; + + int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) + override; + + int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) + override; + + int region_ok_for_hw_watchpoint (CORE_ADDR, int) override; + + int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type, + struct expression *) override; + + int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type, + struct expression *) override; + + int insert_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type) + override; + + int remove_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type) + override; + + bool stopped_by_watchpoint () override; + + bool stopped_data_address (CORE_ADDR *) override; + + bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override; + + bool can_accel_watchpoint_condition (CORE_ADDR, int, int, struct expression *) + override; + + int masked_watch_num_registers (CORE_ADDR, CORE_ADDR) override; + + int ranged_break_num_registers () override; + + const struct target_desc *read_description () override; + + int auxv_parse (gdb_byte **readptr, + gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) + override; + + /* Override linux_nat_target low methods. */ + void low_new_thread (struct lwp_info *lp) override; +}; + +static ppc_linux_nat_target the_ppc_linux_nat_target; + /* *INDENT-OFF* */ /* registers layout, as presented by the ptrace interface: PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7, @@ -359,7 +415,7 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno) { int ret; gdb_vsxregset_t regs; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); @@ -388,7 +444,7 @@ fetch_altivec_register (struct regcache *regcache, int tid, int regno) int ret; int offset = 0; gdb_vrregset_t regs; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum); @@ -452,7 +508,7 @@ get_spe_registers (int tid, struct gdb_evrregset_t *evrregset) static void fetch_spe_register (struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct gdb_evrregset_t evrregs; @@ -491,7 +547,7 @@ fetch_spe_register (struct regcache *regcache, int tid, int regno) static void fetch_register (struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* This isn't really an address. But ptrace thinks of it as one. */ CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno); @@ -583,7 +639,7 @@ static void supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp) { int i; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); @@ -598,7 +654,7 @@ static void supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp) { int i; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1; int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum); @@ -668,7 +724,7 @@ fetch_altivec_registers (struct regcache *regcache, int tid) static int fetch_all_gp_regs (struct regcache *regcache, int tid) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_gregset_t gregset; @@ -696,7 +752,7 @@ fetch_all_gp_regs (struct regcache *regcache, int tid) static void fetch_gp_regs (struct regcache *regcache, int tid) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; @@ -748,7 +804,7 @@ fetch_all_fp_regs (struct regcache *regcache, int tid) static void fetch_fp_regs (struct regcache *regcache, int tid) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; @@ -767,7 +823,7 @@ static void fetch_ppc_registers (struct regcache *regcache, int tid) { int i; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); fetch_gp_regs (regcache, tid); @@ -806,9 +862,8 @@ fetch_ppc_registers (struct regcache *regcache, int tid) /* Fetch registers from the child process. Fetch all registers if regno == -1, otherwise fetch all general registers or all floating point registers depending upon the value of regno. */ -static void -ppc_linux_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) +void +ppc_linux_nat_target::fetch_registers (struct regcache *regcache, int regno) { pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache)); @@ -824,7 +879,7 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno) { int ret; gdb_vsxregset_t regs; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); @@ -854,7 +909,7 @@ store_altivec_register (const struct regcache *regcache, int tid, int regno) int ret; int offset = 0; gdb_vrregset_t regs; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum); @@ -918,7 +973,7 @@ set_spe_registers (int tid, struct gdb_evrregset_t *evrregset) static void store_spe_register (const struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct gdb_evrregset_t evrregs; @@ -973,7 +1028,7 @@ store_spe_register (const struct regcache *regcache, int tid, int regno) static void store_register (const struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* This isn't really an address. But ptrace thinks of it as one. */ CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno); @@ -1050,7 +1105,7 @@ static void fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp) { int i; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); @@ -1063,7 +1118,7 @@ static void fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp) { int i; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1; int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum); @@ -1139,7 +1194,7 @@ store_altivec_registers (const struct regcache *regcache, int tid) static int store_all_gp_regs (const struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_gregset_t gregset; @@ -1177,7 +1232,7 @@ store_all_gp_regs (const struct regcache *regcache, int tid, int regno) static void store_gp_regs (const struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; @@ -1239,7 +1294,7 @@ store_all_fp_regs (const struct regcache *regcache, int tid, int regno) static void store_fp_regs (const struct regcache *regcache, int tid, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; @@ -1258,7 +1313,7 @@ static void store_ppc_registers (const struct regcache *regcache, int tid) { int i; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); store_gp_regs (regcache, tid, -1); @@ -1300,7 +1355,7 @@ ppc_linux_get_hwcap (void) { CORE_ADDR field; - if (target_auxv_search (¤t_target, AT_HWCAP, &field)) + if (target_auxv_search (target_stack, AT_HWCAP, &field)) return (unsigned long) field; return 0; @@ -1385,9 +1440,8 @@ have_ptrace_hwdebug_interface (void) return have_ptrace_hwdebug_interface; } -static int -ppc_linux_can_use_hw_breakpoint (struct target_ops *self, - enum bptype type, int cnt, int ot) +int +ppc_linux_nat_target::can_use_hw_breakpoint (enum bptype type, int cnt, int ot) { int total_hw_wp, total_hw_bp; @@ -1443,9 +1497,8 @@ ppc_linux_can_use_hw_breakpoint (struct target_ops *self, return 1; } -static int -ppc_linux_region_ok_for_hw_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len) +int +ppc_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) { /* Handle sub-8-byte quantities. */ if (len <= 0) @@ -1541,16 +1594,13 @@ hwdebug_insert_point (struct ppc_hw_breakpoint *b, int tid) { int i; long slot; - struct ppc_hw_breakpoint *p = XNEW (struct ppc_hw_breakpoint); + gdb::unique_xmalloc_ptr p (XDUP (ppc_hw_breakpoint, b)); struct hw_break_tuple *hw_breaks; - struct cleanup *c = make_cleanup (xfree, p); struct thread_points *t; struct hw_break_tuple *tuple; - memcpy (p, b, sizeof (struct ppc_hw_breakpoint)); - errno = 0; - slot = ptrace (PPC_PTRACE_SETHWDEBUG, tid, 0, p); + slot = ptrace (PPC_PTRACE_SETHWDEBUG, tid, 0, p.get ()); if (slot < 0) perror_with_name (_("Unexpected error setting breakpoint or watchpoint")); @@ -1564,13 +1614,11 @@ hwdebug_insert_point (struct ppc_hw_breakpoint *b, int tid) if (hw_breaks[i].hw_break == NULL) { hw_breaks[i].slot = slot; - hw_breaks[i].hw_break = p; + hw_breaks[i].hw_break = p.release (); break; } gdb_assert (i != max_slots_number); - - discard_cleanups (c); } /* This function is a generic wrapper that is responsible for removing a @@ -1608,8 +1656,8 @@ hwdebug_remove_point (struct ppc_hw_breakpoint *b, int tid) /* Return the number of registers needed for a ranged breakpoint. */ -static int -ppc_linux_ranged_break_num_registers (struct target_ops *target) +int +ppc_linux_nat_target::ranged_break_num_registers () { return ((have_ptrace_hwdebug_interface () && hwdebug_info.features & PPC_DEBUG_FEATURE_INSN_BP_RANGE)? @@ -1619,10 +1667,9 @@ ppc_linux_ranged_break_num_registers (struct target_ops *target) /* Insert the hardware breakpoint described by BP_TGT. Returns 0 for success, 1 if hardware breakpoints are not supported or -1 for failure. */ -static int -ppc_linux_insert_hw_breakpoint (struct target_ops *self, - struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) +int +ppc_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { struct lwp_info *lp; struct ppc_hw_breakpoint p; @@ -1656,10 +1703,9 @@ ppc_linux_insert_hw_breakpoint (struct target_ops *self, return 0; } -static int -ppc_linux_remove_hw_breakpoint (struct target_ops *self, - struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) +int +ppc_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { struct lwp_info *lp; struct ppc_hw_breakpoint p; @@ -1713,9 +1759,9 @@ get_trigger_type (enum target_hw_bp_type type) or hw_access for an access watchpoint. Returns 0 on success and throws an error on failure. */ -static int -ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr, - CORE_ADDR mask, enum target_hw_bp_type rw) +int +ppc_linux_nat_target::insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, + target_hw_bp_type rw) { struct lwp_info *lp; struct ppc_hw_breakpoint p; @@ -1741,9 +1787,9 @@ ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr, or hw_access for an access watchpoint. Returns 0 on success and throws an error on failure. */ -static int -ppc_linux_remove_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr, - CORE_ADDR mask, enum target_hw_bp_type rw) +int +ppc_linux_nat_target::remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, + target_hw_bp_type rw) { struct lwp_info *lp; struct ppc_hw_breakpoint p; @@ -1845,10 +1891,9 @@ calculate_dvc (CORE_ADDR addr, int len, CORE_ADDR data_value, other kinds of values which are not acceptable in a condition expression (e.g., lval_computed or lval_internalvar). */ static int -num_memory_accesses (struct value *v) +num_memory_accesses (const std::vector &chain) { int found_memory_cnt = 0; - struct value *head = v; /* The idea here is that evaluating an expression generates a series of values, one holding the value of every subexpression. (The @@ -1865,8 +1910,10 @@ num_memory_accesses (struct value *v) notice that an expression contains an inferior function call. FIXME. */ - for (; v; v = value_next (v)) + for (const value_ref_ptr &iter : chain) { + struct value *v = iter.get (); + /* Constants and values from the history are fine. */ if (VALUE_LVAL (v) == not_lval || deprecated_value_modifiable (v) == 0) continue; @@ -1897,7 +1944,8 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond, CORE_ADDR *data_value, int *len) { int pc = 1, num_accesses_left, num_accesses_right; - struct value *left_val, *right_val, *left_chain, *right_chain; + struct value *left_val, *right_val; + std::vector left_chain, right_chain; if (cond->elts[0].opcode != BINOP_EQUAL) return 0; @@ -1906,22 +1954,13 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond, num_accesses_left = num_memory_accesses (left_chain); if (left_val == NULL || num_accesses_left < 0) - { - free_value_chain (left_chain); - - return 0; - } + return 0; fetch_subexp_value (cond, &pc, &right_val, NULL, &right_chain, 0); num_accesses_right = num_memory_accesses (right_chain); if (right_val == NULL || num_accesses_right < 0) - { - free_value_chain (left_chain); - free_value_chain (right_chain); - - return 0; - } + return 0; if (num_accesses_left == 1 && num_accesses_right == 0 && VALUE_LVAL (left_val) == lval_memory @@ -1944,15 +1983,7 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond, *len = TYPE_LENGTH (check_typedef (value_type (right_val))); } else - { - free_value_chain (left_chain); - free_value_chain (right_chain); - - return 0; - } - - free_value_chain (left_chain); - free_value_chain (right_chain); + return 0; return 1; } @@ -1960,10 +1991,10 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond, /* Return non-zero if the target is capable of using hardware to evaluate the condition expression, thus only triggering the watchpoint when it is true. */ -static int -ppc_linux_can_accel_watchpoint_condition (struct target_ops *self, - CORE_ADDR addr, int len, int rw, - struct expression *cond) +bool +ppc_linux_nat_target::can_accel_watchpoint_condition (CORE_ADDR addr, int len, + int rw, + struct expression *cond) { CORE_ADDR data_value; @@ -2023,10 +2054,10 @@ create_watchpoint_request (struct ppc_hw_breakpoint *p, CORE_ADDR addr, p->addr = (uint64_t) addr; } -static int -ppc_linux_insert_watchpoint (struct target_ops *self, CORE_ADDR addr, int len, - enum target_hw_bp_type type, - struct expression *cond) +int +ppc_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len, + enum target_hw_bp_type type, + struct expression *cond) { struct lwp_info *lp; int ret = -1; @@ -2092,10 +2123,10 @@ ppc_linux_insert_watchpoint (struct target_ops *self, CORE_ADDR addr, int len, return ret; } -static int -ppc_linux_remove_watchpoint (struct target_ops *self, CORE_ADDR addr, int len, - enum target_hw_bp_type type, - struct expression *cond) +int +ppc_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len, + enum target_hw_bp_type type, + struct expression *cond) { struct lwp_info *lp; int ret = -1; @@ -2125,8 +2156,8 @@ ppc_linux_remove_watchpoint (struct target_ops *self, CORE_ADDR addr, int len, return ret; } -static void -ppc_linux_new_thread (struct lwp_info *lp) +void +ppc_linux_nat_target::low_new_thread (struct lwp_info *lp) { int tid = ptid_get_lwp (lp->ptid); @@ -2196,17 +2227,17 @@ ppc_linux_thread_exit (struct thread_info *tp, int silent) xfree (t); } -static int -ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p) +bool +ppc_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p) { siginfo_t siginfo; if (!linux_nat_get_siginfo (inferior_ptid, &siginfo)) - return 0; + return false; if (siginfo.si_signo != SIGTRAP || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */) - return 0; + return false; if (have_ptrace_hwdebug_interface ()) { @@ -2227,25 +2258,25 @@ ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p) if (hw_breaks[i].hw_break && hw_breaks[i].slot == slot && hw_breaks[i].hw_break->trigger_type == PPC_BREAKPOINT_TRIGGER_EXECUTE) - return 0; + return false; } } *addr_p = (CORE_ADDR) (uintptr_t) siginfo.si_addr; - return 1; + return true; } -static int -ppc_linux_stopped_by_watchpoint (struct target_ops *ops) +bool +ppc_linux_nat_target::stopped_by_watchpoint () { CORE_ADDR addr; - return ppc_linux_stopped_data_address (ops, &addr); + return stopped_data_address (&addr); } -static int -ppc_linux_watchpoint_addr_within_range (struct target_ops *target, - CORE_ADDR addr, - CORE_ADDR start, int length) +bool +ppc_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr, + CORE_ADDR start, + int length) { int mask; @@ -2265,9 +2296,8 @@ ppc_linux_watchpoint_addr_within_range (struct target_ops *target, /* Return the number of registers needed for a masked hardware watchpoint. */ -static int -ppc_linux_masked_watch_num_registers (struct target_ops *target, - CORE_ADDR addr, CORE_ADDR mask) +int +ppc_linux_nat_target::masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask) { if (!have_ptrace_hwdebug_interface () || (hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_MASK) == 0) @@ -2283,9 +2313,8 @@ ppc_linux_masked_watch_num_registers (struct target_ops *target, return 2; } -static void -ppc_linux_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) +void +ppc_linux_nat_target::store_registers (struct regcache *regcache, int regno) { pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache)); @@ -2339,34 +2368,17 @@ fill_fpregset (const struct regcache *regcache, fpregsetp, sizeof (*fpregsetp)); } -static int -ppc_linux_target_wordsize (void) +int +ppc_linux_nat_target::auxv_parse (gdb_byte **readptr, + gdb_byte *endptr, CORE_ADDR *typep, + CORE_ADDR *valp) { - int wordsize = 4; - - /* Check for 64-bit inferior process. This is the case when the host is - 64-bit, and in addition the top bit of the MSR register is set. */ -#ifdef __powerpc64__ - long msr; - int tid = ptid_get_lwp (inferior_ptid); if (tid == 0) tid = ptid_get_pid (inferior_ptid); - errno = 0; - msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0); - if (errno == 0 && ppc64_64bit_inferior_p (msr)) - wordsize = 8; -#endif - - return wordsize; -} + int sizeof_auxv_field = ppc_linux_target_wordsize (tid); -static int -ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr, - gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) -{ - int sizeof_auxv_field = ppc_linux_target_wordsize (); enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); gdb_byte *ptr = *readptr; @@ -2385,14 +2397,9 @@ ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr, return 1; } -static const struct target_desc * -ppc_linux_read_description (struct target_ops *ops) +const struct target_desc * +ppc_linux_nat_target::read_description () { - int altivec = 0; - int vsx = 0; - int isa205 = 0; - int cell = 0; - int tid = ptid_get_lwp (inferior_ptid); if (tid == 0) tid = ptid_get_pid (inferior_ptid); @@ -2410,13 +2417,19 @@ ppc_linux_read_description (struct target_ops *ops) perror_with_name (_("Unable to fetch SPE registers")); } + struct ppc_linux_features features = ppc_linux_no_features; + + features.wordsize = ppc_linux_target_wordsize (tid); + + unsigned long hwcap = ppc_linux_get_hwcap (); + if (have_ptrace_getsetvsxregs - && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_VSX)) + && (hwcap & PPC_FEATURE_HAS_VSX)) { gdb_vsxregset_t vsxregset; if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0) - vsx = 1; + features.vsx = true; /* EIO means that the PTRACE_GETVSXREGS request isn't supported. Anything else needs to be reported. */ @@ -2425,12 +2438,12 @@ ppc_linux_read_description (struct target_ops *ops) } if (have_ptrace_getvrregs - && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_ALTIVEC)) + && (hwcap & PPC_FEATURE_HAS_ALTIVEC)) { gdb_vrregset_t vrregset; if (ptrace (PTRACE_GETVRREGS, tid, 0, &vrregset) >= 0) - altivec = 1; + features.altivec = true; /* EIO means that the PTRACE_GETVRREGS request isn't supported. Anything else needs to be reported. */ @@ -2438,76 +2451,21 @@ ppc_linux_read_description (struct target_ops *ops) perror_with_name (_("Unable to fetch AltiVec registers")); } - /* Power ISA 2.05 (implemented by Power 6 and newer processors) increases - the FPSCR from 32 bits to 64 bits. Even though Power 7 supports this - ISA version, it doesn't have PPC_FEATURE_ARCH_2_05 set, only - PPC_FEATURE_ARCH_2_06. Since for now the only bits used in the higher - half of the register are for Decimal Floating Point, we check if that - feature is available to decide the size of the FPSCR. */ - if (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_DFP) - isa205 = 1; - - if (ppc_linux_get_hwcap () & PPC_FEATURE_CELL) - cell = 1; - - if (ppc_linux_target_wordsize () == 8) - { - if (cell) - return tdesc_powerpc_cell64l; - else if (vsx) - return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l; - else if (altivec) - return isa205 - ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l; - - return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l; - } + if (hwcap & PPC_FEATURE_CELL) + features.cell = true; - if (cell) - return tdesc_powerpc_cell32l; - else if (vsx) - return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l; - else if (altivec) - return isa205? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l; + features.isa205 = ppc_linux_has_isa205 (hwcap); - return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l; + return ppc_linux_match_description (features); } void _initialize_ppc_linux_nat (void) { - struct target_ops *t; - - /* Fill in the generic GNU/Linux methods. */ - t = linux_target (); + linux_target = &the_ppc_linux_nat_target; - /* Add our register access methods. */ - t->to_fetch_registers = ppc_linux_fetch_inferior_registers; - t->to_store_registers = ppc_linux_store_inferior_registers; - - /* Add our breakpoint/watchpoint methods. */ - t->to_can_use_hw_breakpoint = ppc_linux_can_use_hw_breakpoint; - t->to_insert_hw_breakpoint = ppc_linux_insert_hw_breakpoint; - t->to_remove_hw_breakpoint = ppc_linux_remove_hw_breakpoint; - t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint; - t->to_insert_watchpoint = ppc_linux_insert_watchpoint; - t->to_remove_watchpoint = ppc_linux_remove_watchpoint; - t->to_insert_mask_watchpoint = ppc_linux_insert_mask_watchpoint; - t->to_remove_mask_watchpoint = ppc_linux_remove_mask_watchpoint; - t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint; - t->to_stopped_data_address = ppc_linux_stopped_data_address; - t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range; - t->to_can_accel_watchpoint_condition - = ppc_linux_can_accel_watchpoint_condition; - t->to_masked_watch_num_registers = ppc_linux_masked_watch_num_registers; - t->to_ranged_break_num_registers = ppc_linux_ranged_break_num_registers; - - t->to_read_description = ppc_linux_read_description; - t->to_auxv_parse = ppc_linux_auxv_parse; - - observer_attach_thread_exit (ppc_linux_thread_exit); + gdb::observers::thread_exit.attach (ppc_linux_thread_exit); /* Register the target. */ - linux_nat_add_target (t); - linux_nat_set_new_thread (t, ppc_linux_new_thread); + add_inf_child_target (linux_target); }