diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2008-05-03 17:16:44 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2008-05-03 17:16:44 +0000 |
commit | 7284e1bed8f26d644523bcf82dbfc03ff594ff36 (patch) | |
tree | cdf17fc68a1544fbc953e597a1c6746049c940ae /gdb/ppc-linux-tdep.c | |
parent | 82f68b1c00c3b252230770dc0b3178a61c8c949a (diff) | |
download | gdb-7284e1bed8f26d644523bcf82dbfc03ff594ff36.zip gdb-7284e1bed8f26d644523bcf82dbfc03ff594ff36.tar.gz gdb-7284e1bed8f26d644523bcf82dbfc03ff594ff36.tar.bz2 |
ChangeLog:
* Makefile.in (ppc_linux_tdep_h): New macro.
(powerpc_32l_c, powerpc_altivec32_c, powerpc_altivec32l_c): Likewise.
(powerpc_64l_c, powerpc_altivec64_c, powerpc_altivec64l_c): Likewise.
(powerpc_e500l_c): Likewise.
(ppc-linux-nat.o): Update dependencies.
(ppc-linux-tdep.o): Update dependencies.
(rs6000-tdep.o): Update dependencies.
* ppc-tdep.h (ppc_linux_memory_remove_breakpoint): Remove.
(ppc_linux_svr4_fetch_link_map_offsets): Remove.
(ppc_linux_gregset, ppc_linux_fpregset): Move to ppc-linux-tdep.h
(ppc_supply_reg, ppc_collect_reg): Add prototypes.
(tdesc_powerpc_e500): Remove.
* rs6000.c: Include "features/rs6000/powerpc-altivec32.c"
and "features/rs6000/powerpc-altivec64.c".
(ppc_supply_reg, ppc_collect_reg): Make global.
(variants): Use tdesc_powerpc_32 for "powerpc" and
tdesc_powerpc_altivec64 for "powerpc64".
(_initialize_rs6000_tdep): Initialize AltiVec descriptions.
* ppc-linux-tdep.h: New file.
* ppc-linux-tdep.c: Include "ppc-linux-tdep.c".
Include "features/rs6000/powerpc-32l.c".
Include "features/rs6000/powerpc-altivec32l.c".
Include "features/rs6000/powerpc-64l.c".
Include "features/rs6000/powerpc-altivec64l.c".
Include "features/rs6000/powerpc-e500l.c".
(ppc_linux_supply_gregset): New function.
(ppc_linux_collect_gregset): Handle orig_r3 and trap registers.
(ppc32_linux_gregset): Use ppc_linux_supply_gregset.
(ppc64_linux_gregset): Likewise.
(ppc_linux_sigtramp_cache): Handle orig_r3 and trap registers.
(ppc_linux_trap_reg_p): New function.
(ppc_linux_write_pc): New function.
(ppc_linux_core_read_description): New function.
(ppc_linux_init_abi): Install ppc_linux_write_pc and
ppc_linux_core_read_description. Install orig_r3 and trap
registers if present in the target description.
(_initialize_ppc_linux_tdep): Initialize Linux target descriptions.
* ppc-linux-nat.c: Include "ppc-linux-tdep.h".
(PT_ORIG_R3, PT_TRAP): Define if necessary.
(ppc_register_u_addr): Handle orig_r3 and trap registers.
(fetch_ppc_registers): Likewise.
(store_ppc_registers): Likewise.
(store_register): Likewise.
(ppc_linux_read_description): Check whether AltiVec is supported.
Check whether inferior is 32-bit or 64-bit. Return the appropriate
Linux target description.
* features/Makefile (WHICH): Use rs6000/powerpc-32l and
rs6000/powerpc-altivec32l instead of rs6000/powerpc-32.
Use rs6000/powerpc-64l and rs6000/powerpc-altivec64l instead
of rs6000/powerpc-64. Use rs6000/powerpc-e500l instead of
rs6000/powerpc-e500. Update -expedite variables accordingly.
* features/rs6000/power-spe.xml: Use regnum 73 for "acc".
* features/rs6000/powerpc-32.xml: Do not include power-altivec.xml.
* features/rs6000/powerpc-64.xml: Do not include power-altivec.xml.
* features/rs6000/powerpc-e500.c: Regenerate.
* features/rs6000/powerpc-32.c: Regenerate.
* features/rs6000/powerpc-64.c: Regenerate.
* features/rs6000/power-linux.xml: New file.
* features/rs6000/power64-linux.xml: New file.
* features/rs6000/powerpc-32l.xml: New file.
* features/rs6000/powerpc-altivec32l.xml: New file.
* features/rs6000/powerpc-64l.xml: New file.
* features/rs6000/powerpc-altivec64l.xml: New file.
* features/rs6000/powerpc-e500l.xml: New file.
* features/rs6000/powerpc-32l.c: New (generated) file.
* features/rs6000/powerpc-altivec32l.c: New (generated) file.
* features/rs6000/powerpc-64l.c: New (generated) file.
* features/rs6000/powerpc-altivec64l.c: New (generated) file.
* features/rs6000/powerpc-e500l.xml: New (generated) file.
* regformats/reg-ppc.dat: Remove.
* regformats/reg-ppc64.dat: Remove.
* regformats/rs6000/powerpc-32.dat: Remove.
* regformats/rs6000/powerpc-64.dat: Remove.
* regformats/rs6000/powerpc-e500.dat: Remove.
* regformats/rs6000/powerpc-32l.dat: New (generated) file.
* regformats/rs6000/powerpc-altivec32l.dat: New (generated) file.
* regformats/rs6000/powerpc-64l.dat: New (generated) file.
* regformats/rs6000/powerpc-altivec64l.dat: New (generated) file.
* regformats/rs6000/powerpc-e500l.dat: New (generated) file.
gdbserver/ChangeLog:
* configure.srv (powerpc*-*-linux*): Set srv_regobj to
powerpc-32l.o, powerpc-altivec32l.o, powerpc-e500l.o,
powerpc-64l.o, and powerpc-altivec64l.o.
Remove rs6000/powerpc-32.xml, rs6000/powerpc-64.xml, and
rs6000/powerpc-e500.xml; add rs6000/powerpc-32l.xml,
rs6000/powerpc-altivec32l.xml, rs6000/powerpc-e500l.xml,
rs6000/powerpc-64l.xml, rs6000/powerpc-altivec64l.xml,
rs6000/power-linux.xml, and rs6000/power64-linux.xml
to srv_xmlfiles.
* Makefile.in (reg-ppc.o, reg-ppc.c): Remove, replace by ...
(powerpc-32l.o, powerpc-32l.c): ... these new rules.
(powerpc-32.o, powerpc-32.c): Remove, replace by ...
(powerpc-altivec32l.o, powerpc-altivec32l.c): ... these new rules.
(powerpc-e500.o, powerpc-e500.c): Remove, replace by ...
(powerpc-e500l.o, powerpc-e500l.c): ... these new rules.
(reg-ppc64.o, reg-ppc64.c): Remove, replace by ...
(powerpc-64l.o, powerpc-64l.c): ... these new rules.
(powerpc-64.o, powerpc-64.c): Remove, replace by ...
(powerpc-altivec64l.o, powerpc-altivec64l.c): ... these new rules.
(clean): Update.
* linux-ppc-low.c (init_registers_ppc): Remove, replace by ...
(init_registers_powerpc_32l): ... this new prototype.
(init_registers_powerpc_32): Remove, replace by ...
(init_registers_powerpc_altivec32l): ... this new prototype.
(init_registers_powerpc_e500): Remove, replace by ...
(init_registers_powerpc_e500l): ... this new prototype.
(init_registers_ppc64): Remove, replace by ...
(init_registers_powerpc_64l): ... this new prototype.
(init_registers_powerpc_64): Remove, replace by ...
(init_registers_powerpc_altivec64l): ... this new prototype.
(ppc_num_regs): Set to 73.
(PT_ORIG_R3, PT_TRAP): Define if necessary.
(ppc_regmap, ppc_regmap_e500): Add values for orig_r3 and trap.
(ppc_cannot_store_register): Handle orig_r3 and trap.
(ppc_arch_setup): Update init_registers_... calls.
(ppc_fill_gregset): Handle orig_r3 and trap.
* inferiors.c (clear_inferiors): Reset current_inferior.
Diffstat (limited to 'gdb/ppc-linux-tdep.c')
-rw-r--r-- | gdb/ppc-linux-tdep.c | 157 |
1 files changed, 153 insertions, 4 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 44b66ac..2f776f5 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -34,10 +34,17 @@ #include "regset.h" #include "solib-svr4.h" #include "ppc-tdep.h" +#include "ppc-linux-tdep.h" #include "trad-frame.h" #include "frame-unwind.h" #include "tramp-frame.h" +#include "features/rs6000/powerpc-32l.c" +#include "features/rs6000/powerpc-altivec32l.c" +#include "features/rs6000/powerpc-64l.c" +#include "features/rs6000/powerpc-altivec64l.c" +#include "features/rs6000/powerpc-e500l.c" + static CORE_ADDR ppc_linux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { @@ -620,17 +627,60 @@ ppc_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, return addr; } -/* This wrapper clears areas in the linux gregset not written by - ppc_collect_gregset. */ +/* Wrappers to handle Linux-only registers. */ + +static void +ppc_linux_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const struct ppc_reg_offsets *offsets = regset->descr; + + ppc_supply_gregset (regset, regcache, regnum, gregs, len); + + if (ppc_linux_trap_reg_p (get_regcache_arch (regcache))) + { + /* "orig_r3" is stored 2 slots after "pc". */ + if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM) + ppc_supply_reg (regcache, PPC_ORIG_R3_REGNUM, gregs, + offsets->pc_offset + 2 * offsets->gpr_size, + offsets->gpr_size); + + /* "trap" is stored 8 slots after "pc". */ + if (regnum == -1 || regnum == PPC_TRAP_REGNUM) + ppc_supply_reg (regcache, PPC_TRAP_REGNUM, gregs, + offsets->pc_offset + 8 * offsets->gpr_size, + offsets->gpr_size); + } +} static void ppc_linux_collect_gregset (const struct regset *regset, const struct regcache *regcache, int regnum, void *gregs, size_t len) { + const struct ppc_reg_offsets *offsets = regset->descr; + + /* Clear areas in the linux gregset not written elsewhere. */ if (regnum == -1) memset (gregs, 0, len); + ppc_collect_gregset (regset, regcache, regnum, gregs, len); + + if (ppc_linux_trap_reg_p (get_regcache_arch (regcache))) + { + /* "orig_r3" is stored 2 slots after "pc". */ + if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM) + ppc_collect_reg (regcache, PPC_ORIG_R3_REGNUM, gregs, + offsets->pc_offset + 2 * offsets->gpr_size, + offsets->gpr_size); + + /* "trap" is stored 8 slots after "pc". */ + if (regnum == -1 || regnum == PPC_TRAP_REGNUM) + ppc_collect_reg (regcache, PPC_TRAP_REGNUM, gregs, + offsets->pc_offset + 8 * offsets->gpr_size, + offsets->gpr_size); + } } /* Regset descriptions. */ @@ -686,14 +736,14 @@ static const struct ppc_reg_offsets ppc64_linux_reg_offsets = static const struct regset ppc32_linux_gregset = { &ppc32_linux_reg_offsets, - ppc_supply_gregset, + ppc_linux_supply_gregset, ppc_linux_collect_gregset, NULL }; static const struct regset ppc64_linux_gregset = { &ppc64_linux_reg_offsets, - ppc_supply_gregset, + ppc_linux_supply_gregset, ppc_linux_collect_gregset, NULL }; @@ -789,6 +839,14 @@ ppc_linux_sigtramp_cache (struct frame_info *this_frame, trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, gpregs + 38 * tdep->wordsize); + if (ppc_linux_trap_reg_p (gdbarch)) + { + trad_frame_set_reg_addr (this_cache, PPC_ORIG_R3_REGNUM, + gpregs + 34 * tdep->wordsize); + trad_frame_set_reg_addr (this_cache, PPC_TRAP_REGNUM, + gpregs + 40 * tdep->wordsize); + } + if (ppc_floating_point_unit_p (gdbarch)) { /* Floating point registers. */ @@ -895,11 +953,69 @@ static struct tramp_frame ppc64_linux_sighandler_tramp_frame = { ppc64_linux_sighandler_cache_init }; + +/* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable. */ +int +ppc_linux_trap_reg_p (struct gdbarch *gdbarch) +{ + /* If we do not have a target description with registers, then + the special registers will not be included in the register set. */ + if (!tdesc_has_registers (gdbarch_target_desc (gdbarch))) + return 0; + + /* If we do, then it is safe to check the size. */ + return register_size (gdbarch, PPC_ORIG_R3_REGNUM) > 0 + && register_size (gdbarch, PPC_TRAP_REGNUM) > 0; +} + +static void +ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch), pc); + + /* Set special TRAP register to -1 to prevent the kernel from + messing with the PC we just installed, if we happen to be + within an interrupted system call that the kernel wants to + restart. + + Note that after we return from the dummy call, the TRAP and + ORIG_R3 registers will be automatically restored, and the + kernel continues to restart the system call at this point. */ + if (ppc_linux_trap_reg_p (gdbarch)) + regcache_cooked_write_unsigned (regcache, PPC_TRAP_REGNUM, -1); +} + +static const struct target_desc * +ppc_linux_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd) +{ + asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx"); + asection *section = bfd_get_section_by_name (abfd, ".reg"); + if (! section) + return NULL; + + switch (bfd_section_size (abfd, section)) + { + case 48 * 4: + return altivec? tdesc_powerpc_altivec32l : tdesc_powerpc_32l; + + case 48 * 8: + return altivec? tdesc_powerpc_altivec64l : tdesc_powerpc_64l; + + default: + return NULL; + } +} + static void ppc_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info; /* PPC GNU/Linux uses either 64-bit or 128-bit long doubles; where 128-bit, they are IBM long double, not IEEE quad long double as @@ -914,6 +1030,9 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_convert_from_func_ptr_addr (gdbarch, ppc_linux_convert_from_func_ptr_addr); + /* Handle inferior calls during interrupted system calls. */ + set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc); + if (tdep->wordsize == 4) { /* Until November 2001, gcc did not comply with the 32 bit SysV @@ -951,10 +1070,33 @@ ppc_linux_init_abi (struct gdbarch_info info, tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame); } set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section); + set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description); /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); + + if (tdesc_data) + { + const struct tdesc_feature *feature; + + /* If we have target-described registers, then we can safely + reserve a number for PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM + (whether they are described or not). */ + gdb_assert (gdbarch_num_regs (gdbarch) <= PPC_ORIG_R3_REGNUM); + set_gdbarch_num_regs (gdbarch, PPC_TRAP_REGNUM + 1); + + /* If they are present, then assign them to the reserved number. */ + feature = tdesc_find_feature (info.target_desc, + "org.gnu.gdb.power.linux"); + if (feature != NULL) + { + tdesc_numbered_register (feature, tdesc_data, + PPC_ORIG_R3_REGNUM, "orig_r3"); + tdesc_numbered_register (feature, tdesc_data, + PPC_TRAP_REGNUM, "trap"); + } + } } void @@ -968,4 +1110,11 @@ _initialize_ppc_linux_tdep (void) ppc_linux_init_abi); gdbarch_register_osabi (bfd_arch_rs6000, bfd_mach_rs6k, GDB_OSABI_LINUX, ppc_linux_init_abi); + + /* Initialize the Linux target descriptions. */ + initialize_tdesc_powerpc_32l (); + initialize_tdesc_powerpc_altivec32l (); + initialize_tdesc_powerpc_64l (); + initialize_tdesc_powerpc_altivec64l (); + initialize_tdesc_powerpc_e500l (); } |