summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2006-07-22 15:27:18 +0000
committerobrien <obrien@FreeBSD.org>2006-07-22 15:27:18 +0000
commit100c4dc194adf9364a75aa0fc824559a0f372b7d (patch)
tree2bb507b42ccb1dae8fdf46858970fdda2042888c /gnu
parentec64bbcbdf5fc51b2ac9192f15f3773380f4c492 (diff)
downloadFreeBSD-src-100c4dc194adf9364a75aa0fc824559a0f372b7d.zip
FreeBSD-src-100c4dc194adf9364a75aa0fc824559a0f372b7d.tar.gz
Add initial platform support.
Submitted by: cognet
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/gdb/kgdb/trgt_arm.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_arm.c b/gnu/usr.bin/gdb/kgdb/trgt_arm.c
new file mode 100644
index 0000000..b9b95c6
--- /dev/null
+++ b/gnu/usr.bin/gdb/kgdb/trgt_arm.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2004 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/pcb.h>
+#include <machine/frame.h>
+#include <err.h>
+#include <kvm.h>
+#include <string.h>
+
+#include <defs.h>
+#include <target.h>
+#include <gdbthread.h>
+#include <inferior.h>
+#include <regcache.h>
+#include <frame-unwind.h>
+#include <arm-tdep.h>
+
+#include "kgdb.h"
+
+void
+kgdb_trgt_fetch_registers(int regno __unused)
+{
+ struct kthr *kt;
+ struct pcb pcb;
+ int i, reg;
+
+ kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid));
+ if (kt == NULL)
+ return;
+ if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
+ warnx("kvm_read: %s", kvm_geterr(kvm));
+ memset(&pcb, 0, sizeof(pcb));
+ }
+ for (i = ARM_A1_REGNUM + 8; i <= ARM_SP_REGNUM; i++) {
+ supply_register(i, (char *)&pcb.un_32.pcb32_r8 +
+ (i - (ARM_A1_REGNUM + 8 )) * 4);
+ }
+ if (pcb.un_32.pcb32_sp != 0) {
+ for (i = 0; i < 4; i++) {
+ if (kvm_read(kvm, pcb.un_32.pcb32_sp + (i) * 4,
+ &reg, 4) != 4) {
+ warnx("kvm_read: %s", kvm_geterr(kvm));
+ break;
+ }
+ supply_register(ARM_A1_REGNUM + 4 + i, (char *)&reg);
+ }
+ if (kvm_read(kvm, pcb.un_32.pcb32_sp + 4 * 4, &reg, 4) != 4)
+ warnx("kvm_read :%s", kvm_geterr(kvm));
+ else
+ supply_register(ARM_PC_REGNUM, (char *)&reg);
+ }
+}
+
+void
+kgdb_trgt_store_registers(int regno __unused)
+{
+ fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
+}
+
+struct kgdb_frame_cache {
+ CORE_ADDR fp;
+ CORE_ADDR sp;
+};
+
+static int kgdb_trgt_frame_offset[26] = {
+ offsetof(struct trapframe, tf_r0),
+ offsetof(struct trapframe, tf_r1),
+ offsetof(struct trapframe, tf_r2),
+ offsetof(struct trapframe, tf_r3),
+ offsetof(struct trapframe, tf_r4),
+ offsetof(struct trapframe, tf_r5),
+ offsetof(struct trapframe, tf_r6),
+ offsetof(struct trapframe, tf_r7),
+ offsetof(struct trapframe, tf_r8),
+ offsetof(struct trapframe, tf_r9),
+ offsetof(struct trapframe, tf_r10),
+ offsetof(struct trapframe, tf_r11),
+ offsetof(struct trapframe, tf_r12),
+ offsetof(struct trapframe, tf_svc_sp),
+ offsetof(struct trapframe, tf_svc_lr),
+ offsetof(struct trapframe, tf_pc),
+ -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ offsetof(struct trapframe, tf_spsr)
+};
+
+static struct kgdb_frame_cache *
+kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
+{
+ char buf[MAX_REGISTER_SIZE];
+ struct kgdb_frame_cache *cache;
+
+ cache = *this_cache;
+ if (cache == NULL) {
+ cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
+ *this_cache = cache;
+ frame_unwind_register(next_frame, ARM_SP_REGNUM, buf);
+ cache->sp = extract_unsigned_integer(buf,
+ register_size(current_gdbarch, ARM_SP_REGNUM));
+ frame_unwind_register(next_frame, ARM_FP_REGNUM, buf);
+ cache->fp = extract_unsigned_integer(buf,
+ register_size(current_gdbarch, ARM_FP_REGNUM));
+ }
+ return (cache);
+}
+
+static void
+kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct kgdb_frame_cache *cache;
+
+ cache = kgdb_trgt_frame_cache(next_frame, this_cache);
+ *this_id = frame_id_build(cache->fp, 0);
+}
+
+static void
+kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
+ void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
+ CORE_ADDR *addrp, int *realnump, void *valuep)
+{
+ char dummy_valuep[MAX_REGISTER_SIZE];
+ struct kgdb_frame_cache *cache;
+ int ofs, regsz;
+
+ regsz = register_size(current_gdbarch, regnum);
+
+ if (valuep == NULL)
+ valuep = dummy_valuep;
+ memset(valuep, 0, regsz);
+ *optimizedp = 0;
+ *addrp = 0;
+ *lvalp = not_lval;
+ *realnump = -1;
+
+ ofs = (regnum >= 0 && regnum <= ARM_PS_REGNUM)
+ ? kgdb_trgt_frame_offset[regnum] : -1;
+ if (ofs == -1)
+ return;
+
+ cache = kgdb_trgt_frame_cache(next_frame, this_cache);
+ *addrp = cache->sp + ofs;
+ *lvalp = lval_memory;
+ target_read_memory(*addrp, valuep, regsz);
+}
+
+static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
+ UNKNOWN_FRAME,
+ &kgdb_trgt_trapframe_this_id,
+ &kgdb_trgt_trapframe_prev_register
+};
+
+const struct frame_unwind *
+kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
+{
+ char *pname;
+ CORE_ADDR pc;
+
+ pc = frame_pc_unwind(next_frame);
+ pname = NULL;
+ find_pc_partial_function(pc, &pname, NULL, NULL);
+ if (pname == NULL)
+ return (NULL);
+ if (strcmp(pname, "Laddress_exception_entry") == 0 ||
+ strcmp(pname, "undefined_entry") == 0 ||
+ strcmp(pname, "exception_exit") == 0 ||
+ strcmp(pname, "irq_entry") == 0)
+ return (&kgdb_trgt_trapframe_unwind);
+ return (NULL);
+}
OpenPOWER on IntegriCloud