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