instrument.cpp

来自「用vc++编写的虚拟机仿真系统。可以模拟真实操作系统的一些功能。」· C++ 代码 · 共 407 行

CPP
407
字号
/////////////////////////////////////////////////////////////////////////// $Id: instrument.cc,v 1.4 2001/10/03 13:10:37 bdenney Exp $/////////////////////////////////////////////////////////////////////////////  Copyright (C) 2001  MandrakeSoft S.A.////    MandrakeSoft S.A.//    43, rue d'Aboukir//    75002 Paris - France//    http://www.linux-mandrake.com///    http://www.mandrakesoft.com/////  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 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// Sample instrumentation library to generate physical address// of each instruction executed, and physical address of it's// data reads/writes#include "bochs.h"// maximum size of an instruction#define MAX_OPCODE_SIZE 16// maximum physical addresses an instruction can generate#define MAX_DATA_ACCESSES 1024// maximum number of IO accesses an instruction can generate#define MAX_IO_ACCESSES 4 // probably could be 1// Use this variable to turn on/off collection of instrumentation data// If you are not using the debugger to turn this on/off, then possibly// start this at 1 instead of 0.static Boolean  collect_data = 0;static Boolean  is_valid = 0;  // is current instruction validstatic struct {  unsigned opcode_size;  Bit8u    opcode[MAX_OPCODE_SIZE];  Bit32u   linear_iaddr;  Bit32u   phy_iaddr;  unsigned num_data_accesses;  struct {    Bit32u   laddr; // linear address    Bit32u   paddr; // physical address    unsigned op; // BX_READ or BX_WRITE    unsigned size; // 1 .. 4    } data_access[MAX_DATA_ACCESSES];  unsigned num_io_accesses;  struct {    Bit16u addr;    unsigned op; // BX_READ==inp or BX_WRITE==outp    unsigned size; // 1 .. 4    } io_access[MAX_IO_ACCESSES];  } instruction;static logfunctions *instrument_log;#define LOG_THIS instrument_log->voidbx_instr_init (){  instrument_log = new logfunctions ();  //BX_INFO (("init"));}voidbx_instr_shutdown (){  //BX_INFO (("shutdown"));}  voidbx_instr_opcode_begin(Bit32u linear){  Boolean valid;  if (!collect_data) return;  //BX_INFO(("opcode_begin: linear address is %08x\n", linear));  is_valid = 1;  instruction.opcode_size = 0;  instruction.linear_iaddr = linear;  bx_cpu.dbg_xlate_linear2phy(linear, &instruction.phy_iaddr, &valid);  instruction.phy_iaddr = A20ADDR(instruction.phy_iaddr);  // If linear translation doesn't exist, a paging exception will occur.  // Invalidate collecting data for now.  if (!valid)    is_valid = 0;  instruction.num_data_accesses = 0;  instruction.num_io_accesses = 0;}  voidbx_instr_opcode_end(Bit32u linear){  unsigned i;  UNUSED(linear);  if (!collect_data || !is_valid) return;  // instruction completed:  // print out instruction opcode bytes and phy mem stats  if (is_valid) {    fprintf(stderr, "opcode: l=0x%x, p=0x%x: ",            (unsigned) instruction.linear_iaddr,            (unsigned) instruction.phy_iaddr);    for (i=0; i<instruction.opcode_size; i++) {      fprintf(stderr, " %02x", instruction.opcode[i]);      }    fprintf(stderr, "\n");    for (i=0; i<instruction.num_data_accesses; i++) {      fprintf(stderr, "%s: l=0x%x, p=0x%x, %u bytes\n",        (instruction.data_access[i].op==BX_READ) ? "read" : "write",        (unsigned) instruction.data_access[i].laddr,        (unsigned) instruction.data_access[i].paddr,        (unsigned) instruction.data_access[i].size);      }    for (i=0; i<instruction.num_io_accesses; i++) {      fprintf(stderr, "%s: 0x%x, %u bytes\n",        (instruction.io_access[i].op==BX_READ) ? "in" : "out",        (unsigned) instruction.io_access[i].addr,        (unsigned) instruction.io_access[i].size);      }    }  is_valid = 0;}  voidbx_instr_fetch_byte(Bit8u val8){  if (!collect_data || !is_valid) return;  if ((instruction.opcode_size+1) > MAX_OPCODE_SIZE) {    BX_PANIC (("instr_fetch_byte: opcode too big.\n"));    }  else {    instruction.opcode[instruction.opcode_size] = val8;    instruction.opcode_size++;    }}  voidbx_instr_fetch_word(Bit16u val16){  if (!collect_data || !is_valid) return;  if ((instruction.opcode_size+2) > MAX_OPCODE_SIZE) {    BX_PANIC (("instr_fetch_word: opcode too big.\n"));    }  else {    instruction.opcode[instruction.opcode_size]   = val16 & 0xff;    instruction.opcode[instruction.opcode_size+1] = val16 >> 8;    instruction.opcode_size += 2;    }}  voidbx_instr_fetch_dword(Bit32u val32){  if (!collect_data || !is_valid) return;  if ((instruction.opcode_size+4) > MAX_OPCODE_SIZE) {    BX_PANIC (("instr_fetch_dword: opcode too big.\n"));    }  else {    instruction.opcode[instruction.opcode_size]   = val32; val32 >>= 8;    instruction.opcode[instruction.opcode_size+1] = val32; val32 >>= 8;    instruction.opcode[instruction.opcode_size+2] = val32; val32 >>= 8;    instruction.opcode[instruction.opcode_size+3] = val32;    instruction.opcode_size += 4;    }}  voidbx_instr_interrupt(unsigned vector){  UNUSED(vector);  if (!collect_data || !is_valid) return;}  voidbx_instr_exception(unsigned vector){  is_valid = 0;  if (!collect_data || !is_valid) return;}  voidbx_instr_inp(Bit16u addr, unsigned len){  unsigned index;  if (!collect_data || !is_valid) return;  if (instruction.num_io_accesses >= MAX_IO_ACCESSES) {    BX_PANIC (("instr_inp: instructions has too many accesses\n"));    }  index = instruction.num_io_accesses;  instruction.io_access[index].addr = addr;  instruction.io_access[index].op   = BX_READ;  instruction.io_access[index].size = len;  instruction.num_io_accesses++;}  voidbx_instr_outp(Bit16u addr, unsigned len){  unsigned index;  if (!collect_data || !is_valid) return;  if (instruction.num_io_accesses >= MAX_IO_ACCESSES) {    BX_PANIC (("instr_outp: instructions has too many accesses\n"));    }  index = instruction.num_io_accesses;  instruction.io_access[index].addr = addr;  instruction.io_access[index].op   = BX_WRITE;  instruction.io_access[index].size = len;  instruction.num_io_accesses++;}// some extra functions called from debugger  voidbx_instr_start(void){  collect_data = 1;  is_valid = 0;}  voidbx_instr_stop(void){  collect_data = 0;  is_valid = 0;}  voidbx_instr_reset(void){}  voidbx_instr_print(void){}  voidbx_instr_cnear_branch_taken(Bit32u new_eip){  // conditional near branch was taken  Bit32u laddr, paddr;  Boolean valid;  if (!collect_data || !is_valid) return;  // find linear address  laddr = BX_CPU(0)->sregs[BX_SREG_CS].cache.u.segment.base + new_eip;  // find physical address  bx_cpu.dbg_xlate_linear2phy(laddr, &paddr, &valid);  paddr = A20ADDR(paddr);  if (valid==0) {    // don't use paddr; laddr not found in page tables    }  else {    fprintf(stderr, "cnear taken: l=0x%x p=0x%x\n", laddr, paddr);    }}  voidbx_instr_cnear_branch_not_taken(void){  // conditional near branch was NOT taken  if (!collect_data || !is_valid) return;  fprintf(stderr, "cnear NOT taken\n");}  voidbx_instr_ucnear_branch(unsigned what, Bit32u new_eip){  // unconditional near branch  Bit32u laddr, paddr;  Boolean valid;  if (!collect_data || !is_valid) return;  // find linear address  laddr = BX_CPU(0)->sregs[BX_SREG_CS].cache.u.segment.base + new_eip;  // find physical address  bx_cpu.dbg_xlate_linear2phy(laddr, &paddr, &valid);  paddr = A20ADDR(paddr);  if (valid==0) {    // don't use paddr; laddr not found in page tables    }  else {    fprintf(stderr, "ucnear: l=0x%x p=0x%x\n", laddr, paddr);    }  switch (what) {    case BX_INSTR_IS_CALL: break;    case BX_INSTR_IS_JMP: break;    case BX_INSTR_IS_RET: break;    default:      BX_PANIC (("instr_ucnear_branch: default case reached.\n"));    }}  voidbx_instr_far_branch(unsigned what, Bit32u new_cs, Bit32u new_eip){  // unconditional far branch  Bit32u laddr, paddr;  Boolean valid;  UNUSED(new_cs);  if (!collect_data || !is_valid) return;  // find linear address  laddr = BX_CPU(0)->sregs[BX_SREG_CS].cache.u.segment.base + new_eip;  // find physical address  bx_cpu.dbg_xlate_linear2phy(laddr, &paddr, &valid);  paddr = A20ADDR(paddr);  if (valid==0) {    // don't use paddr; laddr not found in page tables    }  else {    fprintf(stderr, "far: l=0x%x p=0x%x\n", laddr, paddr);    }  switch (what) {    case BX_INSTR_IS_CALL: break;    case BX_INSTR_IS_INT: break;    case BX_INSTR_IS_IRET: break;    case BX_INSTR_IS_JMP: break;    case BX_INSTR_IS_RET: break;    default:      BX_PANIC (("instr_far_branch: default case reached.\n"));    }}  voidbx_instr_lin_write(Bit32u lin, Bit32u phy, unsigned len){  unsigned index;  if (!collect_data || !is_valid) return;  if (instruction.num_data_accesses >= MAX_DATA_ACCESSES) {    BX_PANIC (("instr_lin_write: instruction has too many accesses\n"));    }  index = instruction.num_data_accesses;  instruction.data_access[index].paddr = A20ADDR(phy);  instruction.data_access[index].laddr = lin;  instruction.data_access[index].op   = BX_WRITE;  instruction.data_access[index].size = len;  instruction.num_data_accesses++;}  voidbx_instr_lin_read(Bit32u lin, Bit32u phy, unsigned len){  unsigned index;  if (!collect_data || !is_valid) return;  if (instruction.num_data_accesses >= MAX_DATA_ACCESSES) {    BX_PANIC (("instr_lin_read: instruction has too many accesses\n"));    }  index = instruction.num_data_accesses;  instruction.data_access[index].paddr = A20ADDR(phy);  instruction.data_access[index].laddr = lin;  instruction.data_access[index].op   = BX_READ;  instruction.data_access[index].size = len;  instruction.num_data_accesses++;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?