From 44a03590870c6c99bfb375b8cf09b5d37105610b Mon Sep 17 00:00:00 2001 From: Philip Taffner Date: Sat, 7 Dec 2013 15:55:42 +0100 Subject: [PATCH 01/13] Adds KESO garbage collector experiment Change-Id: I429b58912b46b2ab7213e18651f14f7aed303419 --- src/experiments/kesogc/CMakeLists.txt | 37 +++ src/experiments/kesogc/campaign.cc | 20 ++ src/experiments/kesogc/campaign.hpp | 24 ++ src/experiments/kesogc/experiment.cc | 327 ++++++++++++++++++++++ src/experiments/kesogc/experiment.hpp | 44 +++ src/experiments/kesogc/experimentInfo.hpp | 24 ++ src/experiments/kesogc/kesogc.proto | 31 ++ src/experiments/kesogc/main.cc | 20 ++ 8 files changed, 527 insertions(+) create mode 100644 src/experiments/kesogc/CMakeLists.txt create mode 100644 src/experiments/kesogc/campaign.cc create mode 100644 src/experiments/kesogc/campaign.hpp create mode 100644 src/experiments/kesogc/experiment.cc create mode 100644 src/experiments/kesogc/experiment.hpp create mode 100644 src/experiments/kesogc/experimentInfo.hpp create mode 100644 src/experiments/kesogc/kesogc.proto create mode 100644 src/experiments/kesogc/main.cc diff --git a/src/experiments/kesogc/CMakeLists.txt b/src/experiments/kesogc/CMakeLists.txt new file mode 100644 index 00000000..dfd5e336 --- /dev/null +++ b/src/experiments/kesogc/CMakeLists.txt @@ -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) diff --git a/src/experiments/kesogc/campaign.cc b/src/experiments/kesogc/campaign.cc new file mode 100644 index 00000000..bb7c2aef --- /dev/null +++ b/src/experiments/kesogc/campaign.cc @@ -0,0 +1,20 @@ +#include +#include + +#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); +} diff --git a/src/experiments/kesogc/campaign.hpp b/src/experiments/kesogc/campaign.hpp new file mode 100644 index 00000000..716e9666 --- /dev/null +++ b/src/experiments/kesogc/campaign.hpp @@ -0,0 +1,24 @@ +#ifndef __KESOGCCAMPAIGN_HPP__ + #define __KESOGCCAMPAIGN_HPP__ + +#include "cpn/DatabaseCampaign.hpp" +#include "comm/ExperimentData.hpp" +#include +#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__ diff --git a/src/experiments/kesogc/experiment.cc b/src/experiments/kesogc/experiment.cc new file mode 100644 index 00000000..19f60219 --- /dev/null +++ b/src/experiments/kesogc/experiment.cc @@ -0,0 +1,327 @@ +#include +#include + +// getpid +#include +#include + + +#include +#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 +#include + +#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(); +} + diff --git a/src/experiments/kesogc/experiment.hpp b/src/experiments/kesogc/experiment.hpp new file mode 100644 index 00000000..c69c4956 --- /dev/null +++ b/src/experiments/kesogc/experiment.hpp @@ -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 +#include + + +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__ diff --git a/src/experiments/kesogc/experimentInfo.hpp b/src/experiments/kesogc/experimentInfo.hpp new file mode 100644 index 00000000..bcc57e18 --- /dev/null +++ b/src/experiments/kesogc/experimentInfo.hpp @@ -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__ diff --git a/src/experiments/kesogc/kesogc.proto b/src/experiments/kesogc/kesogc.proto new file mode 100644 index 00000000..03420a40 --- /dev/null +++ b/src/experiments/kesogc/kesogc.proto @@ -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; + } +} diff --git a/src/experiments/kesogc/main.cc b/src/experiments/kesogc/main.cc new file mode 100644 index 00000000..c00c7b3f --- /dev/null +++ b/src/experiments/kesogc/main.cc @@ -0,0 +1,20 @@ +#include +#include + +#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; + } +} From 7b124421179c51069c87934abf791fae4f3d4b4e Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 12 Mar 2014 13:15:33 +0100 Subject: [PATCH 02/13] util: find libdwarf/libelf via cmake itself Instead of hardcoded -lelf/-ldwarf use cmake modules FindLibElf/-Dwarf and link the found libraries accordingly. This enables the user to have those libs in arbitrary locations and link them from there. Change-Id: I2cea3ef648a46f11b0d49d2fe0b006f76a9d4140 --- src/core/util/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index b03de716..3c339ce5 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -54,6 +54,12 @@ endif() 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,7 +73,7 @@ mark_as_advanced(FAIL_OBJDUMP) add_library(fail-util ${SRCS}) add_dependencies(fail-util fail-comm) -target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${ZLIB_LIBRARIES} dwarf elf) +target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${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) From da839c9765ef69037b19c517de9f4734f64ab10c Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 12 Mar 2014 13:15:33 +0100 Subject: [PATCH 03/13] util: find libdwarf/libelf via cmake itself Instead of hardcoded -lelf/-ldwarf use cmake modules FindLibElf/-Dwarf and link the found libraries accordingly. This enables the user to have those libs in arbitrary locations and link them from there. Change-Id: I2cea3ef648a46f11b0d49d2fe0b006f76a9d4140 --- src/core/util/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index 8492d0d9..5544a62f 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -54,6 +54,12 @@ endif() 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") @@ -68,7 +74,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 ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${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) From 7694195f1bfde789e73ade3f92aa1356767fb4bb Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Tue, 1 Apr 2014 15:55:57 +0200 Subject: [PATCH 04/13] cmake: added missing link-time dependency efw->util Change-Id: Iea812ed881f67e452827a718a52517c7328b0729 --- src/core/efw/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/efw/CMakeLists.txt b/src/core/efw/CMakeLists.txt index 3034c840..e0e2fe2c 100644 --- a/src/core/efw/CMakeLists.txt +++ b/src/core/efw/CMakeLists.txt @@ -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}) From 442069dd457c04abb97725b7e5ee0657a067a080 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Wed, 2 Apr 2014 10:42:46 +0200 Subject: [PATCH 05/13] cmake: added missing link-time dependency cpn->util (for synchronized queue implementations) Change-Id: I7b32273b8e76a7b7921af117fdf3ca5af2f42553 --- src/core/cpn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/cpn/CMakeLists.txt b/src/core/cpn/CMakeLists.txt index 79fac5ba..f62c2c95 100644 --- a/src/core/cpn/CMakeLists.txt +++ b/src/core/cpn/CMakeLists.txt @@ -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) From 940fa6035d6e23bb51fcf5557bea8ab8ceeac3c7 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Tue, 1 Apr 2014 15:59:43 +0200 Subject: [PATCH 06/13] ecos: record simulated runtime As the eCos kernel tests do not sufficiently check for failures, a (compared to the golden run) measurably *reduced* simulation time can be used as an indication for SDC. Change-Id: I303f6c3f7ef56cb691c1f226eff74d113dd16629 --- .../ecos_kernel_test/ecos_kernel_test.proto | 9 +++-- .../ecos_kernel_test/experiment.cc | 39 ++++++++++++------- .../ecos_kernel_test/experiment.hpp | 4 +- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/experiments/ecos_kernel_test/ecos_kernel_test.proto b/src/experiments/ecos_kernel_test/ecos_kernel_test.proto index 7cf96dd4..41e17b21 100644 --- a/src/experiments/ecos_kernel_test/ecos_kernel_test.proto +++ b/src/experiments/ecos_kernel_test/ecos_kernel_test.proto @@ -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; } } diff --git a/src/experiments/ecos_kernel_test/experiment.cc b/src/experiments/ecos_kernel_test/experiment.cc index b484b3d7..79a902c2 100644 --- a/src/experiments/ecos_kernel_test/experiment.cc +++ b/src/experiments/ecos_kernel_test/experiment.cc @@ -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; diff --git a/src/experiments/ecos_kernel_test/experiment.hpp b/src/experiments/ecos_kernel_test/experiment.hpp index 9ce811ee..8b83a93c 100644 --- a/src/experiments/ecos_kernel_test/experiment.hpp +++ b/src/experiments/ecos_kernel_test/experiment.hpp @@ -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 = ""); From ba774a258c92c8c466e23535cf1b167b8c3c80c6 Mon Sep 17 00:00:00 2001 From: Florian Lukas Date: Thu, 3 Apr 2014 14:56:41 +0200 Subject: [PATCH 07/13] util/llvmdisassembler: fix section end symbols Somehow, while iterating symbols in a section, it can happen that the last symbol start address is equal to the section size, which means it is beyond the section end. In this case the LLVM getInstruction() method does not return a failure, but a zero-size instruction, resulting in an infinite loop. Now, if beyond section limits, the iteration is aborted. Additionally, an assertion checks for disassembled zero-size instructions. Change-Id: Id8a355475161150d3ee919cd6cf603d4ff26b228 --- src/core/util/llvmdisassembler/LLVMDisassembler.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp index 6e2977aa..c5d03da7 100644 --- a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp +++ b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp @@ -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) { From 11f77f0228204140f6b04780c74af29ddc111be6 Mon Sep 17 00:00:00 2001 From: Richard Hellwig Date: Sat, 5 Apr 2014 16:57:13 +0200 Subject: [PATCH 08/13] tools/import-trace: FullTraceImporter added The FullTraceImporter imports every ip-event into the database. Change-Id: I1c0ce2a0aae72dcd925930861780f2719d37b985 --- tools/import-trace/CMakeLists.txt | 1 + tools/import-trace/FullTraceImporter.cc | 72 ++++++++++++++++++++++++ tools/import-trace/FullTraceImporter.hpp | 25 ++++++++ tools/import-trace/main.cc | 3 + 4 files changed, 101 insertions(+) create mode 100644 tools/import-trace/FullTraceImporter.cc create mode 100644 tools/import-trace/FullTraceImporter.hpp diff --git a/tools/import-trace/CMakeLists.txt b/tools/import-trace/CMakeLists.txt index 583e397d..b8a04e49 100644 --- a/tools/import-trace/CMakeLists.txt +++ b/tools/import-trace/CMakeLists.txt @@ -1,6 +1,7 @@ set(SRCS Importer.cc MemoryImporter.cc + FullTraceImporter.cc ) if (BUILD_LLVM_DISASSEMBLER) diff --git a/tools/import-trace/FullTraceImporter.cc b/tools/import-trace/FullTraceImporter.cc new file mode 100644 index 00000000..5c4a939b --- /dev/null +++ b/tools/import-trace/FullTraceImporter.cc @@ -0,0 +1,72 @@ +#include +#include + +#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(); +} diff --git a/tools/import-trace/FullTraceImporter.hpp b/tools/import-trace/FullTraceImporter.hpp new file mode 100644 index 00000000..2db2b193 --- /dev/null +++ b/tools/import-trace/FullTraceImporter.hpp @@ -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 diff --git a/tools/import-trace/main.cc b/tools/import-trace/main.cc index 14832c82..eb2e71cb 100644 --- a/tools/import-trace/main.cc +++ b/tools/import-trace/main.cc @@ -7,6 +7,7 @@ #include #include #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"; From 1d42007168a28bfa146cd3548b631a362fb21b77 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Tue, 8 Apr 2014 15:42:56 +0200 Subject: [PATCH 09/13] vezs-example: update experiment for new VEZS lecture Change-Id: Ifea2169ceb83135e6e53663d077f8f574539f512 --- src/experiments/vezs-example/CMakeLists.txt | 19 +- src/experiments/vezs-example/campaign.cc | 20 ++ src/experiments/vezs-example/campaign.hpp | 24 ++ src/experiments/vezs-example/experiment.cc | 258 ++++++++++++++---- src/experiments/vezs-example/experiment.hpp | 20 +- .../vezs-example/experimentInfo.hpp | 19 -- src/experiments/vezs-example/main.cc | 7 +- src/experiments/vezs-example/vezs.proto | 23 ++ 8 files changed, 299 insertions(+), 91 deletions(-) create mode 100644 src/experiments/vezs-example/campaign.cc create mode 100644 src/experiments/vezs-example/campaign.hpp create mode 100644 src/experiments/vezs-example/vezs.proto diff --git a/src/experiments/vezs-example/CMakeLists.txt b/src/experiments/vezs-example/CMakeLists.txt index 81320d74..48e30790 100644 --- a/src/experiments/vezs-example/CMakeLists.txt +++ b/src/experiments/vezs-example/CMakeLists.txt @@ -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) diff --git a/src/experiments/vezs-example/campaign.cc b/src/experiments/vezs-example/campaign.cc new file mode 100644 index 00000000..5066a812 --- /dev/null +++ b/src/experiments/vezs-example/campaign.cc @@ -0,0 +1,20 @@ +#include +#include + +#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); +} diff --git a/src/experiments/vezs-example/campaign.hpp b/src/experiments/vezs-example/campaign.hpp new file mode 100644 index 00000000..e7fae4c2 --- /dev/null +++ b/src/experiments/vezs-example/campaign.hpp @@ -0,0 +1,24 @@ +#ifndef __KESOGCCAMPAIGN_HPP__ + #define __KESOGCCAMPAIGN_HPP__ + +#include "cpn/DatabaseCampaign.hpp" +#include "comm/ExperimentData.hpp" +#include +#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__ diff --git a/src/experiments/vezs-example/experiment.cc b/src/experiments/vezs-example/experiment.cc index 37b7e14b..d5267793 100644 --- a/src/experiments/vezs-example/experiment.cc +++ b/src/experiments/vezs-example/experiment.cc @@ -1,3 +1,4 @@ +#include #include #include @@ -8,87 +9,228 @@ #include #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 +#include +#include +#include + +#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(); } + diff --git a/src/experiments/vezs-example/experiment.hpp b/src/experiments/vezs-example/experiment.hpp index 5045cba4..899e833c 100644 --- a/src/experiments/vezs-example/experiment.hpp +++ b/src/experiments/vezs-example/experiment.hpp @@ -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__ diff --git a/src/experiments/vezs-example/experimentInfo.hpp b/src/experiments/vezs-example/experimentInfo.hpp index bcc57e18..de63bb28 100644 --- a/src/experiments/vezs-example/experimentInfo.hpp +++ b/src/experiments/vezs-example/experimentInfo.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__ diff --git a/src/experiments/vezs-example/main.cc b/src/experiments/vezs-example/main.cc index 16605ac5..2afd1c0f 100644 --- a/src/experiments/vezs-example/main.cc +++ b/src/experiments/vezs-example/main.cc @@ -2,11 +2,16 @@ #include #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 { diff --git a/src/experiments/vezs-example/vezs.proto b/src/experiments/vezs-example/vezs.proto new file mode 100644 index 00000000..c63ef553 --- /dev/null +++ b/src/experiments/vezs-example/vezs.proto @@ -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; + } +} From c6344af1891efcadea22109e50127a0f3b13d5e3 Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 26 Feb 2014 15:05:28 +0100 Subject: [PATCH 10/13] Database: commandline option for alt. config file This change adds an optional command line argument "--database-option-file", which can be used to override the default database configuration file ~/.my.cnf Change-Id: I5c71523e1c31dead26f3fedb0ca7354ca99892d4 --- src/core/util/Database.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/core/util/Database.cc b/src/core/util/Database.cc index 41f8eed6..2382f860 100644 --- a/src/core/util/Database.cc +++ b/src/core/util/Database.cc @@ -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 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); From 9113d7c2fa468a8fe7afb0c34ab4dde34a859b58 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 30 Mar 2014 18:16:13 +0200 Subject: [PATCH 11/13] cmake: find libiberty headers via cmake module The libiberty headers moved from /usr/include (and a part of binutils-dev) to /usr/include/libiberty (libiberty-dev) between Ubuntu 13.10 and 14.04, which made a proper cmake search module necessary. Searching still continues working well on Debian 7. Change-Id: I324e5ccb847e4664442d6fa7d7a027705a4f0587 --- cmake/FindLibIberty.cmake | 42 ++++++++++++++++++++++++++++++++++++ doc/how-to-build.txt | 2 +- src/core/util/CMakeLists.txt | 10 +++------ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 cmake/FindLibIberty.cmake diff --git a/cmake/FindLibIberty.cmake b/cmake/FindLibIberty.cmake new file mode 100644 index 00000000..a1ab1815 --- /dev/null +++ b/cmake/FindLibIberty.cmake @@ -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() diff --git a/doc/how-to-build.txt b/doc/how-to-build.txt index dd7fa8b5..4a49a25d 100644 --- a/doc/how-to-build.txt +++ b/doc/how-to-build.txt @@ -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 ; nightlies can be downloaded from . Make sure you use the 64-bit version if running diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index 5544a62f..bc3c3d1e 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -43,12 +43,8 @@ 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) @@ -74,7 +70,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} ${LIBDWARF_LIBRARIES} ${LIBELF_LIBRARIES}) +target_link_libraries(fail-util ${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) From dad8a54e090360f8315d2ae6308b3ff19661b1d8 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 30 Mar 2014 18:17:40 +0200 Subject: [PATCH 12/13] cmake: disable -Wunused-local-typedefs for gcc 4.8+ -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. Change-Id: I79748d5f049e269053b26935cc7a641caeb6dcba --- cmake/compilerconfig.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/compilerconfig.cmake b/cmake/compilerconfig.cmake index 926fd283..91141b1b 100644 --- a/cmake/compilerconfig.cmake +++ b/cmake/compilerconfig.cmake @@ -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") From ffda979e290d1bde64213a82ed4f4442e8fc0259 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 30 Mar 2014 18:33:40 +0200 Subject: [PATCH 13/13] cmake: prefer LLVM 3.4 over older versions Change-Id: Id10afc70023c4b592806bb4276d3c63be20ff7f7 --- cmake/FindLLVM.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindLLVM.cmake b/cmake/FindLLVM.cmake index 88d4a8bb..e13cda05 100644 --- a/cmake/FindLLVM.cmake +++ b/cmake/FindLLVM.cmake @@ -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")