Merge branch 'master' of ssh://i4gerrit.informatik.uni-erlangen.de:29418/fail
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
find_program(LLVMCONFIG NAMES llvm-config llvm-config-3.3 llvm-config-3.2 llvm-config-3.1)
|
||||
find_program(LLVMCONFIG NAMES llvm-config llvm-config-3.4 llvm-config-3.3 llvm-config-3.2 llvm-config-3.1)
|
||||
|
||||
if( NOT LLVMCONFIG )
|
||||
message(FATAL_ERROR "llvm-config not found, try installing llvm-dev llvm")
|
||||
|
||||
42
cmake/FindLibIberty.cmake
Normal file
42
cmake/FindLibIberty.cmake
Normal file
@ -0,0 +1,42 @@
|
||||
# - FindLibIberty.cmake
|
||||
# This module can find libiberty on both Debian 7 and Ubuntu 14.04
|
||||
# (The libiberty headers moved from /usr/include to /usr/include/libiberty
|
||||
# between Ubuntu 13.10 and 14.04, which made this search module necessary.)
|
||||
#
|
||||
# The following variables will be defined for your use:
|
||||
#
|
||||
# LibIberty_FOUND - TRUE if both library and headers were found
|
||||
# LibIberty_INCLUDE_DIRS - Include directories
|
||||
# LibIberty_LIBRARIES - Library path
|
||||
|
||||
# set(LibIberty_PREFER_DYNAMIC True) if you want to prefer the dynamic library
|
||||
|
||||
if(LibIberty_PREFER_DYNAMIC)
|
||||
set(LibIberty_SEARCHORDER libiberty.so libiberty.a)
|
||||
else()
|
||||
set(LibIberty_SEARCHORDER libiberty.a libiberty.so)
|
||||
endif()
|
||||
|
||||
find_library(LibIberty_LIBRARIES NAMES ${LibIberty_SEARCHORDER})
|
||||
|
||||
find_path(LibIberty_INCLUDE_DIRS libiberty.h
|
||||
PATHS
|
||||
/usr/include /usr/include/libiberty
|
||||
/usr/local/include /usr/local/include/libiberty
|
||||
DOC "libiberty include directory containing libiberty.h")
|
||||
|
||||
if(LibIberty_INCLUDE_DIRS AND LibIberty_LIBRARIES)
|
||||
set(LibIberty_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
if(LibIberty_FOUND)
|
||||
if(NOT LibIberty_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found libiberty: ${LibIberty_LIBRARIES}")
|
||||
endif()
|
||||
else()
|
||||
if(LibIberty_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find libiberty: install binutils-dev or libiberty-dev")
|
||||
else()
|
||||
MESSAGE(STATUS "libiberty not found")
|
||||
endif()
|
||||
endif()
|
||||
@ -3,7 +3,10 @@ option( VERBOSE_MAKE "Verbose Makefile output" OFF) # defaults to OFF
|
||||
set(CMAKE_VERBOSE_MAKEFILE ${VERBOSE_MAKE})
|
||||
|
||||
### Additional compiler and linker flags ##
|
||||
set(CMAKE_C_FLAGS "-g -Wall")
|
||||
# -Wunused-local-typedefs is included in -Wall since GCC 4.8, and generates a
|
||||
# flood of "typedef '...' locally defined but not used" warnings in
|
||||
# ac++-1.2-generated code
|
||||
set(CMAKE_C_FLAGS "-g -Wall -Wno-unused-local-typedefs")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-gc-sections")
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ Required for Fail*:
|
||||
- protobuf-compiler
|
||||
- cmake 2.8.2 (2.8.11 preferred)
|
||||
- cmake-curses-gui
|
||||
- binutils-dev
|
||||
- binutils-dev, on newer systems libiberty-dev
|
||||
- AspectC++ (ag++, ac++): AspectC++ 1.1 or newer is known to work and can be
|
||||
obtained from <http://www.aspectc.org>; nightlies can be downloaded from
|
||||
<http://akut.aspectc.org>. Make sure you use the 64-bit version if running
|
||||
|
||||
@ -8,7 +8,7 @@ find_package(MySQL REQUIRED)
|
||||
include_directories(${MYSQL_INCLUDE_DIR})
|
||||
|
||||
add_library(fail-cpn ${SRCS})
|
||||
target_link_libraries(fail-cpn fail-comm ${MYSQL_LIBRARIES})
|
||||
target_link_libraries(fail-cpn fail-comm fail-util ${MYSQL_LIBRARIES})
|
||||
|
||||
# make sure protobufs are generated before we include them
|
||||
add_dependencies(fail-cpn fail-comm)
|
||||
|
||||
@ -9,6 +9,7 @@ set(SRCS
|
||||
add_library(fail-efw ${SRCS})
|
||||
add_dependencies(fail-efw fail-comm)
|
||||
target_link_libraries(fail-efw fail-comm)
|
||||
target_link_libraries(fail-efw fail-util) # WallclockTimer
|
||||
|
||||
find_package(LibPCL REQUIRED)
|
||||
include_directories(${LIBPCL_INCLUDE_DIRS})
|
||||
|
||||
@ -43,17 +43,19 @@ include_directories(${Boost_INCLUDE_DIRS})
|
||||
link_directories(${Boost_LIBRARY_DIRS})
|
||||
|
||||
# libiberty required by Demangler.cc:
|
||||
find_library(LIB_IBERTY iberty)
|
||||
mark_as_advanced(LIB_IBERTY)
|
||||
|
||||
if(${LIB_IBERTY} STREQUAL LIB_IBERTY-NOTFOUND)
|
||||
message(FATAL_ERROR "libiberty not found. Try installing binutils-dev: [ sudo aptitude install binutils-dev ]")
|
||||
endif()
|
||||
find_package(LibIberty REQUIRED)
|
||||
include_directories(${LibIberty_INCLUDE_DIRS})
|
||||
|
||||
# libz required by gzstream
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
|
||||
# libelf and libdwarf required by ElfReader/DwarfReader
|
||||
find_package(LibElf REQUIRED)
|
||||
find_package(LibDwarf REQUIRED)
|
||||
include_directories(${LIBELF_INCLUDE_DIRS})
|
||||
include_directories(${LIBDWARF_INCLUDE_DIRS})
|
||||
|
||||
# objdump required by Diassembler.cc
|
||||
|
||||
set(THE_OBJDUMP "${ARCH_TOOL_PREFIX}objdump")
|
||||
@ -67,8 +69,7 @@ mark_as_advanced(FAIL_OBJDUMP)
|
||||
|
||||
add_library(fail-util ${SRCS})
|
||||
add_dependencies(fail-util fail-comm)
|
||||
target_link_libraries(fail-util fail-comm)
|
||||
target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${ZLIB_LIBRARIES} dwarf elf)
|
||||
target_link_libraries(fail-util fail-comm ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LibIberty_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBDWARF_LIBRARIES} ${LIBELF_LIBRARIES})
|
||||
|
||||
option(BUILD_LLVM_DISASSEMBLER "Build the LLVM-based disassembler (LLVM 3.3 preferred, for 3.1 and 3.2 read doc/how-to-build.txt)" OFF)
|
||||
if (BUILD_LLVM_DISASSEMBLER)
|
||||
|
||||
@ -12,14 +12,21 @@ using namespace fail;
|
||||
boost::mutex Database::m_global_lock;
|
||||
#endif
|
||||
|
||||
static CommandLine::option_handle DATABASE, HOSTNAME, USERNAME, DBDEFAULTS;
|
||||
|
||||
Database::Database(const std::string &username, const std::string &host, const std::string &database) {
|
||||
#ifndef __puma
|
||||
boost::lock_guard<boost::mutex> guard(m_global_lock);
|
||||
#endif
|
||||
CommandLine &cmd = CommandLine::Inst();
|
||||
|
||||
std::string db_conf_file = "~/.my.cnf";
|
||||
if (cmd[DBDEFAULTS].count()) {
|
||||
db_conf_file = cmd[DBDEFAULTS].first()->arg;
|
||||
}
|
||||
handle = mysql_init(0);
|
||||
last_result = 0;
|
||||
mysql_options(handle, MYSQL_READ_DEFAULT_FILE, "~/.my.cnf");
|
||||
mysql_options(handle, MYSQL_READ_DEFAULT_FILE, db_conf_file.c_str());
|
||||
if (!mysql_real_connect(handle, host.c_str(),
|
||||
username.c_str(),
|
||||
0, database.c_str(), 0, 0, 0)) {
|
||||
@ -231,8 +238,6 @@ std::string Database::escape_string(const std::string unescaped_string) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static CommandLine::option_handle DATABASE, HOSTNAME, USERNAME;
|
||||
|
||||
void Database::cmdline_setup() {
|
||||
CommandLine &cmd = CommandLine::Inst();
|
||||
|
||||
@ -241,7 +246,9 @@ void Database::cmdline_setup() {
|
||||
HOSTNAME = cmd.addOption("H", "hostname", Arg::Required,
|
||||
"-h/--hostname \tMYSQL Hostname (default: taken from ~/.my.cnf)");
|
||||
USERNAME = cmd.addOption("u", "username", Arg::Required,
|
||||
"-u/--username \tMYSQL Username (default: taken from ~/.my.cnf, or your current user)\n");
|
||||
"-u/--username \tMYSQL Username (default: taken from ~/.my.cnf, or your current user)");
|
||||
DBDEFAULTS = cmd.addOption("", "database-option--file", Arg::Required,
|
||||
"--database-option-file \toverride MySQL ~/.my.cnf option file (prepend with './' for files in the CWD)\n");
|
||||
|
||||
// should be called before any threads are spawned
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
|
||||
@ -85,7 +85,10 @@ void LLVMDisassembler::disassemble()
|
||||
uint64_t End;
|
||||
// The end is either the size of the section or the beginning of the next
|
||||
// symbol.
|
||||
if (si == se - 1)
|
||||
if (Start >= SectSize)
|
||||
// we are beyond the end of the section
|
||||
break;
|
||||
else if (si == se - 1)
|
||||
End = SectSize;
|
||||
// Make sure this symbol takes up space.
|
||||
else if (Symbols[si + 1].first != Start)
|
||||
@ -98,7 +101,7 @@ void LLVMDisassembler::disassemble()
|
||||
MCInst Inst;
|
||||
|
||||
if (disas->getInstruction(Inst, Size, memoryObject, Index,
|
||||
nulls(), nulls())) {
|
||||
nulls(), nulls()) == MCDisassembler::Success) {
|
||||
const MCInstrDesc &desc = this->instr_info->get(Inst.getOpcode());
|
||||
// Inst.dump();
|
||||
Instr instr_info;
|
||||
@ -107,6 +110,8 @@ void LLVMDisassembler::disassemble()
|
||||
instr_info.address = SectionAddr + Index;
|
||||
instr_info.conditional_branch = desc.isConditionalBranch();
|
||||
|
||||
assert( Size > 0 && "zero size instruction disassembled" );
|
||||
|
||||
unsigned int pos = 0;
|
||||
for (MCInst::iterator it = Inst.begin(); it != Inst.end(); ++it) {
|
||||
|
||||
|
||||
@ -36,13 +36,16 @@ message EcosKernelTestProtoMsg {
|
||||
// did ECC correct the fault?
|
||||
optional Flag error_corrected = 5;
|
||||
|
||||
// simulated runtime factor compared to golden run (1.000 = golden run runtime)
|
||||
optional float sim_runtime_factor = 6;
|
||||
|
||||
// especially interesting for TRAP/UNKNOWN: latest IP
|
||||
optional uint32 latest_ip = 6;
|
||||
optional uint32 latest_ip = 7;
|
||||
|
||||
// optional textual description of what happened
|
||||
optional string details = 7;
|
||||
optional string details = 8;
|
||||
|
||||
// experiment runtime (FIXME: should be part of DatabaseCampaignMessage instead)
|
||||
optional float runtime = 8;
|
||||
optional float runtime = 9;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ using namespace fail;
|
||||
const std::string EcosKernelTestExperiment::dir_images(DIR_IMAGES);
|
||||
const std::string EcosKernelTestExperiment::dir_prerequisites(DIR_PREREQUISITES);
|
||||
|
||||
bool EcosKernelTestExperiment::writeTraceInfo(unsigned instr_counter, unsigned timeout,
|
||||
bool EcosKernelTestExperiment::writeTraceInfo(unsigned instr_counter, unsigned long long runtime,
|
||||
unsigned mem1_low, unsigned mem1_high, // < 1M
|
||||
unsigned mem2_low, unsigned mem2_high, // >= 1M
|
||||
const std::string& variant, const std::string& benchmark) {
|
||||
@ -58,7 +58,7 @@ bool EcosKernelTestExperiment::writeTraceInfo(unsigned instr_counter, unsigned t
|
||||
cout << "failed to open " << filename_traceinfo(variant, benchmark) << endl;
|
||||
return false;
|
||||
}
|
||||
ti << instr_counter << endl << timeout << endl
|
||||
ti << instr_counter << endl << runtime << endl
|
||||
<< mem1_low << endl << mem1_high << endl
|
||||
<< mem2_low << endl << mem2_high << endl;
|
||||
ti.flush();
|
||||
@ -66,7 +66,7 @@ bool EcosKernelTestExperiment::writeTraceInfo(unsigned instr_counter, unsigned t
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EcosKernelTestExperiment::readTraceInfo(unsigned &instr_counter, unsigned &timeout,
|
||||
bool EcosKernelTestExperiment::readTraceInfo(unsigned &instr_counter, unsigned long long &runtime,
|
||||
unsigned &mem1_low, unsigned &mem1_high, // < 1M
|
||||
unsigned &mem2_low, unsigned &mem2_high, // >= 1M
|
||||
const std::string& variant, const std::string& benchmark) {
|
||||
@ -86,7 +86,7 @@ bool EcosKernelTestExperiment::readTraceInfo(unsigned &instr_counter, unsigned &
|
||||
ss >> instr_counter;
|
||||
break;
|
||||
case 1:
|
||||
ss >> timeout;
|
||||
ss >> runtime;
|
||||
break;
|
||||
case 2:
|
||||
ss >> mem1_low;
|
||||
@ -370,15 +370,16 @@ bool EcosKernelTestExperiment::performTrace(guest_address_t addr_entry, guest_ad
|
||||
ev = simulator.resume();
|
||||
}
|
||||
|
||||
unsigned long long estimated_timeout_ticks =
|
||||
simulator.getTimerTicks() - time_start + simulator.getTimerTicksPerSecond() / 18.2; // 1s/18.2
|
||||
unsigned long long goldenrun_runtime_ticks = simulator.getTimerTicks() - time_start;
|
||||
// convert to microseconds
|
||||
unsigned estimated_timeout = (unsigned)
|
||||
(estimated_timeout_ticks * 1000000 / simulator.getTimerTicksPerSecond());
|
||||
unsigned goldenrun_runtime = (unsigned)
|
||||
(goldenrun_runtime_ticks * 1000000.0 / simulator.getTimerTicksPerSecond());
|
||||
|
||||
log << dec << "tracing finished after " << instr_counter << " instructions" << endl;
|
||||
log << hex << "all memory accesses within [0x" << mem1_low << ", 0x" << mem1_high << "] u [0x" << mem2_low << ", 0x" << mem2_high << "] (ignoring VGA mem)" << endl;
|
||||
log << dec << "elapsed simulated time (plus safety margin): " << (estimated_timeout / 1000000.0) << "s" << endl;
|
||||
log << dec << "elapsed simulated time: "
|
||||
<< (goldenrun_runtime / 1000000.0) << "s ("
|
||||
<< goldenrun_runtime_ticks << " ticks)" << endl;
|
||||
|
||||
// sanitize memory ranges
|
||||
if (mem1_low > mem1_high) {
|
||||
@ -389,7 +390,7 @@ bool EcosKernelTestExperiment::performTrace(guest_address_t addr_entry, guest_ad
|
||||
}
|
||||
|
||||
// save these values for experiment STEP 3
|
||||
writeTraceInfo(instr_counter, estimated_timeout,
|
||||
writeTraceInfo(instr_counter, goldenrun_runtime_ticks,
|
||||
mem1_low, mem1_high, mem2_low, mem2_high, m_variant, m_benchmark);
|
||||
|
||||
simulator.removeFlow(&tp);
|
||||
@ -454,7 +455,9 @@ bool EcosKernelTestExperiment::faultInjection() {
|
||||
log << "STEP 3: The actual experiment." << endl;
|
||||
|
||||
// trace info
|
||||
unsigned goldenrun_instr_counter, estimated_timeout, mem1_low, mem1_high, mem2_low, mem2_high;
|
||||
unsigned goldenrun_instr_counter, mem1_low, mem1_high, mem2_low, mem2_high;
|
||||
unsigned long long goldenrun_runtime_ticks;
|
||||
unsigned goldenrun_runtime, timeout_runtime;
|
||||
// ELF symbol addresses
|
||||
guest_address_t addr_entry, addr_finish, addr_testdata, addr_testdata_size,
|
||||
addr_test_output, addr_errors_corrected,
|
||||
@ -502,8 +505,12 @@ bool EcosKernelTestExperiment::faultInjection() {
|
||||
unsigned instr_offset = param.msg.fsppilot().injection_instr();
|
||||
unsigned mem_addr = param.msg.fsppilot().data_address();
|
||||
|
||||
readTraceInfo(goldenrun_instr_counter, estimated_timeout,
|
||||
readTraceInfo(goldenrun_instr_counter, goldenrun_runtime_ticks,
|
||||
mem1_low, mem1_high, mem2_low, mem2_high, m_variant, m_benchmark);
|
||||
// convert to microseconds
|
||||
goldenrun_runtime = (unsigned)
|
||||
(goldenrun_runtime_ticks * 1000000.0 / simulator.getTimerTicksPerSecond());
|
||||
timeout_runtime = goldenrun_runtime + 1000000/18.2; // + 1 timer tick
|
||||
if (!readELFSymbols(addr_entry, addr_finish,
|
||||
addr_testdata, addr_testdata_size, addr_test_output,
|
||||
addr_errors_corrected, addr_panic, addr_text_start, addr_text_end,
|
||||
@ -568,6 +575,9 @@ bool EcosKernelTestExperiment::faultInjection() {
|
||||
SerialOutputLogger sol(0x3f8, LIMIT_SERIAL);
|
||||
simulator.addFlow(&sol);
|
||||
|
||||
// measure elapsed time
|
||||
simtime_t time_start = simulator.getTimerTicks();
|
||||
|
||||
BaseListener* ev;
|
||||
|
||||
// no need to wait if offset is 0
|
||||
@ -671,7 +681,7 @@ bool EcosKernelTestExperiment::faultInjection() {
|
||||
simulator.addListener(&ev_mem_outside4);
|
||||
|
||||
// timeout (e.g., stuck in a HLT instruction)
|
||||
TimerListener ev_timeout(estimated_timeout);
|
||||
TimerListener ev_timeout(timeout_runtime);
|
||||
simulator.addListener(&ev_timeout);
|
||||
|
||||
// grant generous (10x) more instructions before aborting to avoid false positives
|
||||
@ -776,6 +786,9 @@ bool EcosKernelTestExperiment::faultInjection() {
|
||||
}
|
||||
}
|
||||
|
||||
result->set_sim_runtime_factor(
|
||||
(simulator.getTimerTicks() - time_start) / (double) goldenrun_runtime_ticks);
|
||||
|
||||
if (ev == &func_finish && output_correct) {
|
||||
// do we reach finish?
|
||||
log << "experiment finished ordinarily" << endl;
|
||||
|
||||
@ -41,8 +41,8 @@ public:
|
||||
|
||||
void handle_func_test_output(bool &test_failed, bool& test_passed);
|
||||
|
||||
static bool writeTraceInfo(unsigned instr_counter, unsigned timeout, unsigned mem1_low, unsigned mem1_high, unsigned mem2_low, unsigned mem2_high, const std::string& variant = "", const std::string& benchmark = "");
|
||||
static bool readTraceInfo(unsigned &instr_counter, unsigned &timeout, unsigned &mem1_low, unsigned &mem1_high, unsigned &mem2_low, unsigned &mem2_high, const std::string& variant = "", const std::string& benchmark = "");
|
||||
static bool writeTraceInfo(unsigned instr_counter, unsigned long long runtime, unsigned mem1_low, unsigned mem1_high, unsigned mem2_low, unsigned mem2_high, const std::string& variant = "", const std::string& benchmark = "");
|
||||
static bool readTraceInfo(unsigned &instr_counter, unsigned long long &runtime, unsigned &mem1_low, unsigned &mem1_high, unsigned &mem2_low, unsigned &mem2_high, const std::string& variant = "", const std::string& benchmark = "");
|
||||
static std::string filename_memorymap(const std::string& variant = "", const std::string& benchmark = "");
|
||||
static std::string filename_state(unsigned instr_offset, const std::string& variant = "", const std::string& benchmark = "");
|
||||
static std::string filename_trace(const std::string& variant = "", const std::string& benchmark = "");
|
||||
|
||||
37
src/experiments/kesogc/CMakeLists.txt
Normal file
37
src/experiments/kesogc/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
set(EXPERIMENT_NAME kesogc)
|
||||
set(EXPERIMENT_TYPE KESOgc)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
kesogc.proto
|
||||
)
|
||||
|
||||
set(MY_CAMPAIGN_SRCS
|
||||
experiment.hpp
|
||||
experiment.cc
|
||||
campaign.hpp
|
||||
campaign.cc
|
||||
)
|
||||
|
||||
#### PROTOBUFS ####
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
find_package(MySQL REQUIRED)
|
||||
include_directories(${MYSQL_INCLUDE_DIR})
|
||||
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
|
||||
|
||||
## Build library
|
||||
add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
|
||||
add_dependencies(fail-${EXPERIMENT_NAME} fail-comm)
|
||||
target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY})
|
||||
|
||||
## This is the example's campaign server distributing experiment parameters
|
||||
add_executable(${EXPERIMENT_NAME}-server main.cc)
|
||||
target_link_libraries(${EXPERIMENT_NAME}-server -Wl,--start-group fail-${EXPERIMENT_NAME} fail-sal fail-util fail-cpn fail-comm ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} ${MYSQL_LIBRARIES} -Wl,--end-group)
|
||||
install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)
|
||||
20
src/experiments/kesogc/campaign.cc
Normal file
20
src/experiments/kesogc/campaign.cc
Normal file
@ -0,0 +1,20 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/ProtoStream.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
using namespace google::protobuf;
|
||||
|
||||
void KesoGcCampaign::cb_send_pilot(DatabaseCampaignMessage pilot) {
|
||||
KesoGcExperimentData *data = new KesoGcExperimentData;
|
||||
data->msg.mutable_fsppilot()->CopyFrom(pilot);
|
||||
campaignmanager.addParam(data);
|
||||
}
|
||||
24
src/experiments/kesogc/campaign.hpp
Normal file
24
src/experiments/kesogc/campaign.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __KESOGCCAMPAIGN_HPP__
|
||||
#define __KESOGCCAMPAIGN_HPP__
|
||||
|
||||
#include "cpn/DatabaseCampaign.hpp"
|
||||
#include "comm/ExperimentData.hpp"
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include "kesogc.pb.h"
|
||||
|
||||
|
||||
class KesoGcExperimentData : public fail::ExperimentData {
|
||||
public:
|
||||
KesoGcProtoMsg msg;
|
||||
KesoGcExperimentData() : fail::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
|
||||
class KesoGcCampaign : public fail::DatabaseCampaign {
|
||||
virtual const google::protobuf::Descriptor * cb_result_message()
|
||||
{ return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("KesoGcProtoMsg"); }
|
||||
|
||||
virtual void cb_send_pilot(DatabaseCampaignMessage pilot);
|
||||
};
|
||||
|
||||
#endif // __KESOGCCAMPAIGN_HPP__
|
||||
327
src/experiments/kesogc/experiment.cc
Normal file
327
src/experiments/kesogc/experiment.cc
Normal file
@ -0,0 +1,327 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
// getpid
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "experiment.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
#include "sal/SALInst.hpp"
|
||||
#include "sal/Memory.hpp"
|
||||
#include "sal/Listener.hpp"
|
||||
|
||||
#include "sal/bochs/BochsListener.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "kesogc.pb.h"
|
||||
#include "util/Disassembler.hpp"
|
||||
|
||||
const char *parity_types[] = {
|
||||
"LIST",
|
||||
"STACK",
|
||||
"STACK_POINTER",
|
||||
"DOMAIN",
|
||||
"BITMAP",
|
||||
"LLREFS",
|
||||
"COLOR"
|
||||
};
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
// Check if configuration dependencies are satisfied:
|
||||
#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE)
|
||||
#error This experiment needs: breakpoints, traps, save, and restore. Enable these in the configuration.
|
||||
#endif
|
||||
|
||||
unsigned KESOgc::injectBitFlip(address_t data_address, unsigned bitpos){
|
||||
|
||||
MemoryManager& mm = simulator.getMemoryManager();
|
||||
unsigned int value, injectedval;
|
||||
|
||||
value = mm.getByte(data_address);
|
||||
injectedval = value ^ (1 << bitpos);
|
||||
mm.setByte(data_address, injectedval);
|
||||
|
||||
m_log << "INJECTION at: 0x" << hex<< setw(2) << setfill('0') << data_address
|
||||
<< " value: 0x" << setw(2) << setfill('0') << value << " -> 0x" << setw(2) << setfill('0') << mm.getByte(data_address) << endl;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void handleEvent(KesoGcProtoMsg_Result& result, KesoGcProtoMsg_Result_ResultType restype, const std::string &msg) {
|
||||
cout << "Result details: " << msg << endl;
|
||||
result.set_resulttype(restype);
|
||||
result.set_details(msg);
|
||||
}
|
||||
|
||||
|
||||
void handleMemoryAccessEvent(KesoGcProtoMsg_Result& result, const fail::MemAccessListener& l_mem){
|
||||
stringstream sstr;
|
||||
sstr << "mem access (";
|
||||
switch (l_mem.getTriggerAccessType()) {
|
||||
case MemAccessEvent::MEM_READ:
|
||||
sstr << "r";
|
||||
break;
|
||||
case MemAccessEvent::MEM_WRITE:
|
||||
sstr << "w";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
sstr << ") @ 0x" << hex << l_mem.getTriggerAddress();
|
||||
|
||||
sstr << " ip @ 0x" << hex << l_mem.getTriggerInstructionPointer();
|
||||
|
||||
handleEvent(result, result.MEMACCESS, sstr.str());
|
||||
}
|
||||
|
||||
bool KESOgc::run()
|
||||
{
|
||||
address_t minimal_ip = INT_MAX; // 1 Mbyte
|
||||
address_t maximal_ip = 0;
|
||||
address_t minimal_data = 0x100000; // 1 Mbyte
|
||||
address_t maximal_data = 0;
|
||||
|
||||
for (ElfReader::section_iterator it = m_elf.sec_begin();
|
||||
it != m_elf.sec_end(); ++it) {
|
||||
const ElfSymbol &symbol = *it;
|
||||
std::string prefix(".text");
|
||||
if (symbol.getName().compare(0, prefix.size(), prefix) == 0) {
|
||||
minimal_ip = std::min(minimal_ip, symbol.getStart());
|
||||
maximal_ip = std::max(maximal_ip, symbol.getEnd());
|
||||
} else {
|
||||
minimal_data = std::min(minimal_data, symbol.getStart());
|
||||
maximal_data = std::max(maximal_data, symbol.getEnd());
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Code section from " << hex << minimal_ip << " to " << maximal_ip << std::endl;
|
||||
std::cout << "Whole programm section from " << hex << minimal_data << " to " << maximal_data << std::endl;
|
||||
|
||||
|
||||
|
||||
// m_dis.init();
|
||||
//******* Boot, and store state *******//
|
||||
m_log << "STARTING EXPERIMENT" << endl;
|
||||
|
||||
unsigned executed_jobs = 0;
|
||||
|
||||
// Setup exit points
|
||||
const ElfSymbol &s_error = m_elf.getSymbol("keso_throw_error");
|
||||
BPSingleListener l_error(s_error.getAddress());
|
||||
|
||||
const ElfSymbol &s_nullp = m_elf.getSymbol("keso_throw_nullpointer");
|
||||
BPSingleListener l_nullp(s_nullp.getAddress());
|
||||
|
||||
const ElfSymbol &s_oobounds = m_elf.getSymbol("keso_throw_index_out_of_bounds");
|
||||
BPSingleListener l_oobounds(s_oobounds.getAddress());
|
||||
|
||||
const ElfSymbol &s_gc_parity = m_elf.getSymbol("keso_throw_gc_parity");
|
||||
BPSingleListener l_gc_parity(s_gc_parity.getAddress());
|
||||
|
||||
const ElfSymbol &s_parity = m_elf.getSymbol("keso_throw_parity");
|
||||
BPSingleListener l_parity(s_parity.getAddress());
|
||||
|
||||
//BPSingleListener l_dump(m_elf.getSymbol("c17_Main_m4_dumpResults_console").getAddress());
|
||||
BPSingleListener l_end(m_elf.getSymbol("keso_end").getAddress());
|
||||
|
||||
MemAccessListener l_mem_text(minimal_ip, MemAccessEvent::MEM_WRITE);
|
||||
l_mem_text.setWatchWidth(maximal_ip - minimal_ip);
|
||||
|
||||
MemAccessListener l_mem_outerspace( maximal_data, MemAccessEvent::MEM_WRITE);
|
||||
l_mem_outerspace.setWatchWidth(0xfffffff0);
|
||||
|
||||
TrapListener l_trap(ANY_TRAP);
|
||||
|
||||
TimerListener l_timeout(5 * 1000 * 1000); // 5 seconds in microseconds
|
||||
|
||||
const ElfSymbol &s_resilient_heap_repaired = m_elf.getSymbol("keso_resilient_gcHeapPointer_repaired");
|
||||
BPSingleListener l_resilient_heap_repaired(s_resilient_heap_repaired.getAddress());
|
||||
|
||||
const ElfSymbol &s_ft_list_repaired = m_elf.getSymbol("keso_ft_list_repaired");
|
||||
BPSingleListener l_ft_list_repaired(s_ft_list_repaired.getAddress());
|
||||
|
||||
const ElfSymbol &s_ft_list_broken = m_elf.getSymbol("keso_ft_list_broken");
|
||||
BPSingleListener l_ft_list_broken(s_ft_list_broken.getAddress());
|
||||
|
||||
const ElfSymbol &s_resilient_stack_repaired = m_elf.getSymbol("keso_resilient_gcStackPointer_repaired");
|
||||
BPSingleListener l_resilient_stack_repaired(s_resilient_stack_repaired.getAddress());
|
||||
|
||||
while (executed_jobs < 25 || m_jc->getNumberOfUndoneJobs() > 0) {
|
||||
m_log << "asking jobserver for parameters" << endl;
|
||||
KesoGcExperimentData param;
|
||||
if(!m_jc->getParam(param)){
|
||||
m_log << "Dying." << endl; // We were told to die.
|
||||
simulator.terminate(1);
|
||||
}
|
||||
|
||||
// Get input data from Jobserver
|
||||
unsigned injection_instr = param.msg.fsppilot().injection_instr();
|
||||
address_t data_address = param.msg.fsppilot().data_address();
|
||||
|
||||
for (int bit_offset = 0; bit_offset < 8; ++bit_offset) {
|
||||
// 8 results in one job
|
||||
KesoGcProtoMsg_Result *result = param.msg.add_result();
|
||||
result->set_bitoffset(bit_offset);
|
||||
|
||||
m_log << "restoring state" << endl;
|
||||
// Restore to the image, which starts at address(main)
|
||||
simulator.restore("state");
|
||||
executed_jobs ++;
|
||||
|
||||
m_log << "Trying to inject @ instr #" << dec << injection_instr << endl;
|
||||
|
||||
|
||||
if (injection_instr > 0) {
|
||||
simulator.clearListeners();
|
||||
// XXX could be improved with intermediate states (reducing runtime until injection)
|
||||
simulator.addListener(&l_end);
|
||||
|
||||
BPSingleListener bp;
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
|
||||
// Fix offset by 1 error
|
||||
bp.setCounter(injection_instr + 1);
|
||||
|
||||
simulator.addListener(&bp);
|
||||
|
||||
bool inject = true;
|
||||
while (1) {
|
||||
fail::BaseListener * listener = simulator.resume();
|
||||
// finish() before FI?
|
||||
if (listener == &l_end) {
|
||||
m_log << "experiment reached finish() before FI" << endl;
|
||||
handleEvent(*result, result->NOINJECTION, "time_marker reached before instr2");
|
||||
inject = false;
|
||||
break;
|
||||
} else if (listener == &bp) {
|
||||
break;
|
||||
} else {
|
||||
inject = false;
|
||||
handleEvent(*result, result->NOINJECTION, "WTF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Next experiment
|
||||
if (!inject)
|
||||
continue;
|
||||
}
|
||||
|
||||
address_t injection_instr_absolute = param.msg.fsppilot().injection_instr_absolute();
|
||||
if (simulator.getCPU(0).getInstructionPointer() != injection_instr_absolute) {
|
||||
m_log << "Invalid Injection address EIP=0x"
|
||||
<< std::hex << simulator.getCPU(0).getInstructionPointer()
|
||||
<< " != 0x" << injection_instr_absolute << std::endl;
|
||||
simulator.terminate(1);
|
||||
}
|
||||
|
||||
/// INJECT BITFLIP:
|
||||
result->set_original_value(injectBitFlip(data_address, bit_offset));
|
||||
|
||||
cout << " outerspace : " << l_mem_outerspace.getWatchWidth() << " --- @ :" << l_mem_outerspace.getWatchAddress() << endl;
|
||||
simulator.clearListeners();
|
||||
simulator.addListener(&l_trap);
|
||||
if (s_error.isValid())
|
||||
simulator.addListener(&l_error);
|
||||
if (s_nullp.isValid())
|
||||
simulator.addListener(&l_nullp);
|
||||
if (s_oobounds.isValid())
|
||||
simulator.addListener(&l_oobounds);
|
||||
if (s_gc_parity.isValid())
|
||||
simulator.addListener(&l_gc_parity);
|
||||
if (s_parity.isValid())
|
||||
simulator.addListener(&l_parity);
|
||||
simulator.addListener(&l_end);
|
||||
simulator.addListener(&l_mem_text);
|
||||
simulator.addListener(&l_mem_outerspace);
|
||||
simulator.addListener(&l_timeout);
|
||||
|
||||
if(s_resilient_heap_repaired.isValid()){
|
||||
simulator.addListener(&l_resilient_heap_repaired);
|
||||
}
|
||||
|
||||
if(s_resilient_stack_repaired.isValid()){
|
||||
simulator.addListener(&l_resilient_stack_repaired);
|
||||
}
|
||||
|
||||
if(s_ft_list_repaired.isValid()){
|
||||
simulator.addListener(&l_ft_list_repaired);
|
||||
}
|
||||
|
||||
if(s_ft_list_broken.isValid()){
|
||||
simulator.addListener(&l_ft_list_broken);
|
||||
}
|
||||
|
||||
m_log << "Resuming till the crash" << std::endl;
|
||||
// resume and wait for results
|
||||
fail::BaseListener* l = simulator.resume();
|
||||
m_log << "CDX has ended" << std::endl;
|
||||
|
||||
// Evaluate result
|
||||
if(l == &l_error) {
|
||||
handleEvent(*result, result->EXC_ERROR, "exc error");
|
||||
} else if (l == &l_nullp) {
|
||||
handleEvent(*result, result->EXC_NULLPOINTER, "exc nullpointer");
|
||||
|
||||
} else if ( l == &l_oobounds ) {
|
||||
handleEvent(*result, result->EXC_OOBOUNDS, "exc out of bounds");
|
||||
|
||||
} else if (l == &l_gc_parity) {
|
||||
address_t stack_pointer = simulator.getCPU(0).getStackPointer();
|
||||
int32_t parity_type = simulator.getMemoryManager().getByte(stack_pointer + 4); // 1st argument is at esp+4
|
||||
stringstream sstr;
|
||||
sstr << "exc gc_parity of type: " << parity_types[parity_type];
|
||||
handleEvent(*result, result->EXC_GC_PARITY, sstr.str());
|
||||
|
||||
} else if (l == &l_parity) {
|
||||
handleEvent(*result, result->EXC_PARITY, "exc parity");
|
||||
|
||||
} else if (l == &l_end) {
|
||||
handleEvent(*result, result->CALCDONE, "calculation done");
|
||||
|
||||
} else if (l == &l_timeout) {
|
||||
handleEvent(*result, result->TIMEOUT, "5s");
|
||||
|
||||
} else if (l == &l_trap) {
|
||||
stringstream sstr;
|
||||
sstr << "trap #" << l_trap.getTriggerNumber();
|
||||
handleEvent(*result, result->TRAP, sstr.str());
|
||||
|
||||
} else if (l == &l_mem_text){
|
||||
handleMemoryAccessEvent(*result, l_mem_text);
|
||||
|
||||
} else if (l == &l_mem_outerspace){
|
||||
handleMemoryAccessEvent(*result, l_mem_outerspace);
|
||||
|
||||
} else if (l == &l_resilient_heap_repaired){
|
||||
handleEvent(*result, result->RESILIENT_HEAP_REPAIRED, "resilient heap pointer repaired");
|
||||
|
||||
} else if (l == &l_resilient_stack_repaired){
|
||||
handleEvent(*result, result->RESILIENT_STACK_REPAIRED, "resilient stack pointer repaired");
|
||||
|
||||
} else if (l == &l_ft_list_repaired){
|
||||
handleEvent(*result, result->FT_LIST_REPAIRED, "ft list repaired");
|
||||
|
||||
} else if (l == &l_ft_list_broken){
|
||||
handleEvent(*result, result->FT_LIST_BROKEN, "ft list broken");
|
||||
|
||||
} else {
|
||||
handleEvent(*result, result->UNKNOWN, "UNKNOWN event");
|
||||
}
|
||||
simulator.clearListeners();
|
||||
}
|
||||
|
||||
m_jc->sendResult(param);
|
||||
}
|
||||
// Explicitly terminate, or the simulator will continue to run.
|
||||
simulator.terminate();
|
||||
}
|
||||
|
||||
44
src/experiments/kesogc/experiment.hpp
Normal file
44
src/experiments/kesogc/experiment.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef __KESO_GC_EXPERIMENT_HPP__
|
||||
#define __KESO_GC_EXPERIMENT_HPP__
|
||||
|
||||
|
||||
#include "sal/SALInst.hpp"
|
||||
#include "efw/ExperimentFlow.hpp"
|
||||
#include "efw/JobClient.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/ElfReader.hpp"
|
||||
#include "util/Disassembler.hpp"
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
class KESOgc : public fail::ExperimentFlow {
|
||||
fail::JobClient *m_jc;
|
||||
fail::Logger m_log;
|
||||
fail::MemoryManager& m_mm;
|
||||
fail::ElfReader m_elf;
|
||||
fail::Disassembler m_dis;
|
||||
|
||||
void printEIP();
|
||||
void setupExitBPs(const std::string&);
|
||||
void enableBPs();
|
||||
void clearExitBPs();
|
||||
void showStaticRefs();
|
||||
|
||||
unsigned injectBitFlip(fail::address_t data_address, unsigned bitpos);
|
||||
|
||||
public:
|
||||
KESOgc() : m_log("KESOgc", false), m_mm(fail::simulator.getMemoryManager()) {
|
||||
|
||||
char *server_host = getenv("FAIL_SERVER_HOST");
|
||||
if(server_host != NULL){
|
||||
this->m_jc = new fail::JobClient(std::string(server_host));
|
||||
} else {
|
||||
this->m_jc = new fail::JobClient();
|
||||
}
|
||||
|
||||
};
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif // __KESO_GC_EXPERIMENT_HPP__
|
||||
24
src/experiments/kesogc/experimentInfo.hpp
Normal file
24
src/experiments/kesogc/experimentInfo.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
|
||||
// the task function's entry address:
|
||||
// nm -C ecc.elf|fgrep main
|
||||
#define OOSTUBS_FUNC_ENTRY 0x001009d0
|
||||
// empty function that is called explicitly when the experiment finished
|
||||
// nm -C ecc.elf|fgrep "finished()"
|
||||
#define OOSTUBS_FUNC_FINISH 0x001009d6
|
||||
// function executing HLT with no chance for further progress (after panic())
|
||||
// nm -C ecc.elf|fgrep cpu_halt
|
||||
#define OOSTUBS_FUNC_CPU_HALT 0x001009f7
|
||||
|
||||
// nm -C ecc.elf | fgrep "_TEXT_"
|
||||
#define OOSTUBS_TEXT_START 0x00100000
|
||||
#define OOSTUBS_TEXT_END 0x00100a1b
|
||||
|
||||
#define OOSTUBS_NUMINSTR 5
|
||||
|
||||
|
||||
#endif // __EXPERIMENT_INFO_HPP__
|
||||
31
src/experiments/kesogc/kesogc.proto
Normal file
31
src/experiments/kesogc/kesogc.proto
Normal file
@ -0,0 +1,31 @@
|
||||
import "DatabaseCampaignMessage.proto";
|
||||
|
||||
message KesoGcProtoMsg {
|
||||
required DatabaseCampaignMessage fsppilot = 1;
|
||||
|
||||
repeated group Result = 2 {
|
||||
// make these optional to reduce overhead for server->client communication
|
||||
enum ResultType {
|
||||
CALCDONE = 1;
|
||||
TIMEOUT = 2;
|
||||
TRAP = 3;
|
||||
EXC_ERROR = 4;
|
||||
FT_LIST_REPAIRED = 5;
|
||||
EXC_NULLPOINTER = 6;
|
||||
RESILIENT_HEAP_REPAIRED = 7;
|
||||
MEMACCESS = 8;
|
||||
NOINJECTION = 9;
|
||||
FT_LIST_BROKEN = 10;
|
||||
UNKNOWN = 11;
|
||||
RESILIENT_STACK_REPAIRED = 12;
|
||||
EXC_PARITY = 13;
|
||||
EXC_GC_PARITY = 14;
|
||||
EXC_OOBOUNDS = 15;
|
||||
}
|
||||
// result type, see above
|
||||
required ResultType resulttype = 4;
|
||||
required uint32 original_value = 5;
|
||||
required uint32 bitoffset = 6 [(sql_primary_key) = true];
|
||||
optional string details = 7;
|
||||
}
|
||||
}
|
||||
20
src/experiments/kesogc/main.cc
Normal file
20
src/experiments/kesogc/main.cc
Normal file
@ -0,0 +1,20 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "util/CommandLine.hpp"
|
||||
#include "campaign.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
fail::CommandLine &cmd = fail::CommandLine::Inst();
|
||||
for (int i = 1; i < argc; ++i)
|
||||
cmd.add_args(argv[i]);
|
||||
|
||||
KesoGcCampaign c;
|
||||
if (fail::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -5,15 +5,15 @@ configure_file(../instantiate-experiment.ah.in
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
# vezs-example.proto
|
||||
set(MY_PROTOS
|
||||
vezs.proto
|
||||
)
|
||||
|
||||
set(MY_CAMPAIGN_SRCS
|
||||
experiment.hpp
|
||||
experiment.cc
|
||||
#campaign.hpp
|
||||
#campaign.cc
|
||||
campaign.hpp
|
||||
campaign.cc
|
||||
)
|
||||
|
||||
#### PROTOBUFS ####
|
||||
@ -21,7 +21,10 @@ find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
#PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
|
||||
find_package(MySQL REQUIRED)
|
||||
include_directories(${MYSQL_INCLUDE_DIR})
|
||||
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
|
||||
|
||||
## Build library
|
||||
add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
|
||||
@ -30,6 +33,6 @@ target_link_libraries(fail-${EXPERIMENT_NAME} fail-comm)
|
||||
target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY})
|
||||
|
||||
## This is the example's campaign server distributing experiment parameters
|
||||
#add_executable(${EXPERIMENT_NAME}-server main.cc)
|
||||
#target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY})
|
||||
#install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)
|
||||
add_executable(${EXPERIMENT_NAME}-server main.cc)
|
||||
target_link_libraries(${EXPERIMENT_NAME}-server -Wl,--start-group fail-${EXPERIMENT_NAME} fail-sal fail-util fail-cpn fail-comm ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} ${MYSQL_LIBRARIES} -Wl,--end-group)
|
||||
install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)
|
||||
|
||||
20
src/experiments/vezs-example/campaign.cc
Normal file
20
src/experiments/vezs-example/campaign.cc
Normal file
@ -0,0 +1,20 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/ProtoStream.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
using namespace google::protobuf;
|
||||
|
||||
void VEZSCampaign::cb_send_pilot(DatabaseCampaignMessage pilot) {
|
||||
VEZSExperimentData *data = new VEZSExperimentData;
|
||||
data->msg.mutable_fsppilot()->CopyFrom(pilot);
|
||||
campaignmanager.addParam(data);
|
||||
}
|
||||
24
src/experiments/vezs-example/campaign.hpp
Normal file
24
src/experiments/vezs-example/campaign.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __KESOGCCAMPAIGN_HPP__
|
||||
#define __KESOGCCAMPAIGN_HPP__
|
||||
|
||||
#include "cpn/DatabaseCampaign.hpp"
|
||||
#include "comm/ExperimentData.hpp"
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include "vezs.pb.h"
|
||||
|
||||
|
||||
class VEZSExperimentData : public fail::ExperimentData {
|
||||
public:
|
||||
VEZSProtoMsg msg;
|
||||
VEZSExperimentData() : fail::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
|
||||
class VEZSCampaign : public fail::DatabaseCampaign {
|
||||
virtual const google::protobuf::Descriptor * cb_result_message()
|
||||
{ return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("VEZSProtoMsg"); }
|
||||
|
||||
virtual void cb_send_pilot(DatabaseCampaignMessage pilot);
|
||||
};
|
||||
|
||||
#endif // __KESOGCCAMPAIGN_HPP__
|
||||
@ -1,3 +1,4 @@
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
@ -8,87 +9,228 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "experiment.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "sal/SALConfig.hpp"
|
||||
#include "sal/SALInst.hpp"
|
||||
#include "sal/Memory.hpp"
|
||||
#include "sal/Listener.hpp"
|
||||
|
||||
#include "sal/bochs/BochsListener.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/llvmdisassembler/LLVMtoFailTranslator.hpp"
|
||||
#include "util/llvmdisassembler/LLVMtoFailBochs.hpp"
|
||||
#include "campaign.hpp"
|
||||
#include "vezs.pb.h"
|
||||
#include "util/Disassembler.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
// Check if configuration dependencies are satisfied:
|
||||
#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE)
|
||||
#error This experiment needs: breakpoints, traps, save, and restore. Enable these in the configuration.
|
||||
#endif
|
||||
|
||||
void VEZSExperiment::redecodeCurrentInstruction() {
|
||||
/* Flush Instruction Caches and Prefetch queue */
|
||||
BX_CPU_C *cpu_context = simulator.getCPUContext();
|
||||
cpu_context->invalidate_prefetch_q();
|
||||
cpu_context->iCache.flushICacheEntries();
|
||||
|
||||
|
||||
guest_address_t pc = simulator.getCPU(0).getInstructionPointer();
|
||||
bxInstruction_c *currInstr = simulator.getCurrentInstruction();
|
||||
|
||||
cout << "REDECODE INSTRUCTION!" << endl;
|
||||
|
||||
Bit32u eipBiased = pc + cpu_context->eipPageBias;
|
||||
Bit8u instr_plain[32];
|
||||
|
||||
MemoryManager& mm = simulator.getMemoryManager();
|
||||
mm.getBytes(pc, 32, instr_plain);
|
||||
|
||||
unsigned remainingInPage = cpu_context->eipPageWindowSize - eipBiased;
|
||||
int ret;
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (cpu_context->cpu_mode == BX_MODE_LONG_64)
|
||||
ret = cpu_context->fetchDecode64(instr_plain, currInstr, remainingInPage);
|
||||
else
|
||||
#endif
|
||||
ret = cpu_context->fetchDecode32(instr_plain, currInstr, remainingInPage);
|
||||
if (ret < 0) {
|
||||
// handle instrumentation callback inside boundaryFetch
|
||||
cpu_context->boundaryFetch(instr_plain, remainingInPage, currInstr);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned VEZSExperiment::injectBitFlip(address_t data_address, unsigned data_width, unsigned bitpos){
|
||||
MemoryManager& mm = simulator.getMemoryManager();
|
||||
unsigned int value, injectedval;
|
||||
|
||||
value = mm.getByte(data_address);
|
||||
injectedval = value ^ (1 << bitpos);
|
||||
mm.setByte(data_address, injectedval);
|
||||
|
||||
cout << "INJECTION at: 0x" << hex << setw(2) << setfill('0') << data_address
|
||||
<< " value: 0x" << setw(2) << setfill('0') << value << " -> 0x" << setw(2) << setfill('0') << injectedval << endl;
|
||||
|
||||
/* If it is the current instruction redecode it */
|
||||
guest_address_t pc = simulator.getCPU(0).getInstructionPointer();
|
||||
bxInstruction_c *currInstr = simulator.getCurrentInstruction();
|
||||
if (currInstr) {
|
||||
unsigned length_in_bytes = currInstr->ilen();
|
||||
|
||||
if (pc <= data_address && data_address <= (pc + length_in_bytes)) {
|
||||
redecodeCurrentInstruction();
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void handleEvent(VEZSProtoMsg_Result& result, VEZSProtoMsg_Result_ResultType restype, const std::string &msg) {
|
||||
cout << "Result details: " << msg << endl;
|
||||
result.set_resulttype(restype);
|
||||
result.set_details(msg);
|
||||
}
|
||||
|
||||
|
||||
bool VEZSExperiment::run()
|
||||
{
|
||||
//MemoryManager& mm = simulator.getMemoryManager();
|
||||
// m_dis.init();
|
||||
//******* Boot, and store state *******//
|
||||
cout << "STARTING EXPERIMENT" << endl;
|
||||
|
||||
//m_elf.printDemangled();
|
||||
m_log << "STARTING EXPERIMENT" << endl;
|
||||
m_log << "Instruction Pointer: 0x" << hex << simulator.getCPU(0).getInstructionPointer() << endl;
|
||||
// Test register access
|
||||
Register* reg = simulator.getCPU(0).getRegister(RI_R1);
|
||||
m_log << "Register R1: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||
unsigned executed_jobs = 0;
|
||||
|
||||
reg = simulator.getCPU(0).getRegister(RI_R2);
|
||||
m_log << "Register R2: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||
// Setup exit points
|
||||
const ElfSymbol &s_positive = m_elf.getSymbol("fail_marker_positive");
|
||||
BPSingleListener l_positive(s_positive.getAddress());
|
||||
|
||||
const ElfSymbol &s_negative = m_elf.getSymbol("fail_marker_negative");
|
||||
BPSingleListener l_negative(s_negative.getAddress());
|
||||
|
||||
const ElfSymbol &s_end = m_elf.getSymbol("fail_trace_stop");
|
||||
BPSingleListener l_end(s_end.getAddress());
|
||||
|
||||
TrapListener l_trap(ANY_TRAP);
|
||||
|
||||
TimerListener l_timeout(500 * 1000); // 500 ms
|
||||
|
||||
assert(s_positive.isValid() || "fail_marker_positive not found");
|
||||
assert(s_negative.isValid() || "fail_marker_negative not found");
|
||||
assert(s_end.isValid() ||"fail_trace_stop not found");
|
||||
|
||||
|
||||
// Test Listeners
|
||||
address_t address = m_elf.getSymbol("incfoo").getAddress();
|
||||
address &= ~1; // Cortex M3 Thumb Mode has the first bit set..
|
||||
m_log << "incfoo() @ 0x" << std::hex << address << std::endl;
|
||||
while (executed_jobs < 25 || m_jc->getNumberOfUndoneJobs() > 0) {
|
||||
cout << "asking jobserver for parameters" << endl;
|
||||
VEZSExperimentData param;
|
||||
if(!m_jc->getParam(param)){
|
||||
cout << "Dying." << endl; // We were told to die.
|
||||
simulator.terminate(1);
|
||||
}
|
||||
|
||||
address_t pfoo = m_elf.getSymbol("foo").getAddress();
|
||||
//BPSingleListener bp(address);
|
||||
//BPRangeListener bp(address-32, address + 32);
|
||||
MemWriteListener l_foo( pfoo );
|
||||
//MemAccessListener l_foo( 0x20002074 ); l_foo.setWatchWidth(0x4);
|
||||
reg = simulator.getCPU(0).getRegister(RI_R4);
|
||||
// Get input data from Jobserver
|
||||
unsigned injection_instr = param.msg.fsppilot().injection_instr();
|
||||
address_t data_address = param.msg.fsppilot().data_address();
|
||||
unsigned data_width = param.msg.fsppilot().data_width();
|
||||
|
||||
//unsigned foo = 23;
|
||||
for(int i = 0; i < 15; i++){
|
||||
simulator.addListenerAndResume(&l_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 << " Trigger PC: 0x" << std::hex << l_foo.getTriggerInstructionPointer() << std::endl;
|
||||
//m_log << " Register R3: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||
//mm.getBytes(pfoo, 4, (void*)&foo);
|
||||
//m_log << " foo @ 0x"<< std::hex << pfoo << " = " << foo << std::endl;
|
||||
}
|
||||
for (int bit_offset = 0; bit_offset < 8; ++bit_offset) {
|
||||
// 8 results in one job
|
||||
VEZSProtoMsg_Result *result = param.msg.add_result();
|
||||
result->set_bitoffset(bit_offset);
|
||||
|
||||
/*
|
||||
BPRangeListener rbp(0xef, 0xff);
|
||||
simulator.addListener(&rbp);
|
||||
cout << "restoring state" << endl;
|
||||
// Restore to the image, which starts at address(main)
|
||||
simulator.restore("state");
|
||||
executed_jobs ++;
|
||||
|
||||
MemAccessListener l_mem_w(0x1111, MemAccessEvent::MEM_WRITE);
|
||||
l_mem_w.setWatchWidth(16);
|
||||
simulator.addListener(&l_mem_w);
|
||||
cout << "Trying to inject @ instr #" << dec << injection_instr << endl;
|
||||
|
||||
MemAccessListener l_mem_r(0x2222, MemAccessEvent::MEM_READ);
|
||||
l_mem_r.setWatchWidth(16);
|
||||
simulator.addListener(&l_mem_r);
|
||||
|
||||
MemAccessListener l_mem_rw(0x3333, MemAccessEvent::MEM_READWRITE);
|
||||
l_mem_rw.setWatchWidth(16);
|
||||
simulator.addListener(&l_mem_rw);
|
||||
if (injection_instr > 0) {
|
||||
simulator.clearListeners();
|
||||
// XXX could be improved with intermediate states (reducing runtime until injection)
|
||||
simulator.addListener(&l_end);
|
||||
|
||||
simulator.clearListeners();
|
||||
// resume backend.
|
||||
// simulator.resume();
|
||||
BPSingleListener bp;
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
|
||||
// Fix offset by 1 error
|
||||
bp.setCounter(injection_instr + 1);
|
||||
|
||||
simulator.addListener(&bp);
|
||||
|
||||
// Test Memory access
|
||||
address_t targetaddress = 0x12345678;
|
||||
MemoryManager& mm = simulator.getMemoryManager();
|
||||
mm.setByte(targetaddress, 0x42);
|
||||
mm.getByte(targetaddress);
|
||||
bool inject = true;
|
||||
while (1) {
|
||||
fail::BaseListener * listener = simulator.resume();
|
||||
// finish() before FI?
|
||||
if (listener == &l_end) {
|
||||
cout << "experiment reached finish() before FI" << endl;
|
||||
handleEvent(*result, result->NOINJECTION, "time_marker reached before instr2");
|
||||
inject = false;
|
||||
break;
|
||||
} else if (listener == &bp) {
|
||||
break;
|
||||
} else {
|
||||
inject = false;
|
||||
handleEvent(*result, result->NOINJECTION, "WTF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t tb[] = {0xab, 0xbb, 0xcc, 0xdd};
|
||||
mm.setBytes(targetaddress, 4, tb);
|
||||
*((uint32_t*)(tb)) = 0; // clear array.
|
||||
// read back bytes
|
||||
mm.getBytes(targetaddress, 4, tb);
|
||||
// Next experiment
|
||||
if (!inject)
|
||||
continue;
|
||||
}
|
||||
|
||||
address_t injection_instr_absolute = param.msg.fsppilot().injection_instr_absolute();
|
||||
if (simulator.getCPU(0).getInstructionPointer() != injection_instr_absolute) {
|
||||
cout << "Invalid Injection address EIP=0x"
|
||||
<< std::hex << simulator.getCPU(0).getInstructionPointer()
|
||||
<< " != 0x" << injection_instr_absolute << std::endl;
|
||||
simulator.terminate(1);
|
||||
}
|
||||
|
||||
*/
|
||||
// Explicitly terminate, or the simulator will continue to run.
|
||||
simulator.terminate();
|
||||
/// INJECT BITFLIP:
|
||||
result->set_original_value(injectBitFlip(data_address, data_width, bit_offset));
|
||||
|
||||
simulator.clearListeners();
|
||||
simulator.addListener(&l_timeout);
|
||||
simulator.addListener(&l_trap);
|
||||
simulator.addListener(&l_positive);
|
||||
simulator.addListener(&l_negative);
|
||||
|
||||
|
||||
cout << "Resuming till the crash" << std::endl;
|
||||
// resume and wait for results
|
||||
fail::BaseListener* l = simulator.resume();
|
||||
cout << "End of execution" << std::endl;
|
||||
|
||||
// Evaluate result
|
||||
if(l == &l_positive) {
|
||||
handleEvent(*result, result->POSITIVE_MARKER, "fail_marker_positive()");
|
||||
} else if(l == &l_negative) {
|
||||
handleEvent(*result, result->NEGATIVE_MARKER, "fail_marker_negative()");
|
||||
} else if (l == &l_timeout) {
|
||||
handleEvent(*result, result->TIMEOUT, "500ms");
|
||||
} else if (l == &l_trap) {
|
||||
stringstream sstr;
|
||||
sstr << "trap #" << l_trap.getTriggerNumber();
|
||||
handleEvent(*result, result->TRAP, sstr.str());
|
||||
} else {
|
||||
handleEvent(*result, result->UNKNOWN, "UNKNOWN event");
|
||||
}
|
||||
simulator.clearListeners();
|
||||
}
|
||||
|
||||
m_jc->sendResult(param);
|
||||
}
|
||||
// Explicitly terminate, or the simulator will continue to run.
|
||||
simulator.terminate();
|
||||
}
|
||||
|
||||
|
||||
@ -9,14 +9,24 @@
|
||||
#include "util/ElfReader.hpp"
|
||||
|
||||
class VEZSExperiment : public fail::ExperimentFlow {
|
||||
fail::JobClient *m_jc;
|
||||
fail::MemoryManager& m_mm;
|
||||
fail::ElfReader m_elf;
|
||||
|
||||
fail::JobClient m_jc;
|
||||
fail::Logger m_log;
|
||||
fail::ElfReader m_elf;
|
||||
unsigned injectBitFlip(fail::address_t data_address, unsigned data_width, unsigned bitpos);
|
||||
void redecodeCurrentInstruction();
|
||||
|
||||
public:
|
||||
VEZSExperiment() : m_log("VEZS-example", false) {};
|
||||
bool run();
|
||||
VEZSExperiment() : m_mm(fail::simulator.getMemoryManager()) {
|
||||
char *server_host = getenv("FAIL_SERVER_HOST");
|
||||
if(server_host != NULL){
|
||||
this->m_jc = new fail::JobClient(std::string(server_host));
|
||||
} else {
|
||||
this->m_jc = new fail::JobClient();
|
||||
}
|
||||
};
|
||||
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif // __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||
|
||||
@ -1,24 +1,5 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
|
||||
// the task function's entry address:
|
||||
// nm -C ecc.elf|fgrep main
|
||||
#define OOSTUBS_FUNC_ENTRY 0x001009d0
|
||||
// empty function that is called explicitly when the experiment finished
|
||||
// nm -C ecc.elf|fgrep "finished()"
|
||||
#define OOSTUBS_FUNC_FINISH 0x001009d6
|
||||
// function executing HLT with no chance for further progress (after panic())
|
||||
// nm -C ecc.elf|fgrep cpu_halt
|
||||
#define OOSTUBS_FUNC_CPU_HALT 0x001009f7
|
||||
|
||||
// nm -C ecc.elf | fgrep "_TEXT_"
|
||||
#define OOSTUBS_TEXT_START 0x00100000
|
||||
#define OOSTUBS_TEXT_END 0x00100a1b
|
||||
|
||||
#define OOSTUBS_NUMINSTR 5
|
||||
|
||||
|
||||
#endif // __EXPERIMENT_INFO_HPP__
|
||||
|
||||
@ -2,11 +2,16 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "util/CommandLine.hpp"
|
||||
#include "campaign.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ChecksumOOStuBSCampaign c;
|
||||
fail::CommandLine &cmd = fail::CommandLine::Inst();
|
||||
for (int i = 1; i < argc; ++i)
|
||||
cmd.add_args(argv[i]);
|
||||
|
||||
VEZSCampaign c;
|
||||
if (fail::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
23
src/experiments/vezs-example/vezs.proto
Normal file
23
src/experiments/vezs-example/vezs.proto
Normal file
@ -0,0 +1,23 @@
|
||||
import "DatabaseCampaignMessage.proto";
|
||||
|
||||
message VEZSProtoMsg {
|
||||
required DatabaseCampaignMessage fsppilot = 1;
|
||||
|
||||
repeated group Result = 2 {
|
||||
// make these optional to reduce overhead for server->client communication
|
||||
enum ResultType {
|
||||
POSITIVE_MARKER = 1;
|
||||
NEGATIVE_MARKER = 2;
|
||||
NO_MARKER = 3;
|
||||
TIMEOUT = 4;
|
||||
TRAP = 5;
|
||||
NOINJECTION = 6;
|
||||
UNKNOWN = 7;
|
||||
}
|
||||
// result type, see above
|
||||
required ResultType resulttype = 4;
|
||||
required uint32 original_value = 5;
|
||||
required uint32 bitoffset = 6 [(sql_primary_key) = true];
|
||||
optional string details = 7;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
set(SRCS
|
||||
Importer.cc
|
||||
MemoryImporter.cc
|
||||
FullTraceImporter.cc
|
||||
)
|
||||
|
||||
if (BUILD_LLVM_DISASSEMBLER)
|
||||
|
||||
72
tools/import-trace/FullTraceImporter.cc
Normal file
72
tools/import-trace/FullTraceImporter.cc
Normal file
@ -0,0 +1,72 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/Database.hpp"
|
||||
#include "FullTraceImporter.hpp"
|
||||
|
||||
using namespace fail;
|
||||
static fail::Logger LOG("FullTraceImporter");
|
||||
|
||||
Database *db;
|
||||
|
||||
bool FullTraceImporter::handle_ip_event(simtime_t curtime, instruction_count_t instr,
|
||||
Trace_Event &ev) {
|
||||
|
||||
margin_info_t right_margin;
|
||||
right_margin.time = curtime;
|
||||
right_margin.dyninstr = instr; // !< The current instruction
|
||||
right_margin.ip = ev.ip();
|
||||
|
||||
// pass through potentially available extended trace information
|
||||
if (!add_trace_event(right_margin, right_margin, ev)) {
|
||||
LOG << "add_trace_event failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FullTraceImporter::handle_mem_event(simtime_t curtime, instruction_count_t instr,
|
||||
Trace_Event &ev) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FullTraceImporter::create_database() {
|
||||
std::stringstream create_statement;
|
||||
create_statement << "CREATE TABLE IF NOT EXISTS fulltrace ("
|
||||
" variant_id int(11) NOT NULL,"
|
||||
" instr int(10) unsigned NOT NULL,"
|
||||
" instr_absolute int(10) unsigned DEFAULT NULL,"
|
||||
" INDEX(instr),"
|
||||
" PRIMARY KEY (variant_id,instr)"
|
||||
") engine=MyISAM ";
|
||||
return db->query(create_statement.str().c_str());
|
||||
}
|
||||
|
||||
bool FullTraceImporter::clear_database() {
|
||||
std::stringstream ss;
|
||||
ss << "DELETE FROM fulltrace WHERE variant_id = " << m_variant_id;
|
||||
|
||||
bool ret = db->query(ss.str().c_str()) == 0 ? false : true;
|
||||
LOG << "deleted " << db->affected_rows() << " rows from fulltrace table" << std::endl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FullTraceImporter::add_trace_event(margin_info_t &begin, margin_info_t &end,
|
||||
Trace_Event &event, bool is_fake) {
|
||||
// Is event a fake mem-event?
|
||||
if (is_fake) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// INSERT group entry
|
||||
std::stringstream sql;
|
||||
sql << "(" << m_variant_id << "," << end.dyninstr << "," << end.ip << ")";
|
||||
|
||||
return db->insert_multiple("INSERT INTO fulltrace (variant_id, instr, instr_absolute) VALUES ", sql.str().c_str());
|
||||
}
|
||||
|
||||
bool FullTraceImporter::trace_end_reached() {
|
||||
return db->insert_multiple();
|
||||
}
|
||||
25
tools/import-trace/FullTraceImporter.hpp
Normal file
25
tools/import-trace/FullTraceImporter.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __FULL_TRACE_IMPORTER_H__
|
||||
#define __FULL_TRACE_IMPORTER_H__
|
||||
|
||||
#include "Importer.hpp"
|
||||
#include "util/CommandLine.hpp"
|
||||
|
||||
/**
|
||||
The FullTraceImporter imports every dynamic ip-event from the trace into the database.
|
||||
*/
|
||||
class FullTraceImporter : public Importer {
|
||||
|
||||
protected:
|
||||
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||
Trace_Event &ev);
|
||||
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||
Trace_Event &ev);
|
||||
virtual bool create_database();
|
||||
virtual bool clear_database();
|
||||
using Importer::add_trace_event;
|
||||
virtual bool add_trace_event(margin_info_t &begin, margin_info_t &end,
|
||||
Trace_Event &event, bool is_fake = false);
|
||||
virtual bool trace_end_reached();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -7,6 +7,7 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "MemoryImporter.hpp"
|
||||
#include "FullTraceImporter.hpp"
|
||||
|
||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||
#include "InstructionImporter.hpp"
|
||||
@ -129,6 +130,8 @@ int main(int argc, char *argv[]) {
|
||||
if (imp == "BasicImporter" || imp == "MemoryImporter" || imp == "memory" || imp == "mem") {
|
||||
imp = "MemoryImporter";
|
||||
importer = new MemoryImporter();
|
||||
} else if (imp == "FullTraceImporter") {
|
||||
importer = new FullTraceImporter();
|
||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||
} else if (imp == "InstructionImporter" || imp == "code") {
|
||||
imp = "InstructionImporter";
|
||||
|
||||
Reference in New Issue
Block a user