/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. All Rights Reserved. * * You must obtain a written license from and pay applicable license fees to QNX * Software Systems before you may reproduce, modify or distribute this software, * or any work that includes all or part of this software. Free development * licenses are available for evaluation and non-commercial purposes. For more * information visit http://licensing.qnx.com or email licensing@qnx.com. * * This file may contain contributions from others. Please review this entire * file for other proprietary rights or license notices, as well as the QNX * Development Suite License Guide at http://licensing.qnx.com/license-guide/ * for other information. * $ */ #include "kdserver.h" #include #include /* Define a structure used for communication to a GDB client */ typedef struct { int eax, ecx, edx, ebx, uesp, ebp, esi, edi, eip, efl; int cs, ss, ds, es, fs, gs; } x86_gdb_regs; static int x86_init(int elf_cpu) { switch(elf_cpu) { case EM_386: case EM_486: break; default: return 0; } if(note->cpu_info) { // PAE enabled cpu->pgtbl_size = 0x4000; } return 1; } static int x86_v2p(uintptr_t vaddr, paddr64_t *paddrp, unsigned *lenp) { uint64_t pde; uint64_t pte; paddr64_t paddr; unsigned offset; unsigned page_size; // consult the page table... if(note->cpu_info) { // PAE enabled pde = endian_native64(((uint64_t *)pgtbl)[vaddr >> 21]); page_size = 2*1024*1024; } else { pde = endian_native32(((uint32_t *)pgtbl)[vaddr >> 22]); page_size = 4*1024*1024; } if(!(pde & X86_PDE_PRESENT)) { return 0; } if(!(pde & X86_PDE_PS)) { // 4K page page_size = 0x1000; paddr = pde & ~(X86_PDE_NX | (page_size-1)); if(note->cpu_info) { //PAE enabled paddr += ((vaddr >> 12) & 0x1ff)*sizeof(uint64_t); if(core_read_paddr(paddr, &pte, sizeof(pte)) != sizeof(pte)) { fprintf( stderr, "PAE core_readmem of %llx failed\n", paddr ); return 0; } pte = endian_native64(pte); } else { uint32_t pte32; paddr += ((vaddr >> 12) & 0x3ff)*sizeof(uint32_t); if(core_read_paddr(paddr, &pte32, sizeof(pte32)) != sizeof(pte32)) { fprintf( stderr, "core_readmem of %llx failed\n", paddr ); return 0; } pte = endian_native32(pte32); } paddr = pte & ~(X86_PDE_NX | (page_size-1)); if(!(pte & X86_PTE_PRESENT)) { return 0; } } else { paddr = pde & ~(X86_PDE_NX | (page_size-1)); } offset = vaddr & (page_size - 1); *paddrp = paddr | offset; *lenp = page_size - offset; return 1; } static void x86_cvt_regset(const void *in, void *out) { const X86_CPU_REGISTERS *ctx = in; x86_gdb_regs *gdb = out; gdb->eax = ctx->eax; gdb->ebx = ctx->ebx; gdb->ecx = ctx->ecx; gdb->edx = ctx->edx; gdb->esi = ctx->esi; gdb->edi = ctx->edi; gdb->ebp = ctx->ebp; gdb->uesp = ctx->esp; gdb->efl = ctx->efl; gdb->eip = ctx->eip; gdb->cs = ctx->cs; gdb->ds = 0; gdb->ss = ctx->ss; gdb->es = 0; gdb->fs = 0; gdb->gs = 0; } struct cpuinfo cpu_x86 = { x86_init, x86_v2p, x86_cvt_regset, 0x1000, sizeof(x86_gdb_regs), sizeof(uint32_t) };