T32: Dissassembler to evaluate memory instructions.
For the T32 variant we have to evaluate the memory access instruction to find out, which memory address was accessed. Dissassmbly by OpenOCDs arm_disassembler.hpp/.cc: - fine for ARM / Thumb1 - needs fixes for Thumb2 :( (currently doing that..)
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
#include "T32Connector.hpp"
|
#include "T32Connector.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <t32.h>
|
#include <t32.h>
|
||||||
|
#include "sal/MemoryInstruction.hpp"
|
||||||
|
|
||||||
using namespace fail;
|
using namespace fail;
|
||||||
|
|
||||||
@ -93,7 +94,6 @@ void T32Connector::brk() {
|
|||||||
#include "sal/t32/T32Constants.hpp"
|
#include "sal/t32/T32Constants.hpp"
|
||||||
|
|
||||||
void T32Connector::test() {
|
void T32Connector::test() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default T32 error handler */
|
/* Default T32 error handler */
|
||||||
|
|||||||
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include "T32Connector.hpp"
|
#include "T32Connector.hpp"
|
||||||
#include "t32config.hpp"
|
#include "t32config.hpp"
|
||||||
|
#include "sal/MemoryInstruction.hpp"
|
||||||
|
#include "util/Disassembler.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fail;
|
using namespace fail;
|
||||||
@ -96,6 +98,8 @@ int main(int argc, char** argv){
|
|||||||
// The experiments/traces hopefully set some Breakpoints, we can react on.
|
// The experiments/traces hopefully set some Breakpoints, we can react on.
|
||||||
// We may also provide a timeout, if a TimerListener was set wanted.
|
// We may also provide a timeout, if a TimerListener was set wanted.
|
||||||
|
|
||||||
|
MemoryInstruction mem;
|
||||||
|
address_t ip;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
// Start execution (with next timeout, if any)
|
// Start execution (with next timeout, if any)
|
||||||
@ -105,8 +109,11 @@ int main(int argc, char** argv){
|
|||||||
// Evaluate state.
|
// Evaluate state.
|
||||||
t32.test();// TODO
|
t32.test();// TODO
|
||||||
// Call appropriate callback of the SimulatorController.
|
// Call appropriate callback of the SimulatorController.
|
||||||
fail::simulator.onBreakpoint(&fail::simulator.getCPU(0), fail::simulator.getCPU(0).getInstructionPointer(), fail::ANY_ADDR);
|
ip = fail::simulator.getCPU(0).getInstructionPointer();
|
||||||
// TODO fail::simulator.onMemoryAccess(&fail::simulator.getCPU(0), 0x20002074, 1, true, fail::simulator.getCPU(0).getInstructionPointer());
|
fail::simulator.onBreakpoint(&fail::simulator.getCPU(0), ip , fail::ANY_ADDR);
|
||||||
|
if( meminstruction.eval(ip, mem) ) {
|
||||||
|
fail::simulator.onMemoryAccess(&fail::simulator.getCPU(0), mem.getAddress(), mem.getWidth(), mem.isWriteAccess(), ip );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "[T32 Backend] After startup" << endl;
|
cout << "[T32 Backend] After startup" << endl;
|
||||||
|
|||||||
@ -64,6 +64,8 @@ elseif(BUILD_T32)
|
|||||||
if(BUILD_ARM)
|
if(BUILD_ARM)
|
||||||
set(SRCS ${SRCS}
|
set(SRCS ${SRCS}
|
||||||
t32/T32ArmCPU.cc
|
t32/T32ArmCPU.cc
|
||||||
|
arm/ArmMemoryInstruction.cc
|
||||||
|
arm/arm_disassembler.cc
|
||||||
)
|
)
|
||||||
endif(BUILD_ARM)
|
endif(BUILD_ARM)
|
||||||
endif(BUILD_BOCHS)
|
endif(BUILD_BOCHS)
|
||||||
|
|||||||
40
src/core/sal/MemoryInstruction.hpp
Normal file
40
src/core/sal/MemoryInstruction.hpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __MEMORYINSTRUCTION_HPP__
|
||||||
|
#define __MEMORYINSTRUCTION_HPP__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "SALConfig.hpp"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class MemoryInstruction {
|
||||||
|
regdata_t address;
|
||||||
|
regdata_t value;
|
||||||
|
uint8_t width;
|
||||||
|
bool writeAccess;
|
||||||
|
public:
|
||||||
|
MemoryInstruction(regdata_t address = ADDR_INV, regdata_t value = 0, uint8_t width = 0, bool writeAccess = false) :
|
||||||
|
address(address), value(value), width(width), writeAccess(writeAccess) { };
|
||||||
|
|
||||||
|
bool isWriteAccess(void) const { return writeAccess; }
|
||||||
|
regdata_t getAddress() const { return address; }
|
||||||
|
regdata_t getValue() const { return value; }
|
||||||
|
uint8_t getWidth() const { return width; }
|
||||||
|
|
||||||
|
bool isValid(void) const { return address != ADDR_INV; }
|
||||||
|
|
||||||
|
void setAddress(regdata_t addr) { address = addr; }
|
||||||
|
void setValue(regdata_t val) { value = val; }
|
||||||
|
void setWidth(uint8_t w) { width = w; }
|
||||||
|
void setWriteAccess(bool iswrite) { writeAccess = iswrite; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemoryInstructionAnalyzer {
|
||||||
|
public:
|
||||||
|
virtual bool eval(address_t opcode, MemoryInstruction & result) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern MemoryInstructionAnalyzer & meminstruction;
|
||||||
|
} // end of namespace fail
|
||||||
|
|
||||||
|
#endif // __MEMORYINSTRUCTION_HPP__
|
||||||
|
|
||||||
97
src/core/sal/arm/ArmMemoryInstruction.cc
Normal file
97
src/core/sal/arm/ArmMemoryInstruction.cc
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include "ArmMemoryInstruction.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
static ArmMemoryInstructionAnalyzer anal;
|
||||||
|
MemoryInstructionAnalyzer & meminstruction = anal;
|
||||||
|
|
||||||
|
address_t ArmMemoryInstructionAnalyzer::findPrevious(address_t address){
|
||||||
|
if(m_dis.hasInstructionAt(address-2)) {
|
||||||
|
return address - 2;
|
||||||
|
} else if (m_dis.hasInstructionAt(address - 4)) {
|
||||||
|
return address - 4;
|
||||||
|
} else {
|
||||||
|
return ADDR_INV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArmMemoryInstructionAnalyzer::evaluate(arm_instruction & inst, MemoryInstruction& result){
|
||||||
|
cout << "Memory Access: " << inst.text << " - Size: " << inst.instruction_size << " Type " << inst.type << endl;
|
||||||
|
inst.info.load_store.evaluate();
|
||||||
|
result.setValue(inst.info.load_store.value);
|
||||||
|
result.setAddress(inst.info.load_store.address);
|
||||||
|
result.setWidth(4); // TODO;
|
||||||
|
result.setWriteAccess(inst.isStoreInstruction());
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Cortex M3 Lauterbach is a pain in the ass, as a Memory Watchpoint does not stop
|
||||||
|
// at the accessing instruction, but 1 or 2 instructions later.
|
||||||
|
bool ArmMemoryInstructionAnalyzer::eval_cm3(address_t address, MemoryInstruction& result){
|
||||||
|
arm_instruction inst;
|
||||||
|
uint32_t opcode =0;
|
||||||
|
address = findPrevious(address); // Cortex M3: memory access is at the previous instruction
|
||||||
|
opcode = m_dis.disassemble(address).opcode;
|
||||||
|
|
||||||
|
// OpenOCDs thumb2_opcode evaluation is not complete yet. :(
|
||||||
|
thumb2_opcode(address, opcode, &inst);
|
||||||
|
|
||||||
|
if(inst.isMemoryAccess()){
|
||||||
|
evaluate(inst, result);
|
||||||
|
return true;
|
||||||
|
} else if(inst.isBranchInstruction()){
|
||||||
|
// The memory access took place within the function previously branched
|
||||||
|
int regop = inst.info.b_bl_bx_blx.reg_operand;
|
||||||
|
uint32_t addr = inst.info.b_bl_bx_blx.target_address;
|
||||||
|
//cout << " Reg:" << hex << regop << " address " << hex << addr << endl;
|
||||||
|
// Lets look into this function
|
||||||
|
if( regop == -1 ){
|
||||||
|
// address should be set..
|
||||||
|
const ElfSymbol & sym = m_elf.getSymbol(addr|1); // | 1 to set first bit -> thumbmode
|
||||||
|
addr += sym.getSize(); // Go to end of function.
|
||||||
|
// THIS IS DANGEROUS: The memory access can be anywhere within this function, one instruction before a ret.
|
||||||
|
// OR, the memory access itself can result in leaving the function :e.g., ldr pc, [r3]
|
||||||
|
// We cannot be sure :( Here we assume the first memory access from the back.
|
||||||
|
do { // go backwards until there is a memory instruction.
|
||||||
|
addr = findPrevious(addr); // find previous
|
||||||
|
thumb2_opcode(addr, m_dis.disassemble(addr).opcode, &inst);
|
||||||
|
} while( !inst.isMemoryAccess() );
|
||||||
|
evaluate(inst, result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There was a memory access before, but the previous instruction
|
||||||
|
// is neither an access nor a branch.
|
||||||
|
// This can happen if we came here from anywhere, e.g. by ldr pc, [r4]
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmMemoryInstructionAnalyzer::eval_ca9(address_t address, MemoryInstruction& result){
|
||||||
|
arm_instruction inst;
|
||||||
|
uint32_t opcode = m_dis.disassemble(address).opcode;
|
||||||
|
arm_evaluate_opcode(address, opcode, &inst);
|
||||||
|
if( inst.isMemoryAccess() ){
|
||||||
|
evaluate(inst, result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CORTEXM3
|
||||||
|
|
||||||
|
bool ArmMemoryInstructionAnalyzer::eval(address_t address, MemoryInstruction & result){
|
||||||
|
#ifdef CORTEXM3
|
||||||
|
#warning "Memory Accesses cannot be evaluated completedly!"
|
||||||
|
return eval_cm3(address, result);
|
||||||
|
#elif defined CORTEXA9
|
||||||
|
return eval_ca9(address, result);
|
||||||
|
#else
|
||||||
|
#warning "Memory Accesses are not evaluated!"
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
34
src/core/sal/arm/ArmMemoryInstruction.hpp
Normal file
34
src/core/sal/arm/ArmMemoryInstruction.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef __ARMMEMORYINSTRUCITON_HPP__
|
||||||
|
#define __ARMMEMORYINSTRUCITON_HPP__
|
||||||
|
|
||||||
|
#include "../MemoryInstruction.hpp"
|
||||||
|
#include "util/Disassembler.hpp"
|
||||||
|
#include "util/ElfReader.hpp"
|
||||||
|
#include "arm_disassembler.hpp"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class ArmMemoryInstructionAnalyzer : public MemoryInstructionAnalyzer {
|
||||||
|
fail::ElfReader m_elf;
|
||||||
|
fail::Disassembler m_dis;
|
||||||
|
|
||||||
|
address_t findPrevious(address_t addr);
|
||||||
|
void evaluate(arm_instruction & inst, MemoryInstruction& result);
|
||||||
|
bool eval_ca9(address_t address, MemoryInstruction& result);
|
||||||
|
bool eval_cm3(address_t address, MemoryInstruction& result);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ArmMemoryInstructionAnalyzer() {
|
||||||
|
m_dis.init();
|
||||||
|
};
|
||||||
|
|
||||||
|
bool eval(address_t opcode, MemoryInstruction & result);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} //end of namespace fail
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __ARMMEMORYINSTRUCITON_HPP__
|
||||||
|
|
||||||
4565
src/core/sal/arm/arm_disassembler.cc
Normal file
4565
src/core/sal/arm/arm_disassembler.cc
Normal file
File diff suppressed because it is too large
Load Diff
226
src/core/sal/arm/arm_disassembler.hpp
Normal file
226
src/core/sal/arm/arm_disassembler.hpp
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2006 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program 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. *
|
||||||
|
* *
|
||||||
|
* This program 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, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ARM_DISASSEMBLER_H
|
||||||
|
#define ARM_DISASSEMBLER_H
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum arm_instruction_type {
|
||||||
|
ARM_UNKNOWN_INSTUCTION,
|
||||||
|
|
||||||
|
/* Branch instructions */
|
||||||
|
ARM_B,
|
||||||
|
ARM_BL,
|
||||||
|
ARM_BX,
|
||||||
|
ARM_BLX,
|
||||||
|
|
||||||
|
/* Data processing instructions */
|
||||||
|
ARM_AND,
|
||||||
|
ARM_EOR,
|
||||||
|
ARM_SUB,
|
||||||
|
ARM_RSB,
|
||||||
|
ARM_ADD,
|
||||||
|
ARM_ADC,
|
||||||
|
ARM_SBC,
|
||||||
|
ARM_RSC,
|
||||||
|
ARM_TST,
|
||||||
|
ARM_TEQ,
|
||||||
|
ARM_CMP,
|
||||||
|
ARM_CMN,
|
||||||
|
ARM_ORR,
|
||||||
|
ARM_MOV,
|
||||||
|
ARM_BIC,
|
||||||
|
ARM_MVN,
|
||||||
|
|
||||||
|
/* Load/store instructions */
|
||||||
|
ARM_LDR,
|
||||||
|
ARM_LDRB,
|
||||||
|
ARM_LDRT,
|
||||||
|
ARM_LDRBT,
|
||||||
|
|
||||||
|
ARM_LDRH,
|
||||||
|
ARM_LDRSB,
|
||||||
|
ARM_LDRSH,
|
||||||
|
ARM_LDREX,
|
||||||
|
ARM_LDREXB,
|
||||||
|
ARM_LDREXH,
|
||||||
|
ARM_LDM,
|
||||||
|
|
||||||
|
ARM_STR,
|
||||||
|
ARM_STRB,
|
||||||
|
ARM_STRT,
|
||||||
|
ARM_STRBT,
|
||||||
|
|
||||||
|
ARM_STRH,
|
||||||
|
ARM_STREX,
|
||||||
|
ARM_STREXB,
|
||||||
|
ARM_STREXH,
|
||||||
|
ARM_STM,
|
||||||
|
|
||||||
|
/* Status register access instructions */
|
||||||
|
ARM_MRS,
|
||||||
|
ARM_MSR,
|
||||||
|
|
||||||
|
/* Multiply instructions */
|
||||||
|
ARM_MUL,
|
||||||
|
ARM_MLA,
|
||||||
|
ARM_SMULL,
|
||||||
|
ARM_SMLAL,
|
||||||
|
ARM_UMULL,
|
||||||
|
ARM_UMLAL,
|
||||||
|
|
||||||
|
/* Miscellaneous instructions */
|
||||||
|
ARM_CLZ,
|
||||||
|
|
||||||
|
/* Exception generating instructions */
|
||||||
|
ARM_BKPT,
|
||||||
|
ARM_SWI,
|
||||||
|
|
||||||
|
/* Coprocessor instructions */
|
||||||
|
ARM_CDP,
|
||||||
|
ARM_LDC,
|
||||||
|
ARM_STC,
|
||||||
|
ARM_MCR,
|
||||||
|
ARM_MRC,
|
||||||
|
|
||||||
|
/* Semaphore instructions */
|
||||||
|
ARM_SWP,
|
||||||
|
ARM_SWPB,
|
||||||
|
|
||||||
|
/* Enhanced DSP extensions */
|
||||||
|
ARM_MCRR,
|
||||||
|
ARM_MRRC,
|
||||||
|
ARM_PLD,
|
||||||
|
ARM_QADD,
|
||||||
|
ARM_QDADD,
|
||||||
|
ARM_QSUB,
|
||||||
|
ARM_QDSUB,
|
||||||
|
ARM_SMLAxy,
|
||||||
|
ARM_SMLALxy,
|
||||||
|
ARM_SMLAWy,
|
||||||
|
ARM_SMULxy,
|
||||||
|
ARM_SMULWy,
|
||||||
|
ARM_LDRD,
|
||||||
|
ARM_STRD,
|
||||||
|
|
||||||
|
ARM_UNDEFINED_INSTRUCTION = 0xffffffff,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arm_b_bl_bx_blx_instr {
|
||||||
|
int reg_operand;
|
||||||
|
uint32_t target_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
union arm_shifter_operand {
|
||||||
|
struct {
|
||||||
|
uint32_t immediate;
|
||||||
|
} immediate;
|
||||||
|
struct {
|
||||||
|
uint8_t Rm;
|
||||||
|
uint8_t shift; /* 0: LSL, 1: LSR, 2: ASR, 3: ROR, 4: RRX */
|
||||||
|
uint8_t shift_imm;
|
||||||
|
} immediate_shift;
|
||||||
|
struct {
|
||||||
|
uint8_t Rm;
|
||||||
|
uint8_t shift;
|
||||||
|
uint8_t Rs;
|
||||||
|
} register_shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arm_data_proc_instr {
|
||||||
|
int variant; /* 0: immediate, 1: immediate_shift, 2: register_shift */
|
||||||
|
uint8_t S;
|
||||||
|
uint8_t Rn;
|
||||||
|
uint8_t Rd;
|
||||||
|
union arm_shifter_operand shifter_operand;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arm_load_store_instr {
|
||||||
|
uint8_t Rd;
|
||||||
|
uint8_t Rn;
|
||||||
|
uint8_t U;
|
||||||
|
int index_mode; /* 0: offset, 1: pre-indexed, 2: post-indexed */
|
||||||
|
int offset_mode; /* 0: immediate, 1: (scaled) register */
|
||||||
|
union {
|
||||||
|
uint32_t offset;
|
||||||
|
struct {
|
||||||
|
uint8_t Rm;
|
||||||
|
uint8_t shift; /* 0: LSL, 1: LSR, 2: ASR, 3: ROR, 4: RRX */
|
||||||
|
uint8_t shift_imm;
|
||||||
|
} reg;
|
||||||
|
} offset;
|
||||||
|
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t value;
|
||||||
|
uint8_t width;
|
||||||
|
void evaluate(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arm_load_store_multiple_instr {
|
||||||
|
uint8_t Rn;
|
||||||
|
uint32_t register_list;
|
||||||
|
uint8_t addressing_mode; /* 0: IA, 1: IB, 2: DA, 3: DB */
|
||||||
|
uint8_t S;
|
||||||
|
uint8_t W;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arm_instruction {
|
||||||
|
enum arm_instruction_type type;
|
||||||
|
char text[128];
|
||||||
|
uint32_t opcode;
|
||||||
|
|
||||||
|
/* return value ... Thumb-2 sizes vary */
|
||||||
|
unsigned instruction_size;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct arm_b_bl_bx_blx_instr b_bl_bx_blx;
|
||||||
|
struct arm_data_proc_instr data_proc;
|
||||||
|
struct arm_load_store_instr load_store;
|
||||||
|
struct arm_load_store_multiple_instr load_store_multiple;
|
||||||
|
} info;
|
||||||
|
|
||||||
|
bool isBranchInstruction(void) const {
|
||||||
|
return (type == ARM_B) || (type == ARM_BL) || (type == ARM_BX) || (type == ARM_BLX);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isLoadInstruction(void) const {
|
||||||
|
return (type >= ARM_LDR) && (type <= ARM_LDM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStoreInstruction(void) const {
|
||||||
|
return (type >= ARM_STR) && (type <= ARM_STM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMemoryAccess(void) const {
|
||||||
|
return isLoadInstruction() || isStoreInstruction();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
|
||||||
|
struct arm_instruction *instruction);
|
||||||
|
int thumb_evaluate_opcode(uint16_t opcode, uint32_t address,
|
||||||
|
struct arm_instruction *instruction);
|
||||||
|
int thumb2_opcode(uint32_t address, uint32_t opcode,
|
||||||
|
struct arm_instruction *instruction);
|
||||||
|
int arm_access_size(struct arm_instruction *instruction);
|
||||||
|
|
||||||
|
#define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000) >> 28])
|
||||||
|
|
||||||
|
#endif /* ARM_DISASSEMBLER_H */
|
||||||
@ -53,7 +53,9 @@ namespace fail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i) {
|
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i) {
|
||||||
os << i.opcode << "\t" << i.instruction << "\t" << i.comment;
|
#ifndef __puma
|
||||||
|
os << std::hex << ((int)(i.address)) << "\t" << i.opcode << "\t" << i.instruction << "\t" << i.comment;
|
||||||
|
#endif
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ namespace fail {
|
|||||||
// Code lines start with a leading whitespace! (hopefully in each objdump implementation!)
|
// Code lines start with a leading whitespace! (hopefully in each objdump implementation!)
|
||||||
if(line.size() > 0 && isspace(line[0])){
|
if(line.size() > 0 && isspace(line[0])){
|
||||||
// a line looks like: 800156c:\tdd14 \tble.n 8001598 <_ZN2hw3hal7T32Term8PutBlockEPci+0x30>
|
// a line looks like: 800156c:\tdd14 \tble.n 8001598 <_ZN2hw3hal7T32Term8PutBlockEPci+0x30>
|
||||||
boost::regex expr("\\s+([A-Fa-f0-9]+):((?:\\s+[A-Fa-f0-9]+)+)\\s+(.+?)(;.*)?$");
|
boost::regex expr("\\s+([A-Fa-f0-9]+):\\t(.*?)\\t(.+?)(;.*)?$");
|
||||||
boost::smatch res;
|
boost::smatch res;
|
||||||
if(boost::regex_search(line, res, expr)){
|
if(boost::regex_search(line, res, expr)){
|
||||||
std::string address = res[1];
|
std::string address = res[1];
|
||||||
@ -71,22 +73,31 @@ namespace fail {
|
|||||||
ss << std::hex << address;
|
ss << std::hex << address;
|
||||||
address_t addr = 0;
|
address_t addr = 0;
|
||||||
ss >> addr;
|
ss >> addr;
|
||||||
|
ss.clear();
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
std::string opcode = res[2];
|
std::string opcode = res[2];
|
||||||
|
// delete trailing/leading whitespaces
|
||||||
boost::trim(opcode);
|
boost::trim(opcode);
|
||||||
|
// delete inner whitespaces and merge nibbles
|
||||||
|
opcode.erase(std::remove(opcode.begin(), opcode.end(), ' '), opcode.end());
|
||||||
|
ss << std::hex << opcode;
|
||||||
|
unsigned opc = 0;
|
||||||
|
ss >> opc;
|
||||||
|
|
||||||
std::string instruction = res[3];
|
std::string instruction = res[3];
|
||||||
boost::trim(instruction);
|
boost::trim(instruction);
|
||||||
std::string comment = res[4];
|
std::string comment = res[4];
|
||||||
boost::trim(comment);
|
boost::trim(comment);
|
||||||
|
|
||||||
m_code.insert(std::make_pair(addr, Instruction(opcode, instruction, comment)));
|
m_code.insert(std::make_pair(addr, Instruction(addr, opc, instruction, comment)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction g_InstructionNotFound;
|
static Instruction g_InstructionNotFound;
|
||||||
|
const Instruction & Disassembler::disassemble(address_t address) const {
|
||||||
const Instruction& Disassembler::disassemble(address_t address){
|
|
||||||
InstructionMap_t::const_iterator it = m_code.find(address);
|
InstructionMap_t::const_iterator it = m_code.find(address);
|
||||||
if(it == m_code.end()){
|
if(it == m_code.end()){
|
||||||
return g_InstructionNotFound;
|
return g_InstructionNotFound;
|
||||||
|
|||||||
@ -19,11 +19,12 @@ namespace fail {
|
|||||||
* @brief An Instruction represents an disassembled opcode
|
* @brief An Instruction represents an disassembled opcode
|
||||||
*/
|
*/
|
||||||
struct Instruction {
|
struct Instruction {
|
||||||
std::string opcode; // TODO convert to integer, size?
|
address_t address; //!< The instruction address
|
||||||
|
regdata_t opcode; //!< The opcode itself
|
||||||
std::string instruction; //!< The disassembled instruction
|
std::string instruction; //!< The disassembled instruction
|
||||||
std::string comment; //!< Comment (rest of line after ; )
|
std::string comment; //!< Comment (rest of line after ; )
|
||||||
Instruction(std::string opcode = "", const std::string& instr = DISASSEMBLER::FAILED, const std::string& comment = "")
|
Instruction(address_t address = ADDR_INV, regdata_t opcode = 0, const std::string& instr = DISASSEMBLER::FAILED, const std::string& comment = "")
|
||||||
: opcode(opcode), instruction(instr), comment(comment) { };
|
: address(address), opcode(opcode), instruction(instr), comment(comment) { };
|
||||||
};
|
};
|
||||||
//<! This allows to print an Instruction via Logger or cout
|
//<! This allows to print an Instruction via Logger or cout
|
||||||
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i);
|
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i);
|
||||||
@ -41,7 +42,16 @@ namespace fail {
|
|||||||
* @param address The instruction address
|
* @param address The instruction address
|
||||||
* @return The according disassembled instruction if found, else DISASSEMBLER:FAILED
|
* @return The according disassembled instruction if found, else DISASSEMBLER:FAILED
|
||||||
*/
|
*/
|
||||||
const Instruction& disassemble(address_t address);
|
const Instruction & disassemble(address_t address) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if there is an instruction at a given address
|
||||||
|
* @param address The address to test
|
||||||
|
* @return true if found, else false
|
||||||
|
*/
|
||||||
|
bool hasInstructionAt(address_t address) const {
|
||||||
|
return m_code.find(address) != m_code.end();;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate new ELF file
|
* Evaluate new ELF file
|
||||||
|
|||||||
@ -216,7 +216,7 @@ const ElfSymbol& ElfReader::getSection( const std::string& name ){
|
|||||||
return g_SymbolNotFound;
|
return g_SymbolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Pretty" Print
|
// "Pretty" Print
|
||||||
void ElfReader::printDemangled(){
|
void ElfReader::printDemangled(){
|
||||||
m_log << "Demangled: " << std::endl;
|
m_log << "Demangled: " << std::endl;
|
||||||
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
||||||
@ -230,7 +230,7 @@ void ElfReader::printDemangled(){
|
|||||||
|
|
||||||
void ElfReader::printMangled(){
|
void ElfReader::printMangled(){
|
||||||
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
||||||
m_log << "0x" << it->getAddress() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl;
|
m_log << "0x" << std::hex << it->getAddress() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ unsigned KESOrefs::injectBitFlip(address_t data_address, unsigned bitpos){
|
|||||||
unsigned value, injectedval;
|
unsigned value, injectedval;
|
||||||
|
|
||||||
mm.getBytes(data_address, 4, (void*)&value);
|
mm.getBytes(data_address, 4, (void*)&value);
|
||||||
injectedval = value ^ bitpos;
|
injectedval = value ^ (1<<bitpos);
|
||||||
mm.setBytes(data_address, 4, (void*)&injectedval);
|
mm.setBytes(data_address, 4, (void*)&injectedval);
|
||||||
|
|
||||||
m_log << "INJECTION at: 0x" << hex << setw(8) << setfill('0') << data_address;
|
m_log << "INJECTION at: 0x" << hex << setw(8) << setfill('0') << data_address;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ using namespace fail;
|
|||||||
|
|
||||||
bool VEZSExperiment::run()
|
bool VEZSExperiment::run()
|
||||||
{
|
{
|
||||||
MemoryManager& mm = simulator.getMemoryManager();
|
//MemoryManager& mm = simulator.getMemoryManager();
|
||||||
|
|
||||||
//m_elf.printDemangled();
|
//m_elf.printDemangled();
|
||||||
m_log << "STARTING EXPERIMENT" << endl;
|
m_log << "STARTING EXPERIMENT" << endl;
|
||||||
@ -40,17 +40,18 @@ bool VEZSExperiment::run()
|
|||||||
|
|
||||||
address_t pfoo = m_elf.getSymbol("foo").getAddress();
|
address_t pfoo = m_elf.getSymbol("foo").getAddress();
|
||||||
//BPSingleListener bp(address);
|
//BPSingleListener bp(address);
|
||||||
BPRangeListener bp(address-32, address + 32);
|
//BPRangeListener bp(address-32, address + 32);
|
||||||
MemWriteListener l_foo( pfoo );
|
//MemWriteListener l_foo( pfoo );
|
||||||
simulator.addListener(&l_foo);
|
MemAccessListener l_foo( 0x20002018 ); l_foo.setWatchWidth(0x20);
|
||||||
reg = simulator.getCPU(0).getRegister(RI_R4);
|
reg = simulator.getCPU(0).getRegister(RI_R4);
|
||||||
|
|
||||||
unsigned foo = 23;
|
unsigned foo = 23;
|
||||||
for(int i = 0; i < 15; i++){
|
for(int i = 0; i < 15; i++){
|
||||||
simulator.addListenerAndResume(&bp);
|
simulator.addListenerAndResume(&l_foo);
|
||||||
if(i == 0) mm.setBytes(pfoo, 4, (void*)&foo);
|
//if(i == 0) mm.setBytes(pfoo, 4, (void*)&foo);
|
||||||
m_log << " Breakpoint hit! @ 0x" << std::hex << simulator.getCPU(0).getInstructionPointer() << std::endl;
|
m_log << " Breakpoint hit! @ 0x" << std::hex << simulator.getCPU(0).getInstructionPointer() << std::endl;
|
||||||
m_log << " Register R3: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
//m_log << " Register R3: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||||
mm.getBytes(pfoo, 4, (void*)&foo);
|
//mm.getBytes(pfoo, 4, (void*)&foo);
|
||||||
m_log << " foo @ 0x"<< std::hex << pfoo << " = " << foo << std::endl;
|
m_log << " foo @ 0x"<< std::hex << pfoo << " = " << foo << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user