support for ARM GNU/Linux
Philip Blundell
philb@gnu.org
Mon Apr 12 13:01:00 GMT 1999
This patch adds support for GNU/Linux running on ARM systems.
p.
1999-04-12 Philip Blundell <philb@gnu.org>
Scott Bambrough <scottb@corelcomputer.com>
Support for ARM GNU/Linux:
* configure.tgt: Recognize arm*-*-linux* configuration. Set
cpu name to `arm' for any `arm*-*-*' configuration name.
* configure.host: Likewise.
* config/arm/linux.mh, config/arm/linux.mt: New files.
* config/arm/tm-linux.h, config-arm/xm-linux.h,
config/arm/nm-linux.h: Likewise.
* armlnx-tdep.c, armlnx-xdep.c, armlnx-nat.c: Likewise.
* arm-tdep.c (ARM_LE_BREAKPOINT, ARM_BE_BREAKPOINT,
THUMB_LE_BREAKPOINT, THUMB_BE_BREAKPOINT, LOWEST_PC,
LITTLE_BREAKPOINT, BIG_BREAKPOINT): Move
definitions to...
* config/arm/tm-arm.h: ... here.
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/arm-tdep.c gdb/arm-tdep.c
--- /home/phil/gdb/clean/gdb-4.17/gdb/arm-tdep.c Sun Apr 11 21:56:56 1999
+++ gdb/arm-tdep.c Sun Apr 11 19:06:08 1999
@@ -61,7 +61,6 @@
CORE_ADDR chain;
struct frame_info *thisframe;
{
-#define LOWEST_PC 0x20 /* the first 0x20 bytes are the trap vectors. */
return (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC));
}
@@ -1487,17 +1486,6 @@
else
return print_insn_little_arm (memaddr, info);
}
-
-/* Sequence of bytes for breakpoint instruction. */
-#define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7} /* Recognized illegal opcodes */
-#define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
-#define THUMB_LE_BREAKPOINT {0xfe,0xdf}
-#define THUMB_BE_BREAKPOINT {0xdf,0xfe}
-
-/* The following has been superseded by BREAKPOINT_FOR_PC, but
- is defined merely to keep mem-break.c happy. */
-#define LITTLE_BREAKPOINT ARM_LE_BREAKPOINT
-#define BIG_BREAKPOINT ARM_BE_BREAKPOINT
/* This function implements the BREAKPOINT_FROM_PC macro. It uses the program
counter value to determine whether a 16- or 32-bit breakpoint should be
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/armlnx-nat.c gdb/armlnx-nat.c
--- /home/phil/gdb/clean/gdb-4.17/gdb/armlnx-nat.c Thu Jan 1 01:00:00 1970
+++ gdb/armlnx-nat.c Sun Apr 11 19:11:51 1999
@@ -0,0 +1,148 @@
+/* ARM native support for SYSV systems (pre-SVR4).
+ Copyright (C) 1988, 89, 91, 92, 94, 96, 99 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 "inferior.h"
+#include <sys/ptrace.h>
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+
+int
+arm_register_u_addr(blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ return blockend + REGISTER_BYTE(regnum);
+}
+
+int
+kernel_u_size()
+{
+ return (sizeof (struct user));
+}
+
+#ifdef HAVE_GREGSET_T
+#include <sys/procfs.h>
+
+/* Given a pointer to a general register set in /proc format
+ (gregset_t *), unpack the register contents and supply them as
+ gdb's idea of the current register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ int i;
+
+ for (i = 0; i < 26; i++)
+ supply_register(i, (char *) (*gregsetp + i));
+}
+
+#endif
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register int i;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ struct user u;
+ unsigned int offset = (char*)&u.u_ar0 - (char*)&u;
+ offset = ptrace(PT_READ_U,inferior_pid,
+ (PTRACE_ARG3_TYPE)offset,0) - KERNEL_U_ADDR;
+
+ registers_fetched();
+
+ for (regno = 0; regno < NUM_GREGS; regno++)
+ {
+ regaddr = offset + regno * sizeof(long);
+ *(int*)&buf[0] = ptrace(PT_READ_U,inferior_pid,
+ (PTRACE_ARG3_TYPE)regaddr,0);
+ if (regno == PC_REGNUM)
+ *(int*)&buf[0] = GET_PC_PART(*(int*)&buf[0]);
+ supply_register(regno,buf);
+ }
+
+ *(int*)&buf[0] = ptrace(PT_READ_U,inferior_pid,
+ (PTRACE_ARG3_TYPE)(offset + PC_REGNUM*sizeof(long)),
+ 0);
+ supply_register (PS_REGNUM,buf); /* set virtual register ps same as pc */
+
+ /* read the floating point registers */
+ offset = (char*)&u.u_fp0 - (char *)&u;
+ *(int*)buf = ptrace(PT_READ_U,inferior_pid,(PTRACE_ARG3_TYPE)offset,0);
+ supply_register(FPS_REGNUM,buf);
+
+ for (regno = 16; regno < 24; regno++) {
+ regaddr = offset /* + 4 */ + 12 * (regno - 16);
+ for (i = 0; i < 12; i += sizeof(int))
+ *(int*) &buf[i] = ptrace(PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE)(regaddr + i), 0);
+ supply_register(regno,buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct user u;
+ unsigned long value;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
+ - KERNEL_U_ADDR;
+
+ if (regno >= 0) {
+ if (regno >= 16) return;
+ regaddr = offset + 4 * regno;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else for (regno = 0; regno < 15; regno++)
+ {
+ regaddr = offset + regno * 4;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/armlnx-tdep.c gdb/armlnx-tdep.c
--- /home/phil/gdb/clean/gdb-4.17/gdb/armlnx-tdep.c Thu Jan 1 01:00:00 1970
+++ gdb/armlnx-tdep.c Sun Apr 11 14:12:18 1999
@@ -0,0 +1,65 @@
+/* Target-dependent code for the ArmLinux, for GDB, the GNU Debugger.
+ Copyright 1988, 1989, 1991, 1992, 1993, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+/* APCS (ARM procedure call standard) defines the following prologue:
+
+ mov ip, sp
+ [stmfd sp!, {a1,a2,a3,a4}]
+ stmfd sp!, {...,fp,ip,lr,pc}
+ [stfe f7, [sp, #-12]!]
+ [stfe f6, [sp, #-12]!]
+ [stfe f5, [sp, #-12]!]
+ [stfe f4, [sp, #-12]!]
+ sub fp, ip, #nn // nn == 20 or 4 depending on second ins
+*/
+
+void
+arm_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char regbuf[];
+ void *valbuf;
+{
+ if (TYPE_CODE_FLT == TYPE_CODE(type))
+ convert_from_extended(regbuf + REGISTER_BYTE(F0_REGNUM), valbuf);
+ else
+ memcpy(valbuf, regbuf, TYPE_LENGTH(type));
+}
+
+/* not in generic code, macro in tm-arm.h */
+void
+arm_store_return_value(type, valbuf)
+ struct type *type;
+ void *valbuf;
+{
+ if (TYPE_CODE_FLT == TYPE_CODE(type)) {
+ char _buf[MAX_REGISTER_RAW_SIZE];
+ convert_to_extended(valbuf, _buf);
+ write_register_bytes(REGISTER_BYTE(F0_REGNUM), _buf, MAX_REGISTER_RAW_SIZE);
+ } else
+ write_register_bytes(0, valbuf, TYPE_LENGTH(type));
+}
+
+void
+_initialize_linux_tdep(void)
+{
+}
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/linux.mh gdb/config/arm/linux.mh
--- /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/linux.mh Thu Jan 1 01:00:00 1970
+++ gdb/config/arm/linux.mh Sun Apr 11 16:38:20 1999
@@ -0,0 +1,8 @@
+# Host: ARM running GNU/Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o armlnx-nat.o
+GDBSERVER_DEPFILES= low-linux.o
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/linux.mt gdb/config/arm/linux.mt
--- /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/linux.mt Thu Jan 1 01:00:00 1970
+++ gdb/config/arm/linux.mt Sun Apr 11 15:47:57 1999
@@ -0,0 +1,6 @@
+# Target: ARM running GNU/Linux with a.out and ELF
+
+TDEPFILES= armlnx-tdep.o arm-tdep.o
+TM_FILE= tm-linux.h
+
+GDBSERVER_DEPFILES= low-linux.o
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/nm-linux.h gdb/config/arm/nm-linux.h
--- /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/nm-linux.h Thu Jan 1 01:00:00 1970
+++ gdb/config/arm/nm-linux.h Sun Apr 11 19:46:55 1999
@@ -0,0 +1,45 @@
+/* Native machine definitions for GDB on ARM running GNU/Linux
+ Copyright (C) 1999 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 NM_LINUX_H
+#define NM_LINUX_H
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+/* We define this if link.h is available, because with ELF we use SVR4 style
+ shared libraries. */
+#ifdef HAVE_LINK_H
+#define SVR4_SHARED_LIBS
+#include "solib.h" /* Support for shared libraries. */
+#endif
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = arm_register_u_addr ((blockend),(regno));
+
+#ifdef __ARMEB__
+#define HOST_BYTE_ORDER BIG_ENDIAN
+#else
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#endif /* NM_LINUX_H */
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/tm-arm.h gdb/config/arm/tm-arm.h
--- /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/tm-arm.h Sun Apr 11 21:56:59 1999
+++ gdb/config/arm/tm-arm.h Sun Apr 11 19:12:27 1999
@@ -118,6 +120,7 @@
that I can clear the status bits from pc (register 15) */
#define NUM_REGS 26
+#define NUM_GREGS 16
/* An array of names of registers. */
@@ -451,3 +454,16 @@
#undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc, name) 0
+
+/* Sequence of bytes for breakpoint instruction. */
+#define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7} /* Recognized illegal opcodes */
+#define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
+#define THUMB_LE_BREAKPOINT {0xfe,0xdf}
+#define THUMB_BE_BREAKPOINT {0xdf,0xfe}
+
+/* The following has been superseded by BREAKPOINT_FOR_PC, but
+ is defined merely to keep mem-break.c happy. */
+#define LITTLE_BREAKPOINT ARM_LE_BREAKPOINT
+#define BIG_BREAKPOINT ARM_BE_BREAKPOINT
+
+#define LOWEST_PC 0x20 /* the first 0x20 bytes are the trap vectors. */
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/tm-linux.h gdb/config/arm/tm-linux.h
--- /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/tm-linux.h Thu Jan 1 01:00:00 1970
+++ gdb/config/arm/tm-linux.h Sun Apr 11 17:37:22 1999
@@ -0,0 +1,93 @@
+/* Definitions to target GDB to ARM GNU/Linux
+ Copyright 1992, 1993, 1999 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__
+
+/* Scott: SHLIBLEN from bfd/riscix.c. */
+#define SHLIBLEN 60
+
+/* Offset to saved PC in sigcontext, from <linux/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET (sizeof(unsigned long) + sizeof(long) * 15)
+
+/* Number of traps that happen between exec'ing the shell to run an
+ inferior, and when we finally get to the inferior code. This is 2
+ on most implementations. */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* The following is used in the macro CALL_DUMMY in tm-arm.h. */
+#define OS_BKPT_SWI 0xef9f0001
+
+/* Add command to set APCS_32 debugger variable. Used to determine if
+ 32 bit or 26 bit program counter is being used. Set to 1 to add the
+ command to the debugger. */
+#define ADD_SET_APCS_COMMAND 0
+
+/* It is unknown which, if any, SVR4 assemblers do not accept dollar signs
+ in identifiers. The default in G++ is to use dots instead, for all SVR4
+ systems, so we make that our default also. FIXME: There should be some
+ way to get G++ to tell us what CPLUS_MARKER it is using, perhaps by
+ stashing it in the debugging information as part of the name of an
+ invented symbol ("gcc_cplus_marker$" for example). */
+
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
+
+/* Include the generic ARM target header. */
+#include "arm/tm-arm.h"
+
+/* The following are used in arm_breakpoint_from_pc() in arm-tdep.c */
+#undef ARM_LE_BREAKPOINT
+#define ARM_LE_BREAKPOINT {0x01,0x00,0x9f,0xef} /* swi 0x9f0001 */
+#undef ARM_BE_BREAKPOINT
+#define ARM_BE_BREAKPOINT {0xef,0x9f,0x00,0x01}
+
+/* This is used in the macro FRAME_CHAIN_VALID in tm-arm.h. */
+#undef LOWEST_PC
+#define LOWEST_PC 0x8000 /* the first page is not writable in ARM Linux. */
+
+/* For SVR4 shared libraries, each call to a library routine goes through
+ a small piece of trampoline code in the ".plt" section.
+ The horribly ugly wait_for_inferior() routine uses this macro to detect
+ when we have stepped into one of these fragments.
+ We do not use lookup_solib_trampoline_symbol_by_pc, because
+ we cannot always find the shared library trampoline symbols
+ (e.g. on Irix5). */
+extern int in_plt_section PARAMS ((CORE_ADDR, char *));
+
+/* If PC is in a shared library trampoline code, return the PC
+ where the function itself actually starts. If not, return 0. */
+#undef SKIP_TRAMPOLINE_CODE
+#define SKIP_TRAMPOLINE_CODE(pc) \
+ ((in_plt_section((pc), NULL) ? find_solib_trampoline_target (pc) \
+ : arm_skip_stub (pc)))
+
+#undef IN_SOLIB_CALL_TRAMPOLINE
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) (in_plt_section((pc), (name)) \
+ || arm_in_call_stub (pc, name))
+
+#ifndef GET_PC_PART
+#define GET_PC_PART(addr) ADDR_BITS_REMOVE(addr)
+#endif
+
+#ifndef SET_PC_PART
+#define SET_PC_PART(old,new) new
+#endif
+
+#endif /* #ifndef TM_LINUX_H */
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/xm-linux.h gdb/config/arm/xm-linux.h
--- /home/phil/gdb/clean/gdb-4.17/gdb/config/arm/xm-linux.h Thu Jan 1 01:00:00 1970
+++ gdb/config/arm/xm-linux.h Sun Apr 11 14:52:44 1999
@@ -0,0 +1,36 @@
+/* Native support for Linux, for GDB, the GNU debugger.
+ Copyright (C) 1999 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__
+
+#include "arm/xm-arm.h"
+
+#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>
+
+#endif /* __XM_LINUX_H__ */
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/configure.host gdb/configure.host
--- /home/phil/gdb/clean/gdb-4.17/gdb/configure.host Sun Apr 11 21:57:06 1999
+++ gdb/configure.host Sun Apr 11 15:13:31 1999
@@ -11,6 +11,7 @@
case "${host_cpu}" in
alpha*) gdb_host_cpu=alpha ;;
+arm*) gdb_host_cpu=arm ;;
c[12]) gdb_host_cpu=convex ;;
hppa*) gdb_host_cpu=pa ;;
i[3456]86*) gdb_host_cpu=i386 ;;
@@ -35,6 +36,7 @@
alpha*-*-osf[3456789]*) gdb_host=alpha-osf3 ;;
alpha*-*-linux*) gdb_host=alpha-linux ;;
+arm*-*-linux*) gdb_host=linux ;;
arm-*-*) gdb_host=arm ;;
c[12]-*-*) gdb_host=convex ;;
diff -u --recursive --new-file /home/phil/gdb/clean/gdb-4.17/gdb/configure.tgt gdb/configure.tgt
--- /home/phil/gdb/clean/gdb-4.17/gdb/configure.tgt Sun Apr 11 21:57:07 1999
+++ gdb/configure.tgt Sun Apr 11 15:19:26 1999
@@ -13,6 +13,7 @@
case "${target_cpu}" in
alpha*) gdb_target_cpu=alpha ;;
+arm*) gdb_target_cpu=arm ;;
c[12]) gdb_target_cpu=convex ;;
hppa*) gdb_target_cpu=pa ;;
i[3456]86*) gdb_target_cpu=i386 ;;
@@ -50,6 +51,8 @@
arc-*-*) gdb_target=arc ;;
+arm*-*-linux*) gdb_target=linux
+ configdirs="${configdirs} gdbserver" ;;
arm-*-* | thumb-*-* | strongarm-*-*) gdb_target=arm
# rdi doesn't work for wingdb yet
More information about the Gdb-patches
mailing list