From c7b443326321f7edc3859fe7c10344a830e3227a Mon Sep 17 00:00:00 2001 From: Rafal Jaworowski Date: Mon, 17 Nov 2008 16:32:57 +0000 Subject: [PATCH] Initial gdbserver support for ARM. Obtained from: Juniper Networks, Semihalf --- gnu/usr.bin/gdb/Makefile | 2 +- gnu/usr.bin/gdb/gdbserver/Makefile | 14 ++- gnu/usr.bin/gdb/gdbserver/fbsd-arm-low.c | 146 +++++++++++++++++++++++ gnu/usr.bin/gdb/gdbserver/reg-arm.c | 68 +++++++++++ 4 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 gnu/usr.bin/gdb/gdbserver/fbsd-arm-low.c create mode 100644 gnu/usr.bin/gdb/gdbserver/reg-arm.c diff --git a/gnu/usr.bin/gdb/Makefile b/gnu/usr.bin/gdb/Makefile index 8f2870bb8637..5cca8c16f857 100644 --- a/gnu/usr.bin/gdb/Makefile +++ b/gnu/usr.bin/gdb/Makefile @@ -2,7 +2,7 @@ SUBDIR= doc libgdb gdb gdbtui kgdb -.if ${MACHINE_ARCH} == "i386" +.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "arm" SUBDIR+=gdbserver .endif diff --git a/gnu/usr.bin/gdb/gdbserver/Makefile b/gnu/usr.bin/gdb/gdbserver/Makefile index 191232d89d2f..29ea01b5de4f 100644 --- a/gnu/usr.bin/gdb/gdbserver/Makefile +++ b/gnu/usr.bin/gdb/gdbserver/Makefile @@ -10,9 +10,17 @@ GDBDIR= ${.CURDIR}/../../../../contrib/gdb PROG= gdbserver -SRCS= i387-fp.c inferiors.c mem-break.c regcache.c remote-utils.c \ - server.c signals.c target.c reg-i386.c utils.c -SRCS+= fbsd-low.c fbsd-i386-low.c +SRCS= inferiors.c mem-break.c regcache.c remote-utils.c \ + server.c signals.c target.c utils.c +SRCS+= fbsd-low.c + +.if ${MACHINE_ARCH} == "i386" +SRCS+= fbsd-i386-low.c i387-fp.c reg-i386.c +.endif + +.if ${MACHINE_ARCH} == "arm" +SRCS+= fbsd-arm-low.c reg-arm.c +.endif #CFLAGS+= -I${.CURDIR}/../arch/${MACHINE_ARCH} CFLAGS+= -I${GDBDIR}/gdb/gdbserver diff --git a/gnu/usr.bin/gdb/gdbserver/fbsd-arm-low.c b/gnu/usr.bin/gdb/gdbserver/fbsd-arm-low.c new file mode 100644 index 000000000000..faea705f94ff --- /dev/null +++ b/gnu/usr.bin/gdb/gdbserver/fbsd-arm-low.c @@ -0,0 +1,146 @@ +/* FreeBSD/ARM specific low level interface, for the remote server for GDB. + Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004 + 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 +__FBSDID("$FreeBSD$"); + +#include "server.h" +#include "fbsd-low.h" + +#ifdef HAVE_SYS_REG_H +#include +#endif + +#include +#include + +#define arm_num_regs 26 + +static int arm_regmap[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + -1, -1, -1, -1, -1, -1, -1, -1, -1, + 64 +}; + +static int +arm_cannot_store_register (int regno) +{ + return (regno >= arm_num_regs); +} + +static int +arm_cannot_fetch_register (int regno) +{ + return (regno >= arm_num_regs); +} + +extern int debug_threads; + +static CORE_ADDR +arm_get_pc () +{ + unsigned long pc; + collect_register_by_name ("pc", &pc); + if (debug_threads) + fprintf (stderr, "stop pc is %08lx\n", pc); + return pc; +} + +static void +arm_set_pc (CORE_ADDR pc) +{ + unsigned long newpc = pc; + supply_register_by_name ("pc", &newpc); +} + +/* Correct in either endianness. We do not support Thumb yet. */ +static const unsigned long arm_breakpoint = 0xef9f0001; +#define arm_breakpoint_len 4 + +static int +arm_breakpoint_at (CORE_ADDR where) +{ + unsigned long insn; + + (*the_target->read_memory) (where, (char *) &insn, 4); + if (insn == arm_breakpoint) + return 1; + + /* If necessary, recognize more trap instructions here. GDB only uses the + one. */ + return 0; +} + +/* We only place breakpoints in empty marker functions, and thread locking + is outside of the function. So rather than importing software single-step, + we can just run until exit. */ +static CORE_ADDR +arm_reinsert_addr () +{ + unsigned long pc; + collect_register_by_name ("lr", &pc); + return pc; +} + +static void +arm_fill_gregset (void *buf) +{ + int i; + + for (i = 0; i < arm_num_regs; i++) + if (arm_regmap[i] != -1) + collect_register (i, ((char *) buf) + arm_regmap[i]); + +} + +static void +arm_store_gregset (const void *buf) +{ + int i; + + for (i = 0; i < arm_num_regs; i++) + if (arm_regmap[i] != -1) + supply_register (i, ((char *) buf) + arm_regmap[i]); + +} + + +struct regset_info target_regsets[] = { + {PT_GETREGS, PT_SETREGS, sizeof (struct reg), + GENERAL_REGS, + arm_fill_gregset, arm_store_gregset }, + { 0, 0, -1, -1, NULL, NULL } +}; + +struct fbsd_target_ops the_low_target = { + arm_num_regs, + arm_regmap, + arm_cannot_fetch_register, + arm_cannot_store_register, + arm_get_pc, + arm_set_pc, + (const char *) &arm_breakpoint, + arm_breakpoint_len, + arm_reinsert_addr, + 0, + arm_breakpoint_at, +}; diff --git a/gnu/usr.bin/gdb/gdbserver/reg-arm.c b/gnu/usr.bin/gdb/gdbserver/reg-arm.c new file mode 100644 index 000000000000..50379bfed756 --- /dev/null +++ b/gnu/usr.bin/gdb/gdbserver/reg-arm.c @@ -0,0 +1,68 @@ +/* *INDENT-OFF* */ /* THIS FILE IS GENERATED */ + +/* A register protocol for GDB, the GNU debugger. + Copyright 2001, 2002 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. */ + +/* This file was created with the aid of ``regdat.sh'' and ``reg-arm.dat''. */ + +#include +__FBSDID("$FreeBSD$"); + +#include "regdef.h" +#include "regcache.h" + +struct reg regs_arm[] = { + { "r0", 0, 32 }, + { "r1", 32, 32 }, + { "r2", 64, 32 }, + { "r3", 96, 32 }, + { "r4", 128, 32 }, + { "r5", 160, 32 }, + { "r6", 192, 32 }, + { "r7", 224, 32 }, + { "r8", 256, 32 }, + { "r9", 288, 32 }, + { "r10", 320, 32 }, + { "r11", 352, 32 }, + { "r12", 384, 32 }, + { "sp", 416, 32 }, + { "lr", 448, 32 }, + { "pc", 480, 32 }, + { "f0", 512, 96 }, + { "f1", 608, 96 }, + { "f2", 704, 96 }, + { "f3", 800, 96 }, + { "f4", 896, 96 }, + { "f5", 992, 96 }, + { "f6", 1088, 96 }, + { "f7", 1184, 96 }, + { "fps", 1280, 32 }, + { "cpsr", 1312, 32 }, +}; + +const char *expedite_regs_arm[] = { "r11", "sp", "pc", 0 }; + +void +init_registers () +{ + set_register_cache (regs_arm, + sizeof (regs_arm) / sizeof (regs_arm[0])); + gdbserver_expedite_regs = expedite_regs_arm; +}