Additionally passing the current Bochs CPU context and instruction cache entry to BochsController (enables detailed instruction analysis and modification)
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1361 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -1841,19 +1841,19 @@
|
|||||||
</dia:object>
|
</dia:object>
|
||||||
<dia:object type="UML - Class" version="0" id="O1">
|
<dia:object type="UML - Class" version="0" id="O1">
|
||||||
<dia:attribute name="obj_pos">
|
<dia:attribute name="obj_pos">
|
||||||
<dia:point val="20.3,55.05"/>
|
<dia:point val="13.75,58.55"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="obj_bb">
|
<dia:attribute name="obj_bb">
|
||||||
<dia:rectangle val="20.25,55;43.565,73.7"/>
|
<dia:rectangle val="13.7,58.5;44.33,83.6"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="elem_corner">
|
<dia:attribute name="elem_corner">
|
||||||
<dia:point val="20.3,55.05"/>
|
<dia:point val="13.75,58.55"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="elem_width">
|
<dia:attribute name="elem_width">
|
||||||
<dia:real val="23.215"/>
|
<dia:real val="30.530000000000001"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="elem_height">
|
<dia:attribute name="elem_height">
|
||||||
<dia:real val="18.600000000000005"/>
|
<dia:real val="25.000000000000007"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="name">
|
<dia:attribute name="name">
|
||||||
<dia:string>#BochsController#</dia:string>
|
<dia:string>#BochsController#</dia:string>
|
||||||
@ -2035,6 +2035,52 @@
|
|||||||
<dia:boolean val="false"/>
|
<dia:boolean val="false"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
</dia:composite>
|
</dia:composite>
|
||||||
|
<dia:composite type="umlattribute">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#m_CPUContext#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#BX_CPU_C*#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="visibility">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="abstract">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="class_scope">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umlattribute">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#m_CacheEntry#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#bxICacheEntry_c*#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="visibility">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="abstract">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="class_scope">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="operations">
|
<dia:attribute name="operations">
|
||||||
<dia:composite type="umloperation">
|
<dia:composite type="umloperation">
|
||||||
@ -2239,6 +2285,57 @@
|
|||||||
<dia:enum val="1"/>
|
<dia:enum val="1"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
</dia:composite>
|
</dia:composite>
|
||||||
|
<dia:composite type="umlparameter">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#address_space#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#address_t#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="kind">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umlparameter">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#context#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#BX_CPU_C*#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="kind">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umlparameter">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#cache_entry#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#bxICacheEntry_c*#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="kind">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
</dia:composite>
|
</dia:composite>
|
||||||
<dia:composite type="umloperation">
|
<dia:composite type="umloperation">
|
||||||
@ -2732,6 +2829,148 @@
|
|||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="parameters"/>
|
<dia:attribute name="parameters"/>
|
||||||
</dia:composite>
|
</dia:composite>
|
||||||
|
<dia:composite type="umloperation">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#onIOPortEvent#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="stereotype">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#void#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="visibility">
|
||||||
|
<dia:enum val="0"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="abstract">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="inheritance_type">
|
||||||
|
<dia:enum val="2"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="query">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="class_scope">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="parameters">
|
||||||
|
<dia:composite type="umlparameter">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#data#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#unsigned char#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="kind">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umlparameter">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#port#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#unsigned#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="kind">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umlparameter">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#out#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#bool#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="value">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="kind">
|
||||||
|
<dia:enum val="1"/>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
</dia:attribute>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umloperation">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#getICacheEntry#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="stereotype">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#bxICacheEntry_c*#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="visibility">
|
||||||
|
<dia:enum val="0"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="abstract">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="inheritance_type">
|
||||||
|
<dia:enum val="2"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="query">
|
||||||
|
<dia:boolean val="true"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="class_scope">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="parameters"/>
|
||||||
|
</dia:composite>
|
||||||
|
<dia:composite type="umloperation">
|
||||||
|
<dia:attribute name="name">
|
||||||
|
<dia:string>#getCPUContext#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="stereotype">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="type">
|
||||||
|
<dia:string>#BX_CPU_C*#</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="visibility">
|
||||||
|
<dia:enum val="0"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="comment">
|
||||||
|
<dia:string>##</dia:string>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="abstract">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="inheritance_type">
|
||||||
|
<dia:enum val="2"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="query">
|
||||||
|
<dia:boolean val="true"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="class_scope">
|
||||||
|
<dia:boolean val="false"/>
|
||||||
|
</dia:attribute>
|
||||||
|
<dia:attribute name="parameters"/>
|
||||||
|
</dia:composite>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="template">
|
<dia:attribute name="template">
|
||||||
<dia:boolean val="false"/>
|
<dia:boolean val="false"/>
|
||||||
@ -2743,16 +2982,16 @@
|
|||||||
<dia:point val="32.55,48.5503"/>
|
<dia:point val="32.55,48.5503"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="obj_bb">
|
<dia:attribute name="obj_bb">
|
||||||
<dia:rectangle val="31.7,48.5003;33.4,55.0497"/>
|
<dia:rectangle val="28.965,48.5003;33.4,58.5496"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="meta">
|
<dia:attribute name="meta">
|
||||||
<dia:composite type="dict"/>
|
<dia:composite type="dict"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="orth_points">
|
<dia:attribute name="orth_points">
|
||||||
<dia:point val="32.55,48.5503"/>
|
<dia:point val="32.55,48.5503"/>
|
||||||
<dia:point val="32.55,52.175"/>
|
<dia:point val="32.55,53.9249"/>
|
||||||
<dia:point val="31.9075,52.175"/>
|
<dia:point val="29.015,53.9249"/>
|
||||||
<dia:point val="31.9075,54.9997"/>
|
<dia:point val="29.015,58.4996"/>
|
||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:attribute name="orth_orient">
|
<dia:attribute name="orth_orient">
|
||||||
<dia:enum val="1"/>
|
<dia:enum val="1"/>
|
||||||
@ -2776,7 +3015,7 @@
|
|||||||
</dia:attribute>
|
</dia:attribute>
|
||||||
<dia:connections>
|
<dia:connections>
|
||||||
<dia:connection handle="0" to="O0" connection="88"/>
|
<dia:connection handle="0" to="O0" connection="88"/>
|
||||||
<dia:connection handle="1" to="O1" connection="48"/>
|
<dia:connection handle="1" to="O1" connection="58"/>
|
||||||
</dia:connections>
|
</dia:connections>
|
||||||
</dia:object>
|
</dia:object>
|
||||||
<dia:object type="UML - Class" version="0" id="O3">
|
<dia:object type="UML - Class" version="0" id="O3">
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 761 KiB After Width: | Height: | Size: 783 KiB |
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
// Just a dummy function to define a join-point. This function is
|
// Just a dummy function to define a join-point. This function is
|
||||||
// *just* called once within bx_cpu_c::cpu_loop(...).
|
// *just* called once within bx_cpu_c::cpu_loop(...).
|
||||||
static inline void defineCPULoopJoinPoint(BX_CPU_C* pThis)
|
static inline void defineCPULoopJoinPoint(BX_CPU_C* pThis, bxICacheEntry_c *pEntry)
|
||||||
{
|
{
|
||||||
/* nothing to do here */
|
/* nothing to do here */
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ void BX_CPU_C::cpu_loop(Bit32u max_instr_count)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defineCPULoopJoinPoint(BX_CPU_THIS);
|
defineCPULoopJoinPoint(BX_CPU_THIS, entry);
|
||||||
|
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
// instruction decoding completed -> continue with execution
|
// instruction decoding completed -> continue with execution
|
||||||
|
|||||||
@ -19,7 +19,8 @@ bx_bool interrupt_injection_request = false;
|
|||||||
int interrupt_to_fire = -1;
|
int interrupt_to_fire = -1;
|
||||||
|
|
||||||
BochsController::BochsController()
|
BochsController::BochsController()
|
||||||
: SimulatorController(new BochsRegisterManager(), new BochsMemoryManager())
|
: SimulatorController(new BochsRegisterManager(), new BochsMemoryManager()),
|
||||||
|
m_CPUContext(NULL), m_CacheEntry(NULL)
|
||||||
{
|
{
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Add the general purpose register:
|
// Add the general purpose register:
|
||||||
@ -89,12 +90,15 @@ void BochsController::dbgEnableInstrPtrOutput(unsigned regularity, std::ostream*
|
|||||||
}
|
}
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
void BochsController::onInstrPtrChanged(address_t instrPtr, address_t address_space)
|
void BochsController::onInstrPtrChanged(address_t instrPtr, address_t address_space,
|
||||||
|
BX_CPU_C *context, bxICacheEntry_c *cache_entry)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(m_Regularity != 0 && ++m_Counter % m_Regularity == 0)
|
if(m_Regularity != 0 && ++m_Counter % m_Regularity == 0)
|
||||||
(*m_pDest) << "0x" << std::hex << instrPtr;
|
(*m_pDest) << "0x" << std::hex << instrPtr;
|
||||||
#endif
|
#endif
|
||||||
|
m_CPUContext = context;
|
||||||
|
m_CacheEntry = cache_entry;
|
||||||
bool do_fire = false;
|
bool do_fire = false;
|
||||||
// Check for active breakpoint-events:
|
// Check for active breakpoint-events:
|
||||||
bp_cache_t &buffer_cache = m_EvList.getBPBuffer();
|
bp_cache_t &buffer_cache = m_EvList.getBPBuffer();
|
||||||
@ -117,31 +121,6 @@ void BochsController::onInstrPtrChanged(address_t instrPtr, address_t address_sp
|
|||||||
m_EvList.fireActiveEvents();
|
m_EvList.fireActiveEvents();
|
||||||
// Note: SimulatorController::onBreakpointEvent will not be invoked in this
|
// Note: SimulatorController::onBreakpointEvent will not be invoked in this
|
||||||
// implementation.
|
// implementation.
|
||||||
#if 0
|
|
||||||
//deprecated - this code is ugly
|
|
||||||
bool do_fire = false;
|
|
||||||
int i = 0;
|
|
||||||
BufferCache<BPEvent*> *buffer_cache = m_EvList.getBPBuffer();
|
|
||||||
while(i < buffer_cache->getCount()) {
|
|
||||||
BPEvent *pEvBreakpt = buffer_cache->get(i);
|
|
||||||
if(pEvBreakpt->isMatching(instrPtr, address_space)) {
|
|
||||||
pEvBreakpt->setTriggerInstructionPointer(instrPtr);
|
|
||||||
|
|
||||||
i = buffer_cache->makeActive(m_EvList, i);
|
|
||||||
assert(i >= 0 &&
|
|
||||||
"FATAL ERROR: Could not erase BPEvent from cache");
|
|
||||||
|
|
||||||
// we now know we need to fire the active events - usually we do not have to
|
|
||||||
do_fire = true;
|
|
||||||
// "i" has already been set to the next element (by calling
|
|
||||||
// makeActive()):
|
|
||||||
continue; // -> skip loop increment
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if(do_fire)
|
|
||||||
m_EvList.fireActiveEvents();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BochsController::onIOPortEvent(unsigned char data, unsigned port, bool out) {
|
void BochsController::onIOPortEvent(unsigned char data, unsigned port, bool out) {
|
||||||
@ -300,11 +279,13 @@ void BochsController::onEventTrigger(BaseEvent* pev)
|
|||||||
const std::string& BochsController::getMnemonic() const
|
const std::string& BochsController::getMnemonic() const
|
||||||
{
|
{
|
||||||
static std::string str;
|
static std::string str;
|
||||||
|
#if 0
|
||||||
bxICacheEntry_c* pEntry = BX_CPU(0)->getICacheEntry();
|
bxICacheEntry_c* pEntry = BX_CPU(0)->getICacheEntry();
|
||||||
assert(pEntry != NULL && "FATAL ERROR: Bochs internal function returned NULL (not expected)!");
|
assert(pEntry != NULL && "FATAL ERROR: Bochs internal function returned NULL (not expected)!");
|
||||||
bxInstruction_c* pInstr = pEntry->i;
|
bxInstruction_c* pInstr = pEntry->i;
|
||||||
assert(pInstr != NULL && "FATAL ERROR: Bochs internal member was NULL (not expected)!");
|
assert(pInstr != NULL && "FATAL ERROR: Bochs internal member was NULL (not expected)!");
|
||||||
const char* pszName = get_bx_opcode_name(pInstr->getIaOpcode());
|
#endif
|
||||||
|
const char* pszName = get_bx_opcode_name(getICacheEntry()->i->getIaOpcode());
|
||||||
if (pszName != NULL)
|
if (pszName != NULL)
|
||||||
str = pszName;
|
str = pszName;
|
||||||
else
|
else
|
||||||
|
|||||||
@ -81,7 +81,7 @@ public:
|
|||||||
* @param instrPtr the new instruction pointer
|
* @param instrPtr the new instruction pointer
|
||||||
* @param address_space the address space the CPU is currently in
|
* @param address_space the address space the CPU is currently in
|
||||||
*/
|
*/
|
||||||
void onInstrPtrChanged(address_t instrPtr, address_t address_space);
|
void onInstrPtrChanged(address_t instrPtr, address_t address_space, BX_CPU_C *context, bxICacheEntry_c *cache_entry);
|
||||||
/**
|
/**
|
||||||
* I/O port communication handler. This method is called (from
|
* I/O port communication handler. This method is called (from
|
||||||
* the IOPortCom aspect) every time when Bochs performs a port I/O operation.
|
* the IOPortCom aspect) every time when Bochs performs a port I/O operation.
|
||||||
@ -174,6 +174,19 @@ public:
|
|||||||
* the returned string is empty
|
* the returned string is empty
|
||||||
*/
|
*/
|
||||||
const std::string& getMnemonic() const;
|
const std::string& getMnemonic() const;
|
||||||
|
/**
|
||||||
|
* Retrieves the current Bochs instruction cache entry
|
||||||
|
* @returns a pointer to a bxICacheEntry_c object
|
||||||
|
*/
|
||||||
|
inline bxICacheEntry_c *getICacheEntry() const { return m_CacheEntry; }
|
||||||
|
/**
|
||||||
|
* Retrieves the current CPU context
|
||||||
|
* @return a pointer to a BX_CPU_C object
|
||||||
|
*/
|
||||||
|
inline BX_CPU_C *getCPUContext() const { return m_CPUContext; }
|
||||||
|
private:
|
||||||
|
BX_CPU_C *m_CPUContext;
|
||||||
|
bxICacheEntry_c *m_CacheEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -19,10 +19,10 @@ aspect Breakpoints {
|
|||||||
// BX_CPU(0) otherwise
|
// BX_CPU(0) otherwise
|
||||||
BX_CPU_C* pThis = *(tjp->arg<0>());
|
BX_CPU_C* pThis = *(tjp->arg<0>());
|
||||||
// Points to the *current* bxInstruction-object
|
// Points to the *current* bxInstruction-object
|
||||||
//bxInstruction_c* pInstr = *(tjp->arg<1>());
|
bxICacheEntry_c* pEntry = *(tjp->arg<1>());
|
||||||
|
|
||||||
// report this event to the Bochs controller:
|
// report this event to the Bochs controller:
|
||||||
fail::simulator.onInstrPtrChanged(pThis->get_instruction_pointer(), pThis->cr3);
|
fail::simulator.onInstrPtrChanged(pThis->get_instruction_pointer(), pThis->cr3, pThis, pEntry);
|
||||||
// Note: get_bx_opcode_name(pInstr->getIaOpcode()) retrieves the mnemonics.
|
// Note: get_bx_opcode_name(pInstr->getIaOpcode()) retrieves the mnemonics.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,9 +11,24 @@ using namespace std;
|
|||||||
using namespace fail;
|
using namespace fail;
|
||||||
|
|
||||||
char const * const results_csv = "l4sys.csv";
|
char const * const results_csv = "l4sys.csv";
|
||||||
|
const char *l4sys_output_strings[] = { "Unknown", "Done", "Timeout", "Trap", "Interrupt", "Wrong output", "Error" };
|
||||||
|
|
||||||
bool L4SysCampaign::run()
|
std::string L4SysCampaign::output_result(L4SysProtoMsg_ResultType res) {
|
||||||
{
|
#define OUTPUT_CASE(OUTPUT) case L4SysProtoMsg::OUTPUT: return l4sys_output_strings[L4SysProtoMsg::OUTPUT];
|
||||||
|
switch (res) {
|
||||||
|
OUTPUT_CASE(DONE);
|
||||||
|
OUTPUT_CASE(TIMEOUT);
|
||||||
|
OUTPUT_CASE(TRAP);
|
||||||
|
OUTPUT_CASE(INTR);
|
||||||
|
OUTPUT_CASE(WRONG);
|
||||||
|
OUTPUT_CASE(UNKNOWN);
|
||||||
|
default:
|
||||||
|
return l4sys_output_strings[0];
|
||||||
|
}
|
||||||
|
#undef OUTPUT_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
bool L4SysCampaign::run() {
|
||||||
Logger log("L4SysCampaign");
|
Logger log("L4SysCampaign");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -32,17 +47,17 @@ bool L4SysCampaign::run()
|
|||||||
log << "startup" << endl;
|
log << "startup" << endl;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
//iterate over one register
|
srand(time(NULL));
|
||||||
for (int bit_offset = 0; bit_offset < 1; ++bit_offset) {
|
for (int i = 0; i < 3000; ++i) {
|
||||||
for (int instr_offset = 0; instr_offset < L4SYS_NUMINSTR; ++instr_offset) {
|
L4SysExperimentData *d = new L4SysExperimentData;
|
||||||
L4SysExperimentData *d = new L4SysExperimentData;
|
d->msg.set_exp_type(d->msg.IDCFLIP);
|
||||||
d->msg.set_instr_offset(instr_offset);
|
d->msg.set_instr_offset(rand() % L4SYS_NUMINSTR);
|
||||||
d->msg.set_bit_offset(bit_offset);
|
// 15 bytes (120 bits) are the longest instruction Bochs still executes
|
||||||
d->msg.set_bit_offset(0);
|
int bit_offset = rand() % 120;
|
||||||
|
d->msg.set_bit_offset(bit_offset);
|
||||||
campaignmanager.addParam(d);
|
|
||||||
++count;
|
campaignmanager.addParam(d);
|
||||||
}
|
++count;
|
||||||
}
|
}
|
||||||
campaignmanager.noMoreParameters();
|
campaignmanager.noMoreParameters();
|
||||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||||
@ -50,19 +65,19 @@ bool L4SysCampaign::run()
|
|||||||
// collect results
|
// collect results
|
||||||
L4SysExperimentData *res;
|
L4SysExperimentData *res;
|
||||||
int rescount = 0;
|
int rescount = 0;
|
||||||
results << "injection_ip,instr_offset,injection_bit,resulttype,resultdata,output,details" << endl;
|
results
|
||||||
|
<< "injection_ip,instr_offset,injection_bit,resulttype,resultdata,output,details"
|
||||||
|
<< endl;
|
||||||
while ((res = static_cast<L4SysExperimentData *>(campaignmanager.getDone()))) {
|
while ((res = static_cast<L4SysExperimentData *>(campaignmanager.getDone()))) {
|
||||||
rescount++;
|
rescount++;
|
||||||
|
|
||||||
results << hex
|
results << hex << res->msg.injection_ip() << "," << dec
|
||||||
<< res->msg.injection_ip() << ","
|
<< res->msg.instr_offset() << "," << res->msg.bit_offset()
|
||||||
<< dec << res->msg.instr_offset() << ","
|
<< "," << output_result(res->msg.resulttype()) << ","
|
||||||
<< res->msg.bit_offset() << ","
|
<< res->msg.resultdata();
|
||||||
<< res->msg.resulttype() << ","
|
if (res->msg.has_output())
|
||||||
<< res->msg.resultdata();
|
|
||||||
if(res->msg.has_output())
|
|
||||||
results << "," << res->msg.output();
|
results << "," << res->msg.output();
|
||||||
if(res->msg.has_details())
|
if (res->msg.has_details())
|
||||||
results << "," << res->msg.details();
|
results << "," << res->msg.details();
|
||||||
results << endl;
|
results << endl;
|
||||||
delete res;
|
delete res;
|
||||||
|
|||||||
@ -14,6 +14,8 @@ public:
|
|||||||
class L4SysCampaign : public fail::Campaign {
|
class L4SysCampaign : public fail::Campaign {
|
||||||
public:
|
public:
|
||||||
virtual bool run();
|
virtual bool run();
|
||||||
|
private:
|
||||||
|
std::string output_result(L4SysProtoMsg_ResultType res);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __L4SYS_CAMPAIGN_HPP__
|
#endif // __L4SYS_CAMPAIGN_HPP__
|
||||||
|
|||||||
@ -3,13 +3,11 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "util/Logger.hpp"
|
|
||||||
|
|
||||||
#include "experiment.hpp"
|
#include "experiment.hpp"
|
||||||
#include "experimentInfo.hpp"
|
#include "experimentInfo.hpp"
|
||||||
#include "campaign.hpp"
|
|
||||||
|
|
||||||
#include "sal/SALConfig.hpp"
|
#include "sal/SALConfig.hpp"
|
||||||
#include "sal/SALInst.hpp"
|
#include "sal/SALInst.hpp"
|
||||||
@ -33,43 +31,31 @@ using namespace fail;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct __trace_instr_type {
|
typedef struct __trace_instr_type {
|
||||||
address_t trigger_addr;
|
fail::address_t trigger_addr;
|
||||||
unsigned bp_counter;
|
unsigned bp_counter;
|
||||||
} trace_instr;
|
} trace_instr;
|
||||||
|
|
||||||
ostream& operator<<(ostream& out, const trace_instr &val) {
|
|
||||||
out << val.trigger_addr << "," << val.bp_counter;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
istream& operator>>(istream& in, trace_instr &val) {
|
|
||||||
in >> val.trigger_addr;
|
|
||||||
//skip the comma
|
|
||||||
in.ignore(1);
|
|
||||||
in >> val.bp_counter;
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const * const state_folder = "l4sys.state";
|
|
||||||
char const * const instr_list_fn = "ip.list";
|
|
||||||
char const * const golden_run_fn = "golden.out";
|
|
||||||
address_t const aspace = 0x01e00000;
|
|
||||||
string output;
|
string output;
|
||||||
|
#if 0
|
||||||
|
//disabled (see "STEP 2" below)
|
||||||
vector<trace_instr> instr_list;
|
vector<trace_instr> instr_list;
|
||||||
|
vector<trace_instr> alu_instr_list;
|
||||||
|
#endif
|
||||||
string golden_run;
|
string golden_run;
|
||||||
//the program needs to run 5 times without a fault
|
|
||||||
const unsigned times_run = 5;
|
|
||||||
|
|
||||||
string L4SysExperiment::sanitised(string in_str) {
|
string L4SysExperiment::sanitised(const string &in_str) {
|
||||||
string result;
|
string result;
|
||||||
result.reserve(in_str.size());
|
int in_str_size = in_str.size();
|
||||||
for (string::iterator it = in_str.begin(); it != in_str.end(); it++) {
|
result.reserve(in_str_size);
|
||||||
unsigned char_value = static_cast<unsigned>(*it);
|
for (int idx = 0; idx < in_str_size; idx++) {
|
||||||
if (char_value < 0x20 || char_value > 0x7E) {
|
char cur_char = in_str[idx];
|
||||||
|
unsigned cur_char_value = static_cast<unsigned>(cur_char);
|
||||||
|
if (cur_char_value < 0x20 || cur_char_value > 0x7E) {
|
||||||
char str_nr[5];
|
char str_nr[5];
|
||||||
sprintf(str_nr, "\\%03o", char_value);
|
sprintf(str_nr, "\\%03o", cur_char_value);
|
||||||
result += str_nr;
|
result += str_nr;
|
||||||
} else {
|
} else {
|
||||||
result += *it;
|
result += cur_char;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -93,15 +79,119 @@ BaseEvent* L4SysExperiment::waitIOOrOther(bool clear_output) {
|
|||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bit32u L4SysExperiment::eipBiased() {
|
||||||
|
BX_CPU_C *cpu_context = simulator.getCPUContext();
|
||||||
|
Bit32u EIP = cpu_context->gen_reg[BX_32BIT_REG_EIP].dword.erx;
|
||||||
|
return EIP + cpu_context->eipPageBias;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Bit8u *L4SysExperiment::calculateInstructionAddress() {
|
||||||
|
// pasted in from various nested Bochs functions and macros - I hope
|
||||||
|
// they will not change too soon (as do the Bochs developers, probably)
|
||||||
|
BX_CPU_C *cpu_context = simulator.getCPUContext();
|
||||||
|
const Bit8u *result = cpu_context->eipFetchPtr + eipBiased();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bx_bool L4SysExperiment::fetchInstruction(BX_CPU_C *instance, const Bit8u *instr, bxInstruction_c *iStorage)
|
||||||
|
{
|
||||||
|
unsigned remainingInPage = instance->eipPageWindowSize - eipBiased();
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#if BX_SUPPORT_X86_64
|
||||||
|
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
|
||||||
|
ret = instance->fetchDecode64(instr, iStorage, remainingInPage);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ret = instance->fetchDecode32(instr, iStorage, remainingInPage);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
// handle instrumentation callback inside boundaryFetch
|
||||||
|
instance->boundaryFetch(instr, remainingInPage, iStorage);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void L4SysExperiment::logInjection(Logger &log, const L4SysExperimentData ¶m) {
|
||||||
|
// explicit type assignment necessary before sending over output stream
|
||||||
|
int id = param.getWorkloadID();
|
||||||
|
int instr_offset = param.msg.instr_offset();
|
||||||
|
int bit_offset = param.msg.bit_offset();
|
||||||
|
int exp_type = param.msg.exp_type();
|
||||||
|
address_t injection_ip = param.msg.injection_ip();
|
||||||
|
|
||||||
|
log << "job " << id << " exp_type " << exp_type << endl;
|
||||||
|
log << "inject @ ip " << injection_ip << " (offset " << dec
|
||||||
|
<< instr_offset << ")" << " bit " << bit_offset << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool L4SysExperiment::isALUInstruction(unsigned opcode) {
|
||||||
|
switch(opcode) {
|
||||||
|
case BX_IA_INC_Eb: case BX_IA_INC_Ew: case BX_IA_INC_Ed: case BX_IA_INC_RX: case BX_IA_INC_ERX:
|
||||||
|
case BX_IA_DEC_Eb: case BX_IA_DEC_Ew: case BX_IA_DEC_Ed: case BX_IA_DEC_RX: case BX_IA_DEC_ERX:
|
||||||
|
case BX_IA_ADC_EbGb: case BX_IA_ADC_EdGd: case BX_IA_ADC_EwGw: case BX_IA_ADD_EbGb: case BX_IA_ADD_EdGd:
|
||||||
|
case BX_IA_ADD_EwGw: case BX_IA_AND_EbGb: case BX_IA_AND_EdGd: case BX_IA_AND_EwGw: case BX_IA_CMP_EbGb:
|
||||||
|
case BX_IA_CMP_EdGd: case BX_IA_CMP_EwGw: case BX_IA_OR_EbGb: case BX_IA_OR_EdGd: case BX_IA_OR_EwGw:
|
||||||
|
case BX_IA_SBB_EbGb: case BX_IA_SBB_EdGd: case BX_IA_SBB_EwGw: case BX_IA_SUB_EbGb: case BX_IA_SUB_EdGd:
|
||||||
|
case BX_IA_SUB_EwGw: case BX_IA_XOR_EbGb: case BX_IA_XOR_EdGd: case BX_IA_XOR_EwGw: case BX_IA_ADC_ALIb:
|
||||||
|
case BX_IA_ADC_AXIw: case BX_IA_ADC_EAXId: case BX_IA_ADD_EbIb: case BX_IA_OR_EbIb: case BX_IA_ADC_EbIb:
|
||||||
|
case BX_IA_SBB_EbIb: case BX_IA_AND_EbIb: case BX_IA_SUB_EbIb: case BX_IA_XOR_EbIb: case BX_IA_CMP_EbIb:
|
||||||
|
case BX_IA_ADD_EwIw: case BX_IA_OR_EwIw: case BX_IA_ADC_EwIw: case BX_IA_SBB_EwIw: case BX_IA_AND_EwIw:
|
||||||
|
case BX_IA_SUB_EwIw: case BX_IA_XOR_EwIw: case BX_IA_CMP_EwIw: case BX_IA_ADD_EdId: case BX_IA_OR_EdId:
|
||||||
|
case BX_IA_ADC_EdId: case BX_IA_SBB_EdId: case BX_IA_AND_EdId: case BX_IA_SUB_EdId: case BX_IA_XOR_EdId:
|
||||||
|
case BX_IA_CMP_EdId: case BX_IA_ADC_GbEb: case BX_IA_ADC_GwEw: case BX_IA_ADC_GdEd: case BX_IA_ADD_ALIb:
|
||||||
|
case BX_IA_ADD_AXIw: case BX_IA_ADD_EAXId: case BX_IA_ADD_GbEb: case BX_IA_ADD_GwEw: case BX_IA_ADD_GdEd:
|
||||||
|
case BX_IA_AND_ALIb: case BX_IA_AND_AXIw: case BX_IA_AND_EAXId: case BX_IA_AND_GbEb: case BX_IA_AND_GwEw:
|
||||||
|
case BX_IA_AND_GdEd: case BX_IA_ROL_Eb: case BX_IA_ROR_Eb: case BX_IA_RCL_Eb: case BX_IA_RCR_Eb:
|
||||||
|
case BX_IA_SHL_Eb: case BX_IA_SHR_Eb: case BX_IA_SAR_Eb: case BX_IA_ROL_Ew: case BX_IA_ROR_Ew:
|
||||||
|
case BX_IA_RCL_Ew: case BX_IA_RCR_Ew: case BX_IA_SHL_Ew: case BX_IA_SHR_Ew: case BX_IA_SAR_Ew:
|
||||||
|
case BX_IA_ROL_Ed: case BX_IA_ROR_Ed: case BX_IA_RCL_Ed: case BX_IA_RCR_Ed: case BX_IA_SHL_Ed:
|
||||||
|
case BX_IA_SHR_Ed: case BX_IA_SAR_Ed: case BX_IA_NOT_Eb: case BX_IA_NEG_Eb: case BX_IA_NOT_Ew:
|
||||||
|
case BX_IA_NEG_Ew: case BX_IA_NOT_Ed: case BX_IA_NEG_Ed:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void L4SysExperiment::readFromFileToVector(std::ifstream &file, std::vector<trace_instr> &instr_list)
|
||||||
|
{
|
||||||
|
file >> hex;
|
||||||
|
while (!file.eof()) {
|
||||||
|
trace_instr curr_instr;
|
||||||
|
file.read(reinterpret_cast<char*>(&curr_instr), sizeof(trace_instr));
|
||||||
|
instr_list.push_back(curr_instr);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void L4SysExperiment::changeBochsInstruction(bxInstruction_c *dest, bxInstruction_c *src) {
|
||||||
|
// backup the current and insert the faulty instruction
|
||||||
|
bxInstruction_c old_instr;
|
||||||
|
memcpy(&old_instr, dest, sizeof(bxInstruction_c));
|
||||||
|
memcpy(dest, src, sizeof(bxInstruction_c));
|
||||||
|
|
||||||
|
// execute the faulty instruction, then return
|
||||||
|
BPSingleEvent singlestepping_event(ANY_ADDR, L4SYS_ADDRESS_SPACE);
|
||||||
|
simulator.addEvent(&singlestepping_event);
|
||||||
|
waitIOOrOther(false);
|
||||||
|
simulator.removeEvent(&singlestepping_event);
|
||||||
|
|
||||||
|
//restore the old instruction
|
||||||
|
memcpy(dest, &old_instr, sizeof(bxInstruction_c));
|
||||||
|
}
|
||||||
|
|
||||||
bool L4SysExperiment::run() {
|
bool L4SysExperiment::run() {
|
||||||
Logger log("L4Sys", false);
|
Logger log("L4Sys", false);
|
||||||
BPSingleEvent bp(0, aspace);
|
BPSingleEvent bp(0, L4SYS_ADDRESS_SPACE);
|
||||||
|
|
||||||
log << "startup" << endl;
|
log << "startup" << endl;
|
||||||
|
|
||||||
struct stat teststruct;
|
struct stat teststruct;
|
||||||
// STEP 1: run until interesting function starts, and save state
|
// STEP 1: run until interesting function starts, and save state
|
||||||
if (stat(state_folder, &teststruct) == -1) {
|
if (stat(L4SYS_STATE_FOLDER, &teststruct) == -1) {
|
||||||
bp.setWatchInstructionPointer(L4SYS_FUNC_ENTRY);
|
bp.setWatchInstructionPointer(L4SYS_FUNC_ENTRY);
|
||||||
simulator.addEventAndWait(&bp);
|
simulator.addEventAndWait(&bp);
|
||||||
|
|
||||||
@ -109,13 +199,19 @@ bool L4SysExperiment::run() {
|
|||||||
log << "EIP = " << hex << bp.getTriggerInstructionPointer() << " or "
|
log << "EIP = " << hex << bp.getTriggerInstructionPointer() << " or "
|
||||||
<< simulator.getRegisterManager().getInstructionPointer()
|
<< simulator.getRegisterManager().getInstructionPointer()
|
||||||
<< endl;
|
<< endl;
|
||||||
simulator.save(state_folder);
|
simulator.save(L4SYS_STATE_FOLDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP 2: determine instructions executed
|
// STEP 2: determine instructions executed
|
||||||
if (stat(instr_list_fn, &teststruct) == -1) {
|
#if 0
|
||||||
|
// the files currently get too big.
|
||||||
|
/* I do not really have a clever idea to solve this.
|
||||||
|
* You would probably need some kind of loop detection,
|
||||||
|
* but for the moment, I have to focus on different issues.
|
||||||
|
*/
|
||||||
|
if (stat(L4SYS_INSTRUCTION_LIST, &teststruct) == -1 || stat(L4SYS_ALU_INSTRUCTIONS, &teststruct) == -1) {
|
||||||
log << "restoring state" << endl;
|
log << "restoring state" << endl;
|
||||||
simulator.restore(state_folder);
|
simulator.restore(L4SYS_STATE_FOLDER);
|
||||||
log << "EIP = " << hex
|
log << "EIP = " << hex
|
||||||
<< simulator.getRegisterManager().getInstructionPointer()
|
<< simulator.getRegisterManager().getInstructionPointer()
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -123,8 +219,8 @@ bool L4SysExperiment::run() {
|
|||||||
// make sure the timer interrupt doesn't disturb us
|
// make sure the timer interrupt doesn't disturb us
|
||||||
simulator.addSuppressedInterrupt(32);
|
simulator.addSuppressedInterrupt(32);
|
||||||
|
|
||||||
ofstream instr_list_file(instr_list_fn);
|
ofstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::out | ios::binary);
|
||||||
instr_list_file << hex;
|
ofstream alu_instr_file(L4SYS_ALU_INSTRUCTIONS, ios::out | ios::binary);
|
||||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||||
|
|
||||||
map<address_t, unsigned> times_called_map;
|
map<address_t, unsigned> times_called_map;
|
||||||
@ -144,25 +240,34 @@ bool L4SysExperiment::run() {
|
|||||||
new_instr.bp_counter = times_called;
|
new_instr.bp_counter = times_called;
|
||||||
instr_list.push_back(new_instr);
|
instr_list.push_back(new_instr);
|
||||||
|
|
||||||
instr_list_file << new_instr << endl;
|
instr_list_file.write(reinterpret_cast<char*>(&new_instr), sizeof(trace_instr));
|
||||||
|
|
||||||
|
// ALU instructions
|
||||||
|
|
||||||
|
// decode the instruction
|
||||||
|
bxInstruction_c instr;
|
||||||
|
fetchInstruction(simulator.getCPUContext(), calculateInstructionAddress(), &instr);
|
||||||
|
// add it to a second list if it is an ALU instruction
|
||||||
|
if(isALUInstruction(instr.getIaOpcode())) {
|
||||||
|
alu_instr_list.push_back(new_instr);
|
||||||
|
alu_instr_file.write(reinterpret_cast<char*>(&new_instr), sizeof(trace_instr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log << "saving instructions triggered during normal execution" << endl;
|
log << "saving instructions triggered during normal execution" << endl;
|
||||||
|
alu_instr_file.close();
|
||||||
instr_list_file.close();
|
instr_list_file.close();
|
||||||
} else {
|
} else {
|
||||||
ifstream instr_list_file(instr_list_fn);
|
ifstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::in | ios::binary);
|
||||||
instr_list_file >> hex;
|
ifstream alu_instr_file(L4SYS_ALU_INSTRUCTIONS, ios::in | ios::binary);
|
||||||
while (!instr_list_file.eof()) {
|
readFromFileToVector(instr_list_file, instr_list);
|
||||||
trace_instr curr_instr;
|
readFromFileToVector(alu_instr_file, alu_instr_list);
|
||||||
instr_list_file >> curr_instr;
|
|
||||||
instr_list.push_back(curr_instr);
|
|
||||||
}
|
|
||||||
instr_list_file.close();
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// STEP 3: determine the output of a "golden run"
|
// STEP 3: determine the output of a "golden run"
|
||||||
if (stat(golden_run_fn, &teststruct) == -1) {
|
if (stat(L4SYS_CORRECT_OUTPUT, &teststruct) == -1) {
|
||||||
log << "restoring state" << endl;
|
log << "restoring state" << endl;
|
||||||
simulator.restore(state_folder);
|
simulator.restore(L4SYS_STATE_FOLDER);
|
||||||
log << "EIP = " << hex
|
log << "EIP = " << hex
|
||||||
<< simulator.getRegisterManager().getInstructionPointer()
|
<< simulator.getRegisterManager().getInstructionPointer()
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -170,9 +275,9 @@ bool L4SysExperiment::run() {
|
|||||||
// make sure the timer interrupt doesn't disturb us
|
// make sure the timer interrupt doesn't disturb us
|
||||||
simulator.addSuppressedInterrupt(32);
|
simulator.addSuppressedInterrupt(32);
|
||||||
|
|
||||||
ofstream golden_run_file(golden_run_fn);
|
ofstream golden_run_file(L4SYS_CORRECT_OUTPUT);
|
||||||
bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT);
|
bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT);
|
||||||
bp.setCounter(times_run);
|
bp.setCounter(L4SYS_ITERATION_COUNT);
|
||||||
simulator.addEvent(&bp);
|
simulator.addEvent(&bp);
|
||||||
BaseEvent* ev = waitIOOrOther(true);
|
BaseEvent* ev = waitIOOrOther(true);
|
||||||
if (ev == &bp) {
|
if (ev == &bp) {
|
||||||
@ -191,13 +296,9 @@ bool L4SysExperiment::run() {
|
|||||||
log << "saving output generated during normal execution" << endl;
|
log << "saving output generated during normal execution" << endl;
|
||||||
golden_run_file.close();
|
golden_run_file.close();
|
||||||
} else {
|
} else {
|
||||||
ifstream golden_run_file(golden_run_fn);
|
ifstream golden_run_file(L4SYS_CORRECT_OUTPUT);
|
||||||
|
|
||||||
//shamelessly copied from http://stackoverflow.com/questions/2602013/:
|
golden_run.reserve(teststruct.st_size);
|
||||||
golden_run_file.seekg(0, ios::end);
|
|
||||||
size_t flen = golden_run_file.tellg();
|
|
||||||
golden_run.reserve(flen);
|
|
||||||
golden_run_file.seekg(0, ios::beg);
|
|
||||||
|
|
||||||
golden_run.assign((istreambuf_iterator<char>(golden_run_file)),
|
golden_run.assign((istreambuf_iterator<char>(golden_run_file)),
|
||||||
istreambuf_iterator<char>());
|
istreambuf_iterator<char>());
|
||||||
@ -205,130 +306,177 @@ bool L4SysExperiment::run() {
|
|||||||
golden_run_file.close();
|
golden_run_file.close();
|
||||||
|
|
||||||
//the generated output probably has a similar length
|
//the generated output probably has a similar length
|
||||||
output.reserve(flen);
|
output.reserve(teststruct.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP 4: The actual experiment.
|
// STEP 4: The actual experiment.
|
||||||
while (1) {
|
log << "restoring state" << endl;
|
||||||
log << "restoring state" << endl;
|
simulator.restore(L4SYS_STATE_FOLDER);
|
||||||
simulator.restore(state_folder);
|
|
||||||
|
|
||||||
log << "asking job server for experiment parameters" << endl;
|
log << "asking job server for experiment parameters" << endl;
|
||||||
L4SysExperimentData param;
|
L4SysExperimentData param;
|
||||||
if (!m_jc.getParam(param)) {
|
if (!m_jc.getParam(param)) {
|
||||||
log << "Dying." << endl;
|
log << "Dying." << endl;
|
||||||
// communicate that we were told to die
|
// communicate that we were told to die
|
||||||
simulator.terminate(1);
|
simulator.terminate(1);
|
||||||
}
|
}
|
||||||
int id = param.getWorkloadID();
|
|
||||||
int instr_offset = param.msg.instr_offset();
|
|
||||||
int bit_offset = param.msg.bit_offset();
|
|
||||||
log << "job " << id << " instr " << instr_offset << " bit "
|
|
||||||
<< bit_offset << endl;
|
|
||||||
|
|
||||||
bp.setWatchInstructionPointer(instr_list[instr_offset].trigger_addr);
|
int instr_offset = param.msg.instr_offset();
|
||||||
bp.setCounter(instr_list[instr_offset].bp_counter);
|
int bit_offset = param.msg.bit_offset();
|
||||||
simulator.addEvent(&bp);
|
int exp_type = param.msg.exp_type();
|
||||||
//and log the output
|
|
||||||
waitIOOrOther(true);
|
|
||||||
|
|
||||||
// inject
|
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||||
RegisterManager& rm = simulator.getRegisterManager();
|
bp.setCounter(instr_offset);
|
||||||
Register *ebx = rm.getRegister(RID_CBX);
|
simulator.addEvent(&bp);
|
||||||
regdata_t data = ebx->getData();
|
//and log the output
|
||||||
regdata_t newdata = data ^ (1 << bit_offset);
|
waitIOOrOther(true);
|
||||||
ebx->setData(newdata);
|
|
||||||
// note at what IP we did it
|
|
||||||
address_t injection_ip =
|
|
||||||
simulator.getRegisterManager().getInstructionPointer();
|
|
||||||
param.msg.set_injection_ip(injection_ip);
|
|
||||||
log << "inject @ ip " << injection_ip << " (offset " << dec
|
|
||||||
<< instr_offset << ")" << " bit " << bit_offset << ": 0x" << hex
|
|
||||||
<< ((int) data) << " -> 0x" << ((int) newdata) << endl;
|
|
||||||
|
|
||||||
// sanity check (only works if we're working with an instruction trace)
|
// note at what IP we will do the injection
|
||||||
if (injection_ip != instr_list[instr_offset].trigger_addr) {
|
address_t injection_ip =
|
||||||
stringstream ss;
|
simulator.getRegisterManager().getInstructionPointer();
|
||||||
ss << "SANITY CHECK FAILED: " << injection_ip << " != "
|
param.msg.set_injection_ip(injection_ip);
|
||||||
<< instr_list[instr_offset].trigger_addr << endl;
|
|
||||||
log << ss.str();
|
|
||||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
|
||||||
param.msg.set_resultdata(injection_ip);
|
|
||||||
param.msg.set_details(ss.str());
|
|
||||||
|
|
||||||
simulator.clearEvents();
|
#if 0
|
||||||
m_jc.sendResult(param);
|
// temporarily out of order (see above)
|
||||||
simulator.terminate(20);
|
// sanity check (only works if we're working with an instruction trace)
|
||||||
}
|
if (injection_ip != instr_list[instr_offset].trigger_addr) {
|
||||||
|
stringstream ss;
|
||||||
// aftermath
|
ss << "SANITY CHECK FAILED: " << injection_ip << " != "
|
||||||
BPSingleEvent ev_done(L4SYS_FUNC_EXIT, aspace);
|
<< instr_list[instr_offset].trigger_addr << endl;
|
||||||
ev_done.setCounter(times_run);
|
log << ss.str();
|
||||||
simulator.addEvent(&ev_done);
|
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||||
const unsigned instr_run = times_run * L4SYS_NUMINSTR;
|
param.msg.set_resultdata(injection_ip);
|
||||||
BPSingleEvent ev_timeout(ANY_ADDR, aspace);
|
param.msg.set_details(ss.str());
|
||||||
ev_timeout.setCounter(instr_run + 3000);
|
|
||||||
simulator.addEvent(&ev_timeout);
|
|
||||||
TrapEvent ev_trap(ANY_TRAP);
|
|
||||||
simulator.addEvent(&ev_trap);
|
|
||||||
InterruptEvent ev_intr(ANY_INTERRUPT);
|
|
||||||
//ten times as many interrupts as instructions justify an exception
|
|
||||||
ev_intr.setCounter(instr_run * 10);
|
|
||||||
simulator.addEvent(&ev_intr);
|
|
||||||
|
|
||||||
//do not discard output recorded so far
|
|
||||||
BaseEvent *ev = waitIOOrOther(false);
|
|
||||||
|
|
||||||
/* copying a string object that contains control sequences
|
|
||||||
* unfortunately does not work with the library I am using,
|
|
||||||
* which is why output is passed on as C string and
|
|
||||||
* the string compare is done on C strings
|
|
||||||
*/
|
|
||||||
if (ev == &ev_done) {
|
|
||||||
if (strcmp(output.c_str(), golden_run.c_str()) == 0) {
|
|
||||||
log << dec << "Result DONE" << endl;
|
|
||||||
param.msg.set_resulttype(param.msg.DONE);
|
|
||||||
} else {
|
|
||||||
log << dec << "Result WRONG" << endl;
|
|
||||||
param.msg.set_resulttype(param.msg.WRONG);
|
|
||||||
param.msg.set_output(sanitised(output.c_str()));
|
|
||||||
}
|
|
||||||
} else if (ev == &ev_timeout) {
|
|
||||||
log << dec << "Result TIMEOUT" << endl;
|
|
||||||
param.msg.set_resulttype(param.msg.TIMEOUT);
|
|
||||||
param.msg.set_resultdata(
|
|
||||||
simulator.getRegisterManager().getInstructionPointer());
|
|
||||||
param.msg.set_output(sanitised(output.c_str()));
|
|
||||||
} else if (ev == &ev_trap) {
|
|
||||||
log << dec << "Result TRAP #" << ev_trap.getTriggerNumber() << endl;
|
|
||||||
param.msg.set_resulttype(param.msg.TRAP);
|
|
||||||
param.msg.set_resultdata(
|
|
||||||
simulator.getRegisterManager().getInstructionPointer());
|
|
||||||
param.msg.set_output(sanitised(output.c_str()));
|
|
||||||
} else if (ev == &ev_intr) {
|
|
||||||
log << hex << "Result INT FLOOD; Last INT #:"
|
|
||||||
<< ev_intr.getTriggerNumber() << endl;
|
|
||||||
param.msg.set_resulttype(param.msg.INTR);
|
|
||||||
param.msg.set_resultdata(
|
|
||||||
simulator.getRegisterManager().getInstructionPointer());
|
|
||||||
param.msg.set_output(sanitised(output.c_str()));
|
|
||||||
} else {
|
|
||||||
log << dec << "Result WTF?" << endl;
|
|
||||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
|
||||||
param.msg.set_resultdata(
|
|
||||||
simulator.getRegisterManager().getInstructionPointer());
|
|
||||||
param.msg.set_output(sanitised(output.c_str()));
|
|
||||||
|
|
||||||
stringstream ss;
|
|
||||||
ss << "eventid " << ev << " EIP "
|
|
||||||
<< simulator.getRegisterManager().getInstructionPointer()
|
|
||||||
<< endl;
|
|
||||||
param.msg.set_details(ss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
simulator.clearEvents();
|
simulator.clearEvents();
|
||||||
m_jc.sendResult(param);
|
m_jc.sendResult(param);
|
||||||
|
simulator.terminate(20);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// inject
|
||||||
|
if (exp_type == param.msg.GPRFLIP) {
|
||||||
|
RegisterManager& rm = simulator.getRegisterManager();
|
||||||
|
Register *ebx = rm.getRegister(RID_EBX);
|
||||||
|
regdata_t data = ebx->getData();
|
||||||
|
regdata_t newdata = data ^ (1 << bit_offset);
|
||||||
|
ebx->setData(newdata);
|
||||||
|
|
||||||
|
// do the logging in case everything worked out
|
||||||
|
logInjection(log, param);
|
||||||
|
log << "register data: 0x" << hex
|
||||||
|
<< ((int) data) << " -> 0x" << ((int) newdata) << endl;
|
||||||
|
} else if(exp_type == param.msg.IDCFLIP) {
|
||||||
|
// this is a twisted one
|
||||||
|
|
||||||
|
// initial definitions
|
||||||
|
bxICacheEntry_c *cache_entry = simulator.getICacheEntry();
|
||||||
|
unsigned length_in_bits = cache_entry->i->ilen() << 3;
|
||||||
|
|
||||||
|
// get the instruction in plain text in inject the error there
|
||||||
|
// Note: we need to fetch some extra bytes into the array
|
||||||
|
// in case the faulty instruction is interpreted to be longer
|
||||||
|
// than the original one
|
||||||
|
Bit8u curr_instr_plain[MAX_INSTR_BYTES];
|
||||||
|
const Bit8u *addr = calculateInstructionAddress();
|
||||||
|
memcpy(curr_instr_plain, addr, MAX_INSTR_BYTES);
|
||||||
|
|
||||||
|
// CampaignManager has no idea of the instruction length
|
||||||
|
// (neither do we), therefore this small adaption
|
||||||
|
bit_offset %= length_in_bits;
|
||||||
|
param.msg.set_bit_offset(bit_offset);
|
||||||
|
|
||||||
|
// do some access calculation
|
||||||
|
int byte_index = bit_offset >> 3;
|
||||||
|
Bit8u bit_index = bit_offset & 7;
|
||||||
|
|
||||||
|
// apply the fault
|
||||||
|
curr_instr_plain[byte_index] ^= 1 << bit_index;
|
||||||
|
|
||||||
|
// decode the instruction
|
||||||
|
bxInstruction_c bochs_instr;
|
||||||
|
memset(&bochs_instr, 0, sizeof(bxInstruction_c));
|
||||||
|
fetchInstruction(simulator.getCPUContext(), curr_instr_plain, &bochs_instr);
|
||||||
|
|
||||||
|
// inject it
|
||||||
|
changeBochsInstruction(cache_entry->i, &bochs_instr);
|
||||||
|
|
||||||
|
// do the logging
|
||||||
|
logInjection(log, param);
|
||||||
|
} else if(exp_type == param.msg.RATFLIP) {
|
||||||
|
bxICacheEntry_c *cache_entry = simulator.getICacheEntry();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// aftermath
|
||||||
|
BPSingleEvent ev_done(L4SYS_FUNC_EXIT, L4SYS_ADDRESS_SPACE);
|
||||||
|
ev_done.setCounter(L4SYS_ITERATION_COUNT);
|
||||||
|
simulator.addEvent(&ev_done);
|
||||||
|
const unsigned instr_run = L4SYS_ITERATION_COUNT * L4SYS_NUMINSTR;
|
||||||
|
BPSingleEvent ev_timeout(ANY_ADDR, L4SYS_ADDRESS_SPACE);
|
||||||
|
ev_timeout.setCounter(instr_run + 3000);
|
||||||
|
simulator.addEvent(&ev_timeout);
|
||||||
|
TrapEvent ev_trap(ANY_TRAP);
|
||||||
|
//one trap for each 150 instructions justifies an exception
|
||||||
|
ev_trap.setCounter(instr_run / 150);
|
||||||
|
simulator.addEvent(&ev_trap);
|
||||||
|
InterruptEvent ev_intr(ANY_INTERRUPT);
|
||||||
|
//one interrupt for each 100 instructions justifies an exception (timeout mostly)
|
||||||
|
ev_intr.setCounter(instr_run / 100);
|
||||||
|
simulator.addEvent(&ev_intr);
|
||||||
|
|
||||||
|
//do not discard output recorded so far
|
||||||
|
BaseEvent *ev = waitIOOrOther(false);
|
||||||
|
|
||||||
|
/* copying a string object that contains control sequences
|
||||||
|
* unfortunately does not work with the library I am using,
|
||||||
|
* which is why output is passed on as C string and
|
||||||
|
* the string compare is done on C strings
|
||||||
|
*/
|
||||||
|
if (ev == &ev_done) {
|
||||||
|
if (strcmp(output.c_str(), golden_run.c_str()) == 0) {
|
||||||
|
log << dec << "Result DONE" << endl;
|
||||||
|
param.msg.set_resulttype(param.msg.DONE);
|
||||||
|
} else {
|
||||||
|
log << dec << "Result WRONG" << endl;
|
||||||
|
param.msg.set_resulttype(param.msg.WRONG);
|
||||||
|
param.msg.set_output(sanitised(output.c_str()));
|
||||||
|
}
|
||||||
|
} else if (ev == &ev_timeout) {
|
||||||
|
log << dec << "Result TIMEOUT" << endl;
|
||||||
|
param.msg.set_resulttype(param.msg.TIMEOUT);
|
||||||
|
param.msg.set_resultdata(
|
||||||
|
simulator.getRegisterManager().getInstructionPointer());
|
||||||
|
param.msg.set_output(sanitised(output.c_str()));
|
||||||
|
} else if (ev == &ev_trap) {
|
||||||
|
log << dec << "Result TRAP #" << ev_trap.getTriggerNumber() << endl;
|
||||||
|
param.msg.set_resulttype(param.msg.TRAP);
|
||||||
|
param.msg.set_resultdata(
|
||||||
|
simulator.getRegisterManager().getInstructionPointer());
|
||||||
|
param.msg.set_output(sanitised(output.c_str()));
|
||||||
|
} else if (ev == &ev_intr) {
|
||||||
|
log << hex << "Result INT FLOOD; Last INT #:"
|
||||||
|
<< ev_intr.getTriggerNumber() << endl;
|
||||||
|
param.msg.set_resulttype(param.msg.INTR);
|
||||||
|
param.msg.set_resultdata(
|
||||||
|
simulator.getRegisterManager().getInstructionPointer());
|
||||||
|
param.msg.set_output(sanitised(output.c_str()));
|
||||||
|
} else {
|
||||||
|
log << dec << "Result WTF?" << endl;
|
||||||
|
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||||
|
param.msg.set_resultdata(
|
||||||
|
simulator.getRegisterManager().getInstructionPointer());
|
||||||
|
param.msg.set_output(sanitised(output.c_str()));
|
||||||
|
|
||||||
|
stringstream ss;
|
||||||
|
ss << "eventid " << ev << " EIP "
|
||||||
|
<< simulator.getRegisterManager().getInstructionPointer()
|
||||||
|
<< endl;
|
||||||
|
param.msg.set_details(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
simulator.clearEvents();
|
||||||
|
m_jc.sendResult(param);
|
||||||
|
|
||||||
#ifdef HEADLESS_EXPERIMENT
|
#ifdef HEADLESS_EXPERIMENT
|
||||||
simulator.terminate(0);
|
simulator.terminate(0);
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "efw/ExperimentFlow.hpp"
|
#include "efw/ExperimentFlow.hpp"
|
||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
|
#include "campaign.hpp"
|
||||||
|
#include "util/Logger.hpp"
|
||||||
|
|
||||||
class L4SysExperiment : public fail::ExperimentFlow {
|
class L4SysExperiment : public fail::ExperimentFlow {
|
||||||
fail::JobClient m_jc;
|
fail::JobClient m_jc;
|
||||||
@ -12,12 +14,45 @@ public:
|
|||||||
L4SysExperiment() : m_jc("localhost") {}
|
L4SysExperiment() : m_jc("localhost") {}
|
||||||
bool run();
|
bool run();
|
||||||
private:
|
private:
|
||||||
// NOTE: It's good practise to use "const std::string&" as parameter type.
|
/**
|
||||||
// Additionaly, if you don't need the return value to be copied,
|
* Sanitises the output string of the serial device monitored.
|
||||||
// return a (const) reference to a class member or a static string-
|
* @param a string containing special ASCII characters
|
||||||
// object.
|
* @returns a byte-stuffed version of the given string
|
||||||
std::string sanitised(std::string in_str);
|
*/
|
||||||
|
std::string sanitised(const std::string &in_str);
|
||||||
|
/**
|
||||||
|
* Waits for events and simultaneously logs output from the serial console
|
||||||
|
* @param clear_output if true, the output logged so far is deleted, thus the buffer is reset (cleared)
|
||||||
|
* @returns the event returned by waitAny, as long as it did not log output
|
||||||
|
*/
|
||||||
fail::BaseEvent* waitIOOrOther(bool clear_output);
|
fail::BaseEvent* waitIOOrOther(bool clear_output);
|
||||||
|
/**
|
||||||
|
* Calculates the address where Bochs will read the current instruction from.
|
||||||
|
* This code is copied from various Bochs methods and should be reviewed as
|
||||||
|
* soon as a new Bochs version is introduced.
|
||||||
|
* @returns a pointer to the memory region containing the current Bochs instruction
|
||||||
|
*/
|
||||||
|
const Bit8u *calculateInstructionAddress();
|
||||||
|
/**
|
||||||
|
* A function necessary for Bochs internal address translation
|
||||||
|
* @returns a value for Bochs' eipBiased variable
|
||||||
|
*/
|
||||||
|
Bit32u eipBiased();
|
||||||
|
/**
|
||||||
|
* Parses a raw instruction into a bxInstruction_c structure.
|
||||||
|
* This simple version of the function is taken from Bochs
|
||||||
|
* where it is currently disabled due to the TRACE_CACHE option,
|
||||||
|
* and has been modified to fit the needs of instruction modification.
|
||||||
|
* @param instance a pointer to the current Bochs CPU
|
||||||
|
* @param instr a pointer to the address the instruction is fetched from
|
||||||
|
* @param iStorage an outgoing value which contains the parsed instruction
|
||||||
|
* @returns \a false if the instruction continued on the following page in memory
|
||||||
|
*/
|
||||||
|
bx_bool fetchInstruction(BX_CPU_C *instance, const Bit8u *instr, bxInstruction_c *iStorage);
|
||||||
|
void logInjection(fail::Logger &log, const L4SysExperimentData ¶m);
|
||||||
|
bool isALUInstruction(unsigned opcode);
|
||||||
|
void readFromFileToVector(std::ifstream &file, std::vector<struct __trace_instr_type> &instr_list);
|
||||||
|
void changeBochsInstruction(bxInstruction_c *dest, bxInstruction_c *src);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __L4SYS_EXPERIMENT_HPP__
|
#endif // __L4SYS_EXPERIMENT_HPP__
|
||||||
|
|||||||
@ -1,15 +1,25 @@
|
|||||||
#ifndef __EXPERIMENT_INFO_HPP__
|
#ifndef __EXPERIMENT_INFO_HPP__
|
||||||
#define __EXPERIMENT_INFO_HPP__
|
#define __EXPERIMENT_INFO_HPP__
|
||||||
|
|
||||||
//experiment types:
|
// the maximum number of bytes in a Bochs instruction
|
||||||
#define GPRFLIP 10
|
#define MAX_INSTR_BYTES 15
|
||||||
#define IDCFLIP 20
|
|
||||||
|
|
||||||
#define L4SYS_FUNC_ENTRY 0x1007cd0
|
// the bounds of the program
|
||||||
#define L4SYS_FUNC_EXIT 0x1007d3a
|
#define L4SYS_ADDRESS_SPACE 0x203d000
|
||||||
#define L4SYS_NUMINSTR 3184
|
#define L4SYS_FUNC_ENTRY 0x1000400
|
||||||
|
#define L4SYS_FUNC_EXIT 0x10005b0
|
||||||
|
#define L4SYS_NUMINSTR 56052772
|
||||||
|
|
||||||
|
#define L4SYS_ITERATION_COUNT 1
|
||||||
|
|
||||||
|
// several file names used
|
||||||
|
#define L4SYS_STATE_FOLDER "l4sys.state"
|
||||||
|
#define L4SYS_INSTRUCTION_LIST "ip.list"
|
||||||
|
#define L4SYS_ALU_INSTRUCTIONS "alu.list"
|
||||||
|
#define L4SYS_CORRECT_OUTPUT "golden.out"
|
||||||
|
|
||||||
|
// flags
|
||||||
#define HEADLESS_EXPERIMENT
|
#define HEADLESS_EXPERIMENT
|
||||||
#define EXPERIMENT_TYPE IDCFLIP
|
|
||||||
//#define PREPARE_EXPERIMENT
|
//#define PREPARE_EXPERIMENT
|
||||||
|
|
||||||
#endif // __EXPERIMENT_INFO_HPP__
|
#endif // __EXPERIMENT_INFO_HPP__
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
message L4SysProtoMsg {
|
message L4SysProtoMsg {
|
||||||
|
// experiment types
|
||||||
|
enum ExperimentType {
|
||||||
|
GPRFLIP = 10;
|
||||||
|
RATFLIP = 15;
|
||||||
|
IDCFLIP = 20;
|
||||||
|
ALUINSTR = 30;
|
||||||
|
}
|
||||||
// parameters
|
// parameters
|
||||||
required int32 instr_offset = 1;
|
required ExperimentType exp_type = 10;
|
||||||
required int32 bit_offset = 2;
|
required int32 instr_offset = 20;
|
||||||
|
required int32 bit_offset = 30;
|
||||||
|
|
||||||
// results
|
// results
|
||||||
// make these optional to reduce overhead for server->client communication
|
// make these optional to reduce overhead for server->client communication
|
||||||
@ -14,13 +22,13 @@ message L4SysProtoMsg {
|
|||||||
UNKNOWN = 6;
|
UNKNOWN = 6;
|
||||||
}
|
}
|
||||||
// instruction pointer where injection was done
|
// instruction pointer where injection was done
|
||||||
optional uint32 injection_ip = 3;
|
optional uint32 injection_ip = 40;
|
||||||
// result type, see above
|
// result type, see above
|
||||||
optional ResultType resulttype = 4;
|
optional ResultType resulttype = 50;
|
||||||
// result data, depending on resulttype (see source code)
|
// result data, depending on resulttype (see source code)
|
||||||
optional uint32 resultdata = 5;
|
optional uint32 resultdata = 60;
|
||||||
// generated output
|
// generated output
|
||||||
optional string output = 6;
|
optional string output = 70;
|
||||||
// optional textual description of what happened
|
// optional textual description of what happened
|
||||||
optional string details = 7;
|
optional string details = 80;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user