diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 37c7b8b61e..6a581df8b7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,55 @@ +2000-07-31 Kevin Buettner + + * ppc-tdep.h: New file. + * Makefile.in (ppc-linux-tdep.o, rs6000-tdep.o): Add ppc-tdep.h + as a dependency. + * ppc-linux-tdep.c, rs6000-tdep.c (ppc-tdep.h): Include. + + * ppc-linux-tdep.c (ppc_linux_at_sigtramp_return_path): Made static. + + * rs6000-tdep.c (elf-bfd.h): Include. + (gdbarch_tdep): Add field osabi to this struct. + (rs6000_init_extra_frame_info, rs6000_frame_init_saved_regs, + rs6000_frameless_function_invocation, rs6000_frame_saved_pc, + rs6000_frame_chain): No longer static. + (process_note_abi_tag_sections, get_elfosabi): New static + functions. + (rs6000_gdbarch_init): Revised to accomodate ELF executables; + also use Linux specific methods when the target is Linux. + + * config/powerpc/aix.mt, config/powerpc/cygwin.mt, + config/powerpc/macos.mt, config/powerpc/nbsd.mt, + config/powerpc/ppc-eabi.mt, config/powerpc/ppc-nw.mt, + config/powerpc/ppc-sim.mt, config/powerpc/ppcle-eabi.mt, + config/powerpc/ppcle-sim.mt, config/powerpc/solaris.mt, + config/powerpc/vxworks.mt, config/rs6000/aix4.mt, + config/rs6000/rs6000.mt, config/rs6000/rs6000lynx.mt + (TDEPFILES): Add ppc-linux-tdep.o. + + * config/tm-linux.h (SIGCONTEXT_PC_OFFSET, FRAME_SAVED_PC, + INIT_EXTRA_FRAME_INFO, FRAMELESS_FUNCTION_INVOCATION, + FRAME_INIT_SAVED_REGS, FRAME_CHAIN, PUSH_ARGUMENTS, + MEMORY_REMOVE_BREAKPOINT: Removed defines. + (ppc_linux_frame_saved_pc, ppc_linux_init_extra_frame_info, + ppc_linux_frameless_function_invocation, + ppc_linux_frame_init_saved_regs, ppc_linux_frame_chain, + ppc_sysv_abi_push_arguments, ppc_linux_memory_remove_breakpoint): + Removed declarations. + (CANNOT_FETCH_REGISTER, CANNOT_STORE_REGISTER): Disabled. + + * dink32-rom.c (dink32_regnames): Make array size implicit. + + * ppc-bdm.h (ppc-tdep.h): Include. + + * rs6000-tdep.c, ppc-linux-tdep.c, ppc-bdm.h, ppc-tdep.h + (GP0_REGNUM, TOC_REGNUM, PS_REGNUM, CR_REGNUM, LR_REGNUM, + CTR_REGNUM, XER_REGNUM, MQ_REGNUM): Add PPC_ prefix. + + From Nick Duffek: + * ppc-tdep.h (ppc_linux_frame_saved_pc, rs6000_frame_saved_pc): + Change return type to CORE_ADDR. + * ppc-linux-tdep.c (ppc_linux_frame_saved_pc): Likewise. + 2000-07-31 Elena Zannoni * remote-e7000.c (e7000_start_remote): Use void *, not char * as diff --git a/gdb/Makefile.in b/gdb/Makefile.in index e6b717df7d..9be5d368ae 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1627,7 +1627,7 @@ ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(gdbcore_h) $(frame_h) \ $(inferior_h) target.h ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \ - target.h + target.h ppc-tdep.h ppcbug-rom.o: ppcbug-rom.c monitor.h $(bfd_h) gdb_wait.h $(defs_h) $(gdbcmd_h) \ $(inferior_h) target.h serial.h terminal.h @@ -1769,7 +1769,7 @@ rs6000-nat.o: rs6000-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h \ xcoffsolib.h rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \ - target.h xcoffsolib.h + target.h xcoffsolib.h ppc-tdep.h scm-exp.o: $(defs_h) $(value_h) parser-defs.h language.h c-lang.h \ scm-lang.h scm-tags.h diff --git a/gdb/config/powerpc/aix.mt b/gdb/config/powerpc/aix.mt index 6d03b7de26..38436ee89a 100644 --- a/gdb/config/powerpc/aix.mt +++ b/gdb/config/powerpc/aix.mt @@ -1,3 +1,3 @@ # Target: PowerPC running AIX -TDEPFILES= rs6000-tdep.o xcoffsolib.o +TDEPFILES= rs6000-tdep.o xcoffsolib.o ppc-linux-tdep.o TM_FILE= tm-ppc-aix.h diff --git a/gdb/config/powerpc/cygwin.mt b/gdb/config/powerpc/cygwin.mt index b86b2afa28..13a60f1e1f 100644 --- a/gdb/config/powerpc/cygwin.mt +++ b/gdb/config/powerpc/cygwin.mt @@ -1,5 +1,5 @@ # Target: Powerpc running cygnus's unix api over win32 -TDEPFILES= rs6000-tdep.o +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o TM_FILE= tm-cygwin.h diff --git a/gdb/config/powerpc/macos.mt b/gdb/config/powerpc/macos.mt index 07ad0d2208..061d9d612c 100644 --- a/gdb/config/powerpc/macos.mt +++ b/gdb/config/powerpc/macos.mt @@ -1,3 +1,3 @@ # Target: PowerMac (PowerPC running MacOS) -TDEPFILES= rs6000-tdep.o xcoffread.o +TDEPFILES= rs6000-tdep.o xcoffread.o ppc-linux-tdep.o TM_FILE= tm-macos.h diff --git a/gdb/config/powerpc/nbsd.mt b/gdb/config/powerpc/nbsd.mt index 2173f65008..7a32fd2db4 100644 --- a/gdb/config/powerpc/nbsd.mt +++ b/gdb/config/powerpc/nbsd.mt @@ -1,5 +1,5 @@ # Target: PowerPC, running NetBSD -TDEPFILES= rs6000-tdep.o +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o TM_FILE= tm-nbsd.h GDBSERVER_DEPFILES= low-nbsd.o diff --git a/gdb/config/powerpc/ppc-eabi.mt b/gdb/config/powerpc/ppc-eabi.mt index c4e21c8177..a142c86dc5 100644 --- a/gdb/config/powerpc/ppc-eabi.mt +++ b/gdb/config/powerpc/ppc-eabi.mt @@ -1,3 +1,3 @@ # Target: PowerPC running eabi -TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o +TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o ppc-linux-tdep.o TM_FILE= tm-ppc-eabi.h diff --git a/gdb/config/powerpc/ppc-nw.mt b/gdb/config/powerpc/ppc-nw.mt index 0eaa23d55b..3601b4e8fa 100644 --- a/gdb/config/powerpc/ppc-nw.mt +++ b/gdb/config/powerpc/ppc-nw.mt @@ -1,3 +1,3 @@ # Target: PowerPC running Netware -TDEPFILES= rs6000-tdep.o +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o TM_FILE= tm-ppc-nw.h diff --git a/gdb/config/powerpc/ppc-sim.mt b/gdb/config/powerpc/ppc-sim.mt index c73fef2885..a798d10a64 100644 --- a/gdb/config/powerpc/ppc-sim.mt +++ b/gdb/config/powerpc/ppc-sim.mt @@ -1,5 +1,5 @@ # Target: PowerPC running eabi and including the simulator -TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o +TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o ppc-linux-tdep.o TM_FILE= tm-ppc-eabi.h SIM_OBS = remote-sim.o diff --git a/gdb/config/powerpc/ppcle-eabi.mt b/gdb/config/powerpc/ppcle-eabi.mt index b336a111ce..6de3f1d98f 100644 --- a/gdb/config/powerpc/ppcle-eabi.mt +++ b/gdb/config/powerpc/ppcle-eabi.mt @@ -1,3 +1,3 @@ # Target: PowerPC running eabi in little endian mode -TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o +TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o ppc-linux-tdep.o TM_FILE= tm-ppcle-eabi.h diff --git a/gdb/config/powerpc/ppcle-sim.mt b/gdb/config/powerpc/ppcle-sim.mt index f08dafe53a..401a809586 100644 --- a/gdb/config/powerpc/ppcle-sim.mt +++ b/gdb/config/powerpc/ppcle-sim.mt @@ -1,5 +1,5 @@ # Target: PowerPC running eabi in little endian mode under the simulator -TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o +TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o ppc-linux-tdep.o TM_FILE= tm-ppcle-eabi.h SIM_OBS = remote-sim.o diff --git a/gdb/config/powerpc/solaris.mt b/gdb/config/powerpc/solaris.mt index a6e421e7e0..a18ba52ca8 100644 --- a/gdb/config/powerpc/solaris.mt +++ b/gdb/config/powerpc/solaris.mt @@ -1,3 +1,3 @@ # Target: PowerPC, running Solaris 2 -TDEPFILES= rs6000-tdep.o +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o TM_FILE= tm-solaris.h diff --git a/gdb/config/powerpc/tm-linux.h b/gdb/config/powerpc/tm-linux.h index b1abb0ee8b..99d4c962fe 100644 --- a/gdb/config/powerpc/tm-linux.h +++ b/gdb/config/powerpc/tm-linux.h @@ -42,9 +42,6 @@ extern int at_subroutine_call_instruction_target(); in symfile.c) */ #undef IBM6000_TARGET -/* Offset to saved PC in sigcontext, from . */ -#define SIGCONTEXT_PC_OFFSET 184 - extern CORE_ADDR ppc_linux_skip_trampoline_code (CORE_ADDR pc); #undef SKIP_TRAMPOLINE_CODE #define SKIP_TRAMPOLINE_CODE(pc) ppc_linux_skip_trampoline_code (pc) @@ -53,36 +50,10 @@ extern int ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name); #undef IN_SIGTRAMP #define IN_SIGTRAMP(pc,func_name) ppc_linux_in_sigtramp (pc,func_name) -extern unsigned long ppc_linux_frame_saved_pc (struct frame_info *); -#undef FRAME_SAVED_PC -#define FRAME_SAVED_PC(FRAME) ppc_linux_frame_saved_pc (FRAME) - -extern void ppc_linux_init_extra_frame_info (int fromleaf, struct frame_info *); -#undef INIT_EXTRA_FRAME_INFO -#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \ - ppc_linux_init_extra_frame_info (fromleaf, fi) - -extern int ppc_linux_frameless_function_invocation (struct frame_info *); -#undef FRAMELESS_FUNCTION_INVOCATION -#define FRAMELESS_FUNCTION_INVOCATION(FI) \ - (ppc_linux_frameless_function_invocation (FI)) - -extern void ppc_linux_frame_init_saved_regs (struct frame_info *); -#undef FRAME_INIT_SAVED_REGS -#define FRAME_INIT_SAVED_REGS(FI) ppc_linux_frame_init_saved_regs (FI) - -CORE_ADDR ppc_linux_frame_chain (struct frame_info *); -#undef FRAME_CHAIN -#define FRAME_CHAIN(thisframe) ppc_linux_frame_chain (thisframe) - -CORE_ADDR ppc_sysv_abi_push_arguments (int, struct value **, CORE_ADDR, int, - CORE_ADDR); -#undef PUSH_ARGUMENTS -#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \ - (ppc_sysv_abi_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))) - +#if 0 #define CANNOT_FETCH_REGISTER(regno) ((regno) >= MQ_REGNUM) #define CANNOT_STORE_REGISTER(regno) ((regno) >= MQ_REGNUM) +#endif /* Linux doesn't use the PowerOpen ABI for function pointer representation */ #undef CONVERT_FROM_FUNC_PTR_ADDR @@ -94,13 +65,6 @@ CORE_ADDR ppc_sysv_abi_push_arguments (int, struct value **, CORE_ADDR, int, #define PROLOGUE_FIRSTLINE_OVERLAP #endif -/* Needed to handled the self-modifying code situation due to the dynamic - linker. */ -int ppc_linux_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache); -#undef MEMORY_REMOVE_BREAKPOINT -#define MEMORY_REMOVE_BREAKPOINT(addr, contents_cache) \ - ppc_linux_memory_remove_breakpoint(addr, contents_cache) - /* N_FUN symbols in shared libaries have 0 for their values and need to be relocated. */ #define SOFUN_ADDRESS_MAYBE_MISSING diff --git a/gdb/config/powerpc/vxworks.mt b/gdb/config/powerpc/vxworks.mt index 1c71413bb0..11d8ef2a8a 100644 --- a/gdb/config/powerpc/vxworks.mt +++ b/gdb/config/powerpc/vxworks.mt @@ -1,3 +1,3 @@ # Target: Powerpc running VxWorks -TDEPFILES= rs6000-tdep.o +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o TM_FILE= tm-vxworks.h diff --git a/gdb/config/rs6000/aix4.mt b/gdb/config/rs6000/aix4.mt index f213f0f6f2..d602415847 100644 --- a/gdb/config/rs6000/aix4.mt +++ b/gdb/config/rs6000/aix4.mt @@ -1,3 +1,3 @@ # Target: IBM RS/6000 running AIX4 -TDEPFILES= rs6000-tdep.o xcoffsolib.o xcoffread.o +TDEPFILES= rs6000-tdep.o xcoffsolib.o xcoffread.o ppc-linux-tdep.o TM_FILE= tm-rs6000-aix4.h diff --git a/gdb/config/rs6000/rs6000.mt b/gdb/config/rs6000/rs6000.mt index a2294b2c55..941ad328aa 100644 --- a/gdb/config/rs6000/rs6000.mt +++ b/gdb/config/rs6000/rs6000.mt @@ -1,3 +1,3 @@ # Target: IBM RS/6000 running AIX -TDEPFILES= rs6000-tdep.o xcoffsolib.o xcoffread.o +TDEPFILES= rs6000-tdep.o xcoffsolib.o xcoffread.o ppc-linux-tdep.o TM_FILE= tm-rs6000.h diff --git a/gdb/config/rs6000/rs6000lynx.mt b/gdb/config/rs6000/rs6000lynx.mt index 978030c539..fae6d8c570 100644 --- a/gdb/config/rs6000/rs6000lynx.mt +++ b/gdb/config/rs6000/rs6000lynx.mt @@ -1,3 +1,3 @@ # Target: IBM RS6000 running LynxOS -TDEPFILES= coff-solib.o rs6000-tdep.o +TDEPFILES= coff-solib.o rs6000-tdep.o ppc-linux-tdep.o TM_FILE= tm-rs6000ly.h diff --git a/gdb/dink32-rom.c b/gdb/dink32-rom.c index 059a5b69ce..2ad9c6153d 100644 --- a/gdb/dink32-rom.c +++ b/gdb/dink32-rom.c @@ -115,7 +115,7 @@ dink32_load (struct monitor_ops *monops, char *filename, int from_tty) different names than GDB does, and don't support all the registers either. */ -static char *dink32_regnames[NUM_REGS] = +static char *dink32_regnames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", diff --git a/gdb/ppc-bdm.c b/gdb/ppc-bdm.c index 1cd0237fbf..5b8877f845 100644 --- a/gdb/ppc-bdm.c +++ b/gdb/ppc-bdm.c @@ -36,6 +36,7 @@ #include #include "serial.h" #include "ocd.h" +#include "ppc-tdep.h" static void bdm_ppc_open (char *name, int from_tty); @@ -198,7 +199,7 @@ bdm_ppc_fetch_registers (int regno) /* printf("Asking for register %d\n", first_regno); */ /* if asking for an invalid register */ - if ((first_regno == MQ_REGNUM) || + if ((first_regno == PPC_MQ_REGNUM) || ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM))) { /* printf("invalid reg request!\n"); */ @@ -287,14 +288,14 @@ bdm_ppc_store_registers (int regno) /* only attempt to write if it's a valid ppc 8xx register */ /* (need to avoid FP regs and MQ reg) */ - if ((i != MQ_REGNUM) && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM))) + if ((i != PPC_MQ_REGNUM) && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM))) { /* printf("write valid reg %d\n", bdm_regno); */ ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4); } /* - else if (i == MQ_REGNUM) - printf("don't write invalid reg %d (MQ_REGNUM)\n", bdm_regno); + else if (i == PPC_MQ_REGNUM) + printf("don't write invalid reg %d (PPC_MQ_REGNUM)\n", bdm_regno); else printf("don't write invalid reg %d\n", bdm_regno); */ diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 55ab716c21..624d1d7368 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -29,6 +29,8 @@ #include "symfile.h" #include "objfiles.h" +#include "ppc-tdep.h" + /* The following two instructions are used in the signal trampoline code on linux/ppc */ #define INSTR_LI_R0_0x7777 0x38007777 @@ -95,7 +97,7 @@ #define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31) #define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1) -int ppc_linux_at_sigtramp_return_path (CORE_ADDR pc); +static int ppc_linux_at_sigtramp_return_path (CORE_ADDR pc); /* Determine if pc is in a signal trampoline... @@ -150,7 +152,7 @@ ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name) char buf[4]; CORE_ADDR handler; - lr = read_register (LR_REGNUM); + lr = read_register (PPC_LR_REGNUM); if (!ppc_linux_at_sigtramp_return_path (lr)) return 0; @@ -177,7 +179,7 @@ ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name) * instructions. It'd be faster though if we could find a way to do this * via some simple address comparisons. */ -int +static int ppc_linux_at_sigtramp_return_path (CORE_ADDR pc) { char buf[12]; @@ -308,7 +310,7 @@ ppc_linux_skip_trampoline_code (CORE_ADDR pc) /* The rs6000 version of FRAME_SAVED_PC will almost work for us. The signal handler details are different, so we'll handle those here and call the rs6000 version to do the rest. */ -unsigned long +CORE_ADDR ppc_linux_frame_saved_pc (struct frame_info *fi) { if (fi->signal_handler_caller) @@ -372,14 +374,14 @@ ppc_linux_frame_init_saved_regs (struct frame_info *fi) regs_addr = read_memory_integer (fi->frame + PPC_LINUX_REGS_PTR_OFFSET, 4); fi->saved_regs[PC_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_NIP; - fi->saved_regs[PS_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MSR; - fi->saved_regs[CR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CCR; - fi->saved_regs[LR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_LNK; - fi->saved_regs[CTR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CTR; - fi->saved_regs[XER_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_XER; - fi->saved_regs[MQ_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MQ; + fi->saved_regs[PPC_PS_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MSR; + fi->saved_regs[PPC_CR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CCR; + fi->saved_regs[PPC_LR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_LNK; + fi->saved_regs[PPC_CTR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CTR; + fi->saved_regs[PPC_XER_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_XER; + fi->saved_regs[PPC_MQ_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MQ; for (i = 0; i < 32; i++) - fi->saved_regs[GP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_R0 + 4 * i; + fi->saved_regs[PPC_GP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_R0 + 4 * i; for (i = 0; i < 32; i++) fi->saved_regs[FP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_FPR0 + 8 * i; } diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h new file mode 100644 index 0000000000..c22ec13bbe --- /dev/null +++ b/gdb/ppc-tdep.h @@ -0,0 +1,49 @@ +/* Target-dependent code for GDB, the GNU debugger. + Copyright 2000 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* From ppc-linux-tdep.c... */ +CORE_ADDR ppc_linux_frame_saved_pc (struct frame_info *fi); +void ppc_linux_init_extra_frame_info (int fromleaf, struct frame_info *); +int ppc_linux_frameless_function_invocation (struct frame_info *); +void ppc_linux_frame_init_saved_regs (struct frame_info *); +CORE_ADDR ppc_linux_frame_chain (struct frame_info *); +CORE_ADDR ppc_sysv_abi_push_arguments (int, value_ptr *, CORE_ADDR, int, + CORE_ADDR); +int ppc_linux_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache); + + +/* From rs6000-tdep.c... */ +CORE_ADDR rs6000_frame_saved_pc (struct frame_info *fi); +void rs6000_init_extra_frame_info (int fromleaf, struct frame_info *); +int rs6000_frameless_function_invocation (struct frame_info *); +void rs6000_frame_init_saved_regs (struct frame_info *); +CORE_ADDR rs6000_frame_chain (struct frame_info *); + +/* Some important register numbers. */ + +#define PPC_GP0_REGNUM 0 /* GPR register 0 */ +#define PPC_TOC_REGNUM 2 /* TOC register */ +#define PPC_PS_REGNUM 65 /* Processor (or machine) status (%msr) */ +#define PPC_CR_REGNUM 66 /* Condition register */ +#define PPC_LR_REGNUM 67 /* Link register */ +#define PPC_CTR_REGNUM 68 /* Count register */ +#define PPC_XER_REGNUM 69 /* Integer exception register */ +#define PPC_MQ_REGNUM 70 /* Multiply/Divide extension register */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index fbcc2042af..2c9e134469 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -35,15 +35,9 @@ #include "coff/internal.h" /* for libcoff.h */ #include "bfd/libcoff.h" /* for xcoff_data */ -/* Some important register numbers. Keep these in the same order as in - /usr/mstsave.h `mstsave' structure, for easier processing. */ +#include "elf-bfd.h" -#define GP0_REGNUM 0 /* GPR register 0 */ -#define TOC_REGNUM 2 /* TOC register */ -#define PS_REGNUM 65 /* Processor (or machine) status (%msr) */ -#define CR_REGNUM 66 /* Condition register */ -#define LR_REGNUM 67 /* Link register */ -#define CTR_REGNUM 68 /* Count register */ +#include "ppc-tdep.h" /* If the kernel has to deliver a signal, it pushes a sigcontext structure on the stack and then calls the signal handler, passing @@ -89,6 +83,7 @@ struct reg struct gdbarch_tdep { int wordsize; /* size in bytes of fixed-point word */ + int osabi; /* OS / ABI from ELF header */ int *regoff; /* byte offsets in register arrays */ const struct reg *regs; /* from current variant */ }; @@ -157,7 +152,7 @@ struct frame_extra_info CORE_ADDR initial_sp; /* initial stack pointer. */ }; -static void +void rs6000_init_extra_frame_info (int fromleaf, struct frame_info *fi) { fi->extra_info = (struct frame_extra_info *) @@ -182,7 +177,7 @@ rs6000_init_extra_frame_info (int fromleaf, struct frame_info *fi) not sure if it will be needed. The following function takes care of gpr's and fpr's only. */ -static void +void rs6000_frame_init_saved_regs (struct frame_info *fi) { frame_get_saved_regs (fi, NULL); @@ -205,7 +200,7 @@ rs6000_frame_args_address (struct frame_info *fi) static CORE_ADDR rs6000_saved_pc_after_call (struct frame_info *fi) { - return read_register (LR_REGNUM); + return read_register (PPC_LR_REGNUM); } /* Calculate the destination of a branch/jump. Return -1 if not a branch. */ @@ -243,7 +238,7 @@ branch_dest (int opcode, int instr, CORE_ADDR pc, CORE_ADDR safety) if (ext_op == 16) /* br conditional register */ { - dest = read_register (LR_REGNUM) & ~3; + dest = read_register (PPC_LR_REGNUM) & ~3; /* If we are about to return from a signal handler, dest is something like 0x3c90. The current frame is a signal handler @@ -262,13 +257,13 @@ branch_dest (int opcode, int instr, CORE_ADDR pc, CORE_ADDR safety) else if (ext_op == 528) /* br cond to count reg */ { - dest = read_register (CTR_REGNUM) & ~3; + dest = read_register (PPC_CTR_REGNUM) & ~3; /* If we are about to execute a system call, dest is something like 0x22fc or 0x3b00. Upon completion the system call will return to the address in the link register. */ if (dest < TEXT_SEGMENT_BASE) - dest = read_register (LR_REGNUM) & ~3; + dest = read_register (PPC_LR_REGNUM) & ~3; } else return -1; @@ -715,7 +710,7 @@ rs6000_pop_frame (void) else prev_sp = read_memory_addr (sp, wordsize); if (fdata.lr_offset == 0) - lr = read_register (LR_REGNUM); + lr = read_register (PPC_LR_REGNUM); else lr = read_memory_addr (prev_sp + fdata.lr_offset, wordsize); @@ -766,7 +761,7 @@ rs6000_fix_call_dummy (char *dummyname, CORE_ADDR pc, CORE_ADDR fun, if (rs6000_find_toc_address_hook != NULL) { CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (fun); - write_register (TOC_REGNUM, tocvalue); + write_register (PPC_TOC_REGNUM, tocvalue); } } @@ -989,7 +984,7 @@ ran_out_of_registers_for_arguments: static CORE_ADDR ppc_push_return_address (CORE_ADDR pc, CORE_ADDR sp) { - write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ()); + write_register (PPC_LR_REGNUM, CALL_DUMMY_ADDRESS ()); return sp; } @@ -1085,7 +1080,7 @@ rs6000_skip_trampoline_code (CORE_ADDR pc) /* Determines whether the function FI has a frame on the stack or not. */ -static int +int rs6000_frameless_function_invocation (struct frame_info *fi) { CORE_ADDR func_start; @@ -1119,7 +1114,7 @@ rs6000_frameless_function_invocation (struct frame_info *fi) /* Return the PC saved in a frame */ -static CORE_ADDR +CORE_ADDR rs6000_frame_saved_pc (struct frame_info *fi) { CORE_ADDR func_start; @@ -1152,7 +1147,7 @@ rs6000_frame_saved_pc (struct frame_info *fi) } if (fdata.lr_offset == 0) - return read_register (LR_REGNUM); + return read_register (PPC_LR_REGNUM); return read_memory_addr (FRAME_CHAIN (fi) + fdata.lr_offset, wordsize); } @@ -1223,12 +1218,12 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap) /* If != 0, fdatap->cr_offset is the offset from the frame that holds the CR. */ if (fdatap->cr_offset != 0) - fi->saved_regs[CR_REGNUM] = frame_addr + fdatap->cr_offset; + fi->saved_regs[PPC_CR_REGNUM] = frame_addr + fdatap->cr_offset; /* If != 0, fdatap->lr_offset is the offset from the frame that holds the LR. */ if (fdatap->lr_offset != 0) - fi->saved_regs[LR_REGNUM] = frame_addr + fdatap->lr_offset; + fi->saved_regs[PPC_LR_REGNUM] = frame_addr + fdatap->lr_offset; } /* Return the address of a frame. This is the inital %sp value when the frame @@ -1313,7 +1308,7 @@ frame_initial_stack_address (struct frame_info *fi) /* In the case of the RS/6000, the frame's nominal address is the address of a 4-byte word containing the calling frame's address. */ -static CORE_ADDR +CORE_ADDR rs6000_frame_chain (struct frame_info *thisframe) { CORE_ADDR fp, fpp, lr; @@ -1338,7 +1333,7 @@ rs6000_frame_chain (struct frame_info *thisframe) else fp = read_memory_addr ((thisframe)->frame, wordsize); - lr = read_register (LR_REGNUM); + lr = read_register (PPC_LR_REGNUM); if (lr == entry_point_address ()) if (fp != 0 && (fpp = read_memory_addr (fp, wordsize)) != 0) if (PC_IN_CALL_DUMMY (lr, fpp, fpp)) @@ -1500,7 +1495,7 @@ rs6000_store_return_value (struct type *type, char *valbuf) TYPE_LENGTH (type)); else /* Everything else is returned in GPR3 and up. */ - write_register_bytes (REGISTER_BYTE (GP0_REGNUM + 3), valbuf, + write_register_bytes (REGISTER_BYTE (PPC_GP0_REGNUM + 3), valbuf, TYPE_LENGTH (type)); } @@ -1909,6 +1904,84 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach) return NULL; } + + + +static void +process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj) +{ + int *os_ident_ptr = obj; + const char *name; + unsigned int sectsize; + + name = bfd_get_section_name (abfd, sect); + sectsize = bfd_section_size (abfd, sect); + if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0) + { + unsigned int name_length, data_length, note_type; + char *note = alloca (sectsize); + + bfd_get_section_contents (abfd, sect, note, + (file_ptr) 0, (bfd_size_type) sectsize); + + name_length = bfd_h_get_32 (abfd, note); + data_length = bfd_h_get_32 (abfd, note + 4); + note_type = bfd_h_get_32 (abfd, note + 8); + + if (name_length == 4 && data_length == 16 && note_type == 1 + && strcmp (note + 12, "GNU") == 0) + { + int os_number = bfd_h_get_32 (abfd, note + 16); + + /* The case numbers are from abi-tags in glibc */ + switch (os_number) + { + case 0 : + *os_ident_ptr = ELFOSABI_LINUX; + break; + case 1 : + *os_ident_ptr = ELFOSABI_HURD; + break; + case 2 : + *os_ident_ptr = ELFOSABI_SOLARIS; + break; + default : + internal_error ( + "process_note_abi_sections: unknown OS number %d", os_number); + break; + } + } + } +} + +/* Return one of the ELFOSABI_ constants for BFDs representing ELF + executables. If it's not an ELF executable or if the OS/ABI couldn't + be determined, simply return -1. */ + +static int +get_elfosabi (bfd *abfd) +{ + int elfosabi = -1; + + if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour) + { + elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; + + /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate + that we're on a SYSV system. However, GNU/Linux uses a note section + to record OS/ABI info, but leaves e_ident[EI_OSABI] zero. So we + have to check the note sections too. */ + if (elfosabi == 0) + { + bfd_map_over_sections (abfd, + process_note_abi_tag_sections, + &elfosabi); + } + } + + return elfosabi; +} + /* Initialize the current architecture based on INFO. If possible, re-use an @@ -1923,25 +1996,40 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; struct gdbarch_tdep *tdep; - int wordsize, fromexec, power, i, off; + int wordsize, from_xcoff_exec, from_elf_exec, power, i, off; struct reg *regs; const struct variant *v; enum bfd_architecture arch; unsigned long mach; bfd abfd; + int osabi, sysv_abi; - fromexec = info.abfd && info.abfd->format == bfd_object && + from_xcoff_exec = info.abfd && info.abfd->format == bfd_object && bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour; + from_elf_exec = info.abfd && info.abfd->format == bfd_object && + bfd_get_flavour (info.abfd) == bfd_target_elf_flavour; + + sysv_abi = info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour; + + osabi = get_elfosabi (info.abfd); + /* Check word size. If INFO is from a binary file, infer it from that, else use the previously-inferred size. */ - if (fromexec) + if (from_xcoff_exec) { if (xcoff_data (info.abfd)->xcoff64) wordsize = 8; else wordsize = 4; } + else if (from_elf_exec) + { + if (elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64) + wordsize = 8; + else + wordsize = 4; + } else { tdep = TDEP; @@ -1960,7 +2048,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform separate word size check. */ tdep = gdbarch_tdep (arches->gdbarch); - if (tdep && tdep->wordsize == wordsize) + if (tdep && tdep->wordsize == wordsize && tdep->osabi == osabi) return arches->gdbarch; } @@ -1972,7 +2060,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) - "set arch" trust blindly - GDB startup useless but harmless */ - if (!fromexec) + if (!from_xcoff_exec) { arch = info.bfd_architecture; mach = info.bfd_arch_info->mach; @@ -1986,6 +2074,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } tdep = xmalloc (sizeof (struct gdbarch_tdep)); tdep->wordsize = wordsize; + tdep->osabi = osabi; gdbarch = gdbarch_alloc (&info, tdep); power = arch == bfd_arch_rs6000; @@ -2060,16 +2149,17 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw); set_gdbarch_extract_return_value (gdbarch, rs6000_extract_return_value); - set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments); + + if (sysv_abi) + set_gdbarch_push_arguments (gdbarch, ppc_sysv_abi_push_arguments); + else + set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments); set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return); set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); set_gdbarch_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention); - set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs); - set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info); - set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame); set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue); @@ -2081,10 +2171,32 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Not sure on this. FIXMEmgo */ set_gdbarch_frame_args_skip (gdbarch, 8); - set_gdbarch_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation); - set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain); set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid); - set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc); + if (osabi == ELFOSABI_LINUX) + { + set_gdbarch_frameless_function_invocation (gdbarch, + ppc_linux_frameless_function_invocation); + set_gdbarch_frame_chain (gdbarch, ppc_linux_frame_chain); + set_gdbarch_frame_saved_pc (gdbarch, ppc_linux_frame_saved_pc); + + set_gdbarch_frame_init_saved_regs (gdbarch, + ppc_linux_frame_init_saved_regs); + set_gdbarch_init_extra_frame_info (gdbarch, + ppc_linux_init_extra_frame_info); + + set_gdbarch_memory_remove_breakpoint (gdbarch, + ppc_linux_memory_remove_breakpoint); + } + else + { + set_gdbarch_frameless_function_invocation (gdbarch, + rs6000_frameless_function_invocation); + set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain); + set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc); + + set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs); + set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info); + } set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address); set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address); set_gdbarch_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);