trgt_i386.c revision 178638
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 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/gnu/usr.bin/gdb/kgdb/trgt_i386.c 178638 2008-04-28 18:27:19Z jhb $"); 29 30#include <sys/param.h> 31#include <sys/proc.h> 32#include <machine/pcb.h> 33#include <machine/frame.h> 34#include <machine/segments.h> 35#include <machine/tss.h> 36#include <err.h> 37#include <kvm.h> 38#include <string.h> 39 40#include <defs.h> 41#include <target.h> 42#include <gdbthread.h> 43#include <inferior.h> 44#include <regcache.h> 45#include <frame-unwind.h> 46#include <i386-tdep.h> 47 48#include "kgdb.h" 49 50void 51kgdb_trgt_fetch_registers(int regno __unused) 52{ 53 struct kthr *kt; 54 struct pcb pcb; 55 56 kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); 57 if (kt == NULL) 58 return; 59 if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 60 warnx("kvm_read: %s", kvm_geterr(kvm)); 61 memset(&pcb, 0, sizeof(pcb)); 62 } 63 supply_register(I386_EBX_REGNUM, (char *)&pcb.pcb_ebx); 64 supply_register(I386_ESP_REGNUM, (char *)&pcb.pcb_esp); 65 supply_register(I386_EBP_REGNUM, (char *)&pcb.pcb_ebp); 66 supply_register(I386_ESI_REGNUM, (char *)&pcb.pcb_esi); 67 supply_register(I386_EDI_REGNUM, (char *)&pcb.pcb_edi); 68 supply_register(I386_EIP_REGNUM, (char *)&pcb.pcb_eip); 69} 70 71void 72kgdb_trgt_store_registers(int regno __unused) 73{ 74 fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); 75} 76 77struct kgdb_tss_cache { 78 CORE_ADDR pc; 79 CORE_ADDR sp; 80 CORE_ADDR tss; 81}; 82 83static int kgdb_trgt_tss_offset[15] = { 84 offsetof(struct i386tss, tss_eax), 85 offsetof(struct i386tss, tss_ecx), 86 offsetof(struct i386tss, tss_edx), 87 offsetof(struct i386tss, tss_ebx), 88 offsetof(struct i386tss, tss_esp), 89 offsetof(struct i386tss, tss_ebp), 90 offsetof(struct i386tss, tss_esi), 91 offsetof(struct i386tss, tss_edi), 92 offsetof(struct i386tss, tss_eip), 93 offsetof(struct i386tss, tss_eflags), 94 offsetof(struct i386tss, tss_cs), 95 offsetof(struct i386tss, tss_ss), 96 offsetof(struct i386tss, tss_ds), 97 offsetof(struct i386tss, tss_es), 98 offsetof(struct i386tss, tss_fs) 99}; 100 101/* 102 * If the current thread is executing on a CPU, fetch the common_tss 103 * for that CPU. 104 * 105 * This is painful because 'struct pcpu' is variant sized, so we can't 106 * use it. Instead, we lookup the GDT selector for this CPU and 107 * extract the base of the TSS from there. 108 */ 109static CORE_ADDR 110kgdb_trgt_fetch_tss(void) 111{ 112 struct kthr *kt; 113 struct segment_descriptor sd; 114 uintptr_t addr, cpu0prvpage, tss; 115 116 kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); 117 if (kt == NULL || kt->cpu == NOCPU) 118 return (0); 119 120 addr = kgdb_lookup("_gdt"); 121 if (addr == 0) 122 return (0); 123 addr += (kt->cpu * NGDT + GPROC0_SEL) * sizeof(sd); 124 if (kvm_read(kvm, addr, &sd, sizeof(sd)) != sizeof(sd)) { 125 warnx("kvm_read: %s", kvm_geterr(kvm)); 126 return (0); 127 } 128 if (sd.sd_type != SDT_SYS386BSY) { 129 warnx("descriptor is not a busy TSS"); 130 return (0); 131 } 132 tss = sd.sd_hibase << 24 | sd.sd_lobase; 133 134 /* 135 * In SMP kernels, the TSS is stored as part of the per-CPU 136 * data. On older kernels, the CPU0's private page 137 * is stored at an address that isn't mapped in minidumps. 138 * However, the data is mapped at the alternate cpu0prvpage 139 * address. Thus, if the TSS is at the invalid address, 140 * change it to be relative to cpu0prvpage instead. 141 */ 142 if (trunc_page(tss) == 0xffc00000) { 143 addr = kgdb_lookup("_cpu0prvpage"); 144 if (addr == 0) { 145 warnx("kvm_nlist(_cpu0prvpage): %s", kvm_geterr(kvm)); 146 return (0); 147 } 148 if (kvm_read(kvm, addr, &cpu0prvpage, sizeof(cpu0prvpage)) != 149 sizeof(cpu0prvpage)) { 150 warnx("kvm_read: %s", kvm_geterr(kvm)); 151 return (0); 152 } 153 tss = cpu0prvpage + (tss & PAGE_MASK); 154 } 155 return ((CORE_ADDR)tss); 156} 157 158static struct kgdb_tss_cache * 159kgdb_trgt_tss_cache(struct frame_info *next_frame, void **this_cache) 160{ 161 char buf[MAX_REGISTER_SIZE]; 162 struct kgdb_tss_cache *cache; 163 164 cache = *this_cache; 165 if (cache == NULL) { 166 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_tss_cache); 167 *this_cache = cache; 168 cache->pc = frame_func_unwind(next_frame); 169 frame_unwind_register(next_frame, SP_REGNUM, buf); 170 cache->sp = extract_unsigned_integer(buf, 171 register_size(current_gdbarch, SP_REGNUM)); 172 cache->tss = kgdb_trgt_fetch_tss(); 173 } 174 return (cache); 175} 176 177static void 178kgdb_trgt_dblfault_this_id(struct frame_info *next_frame, void **this_cache, 179 struct frame_id *this_id) 180{ 181 struct kgdb_tss_cache *cache; 182 183 cache = kgdb_trgt_tss_cache(next_frame, this_cache); 184 *this_id = frame_id_build(cache->sp, cache->pc); 185} 186 187static void 188kgdb_trgt_dblfault_prev_register(struct frame_info *next_frame, 189 void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 190 CORE_ADDR *addrp, int *realnump, void *valuep) 191{ 192 char dummy_valuep[MAX_REGISTER_SIZE]; 193 struct kgdb_tss_cache *cache; 194 int ofs, regsz; 195 196 regsz = register_size(current_gdbarch, regnum); 197 198 if (valuep == NULL) 199 valuep = dummy_valuep; 200 memset(valuep, 0, regsz); 201 *optimizedp = 0; 202 *addrp = 0; 203 *lvalp = not_lval; 204 *realnump = -1; 205 206 ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) 207 ? kgdb_trgt_tss_offset[regnum] : -1; 208 if (ofs == -1) 209 return; 210 211 cache = kgdb_trgt_tss_cache(next_frame, this_cache); 212 if (cache->tss == 0) 213 return; 214 *addrp = cache->tss + ofs; 215 *lvalp = lval_memory; 216 target_read_memory(*addrp, valuep, regsz); 217} 218 219static const struct frame_unwind kgdb_trgt_dblfault_unwind = { 220 UNKNOWN_FRAME, 221 &kgdb_trgt_dblfault_this_id, 222 &kgdb_trgt_dblfault_prev_register 223}; 224 225struct kgdb_frame_cache { 226 int intrframe; 227 CORE_ADDR pc; 228 CORE_ADDR sp; 229}; 230 231static int kgdb_trgt_frame_offset[15] = { 232 offsetof(struct trapframe, tf_eax), 233 offsetof(struct trapframe, tf_ecx), 234 offsetof(struct trapframe, tf_edx), 235 offsetof(struct trapframe, tf_ebx), 236 offsetof(struct trapframe, tf_esp), 237 offsetof(struct trapframe, tf_ebp), 238 offsetof(struct trapframe, tf_esi), 239 offsetof(struct trapframe, tf_edi), 240 offsetof(struct trapframe, tf_eip), 241 offsetof(struct trapframe, tf_eflags), 242 offsetof(struct trapframe, tf_cs), 243 offsetof(struct trapframe, tf_ss), 244 offsetof(struct trapframe, tf_ds), 245 offsetof(struct trapframe, tf_es), 246 offsetof(struct trapframe, tf_fs) 247}; 248 249static struct kgdb_frame_cache * 250kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 251{ 252 char buf[MAX_REGISTER_SIZE]; 253 struct kgdb_frame_cache *cache; 254 char *pname; 255 256 cache = *this_cache; 257 if (cache == NULL) { 258 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 259 *this_cache = cache; 260 cache->pc = frame_func_unwind(next_frame); 261 find_pc_partial_function(cache->pc, &pname, NULL, NULL); 262 cache->intrframe = (pname[0] == 'X') ? 1 : 0; 263 frame_unwind_register(next_frame, SP_REGNUM, buf); 264 cache->sp = extract_unsigned_integer(buf, 265 register_size(current_gdbarch, SP_REGNUM)); 266 } 267 return (cache); 268} 269 270static void 271kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 272 struct frame_id *this_id) 273{ 274 struct kgdb_frame_cache *cache; 275 276 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 277 *this_id = frame_id_build(cache->sp, cache->pc); 278} 279 280static void 281kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, 282 void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 283 CORE_ADDR *addrp, int *realnump, void *valuep) 284{ 285 char dummy_valuep[MAX_REGISTER_SIZE]; 286 struct kgdb_frame_cache *cache; 287 int ofs, regsz; 288 static int ofs_fix = 0; 289 static int ofs_fixed = 0; 290 291 regsz = register_size(current_gdbarch, regnum); 292 293 if (valuep == NULL) 294 valuep = dummy_valuep; 295 memset(valuep, 0, regsz); 296 *optimizedp = 0; 297 *addrp = 0; 298 *lvalp = not_lval; 299 *realnump = -1; 300 301 if (!ofs_fixed) { 302 /* 303 * In revision 1.117 of i386/i386/exception.S trap handlers 304 * were changed to pass trapframes by reference rather than 305 * by value. Detect this by seeing if the first instruction 306 * at the 'calltrap' label is a "push %esp" which has the 307 * opcode 0x54. 308 */ 309 if (kgdb_parse("((char *)calltrap)[0]") == 0x54) 310 ofs_fix = 4; 311 ofs_fixed = 1; 312 } 313 ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) 314 ? kgdb_trgt_frame_offset[regnum] + ofs_fix : -1; 315 if (ofs == -1) 316 return; 317 318 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 319 *addrp = cache->sp + ofs + (cache->intrframe ? 4 : 0); 320 *lvalp = lval_memory; 321 target_read_memory(*addrp, valuep, regsz); 322} 323 324static const struct frame_unwind kgdb_trgt_trapframe_unwind = { 325 UNKNOWN_FRAME, 326 &kgdb_trgt_trapframe_this_id, 327 &kgdb_trgt_trapframe_prev_register 328}; 329 330const struct frame_unwind * 331kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) 332{ 333 char *pname; 334 CORE_ADDR pc; 335 336 pc = frame_pc_unwind(next_frame); 337 pname = NULL; 338 find_pc_partial_function(pc, &pname, NULL, NULL); 339 if (pname == NULL) 340 return (NULL); 341 if (strcmp(pname, "dblfault_handler") == 0) 342 return (&kgdb_trgt_dblfault_unwind); 343 if (strcmp(pname, "calltrap") == 0 || 344 (pname[0] == 'X' && pname[1] != '_')) 345 return (&kgdb_trgt_trapframe_unwind); 346 /* printf("%s: %llx =%s\n", __func__, pc, pname); */ 347 return (NULL); 348} 349