| /* | |
| * Debugger CPU backend definitions | |
| * | |
| * Copyright 2004 Eric Pouech | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library 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 | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| enum be_cpu_addr {be_cpu_addr_pc, be_cpu_addr_stack, be_cpu_addr_frame}; | |
| enum be_xpoint_type {be_xpoint_break, be_xpoint_watch_exec, be_xpoint_watch_read, | |
| be_xpoint_watch_write}; | |
| struct backend_cpu | |
| { | |
| /* ------------------------------------------------------------------------------ | |
| * address manipulation | |
| * ------------------------------------------------------------------------------ */ | |
| /* Linearizes an address. Only CPUs with segmented address model need this. | |
| * Otherwise, implementation is straigthforward (be_cpu_linearize will do) | |
| */ | |
| void* (*linearize)(HANDLE hThread, const ADDRESS*); | |
| /* Fills in an ADDRESS structure from a segment & an offset. CPUs without | |
| * segment address model should use 0 as seg. Required method to fill | |
| * in an ADDRESS (except an linear one). | |
| * Non segmented CPU shall use be_cpu_build_addr | |
| */ | |
| unsigned (*build_addr)(HANDLE hThread, const CONTEXT* ctx, | |
| ADDRESS* addr, unsigned seg, | |
| unsigned long offset); | |
| /* Retrieves in addr an address related to the context (program counter, stack | |
| * pointer, frame pointer) | |
| */ | |
| unsigned (*get_addr)(HANDLE hThread, const CONTEXT* ctx, | |
| enum be_cpu_addr, ADDRESS* addr); | |
| /* ------------------------------------------------------------------------------- | |
| * context manipulation | |
| * ------------------------------------------------------------------------------- */ | |
| /* Enables/disables CPU single step mode (depending on enable) */ | |
| void (*single_step)(CONTEXT* ctx, unsigned enable); | |
| /* Dumps out the content of the context */ | |
| void (*print_context)(HANDLE hThread, const CONTEXT* ctx); | |
| /* Prints information about segments. Non segmented CPU should leave this | |
| * function empty | |
| */ | |
| void (*print_segment_info)(HANDLE hThread, const CONTEXT* ctx); | |
| /* Do the initialization so that the debugger has internal variables linked | |
| * to the context's registers | |
| */ | |
| const struct dbg_internal_var* | |
| (*init_registers)(CONTEXT* ctx); | |
| /* ------------------------------------------------------------------------------- | |
| * code inspection | |
| * -------------------------------------------------------------------------------*/ | |
| /* Check whether the instruction at addr is an insn to step over | |
| * (like function call, interruption...) | |
| */ | |
| unsigned (*is_step_over_insn)(const void* addr); | |
| /* Check whether instruction at 'addr' is the return from a function call */ | |
| unsigned (*is_function_return)(const void* addr); | |
| /* Check whether instruction at 'addr' is the CPU break instruction. On i386, | |
| * it's INT3 (0xCC) | |
| */ | |
| unsigned (*is_break_insn)(const void*); | |
| /* Check whether instruciton at 'addr' is a function call */ | |
| unsigned (*is_function_call)(const void* insn, ADDRESS* callee); | |
| /* Ask for dissasembling one instruction. If display is true, assembly code | |
| * will be printed. In all cases, 'addr' is advanced at next instruction | |
| */ | |
| void (*disasm_one_insn)(ADDRESS* addr, int display); | |
| /* ------------------------------------------------------------------------------- | |
| * break points / watchpoints handling | |
| * -------------------------------------------------------------------------------*/ | |
| /* Inserts an Xpoint in the CPU context and/or debuggee address space */ | |
| unsigned (*insert_Xpoint)(HANDLE hProcess, CONTEXT* ctx, | |
| enum be_xpoint_type type, void* addr, | |
| unsigned long* val, unsigned size); | |
| /* Removes an Xpoint in the CPU context and/or debuggee address space */ | |
| unsigned (*remove_Xpoint)(HANDLE hProcess, CONTEXT* ctx, | |
| enum be_xpoint_type type, void* addr, | |
| unsigned long val, unsigned size); | |
| /* Checks whether a given watchpoint has been triggered */ | |
| unsigned (*is_watchpoint_set)(const CONTEXT* ctx, unsigned idx); | |
| /* Clears the watchpoint indicator */ | |
| void (*clear_watchpoint)(CONTEXT* ctx, unsigned idx); | |
| /* After a break instruction is executed, in the corresponding exception handler, | |
| * some CPUs report the address of the insn after the break insn, some others | |
| * report the address of the break insn itself. | |
| * This function lets adjust the context PC to reflect this behavior. | |
| */ | |
| int (*adjust_pc_for_break)(CONTEXT* ctx, BOOL way); | |
| /* ------------------------------------------------------------------------------- | |
| * basic type read/write | |
| * -------------------------------------------------------------------------------*/ | |
| /* Reads an integer from memory and stores it inside a long long int */ | |
| int (*fetch_integer)(const struct dbg_lvalue* lvalue, unsigned size, unsigned is_signed, long long int*); | |
| /* Reads a real from memory and stores it inside a long double */ | |
| int (*fetch_float)(const struct dbg_lvalue* lvalue, unsigned size, long double*); | |
| }; | |
| extern struct backend_cpu* be_cpu; | |
| /* some handy functions for non segmented CPUs */ | |
| void* be_cpu_linearize(HANDLE hThread, const ADDRESS*); | |
| unsigned be_cpu_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS* addr, | |
| unsigned seg, unsigned long offset); |