1160581Sobrien/* 2160581Sobrien * Copyright (c) 2004 Marcel Moolenaar 3160581Sobrien * All rights reserved. 4160581Sobrien * 5160581Sobrien * Redistribution and use in source and binary forms, with or without 6160581Sobrien * modification, are permitted provided that the following conditions 7160581Sobrien * are met: 8160581Sobrien * 9160581Sobrien * 1. Redistributions of source code must retain the above copyright 10160581Sobrien * notice, this list of conditions and the following disclaimer. 11160581Sobrien * 2. Redistributions in binary form must reproduce the above copyright 12160581Sobrien * notice, this list of conditions and the following disclaimer in the 13160581Sobrien * documentation and/or other materials provided with the distribution. 14160581Sobrien * 15160581Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16160581Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17160581Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18160581Sobrien * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19160581Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20160581Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21160581Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22160581Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23160581Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24160581Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25160581Sobrien */ 26160581Sobrien 27160581Sobrien#include <sys/cdefs.h> 28160581Sobrien__FBSDID("$FreeBSD$"); 29160581Sobrien 30160581Sobrien#include <sys/types.h> 31162303Simp#ifndef CROSS_DEBUGGER 32160581Sobrien#include <machine/pcb.h> 33160581Sobrien#include <machine/frame.h> 34162303Simp#include <machine/armreg.h> 35162303Simp#endif 36160581Sobrien#include <err.h> 37160581Sobrien#include <kvm.h> 38160581Sobrien#include <string.h> 39160581Sobrien 40160581Sobrien#include <defs.h> 41160581Sobrien#include <target.h> 42160581Sobrien#include <gdbthread.h> 43160581Sobrien#include <inferior.h> 44160581Sobrien#include <regcache.h> 45160581Sobrien#include <frame-unwind.h> 46160581Sobrien#include <arm-tdep.h> 47160581Sobrien 48160581Sobrien#include "kgdb.h" 49160581Sobrien 50246893SmarcelCORE_ADDR 51246893Smarcelkgdb_trgt_core_pcb(u_int cpuid) 52246893Smarcel{ 53246893Smarcel return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); 54246893Smarcel} 55246893Smarcel 56160581Sobrienvoid 57160581Sobrienkgdb_trgt_fetch_registers(int regno __unused) 58160581Sobrien{ 59162303Simp#ifndef CROSS_DEBUGGER 60160581Sobrien struct kthr *kt; 61160581Sobrien struct pcb pcb; 62160581Sobrien int i, reg; 63163440Sjhb 64178713Sjhb kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 65160581Sobrien if (kt == NULL) 66160581Sobrien return; 67160581Sobrien if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 68160581Sobrien warnx("kvm_read: %s", kvm_geterr(kvm)); 69160581Sobrien memset(&pcb, 0, sizeof(pcb)); 70160581Sobrien } 71160581Sobrien for (i = ARM_A1_REGNUM + 8; i <= ARM_SP_REGNUM; i++) { 72163440Sjhb supply_register(i, (char *)&pcb.un_32.pcb32_r8 + 73160581Sobrien (i - (ARM_A1_REGNUM + 8 )) * 4); 74160581Sobrien } 75160581Sobrien if (pcb.un_32.pcb32_sp != 0) { 76160581Sobrien for (i = 0; i < 4; i++) { 77160581Sobrien if (kvm_read(kvm, pcb.un_32.pcb32_sp + (i) * 4, 78160581Sobrien ®, 4) != 4) { 79160581Sobrien warnx("kvm_read: %s", kvm_geterr(kvm)); 80160581Sobrien break; 81160581Sobrien } 82160581Sobrien supply_register(ARM_A1_REGNUM + 4 + i, (char *)®); 83160581Sobrien } 84160581Sobrien if (kvm_read(kvm, pcb.un_32.pcb32_sp + 4 * 4, ®, 4) != 4) 85160581Sobrien warnx("kvm_read :%s", kvm_geterr(kvm)); 86160581Sobrien else 87160581Sobrien supply_register(ARM_PC_REGNUM, (char *)®); 88160581Sobrien } 89162303Simp#endif 90160581Sobrien} 91160581Sobrien 92160581Sobrienvoid 93160581Sobrienkgdb_trgt_store_registers(int regno __unused) 94160581Sobrien{ 95160581Sobrien fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); 96160581Sobrien} 97160581Sobrien 98178670Sjhbvoid 99178670Sjhbkgdb_trgt_new_objfile(struct objfile *objfile) 100178670Sjhb{ 101178670Sjhb} 102178670Sjhb 103162303Simp#ifndef CROSS_DEBUGGER 104160581Sobrienstruct kgdb_frame_cache { 105160581Sobrien CORE_ADDR fp; 106160581Sobrien CORE_ADDR sp; 107160581Sobrien}; 108160581Sobrien 109160581Sobrienstatic int kgdb_trgt_frame_offset[26] = { 110160581Sobrien offsetof(struct trapframe, tf_r0), 111160581Sobrien offsetof(struct trapframe, tf_r1), 112160581Sobrien offsetof(struct trapframe, tf_r2), 113160581Sobrien offsetof(struct trapframe, tf_r3), 114160581Sobrien offsetof(struct trapframe, tf_r4), 115160581Sobrien offsetof(struct trapframe, tf_r5), 116160581Sobrien offsetof(struct trapframe, tf_r6), 117160581Sobrien offsetof(struct trapframe, tf_r7), 118160581Sobrien offsetof(struct trapframe, tf_r8), 119160581Sobrien offsetof(struct trapframe, tf_r9), 120160581Sobrien offsetof(struct trapframe, tf_r10), 121160581Sobrien offsetof(struct trapframe, tf_r11), 122160581Sobrien offsetof(struct trapframe, tf_r12), 123160581Sobrien offsetof(struct trapframe, tf_svc_sp), 124160581Sobrien offsetof(struct trapframe, tf_svc_lr), 125160581Sobrien offsetof(struct trapframe, tf_pc), 126160581Sobrien -1, -1, -1, -1, -1, -1, -1, -1, -1, 127160581Sobrien offsetof(struct trapframe, tf_spsr) 128160581Sobrien}; 129160581Sobrien 130160581Sobrienstatic struct kgdb_frame_cache * 131160581Sobrienkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 132160581Sobrien{ 133160581Sobrien char buf[MAX_REGISTER_SIZE]; 134160581Sobrien struct kgdb_frame_cache *cache; 135160581Sobrien 136160581Sobrien cache = *this_cache; 137160581Sobrien if (cache == NULL) { 138160581Sobrien cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 139160581Sobrien *this_cache = cache; 140160581Sobrien frame_unwind_register(next_frame, ARM_SP_REGNUM, buf); 141160581Sobrien cache->sp = extract_unsigned_integer(buf, 142160581Sobrien register_size(current_gdbarch, ARM_SP_REGNUM)); 143160581Sobrien frame_unwind_register(next_frame, ARM_FP_REGNUM, buf); 144160581Sobrien cache->fp = extract_unsigned_integer(buf, 145160581Sobrien register_size(current_gdbarch, ARM_FP_REGNUM)); 146160581Sobrien } 147160581Sobrien return (cache); 148160581Sobrien} 149160581Sobrien 150162303Simpstatic int is_undef; 151162303Simp 152160581Sobrienstatic void 153160581Sobrienkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 154160581Sobrien struct frame_id *this_id) 155160581Sobrien{ 156160581Sobrien struct kgdb_frame_cache *cache; 157160581Sobrien 158160581Sobrien cache = kgdb_trgt_frame_cache(next_frame, this_cache); 159160581Sobrien *this_id = frame_id_build(cache->fp, 0); 160160581Sobrien} 161160581Sobrien 162160581Sobrienstatic void 163160581Sobrienkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, 164160581Sobrien void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 165160581Sobrien CORE_ADDR *addrp, int *realnump, void *valuep) 166160581Sobrien{ 167160581Sobrien char dummy_valuep[MAX_REGISTER_SIZE]; 168160581Sobrien struct kgdb_frame_cache *cache; 169160581Sobrien int ofs, regsz; 170162303Simp int is_undefined = 0; 171160581Sobrien 172160581Sobrien regsz = register_size(current_gdbarch, regnum); 173160581Sobrien 174160581Sobrien if (valuep == NULL) 175160581Sobrien valuep = dummy_valuep; 176160581Sobrien memset(valuep, 0, regsz); 177160581Sobrien *optimizedp = 0; 178160581Sobrien *addrp = 0; 179160581Sobrien *lvalp = not_lval; 180160581Sobrien *realnump = -1; 181160581Sobrien 182160581Sobrien ofs = (regnum >= 0 && regnum <= ARM_PS_REGNUM) 183160581Sobrien ? kgdb_trgt_frame_offset[regnum] : -1; 184160581Sobrien if (ofs == -1) 185160581Sobrien return; 186160581Sobrien 187160581Sobrien cache = kgdb_trgt_frame_cache(next_frame, this_cache); 188163440Sjhb 189162303Simp if (is_undef && (regnum == ARM_SP_REGNUM || regnum == ARM_PC_REGNUM)) { 190162303Simp *addrp = cache->sp + offsetof(struct trapframe, tf_spsr); 191162303Simp target_read_memory(*addrp, valuep, regsz); 192162303Simp is_undefined = 1; 193162303Simp ofs = kgdb_trgt_frame_offset[ARM_SP_REGNUM]; 194162303Simp 195162303Simp } 196160581Sobrien *addrp = cache->sp + ofs; 197160581Sobrien *lvalp = lval_memory; 198160581Sobrien target_read_memory(*addrp, valuep, regsz); 199162303Simp 200162303Simp if (is_undefined) { 201162303Simp *addrp = *(unsigned int *)valuep + (regnum == ARM_SP_REGNUM ? 202162303Simp 0 : 8); 203162303Simp target_read_memory(*addrp, valuep, regsz); 204162303Simp 205162303Simp } 206160581Sobrien} 207160581Sobrien 208160581Sobrienstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = { 209160581Sobrien UNKNOWN_FRAME, 210160581Sobrien &kgdb_trgt_trapframe_this_id, 211160581Sobrien &kgdb_trgt_trapframe_prev_register 212160581Sobrien}; 213162303Simp#endif 214160581Sobrien 215160581Sobrienconst struct frame_unwind * 216160581Sobrienkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) 217160581Sobrien{ 218162303Simp#ifndef CROSS_DEBUGGER 219160581Sobrien char *pname; 220160581Sobrien CORE_ADDR pc; 221160581Sobrien 222160581Sobrien pc = frame_pc_unwind(next_frame); 223160581Sobrien pname = NULL; 224160581Sobrien find_pc_partial_function(pc, &pname, NULL, NULL); 225162303Simp if (pname == NULL) { 226162303Simp is_undef = 0; 227160581Sobrien return (NULL); 228162303Simp } 229162303Simp if (!strcmp(pname, "undefinedinstruction")) 230162303Simp is_undef = 1; 231160581Sobrien if (strcmp(pname, "Laddress_exception_entry") == 0 || 232160581Sobrien strcmp(pname, "undefined_entry") == 0 || 233160581Sobrien strcmp(pname, "exception_exit") == 0 || 234162303Simp strcmp(pname, "Laddress_exception_msg") == 0 || 235160581Sobrien strcmp(pname, "irq_entry") == 0) 236160581Sobrien return (&kgdb_trgt_trapframe_unwind); 237162303Simp if (!strcmp(pname, "undefinedinstruction")) 238162303Simp is_undef = 1; 239162303Simp else 240162303Simp is_undef = 0; 241162303Simp#endif 242160581Sobrien return (NULL); 243160581Sobrien} 244