📄 xenitp.c
字号:
/* tools/debugger/xenitp.c - A low-level debugger. Based on xenctxt.c, but heavily modified. Copyright 2007 Tristan Gingold <tgingold@free.fr> Xenitp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Xenitp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#include <time.h>#include <stdlib.h>#include <sys/mman.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <argp.h>#include <signal.h>#include <string.h>#include <getopt.h>#include "xenctrl.h"#include <xen/sys/privcmd.h>#include "dis-asm.h"#ifdef __HYPERVISOR_ia64_debug_op#define HAVE_DEBUG_OP#include <xen/arch-ia64/debug_op.h>#endifstatic int xc_handle = 0;static int domid = 0;static vcpu_guest_context_t *cur_ctx;static int cur_vcpu;#define PSR_BN (1UL << 44)#define PSR_SS (1UL << 40)#define PSR_DB (1UL << 24)#define PSR_TB (1UL << 26)#define PSR_DD (1UL << 39)#define PSR_ID (1UL << 37)#define PSR_IT (1UL << 36)#define PSR_DT (1UL << 17)#define PSR_RI_SHIFT 41#define CFM_SOF_MASK 0x3fint virt_to_phys (int is_inst, unsigned long vaddr, unsigned long *paddr);/* wrapper for vcpu_gest_context_any_t */static int xc_ia64_vcpu_getcontext(int xc_handle, uint32_t domid, uint32_t vcpu, vcpu_guest_context_t *ctxt){ return xc_vcpu_getcontext(xc_handle, domid, vcpu, (vcpu_guest_context_any_t *)ctxt);}static inline unsigned int ctx_slot (vcpu_guest_context_t *ctx){ return (ctx->regs.psr >> PSR_RI_SHIFT) & 3;}unsigned char *target_map_memory (unsigned long paddr){ static unsigned long cur_page = (unsigned long)-1; static unsigned char *cur_map = NULL; if ((paddr >> XC_PAGE_SHIFT) != cur_page) { if (cur_map) { munmap (cur_map, XC_PAGE_SIZE); cur_map = NULL; } cur_page = paddr >> XC_PAGE_SHIFT; cur_map = xc_map_foreign_range (xc_handle, domid, XC_PAGE_SIZE, PROT_READ, cur_page); if (cur_map == NULL) { perror ("cannot map page"); cur_page = -1; return NULL; } } return cur_map + (paddr & (XC_PAGE_SIZE - 1));}/* Get LENGTH bytes from info's buffer, at target address memaddr. Transfer them to myaddr. */inttarget_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info){ int i; unsigned long paddr; if (cur_ctx->regs.psr & PSR_IT) { if (virt_to_phys (1, memaddr, &paddr) != 0) return EIO; } else { /* Clear UC. */ paddr = memaddr & ~(1UL << 63); } for (i = 0; i < length; i++) { unsigned char *p = target_map_memory (paddr + i); if (p == NULL) return EIO; myaddr[i] = *p; } return 0;}/* Print an error message. We can assume that this is in response to an error return from buffer_read_memory. */voidperror_memory (int status, bfd_vma memaddr, struct disassemble_info *info){ if (status != EIO) /* Can't happen. */ (*info->fprintf_func) (info->stream, "Unknown error %d\n", status); else /* Actually, address between memaddr and memaddr + len was out of bounds. */ (*info->fprintf_func) (info->stream, "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);}/* This could be in a separate file, to save miniscule amounts of space in statically linked executables. *//* Just print the address is hex. This is included for completeness even though both GDB and objdump provide their own (to print symbolic addresses). */voidgeneric_print_address (bfd_vma addr, struct disassemble_info *info){ (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);}/* Just return the given address. */intgeneric_symbol_at_address (bfd_vma addr, struct disassemble_info * info){ return 1;}bfd_booleangeneric_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED, struct disassemble_info *info ATTRIBUTE_UNUSED){ return 1;}bfd_vma bfd_getl32 (const bfd_byte *addr){ unsigned long v; v = (unsigned long) addr[0]; v |= (unsigned long) addr[1] << 8; v |= (unsigned long) addr[2] << 16; v |= (unsigned long) addr[3] << 24; return (bfd_vma) v;}bfd_vma bfd_getl64 (const bfd_byte *addr){ unsigned long v; v = (unsigned long) addr[0]; v |= (unsigned long) addr[1] << 8; v |= (unsigned long) addr[2] << 16; v |= (unsigned long) addr[3] << 24; v |= (unsigned long) addr[4] << 32; v |= (unsigned long) addr[5] << 40; v |= (unsigned long) addr[6] << 48; v |= (unsigned long) addr[7] << 56; return (bfd_vma) v;}bfd_vma bfd_getb32 (const bfd_byte *addr){ unsigned long v; v = (unsigned long) addr[0] << 24; v |= (unsigned long) addr[1] << 16; v |= (unsigned long) addr[2] << 8; v |= (unsigned long) addr[3]; return (bfd_vma) v;}bfd_vma bfd_getl16 (const bfd_byte *addr){ unsigned long v; v = (unsigned long) addr[0]; v |= (unsigned long) addr[1] << 8; return (bfd_vma) v;}bfd_vma bfd_getb16 (const bfd_byte *addr){ unsigned long v; v = (unsigned long) addr[0] << 24; v |= (unsigned long) addr[1] << 16; return (bfd_vma) v;}voidinit_disassemble_info (struct disassemble_info *info, void *stream, fprintf_ftype fprintf_func){ memset (info, 0, sizeof (*info)); info->flavour = bfd_target_unknown_flavour; info->arch = bfd_arch_unknown; info->endian = BFD_ENDIAN_UNKNOWN; info->octets_per_byte = 1; info->fprintf_func = fprintf_func; info->stream = stream; info->read_memory_func = target_read_memory; info->memory_error_func = perror_memory; info->print_address_func = generic_print_address; info->symbol_at_address_func = generic_symbol_at_address; info->symbol_is_valid = generic_symbol_is_valid; info->display_endian = BFD_ENDIAN_UNKNOWN;}void target_disas (FILE *out, unsigned long code, unsigned long size){ unsigned long pc; int count; struct disassemble_info disasm_info; INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf); disasm_info.read_memory_func = target_read_memory;#if 0 disasm_info.buffer = NULL; disasm_info.buffer_vma = (unsigned long)code; disasm_info.buffer_length = size;#endif disasm_info.endian = BFD_ENDIAN_LITTLE; disasm_info.mach = 0; //bfd_mach_ia64; for (pc = code; pc < code + size; pc += count) { int slot = (pc & 0x0f) / 6; fprintf (out, "0x%016lx+%d:%c ", pc & ~0x0fUL, slot, ((pc & ~0x0fUL) == cur_ctx->regs.ip && slot == ctx_slot (cur_ctx)) ? '*' : ' '); count = print_insn_ia64 (pc, &disasm_info);#if 0 { int i; uint8_t b; fprintf (out, " {"); for (i = 0; i < count; i++) { target_read_memory (pc + i, &b, 1, &disasm_info); fprintf (out, " %02x", b); } fprintf (out, " }"); }#endif fprintf (out, "\n"); if (count < 0) break; }}#define PTE_ED_SHIFT 52#define PTE_ED_MASK 1#define PTE_PPN_SHIFT 12#define PTE_PPN_MASK 0x3fffffffff#define PTE_AR_SHIFT 9#define PTE_AR_MASK 7#define PTE_PL_SHIFT 7#define PTE_PL_MASK 3#define PTE_D_SHIFT 6#define PTE_D_MASK 1#define PTE_A_SHIFT 5#define PTE_A_MASK 1#define PTE_MA_SHIFT 2#define PTE_MA_MASK 7#define PTE_P_SHIFT 0#define PTE_P_MASK 1#define ITIR_KEY_SHIFT 8#define ITIR_KEY_MASK 0xffffff#define ITIR_PS_SHIFT 2#define ITIR_PS_MASK 0x3f#define ITIR_PS_MIN 12#define ITIR_PS_MAX 28#define RR_RID_SHIFT 8#define RR_RID_MASK 0xffffff#define RR_PS_SHIFT 2#define RR_PS_MASK 0x3f#define RR_VE_MASK 1static const char *get_ps (int ps_val){ static const char ps[][5] = {" 4K", " 8K", " 16K", " ", " 64K", " ", "256K", " ", " 1M", " ", " 4M", " ", " 16M", " ", " 64M", " ", "256M"}; return ((ps_val >= ITIR_PS_MIN && ps_val <= ITIR_PS_MAX) ? ps[ps_val - ITIR_PS_MIN] : " ");}static void print_a_tr (int i, const struct ia64_tr_entry *tr){ int ps_val, ma_val; unsigned long pa; static const char ma[][4] = {"WB ", " ", " ", " ", "UC ", "UCE", "WC ", "Nat"}; ps_val = tr->itir >> ITIR_PS_SHIFT & ITIR_PS_MASK; ma_val = tr->pte >> PTE_MA_SHIFT & PTE_MA_MASK; pa = (tr->pte >> PTE_PPN_SHIFT & PTE_PPN_MASK) << PTE_PPN_SHIFT; pa = (pa >> ps_val) << ps_val; printf (" [%2d] %ld %06lx %016lx %013lx %02d %s %ld %ld %ld %ld " "%ld %d %s %06lx\n", i, tr->pte >> PTE_P_SHIFT & PTE_P_MASK, tr->rid >> RR_RID_SHIFT & RR_RID_MASK, tr->vadr, pa, ps_val, get_ps (ps_val), tr->pte >> PTE_ED_SHIFT & PTE_ED_MASK, tr->pte >> PTE_PL_SHIFT & PTE_PL_MASK, tr->pte >> PTE_AR_SHIFT & PTE_AR_MASK, tr->pte >> PTE_A_SHIFT & PTE_A_MASK, tr->pte >> PTE_D_SHIFT & PTE_D_MASK, ma_val, ma[ma_val], tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);}void print_ctx (vcpu_guest_context_t *ctx){ struct vcpu_guest_context_regs *regs = &ctx->regs; int i; unsigned int rbs_size, cfm_sof; rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8; cfm_sof = (regs->cfm & CFM_SOF_MASK); printf ("bspstore: %016lx bsp: %016lx rbs_size=%d, sof=%d\n", regs->ar.bspstore, regs->ar.bsp, rbs_size, cfm_sof); for (i = 0; i < cfm_sof; i++) { int off = cfm_sof - i; unsigned int rbs_off = (((62 - ((rbs_size + regs->rbs_voff) % 64) + off)) / 63) + off; if (rbs_off > rbs_size) break; printf (" r%02d: %016lx%s", 32 + i, regs->rbs[rbs_size - rbs_off], (i % 3) != 2 ? " " : "\n"); } if ((i % 3) != 0) printf ("\n"); printf ("\n"); printf (" r1: %016lx ", regs->r[1]); printf (" r2: %016lx ", regs->r[2]); printf (" r3: %016lx\n", regs->r[3]); printf (" r4: %016lx ", regs->r[4]); printf (" r5: %016lx ", regs->r[5]); printf (" r6: %016lx\n", regs->r[6]); printf (" r7: %016lx ", regs->r[7]); printf (" r8: %016lx ", regs->r[8]); printf (" r9: %016lx\n", regs->r[9]); printf (" r10: %016lx ", regs->r[10]); printf (" r11: %016lx ", regs->r[11]); printf (" sp: %016lx\n", regs->r[12]); printf (" tp: %016lx ", regs->r[13]); printf (" r14: %016lx ", regs->r[14]); printf (" r15: %016lx\n", regs->r[15]); printf (" r16: %016lx ", regs->r[16]); printf (" r17: %016lx ", regs->r[17]); printf (" r18: %016lx\n", regs->r[18]); printf (" r19: %016lx ", regs->r[19]); printf (" r20: %016lx ", regs->r[20]); printf (" r21: %016lx\n", regs->r[21]); printf (" r22: %016lx ", regs->r[22]); printf (" r23: %016lx ", regs->r[23]); printf (" r24: %016lx\n", regs->r[24]); printf (" r25: %016lx ", regs->r[25]); printf (" r26: %016lx ", regs->r[26]); printf (" r27: %016lx\n", regs->r[27]); printf (" r28: %016lx ", regs->r[28]); printf (" r29: %016lx ", regs->r[29]); printf (" r30: %016lx\n", regs->r[30]); printf (" r31: %016lx ", regs->r[31]); printf (" "); printf (" b0: %016lx\n", regs->b[0]); printf ("\n"); printf (" psr: %016lx ", regs->psr); printf (" cfm: %016lx ", regs->cfm); printf (" pr: %016lx\n", regs->pr); printf ("\n"); printf (" ip: %016lx+%d", regs->ip, (int)(regs->psr >> PSR_RI_SHIFT) & 3); printf ("\n"); target_disas (stdout, regs->ip, 16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -