From 010d4a892d832c72edcdd1b4f5e855124fe483cc Mon Sep 17 00:00:00 2001 From: Florian Lukas Date: Wed, 12 Mar 2014 11:25:54 +0100 Subject: [PATCH 01/12] DatabaseCampaign: fix finished experiments SQL The database queries to fetch all unfinished experiments were broken. The server tried to insert all finished pilot_ids into the temporary result_ids table and then discard all experiments which have the correct (finished) count of IDs in this table. This cannot work as the pilot_id is the only column of result_ids and must be a unique primary key. As a fix, the count of results is stored as a second field in result_ids and the result table is now joined against result_ids to check this field. Change-Id: I6a9fb774825f0cc4ce104c6e51d7b2fe16957aec --- src/core/cpn/DatabaseCampaign.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/cpn/DatabaseCampaign.cc b/src/core/cpn/DatabaseCampaign.cc index 365a896b..b9832275 100644 --- a/src/core/cpn/DatabaseCampaign.cc +++ b/src/core/cpn/DatabaseCampaign.cc @@ -134,14 +134,15 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) { * other, collect_result_thread() may even starve until the memory for the * JobServer's "done" queue runs out, resulting in a crash and the loss of * all queued results. */ - db->query("CREATE TEMPORARY TABLE IF NOT EXISTS result_ids (pilot_id INT NOT NULL PRIMARY KEY)"); + db->query("CREATE TEMPORARY TABLE IF NOT EXISTS result_ids (pilot_id INT NOT NULL PRIMARY KEY, count INT NOT NULL)"); db->query("TRUNCATE TABLE result_ids"); std::stringstream ss; ss << "INSERT INTO result_ids " - << "SELECT r.pilot_id FROM " << db_connect.result_table() << " r " + << "SELECT r.pilot_id, COUNT(*) FROM " << db_connect.result_table() << " r " << "JOIN fsppilot p ON r.pilot_id = p.id " << "WHERE p.fspmethod_id = " << fspmethod_id - << " AND p.variant_id = " << variant.id; + << " AND p.variant_id = " << variant.id + << " GROUP BY r.pilot_id"; db->query(ss.str().c_str()); ss.str(""); @@ -149,10 +150,12 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) { int experiment_count; std::string sql_select = "SELECT p.id, p.fspmethod_id, p.variant_id, p.injection_instr, p.injection_instr_absolute, p.data_address, p.data_width "; ss << " FROM fsppilot p " + << " LEFT JOIN result_ids r ON r.pilot_id = p.id" << " WHERE p.fspmethod_id = " << fspmethod_id << " AND p.variant_id = " << variant.id - << " AND (SELECT COUNT(*) FROM result_ids as r WHERE r.pilot_id = p.id)" + << " AND (r.count" << " < " << expected_number_of_results(variant.variant, variant.benchmark) + << " OR r.count IS NULL)" << " ORDER BY p.injection_instr"; std::string sql_body = ss.str(); From b7ff284d54faf5afcdcc5edee212d73dd02007f3 Mon Sep 17 00:00:00 2001 From: Christoph Borchert Date: Mon, 3 Mar 2014 15:45:27 +0100 Subject: [PATCH 02/12] generic-tracing: add configuration dependencies Added hint: Use /dev/null if no state is required Change-Id: I76a935f88e6a7a8f707970797d508dad3a961ab5 --- src/experiments/generic-tracing/experiment.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/experiments/generic-tracing/experiment.cc b/src/experiments/generic-tracing/experiment.cc index a2121bb2..fd95128f 100644 --- a/src/experiments/generic-tracing/experiment.cc +++ b/src/experiments/generic-tracing/experiment.cc @@ -20,6 +20,11 @@ using namespace std; using namespace fail; +// Check if configuration dependencies are satisfied: +#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_SAVE) + #error This experiment needs: breakpoints, and save. Enable these in the configuration. +#endif + void GenericTracing::parseOptions() { CommandLine &cmd = CommandLine::Inst(); cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... \n\n"); @@ -36,7 +41,8 @@ void GenericTracing::parseOptions() { "-S,--save-symbol \tELF symbol to save the state of the machine " "(exists for backward compatibility, must be identical to --start-symbol if used)\n"); CommandLine::option_handle STATE_FILE = cmd.addOption("f", "state-file", Arg::Required, - "-f,--state-file \tFile/dir to save the state to (default: state)"); + "-f,--state-file \tFile/dir to save the state to (default: state). " + "Use /dev/null if no state is required"); CommandLine::option_handle TRACE_FILE = cmd.addOption("t", "trace-file", Arg::Required, "-t,--trace-file \tFile to save the execution trace to (default: trace.pb)\n"); From 5567c595fb4e6a5c82a60c9c07cbaa7719600a89 Mon Sep 17 00:00:00 2001 From: Florian Lukas Date: Wed, 12 Mar 2014 13:34:32 +0100 Subject: [PATCH 03/12] DatabaseCampaign: experiment completion checks If the queue for outbound jobs is not unlimited, experiment rows are fetched from the DB server continuously as experiments finish. When this takes too long the connection to the DB server can be lost. The code did not check for a mysql_error and assumed the result set was fetched completely, thus skipping a potentially large amount of experiments (in our case only ~20000 of 400000+ experiments were run). This change adds checks to determine if the result fetch loop was finished due to an error and checks the sent pilot count to the unfinished experiment count. Additionally, the mysql result object is correctly freed. The underlying problem of MySQL connection loss can hopefully be prevented by increasing timeouts in the MySQL config as described in doc/how-to-build.txt. To prevent the problem from occurring when this is forgotten, this change reverts the default job queue length to be unlimited (SERVER_OUT_QUEUE_SIZE=0), at the cost of increased memory usage. Change-Id: I09d9faddd8190c6dd5fbe733a0679a733d5837ec --- src/core/config/CMakeLists.txt | 2 +- src/core/cpn/DatabaseCampaign.cc | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/config/CMakeLists.txt b/src/core/config/CMakeLists.txt index dc30d259..a2b181b6 100644 --- a/src/core/config/CMakeLists.txt +++ b/src/core/config/CMakeLists.txt @@ -25,7 +25,7 @@ OPTION(CONFIG_FAST_BREAKPOINTS "Enable fast breakpoints (requires break OPTION(CONFIG_FAST_WATCHPOINTS "Enable fast watchpoints (requires memory access events to be enabled)" OFF) SET(SERVER_COMM_HOSTNAME "localhost" CACHE STRING "Job-server hostname or IP") SET(SERVER_COMM_TCP_PORT "1111" CACHE STRING "Job-server TCP port") -SET(SERVER_OUT_QUEUE_SIZE "10000" CACHE STRING "Queue size for outbound jobs (0 = unlimited)") +SET(SERVER_OUT_QUEUE_SIZE "0" CACHE STRING "Queue size for outbound jobs (0 = unlimited)") SET(SERVER_PERF_LOG_PATH "perf.log" CACHE STRING "A file name for storing the server's performance log (CSV)") SET(SERVER_PERF_STEPPING_SEC "1" CACHE STRING "Stepping of performance measurements in seconds") SET(CLIENT_RAND_BACKOFF_TSTART "3" CACHE STRING "Lower limit of client's backoff phase in seconds") diff --git a/src/core/cpn/DatabaseCampaign.cc b/src/core/cpn/DatabaseCampaign.cc index b9832275..5e32d81d 100644 --- a/src/core/cpn/DatabaseCampaign.cc +++ b/src/core/cpn/DatabaseCampaign.cc @@ -200,6 +200,16 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) { log_send << "pushed " << sent_pilots << " pilots into the queue" << std::endl; } } + + if (*mysql_error(db->getHandle())) { + log_send << "MYSQL ERROR: " << mysql_error(db->getHandle()) << std::endl; + return false; + } + + assert(experiment_count == sent_pilots && "ERROR: not all unfinished experiments pushed to queue"); + + mysql_free_result(pilots); + return true; } From 396e00ce59f3a55fa342e787238eda00b9035277 Mon Sep 17 00:00:00 2001 From: Florian Lukas Date: Tue, 18 Feb 2014 17:20:21 +0100 Subject: [PATCH 04/12] cmake: static library dependencies CMake does not support linker groups, which were used to "automatically" fix circular dependencies between different static FAIL* libraries and the ordering of dynamic external libraries broke linking. CMake can however correctly invoke the linker if dependencies are decribed correctly (even if circular). This required changing all add_dependencies calls between libraries to target_link_libraries (which creates a link-time dependency) and linking all experiments to fail-sal. Change-Id: I3a0d5dddb9b3d963ef538814e20d6b3de85d4ec5 --- src/CMakeLists.txt | 2 +- src/core/efw/CMakeLists.txt | 1 + src/core/sal/CMakeLists.txt | 6 +++++- src/core/util/CMakeLists.txt | 1 + src/core/util/llvmdisassembler/CMakeLists.txt | 2 +- src/experiments/checksum-oostubs/CMakeLists.txt | 3 ++- src/experiments/cool-checksum/CMakeLists.txt | 3 ++- src/experiments/cored-voter/CMakeLists.txt | 1 + src/experiments/dciao-kernelstructs/CMakeLists.txt | 1 + src/experiments/ecos_kernel_test/CMakeLists.txt | 3 ++- src/experiments/ezs-logger/CMakeLists.txt | 1 + src/experiments/generic-tracing/CMakeLists.txt | 3 ++- src/experiments/kesorefs/CMakeLists.txt | 1 + src/experiments/l4-sys/CMakeLists.txt | 1 + src/experiments/mh-test-campaign/CMakeLists.txt | 1 + src/experiments/nanojpeg/CMakeLists.txt | 3 ++- src/experiments/rampage/CMakeLists.txt | 1 + src/experiments/tracing-test/CMakeLists.txt | 2 +- src/experiments/vezs-example/CMakeLists.txt | 1 + src/experiments/weather-monitor-gem5/CMakeLists.txt | 3 ++- src/experiments/weather-monitor/CMakeLists.txt | 3 ++- src/plugins/tracing/CMakeLists.txt | 3 +-- 22 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff878659..4d84ce83 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,4 +45,4 @@ set(experiment_libraries "") foreach(exp_or_plugin ${EXPERIMENTS_ACTIVATED} ${PLUGINS_ACTIVATED}) set(experiment_libraries ${experiment_libraries} fail-${exp_or_plugin}) endforeach(exp_or_plugin) -target_link_libraries(fail -Wl,-start-group fail-sal fail-cpn fail-efw fail-comm fail-util ${experiment_libraries} -Wl,-end-group) +target_link_libraries(fail fail-sal fail-cpn fail-efw fail-comm fail-util ${experiment_libraries}) diff --git a/src/core/efw/CMakeLists.txt b/src/core/efw/CMakeLists.txt index 939e6633..3034c840 100644 --- a/src/core/efw/CMakeLists.txt +++ b/src/core/efw/CMakeLists.txt @@ -8,6 +8,7 @@ set(SRCS add_library(fail-efw ${SRCS}) add_dependencies(fail-efw fail-comm) +target_link_libraries(fail-efw fail-comm) find_package(LibPCL REQUIRED) include_directories(${LIBPCL_INCLUDE_DIRS}) diff --git a/src/core/sal/CMakeLists.txt b/src/core/sal/CMakeLists.txt index a3ee96d7..30d42e9e 100644 --- a/src/core/sal/CMakeLists.txt +++ b/src/core/sal/CMakeLists.txt @@ -102,4 +102,8 @@ endif(CONFIG_FAST_BREAKPOINTS) add_library(fail-sal ${SRCS}) -add_dependencies(fail-sal fail-efw) +target_link_libraries(fail-sal fail-efw fail-util) + +foreach(exp ${EXPERIMENTS_ACTIVATED}) + target_link_libraries(fail-sal fail-${exp}) +endforeach() diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index b03de716..8492d0d9 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -67,6 +67,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) 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) diff --git a/src/core/util/llvmdisassembler/CMakeLists.txt b/src/core/util/llvmdisassembler/CMakeLists.txt index 94665f29..80f52b1d 100644 --- a/src/core/util/llvmdisassembler/CMakeLists.txt +++ b/src/core/util/llvmdisassembler/CMakeLists.txt @@ -15,7 +15,7 @@ include(FindLLVM) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS} -fno-rtti" ) add_library(fail-llvmdisassembler ${SRCS}) -add_dependencies(fail-llvmdisassembler fail-sal) +target_link_libraries(fail-llvmdisassembler fail-sal) target_link_libraries(fail-llvmdisassembler ${LLVM_LIBS} ${LLVM_LDFLAGS} ) ### Tests diff --git a/src/experiments/checksum-oostubs/CMakeLists.txt b/src/experiments/checksum-oostubs/CMakeLists.txt index ae411697..47c24345 100644 --- a/src/experiments/checksum-oostubs/CMakeLists.txt +++ b/src/experiments/checksum-oostubs/CMakeLists.txt @@ -25,7 +25,8 @@ 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-tracing fail-comm) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/cool-checksum/CMakeLists.txt b/src/experiments/cool-checksum/CMakeLists.txt index a45f3b4d..a169155f 100644 --- a/src/experiments/cool-checksum/CMakeLists.txt +++ b/src/experiments/cool-checksum/CMakeLists.txt @@ -25,7 +25,8 @@ 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-tracing fail-comm) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/cored-voter/CMakeLists.txt b/src/experiments/cored-voter/CMakeLists.txt index 684d21a0..986915e9 100644 --- a/src/experiments/cored-voter/CMakeLists.txt +++ b/src/experiments/cored-voter/CMakeLists.txt @@ -26,6 +26,7 @@ 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} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} fail-llvmdisassembler) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/dciao-kernelstructs/CMakeLists.txt b/src/experiments/dciao-kernelstructs/CMakeLists.txt index a14aacf7..9e34be8e 100644 --- a/src/experiments/dciao-kernelstructs/CMakeLists.txt +++ b/src/experiments/dciao-kernelstructs/CMakeLists.txt @@ -29,6 +29,7 @@ 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} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/ecos_kernel_test/CMakeLists.txt b/src/experiments/ecos_kernel_test/CMakeLists.txt index 7546f9c6..360fad89 100644 --- a/src/experiments/ecos_kernel_test/CMakeLists.txt +++ b/src/experiments/ecos_kernel_test/CMakeLists.txt @@ -29,7 +29,8 @@ 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-tracing fail-comm) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} ${MYSQL_LIBRARIES}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/ezs-logger/CMakeLists.txt b/src/experiments/ezs-logger/CMakeLists.txt index b66af55e..9dbdcb77 100644 --- a/src/experiments/ezs-logger/CMakeLists.txt +++ b/src/experiments/ezs-logger/CMakeLists.txt @@ -16,5 +16,6 @@ set(MY_CAMPAIGN_SRCS ## Build library add_library(fail-${EXPERIMENT_NAME} ${MY_CAMPAIGN_SRCS}) add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME}) diff --git a/src/experiments/generic-tracing/CMakeLists.txt b/src/experiments/generic-tracing/CMakeLists.txt index 76d1912b..1bfc812a 100644 --- a/src/experiments/generic-tracing/CMakeLists.txt +++ b/src/experiments/generic-tracing/CMakeLists.txt @@ -14,4 +14,5 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) ## Build library add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) -add_dependencies(fail-${EXPERIMENT_NAME} fail-tracing) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) diff --git a/src/experiments/kesorefs/CMakeLists.txt b/src/experiments/kesorefs/CMakeLists.txt index 37298030..8602c3ed 100644 --- a/src/experiments/kesorefs/CMakeLists.txt +++ b/src/experiments/kesorefs/CMakeLists.txt @@ -29,6 +29,7 @@ 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} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/l4-sys/CMakeLists.txt b/src/experiments/l4-sys/CMakeLists.txt index b14e1b20..4a0589e8 100644 --- a/src/experiments/l4-sys/CMakeLists.txt +++ b/src/experiments/l4-sys/CMakeLists.txt @@ -38,6 +38,7 @@ find_package(LibUdis86 REQUIRED) include_directories(${LIBUDIS86_INCLUDE_DIRS}) link_directories(${LIBUDIS86_LINK_DIRS}) add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${LIBUDIS86_LIBRARIES} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/mh-test-campaign/CMakeLists.txt b/src/experiments/mh-test-campaign/CMakeLists.txt index 0f01e761..1c33ac26 100644 --- a/src/experiments/mh-test-campaign/CMakeLists.txt +++ b/src/experiments/mh-test-campaign/CMakeLists.txt @@ -26,6 +26,7 @@ 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} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/nanojpeg/CMakeLists.txt b/src/experiments/nanojpeg/CMakeLists.txt index 993bae8e..10fe4f99 100644 --- a/src/experiments/nanojpeg/CMakeLists.txt +++ b/src/experiments/nanojpeg/CMakeLists.txt @@ -39,7 +39,8 @@ link_directories(${LIBUDIS86_LINK_DIRS}) ## Build library add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) -add_dependencies(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${LIBUDIS86_LIBRARIES} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/rampage/CMakeLists.txt b/src/experiments/rampage/CMakeLists.txt index e06f9396..8c461281 100644 --- a/src/experiments/rampage/CMakeLists.txt +++ b/src/experiments/rampage/CMakeLists.txt @@ -27,6 +27,7 @@ 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} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/tracing-test/CMakeLists.txt b/src/experiments/tracing-test/CMakeLists.txt index fe8c210f..bfe7d9b0 100644 --- a/src/experiments/tracing-test/CMakeLists.txt +++ b/src/experiments/tracing-test/CMakeLists.txt @@ -14,4 +14,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) ## Build library add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) -add_dependencies(fail-${EXPERIMENT_NAME} fail-tracing) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing) diff --git a/src/experiments/vezs-example/CMakeLists.txt b/src/experiments/vezs-example/CMakeLists.txt index 071ad8e6..81320d74 100644 --- a/src/experiments/vezs-example/CMakeLists.txt +++ b/src/experiments/vezs-example/CMakeLists.txt @@ -26,6 +26,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) ## 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} fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/weather-monitor-gem5/CMakeLists.txt b/src/experiments/weather-monitor-gem5/CMakeLists.txt index 2ba91b8a..659f9e19 100644 --- a/src/experiments/weather-monitor-gem5/CMakeLists.txt +++ b/src/experiments/weather-monitor-gem5/CMakeLists.txt @@ -26,7 +26,8 @@ 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-tracing fail-comm) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/experiments/weather-monitor/CMakeLists.txt b/src/experiments/weather-monitor/CMakeLists.txt index f82508ae..0d95b4ac 100644 --- a/src/experiments/weather-monitor/CMakeLists.txt +++ b/src/experiments/weather-monitor/CMakeLists.txt @@ -26,7 +26,8 @@ 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-tracing fail-comm) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters diff --git a/src/plugins/tracing/CMakeLists.txt b/src/plugins/tracing/CMakeLists.txt index f1dbd2d9..d37dc373 100644 --- a/src/plugins/tracing/CMakeLists.txt +++ b/src/plugins/tracing/CMakeLists.txt @@ -9,5 +9,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) ## Build library add_library(fail-${PLUGIN_NAME} ${MY_PLUGIN_SRCS}) add_dependencies(fail-${PLUGIN_NAME} fail-comm) -target_link_libraries(fail-${PLUGIN_NAME}) - +target_link_libraries(fail-${PLUGIN_NAME} fail-sal fail-cpn fail-efw fail-comm) From 21f5f681e0bb10391334a9c291aafaad1c96d0f7 Mon Sep 17 00:00:00 2001 From: Florian Lukas Date: Wed, 26 Feb 2014 14:10:44 +0100 Subject: [PATCH 05/12] core/sal: add x86 control and segment registers new register type RT_CONTROL: CR0, CR2, CR3, CR4 new register type RT_SEGMENT: CS, DS, ES, FS, GS, SS Reading/writing is mostly untested except for CR3... Change-Id: I0d0fba4a1669153ab2577e82ab64a04cf2bbfb94 --- src/core/sal/Register.hpp | 2 + src/core/sal/bochs/BochsCPU.cc | 110 +++++++++++++++++++++++++++ src/core/sal/x86/X86Architecture.cc | 42 ++++++++++ src/core/sal/x86/X86Architecture.hpp | 15 +++- 4 files changed, 168 insertions(+), 1 deletion(-) diff --git a/src/core/sal/Register.hpp b/src/core/sal/Register.hpp index 1831be0d..9935d598 100644 --- a/src/core/sal/Register.hpp +++ b/src/core/sal/Register.hpp @@ -24,6 +24,8 @@ enum RegisterType { RT_FP, //!< floating point register RT_IP, //!< program counter / instruction pointer RT_ST, //!< status register + RT_CONTROL, //!< control registers + RT_SEGMENT, //!< segmentation registers RT_TRACE //!< registers to be recorded in an extended trace }; diff --git a/src/core/sal/bochs/BochsCPU.cc b/src/core/sal/bochs/BochsCPU.cc index 4eb0a544..a1868bb7 100644 --- a/src/core/sal/bochs/BochsCPU.cc +++ b/src/core/sal/bochs/BochsCPU.cc @@ -14,6 +14,55 @@ regdata_t BochsCPU::getRegisterContent(const Register* reg) const return static_cast(BX_CPU(id)->read_eflags()); } + // untested + if (reg->getId() == RID_CR0) { // CR0 register? + return static_cast(BX_CPU(id)->read_CR0()); + } + + // untested + if (reg->getId() == RID_CR2) { // CR2 register? + return static_cast(BX_CPU(id)->cr2); + } + + if (reg->getId() == RID_CR3) { // CR3 register? + return static_cast(BX_CPU(id)->cr3); + } + + // untested + if (reg->getId() == RID_CR4) { // CR4 register? + return static_cast(BX_CPU(id)->read_CR4()); + } + + // untested + if (reg->getId() == RID_CS) { // CS register? + return static_cast(BX_CPU(id)->sregs[BX_SEG_REG_CS].selector.value); + } + + // untested + if (reg->getId() == RID_DS) { // DS register? + return static_cast(BX_CPU(id)->sregs[BX_SEG_REG_DS].selector.value); + } + + // untested + if (reg->getId() == RID_ES) { // ES register? + return static_cast(BX_CPU(id)->sregs[BX_SEG_REG_ES].selector.value); + } + + // untested + if (reg->getId() == RID_FS) { // FS register? + return static_cast(BX_CPU(id)->sregs[BX_SEG_REG_FS].selector.value); + } + + // untested + if (reg->getId() == RID_GS) { // GS register? + return static_cast(BX_CPU(id)->sregs[BX_SEG_REG_GS].selector.value); + } + + // untested + if (reg->getId() == RID_SS) { // SS register? + return static_cast(BX_CPU(id)->sregs[BX_SEG_REG_SS].selector.value); + } + #ifdef SIM_SUPPORT_64 if (reg->getId() == RID_PC) // program counter? return static_cast(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx); @@ -45,6 +94,67 @@ void BochsCPU::setRegisterContent(const Register* reg, regdata_t value) return; } + #ifndef __puma + // untested + if (reg->getId() == RID_CR0) { // CR0 register? + BX_CPU(id)->SetCR0(value); + return; + } + + // untested + if (reg->getId() == RID_CR2) { // CR2 register? + BX_CPU(id)->cr2 = value; + return; + } + + if (reg->getId() == RID_CR3) { // CR3 register? + BX_CPU(id)->SetCR3(value); + return; + } + + // untested + if (reg->getId() == RID_CR4) { // CR4 register? + BX_CPU(id)->SetCR4(value); + return; + } + + // untested + if (reg->getId() == RID_CS) { // CS register? + BX_CPU(id)->load_seg_reg(&BX_CPU(id)->sregs[BX_SEG_REG_CS], value); + return; + } + + // untested + if (reg->getId() == RID_DS) { // DS register? + BX_CPU(id)->load_seg_reg(&BX_CPU(id)->sregs[BX_SEG_REG_DS], value); + return; + } + + // untested + if (reg->getId() == RID_ES) { // ES register? + BX_CPU(id)->load_seg_reg(&BX_CPU(id)->sregs[BX_SEG_REG_ES], value); + return; + } + + // untested + if (reg->getId() == RID_FS) { // FS register? + BX_CPU(id)->load_seg_reg(&BX_CPU(id)->sregs[BX_SEG_REG_FS], value); + return; + } + + // untested + if (reg->getId() == RID_GS) { // GS register? + BX_CPU(id)->load_seg_reg(&BX_CPU(id)->sregs[BX_SEG_REG_GS], value); + return; + } + + // untested + if (reg->getId() == RID_SS) { // SS register? + BX_CPU(id)->load_seg_reg(&BX_CPU(id)->sregs[BX_SEG_REG_SS], value); + return; + } + #endif + regdata_t* pData; #ifdef SIM_SUPPORT_64 if (reg->getId() == RID_PC) // program counter? diff --git a/src/core/sal/x86/X86Architecture.cc b/src/core/sal/x86/X86Architecture.cc index 84f751c8..312ba4e1 100644 --- a/src/core/sal/x86/X86Architecture.cc +++ b/src/core/sal/x86/X86Architecture.cc @@ -42,6 +42,48 @@ X86Architecture::X86Architecture() pFlagReg->setName("EFLAGS"); m_addRegister(pFlagReg, RT_ST); + // Add the control registers + Register* pCR0Reg = new Register(RID_CR0, 32); + pCR0Reg->setName("CR0"); + m_addRegister(pCR0Reg, RT_CONTROL); + + Register* pCR2Reg = new Register(RID_CR2, 32); + pCR2Reg->setName("CR2"); + m_addRegister(pCR2Reg, RT_CONTROL); + + Register* pCR3Reg = new Register(RID_CR3, 32); + pCR3Reg->setName("CR3"); + m_addRegister(pCR3Reg, RT_CONTROL); + + Register* pCR4Reg = new Register(RID_CR4, 32); + pCR4Reg->setName("CR4"); + m_addRegister(pCR4Reg, RT_CONTROL); + + // Add the segment selector registers + Register* pCSReg = new Register(RID_CS, 16); + pCSReg->setName("CS"); + m_addRegister(pCSReg, RT_SEGMENT); + + Register* pDSReg = new Register(RID_DS, 16); + pDSReg->setName("DS"); + m_addRegister(pDSReg, RT_SEGMENT); + + Register* pESReg = new Register(RID_ES, 16); + pESReg->setName("ES"); + m_addRegister(pESReg, RT_SEGMENT); + + Register* pFSReg = new Register(RID_FS, 16); + pFSReg->setName("FS"); + m_addRegister(pFSReg, RT_SEGMENT); + + Register* pGSReg = new Register(RID_GS, 16); + pGSReg->setName("GS"); + m_addRegister(pGSReg, RT_SEGMENT); + + Register* pSSReg = new Register(RID_SS, 16); + pSSReg->setName("SS"); + m_addRegister(pSSReg, RT_SEGMENT); + // Registers used for extended tracing: size_t ids[] = {RID_CAX, RID_CBX, RID_CCX, RID_CDX, RID_CSI, RID_CDI, RID_CSP, RID_CBP, RID_FLAGS}; for (size_t i = 0; i < sizeof(ids)/sizeof(*ids); ++i) { diff --git a/src/core/sal/x86/X86Architecture.hpp b/src/core/sal/x86/X86Architecture.hpp index c867836a..00cae041 100644 --- a/src/core/sal/x86/X86Architecture.hpp +++ b/src/core/sal/x86/X86Architecture.hpp @@ -50,7 +50,20 @@ enum PCRegisterId { RID_PC = RID_LAST_GP_ID, RID_LAST_PC_ID }; * \enum FlagsRegisterId * Symbolic identifier to access the flags register. */ -enum FlagsRegisterId { RID_FLAGS = RID_LAST_PC_ID }; +enum FlagsRegisterId { RID_FLAGS = RID_LAST_PC_ID, RID_LAST_FLAGS_ID }; + +/** + * \enum SegmentRegisterId + * Symbolic identifier to access the segment register. + */ +enum SegmentRegisterId { RID_CS = RID_LAST_FLAGS_ID, RID_DS, RID_ES, RID_FS, + RID_GS, RID_SS, RID_LAST_SEGMENT_ID}; + +/** + * \enum ControlRegisterId + * Symbolic identifier to access the control register. + */ +enum ControlRegisterId { RID_CR0 = RID_LAST_SEGMENT_ID, RID_CR1, RID_CR2, RID_CR3, RID_CR4 }; } // end-of-namespace: fail From 0799e52fdef51ac47578638672830c87a4270d2f Mon Sep 17 00:00:00 2001 From: Florian Lukas Date: Wed, 26 Feb 2014 14:33:48 +0100 Subject: [PATCH 06/12] util/llvmdisassembler: map registers by names Internal LLVM register IDs can and did change between LLVM versions. These magic integers are replaced by iterating over all LLVM registers and mapping them to FAIL* registers by name. As this iteration requires a LLVM object created from a binary, a static convenience function is added to LLVMtoFailTranslator which creates a translator given the binary filename. Building this functionality inside libfail-llvmdisassembler prevents experiments from needing to add LLVM includes and library definitions. Change-Id: I27927f40d5cb6d9a22bb2caf21ca2450f6bcb0b8 --- .../llvmdisassembler/LLVMDisassembler.cpp | 4 +- .../util/llvmdisassembler/LLVMtoFailBochs.cpp | 86 ++++++++++++------- .../util/llvmdisassembler/LLVMtoFailBochs.hpp | 4 +- .../util/llvmdisassembler/LLVMtoFailGem5.cpp | 48 ++++++----- .../util/llvmdisassembler/LLVMtoFailGem5.hpp | 4 +- .../llvmdisassembler/LLVMtoFailTranslator.cpp | 20 +++++ .../llvmdisassembler/LLVMtoFailTranslator.hpp | 2 + 7 files changed, 111 insertions(+), 57 deletions(-) diff --git a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp index c97ddc3e..6e2977aa 100644 --- a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp +++ b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp @@ -12,10 +12,10 @@ LLVMtoFailTranslator & LLVMDisassembler::getTranslator() { switch ( llvm::Triple::ArchType(object->getArch()) ) { case llvm::Triple::x86: case llvm::Triple::x86_64: - ltofail = new LLVMtoFailBochs; + ltofail = new LLVMtoFailBochs(this); break; case llvm::Triple::arm: - ltofail = new LLVMtoFailGem5; + ltofail = new LLVMtoFailGem5(this); break; default: std::cout << " not supported :("; diff --git a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp index 22f8d38c..c3f381a2 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp @@ -1,48 +1,68 @@ +#include "LLVMDisassembler.hpp" #include "LLVMtoFailBochs.hpp" #include "sal/x86/X86Architecture.hpp" using namespace fail; -LLVMtoFailBochs::LLVMtoFailBochs() { - /* These magic numbers are taken from the llvm compiler (MC), they - do not appear in any header. They hopefully will never - change */ - llvm_to_fail_map[1] = reginfo_t(RID_CAX, 8, 8) ; // AH - llvm_to_fail_map[2] = reginfo_t(RID_CAX, 8, 0); // AL - llvm_to_fail_map[3] = reginfo_t(RID_CAX, 16, 0); // AX - llvm_to_fail_map[43] = reginfo_t(RID_CAX, 32, 0); // EAX +LLVMtoFailBochs::LLVMtoFailBochs(LLVMDisassembler *disas) { + std::map reg_name_map; - llvm_to_fail_map[4] = reginfo_t(RID_CBX, 8, 8); // BH - llvm_to_fail_map[5] = reginfo_t(RID_CBX, 8, 0); // BL - llvm_to_fail_map[8] = reginfo_t(RID_CBX, 16, 0); // BX - llvm_to_fail_map[45] = reginfo_t(RID_CBX, 32, 0); // EBX + reg_name_map["AH"] = reginfo_t(RID_CAX, 8, 8); + reg_name_map["AL"] = reginfo_t(RID_CAX, 8, 0); + reg_name_map["AX"] = reginfo_t(RID_CAX, 16, 0); + reg_name_map["EAX"] = reginfo_t(RID_CAX, 32, 0); - llvm_to_fail_map[9] = reginfo_t(RID_CCX, 8, 8); // CH - llvm_to_fail_map[10] = reginfo_t(RID_CCX, 8, 0); // CL - llvm_to_fail_map[28] = reginfo_t(RID_CCX, 16, 0); // CX - llvm_to_fail_map[46] = reginfo_t(RID_CCX); // ECX + reg_name_map["BH"] = reginfo_t(RID_CBX, 8, 8); + reg_name_map["BL"] = reginfo_t(RID_CBX, 8, 0); + reg_name_map["BX"] = reginfo_t(RID_CBX, 16, 0); + reg_name_map["EBX"] = reginfo_t(RID_CBX, 32, 0); - llvm_to_fail_map[29] = reginfo_t(RID_CDX, 8, 8); // DH - llvm_to_fail_map[32] = reginfo_t(RID_CDX, 8, 0); // DL - llvm_to_fail_map[42] = reginfo_t(RID_CDX, 16, 0); // DX - llvm_to_fail_map[48] = reginfo_t(RID_CDX); // EDX + reg_name_map["CH"] = reginfo_t(RID_CCX, 8, 8); + reg_name_map["CL"] = reginfo_t(RID_CCX, 8, 0); + reg_name_map["CX"] = reginfo_t(RID_CCX, 16, 0); + reg_name_map["ECX"] = reginfo_t(RID_CCX); - llvm_to_fail_map[30] = reginfo_t(RID_CDI, 16, 0); // DI - llvm_to_fail_map[31] = reginfo_t(RID_CDI, 8, 0); // DIL - llvm_to_fail_map[47] = reginfo_t(RID_CDI); // EDI + reg_name_map["DH"] = reginfo_t(RID_CDX, 8, 8); + reg_name_map["DL"] = reginfo_t(RID_CDX, 8, 0); + reg_name_map["DX"] = reginfo_t(RID_CDX, 16, 0); + reg_name_map["EDX"] = reginfo_t(RID_CDX); - llvm_to_fail_map[6] = reginfo_t(RID_CBP, 16, 0); // BP - llvm_to_fail_map[7] = reginfo_t(RID_CBP, 8, 0); // BPL - llvm_to_fail_map[44] = reginfo_t(RID_CBP); // EBP + reg_name_map["DI"] = reginfo_t(RID_CDI, 16, 0); + reg_name_map["DIL"] = reginfo_t(RID_CDI, 8, 0); + reg_name_map["EDI"] = reginfo_t(RID_CDI); - llvm_to_fail_map[49] = reginfo_t(RID_FLAGS); // EFLAGS + reg_name_map["BP"] = reginfo_t(RID_CBP, 16, 0); + reg_name_map["BPL"] = reginfo_t(RID_CBP, 8, 0); + reg_name_map["EBP"] = reginfo_t(RID_CBP); - llvm_to_fail_map[50] = reginfo_t(RID_PC); // EIP + reg_name_map["EFLAGS"] = reginfo_t(RID_FLAGS); - llvm_to_fail_map[115] = reginfo_t(RID_CSI, 16, 0); // SI - llvm_to_fail_map[53] = reginfo_t(RID_CSI); // ESI + reg_name_map["EIP"] = reginfo_t(RID_PC); - llvm_to_fail_map[54] = reginfo_t(RID_CSP); // ESP - llvm_to_fail_map[117] = reginfo_t(RID_CSP, 16, 0); // SP - llvm_to_fail_map[118] = reginfo_t(RID_CSP, 8, 0); // SPL + reg_name_map["SI"] = reginfo_t(RID_CSI, 16, 0); + reg_name_map["ESI"] = reginfo_t(RID_CSI); + + reg_name_map["ESP"] = reginfo_t(RID_CSP); + reg_name_map["SP"] = reginfo_t(RID_CSP, 16, 0); + reg_name_map["SPL"] = reginfo_t(RID_CSP, 8, 0); + + reg_name_map["CR0"] = reginfo_t(RID_CR0); + reg_name_map["CR2"] = reginfo_t(RID_CR2); + reg_name_map["CR3"] = reginfo_t(RID_CR3); + reg_name_map["CR4"] = reginfo_t(RID_CR4); + + reg_name_map["CS"] = reginfo_t(RID_CS, 16, 0); + reg_name_map["DS"] = reginfo_t(RID_DS, 16, 0); + reg_name_map["ES"] = reginfo_t(RID_ES, 16, 0); + reg_name_map["FS"] = reginfo_t(RID_FS, 16, 0); + reg_name_map["GS"] = reginfo_t(RID_GS, 16, 0); + reg_name_map["SS"] = reginfo_t(RID_SS, 16, 0); + + const llvm::MCRegisterInfo ®_info = disas->getRegisterInfo(); + for (unsigned int i = 0; i < reg_info.getNumRegs(); ++i){ + std::string name = reg_info.getName(i); + if (reg_name_map.count(name) > 0) { + llvm_to_fail_map[i] = reg_name_map[name]; + } + } } diff --git a/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp b/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp index 25161afa..86a9e966 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailBochs.hpp @@ -7,11 +7,13 @@ namespace fail { +class LLVMDisassembler; + class LLVMtoFailBochs : public LLVMtoFailTranslator { public: - LLVMtoFailBochs(); + LLVMtoFailBochs(LLVMDisassembler *disas); }; } // end of namespace diff --git a/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp b/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp index e89a6419..c7d7031d 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp @@ -1,26 +1,34 @@ +#include "LLVMDisassembler.hpp" #include "LLVMtoFailGem5.hpp" #include "sal/arm/ArmArchitecture.hpp" using namespace fail; -LLVMtoFailGem5::LLVMtoFailGem5() { - /* These magic numbers are taken from the machine descriptions of - LLVM they (hopefully) will not change, since they are not exported - via a header */ - llvm_to_fail_map[60] = reginfo_t(RI_R0); - llvm_to_fail_map[61] = reginfo_t(RI_R1); - llvm_to_fail_map[62] = reginfo_t(RI_R2); - llvm_to_fail_map[63] = reginfo_t(RI_R3); - llvm_to_fail_map[64] = reginfo_t(RI_R4); - llvm_to_fail_map[65] = reginfo_t(RI_R5); - llvm_to_fail_map[66] = reginfo_t(RI_R6); - llvm_to_fail_map[67] = reginfo_t(RI_R7); - llvm_to_fail_map[68] = reginfo_t(RI_R8); - llvm_to_fail_map[69] = reginfo_t(RI_R9); - llvm_to_fail_map[70] = reginfo_t(RI_R10); - llvm_to_fail_map[71] = reginfo_t(RI_R11); - llvm_to_fail_map[72] = reginfo_t(RI_R12); - llvm_to_fail_map[105] = reginfo_t(RI_SP); - llvm_to_fail_map[40] = reginfo_t(RI_LR); - llvm_to_fail_map[43] = reginfo_t(RI_IP); +LLVMtoFailGem5::LLVMtoFailGem5(LLVMDisassembler *disas) { + std::map reg_name_map; + + reg_name_map["R0"] = reginfo_t(RI_R0); + reg_name_map["R1"] = reginfo_t(RI_R1); + reg_name_map["R2"] = reginfo_t(RI_R2); + reg_name_map["R3"] = reginfo_t(RI_R3); + reg_name_map["R4"] = reginfo_t(RI_R4); + reg_name_map["R5"] = reginfo_t(RI_R5); + reg_name_map["R6"] = reginfo_t(RI_R6); + reg_name_map["R7"] = reginfo_t(RI_R7); + reg_name_map["R8"] = reginfo_t(RI_R8); + reg_name_map["R9"] = reginfo_t(RI_R9); + reg_name_map["R10"] = reginfo_t(RI_R10); + reg_name_map["R11"] = reginfo_t(RI_R11); + reg_name_map["R12"] = reginfo_t(RI_R12); + reg_name_map["SP"] = reginfo_t(RI_SP); + reg_name_map["LR"] = reginfo_t(RI_LR); + reg_name_map["PC"] = reginfo_t(RI_IP); + + const llvm::MCRegisterInfo ®_info = disas->getRegisterInfo(); + for (unsigned int i = 0; i < reg_info.getNumRegs(); ++i){ + std::string name = reg_info.getName(i); + if (reg_name_map.count(name) > 0) { + llvm_to_fail_map[i] = reg_name_map[name]; + } + } } diff --git a/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp b/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp index 92e46aba..7dec87ef 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailGem5.hpp @@ -7,11 +7,13 @@ namespace fail { +class LLVMDisassembler; + class LLVMtoFailGem5 : public LLVMtoFailTranslator { public: - LLVMtoFailGem5(); + LLVMtoFailGem5(LLVMDisassembler *disas); }; } // end of namespace diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp index f17be92b..77a642dc 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp @@ -1,7 +1,10 @@ +#include "LLVMDisassembler.hpp" #include "LLVMtoFailTranslator.hpp" #include "sal/SALInst.hpp" using namespace fail; +using namespace llvm; +using namespace llvm::object; const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) { ltof_map_t::iterator it = llvm_to_fail_map.find(regid); @@ -38,3 +41,20 @@ void LLVMtoFailTranslator::setRegisterContent(ConcreteCPU & cpu, const reginfo_t cpu.setRegisterContent( reg, value ); // write back register content } + +LLVMtoFailTranslator* LLVMtoFailTranslator::createFromBinary(const std::string elf_path) { + llvm_shutdown_obj Y; + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); + + OwningPtr binary; + assert(createBinary(elf_path, binary) == 0); + + #ifndef __puma + LLVMDisassembler disas(dyn_cast(binary.get())); + return &disas.getTranslator(); + #else + return 0; + #endif +} \ No newline at end of file diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp index 7dbc84b4..9b65116b 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp @@ -68,6 +68,8 @@ public: int getFailRegisterId(unsigned int regid) { return this->getFailRegisterID(regid).id; }; reginfo_t notfound; + + static LLVMtoFailTranslator* createFromBinary(const std::string elf_path); }; } // end of namespace From 0acfe5b2e2451a8c29455de9a8ddbfc720fdb7db Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Wed, 26 Mar 2014 14:54:17 +0100 Subject: [PATCH 07/12] TracingPlugin: cap size of memory access to 8 There are instruction in the real world, that seem to read more than 8 bytes. Therefore we cap the accesses memory to 8 and don't abort with an assertion. Change-Id: Ib2bfd0ac6dc0c030cd6a22940e31f8463a3337cf --- src/plugins/tracing/TracingPlugin.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/tracing/TracingPlugin.cc b/src/plugins/tracing/TracingPlugin.cc index b17a01ec..07263476 100644 --- a/src/plugins/tracing/TracingPlugin.cc +++ b/src/plugins/tracing/TracingPlugin.cc @@ -107,7 +107,9 @@ bool TracingPlugin::run() if (m_full_trace) { Trace_Event_Extended &ext = *e.mutable_trace_ext(); // Read the accessed data - assert(width <= 8); + if (width > 8) { + width = 8; + } uint64_t data = 0; mm.getBytes(addr, width, &data); ext.set_data(data); From 84a03b55ff3d053bf082d9ec3123ed6ae380568c Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 16 Mar 2014 19:03:24 +0100 Subject: [PATCH 08/12] import-trace: limit to general-purpose registers This change limits fault injection to general-purpose registers, instead of relying on the LLVM/Fail* bridge to only recognize the status register (EFLAGS on x86) and general-purpose registers. Since this bridge just learned to translate x86's control and segment registers, and these registers need special handling for fault injection (def/use pruning does not work here), only import register accesses from the RT_GP subset. Status register and instruction pointer injection remain functional, and import-trace now should work architecture independently. Change-Id: Id8ad2f0a9dab1861bf16ea9443c3bdfe7213d3fa --- tools/import-trace/RegisterImporter.cc | 39 ++++++++++++++++++------- tools/import-trace/RegisterImporter.hpp | 5 +++- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/tools/import-trace/RegisterImporter.cc b/tools/import-trace/RegisterImporter.cc index 45b9d434..9467bf6a 100644 --- a/tools/import-trace/RegisterImporter.cc +++ b/tools/import-trace/RegisterImporter.cc @@ -107,6 +107,27 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun do_ip = cmd[IP]; do_split_registers = !cmd[NO_SPLIT]; + // retrieve register IDs for general-purpose and flags register(s) for + // the configured architecture + fail::Architecture arch; + m_ip_register_id = + (*arch.getRegisterSetOfType(RT_IP)->begin())->getId(); + fail::UniformRegisterSet *regset; + if (do_gp) { + regset = arch.getRegisterSetOfType(RT_GP); + for (fail::UniformRegisterSet::iterator it = regset->begin(); + it != regset->end(); ++it) { + m_register_ids.insert((*it)->getId()); + } + } + if (do_flags) { + regset = arch.getRegisterSetOfType(RT_ST); + for (fail::UniformRegisterSet::iterator it = regset->begin(); + it != regset->end(); ++it) { + m_register_ids.insert((*it)->getId()); + } + } + /* Disassemble the binary if necessary */ llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); @@ -147,12 +168,10 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun continue; } - /* if not tracing flags, but flags register -> ignore it - if not tracing gp, but ! flags -> ignore it*/ - if (info.id == RID_FLAGS && !do_flags) - continue; - else if (!do_gp) + /* only proceed if we want to inject into this register */ + if (m_register_ids.find(info.id) == m_register_ids.end()) { continue; + } if (!addRegisterTrace(curtime, instr, ev, info, 'R')) { return false; @@ -169,18 +188,16 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun continue; } - /* if not tracing flags, but flags register -> ignore it - if not tracing gp, but ! flags -> ignore it*/ - if (info.id == RID_FLAGS && !do_flags) - continue; - else if (!do_gp) + /* only proceed if we want to inject into this register */ + if (m_register_ids.find(info.id) == m_register_ids.end()) { continue; + } if (!addRegisterTrace(curtime, instr, ev, info, 'W')) return false; } - const LLVMtoFailTranslator::reginfo_t info_pc(RID_PC); + const LLVMtoFailTranslator::reginfo_t info_pc(m_ip_register_id); if (do_ip) { if (!addRegisterTrace(curtime, instr, ev, info_pc, 'R')) return false; diff --git a/tools/import-trace/RegisterImporter.hpp b/tools/import-trace/RegisterImporter.hpp index a6cefc1d..5576ba05 100644 --- a/tools/import-trace/RegisterImporter.hpp +++ b/tools/import-trace/RegisterImporter.hpp @@ -1,7 +1,7 @@ #ifndef __REGISTER_IMPORTER_H__ #define __REGISTER_IMPORTER_H__ - +#include #include "util/CommandLine.hpp" #include "Importer.hpp" @@ -20,6 +20,9 @@ class RegisterImporter : public Importer { fail::CommandLine::option_handle NO_GP, FLAGS, IP, NO_SPLIT; bool do_gp, do_flags, do_ip, do_split_registers; + std::set m_register_ids; + unsigned m_ip_register_id; + public: RegisterImporter() : Importer(), do_gp(true), do_flags(false), do_ip(false), do_split_registers(true) {} From 1ad2eb51109481a993c0a601bd86600b12c44793 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 16 Mar 2014 18:53:47 +0100 Subject: [PATCH 09/12] core/sal: fix x86 register IDs for x86_64 This bug mapped EFLAGS to the same Fail* register ID as R9 on x86_64. This probably has not had consequences yet, as most FailBochs users use 32-bit code. Change-Id: I00a680675bb9e73c2781276f3ef651162c8e4445 --- src/core/sal/x86/X86Architecture.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/sal/x86/X86Architecture.hpp b/src/core/sal/x86/X86Architecture.hpp index 00cae041..5d74db6b 100644 --- a/src/core/sal/x86/X86Architecture.hpp +++ b/src/core/sal/x86/X86Architecture.hpp @@ -34,9 +34,10 @@ enum GPRegisterId { RID_R8, RID_R9, RID_R10, RID_R11, RID_R12, RID_R13, RID_R14, RID_R15, #else // 32 bit register id's: RID_EAX = 0, RID_ECX, RID_EDX, RID_EBX, RID_ESP, RID_EBP, RID_ESI, RID_EDI, - #endif // common register id's (independent of the current register width): - RID_CAX = 0, RID_CCX, RID_CDX, RID_CBX, RID_CSP, RID_CBP, RID_CSI, RID_CDI, - RID_LAST_GP_ID + #endif + RID_LAST_GP_ID, + // common register id's (independent of the current register width): + RID_CAX = 0, RID_CCX, RID_CDX, RID_CBX, RID_CSP, RID_CBP, RID_CSI, RID_CDI }; /** From 136d397a52256a2fb7a9aaa4e1aa981962ea13d6 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Wed, 26 Mar 2014 17:46:46 +0100 Subject: [PATCH 10/12] core/sal: identical register IDs for 32 and 64 bit With this change, x86 special-purpose registers (e.g., EFLAGS) get the same register ID in both 32 bit and 64 bit configurations. Change-Id: I69db9397481414f99ca05ecb0ea9dc8ab7d989c9 --- src/core/sal/x86/X86Architecture.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/sal/x86/X86Architecture.hpp b/src/core/sal/x86/X86Architecture.hpp index 5d74db6b..45655697 100644 --- a/src/core/sal/x86/X86Architecture.hpp +++ b/src/core/sal/x86/X86Architecture.hpp @@ -34,6 +34,9 @@ enum GPRegisterId { RID_R8, RID_R9, RID_R10, RID_R11, RID_R12, RID_R13, RID_R14, RID_R15, #else // 32 bit register id's: RID_EAX = 0, RID_ECX, RID_EDX, RID_EBX, RID_ESP, RID_EBP, RID_ESI, RID_EDI, + // skip a few IDs to get identical numbers for special-purpose registers in + // 32 and 64 bit setups: + SKIP_64BIT_IDS = 15, #endif RID_LAST_GP_ID, // common register id's (independent of the current register width): From ba60ecc4e6bb8e13d73d9fd0f579f2dd6fe9bf17 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Wed, 26 Mar 2014 17:47:03 +0100 Subject: [PATCH 11/12] core/sal: comment typos Change-Id: I9ac66d7d1afa22dc6645433736e1c1d38a4e23fa --- src/core/sal/x86/X86Architecture.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/sal/x86/X86Architecture.hpp b/src/core/sal/x86/X86Architecture.hpp index 45655697..b9d13573 100644 --- a/src/core/sal/x86/X86Architecture.hpp +++ b/src/core/sal/x86/X86Architecture.hpp @@ -29,17 +29,17 @@ typedef X86Architecture Architecture; * in case the activated simulator has 64 bit ability. */ enum GPRegisterId { - #ifdef SIM_SUPPORT_64 // 64 bit register id's: + #ifdef SIM_SUPPORT_64 // 64 bit register IDs: RID_RAX = 0, RID_RCX, RID_RDX, RID_RBX, RID_RSP, RID_RBP, RID_RSI, RID_RDI, RID_R8, RID_R9, RID_R10, RID_R11, RID_R12, RID_R13, RID_R14, RID_R15, - #else // 32 bit register id's: + #else // 32 bit register IDs: RID_EAX = 0, RID_ECX, RID_EDX, RID_EBX, RID_ESP, RID_EBP, RID_ESI, RID_EDI, // skip a few IDs to get identical numbers for special-purpose registers in // 32 and 64 bit setups: SKIP_64BIT_IDS = 15, #endif RID_LAST_GP_ID, - // common register id's (independent of the current register width): + // common register IDs (independent of the current register width): RID_CAX = 0, RID_CCX, RID_CDX, RID_CBX, RID_CSP, RID_CBP, RID_CSI, RID_CDI }; From 5378620b63ba9735d95f300cb3a727555e3ab01e Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Wed, 26 Mar 2014 16:18:18 +0100 Subject: [PATCH 12/12] core/sal: fix warning for 32-bit Bochs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warning: unused variable ‘regdata’ Change-Id: I2b5b0ab7d920dc060ec814494e9817f1f49496a9 --- src/core/sal/bochs/BochsCPU.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/sal/bochs/BochsCPU.cc b/src/core/sal/bochs/BochsCPU.cc index a1868bb7..63f03e84 100644 --- a/src/core/sal/bochs/BochsCPU.cc +++ b/src/core/sal/bochs/BochsCPU.cc @@ -82,9 +82,9 @@ void BochsCPU::setRegisterContent(const Register* reg, regdata_t value) // TODO: BX_CPU(0) *always* correct? if (reg->getId() == RID_FLAGS) { // EFLAGS register? - regdata_t regdata = getRegisterContent(reg); #ifdef SIM_SUPPORT_64 // We are in 64 bit mode: Just assign the lower 32 bits! + regdata_t regdata = getRegisterContent(reg); BX_CPU(id)->writeEFlags((regdata & 0xFFFFFFFF00000000ULL) | (value & 0xFFFFFFFFULL), 0xffffffff); #else