This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project. See the GDB home page for more information.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
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