This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Changes for GNU/Linux PPC port


I've just committed the following changes for the GNU/Linux PPC native
port.  I'm seeing 33 unexpected failures while running the test suite.
I'll try to whittle these down to a more reasonable number after I get
this patch committed to the internal repository.

Kevin

	* Makefile.in (ppc-linux-nat.c, ppc-linux-tdep.c): New files.
	(ppc-linux-nat.o, ppc-linux-tdep.o): Add dependencies.
	* configure.tgt (powerpc-*-linux*): Separate from powerpc-*-eabi
	and like targets.

	* ppc-linux-nat.c, ppc-linux-tdep.c, config/powerpc/linux.mt,
	config/powerpc/nm-linux.h, config/powerpc/tm-linux.h: New files.
	* config/powerpc/xm-linux.h: Substantially revised for native
	port.
	* config/powerpc/linux.mh (NAT_FILE): Redefine to be nm-linux.h.
	(NATDEPFILES): Update list to reflect the fact that we can
	now debug natively.

	* rs6000-tdep.c, config/rs6000/tm-rs6000.h
	(rs6000_frameless_function_invocation, rs6000_frame_saved_pc):
	Renamed; The former names were lacking the rs6000_ prefix.
	* rs6000-tdep.c (rs6000_frame_saved_pc): Call FRAME_CHAIN
	instead of rs6000_frame_chain.
	(rs6000_frame_chain): Call FRAMELESS_FUNCTION_INVOCATION instead
	of rs6000_frameless_function_invocation.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.5
diff -u -p -r1.5 Makefile.in
--- Makefile.in	2000/02/16 23:35:19	1.5
+++ Makefile.in	2000/02/22 00:48:30
@@ -1047,6 +1047,7 @@ ALLDEPFILES = 29k-share/udi/udip2soc.c 2
 	nindy-share/ttyflush.c nindy-tdep.c \
 	ns32k-tdep.c ns32km3-nat.c osfsolib.c \
 	somread.c somsolib.c $(HPREAD_SOURCE) \
+	ppc-linux-nat.c ppc-linux-tdep.c \
 	procfs.c pyr-tdep.c pyr-xdep.c \
 	remote-adapt.c remote-array.c remote-bug.c remote-e7000.c remote-eb.c \
 	remote-es.c remote-hms.c remote-mips.c \
@@ -1520,6 +1521,12 @@ parse.o: parse.c $(command_h) $(defs_h) 
 ppc-bdm.o: ppc-bdm.c $(defs_h) $(gdbcore_h) gdb_string.h $(frame_h) \
 	$(inferior_h) $(bfd_h) symfile.h target.h gdb_wait.h $(gdbcmd_h) \
 	objfiles.h gdb-stabs.h serial.h ocd.h
+
+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
 
 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
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.2
diff -u -p -r1.2 configure.tgt
--- configure.tgt	2000/02/13 01:06:57	1.2
+++ configure.tgt	2000/02/22 00:48:30
@@ -224,7 +224,7 @@ powerpc-*-netware*)	gdb_target=ppc-nw
 powerpc-*-aix*)		gdb_target=aix ;;
 powerpcle-*-cygwin*)	gdb_target=cygwin ;;
 powerpcle-*-solaris*)	gdb_target=solaris ;;
-powerpc-*-eabi* | powerpc-*-linux* | powerpc-*-sysv* | powerpc-*-elf*)
+powerpc-*-eabi* | powerpc-*-sysv* | powerpc-*-elf*)
 			if test -f ../sim/ppc/Makefile; then
 			  gdb_target=ppc-sim
 			else
@@ -236,6 +236,7 @@ powerpcle-*-eabi* | powerpcle-*-sysv* | 
 			else
 			  gdb_target=ppcle-eabi
 			fi ;;
+powerpc-*-linux*)	gdb_target=linux ;;
 powerpc-*-vxworks*)	gdb_target=vxworks ;;
 
 # OBSOLETE pyramid-*-*)		gdb_target=pyramid ;;
Index: ppc-linux-nat.c
===================================================================
RCS file: ppc-linux-nat.c
diff -N ppc-linux-nat.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ ppc-linux-nat.c	Mon Feb 21 16:48:30 2000
@@ -0,0 +1,76 @@
+/* PPC linux native support.
+   Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996 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.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <sys/procfs.h>
+
+int
+kernel_u_size ()
+{
+  return (sizeof (struct user));
+}
+
+static int regmap[] =
+{PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+ PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
+ PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
+ PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
+ PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
+ PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
+ PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
+ PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
+ PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ};
+
+int 
+ppc_register_u_addr (int ustart, int regnum)
+{
+  return (ustart + 4 * regmap[regnum]);
+}
+
+supply_gregset (gregset_t * gregsetp)
+{
+  int regi;
+  register greg_t *regp = (greg_t *) gregsetp;
+
+  for (regi = 0; regi < 32; regi++)
+    supply_register (regi, (char *) (regp + regi));
+
+  for (regi = FIRST_UISA_SP_REGNUM; regi <= LAST_UISA_SP_REGNUM; regi++)
+    supply_register (regi, (char *) (regp + regmap[regi]));
+}
+
+supply_fpregset (fpregset_t * fpregsetp)
+{
+  int regi;
+  for (regi = 0; regi < 32; regi++)
+    {
+      supply_register (FP0_REGNUM + regi, (char *) (*fpregsetp + regi));
+    }
+}
Index: ppc-linux-tdep.c
===================================================================
RCS file: ppc-linux-tdep.c
diff -N ppc-linux-tdep.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ ppc-linux-tdep.c	Mon Feb 21 16:48:31 2000
@@ -0,0 +1,599 @@
+/* Target-dependent code for GDB, the GNU debugger.
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 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.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* The following two instructions are used in the signal trampoline
+   code on linux/ppc */
+#define INSTR_LI_R0_0x7777	0x38007777
+#define INSTR_SC		0x44000002
+
+/* Since the *-tdep.c files are platform independent (i.e, they may be
+   used to build cross platform debuggers), we can't include system
+   headers.  Therefore, details concerning the sigcontext structure
+   must be painstakingly rerecorded.  What's worse, if these details
+   ever change in the header files, they'll have to be changed here
+   as well. */
+
+/* __SIGNAL_FRAMESIZE from <asm/ptrace.h> */
+#define PPC_LINUX_SIGNAL_FRAMESIZE 64
+
+/* From <asm/sigcontext.h>, offsetof(struct sigcontext_struct, regs) == 0x1c */
+#define PPC_LINUX_REGS_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x1c)
+
+/* From <asm/sigcontext.h>, 
+   offsetof(struct sigcontext_struct, handler) == 0x14 */
+#define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14)
+
+/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
+#define PPC_LINUX_PT_R0		0
+#define PPC_LINUX_PT_R1		1
+#define PPC_LINUX_PT_R2		2
+#define PPC_LINUX_PT_R3		3
+#define PPC_LINUX_PT_R4		4
+#define PPC_LINUX_PT_R5		5
+#define PPC_LINUX_PT_R6		6
+#define PPC_LINUX_PT_R7		7
+#define PPC_LINUX_PT_R8		8
+#define PPC_LINUX_PT_R9		9
+#define PPC_LINUX_PT_R10	10
+#define PPC_LINUX_PT_R11	11
+#define PPC_LINUX_PT_R12	12
+#define PPC_LINUX_PT_R13	13
+#define PPC_LINUX_PT_R14	14
+#define PPC_LINUX_PT_R15	15
+#define PPC_LINUX_PT_R16	16
+#define PPC_LINUX_PT_R17	17
+#define PPC_LINUX_PT_R18	18
+#define PPC_LINUX_PT_R19	19
+#define PPC_LINUX_PT_R20	20
+#define PPC_LINUX_PT_R21	21
+#define PPC_LINUX_PT_R22	22
+#define PPC_LINUX_PT_R23	23
+#define PPC_LINUX_PT_R24	24
+#define PPC_LINUX_PT_R25	25
+#define PPC_LINUX_PT_R26	26
+#define PPC_LINUX_PT_R27	27
+#define PPC_LINUX_PT_R28	28
+#define PPC_LINUX_PT_R29	29
+#define PPC_LINUX_PT_R30	30
+#define PPC_LINUX_PT_R31	31
+#define PPC_LINUX_PT_NIP	32
+#define PPC_LINUX_PT_MSR	33
+#define PPC_LINUX_PT_CTR	35
+#define PPC_LINUX_PT_LNK	36
+#define PPC_LINUX_PT_XER	37
+#define PPC_LINUX_PT_CCR	38
+#define PPC_LINUX_PT_MQ		39
+#define PPC_LINUX_PT_FPR0	48	/* each FP reg occupies 2 slots in this space */
+#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31)
+#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1)
+
+/* Determine if pc is in a signal trampoline...
+
+   Ha!  That's not what this does at all.  wait_for_inferior in infrun.c
+   calls IN_SIGTRAMP in order to detect entry into a signal trampoline
+   just after delivery of a signal.  But on linux, signal trampolines
+   are used for the return path only.  The kernel sets things up so that
+   the signal handler is called directly.
+
+   If we use in_sigtramp2() in place of in_sigtramp() (see below)
+   we'll (often) end up with stop_pc in the trampoline and prev_pc in
+   the (now exited) handler.  The code there will cause a temporary
+   breakpoint to be set on prev_pc which is not very likely to get hit
+   again.
+
+   If this is confusing, think of it this way...  the code in
+   wait_for_inferior() needs to be able to detect entry into a signal
+   trampoline just after a signal is delivered, not after the handler
+   has been run.
+
+   So, we define in_sigtramp() below to return 1 if the following is
+   true:
+
+   1) The previous frame is a real signal trampoline.
+
+   - and -
+
+   2) pc is at the first or second instruction of the corresponding
+   handler.
+
+   Why the second instruction?  It seems that wait_for_inferior()
+   never sees the first instruction when single stepping.  When a
+   signal is delivered while stepping, the next instruction that
+   would've been stepped over isn't, instead a signal is delivered and
+   the first instruction of the handler is stepped over instead.  That
+   puts us on the second instruction.  (I added the test for the
+   first instruction long after the fact, just in case the observed
+   behavior is ever fixed.)
+
+   IN_SIGTRAMP is called from blockframe.c as well in order to set
+   the signal_handler_caller flag.  Because of our strange definition
+   of in_sigtramp below, we can't rely on signal_handler_caller getting
+   set correctly from within blockframe.c.  This is why we take pains
+   to set it in init_extra_frame_info().  */
+
+int
+ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name)
+{
+  CORE_ADDR lr;
+  CORE_ADDR sp;
+  CORE_ADDR tramp_sp;
+  char buf[4];
+  CORE_ADDR handler;
+
+  lr = read_register (LR_REGNUM);
+  if (!ppc_linux_at_sigtramp_return_path (lr))
+    return 0;
+
+  sp = read_register (SP_REGNUM);
+
+  if (target_read_memory (sp, buf, sizeof (buf)) != 0)
+    return 0;
+
+  tramp_sp = extract_unsigned_integer (buf, 4);
+
+  if (target_read_memory (tramp_sp + PPC_LINUX_HANDLER_PTR_OFFSET, buf,
+			  sizeof (buf)) != 0)
+    return 0;
+
+  handler = extract_unsigned_integer (buf, 4);
+
+  return (pc == handler || pc == handler + 4);
+}
+
+/*
+ * The signal handler trampoline is on the stack and consists of exactly
+ * two instructions.  The easiest and most accurate way of determining
+ * whether the pc is in one of these trampolines is by inspecting the
+ * instructions.  It'd be faster though if we could find a way to do this
+ * via some simple address comparisons.
+ */
+int
+ppc_linux_at_sigtramp_return_path (CORE_ADDR pc)
+{
+  char buf[12];
+  unsigned long pcinsn;
+  if (target_read_memory (pc - 4, buf, sizeof (buf)) != 0)
+    return 0;
+
+  /* extract the instruction at the pc */
+  pcinsn = extract_unsigned_integer (buf + 4, 4);
+
+  return (
+	   (pcinsn == INSTR_LI_R0_0x7777
+	    && extract_unsigned_integer (buf + 8, 4) == INSTR_SC)
+	   ||
+	   (pcinsn == INSTR_SC
+	    && extract_unsigned_integer (buf, 4) == INSTR_LI_R0_0x7777));
+}
+
+CORE_ADDR
+ppc_linux_skip_trampoline_code (CORE_ADDR pc)
+{
+  char buf[4];
+  struct obj_section *sect;
+  struct objfile *objfile;
+  unsigned long insn;
+  CORE_ADDR plt_start = 0;
+  CORE_ADDR symtab = 0;
+  CORE_ADDR strtab = 0;
+  int num_slots = -1;
+  int reloc_index = -1;
+  CORE_ADDR plt_table;
+  CORE_ADDR reloc;
+  CORE_ADDR sym;
+  long symidx;
+  char symname[1024];
+  struct minimal_symbol *msymbol;
+
+  /* Find the section pc is in; return if not in .plt */
+  sect = find_pc_section (pc);
+  if (!sect || strcmp (sect->the_bfd_section->name, ".plt") != 0)
+    return 0;
+
+  objfile = sect->objfile;
+
+  /* Pick up the instruction at pc.  It had better be of the
+     form
+     li r11, IDX
+
+     where IDX is an index into the plt_table.  */
+
+  if (target_read_memory (pc, buf, 4) != 0)
+    return 0;
+  insn = extract_unsigned_integer (buf, 4);
+
+  if ((insn & 0xffff0000) != 0x39600000 /* li r11, VAL */ )
+    return 0;
+
+  reloc_index = (insn << 16) >> 16;
+
+  /* Find the objfile that pc is in and obtain the information
+     necessary for finding the symbol name. */
+  for (sect = objfile->sections; sect < objfile->sections_end; ++sect)
+    {
+      const char *secname = sect->the_bfd_section->name;
+      if (strcmp (secname, ".plt") == 0)
+	plt_start = sect->addr;
+      else if (strcmp (secname, ".rela.plt") == 0)
+	num_slots = ((int) sect->endaddr - (int) sect->addr) / 12;
+      else if (strcmp (secname, ".dynsym") == 0)
+	symtab = sect->addr;
+      else if (strcmp (secname, ".dynstr") == 0)
+	strtab = sect->addr;
+    }
+
+  /* Make sure we have all the information we need. */
+  if (plt_start == 0 || num_slots == -1 || symtab == 0 || strtab == 0)
+    return 0;
+
+  /* Compute the value of the plt table */
+  plt_table = plt_start + 72 + 8 * num_slots;
+
+  /* Get address of the relocation entry (Elf32_Rela) */
+  if (target_read_memory (plt_table + reloc_index, buf, 4) != 0)
+    return 0;
+  reloc = extract_address (buf, 4);
+
+  sect = find_pc_section (reloc);
+  if (!sect)
+    return 0;
+
+  if (strcmp (sect->the_bfd_section->name, ".text") == 0)
+    return reloc;
+
+  /* Now get the r_info field which is the relocation type and symbol
+     index. */
+  if (target_read_memory (reloc + 4, buf, 4) != 0)
+    return 0;
+  symidx = extract_unsigned_integer (buf, 4);
+
+  /* Shift out the relocation type leaving just the symbol index */
+  /* symidx = ELF32_R_SYM(symidx); */
+  symidx = symidx >> 8;
+
+  /* compute the address of the symbol */
+  sym = symtab + symidx * 4;
+
+  /* Fetch the string table index */
+  if (target_read_memory (sym, buf, 4) != 0)
+    return 0;
+  symidx = extract_unsigned_integer (buf, 4);
+
+  /* Fetch the string; we don't know how long it is.  Is it possible
+     that the following will fail because we're trying to fetch too
+     much? */
+  if (target_read_memory (strtab + symidx, symname, sizeof (symname)) != 0)
+    return 0;
+
+  /* This might not work right if we have multiple symbols with the
+     same name; the only way to really get it right is to perform
+     the same sort of lookup as the dynamic linker. */
+  msymbol = lookup_minimal_symbol_text (symname, NULL, NULL);
+  if (!msymbol)
+    return 0;
+
+  return SYMBOL_VALUE_ADDRESS (msymbol);
+}
+
+/* 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
+ppc_linux_frame_saved_pc (struct frame_info *fi)
+{
+  if (fi->signal_handler_caller)
+    {
+      CORE_ADDR regs_addr =
+      read_memory_integer (fi->frame + PPC_LINUX_REGS_PTR_OFFSET, 4);
+      /* return the NIP in the regs array */
+      return read_memory_integer (regs_addr + 4 * PPC_LINUX_PT_NIP, 4);
+    }
+
+  return rs6000_frame_saved_pc (fi);
+}
+
+void
+ppc_linux_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+{
+  rs6000_init_extra_frame_info (fromleaf, fi);
+
+  if (fi->next != 0)
+    {
+      /* We're called from get_prev_frame_info; check to see if
+         this is a signal frame by looking to see if the pc points
+         at trampoline code */
+      if (ppc_linux_at_sigtramp_return_path (fi->pc))
+	fi->signal_handler_caller = 1;
+      else
+	fi->signal_handler_caller = 0;
+    }
+}
+
+int
+ppc_linux_frameless_function_invocation (struct frame_info *fi)
+{
+  /* We'll find the wrong thing if we let 
+     rs6000_frameless_function_invocation () search for a signal trampoline */
+  if (ppc_linux_at_sigtramp_return_path (fi->pc))
+    return 0;
+  else
+    return rs6000_frameless_function_invocation (fi);
+}
+
+void
+ppc_linux_frame_init_saved_regs (struct frame_info *fi)
+{
+  if (fi->signal_handler_caller)
+    {
+      CORE_ADDR regs_addr;
+      int i;
+      if (fi->saved_regs)
+	return;
+
+      frame_saved_regs_zalloc (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;
+      for (i = 0; i < 32; i++)
+	fi->saved_regs[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;
+    }
+  else
+    rs6000_frame_init_saved_regs (fi);
+}
+
+CORE_ADDR
+ppc_linux_frame_chain (struct frame_info *thisframe)
+{
+  /* Kernel properly constructs the frame chain for the handler */
+  if (thisframe->signal_handler_caller)
+    return read_memory_integer ((thisframe)->frame, 4);
+  else
+    return rs6000_frame_chain (thisframe);
+}
+
+/* FIXME: Move the following to rs6000-tdep.c (or some other file where
+   it may be used generically by ports which use either the SysV ABI or
+   the EABI */
+
+/* round2 rounds x up to the nearest multiple of s assuming that s is a
+   power of 2 */
+
+#undef round2
+#define round2(x,s) ((((long) (x) - 1) & ~(long)((s)-1)) + (s))
+
+/* Pass the arguments in either registers, or in the stack. Using the
+   ppc sysv ABI, the first eight words of the argument list (that might
+   be less than eight parameters if some parameters occupy more than one
+   word) are passed in r3..r10 registers.  float and double parameters are
+   passed in fpr's, in addition to that. Rest of the parameters if any
+   are passed in user stack. 
+
+   If the function is returning a structure, then the return address is passed
+   in r3, then the first 7 words of the parametes can be passed in registers,
+   starting from r4. */
+
+CORE_ADDR
+ppc_sysv_abi_push_arguments (nargs, args, sp, struct_return, struct_addr)
+     int nargs;
+     value_ptr *args;
+     CORE_ADDR sp;
+     int struct_return;
+     CORE_ADDR struct_addr;
+{
+  int argno;
+  int greg, freg;
+  int argstkspace;
+  int structstkspace;
+  int argoffset;
+  int structoffset;
+  value_ptr arg;
+  struct type *type;
+  int len;
+  char old_sp_buf[4];
+  CORE_ADDR saved_sp;
+
+  greg = struct_return ? 4 : 3;
+  freg = 1;
+  argstkspace = 0;
+  structstkspace = 0;
+
+  /* Figure out how much new stack space is required for arguments
+     which don't fit in registers.  Unlike the PowerOpen ABI, the
+     SysV ABI doesn't reserve any extra space for parameters which
+     are put in registers. */
+  for (argno = 0; argno < nargs; argno++)
+    {
+      arg = args[argno];
+      type = check_typedef (VALUE_TYPE (arg));
+      len = TYPE_LENGTH (type);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+	{
+	  if (freg <= 8)
+	    freg++;
+	  else
+	    {
+	      /* SysV ABI converts floats to doubles when placed in
+	         memory and requires 8 byte alignment */
+	      if (argstkspace & 0x4)
+		argstkspace += 4;
+	      argstkspace += 8;
+	    }
+	}
+      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
+	{
+	  if (greg > 9)
+	    {
+	      greg = 11;
+	      if (argstkspace & 0x4)
+		argstkspace += 4;
+	      argstkspace += 8;
+	    }
+	  else
+	    {
+	      if ((greg & 1) == 0)
+		greg++;
+	      greg += 2;
+	    }
+	}
+      else
+	{
+	  if (len > 4
+	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
+	      || TYPE_CODE (type) == TYPE_CODE_UNION)
+	    {
+	      /* Rounding to the nearest multiple of 8 may not be necessary,
+	         but it is safe.  Particularly since we don't know the
+	         field types of the structure */
+	      structstkspace += round2 (len, 8);
+	    }
+	  if (greg <= 10)
+	    greg++;
+	  else
+	    argstkspace += 4;
+	}
+    }
+
+  /* Get current SP location */
+  saved_sp = read_sp ();
+
+  sp -= argstkspace + structstkspace;
+
+  /* Allocate space for backchain and callee's saved lr */
+  sp -= 8;
+
+  /* Make sure that we maintain 16 byte alignment */
+  sp &= ~0x0f;
+
+  /* Update %sp before proceeding any further */
+  write_register (SP_REGNUM, sp);
+
+  /* write the backchain */
+  store_address (old_sp_buf, 4, saved_sp);
+  write_memory (sp, old_sp_buf, 4);
+
+  argoffset = 8;
+  structoffset = argoffset + argstkspace;
+  freg = 1;
+  greg = 3;
+  /* Now fill in the registers and stack... */
+  for (argno = 0; argno < nargs; argno++)
+    {
+      arg = args[argno];
+      type = check_typedef (VALUE_TYPE (arg));
+      len = TYPE_LENGTH (type);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+	{
+	  if (freg <= 8)
+	    {
+	      if (len > 8)
+		printf_unfiltered (
+				    "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+	      memcpy (&registers[REGISTER_BYTE (FP0_REGNUM + freg)],
+		      VALUE_CONTENTS (arg), len);
+	      freg++;
+	    }
+	  else
+	    {
+	      /* SysV ABI converts floats to doubles when placed in
+	         memory and requires 8 byte alignment */
+	      /* FIXME: Convert floats to doubles */
+	      if (argoffset & 0x4)
+		argoffset += 4;
+	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
+	      argoffset += 8;
+	    }
+	}
+      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
+	{
+	  if (greg > 9)
+	    {
+	      greg = 11;
+	      if (argoffset & 0x4)
+		argoffset += 4;
+	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
+	      argoffset += 8;
+	    }
+	  else
+	    {
+	      if ((greg & 1) == 0)
+		greg++;
+
+	      memcpy (&registers[REGISTER_BYTE (greg)],
+		      VALUE_CONTENTS (arg), 4);
+	      memcpy (&registers[REGISTER_BYTE (greg + 1)],
+		      VALUE_CONTENTS (arg) + 4, 4);
+	      greg += 2;
+	    }
+	}
+      else
+	{
+	  char val_buf[4];
+	  if (len > 4
+	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
+	      || TYPE_CODE (type) == TYPE_CODE_UNION)
+	    {
+	      write_memory (sp + structoffset, VALUE_CONTENTS (arg), len);
+	      store_address (val_buf, 4, sp + structoffset);
+	      structoffset += round2 (len, 8);
+	    }
+	  else
+	    {
+	      memset (val_buf, 0, 4);
+	      memcpy (val_buf, VALUE_CONTENTS (arg), len);
+	    }
+	  if (greg <= 10)
+	    {
+	      *(int *) &registers[REGISTER_BYTE (greg)] = 0;
+	      memcpy (&registers[REGISTER_BYTE (greg)], val_buf, 4);
+	      greg++;
+	    }
+	  else
+	    {
+	      write_memory (sp + argoffset, val_buf, 4);
+	      argoffset += 4;
+	    }
+	}
+    }
+
+  target_store_registers (-1);
+  return sp;
+}
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.2
diff -u -p -r1.2 rs6000-tdep.c
--- rs6000-tdep.c	2000/02/15 21:17:04	1.2
+++ rs6000-tdep.c	2000/02/22 00:48:33
@@ -1,5 +1,5 @@
 /* Target-dependent code for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -1238,8 +1238,7 @@ skip_trampoline_code (pc)
 /* Determines whether the function FI has a frame on the stack or not.  */
 
 int
-frameless_function_invocation (fi)
-     struct frame_info *fi;
+rs6000_frameless_function_invocation (struct frame_info *fi)
 {
   CORE_ADDR func_start;
   struct rs6000_framedata fdata;
@@ -1273,8 +1272,7 @@ frameless_function_invocation (fi)
 /* Return the PC saved in a frame */
 
 unsigned long
-frame_saved_pc (fi)
-     struct frame_info *fi;
+rs6000_frame_saved_pc (struct frame_info *fi)
 {
   CORE_ADDR func_start;
   struct rs6000_framedata fdata;
@@ -1302,14 +1300,13 @@ frame_saved_pc (fi)
       if (fi->next->signal_handler_caller)
 	return read_memory_integer (fi->next->frame + SIG_FRAME_LR_OFFSET, 4);
       else
-	return read_memory_integer (rs6000_frame_chain (fi) + DEFAULT_LR_SAVE,
-				    4);
+	return read_memory_integer (FRAME_CHAIN (fi) + DEFAULT_LR_SAVE, 4);
     }
 
   if (fdata.lr_offset == 0)
     return read_register (LR_REGNUM);
 
-  return read_memory_integer (rs6000_frame_chain (fi) + fdata.lr_offset, 4);
+  return read_memory_integer (FRAME_CHAIN (fi) + fdata.lr_offset, 4);
 }
 
 /* If saved registers of frame FI are not known yet, read and cache them.
@@ -1480,7 +1477,7 @@ rs6000_frame_chain (thisframe)
     fp = read_memory_integer (thisframe->frame + SIG_FRAME_FP_OFFSET, 4);
   else if (thisframe->next != NULL
 	   && thisframe->next->signal_handler_caller
-	   && frameless_function_invocation (thisframe))
+	   && FRAMELESS_FUNCTION_INVOCATION (thisframe))
     /* A frameless function interrupted by a signal did not change the
        frame pointer.  */
     fp = FRAME_FP (thisframe);
Index: config/powerpc/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/linux.mh,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 linux.mh
--- linux.mh	1999/04/16 01:34:24	1.1.1.1
+++ linux.mh	2000/02/22 00:48:34
@@ -4,7 +4,7 @@ XM_FILE= xm-linux.h
 XDEPFILES= ser-tcp.o
 XM_CLIBS=
 
-NAT_FILE= ../nm-sysv4.h
-NATDEPFILES= solib.o corelow.o # infptrace.o inftarg.o fork-child.o core-aout.o core-regset.o
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o ppc-linux-nat.o linux-thread.o
 
 GDBSERVER_DEPFILES= low-linux.o
Index: config/powerpc/linux.mt
===================================================================
RCS file: linux.mt
diff -N linux.mt
--- /dev/null	Tue May  5 13:32:27 1998
+++ linux.mt	Mon Feb 21 16:48:34 2000
@@ -0,0 +1,3 @@
+# Target: Motorola PPC on Linux
+TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o
+TM_FILE= tm-linux.h
Index: config/powerpc/nm-linux.h
===================================================================
RCS file: nm-linux.h
diff -N nm-linux.h
--- /dev/null	Tue May  5 13:32:27 1998
+++ nm-linux.h	Mon Feb 21 16:48:34 2000
@@ -0,0 +1,64 @@
+/* IBM PowerPC native-dependent macros for GDB, the GNU debugger.
+   Copyright 1995 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef NM_LINUX_H
+#define NM_LINUX_H
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+#define U_REGS_OFFSET 0
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+        (addr) = ppc_register_u_addr ((blockend),(regno));
+
+/* No <sys/reg.h> */
+
+#define NO_SYS_REG_H
+
+#ifdef HAVE_LINK_H
+#include "solib.h"             /* Support for shared libraries. */
+#define SVR4_SHARED_LIBS
+#endif
+
+/* Support for Linuxthreads. */
+
+#ifdef __STDC__
+struct objfile;
+#endif
+
+extern void
+linuxthreads_new_objfile PARAMS ((struct objfile *objfile));
+#define target_new_objfile(OBJFILE) linuxthreads_new_objfile (OBJFILE)
+
+extern char *
+linuxthreads_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) linuxthreads_pid_to_str (PID)
+
+extern int
+linuxthreads_prepare_to_proceed PARAMS ((int step));
+#define PREPARE_TO_PROCEED(select_it) linuxthreads_prepare_to_proceed (1)
+
+
+#endif /* #ifndef NM_LINUX_H */
Index: config/powerpc/tm-linux.h
===================================================================
RCS file: tm-linux.h
diff -N tm-linux.h
--- /dev/null	Tue May  5 13:32:27 1998
+++ tm-linux.h	Mon Feb 21 16:48:34 2000
@@ -0,0 +1,113 @@
+/* Definitions to target GDB to Linux on 386.
+   Copyright 1992, 1993 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.  */
+
+#ifndef TM_LINUX_H
+#define TM_LINUX_H
+
+#include "powerpc/tm-ppc-eabi.h"
+
+#undef PUSH_ARGUMENTS
+
+/* We can single step on linux */
+#undef  SOFTWARE_SINGLE_STEP
+#define SOFTWARE_SINGLE_STEP(p,q) abort() /* Will never execute! */
+#undef  SOFTWARE_SINGLE_STEP_P
+#define SOFTWARE_SINGLE_STEP_P 0
+
+/* Make sure nexti gets the help it needs for debugging assembly code
+   without symbols */
+
+#define AT_SUBROUTINE_CALL_INSTRUCTION_TARGET(prevpc,stoppc) \
+   at_subroutine_call_instruction_target(prevpc,stoppc)
+extern int at_subroutine_call_instruction_target();
+
+/* We _want_ the SVR4 section offset calculations (see syms_from_objfile()
+   in symfile.c) */
+#undef IBM6000_TARGET
+
+/* Offset to saved PC in sigcontext, from <linux/signal.h>.  */
+#define SIGCONTEXT_PC_OFFSET 184
+
+/* Avoid warning from redefinition in tm-sysv4.h */
+#undef SKIP_TRAMPOLINE_CODE
+
+/* We need this file for the SOLIB_TRAMPOLINE stuff. */
+#include "tm-sysv4.h"
+
+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)
+
+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 PARAMS ((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_STORE_REGISTER(regno) ((regno) >= MQ_REGNUM)
+
+/* Linux doesn't use the PowerOpen ABI for function pointer representation */
+#undef CONVERT_FROM_FUNC_PTR_ADDR
+
+#if 0 /* If skip_prologue() isn't too greedy, we don't need this */
+/* There is some problem with the debugging symbols generated by the
+   compiler such that the debugging symbol for the first line of a
+   function overlap with the function prologue.  */
+#define PROLOGUE_FIRSTLINE_OVERLAP
+#endif
+
+/* Some versions of Linux have real-time signal support in the C library, and
+   some don't.  We have to include this file to find out.  */
+#include <signal.h>
+
+#ifdef __SIGRTMIN
+#define REALTIME_LO __SIGRTMIN
+#define REALTIME_HI (__SIGRTMAX + 1)
+#else
+#define REALTIME_LO 32
+#define REALTIME_HI 64
+#endif
+
+#endif  /* #ifndef TM_LINUX_H */
Index: config/powerpc/xm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/xm-linux.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 xm-linux.h
--- xm-linux.h	1999/07/07 20:16:41	1.1.1.2
+++ xm-linux.h	2000/02/22 00:48:34
@@ -1,3 +1,49 @@
+/* Native support for linux, for GDB, the GNU debugger.
+   Copyright (C) 1986, 1987, 1989, 1992 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.  */
+
+#ifndef XM_LINUX_H
+#define XM_LINUX_H
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_TERMIOS
+
+/* This is the amount to subtract from u.u_ar0
+   +   to get the offset in the core file of the register values.  */
+#define KERNEL_U_ADDR 0x0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined.  */
+#include <unistd.h>
+
+/* If you expect to use the mmalloc package to obtain mapped symbol files,
+   for now you have to specify some parameters that determine how gdb places
+   the mappings in it's address space.  See the comments in map_to_address()
+   for details.  This is expected to only be a short term solution.  Yes it
+   is a kludge.
+   FIXME:  Make this more automatic. */
+
+#define MMAP_BASE_ADDRESS      0x20000000      /* First mapping here */
+#define MMAP_INCREMENT         0x01000000      /* Increment to next mapping */
+
+#endif /* #ifndef XM_LINUX_H */
 /* Host definitions for a Sun 4, for GDB, the GNU debugger.
    Copyright 1996
    Free Software Foundation, Inc.
Index: config/rs6000/tm-rs6000.h
===================================================================
RCS file: /cvs/src/src/gdb/config/rs6000/tm-rs6000.h,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 tm-rs6000.h
--- tm-rs6000.h	1999/08/31 01:07:59	1.1.1.5
+++ tm-rs6000.h	2000/02/22 00:48:35
@@ -380,11 +380,10 @@ CORE_ADDR rs6000_frame_chain PARAMS ((st
    by FI does not have a frame on the stack associated with it.  If it
    does not, FRAMELESS is set to 1, else 0.  */
 
+extern int rs6000_frameless_function_invocation (struct frame_info *);
 #define FRAMELESS_FUNCTION_INVOCATION(FI) \
-  (frameless_function_invocation (FI))
+  (rs6000_frameless_function_invocation (FI))
 
-extern int frameless_function_invocation PARAMS ((struct frame_info *));
-
 #define INIT_FRAME_PC_FIRST(fromleaf, prev) \
   prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
 	      prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
@@ -407,9 +406,9 @@ extern void rs6000_init_extra_frame_info
 #define	DEFAULT_LR_SAVE 8
 
 /* Return saved PC from a frame */
-#define FRAME_SAVED_PC(FRAME)  frame_saved_pc (FRAME)
+#define FRAME_SAVED_PC(FRAME)  rs6000_frame_saved_pc (FRAME)
 
-extern unsigned long frame_saved_pc PARAMS ((struct frame_info *));
+extern unsigned long rs6000_frame_saved_pc (struct frame_info *);
 
 extern CORE_ADDR rs6000_frame_args_address PARAMS ((struct frame_info *));
 #define FRAME_ARGS_ADDRESS(FI) rs6000_frame_args_address (FI)


-- 
Kevin Buettner
kev@primenet.com, kevinb@redhat.com

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]