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 52246893SmarcelCORE_ADDR 53246893Smarcelkgdb_trgt_core_pcb(u_int cpuid) 54246893Smarcel{ 55246893Smarcel return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); 56246893Smarcel} 57246893Smarcel 58132624Smarcelvoid 59132624Smarcelkgdb_trgt_fetch_registers(int regno __unused) 60132624Smarcel{ 61132624Smarcel struct kthr *kt; 62132624Smarcel struct pcb pcb; 63132624Smarcel 64178713Sjhb kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 65132624Smarcel if (kt == NULL) 66132624Smarcel return; 67132624Smarcel if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 68132624Smarcel warnx("kvm_read: %s", kvm_geterr(kvm)); 69132624Smarcel memset(&pcb, 0, sizeof(pcb)); 70132624Smarcel } 71149955Smarcel supply_register(I386_EBX_REGNUM, (char *)&pcb.pcb_ebx); 72149955Smarcel supply_register(I386_ESP_REGNUM, (char *)&pcb.pcb_esp); 73149955Smarcel supply_register(I386_EBP_REGNUM, (char *)&pcb.pcb_ebp); 74149955Smarcel supply_register(I386_ESI_REGNUM, (char *)&pcb.pcb_esi); 75149955Smarcel supply_register(I386_EDI_REGNUM, (char *)&pcb.pcb_edi); 76149955Smarcel supply_register(I386_EIP_REGNUM, (char *)&pcb.pcb_eip); 77132624Smarcel} 78132624Smarcel 79132624Smarcelvoid 80132624Smarcelkgdb_trgt_store_registers(int regno __unused) 81132624Smarcel{ 82132624Smarcel fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); 83132624Smarcel} 84149954Smarcel 85178670Sjhbvoid 86178670Sjhbkgdb_trgt_new_objfile(struct objfile *objfile) 87178670Sjhb{ 88178670Sjhb 89178670Sjhb /* 90178670Sjhb * In revision 1.117 of i386/i386/exception.S trap handlers 91178670Sjhb * were changed to pass trapframes by reference rather than 92178670Sjhb * by value. Detect this by seeing if the first instruction 93178670Sjhb * at the 'calltrap' label is a "push %esp" which has the 94178670Sjhb * opcode 0x54. 95178670Sjhb */ 96178670Sjhb if (kgdb_parse("((char *)calltrap)[0]") == 0x54) 97178670Sjhb ofs_fix = 4; 98178670Sjhb else 99178670Sjhb ofs_fix = 0; 100178670Sjhb} 101178670Sjhb 102173681Sjhbstruct kgdb_tss_cache { 103173681Sjhb CORE_ADDR pc; 104173681Sjhb CORE_ADDR sp; 105173681Sjhb CORE_ADDR tss; 106173681Sjhb}; 107173681Sjhb 108173681Sjhbstatic int kgdb_trgt_tss_offset[15] = { 109173681Sjhb offsetof(struct i386tss, tss_eax), 110173681Sjhb offsetof(struct i386tss, tss_ecx), 111173681Sjhb offsetof(struct i386tss, tss_edx), 112173681Sjhb offsetof(struct i386tss, tss_ebx), 113173681Sjhb offsetof(struct i386tss, tss_esp), 114173681Sjhb offsetof(struct i386tss, tss_ebp), 115173681Sjhb offsetof(struct i386tss, tss_esi), 116173681Sjhb offsetof(struct i386tss, tss_edi), 117173681Sjhb offsetof(struct i386tss, tss_eip), 118173681Sjhb offsetof(struct i386tss, tss_eflags), 119173681Sjhb offsetof(struct i386tss, tss_cs), 120173681Sjhb offsetof(struct i386tss, tss_ss), 121173681Sjhb offsetof(struct i386tss, tss_ds), 122173681Sjhb offsetof(struct i386tss, tss_es), 123173681Sjhb offsetof(struct i386tss, tss_fs) 124173681Sjhb}; 125173681Sjhb 126173681Sjhb/* 127173681Sjhb * If the current thread is executing on a CPU, fetch the common_tss 128173681Sjhb * for that CPU. 129173681Sjhb * 130173681Sjhb * This is painful because 'struct pcpu' is variant sized, so we can't 131173681Sjhb * use it. Instead, we lookup the GDT selector for this CPU and 132173681Sjhb * extract the base of the TSS from there. 133173681Sjhb */ 134173681Sjhbstatic CORE_ADDR 135173681Sjhbkgdb_trgt_fetch_tss(void) 136173681Sjhb{ 137173681Sjhb struct kthr *kt; 138173681Sjhb struct segment_descriptor sd; 139173681Sjhb uintptr_t addr, cpu0prvpage, tss; 140173681Sjhb 141178713Sjhb kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 142173681Sjhb if (kt == NULL || kt->cpu == NOCPU) 143173681Sjhb return (0); 144173681Sjhb 145210852Sjhb addr = kgdb_lookup("gdt"); 146173681Sjhb if (addr == 0) 147173681Sjhb return (0); 148173681Sjhb addr += (kt->cpu * NGDT + GPROC0_SEL) * sizeof(sd); 149173681Sjhb if (kvm_read(kvm, addr, &sd, sizeof(sd)) != sizeof(sd)) { 150173681Sjhb warnx("kvm_read: %s", kvm_geterr(kvm)); 151173681Sjhb return (0); 152173681Sjhb } 153173681Sjhb if (sd.sd_type != SDT_SYS386BSY) { 154173681Sjhb warnx("descriptor is not a busy TSS"); 155173681Sjhb return (0); 156173681Sjhb } 157173681Sjhb tss = sd.sd_hibase << 24 | sd.sd_lobase; 158173681Sjhb 159173681Sjhb /* 160173681Sjhb * In SMP kernels, the TSS is stored as part of the per-CPU 161173681Sjhb * data. On older kernels, the CPU0's private page 162173681Sjhb * is stored at an address that isn't mapped in minidumps. 163173681Sjhb * However, the data is mapped at the alternate cpu0prvpage 164173681Sjhb * address. Thus, if the TSS is at the invalid address, 165173681Sjhb * change it to be relative to cpu0prvpage instead. 166173681Sjhb */ 167173681Sjhb if (trunc_page(tss) == 0xffc00000) { 168210852Sjhb addr = kgdb_lookup("cpu0prvpage"); 169210852Sjhb if (addr == 0) 170173681Sjhb return (0); 171173681Sjhb if (kvm_read(kvm, addr, &cpu0prvpage, sizeof(cpu0prvpage)) != 172173681Sjhb sizeof(cpu0prvpage)) { 173173681Sjhb warnx("kvm_read: %s", kvm_geterr(kvm)); 174173681Sjhb return (0); 175173681Sjhb } 176173681Sjhb tss = cpu0prvpage + (tss & PAGE_MASK); 177173681Sjhb } 178173681Sjhb return ((CORE_ADDR)tss); 179173681Sjhb} 180173681Sjhb 181173681Sjhbstatic struct kgdb_tss_cache * 182173681Sjhbkgdb_trgt_tss_cache(struct frame_info *next_frame, void **this_cache) 183173681Sjhb{ 184173681Sjhb char buf[MAX_REGISTER_SIZE]; 185173681Sjhb struct kgdb_tss_cache *cache; 186173681Sjhb 187173681Sjhb cache = *this_cache; 188173681Sjhb if (cache == NULL) { 189173681Sjhb cache = FRAME_OBSTACK_ZALLOC(struct kgdb_tss_cache); 190173681Sjhb *this_cache = cache; 191173681Sjhb cache->pc = frame_func_unwind(next_frame); 192173681Sjhb frame_unwind_register(next_frame, SP_REGNUM, buf); 193173681Sjhb cache->sp = extract_unsigned_integer(buf, 194173681Sjhb register_size(current_gdbarch, SP_REGNUM)); 195173681Sjhb cache->tss = kgdb_trgt_fetch_tss(); 196173681Sjhb } 197173681Sjhb return (cache); 198173681Sjhb} 199173681Sjhb 200173681Sjhbstatic void 201173681Sjhbkgdb_trgt_dblfault_this_id(struct frame_info *next_frame, void **this_cache, 202173681Sjhb struct frame_id *this_id) 203173681Sjhb{ 204173681Sjhb struct kgdb_tss_cache *cache; 205173681Sjhb 206173681Sjhb cache = kgdb_trgt_tss_cache(next_frame, this_cache); 207173681Sjhb *this_id = frame_id_build(cache->sp, cache->pc); 208173681Sjhb} 209173681Sjhb 210173681Sjhbstatic void 211173681Sjhbkgdb_trgt_dblfault_prev_register(struct frame_info *next_frame, 212173681Sjhb void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 213173681Sjhb CORE_ADDR *addrp, int *realnump, void *valuep) 214173681Sjhb{ 215173681Sjhb char dummy_valuep[MAX_REGISTER_SIZE]; 216173681Sjhb struct kgdb_tss_cache *cache; 217173681Sjhb int ofs, regsz; 218173681Sjhb 219173681Sjhb regsz = register_size(current_gdbarch, regnum); 220173681Sjhb 221173681Sjhb if (valuep == NULL) 222173681Sjhb valuep = dummy_valuep; 223173681Sjhb memset(valuep, 0, regsz); 224173681Sjhb *optimizedp = 0; 225173681Sjhb *addrp = 0; 226173681Sjhb *lvalp = not_lval; 227173681Sjhb *realnump = -1; 228173681Sjhb 229173681Sjhb ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) 230173681Sjhb ? kgdb_trgt_tss_offset[regnum] : -1; 231173681Sjhb if (ofs == -1) 232173681Sjhb return; 233173681Sjhb 234173681Sjhb cache = kgdb_trgt_tss_cache(next_frame, this_cache); 235173681Sjhb if (cache->tss == 0) 236173681Sjhb return; 237173681Sjhb *addrp = cache->tss + ofs; 238173681Sjhb *lvalp = lval_memory; 239173681Sjhb target_read_memory(*addrp, valuep, regsz); 240173681Sjhb} 241173681Sjhb 242173681Sjhbstatic const struct frame_unwind kgdb_trgt_dblfault_unwind = { 243173681Sjhb UNKNOWN_FRAME, 244173681Sjhb &kgdb_trgt_dblfault_this_id, 245173681Sjhb &kgdb_trgt_dblfault_prev_register 246173681Sjhb}; 247173681Sjhb 248149955Smarcelstruct kgdb_frame_cache { 249183414Skib int frame_type; 250149955Smarcel CORE_ADDR pc; 251149955Smarcel CORE_ADDR sp; 252149955Smarcel}; 253183414Skib#define FT_NORMAL 1 254183414Skib#define FT_INTRFRAME 2 255183414Skib#define FT_INTRTRAPFRAME 3 256183414Skib#define FT_TIMERFRAME 4 257149955Smarcel 258149955Smarcelstatic int kgdb_trgt_frame_offset[15] = { 259149955Smarcel offsetof(struct trapframe, tf_eax), 260149955Smarcel offsetof(struct trapframe, tf_ecx), 261149955Smarcel offsetof(struct trapframe, tf_edx), 262149955Smarcel offsetof(struct trapframe, tf_ebx), 263149955Smarcel offsetof(struct trapframe, tf_esp), 264149955Smarcel offsetof(struct trapframe, tf_ebp), 265149955Smarcel offsetof(struct trapframe, tf_esi), 266149955Smarcel offsetof(struct trapframe, tf_edi), 267149955Smarcel offsetof(struct trapframe, tf_eip), 268149955Smarcel offsetof(struct trapframe, tf_eflags), 269149955Smarcel offsetof(struct trapframe, tf_cs), 270149955Smarcel offsetof(struct trapframe, tf_ss), 271149955Smarcel offsetof(struct trapframe, tf_ds), 272149955Smarcel offsetof(struct trapframe, tf_es), 273149955Smarcel offsetof(struct trapframe, tf_fs) 274149955Smarcel}; 275149955Smarcel 276149955Smarcelstatic struct kgdb_frame_cache * 277149955Smarcelkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 278149955Smarcel{ 279149955Smarcel char buf[MAX_REGISTER_SIZE]; 280149955Smarcel struct kgdb_frame_cache *cache; 281149975Smarcel char *pname; 282149955Smarcel 283149955Smarcel cache = *this_cache; 284149955Smarcel if (cache == NULL) { 285149955Smarcel cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 286149955Smarcel *this_cache = cache; 287149955Smarcel cache->pc = frame_func_unwind(next_frame); 288149975Smarcel find_pc_partial_function(cache->pc, &pname, NULL, NULL); 289183414Skib if (pname[0] != 'X') 290183414Skib cache->frame_type = FT_NORMAL; 291183414Skib else if (strcmp(pname, "Xtimerint") == 0) 292183414Skib cache->frame_type = FT_TIMERFRAME; 293183414Skib else if (strcmp(pname, "Xcpustop") == 0 || 294183414Skib strcmp(pname, "Xrendezvous") == 0 || 295183414Skib strcmp(pname, "Xipi_intr_bitmap_handler") == 0 || 296183414Skib strcmp(pname, "Xlazypmap") == 0) 297183414Skib cache->frame_type = FT_INTRTRAPFRAME; 298183414Skib else 299183414Skib cache->frame_type = FT_INTRFRAME; 300149955Smarcel frame_unwind_register(next_frame, SP_REGNUM, buf); 301149955Smarcel cache->sp = extract_unsigned_integer(buf, 302149955Smarcel register_size(current_gdbarch, SP_REGNUM)); 303149955Smarcel } 304149955Smarcel return (cache); 305149955Smarcel} 306149955Smarcel 307149954Smarcelstatic void 308149954Smarcelkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 309149954Smarcel struct frame_id *this_id) 310149954Smarcel{ 311149955Smarcel struct kgdb_frame_cache *cache; 312149955Smarcel 313149955Smarcel cache = kgdb_trgt_frame_cache(next_frame, this_cache); 314149955Smarcel *this_id = frame_id_build(cache->sp, cache->pc); 315149954Smarcel} 316149954Smarcel 317149954Smarcelstatic void 318149954Smarcelkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, 319149954Smarcel void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, 320149954Smarcel CORE_ADDR *addrp, int *realnump, void *valuep) 321149954Smarcel{ 322149955Smarcel char dummy_valuep[MAX_REGISTER_SIZE]; 323149955Smarcel struct kgdb_frame_cache *cache; 324149955Smarcel int ofs, regsz; 325149955Smarcel 326149955Smarcel regsz = register_size(current_gdbarch, regnum); 327149955Smarcel 328149955Smarcel if (valuep == NULL) 329149955Smarcel valuep = dummy_valuep; 330149955Smarcel memset(valuep, 0, regsz); 331149955Smarcel *optimizedp = 0; 332149955Smarcel *addrp = 0; 333149955Smarcel *lvalp = not_lval; 334149955Smarcel *realnump = -1; 335149955Smarcel 336149955Smarcel ofs = (regnum >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) 337167143Skib ? kgdb_trgt_frame_offset[regnum] + ofs_fix : -1; 338149955Smarcel if (ofs == -1) 339149955Smarcel return; 340149955Smarcel 341149955Smarcel cache = kgdb_trgt_frame_cache(next_frame, this_cache); 342183414Skib switch (cache->frame_type) { 343183414Skib case FT_NORMAL: 344183414Skib break; 345183414Skib case FT_INTRFRAME: 346183414Skib ofs += 4; 347183414Skib break; 348183414Skib case FT_TIMERFRAME: 349183414Skib break; 350183414Skib case FT_INTRTRAPFRAME: 351183414Skib ofs -= ofs_fix; 352183414Skib break; 353183414Skib default: 354183414Skib fprintf_unfiltered(gdb_stderr, "Correct FT_XXX frame offsets " 355183414Skib "for %d\n", cache->frame_type); 356183414Skib break; 357183414Skib } 358183414Skib *addrp = cache->sp + ofs; 359149955Smarcel *lvalp = lval_memory; 360149955Smarcel target_read_memory(*addrp, valuep, regsz); 361149954Smarcel} 362149954Smarcel 363149954Smarcelstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = { 364149954Smarcel UNKNOWN_FRAME, 365149954Smarcel &kgdb_trgt_trapframe_this_id, 366149954Smarcel &kgdb_trgt_trapframe_prev_register 367149954Smarcel}; 368149954Smarcel 369149954Smarcelconst struct frame_unwind * 370149954Smarcelkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) 371149954Smarcel{ 372149955Smarcel char *pname; 373149955Smarcel CORE_ADDR pc; 374149954Smarcel 375149955Smarcel pc = frame_pc_unwind(next_frame); 376149955Smarcel pname = NULL; 377149955Smarcel find_pc_partial_function(pc, &pname, NULL, NULL); 378149955Smarcel if (pname == NULL) 379149955Smarcel return (NULL); 380173681Sjhb if (strcmp(pname, "dblfault_handler") == 0) 381173681Sjhb return (&kgdb_trgt_dblfault_unwind); 382149975Smarcel if (strcmp(pname, "calltrap") == 0 || 383149975Smarcel (pname[0] == 'X' && pname[1] != '_')) 384149955Smarcel return (&kgdb_trgt_trapframe_unwind); 385149955Smarcel /* printf("%s: %llx =%s\n", __func__, pc, pname); */ 386149975Smarcel return (NULL); 387149954Smarcel} 388