1 /* 2 * Copyright (c) 2004 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: src/gnu/usr.bin/gdb/kgdb/trgt_amd64.c,v 1.10 2008/05/01 20:36:48 jhb Exp $ 27 */ 28 29 #include <sys/cdefs.h> 30 31 #include <sys/types.h> 32 #include <sys/thread.h> 33 #include <machine/pcb.h> 34 #include <machine/frame.h> 35 #include <err.h> 36 #include <kvm.h> 37 #include <string.h> 38 39 #include <defs.h> 40 #include <target.h> 41 #include <gdbthread.h> 42 #include <inferior.h> 43 #include <regcache.h> 44 #include <frame-unwind.h> 45 #include <amd64-tdep.h> 46 47 #include "kgdb.h" 48 49 static int 50 kgdb_trgt_trapframe_sniffer(const struct frame_unwind *self, 51 struct frame_info *next_frame, 52 void **this_prologue_cache); 53 54 void 55 kgdb_trgt_fetch_registers(struct target_ops *target_ops, struct regcache *regcache, int regno) 56 { 57 struct kthr *kt; 58 struct pcb pcb; 59 60 kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); 61 if (kt == NULL) { 62 regcache_raw_supply(regcache, regno, NULL); 63 return; 64 } 65 66 /* 67 * kt->pcb == 0 is a marker for "non-dumping kernel thread". 68 */ 69 if (kt->pcb == 0) { 70 uintptr_t regs[7]; 71 uintptr_t addr; 72 uintptr_t sp; 73 74 addr = kt->kaddr + offsetof(struct thread, td_sp); 75 kvm_read(kvm, addr, &sp, sizeof(sp)); 76 /* 77 * Stack is: 78 * -2 ret 79 * -1 popfq 80 * 0 popq %r15 edi 81 * 1 popq %r14 82 * 2 popq %r13 83 * 3 popq %r12 84 * 4 popq %rbx 85 * 5 popq %rbp 86 * 6 ret 87 */ 88 if (kvm_read(kvm, sp + 2 * sizeof(regs[0]), regs, sizeof(regs)) != sizeof(regs)) { 89 warnx("kvm_read: %s", kvm_geterr(kvm)); 90 memset(regs, 0, sizeof(regs)); 91 } 92 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 7, ®s[0]); 93 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 6, ®s[1]); 94 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 5, ®s[2]); 95 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 4, ®s[3]); 96 regcache_raw_supply(regcache, AMD64_RBX_REGNUM, ®s[4]); 97 regcache_raw_supply(regcache, AMD64_RBP_REGNUM, ®s[5]); 98 regcache_raw_supply(regcache, AMD64_RIP_REGNUM, ®s[6]); 99 sp += 9 * sizeof(regs[0]); 100 regcache_raw_supply(regcache, AMD64_RSP_REGNUM, &sp); 101 return; 102 } 103 104 if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 105 warnx("kvm_read: %s", kvm_geterr(kvm)); 106 memset(&pcb, 0, sizeof(pcb)); 107 } 108 109 regcache_raw_supply(regcache, AMD64_RBX_REGNUM, (char *)&pcb.pcb_rbx); 110 regcache_raw_supply(regcache, AMD64_RBP_REGNUM, (char *)&pcb.pcb_rbp); 111 regcache_raw_supply(regcache, AMD64_RSP_REGNUM, (char *)&pcb.pcb_rsp); 112 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 4, (char *)&pcb.pcb_r12); 113 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 5, (char *)&pcb.pcb_r13); 114 regcache_raw_supply(regcache, AMD64_R8_REGNUM + 6, (char *)&pcb.pcb_r14); 115 regcache_raw_supply(regcache, AMD64_R15_REGNUM, (char *)&pcb.pcb_r15); 116 regcache_raw_supply(regcache, AMD64_RIP_REGNUM, (char *)&pcb.pcb_rip); 117 } 118 119 struct kgdb_frame_cache { 120 int frame_type; 121 CORE_ADDR pc; 122 CORE_ADDR sp; 123 }; 124 125 #define FT_NORMAL 1 126 #define FT_INTRFRAME 2 127 /*#define FT_INTRTRAPFRAME 3*/ 128 #define FT_TIMERFRAME 4 129 #define FT_CALLTRAP 5 130 131 static int kgdb_trgt_frame_offset[20] = { 132 offsetof(struct trapframe, tf_rax), 133 offsetof(struct trapframe, tf_rbx), 134 offsetof(struct trapframe, tf_rcx), 135 offsetof(struct trapframe, tf_rdx), 136 offsetof(struct trapframe, tf_rsi), 137 offsetof(struct trapframe, tf_rdi), 138 offsetof(struct trapframe, tf_rbp), 139 offsetof(struct trapframe, tf_rsp), 140 offsetof(struct trapframe, tf_r8), 141 offsetof(struct trapframe, tf_r9), 142 offsetof(struct trapframe, tf_r10), 143 offsetof(struct trapframe, tf_r11), 144 offsetof(struct trapframe, tf_r12), 145 offsetof(struct trapframe, tf_r13), 146 offsetof(struct trapframe, tf_r14), 147 offsetof(struct trapframe, tf_r15), 148 offsetof(struct trapframe, tf_rip), 149 offsetof(struct trapframe, tf_rflags), 150 offsetof(struct trapframe, tf_cs), 151 offsetof(struct trapframe, tf_ss) 152 }; 153 154 static struct kgdb_frame_cache * 155 kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 156 { 157 struct kgdb_frame_cache *cache; 158 const char *pname; 159 160 cache = *this_cache; 161 if (cache == NULL) { 162 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 163 *this_cache = cache; 164 cache->pc = get_frame_address_in_block(next_frame); 165 cache->sp = get_frame_sp(next_frame); 166 find_pc_partial_function(cache->pc, &pname, NULL, NULL); 167 168 if (strcmp(pname, "calltrap") == 0) 169 cache->frame_type = FT_CALLTRAP; 170 else if (pname[0] != 'X') 171 cache->frame_type = FT_NORMAL; 172 else if (strcmp(pname, "Xtimerint") == 0) 173 cache->frame_type = FT_TIMERFRAME; 174 else 175 cache->frame_type = FT_INTRFRAME; 176 } 177 return (cache); 178 } 179 180 static void 181 kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 182 struct frame_id *this_id) 183 { 184 struct kgdb_frame_cache *cache; 185 186 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 187 *this_id = frame_id_build(cache->sp, cache->pc); 188 } 189 190 static struct value * 191 kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, 192 void **this_cache, int regnum) 193 { 194 CORE_ADDR addrp; 195 struct kgdb_frame_cache *cache; 196 int ofs; 197 198 if (regnum < AMD64_RAX_REGNUM || regnum > AMD64_EFLAGS_REGNUM + 2) 199 return frame_unwind_got_register(next_frame, regnum, regnum); 200 201 ofs = kgdb_trgt_frame_offset[regnum]; 202 203 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 204 205 switch (cache->frame_type) { 206 case FT_NORMAL: 207 break; 208 case FT_INTRFRAME: 209 ofs += 8; 210 break; 211 case FT_TIMERFRAME: 212 break; 213 /* 214 case FT_INTRTRAPFRAME: 215 ofs -= ofs_fix; 216 break; 217 */ 218 case FT_CALLTRAP: 219 ofs += 0; 220 break; 221 default: 222 fprintf_unfiltered(gdb_stderr, "Correct FT_XXX frame offsets " 223 "for %d\n", cache->frame_type); 224 break; 225 } 226 227 addrp = cache->sp + ofs; 228 return frame_unwind_got_memory(next_frame, regnum, addrp); 229 } 230 231 static enum unwind_stop_reason 232 kgdb_trgt_trapframe_unwind_reason(struct frame_info *next_frame, 233 void **this_cache) 234 { 235 /* XXX marino : populate logic to determine unwind stoppage */ 236 return UNWIND_NO_REASON; 237 } 238 239 const struct frame_unwind kgdb_trgt_trapframe_unwind = { 240 NORMAL_FRAME, 241 &kgdb_trgt_trapframe_unwind_reason, 242 &kgdb_trgt_trapframe_this_id, 243 &kgdb_trgt_trapframe_prev_register, 244 .sniffer = kgdb_trgt_trapframe_sniffer 245 }; 246 247 static int 248 kgdb_trgt_trapframe_sniffer(const struct frame_unwind *self, 249 struct frame_info *next_frame, 250 void **this_prologue_cache) 251 { 252 const char *pname; 253 CORE_ADDR pc; 254 255 pc = get_frame_address_in_block(next_frame); 256 pname = NULL; 257 find_pc_partial_function(pc, &pname, NULL, NULL); 258 if (pname == NULL) 259 return (0); 260 if (strcmp(pname, "calltrap") == 0 || 261 strcmp(pname, "dblfault_handler") == 0 || 262 strcmp(pname, "nmi_calltrap") == 0 || 263 (pname[0] == 'X' && pname[1] != '_')) 264 return (1); 265 return (0); 266 } 267