1/** 2 * \file 3 * \brief Arch specific debugging functions 4 */ 5 6/* 7 * Copyright (c) 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <barrelfish/barrelfish.h> 17#include <barrelfish/caddr.h> 18#include <barrelfish/debug.h> 19#include <barrelfish/dispatch.h> 20#include <if/monitor_defs.h> 21#include <stdarg.h> 22#include <stdlib.h> 23#include <string.h> 24#include <inttypes.h> 25 26#define NR_OF_DISPLAYED_RET_ADDRS 10 27 28/** 29 * \brief Dump out various memory regions and a partial backtrace. 30 * 31 * Mainly for debugging traps and faults in the dispatcher handlers. 32 */ 33void debug_dump(arch_registers_state_t *archregs) 34{ 35 struct registers_x86_32 *regs = archregs; 36 37 debug_printf("Dumping stack (0x%" PRIx32 ")...\n", regs->esp); 38 debug_dump_mem_around_addr(regs->esp); 39 // debug_printf("Dumping code (0x%x)...\n", regs->eip); 40 // debug_dump_mem_around_addr(regs->eip); 41 // debug_printf("Dumping memory around ebp (0x%x)\n", regs->ebp); 42 // debug_dump_mem_around_addr(regs->ebp); 43} 44 45static void debug_call_chain_rbp(uintptr_t bp) 46{ 47 uintptr_t ret_addr; 48 uintptr_t user_rbp = bp; 49 50 for (int it = 0; it < NR_OF_DISPLAYED_RET_ADDRS; it++) { 51 if (user_rbp < BASE_PAGE_SIZE || (user_rbp % sizeof(uintptr_t)) != 0) { 52 break; 53 } 54 // get return address 55 ret_addr = *(uintptr_t *)(user_rbp + sizeof(uintptr_t)); 56 debug_printf("return address = 0x%" PRIxPTR "\n", ret_addr); 57 // get next RBP 58 user_rbp = *(uintptr_t *)user_rbp; 59 } 60} 61 62void debug_call_chain(arch_registers_state_t *archregs) 63{ 64 debug_call_chain_rbp(archregs->ebp); 65} 66 67/** 68 * \brief Print out the registers in a dispatcher save area, for trap handlers. 69 */ 70void debug_print_save_area(arch_registers_state_t *state) 71{ 72 uintptr_t *regs = (uintptr_t*)state; 73 const char *reg_names[]={"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", 74 "esp", "eip", "eflags", "cs", "ss"}; 75 for (int i = 0; i < X86_32_NUM_REGS; i++) { 76 debug_printf("%02u: %016" PRIxPTR " %s\n", i, regs[i], reg_names[i]); 77 } 78} 79 80void debug_return_addresses(void) 81{ 82 debug_printf("return address = %p\n", __builtin_return_address(0)); 83 debug_printf("return address = %p\n", __builtin_return_address(1)); 84 debug_printf("return address = %p\n", __builtin_return_address(2)); 85 debug_printf("return address = %p\n", __builtin_return_address(3)); 86 debug_printf("return address = %p\n", __builtin_return_address(4)); 87} 88 89void debug_print_fpu_state(struct registers_fpu_x86_32 *fpustate) 90{ 91 uint8_t *regs8 = fpustate->registers; 92 regs8 += 16 - ((uintptr_t)regs8 % 16); 93 94 uint16_t *regs16 = (void *)regs8; 95 uint32_t *regs32 = (void *)regs8; 96 uint64_t *regs64 = (void *)regs8; 97 98 debug_printf("FCW %x\n", regs16[0]); 99 debug_printf("FSW %x\n", regs16[1]); 100 debug_printf("FTW %x\n", regs8[4]); 101 debug_printf("FOP %x\n", regs16[3]); 102 debug_printf("IP %" PRIx32 "\n", regs32[3]); 103 debug_printf("CS %x\n", regs16[6]); 104 debug_printf("DP %" PRIx32 "\n", regs32[5]); 105 debug_printf("DS %x\n", regs16[10]); 106 debug_printf("MXCSR %" PRIx32 "\n", regs32[7]); 107 debug_printf("MXCSR mask %" PRIx32 "\n", regs32[8]); 108 109 for (int i = 0; i < 7; i++) { 110 debug_printf("ST%d/MM%d %llx:%llx\n", i, i, 111 regs64[4 + i * 2 + 1] & 0xffff, 112 regs64[4 + i * 2]); 113 } 114 115 for (int i = 0; i < 7; i++) { 116 debug_printf("XMM%d %llx:%llx\n", i, 117 regs64[20 + i * 2 + 1], 118 regs64[20 + i * 2]); 119 } 120} 121