1132624Smarcel/* 2132624Smarcel * Copyright (c) 2004 Marcel Moolenaar 3132624Smarcel * All rights reserved. 4132624Smarcel * 5132624Smarcel * Redistribution and use in source and binary forms, with or without 6132624Smarcel * modification, are permitted provided that the following conditions 7132624Smarcel * are met: 8132624Smarcel * 9132624Smarcel * 1. Redistributions of source code must retain the above copyright 10132624Smarcel * notice, this list of conditions and the following disclaimer. 11132624Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12132624Smarcel * notice, this list of conditions and the following disclaimer in the 13132624Smarcel * documentation and/or other materials provided with the distribution. 14132624Smarcel * 15132624Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16132624Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17132624Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18132624Smarcel * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19132624Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20132624Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21132624Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22132624Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23132624Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24132624Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25132624Smarcel */ 26132624Smarcel 27132624Smarcel#include <sys/cdefs.h> 28132624Smarcel__FBSDID("$FreeBSD$"); 29132624Smarcel 30173681Sjhb#include <sys/param.h> 31173681Sjhb#include <sys/proc.h> 32132624Smarcel#include <machine/pcb.h> 33149955Smarcel#include <machine/frame.h> 34173681Sjhb#include <machine/segments.h> 35173681Sjhb#include <machine/tss.h> 36132624Smarcel#include <err.h> 37132624Smarcel#include <kvm.h> 38132624Smarcel#include <string.h> 39132624Smarcel 40132624Smarcel#include <defs.h> 41132624Smarcel#include <target.h> 42132624Smarcel#include <gdbthread.h> 43132624Smarcel#include <inferior.h> 44132624Smarcel#include <regcache.h> 45149954Smarcel#include <frame-unwind.h> 46149955Smarcel#include <i386-tdep.h> 47132624Smarcel 48149954Smarcel#include "kgdb.h" 49149954Smarcel 50178670Sjhbstatic int ofs_fix; 51178670Sjhb 52132624Smarcelvoid 53132624Smarcelkgdb_trgt_fetch_registers(int regno __unused) 54132624Smarcel{ 55132624Smarcel struct kthr *kt; 56132624Smarcel struct pcb pcb; 57132624Smarcel 58178713Sjhb kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 59132624Smarcel if (kt == NULL) 60132624Smarcel return; 61132624Smarcel if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 62132624Smarcel warnx("kvm_read: %s", kvm_geterr(kvm)); 63132624Smarcel memset(&pcb, 0, sizeof(pcb)); 64132624Smarcel } 65149955Smarcel supply_register(I386_EBX_REGNUM, (char *)&pcb.pcb_ebx); 66149955Smarcel supply_register(I386_ESP_REGNUM, (char *)&pcb.pcb_esp); 67149955Smarcel supply_register(I386_EBP_REGNUM, (char *)&pcb.pcb_ebp); 68149955Smarcel supply_register(I386_ESI_REGNUM, (char *)&pcb.pcb_esi); 69149955Smarcel supply_register(I386_EDI_REGNUM, (char *)&pcb.pcb_edi); 70149955Smarcel supply_register(I386_EIP_REGNUM, (char *)&pcb.pcb_eip); 71132624Smarcel} 72132624Smarcel 73132624Smarcelvoid 74132624Smarcelkgdb_trgt_store_registers(int regno __unused) 75132624Smarcel{ 76132624Smarcel fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); 77132624Smarcel} 78149954Smarcel 79178670Sjhbvoid 80178670Sjhbkgdb_trgt_new_objfile(struct objfile *objfile) 81178670Sjhb{ 82178670Sjhb 83178670Sjhb /* 84178670Sjhb * In revision 1.117 of i386/i386/exception.S trap handlers 85178670Sjhb * were changed to pass trapframes by reference rather than 86178670Sjhb * by value. Detect this by seeing if the first instruction 87178670Sjhb * at the 'calltrap' label is a "push %esp" which has the 88178670Sjhb * opcode 0x54. 89178670Sjhb */ 90178670Sjhb if (kgdb_parse("((char *)calltrap)[0]") == 0x54) 91178670Sjhb ofs_fix = 4; 92178670Sjhb else 93178670Sjhb ofs_fix = 0; 94178670Sjhb} 95178670Sjhb 96173681Sjhbstruct kgdb_tss_cache { 97173681Sjhb CORE_ADDR pc; 98173681Sjhb CORE_ADDR sp; 99173681Sjhb CORE_ADDR tss; 100173681Sjhb}; 101173681Sjhb 102173681Sjhbstatic int kgdb_trgt_tss_offset[15] = { 103173681Sjhb offsetof(struct i386tss, tss_eax), 104173681Sjhb offsetof(struct i386tss, tss_ecx), 105173681Sjhb offsetof(struct i386tss, tss_edx), 106173681Sjhb offsetof(struct i386tss, tss_ebx), 107173681Sjhb offsetof(struct i386tss, tss_esp), 108173681Sjhb offsetof(struct i386tss, tss_ebp), 109173681Sjhb offsetof(struct i386tss, tss_esi), 110173681Sjhb offsetof(struct i386tss, tss_edi), 111173681Sjhb offsetof(struct i386tss, tss_eip), 112173681Sjhb offsetof(struct i386tss, tss_eflags), 113173681Sjhb offsetof(struct i386tss, tss_cs), 114173681Sjhb offsetof(struct i386tss, tss_ss), 115173681Sjhb offsetof(struct i386tss, tss_ds), 116173681Sjhb offsetof(struct i386tss, tss_es), 117173681Sjhb offsetof(struct i386tss, tss_fs) 118173681Sjhb}; 119173681Sjhb 120173681Sjhb/* 121173681Sjhb * If the current thread is executing on a CPU, fetch the common_tss 122173681Sjhb * for that CPU. 123173681Sjhb * 124173681Sjhb * This is painful because 'struct pcpu' is variant sized, so we can't 125173681Sjhb * use it. Instead, we lookup the GDT selector for this CPU and 126173681Sjhb * extract the base of the TSS from there. 127173681Sjhb */ 128173681Sjhbstatic CORE_ADDR 129173681Sjhbkgdb_trgt_fetch_tss(void) 130173681Sjhb{ 131173681Sjhb struct kthr *kt; 132173681Sjhb struct segment_descriptor sd; 133173681Sjhb uintptr_t addr, cpu0prvpage, tss; 134173681Sjhb 135178713Sjhb kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 136173681Sjhb if (kt == NULL || kt->cpu == NOCPU) 137173681Sjhb return (0); 138173681Sjhb 139210852Sjhb addr = kgdb_lookup("gdt"); 140173681Sjhb if (addr == 0) 141173681Sjhb return (0); 142173681Sjhb addr += (kt->cpu * NGDT + GPROC0_SEL) * sizeof(sd); 143173681Sjhb if (kvm_read(kvm, addr, &sd, sizeof(sd)) != sizeof(sd)) { 144173681Sjhb warnx("kvm_read: %s", kvm_geterr(kvm)); 145173681Sjhb return (0); 146173681Sjhb } 147173681Sjhb if (sd.sd_type != SDT_SYS386BSY) { 148173681Sjhb warnx("descriptor is not a busy TSS"); 149173681Sjhb return (0); 150173681Sjhb } 151173681Sjhb tss = sd.sd_hibase << 24 | sd.sd_lobase; 152173681Sjhb 153173681Sjhb /* 154173681Sjhb * In SMP kernels, the TSS is stored as part of the per-CPU 155173681Sjhb * data. On older kernels, the CPU0's private page 156173681Sjhb * is stored at an address that isn't mapped in minidumps. 157173681Sjhb * However, the data is mapped at the alternate cpu0prvpage 158173681Sjhb * address. Thus, if the TSS is at the invalid address, 159173681Sjhb * change it to be relative to cpu0prvpage instead. 160173681Sjhb */ 161173681Sjhb if (trunc_page(tss) == 0xffc00000) { 162210852Sjhb addr = kgdb_lookup("cpu0prvpage"); 163210852Sjhb if (addr == 0) 164173681Sjhb return (0); 165173681Sjhb if (kvm_read(kvm, addr, &cpu0prvpage, sizeof(cpu0prvpage)) != 166173681Sjhb sizeof(cpu0prvpage)) { 167173681Sjhb warnx("kvm_read: %s", kvm_geterr(kvm)); 168173681Sjhb return (0); 169173681Sjhb } 170173681Sjhb tss = cpu0prvpage + (tss & PAGE_MASK); 171173681Sjhb } 172173681Sjhb return ((CORE_ADDR)tss); 173173681Sjhb} 174173681Sjhb 175173681Sjhbstatic struct kgdb_tss_cache * 176173681Sjhbkgdb_trgt_tss_cache(struct frame_info *next_frame, void **this_cache) 177173681Sjhb{ 178173681Sjhb char buf[MAX_REGISTER_SIZE]; 179173681Sjhb struct kgdb_tss_cache *cache; 180173681Sjhb 181173681Sjhb cache = *this_cache; 182173681Sjhb if (cache == NULL) { 183173681Sjhb cache = FRAME_OBSTACK_ZALLOC(struct kgdb_tss_cache); 184173681Sjhb *this_cache = cache; 185173681Sjhb cache->pc = frame_func_unwind(next_frame); 186173681Sjhb frame_unwind_register(next_frame, SP_REGNUM, buf); 187173681Sjhb cache->sp = extract_unsigned_integer(buf, 188173681Sjhb register_size(current_gdbarch, SP_REGNUM)); 189173681Sjhb cache->tss = kgdb_trgt_fetch_tss(); 190173681Sjhb } 191173681Sjhb return (cache); 192173681Sjhb} 193173681Sjhb 194173681Sjhbstatic void 195173681Sjhbkgdb_trgt_dblfault_this_id(struct frame_info *next_frame, void **this_cache, 196173681Sjhb struct frame_id *this_id) 197173681Sjhb{ 198173681Sjhb struct kgdb_tss_cache *cache; 199173681Sjhb 200173681Sjhb cache = kgdb_trgt_tss_cache(next_frame, this_cache); 201173681Sjhb *this_id = frame_id_build(cache->sp, cache->pc); 202173681Sjhb} 203173681Sjhb 204173681Sjhbstatic void 205173681Sjhbkgdb_trgt_dblfault_prev_register(struct frame_info *next_frame, 206173681Sjhb void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 207173681Sjhb CORE_ADDR *addrp, int *realnump, void *valuep) 208173681Sjhb{ 209173681Sjhb char dummy_valuep[MAX_REGISTER_SIZE]; 210173681Sjhb struct kgdb_tss_cache *cache; 211173681Sjhb int ofs, regsz; 212173681Sjhb 213173681Sjhb regsz = register_size(current_gdbarch, regnum); 214173681Sjhb 215173681Sjhb if (valuep == NULL) 216173681Sjhb valuep = dummy_valuep; 217173681Sjhb memset(valuep, 0, regsz); 218173681Sjhb *optimizedp = 0; 219173681Sjhb *addrp = 0; 220173681Sjhb *lvalp = not_lval; 221173681Sjhb *realnump = -1; 222173681Sjhb 223173681Sjhb ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) 224173681Sjhb ? kgdb_trgt_tss_offset[regnum] : -1; 225173681Sjhb if (ofs == -1) 226173681Sjhb return; 227173681Sjhb 228173681Sjhb cache = kgdb_trgt_tss_cache(next_frame, this_cache); 229173681Sjhb if (cache->tss == 0) 230173681Sjhb return; 231173681Sjhb *addrp = cache->tss + ofs; 232173681Sjhb *lvalp = lval_memory; 233173681Sjhb target_read_memory(*addrp, valuep, regsz); 234173681Sjhb} 235173681Sjhb 236173681Sjhbstatic const struct frame_unwind kgdb_trgt_dblfault_unwind = { 237173681Sjhb UNKNOWN_FRAME, 238173681Sjhb &kgdb_trgt_dblfault_this_id, 239173681Sjhb &kgdb_trgt_dblfault_prev_register 240173681Sjhb}; 241173681Sjhb 242149955Smarcelstruct kgdb_frame_cache { 243183414Skib int frame_type; 244149955Smarcel CORE_ADDR pc; 245149955Smarcel CORE_ADDR sp; 246149955Smarcel}; 247183414Skib#define FT_NORMAL 1 248183414Skib#define FT_INTRFRAME 2 249183414Skib#define FT_INTRTRAPFRAME 3 250183414Skib#define FT_TIMERFRAME 4 251149955Smarcel 252149955Smarcelstatic int kgdb_trgt_frame_offset[15] = { 253149955Smarcel offsetof(struct trapframe, tf_eax), 254149955Smarcel offsetof(struct trapframe, tf_ecx), 255149955Smarcel offsetof(struct trapframe, tf_edx), 256149955Smarcel offsetof(struct trapframe, tf_ebx), 257149955Smarcel offsetof(struct trapframe, tf_esp), 258149955Smarcel offsetof(struct trapframe, tf_ebp), 259149955Smarcel offsetof(struct trapframe, tf_esi), 260149955Smarcel offsetof(struct trapframe, tf_edi), 261149955Smarcel offsetof(struct trapframe, tf_eip), 262149955Smarcel offsetof(struct trapframe, tf_eflags), 263149955Smarcel offsetof(struct trapframe, tf_cs), 264149955Smarcel offsetof(struct trapframe, tf_ss), 265149955Smarcel offsetof(struct trapframe, tf_ds), 266149955Smarcel offsetof(struct trapframe, tf_es), 267149955Smarcel offsetof(struct trapframe, tf_fs) 268149955Smarcel}; 269149955Smarcel 270149955Smarcelstatic struct kgdb_frame_cache * 271149955Smarcelkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 272149955Smarcel{ 273149955Smarcel char buf[MAX_REGISTER_SIZE]; 274149955Smarcel struct kgdb_frame_cache *cache; 275149975Smarcel char *pname; 276149955Smarcel 277149955Smarcel cache = *this_cache; 278149955Smarcel if (cache == NULL) { 279149955Smarcel cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 280149955Smarcel *this_cache = cache; 281149955Smarcel cache->pc = frame_func_unwind(next_frame); 282149975Smarcel find_pc_partial_function(cache->pc, &pname, NULL, NULL); 283183414Skib if (pname[0] != 'X') 284183414Skib cache->frame_type = FT_NORMAL; 285183414Skib else if (strcmp(pname, "Xtimerint") == 0) 286183414Skib cache->frame_type = FT_TIMERFRAME; 287183414Skib else if (strcmp(pname, "Xcpustop") == 0 || 288183414Skib strcmp(pname, "Xrendezvous") == 0 || 289183414Skib strcmp(pname, "Xipi_intr_bitmap_handler") == 0 || 290183414Skib strcmp(pname, "Xlazypmap") == 0) 291183414Skib cache->frame_type = FT_INTRTRAPFRAME; 292183414Skib else 293183414Skib cache->frame_type = FT_INTRFRAME; 294149955Smarcel frame_unwind_register(next_frame, SP_REGNUM, buf); 295149955Smarcel cache->sp = extract_unsigned_integer(buf, 296149955Smarcel register_size(current_gdbarch, SP_REGNUM)); 297149955Smarcel } 298149955Smarcel return (cache); 299149955Smarcel} 300149955Smarcel 301149954Smarcelstatic void 302149954Smarcelkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 303149954Smarcel struct frame_id *this_id) 304149954Smarcel{ 305149955Smarcel struct kgdb_frame_cache *cache; 306149955Smarcel 307149955Smarcel cache = kgdb_trgt_frame_cache(next_frame, this_cache); 308149955Smarcel *this_id = frame_id_build(cache->sp, cache->pc); 309149954Smarcel} 310149954Smarcel 311149954Smarcelstatic void 312149954Smarcelkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, 313149954Smarcel void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 314149954Smarcel CORE_ADDR *addrp, int *realnump, void *valuep) 315149954Smarcel{ 316149955Smarcel char dummy_valuep[MAX_REGISTER_SIZE]; 317149955Smarcel struct kgdb_frame_cache *cache; 318149955Smarcel int ofs, regsz; 319149955Smarcel 320149955Smarcel regsz = register_size(current_gdbarch, regnum); 321149955Smarcel 322149955Smarcel if (valuep == NULL) 323149955Smarcel valuep = dummy_valuep; 324149955Smarcel memset(valuep, 0, regsz); 325149955Smarcel *optimizedp = 0; 326149955Smarcel *addrp = 0; 327149955Smarcel *lvalp = not_lval; 328149955Smarcel *realnump = -1; 329149955Smarcel 330149955Smarcel ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) 331167143Skib ? kgdb_trgt_frame_offset[regnum] + ofs_fix : -1; 332149955Smarcel if (ofs == -1) 333149955Smarcel return; 334149955Smarcel 335149955Smarcel cache = kgdb_trgt_frame_cache(next_frame, this_cache); 336183414Skib switch (cache->frame_type) { 337183414Skib case FT_NORMAL: 338183414Skib break; 339183414Skib case FT_INTRFRAME: 340183414Skib ofs += 4; 341183414Skib break; 342183414Skib case FT_TIMERFRAME: 343183414Skib break; 344183414Skib case FT_INTRTRAPFRAME: 345183414Skib ofs -= ofs_fix; 346183414Skib break; 347183414Skib default: 348183414Skib fprintf_unfiltered(gdb_stderr, "Correct FT_XXX frame offsets " 349183414Skib "for %d\n", cache->frame_type); 350183414Skib break; 351183414Skib } 352183414Skib *addrp = cache->sp + ofs; 353149955Smarcel *lvalp = lval_memory; 354149955Smarcel target_read_memory(*addrp, valuep, regsz); 355149954Smarcel} 356149954Smarcel 357149954Smarcelstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = { 358149954Smarcel UNKNOWN_FRAME, 359149954Smarcel &kgdb_trgt_trapframe_this_id, 360149954Smarcel &kgdb_trgt_trapframe_prev_register 361149954Smarcel}; 362149954Smarcel 363149954Smarcelconst struct frame_unwind * 364149954Smarcelkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) 365149954Smarcel{ 366149955Smarcel char *pname; 367149955Smarcel CORE_ADDR pc; 368149954Smarcel 369149955Smarcel pc = frame_pc_unwind(next_frame); 370149955Smarcel pname = NULL; 371149955Smarcel find_pc_partial_function(pc, &pname, NULL, NULL); 372149955Smarcel if (pname == NULL) 373149955Smarcel return (NULL); 374173681Sjhb if (strcmp(pname, "dblfault_handler") == 0) 375173681Sjhb return (&kgdb_trgt_dblfault_unwind); 376149975Smarcel if (strcmp(pname, "calltrap") == 0 || 377149975Smarcel (pname[0] == 'X' && pname[1] != '_')) 378149955Smarcel return (&kgdb_trgt_trapframe_unwind); 379149955Smarcel /* printf("%s: %llx =%s\n", __func__, pc, pname); */ 380149975Smarcel return (NULL); 381149954Smarcel} 382