Make GNU/Linux/PPC work again.

This commit is contained in:
Kevin Buettner 2000-07-31 20:56:44 +00:00
parent dc62a253bc
commit 9aa1e687a2
22 changed files with 287 additions and 107 deletions

View file

@ -1,3 +1,55 @@
2000-07-31 Kevin Buettner <kevinb@redhat.com>
* 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 <ezannoni@kwikemart.cygnus.com> 2000-07-31 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
* remote-e7000.c (e7000_start_remote): Use void *, not char * as * remote-e7000.c (e7000_start_remote): Use void *, not char * as

View file

@ -1627,7 +1627,7 @@ ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(gdbcore_h) $(frame_h) \
$(inferior_h) target.h $(inferior_h) target.h
ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(gdbcore_h) $(inferior_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) \ 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 $(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 xcoffsolib.h
rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_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-exp.o: $(defs_h) $(value_h) parser-defs.h language.h c-lang.h \
scm-lang.h scm-tags.h scm-lang.h scm-tags.h

View file

@ -1,3 +1,3 @@
# Target: PowerPC running AIX # 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 TM_FILE= tm-ppc-aix.h

View file

@ -1,5 +1,5 @@
# Target: Powerpc running cygnus's unix api over win32 # 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 TM_FILE= tm-cygwin.h

View file

@ -1,3 +1,3 @@
# Target: PowerMac (PowerPC running MacOS) # 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 TM_FILE= tm-macos.h

View file

@ -1,5 +1,5 @@
# Target: PowerPC, running NetBSD # Target: PowerPC, running NetBSD
TDEPFILES= rs6000-tdep.o TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o
TM_FILE= tm-nbsd.h TM_FILE= tm-nbsd.h
GDBSERVER_DEPFILES= low-nbsd.o GDBSERVER_DEPFILES= low-nbsd.o

View file

@ -1,3 +1,3 @@
# Target: PowerPC running eabi # 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 TM_FILE= tm-ppc-eabi.h

View file

@ -1,3 +1,3 @@
# Target: PowerPC running Netware # Target: PowerPC running Netware
TDEPFILES= rs6000-tdep.o TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o
TM_FILE= tm-ppc-nw.h TM_FILE= tm-ppc-nw.h

View file

@ -1,5 +1,5 @@
# Target: PowerPC running eabi and including the simulator # 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 TM_FILE= tm-ppc-eabi.h
SIM_OBS = remote-sim.o SIM_OBS = remote-sim.o

View file

@ -1,3 +1,3 @@
# Target: PowerPC running eabi in little endian mode # 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 TM_FILE= tm-ppcle-eabi.h

View file

@ -1,5 +1,5 @@
# Target: PowerPC running eabi in little endian mode under the simulator # 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 TM_FILE= tm-ppcle-eabi.h
SIM_OBS = remote-sim.o SIM_OBS = remote-sim.o

View file

@ -1,3 +1,3 @@
# Target: PowerPC, running Solaris 2 # Target: PowerPC, running Solaris 2
TDEPFILES= rs6000-tdep.o TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o
TM_FILE= tm-solaris.h TM_FILE= tm-solaris.h

View file

@ -42,9 +42,6 @@ extern int at_subroutine_call_instruction_target();
in symfile.c) */ in symfile.c) */
#undef IBM6000_TARGET #undef IBM6000_TARGET
/* Offset to saved PC in sigcontext, from <linux/signal.h>. */
#define SIGCONTEXT_PC_OFFSET 184
extern CORE_ADDR ppc_linux_skip_trampoline_code (CORE_ADDR pc); extern CORE_ADDR ppc_linux_skip_trampoline_code (CORE_ADDR pc);
#undef SKIP_TRAMPOLINE_CODE #undef SKIP_TRAMPOLINE_CODE
#define SKIP_TRAMPOLINE_CODE(pc) ppc_linux_skip_trampoline_code (pc) #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 #undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc,func_name) ppc_linux_in_sigtramp (pc,func_name) #define IN_SIGTRAMP(pc,func_name) ppc_linux_in_sigtramp (pc,func_name)
extern unsigned long ppc_linux_frame_saved_pc (struct frame_info *); #if 0
#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)))
#define CANNOT_FETCH_REGISTER(regno) ((regno) >= MQ_REGNUM) #define CANNOT_FETCH_REGISTER(regno) ((regno) >= MQ_REGNUM)
#define CANNOT_STORE_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 */ /* Linux doesn't use the PowerOpen ABI for function pointer representation */
#undef CONVERT_FROM_FUNC_PTR_ADDR #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 #define PROLOGUE_FIRSTLINE_OVERLAP
#endif #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 /* N_FUN symbols in shared libaries have 0 for their values and need
to be relocated. */ to be relocated. */
#define SOFUN_ADDRESS_MAYBE_MISSING #define SOFUN_ADDRESS_MAYBE_MISSING

View file

@ -1,3 +1,3 @@
# Target: Powerpc running VxWorks # Target: Powerpc running VxWorks
TDEPFILES= rs6000-tdep.o TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o
TM_FILE= tm-vxworks.h TM_FILE= tm-vxworks.h

View file

@ -1,3 +1,3 @@
# Target: IBM RS/6000 running AIX4 # 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 TM_FILE= tm-rs6000-aix4.h

View file

@ -1,3 +1,3 @@
# Target: IBM RS/6000 running AIX # 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 TM_FILE= tm-rs6000.h

View file

@ -1,3 +1,3 @@
# Target: IBM RS6000 running LynxOS # 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 TM_FILE= tm-rs6000ly.h

View file

@ -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 different names than GDB does, and don't support all the registers
either. */ either. */
static char *dink32_regnames[NUM_REGS] = static char *dink32_regnames[] =
{ {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",

View file

@ -36,6 +36,7 @@
#include <signal.h> #include <signal.h>
#include "serial.h" #include "serial.h"
#include "ocd.h" #include "ocd.h"
#include "ppc-tdep.h"
static void bdm_ppc_open (char *name, int from_tty); 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); */ /* printf("Asking for register %d\n", first_regno); */
/* if asking for an invalid register */ /* 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))) ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM)))
{ {
/* printf("invalid reg request!\n"); */ /* 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 */ /* only attempt to write if it's a valid ppc 8xx register */
/* (need to avoid FP regs and MQ reg) */ /* (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); */ /* printf("write valid reg %d\n", bdm_regno); */
ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4); ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
} }
/* /*
else if (i == MQ_REGNUM) else if (i == PPC_MQ_REGNUM)
printf("don't write invalid reg %d (MQ_REGNUM)\n", bdm_regno); printf("don't write invalid reg %d (PPC_MQ_REGNUM)\n", bdm_regno);
else else
printf("don't write invalid reg %d\n", bdm_regno); printf("don't write invalid reg %d\n", bdm_regno);
*/ */

View file

@ -29,6 +29,8 @@
#include "symfile.h" #include "symfile.h"
#include "objfiles.h" #include "objfiles.h"
#include "ppc-tdep.h"
/* The following two instructions are used in the signal trampoline /* The following two instructions are used in the signal trampoline
code on linux/ppc */ code on linux/ppc */
#define INSTR_LI_R0_0x7777 0x38007777 #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_FPR31 (PPC_LINUX_PT_FPR0 + 2*31)
#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1) #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... /* 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]; char buf[4];
CORE_ADDR handler; CORE_ADDR handler;
lr = read_register (LR_REGNUM); lr = read_register (PPC_LR_REGNUM);
if (!ppc_linux_at_sigtramp_return_path (lr)) if (!ppc_linux_at_sigtramp_return_path (lr))
return 0; 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 * instructions. It'd be faster though if we could find a way to do this
* via some simple address comparisons. * via some simple address comparisons.
*/ */
int static int
ppc_linux_at_sigtramp_return_path (CORE_ADDR pc) ppc_linux_at_sigtramp_return_path (CORE_ADDR pc)
{ {
char buf[12]; 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 /* The rs6000 version of FRAME_SAVED_PC will almost work for us. The
signal handler details are different, so we'll handle those here signal handler details are different, so we'll handle those here
and call the rs6000 version to do the rest. */ and call the rs6000 version to do the rest. */
unsigned long CORE_ADDR
ppc_linux_frame_saved_pc (struct frame_info *fi) ppc_linux_frame_saved_pc (struct frame_info *fi)
{ {
if (fi->signal_handler_caller) if (fi->signal_handler_caller)
@ -372,14 +374,14 @@ ppc_linux_frame_init_saved_regs (struct frame_info *fi)
regs_addr = regs_addr =
read_memory_integer (fi->frame + PPC_LINUX_REGS_PTR_OFFSET, 4); 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[PC_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_NIP;
fi->saved_regs[PS_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MSR; fi->saved_regs[PPC_PS_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MSR;
fi->saved_regs[CR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CCR; fi->saved_regs[PPC_CR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CCR;
fi->saved_regs[LR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_LNK; fi->saved_regs[PPC_LR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_LNK;
fi->saved_regs[CTR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CTR; fi->saved_regs[PPC_CTR_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_CTR;
fi->saved_regs[XER_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_XER; fi->saved_regs[PPC_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_MQ_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_MQ;
for (i = 0; i < 32; i++) 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++) for (i = 0; i < 32; i++)
fi->saved_regs[FP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_FPR0 + 8 * i; fi->saved_regs[FP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_FPR0 + 8 * i;
} }

49
gdb/ppc-tdep.h Normal file
View file

@ -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 */

View file

@ -35,15 +35,9 @@
#include "coff/internal.h" /* for libcoff.h */ #include "coff/internal.h" /* for libcoff.h */
#include "bfd/libcoff.h" /* for xcoff_data */ #include "bfd/libcoff.h" /* for xcoff_data */
/* Some important register numbers. Keep these in the same order as in #include "elf-bfd.h"
/usr/mstsave.h `mstsave' structure, for easier processing. */
#define GP0_REGNUM 0 /* GPR register 0 */ #include "ppc-tdep.h"
#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 */
/* If the kernel has to deliver a signal, it pushes a sigcontext /* If the kernel has to deliver a signal, it pushes a sigcontext
structure on the stack and then calls the signal handler, passing structure on the stack and then calls the signal handler, passing
@ -89,6 +83,7 @@ struct reg
struct gdbarch_tdep struct gdbarch_tdep
{ {
int wordsize; /* size in bytes of fixed-point word */ int wordsize; /* size in bytes of fixed-point word */
int osabi; /* OS / ABI from ELF header */
int *regoff; /* byte offsets in register arrays */ int *regoff; /* byte offsets in register arrays */
const struct reg *regs; /* from current variant */ const struct reg *regs; /* from current variant */
}; };
@ -157,7 +152,7 @@ struct frame_extra_info
CORE_ADDR initial_sp; /* initial stack pointer. */ CORE_ADDR initial_sp; /* initial stack pointer. */
}; };
static void void
rs6000_init_extra_frame_info (int fromleaf, struct frame_info *fi) rs6000_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{ {
fi->extra_info = (struct frame_extra_info *) 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 not sure if it will be needed. The following function takes care of gpr's
and fpr's only. */ and fpr's only. */
static void void
rs6000_frame_init_saved_regs (struct frame_info *fi) rs6000_frame_init_saved_regs (struct frame_info *fi)
{ {
frame_get_saved_regs (fi, NULL); frame_get_saved_regs (fi, NULL);
@ -205,7 +200,7 @@ rs6000_frame_args_address (struct frame_info *fi)
static CORE_ADDR static CORE_ADDR
rs6000_saved_pc_after_call (struct frame_info *fi) 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. */ /* 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 */ 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 /* If we are about to return from a signal handler, dest is
something like 0x3c90. The current frame is a signal handler 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 */ 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 /* If we are about to execute a system call, dest is something
like 0x22fc or 0x3b00. Upon completion the system call like 0x22fc or 0x3b00. Upon completion the system call
will return to the address in the link register. */ will return to the address in the link register. */
if (dest < TEXT_SEGMENT_BASE) if (dest < TEXT_SEGMENT_BASE)
dest = read_register (LR_REGNUM) & ~3; dest = read_register (PPC_LR_REGNUM) & ~3;
} }
else else
return -1; return -1;
@ -715,7 +710,7 @@ rs6000_pop_frame (void)
else else
prev_sp = read_memory_addr (sp, wordsize); prev_sp = read_memory_addr (sp, wordsize);
if (fdata.lr_offset == 0) if (fdata.lr_offset == 0)
lr = read_register (LR_REGNUM); lr = read_register (PPC_LR_REGNUM);
else else
lr = read_memory_addr (prev_sp + fdata.lr_offset, wordsize); 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) if (rs6000_find_toc_address_hook != NULL)
{ {
CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (fun); 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 static CORE_ADDR
ppc_push_return_address (CORE_ADDR pc, CORE_ADDR sp) 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; 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. */ /* Determines whether the function FI has a frame on the stack or not. */
static int int
rs6000_frameless_function_invocation (struct frame_info *fi) rs6000_frameless_function_invocation (struct frame_info *fi)
{ {
CORE_ADDR func_start; CORE_ADDR func_start;
@ -1119,7 +1114,7 @@ rs6000_frameless_function_invocation (struct frame_info *fi)
/* Return the PC saved in a frame */ /* Return the PC saved in a frame */
static CORE_ADDR CORE_ADDR
rs6000_frame_saved_pc (struct frame_info *fi) rs6000_frame_saved_pc (struct frame_info *fi)
{ {
CORE_ADDR func_start; CORE_ADDR func_start;
@ -1152,7 +1147,7 @@ rs6000_frame_saved_pc (struct frame_info *fi)
} }
if (fdata.lr_offset == 0) 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); 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 /* If != 0, fdatap->cr_offset is the offset from the frame that holds
the CR. */ the CR. */
if (fdatap->cr_offset != 0) 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 /* If != 0, fdatap->lr_offset is the offset from the frame that holds
the LR. */ the LR. */
if (fdatap->lr_offset != 0) 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 /* 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 /* 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. */ 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) rs6000_frame_chain (struct frame_info *thisframe)
{ {
CORE_ADDR fp, fpp, lr; CORE_ADDR fp, fpp, lr;
@ -1338,7 +1333,7 @@ rs6000_frame_chain (struct frame_info *thisframe)
else else
fp = read_memory_addr ((thisframe)->frame, wordsize); fp = read_memory_addr ((thisframe)->frame, wordsize);
lr = read_register (LR_REGNUM); lr = read_register (PPC_LR_REGNUM);
if (lr == entry_point_address ()) if (lr == entry_point_address ())
if (fp != 0 && (fpp = read_memory_addr (fp, wordsize)) != 0) if (fp != 0 && (fpp = read_memory_addr (fp, wordsize)) != 0)
if (PC_IN_CALL_DUMMY (lr, fpp, fpp)) if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
@ -1500,7 +1495,7 @@ rs6000_store_return_value (struct type *type, char *valbuf)
TYPE_LENGTH (type)); TYPE_LENGTH (type));
else else
/* Everything else is returned in GPR3 and up. */ /* 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)); TYPE_LENGTH (type));
} }
@ -1909,6 +1904,84 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
return NULL; 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 /* 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 *gdbarch;
struct gdbarch_tdep *tdep; struct gdbarch_tdep *tdep;
int wordsize, fromexec, power, i, off; int wordsize, from_xcoff_exec, from_elf_exec, power, i, off;
struct reg *regs; struct reg *regs;
const struct variant *v; const struct variant *v;
enum bfd_architecture arch; enum bfd_architecture arch;
unsigned long mach; unsigned long mach;
bfd abfd; 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; 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, /* Check word size. If INFO is from a binary file, infer it from that,
else use the previously-inferred size. */ else use the previously-inferred size. */
if (fromexec) if (from_xcoff_exec)
{ {
if (xcoff_data (info.abfd)->xcoff64) if (xcoff_data (info.abfd)->xcoff64)
wordsize = 8; wordsize = 8;
else else
wordsize = 4; wordsize = 4;
} }
else if (from_elf_exec)
{
if (elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
wordsize = 8;
else
wordsize = 4;
}
else else
{ {
tdep = TDEP; 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 meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform
separate word size check. */ separate word size check. */
tdep = gdbarch_tdep (arches->gdbarch); tdep = gdbarch_tdep (arches->gdbarch);
if (tdep && tdep->wordsize == wordsize) if (tdep && tdep->wordsize == wordsize && tdep->osabi == osabi)
return arches->gdbarch; return arches->gdbarch;
} }
@ -1972,7 +2060,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
- "set arch" trust blindly - "set arch" trust blindly
- GDB startup useless but harmless */ - GDB startup useless but harmless */
if (!fromexec) if (!from_xcoff_exec)
{ {
arch = info.bfd_architecture; arch = info.bfd_architecture;
mach = info.bfd_arch_info->mach; 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 = xmalloc (sizeof (struct gdbarch_tdep));
tdep->wordsize = wordsize; tdep->wordsize = wordsize;
tdep->osabi = osabi;
gdbarch = gdbarch_alloc (&info, tdep); gdbarch = gdbarch_alloc (&info, tdep);
power = arch == bfd_arch_rs6000; 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_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw);
set_gdbarch_extract_return_value (gdbarch, rs6000_extract_return_value); 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_struct_return (gdbarch, rs6000_store_struct_return);
set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value);
set_gdbarch_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); set_gdbarch_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention); 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_pop_frame (gdbarch, rs6000_pop_frame);
set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue); 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 */ /* Not sure on this. FIXMEmgo */
set_gdbarch_frame_args_skip (gdbarch, 8); 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_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_args_address (gdbarch, rs6000_frame_args_address);
set_gdbarch_frame_locals_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); set_gdbarch_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);