Merge branch 'master' of ssh://vamos.informatik.uni-erlangen.de:29418/fail
This commit is contained in:
@ -11,4 +11,6 @@ message DatabaseCampaignMessage {
|
|||||||
required int32 injection_instr = 4 [(sql_ignore) = true];
|
required int32 injection_instr = 4 [(sql_ignore) = true];
|
||||||
optional int32 injection_instr_absolute = 5 [(sql_ignore) = true];
|
optional int32 injection_instr_absolute = 5 [(sql_ignore) = true];
|
||||||
required int32 data_address = 6 [(sql_ignore) = true];
|
required int32 data_address = 6 [(sql_ignore) = true];
|
||||||
|
required string variant = 7 [(sql_ignore) = true];
|
||||||
|
required string benchmark = 8 [(sql_ignore) = true];
|
||||||
}
|
}
|
||||||
@ -63,8 +63,7 @@ bool DatabaseCampaign::run() {
|
|||||||
pruner = "basic";
|
pruner = "basic";
|
||||||
|
|
||||||
db = Database::cmdline_connect();
|
db = Database::cmdline_connect();
|
||||||
variant_id = db->get_variant_id(variant, benchmark);
|
log_send << "Variant to use " << variant << "/" << benchmark << std::endl;
|
||||||
log_send << "Variant to use " << variant << "/" << benchmark << " (ID: " << variant_id << ")" << std::endl;
|
|
||||||
fspmethod_id = db->get_fspmethod_id(pruner);
|
fspmethod_id = db->get_fspmethod_id(pruner);
|
||||||
log_send << "Pruner to use " << pruner << " (ID: " << fspmethod_id << ")" << std::endl;
|
log_send << "Pruner to use " << pruner << " (ID: " << fspmethod_id << ")" << std::endl;
|
||||||
|
|
||||||
@ -80,56 +79,17 @@ bool DatabaseCampaign::run() {
|
|||||||
boost::thread collect_thread(&DatabaseCampaign::collect_result_thread, this);
|
boost::thread collect_thread(&DatabaseCampaign::collect_result_thread, this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Gather all unfinished jobs */
|
std::vector<Database::Variant> variants = db->get_variants(variant, benchmark);
|
||||||
int experiment_count;
|
for (std::vector<Database::Variant>::const_iterator it = variants.begin();
|
||||||
std::string sql_select = "SELECT pilot_id, g.fspmethod_id, g.variant_id, p.injection_instr, p.injection_instr_absolute, g.data_address";
|
it != variants.end(); ++it) {
|
||||||
std::stringstream ss;
|
if(!run_variant(*it)) {
|
||||||
ss << " FROM fspgroup g"
|
log_send << "run_variant failed for " << it->variant << "/" << it->benchmark <<std::endl;
|
||||||
<< " INNER JOIN fsppilot p ON p.id = g.pilot_id "
|
return false;
|
||||||
<< " WHERE p.known_outcome = 0 "
|
|
||||||
<< " AND g.fspmethod_id = " << fspmethod_id
|
|
||||||
<< " AND g.variant_id = " << variant_id
|
|
||||||
<< " AND (SELECT COUNT(*) FROM " + db_connect.result_table() + " as r WHERE r.pilot_id = g.pilot_id) < 8"
|
|
||||||
<< " ORDER BY p.injection_instr";
|
|
||||||
std::string sql_body = ss.str();
|
|
||||||
|
|
||||||
/* Get the number of unfinished experiments */
|
|
||||||
MYSQL_RES *count = db->query(("SELECT COUNT(*) " + sql_body).c_str(), true);
|
|
||||||
MYSQL_ROW row = mysql_fetch_row(count);
|
|
||||||
experiment_count = atoi(row[0]);
|
|
||||||
|
|
||||||
|
|
||||||
MYSQL_RES *pilots = db->query_stream ((sql_select + sql_body).c_str());
|
|
||||||
|
|
||||||
log_send << "Found " << experiment_count << " unfinished experiments in database." << std::endl;
|
|
||||||
|
|
||||||
sent_pilots = 0;
|
|
||||||
while ((row = mysql_fetch_row(pilots)) != 0) {
|
|
||||||
unsigned pilot_id = atoi(row[0]);
|
|
||||||
unsigned injection_instr = atoi(row[3]);
|
|
||||||
unsigned data_address = atoi(row[5]);
|
|
||||||
|
|
||||||
DatabaseCampaignMessage pilot;
|
|
||||||
pilot.set_pilot_id(pilot_id);
|
|
||||||
pilot.set_fspmethod_id(fspmethod_id);
|
|
||||||
pilot.set_variant_id(variant_id);
|
|
||||||
pilot.set_injection_instr(injection_instr);
|
|
||||||
if (row[4]) {
|
|
||||||
unsigned injection_instr_absolute = atoi(row[4]);
|
|
||||||
pilot.set_injection_instr_absolute(injection_instr_absolute);
|
|
||||||
}
|
|
||||||
pilot.set_data_address(data_address);
|
|
||||||
|
|
||||||
this->cb_send_pilot(pilot);
|
|
||||||
|
|
||||||
if ((++sent_pilots) % 1000 == 0) {
|
|
||||||
log_send << "pushed " << sent_pilots << " pilots into the queue" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_send << "pushed " << sent_pilots << " pilots into the queue" << std::endl;
|
log_send << "pushed " << sent_pilots << " pilots into the queue" << std::endl;
|
||||||
log_send << "wait for the clients to complete" << std::endl;
|
log_send << "wait for the clients to complete" << std::endl;
|
||||||
|
|
||||||
campaignmanager.noMoreParameters();
|
campaignmanager.noMoreParameters();
|
||||||
|
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
@ -149,3 +109,58 @@ void DatabaseCampaign::collect_result_thread() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
||||||
|
/* Gather all unfinished jobs */
|
||||||
|
int experiment_count;
|
||||||
|
std::string sql_select = "SELECT pilot_id, g.fspmethod_id, g.variant_id, p.injection_instr, p.injection_instr_absolute, g.data_address ";
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << " FROM fspgroup g"
|
||||||
|
<< " INNER JOIN fsppilot p ON p.id = g.pilot_id "
|
||||||
|
<< " WHERE p.known_outcome = 0 "
|
||||||
|
<< " AND g.fspmethod_id = " << fspmethod_id
|
||||||
|
<< " AND g.variant_id = " << variant.id
|
||||||
|
<< " AND (SELECT COUNT(*) FROM " + db_connect.result_table() + " as r WHERE r.pilot_id = g.pilot_id)"
|
||||||
|
<< " < " << expected_number_of_results(variant.variant, variant.benchmark)
|
||||||
|
<< " ORDER BY p.injection_instr";
|
||||||
|
std::string sql_body = ss.str();
|
||||||
|
|
||||||
|
/* Get the number of unfinished experiments */
|
||||||
|
MYSQL_RES *count = db->query(("SELECT COUNT(*) " + sql_body).c_str(), true);
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(count);
|
||||||
|
experiment_count = atoi(row[0]);
|
||||||
|
|
||||||
|
|
||||||
|
MYSQL_RES *pilots = db->query_stream ((sql_select + sql_body).c_str());
|
||||||
|
|
||||||
|
log_send << "Found " << experiment_count << " unfinished experiments in database. ("
|
||||||
|
<< variant.variant << "/" << variant.benchmark << ")" << std::endl;
|
||||||
|
|
||||||
|
sent_pilots = 0;
|
||||||
|
while ((row = mysql_fetch_row(pilots)) != 0) {
|
||||||
|
unsigned pilot_id = atoi(row[0]);
|
||||||
|
unsigned injection_instr = atoi(row[3]);
|
||||||
|
unsigned data_address = atoi(row[5]);
|
||||||
|
|
||||||
|
|
||||||
|
DatabaseCampaignMessage pilot;
|
||||||
|
pilot.set_pilot_id(pilot_id);
|
||||||
|
pilot.set_fspmethod_id(fspmethod_id);
|
||||||
|
pilot.set_variant_id(variant.id);
|
||||||
|
pilot.set_injection_instr(injection_instr);
|
||||||
|
pilot.set_variant(variant.variant);
|
||||||
|
pilot.set_benchmark(variant.benchmark);
|
||||||
|
if (row[4]) {
|
||||||
|
unsigned injection_instr_absolute = atoi(row[4]);
|
||||||
|
pilot.set_injection_instr_absolute(injection_instr_absolute);
|
||||||
|
}
|
||||||
|
pilot.set_data_address(data_address);
|
||||||
|
|
||||||
|
this->cb_send_pilot(pilot);
|
||||||
|
|
||||||
|
if ((++sent_pilots) % 1000 == 0) {
|
||||||
|
log_send << "pushed " << sent_pilots << " pilots into the queue" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -24,7 +24,6 @@ class DatabaseCampaign : public Campaign {
|
|||||||
Database *db; // !< The database connection object
|
Database *db; // !< The database connection object
|
||||||
DatabaseProtobufAdapter db_connect;
|
DatabaseProtobufAdapter db_connect;
|
||||||
|
|
||||||
int variant_id; // !< Which variant do we work on (from CMDLINE)
|
|
||||||
int fspmethod_id; // !< Which fspmethod should be put out to the clients
|
int fspmethod_id; // !< Which fspmethod should be put out to the clients
|
||||||
|
|
||||||
void collect_result_thread();
|
void collect_result_thread();
|
||||||
@ -41,6 +40,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool run();
|
virtual bool run();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is called by run() for every variant, returned by the variant
|
||||||
|
* filter (SQL LIKE).
|
||||||
|
* @return \c true if the campaign was successful, \c false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool run_variant(fail::Database::Variant);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many results have to are expected from each fsppilot. If
|
||||||
|
* there are less result rows, the pilot will be again sent to the clients
|
||||||
|
* @return \c exptected number of results
|
||||||
|
*/
|
||||||
|
virtual int expected_number_of_results(std::string variant, std::string benchmark) { return 8;}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function that can be used to add command line options
|
* Callback function that can be used to add command line options
|
||||||
* to the campaign
|
* to the campaign
|
||||||
|
|||||||
@ -74,36 +74,56 @@ my_ulonglong Database::affected_rows()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Database::get_variant_id(const std::string &variant, const std::string &benchmark)
|
std::vector<Database::Variant> Database::get_variants(const std::string &variant, const std::string &benchmark) {
|
||||||
{
|
std::vector<Variant> result;
|
||||||
|
|
||||||
if (!query("CREATE TABLE IF NOT EXISTS variant ("
|
if (!query("CREATE TABLE IF NOT EXISTS variant ("
|
||||||
" id int(11) NOT NULL AUTO_INCREMENT,"
|
" id int(11) NOT NULL AUTO_INCREMENT,"
|
||||||
" variant varchar(255) NOT NULL,"
|
" variant varchar(255) NOT NULL,"
|
||||||
" benchmark varchar(255) NOT NULL,"
|
" benchmark varchar(255) NOT NULL,"
|
||||||
" PRIMARY KEY (id),"
|
" PRIMARY KEY (id),"
|
||||||
"UNIQUE KEY variant (variant,benchmark))")) {
|
"UNIQUE KEY variant (variant,benchmark)) ENGINE=MyISAM")) {
|
||||||
return 0;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int variant_id;
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
// FIXME SQL injection possible
|
// FIXME SQL injection possible
|
||||||
ss << "SELECT id FROM variant WHERE variant LIKE '" << variant << "' AND benchmark LIKE '" << benchmark << "'";
|
ss << "SELECT id, variant, benchmark FROM variant WHERE variant LIKE '" << variant << "' AND benchmark LIKE '" << benchmark << "'";
|
||||||
MYSQL_RES *variant_id_res = query(ss.str().c_str(), true);
|
MYSQL_RES *variant_id_res = query(ss.str().c_str(), true);
|
||||||
|
|
||||||
if (!variant_id_res) {
|
if (!variant_id_res) {
|
||||||
return 0;
|
return result;
|
||||||
} else if (mysql_num_rows(variant_id_res)) {
|
} else if (mysql_num_rows(variant_id_res)) {
|
||||||
MYSQL_ROW row = mysql_fetch_row(variant_id_res);
|
for (unsigned int i = 0; i < mysql_num_rows(variant_id_res); ++i) {
|
||||||
variant_id = atoi(row[0]);
|
MYSQL_ROW row = mysql_fetch_row(variant_id_res);
|
||||||
} else {
|
Variant var;
|
||||||
ss.str("");
|
var.id = atoi(row[0]);
|
||||||
|
var.variant = std::string(row[1]);
|
||||||
|
var.benchmark = std::string(row[2]);
|
||||||
|
result.push_back(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Database::get_variant_id(const std::string &variant, const std::string &benchmark)
|
||||||
|
{
|
||||||
|
std::vector<Variant> variants = get_variants(variant, benchmark);
|
||||||
|
if (variants.size() == 0) {
|
||||||
|
// Insert a new variant
|
||||||
|
std::stringstream ss;
|
||||||
ss << "INSERT INTO variant (variant, benchmark) VALUES ('" << variant << "', '" << benchmark << "')";
|
ss << "INSERT INTO variant (variant, benchmark) VALUES ('" << variant << "', '" << benchmark << "')";
|
||||||
if (!query(ss.str().c_str())) {
|
if (!query(ss.str().c_str())) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
variant_id = mysql_insert_id(handle);
|
return mysql_insert_id(handle);
|
||||||
|
} else if (variants.size() == 1) {
|
||||||
|
return variants[0].id;
|
||||||
|
} else {
|
||||||
|
LOG << "Variant identifier " << variant << "/" << benchmark << " is ambigious!" << std::endl;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return variant_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Database::get_fspmethod_id(const std::string &method)
|
int Database::get_fspmethod_id(const std::string &method)
|
||||||
@ -111,7 +131,7 @@ int Database::get_fspmethod_id(const std::string &method)
|
|||||||
if (!query("CREATE TABLE IF NOT EXISTS fspmethod ("
|
if (!query("CREATE TABLE IF NOT EXISTS fspmethod ("
|
||||||
" id int(11) NOT NULL AUTO_INCREMENT,"
|
" id int(11) NOT NULL AUTO_INCREMENT,"
|
||||||
" method varchar(255) NOT NULL,"
|
" method varchar(255) NOT NULL,"
|
||||||
" PRIMARY KEY (id), UNIQUE KEY method (method))")) {
|
" PRIMARY KEY (id), UNIQUE KEY method (method)) ENGINE=MyISAM")) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <mysql/mysql.h>
|
#include <mysql/mysql.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -31,6 +32,12 @@ namespace fail {
|
|||||||
Database(const std::string &username, const std::string &host, const std::string &database);
|
Database(const std::string &username, const std::string &host, const std::string &database);
|
||||||
~Database() { mysql_close(handle); }
|
~Database() { mysql_close(handle); }
|
||||||
|
|
||||||
|
struct Variant {
|
||||||
|
int id;
|
||||||
|
std::string variant;
|
||||||
|
std::string benchmark;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the variant id for a specific variant/benchmark pair,
|
* Get the variant id for a specific variant/benchmark pair,
|
||||||
* if it isn't defined in the database (variant table), it is
|
* if it isn't defined in the database (variant table), it is
|
||||||
@ -38,6 +45,13 @@ namespace fail {
|
|||||||
*/
|
*/
|
||||||
int get_variant_id(const std::string &variant, const std::string &benchmark);
|
int get_variant_id(const std::string &variant, const std::string &benchmark);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all variants that fit the given patterns (will be
|
||||||
|
* queried with SQL LIKE).
|
||||||
|
*/
|
||||||
|
std::vector<Variant> get_variants(const std::string &variant, const std::string &benchmark);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the fault space pruning method id for a specific
|
* Get the fault space pruning method id for a specific
|
||||||
* pruning method, if it isn't defined in the database
|
* pruning method, if it isn't defined in the database
|
||||||
|
|||||||
@ -48,6 +48,8 @@ void ElfReader::setup(const char* path) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_filename = std::string(path);
|
||||||
|
|
||||||
// Evaluate headers
|
// Evaluate headers
|
||||||
Elf32_Ehdr ehdr;
|
Elf32_Ehdr ehdr;
|
||||||
Elf32_Shdr sec_hdr;
|
Elf32_Shdr sec_hdr;
|
||||||
|
|||||||
@ -75,7 +75,6 @@ namespace fail {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class ElfReader {
|
class ElfReader {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ElfSymbol entry_t;
|
typedef ElfSymbol entry_t;
|
||||||
typedef std::vector<entry_t> container_t;
|
typedef std::vector<entry_t> container_t;
|
||||||
@ -153,9 +152,11 @@ namespace fail {
|
|||||||
container_t::const_iterator sec_begin() { return m_sectiontable.begin(); }
|
container_t::const_iterator sec_begin() { return m_sectiontable.begin(); }
|
||||||
container_t::const_iterator sec_end() { return m_sectiontable.end(); }
|
container_t::const_iterator sec_end() { return m_sectiontable.end(); }
|
||||||
|
|
||||||
|
const std::string & getFilename() { return m_filename; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger m_log;
|
Logger m_log;
|
||||||
|
std::string m_filename;
|
||||||
|
|
||||||
void setup(const char*);
|
void setup(const char*);
|
||||||
int process_symboltable(int sect_num, FILE* fp);
|
int process_symboltable(int sect_num, FILE* fp);
|
||||||
|
|||||||
@ -95,7 +95,7 @@ void LLVMDisassembler::disassemble()
|
|||||||
// This symbol has the same address as the next symbol. Skip it.
|
// This symbol has the same address as the next symbol. Skip it.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (Index = Start; Index < End; Index += Size) {
|
for (Index = Start; Index <= End; Index += Size) {
|
||||||
MCInst Inst;
|
MCInst Inst;
|
||||||
|
|
||||||
if (disas->getInstruction(Inst, Size, memoryObject, Index,
|
if (disas->getInstruction(Inst, Size, memoryObject, Index,
|
||||||
|
|||||||
@ -265,7 +265,7 @@ bool EcosKernelTestCampaign::run()
|
|||||||
<< " AND p.fspmethod_id = " << fspmethod_id << " "
|
<< " AND p.fspmethod_id = " << fspmethod_id << " "
|
||||||
<< " AND (" << sql_variants << ") ";
|
<< " AND (" << sql_variants << ") ";
|
||||||
#elif 1
|
#elif 1
|
||||||
if (!db->query("CREATE TEMPORARY TABLE done_pilots (id INT UNSIGNED NOT NULL PRIMARY KEY)")) return false;
|
if (!db->query("CREATE TEMPORARY TABLE done_pilots (id INT UNSIGNED NOT NULL PRIMARY KEY) ENGINE=MyISAM")) return false;
|
||||||
ss << "INSERT INTO done_pilots SELECT pilot_id FROM " << m_result_table << " GROUP BY pilot_id HAVING SUM(bit_width) = 8";
|
ss << "INSERT INTO done_pilots SELECT pilot_id FROM " << m_result_table << " GROUP BY pilot_id HAVING SUM(bit_width) = 8";
|
||||||
if (!db->query(ss.str().c_str())) return false;
|
if (!db->query(ss.str().c_str())) return false;
|
||||||
unsigned finished_jobs = db->affected_rows();
|
unsigned finished_jobs = db->affected_rows();
|
||||||
|
|||||||
@ -55,6 +55,9 @@ int main(int argc, char *argv[])
|
|||||||
CommandLine::option_handle STATS =
|
CommandLine::option_handle STATS =
|
||||||
cmd.addOption("s", "stats", Arg::None,
|
cmd.addOption("s", "stats", Arg::None,
|
||||||
"-s/--stats \tShow trace stats");
|
"-s/--stats \tShow trace stats");
|
||||||
|
CommandLine::option_handle EXTENDED_TRACE =
|
||||||
|
cmd.addOption("", "extended-trace", Arg::None,
|
||||||
|
"--extended-trace \tDump extended trace information if available");
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
cmd.add_args(argv[i]);
|
cmd.add_args(argv[i]);
|
||||||
@ -73,10 +76,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stats_only = false;
|
bool stats_only = cmd[STATS];
|
||||||
if (cmd[STATS]) {
|
bool extended = cmd[EXTENDED_TRACE];
|
||||||
stats_only = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream normal_stream;
|
std::ifstream normal_stream;
|
||||||
igzstream gz_stream;
|
igzstream gz_stream;
|
||||||
@ -99,7 +100,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stringstream ext;
|
stringstream ext;
|
||||||
if (ev.has_trace_ext() && !stats_only) {
|
if (ev.has_trace_ext() && !stats_only && extended) {
|
||||||
const Trace_Event_Extended& temp_ext = ev.trace_ext();
|
const Trace_Event_Extended& temp_ext = ev.trace_ext();
|
||||||
ext << " DATA " << std::hex;
|
ext << " DATA " << std::hex;
|
||||||
ext << (uint64_t) temp_ext.data();
|
ext << (uint64_t) temp_ext.data();
|
||||||
|
|||||||
@ -3,6 +3,33 @@ set(SRCS
|
|||||||
MemoryImporter.cc
|
MemoryImporter.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (BUILD_LLVM_DISASSEMBLER)
|
||||||
|
set(SRCS ${SRCS}
|
||||||
|
InstructionImporter.cc
|
||||||
|
RegisterImporter.cc
|
||||||
|
RandomJumpImporter.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
include(FindLLVM)
|
||||||
|
|
||||||
|
# llvm-config does add -fno-exception to the command line. But this
|
||||||
|
# breaks some boost libraries.
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS} -fexceptions")
|
||||||
|
endif(BUILD_LLVM_DISASSEMBLER)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_executable(import-trace main.cc ${SRCS})
|
add_executable(import-trace main.cc ${SRCS})
|
||||||
target_link_libraries(import-trace ${PROTOBUF_LIBRARY} -lmysqlclient fail-util fail-sal fail-comm)
|
|
||||||
|
target_link_libraries(import-trace
|
||||||
|
${PROTOBUF_LIBRARY}
|
||||||
|
-lmysqlclient
|
||||||
|
fail-util
|
||||||
|
fail-comm
|
||||||
|
fail-sal)
|
||||||
|
|
||||||
|
if (BUILD_LLVM_DISASSEMBLER)
|
||||||
|
target_link_libraries(import-trace fail-llvmdisassembler fail-sal ${LLVM_LIBS} ${LLVM_LDFLAGS})
|
||||||
|
endif (BUILD_LLVM_DISASSEMBLER)
|
||||||
|
|
||||||
install(TARGETS import-trace RUNTIME DESTINATION bin)
|
install(TARGETS import-trace RUNTIME DESTINATION bin)
|
||||||
|
|||||||
@ -64,6 +64,12 @@ public:
|
|||||||
Importer() : m_sanitychecks(false), m_row_count(0), m_time_trace_start(0) {}
|
Importer() : m_sanitychecks(false), m_row_count(0), m_time_trace_start(0) {}
|
||||||
bool init(const std::string &variant, const std::string &benchmark, fail::Database *db);
|
bool init(const std::string &variant, const std::string &benchmark, fail::Database *db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the cmd interface
|
||||||
|
*/
|
||||||
|
virtual bool cb_commandline_init() { return true; }
|
||||||
|
|
||||||
virtual bool create_database();
|
virtual bool create_database();
|
||||||
virtual bool copy_to_database(fail::ProtoIStream &ps);
|
virtual bool copy_to_database(fail::ProtoIStream &ps);
|
||||||
virtual bool clear_database();
|
virtual bool clear_database();
|
||||||
@ -78,7 +84,8 @@ public:
|
|||||||
const Trace_Event &ev) = 0;
|
const Trace_Event &ev) = 0;
|
||||||
|
|
||||||
|
|
||||||
void set_elf_file(fail::ElfReader *elf) { m_elf = elf; }
|
void set_elf(fail::ElfReader *elf) { m_elf = elf; }
|
||||||
|
|
||||||
void set_memorymap(fail::MemoryMap *mm) { m_mm = mm; }
|
void set_memorymap(fail::MemoryMap *mm) { m_mm = mm; }
|
||||||
void set_faultspace_rightmargin(char accesstype) { m_faultspace_rightmargin = accesstype; }
|
void set_faultspace_rightmargin(char accesstype) { m_faultspace_rightmargin = accesstype; }
|
||||||
void set_sanitychecks(bool enabled) { m_sanitychecks = enabled; }
|
void set_sanitychecks(bool enabled) { m_sanitychecks = enabled; }
|
||||||
|
|||||||
80
tools/import-trace/InstructionImporter.cc
Normal file
80
tools/import-trace/InstructionImporter.cc
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#ifndef __puma
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include "InstructionImporter.hpp"
|
||||||
|
#include "util/Logger.hpp"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
|
using namespace fail;
|
||||||
|
|
||||||
|
|
||||||
|
static Logger LOG("InstructionImporter");
|
||||||
|
|
||||||
|
bool InstructionImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
if (!binary) {
|
||||||
|
/* Disassemble the binary if necessary */
|
||||||
|
llvm::InitializeAllTargetInfos();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
|
llvm::InitializeAllDisassemblers();
|
||||||
|
|
||||||
|
if (error_code ec = createBinary(m_elf->getFilename(), binary)) {
|
||||||
|
LOG << m_elf->getFilename() << "': " << ec.message() << ".\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectFile *obj = dyn_cast<ObjectFile, Binary>(binary.get());
|
||||||
|
|
||||||
|
disas.reset(new LLVMDisassembler(obj));
|
||||||
|
disas->disassemble();
|
||||||
|
LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||||
|
LOG << "instructions disassembled: " << instr_map.size() << " Triple: " << disas->GetTriple() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||||
|
const LLVMDisassembler::Instr &opcode = instr_map.at(ev.ip());
|
||||||
|
|
||||||
|
address_t from = ev.ip(), to = ev.ip() + opcode.length;
|
||||||
|
|
||||||
|
// Iterate over all accessed bytes
|
||||||
|
for (address_t data_address = from; data_address < to; ++data_address) {
|
||||||
|
// skip events outside a possibly supplied memory map
|
||||||
|
if (m_mm && !m_mm->isMatching(data_address)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
margin_info_t left_margin = getOpenEC(data_address);
|
||||||
|
margin_info_t right_margin;
|
||||||
|
right_margin.time = curtime;
|
||||||
|
right_margin.dyninstr = instr; // !< The current instruction
|
||||||
|
right_margin.ip = ev.ip();
|
||||||
|
|
||||||
|
// skip zero-sized intervals: these can occur when an instruction
|
||||||
|
// accesses a memory location more than once (e.g., INC, CMPXCHG)
|
||||||
|
if (left_margin.dyninstr > right_margin.dyninstr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we now have an interval-terminating R/W event to the memaddr
|
||||||
|
// we're currently looking at; the EC is defined by
|
||||||
|
// data_address, dynamic instruction start/end, the absolute PC at
|
||||||
|
// the end, and time start/end
|
||||||
|
access_info_t access;
|
||||||
|
access.access_type = 'R'; // instruction fetch is always a read
|
||||||
|
access.data_address = data_address;
|
||||||
|
access.data_width = 1; // exactly one byte
|
||||||
|
if (!add_trace_event(left_margin, right_margin, access)) {
|
||||||
|
LOG << "add_trace_event failed" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// next interval must start at next instruction; the aforementioned
|
||||||
|
// skipping mechanism wouldn't work otherwise
|
||||||
|
newOpenEC(data_address, curtime + 1, instr + 1, ev.ip());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !__puma
|
||||||
27
tools/import-trace/InstructionImporter.hpp
Normal file
27
tools/import-trace/InstructionImporter.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __INSTRUCTION_IMPORTER_H__
|
||||||
|
#define __INSTRUCTION_IMPORTER_H__
|
||||||
|
|
||||||
|
#include "Importer.hpp"
|
||||||
|
|
||||||
|
#ifndef __puma
|
||||||
|
#include "util/llvmdisassembler/LLVMDisassembler.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class InstructionImporter : public Importer {
|
||||||
|
#ifndef __puma
|
||||||
|
llvm::OwningPtr<llvm::object::Binary> binary;
|
||||||
|
llvm::OwningPtr<fail::LLVMDisassembler> disas;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev);
|
||||||
|
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
/* ignore on purpose */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
132
tools/import-trace/RandomJumpImporter.cc
Normal file
132
tools/import-trace/RandomJumpImporter.cc
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#ifndef __puma
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include "util/Logger.hpp"
|
||||||
|
#include "RandomJumpImporter.hpp"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
|
using namespace fail;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static Logger LOG("RandomJumpImporter");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the campaign
|
||||||
|
*/
|
||||||
|
bool RandomJumpImporter::cb_commandline_init() {
|
||||||
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
|
|
||||||
|
FROM = cmd.addOption("", "jump-from", Arg::Required,
|
||||||
|
"--jump-from\t RandomJump: Which addresses should be jumped from\n");
|
||||||
|
TO = cmd.addOption("", "jump-to", Arg::Required,
|
||||||
|
"--jump-to\t RandomJump: Where to jump (a memory map>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RandomJumpImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
if (!binary) {
|
||||||
|
// Parse command line again, for jump-from and jump-to
|
||||||
|
// operations
|
||||||
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
|
if (!cmd.parse()) {
|
||||||
|
std::cerr << "Error parsing arguments." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read FROM memory file
|
||||||
|
if (cmd[FROM].count() > 0) {
|
||||||
|
m_mm_from = new MemoryMap();
|
||||||
|
for (option::Option *o = cmd[FROM]; o; o = o->next()) {
|
||||||
|
if (!m_mm_from->readFromFile(o->arg)) {
|
||||||
|
LOG << "failed to load memorymap " << o->arg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd[TO].count() > 0) {
|
||||||
|
m_mm_to = new MemoryMap();
|
||||||
|
for (option::Option *o = cmd[TO]; o; o = o->next()) {
|
||||||
|
if (!m_mm_to->readFromFile(o->arg)) {
|
||||||
|
LOG << "failed to load memorymap " << o->arg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG << "Please give at least one --jump-to memory map" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disassemble the binary if necessary */
|
||||||
|
llvm::InitializeAllTargetInfos();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
|
llvm::InitializeAllDisassemblers();
|
||||||
|
|
||||||
|
if (error_code ec = createBinary(m_elf->getFilename(), binary)) {
|
||||||
|
LOG << m_elf->getFilename() << "': " << ec.message() << ".\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectFile *obj = dyn_cast<ObjectFile, Binary>(binary.get());
|
||||||
|
|
||||||
|
disas.reset(new LLVMDisassembler(obj));
|
||||||
|
disas->disassemble();
|
||||||
|
LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||||
|
LOG << "instructions disassembled: " << instr_map.size() << " Triple: " << disas->GetTriple() << std::endl;
|
||||||
|
|
||||||
|
/* Collect all addresses we want to jump to */
|
||||||
|
for (LLVMDisassembler::InstrMap::const_iterator instr = instr_map.begin();
|
||||||
|
instr != instr_map.end(); ++instr) {
|
||||||
|
if (m_mm_to->isMatching(instr->first)) {
|
||||||
|
m_jump_to_addresses.push_back(instr->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG << "we will jump to " << m_jump_to_addresses.size() << " addresses" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// skip events that are outside the memory map. -m instruction map
|
||||||
|
if (m_mm && !m_mm->isMatching(ev.ip())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip events that are outside the --jump-from memory map.
|
||||||
|
if (!m_mm_from->isMatching(ev.ip())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (std::vector<guest_address_t>::const_iterator it = m_jump_to_addresses.begin();
|
||||||
|
it != m_jump_to_addresses.end(); ++it) {
|
||||||
|
guest_address_t to_addr = *it;
|
||||||
|
/* Do not add a jump to the same instruction */
|
||||||
|
if (to_addr == ev.ip())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
margin_info_t margin;
|
||||||
|
margin.time = curtime;
|
||||||
|
margin.dyninstr = instr; // !< The current instruction
|
||||||
|
margin.ip = ev.ip();
|
||||||
|
|
||||||
|
// we now have an interval-terminating R/W event to the memaddr
|
||||||
|
// we're currently looking at; the EC is defined by
|
||||||
|
// data_address, dynamic instruction start/end, the absolute PC at
|
||||||
|
// the end, and time start/end
|
||||||
|
access_info_t access;
|
||||||
|
access.access_type = 'R'; // instruction fetch is always a read
|
||||||
|
access.data_address = to_addr;
|
||||||
|
access.data_width = 4; // exactly one byte
|
||||||
|
if (!add_trace_event(margin, margin, access)) {
|
||||||
|
LOG << "add_trace_event failed" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !__puma
|
||||||
43
tools/import-trace/RandomJumpImporter.hpp
Normal file
43
tools/import-trace/RandomJumpImporter.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef __RANDOM_JUMP_IMPORTER_H__
|
||||||
|
#define __RANDOM_JUMP_IMPORTER_H__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "util/CommandLine.hpp"
|
||||||
|
#include "Importer.hpp"
|
||||||
|
|
||||||
|
#ifndef __puma
|
||||||
|
#include "util/llvmdisassembler/LLVMDisassembler.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class RandomJumpImporter : public Importer {
|
||||||
|
#ifndef __puma
|
||||||
|
llvm::OwningPtr<llvm::object::Binary> binary;
|
||||||
|
llvm::OwningPtr<fail::LLVMDisassembler> disas;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fail::CommandLine::option_handle FROM, TO;
|
||||||
|
|
||||||
|
fail::MemoryMap *m_mm_from, *m_mm_to;
|
||||||
|
std::vector<fail::guest_address_t> m_jump_to_addresses;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the campaign
|
||||||
|
*/
|
||||||
|
virtual bool cb_commandline_init();
|
||||||
|
|
||||||
|
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev);
|
||||||
|
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
/* ignore on purpose */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void open_unused_ec_intervals() {
|
||||||
|
/* empty, Memory Map has a different meaning in this importer */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
171
tools/import-trace/RegisterImporter.cc
Normal file
171
tools/import-trace/RegisterImporter.cc
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#ifndef __puma
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include "RegisterImporter.hpp"
|
||||||
|
#include "util/Logger.hpp"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
|
using namespace fail;
|
||||||
|
|
||||||
|
|
||||||
|
static Logger LOG("RegisterImporter");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the campaign
|
||||||
|
*/
|
||||||
|
bool RegisterImporter::cb_commandline_init() {
|
||||||
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
|
|
||||||
|
NO_GP = cmd.addOption("", "no-gp", Arg::None,
|
||||||
|
"--no-gp\t RegisterImporter: do not inject general purpose registers\n");
|
||||||
|
FLAGS = cmd.addOption("", "flags", Arg::None,
|
||||||
|
"--flags: RegisterImporter: trace flags register\n");
|
||||||
|
IP = cmd.addOption("", "ip", Arg::None,
|
||||||
|
"--ip: RegisterImporter: trace instruction pointer\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RegisterImporter::addRegisterTrace(simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev,
|
||||||
|
const LLVMtoFailTranslator::reginfo_t &info,
|
||||||
|
char access_type) {
|
||||||
|
LLVMtoFailTranslator::reginfo_t one_byte_window = info;
|
||||||
|
one_byte_window.width = 8;
|
||||||
|
address_t from = one_byte_window.toDataAddress(), to = one_byte_window.toDataAddress() + (info.width) / 8;
|
||||||
|
|
||||||
|
// Iterate over all accessed bytes
|
||||||
|
for (address_t data_address = from; data_address < to; ++data_address) {
|
||||||
|
// skip events outside a possibly supplied memory map
|
||||||
|
if (m_mm && !m_mm->isMatching(ev.ip())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
margin_info_t left_margin = getOpenEC(data_address);
|
||||||
|
margin_info_t right_margin;
|
||||||
|
right_margin.time = curtime;
|
||||||
|
right_margin.dyninstr = instr; // !< The current instruction
|
||||||
|
right_margin.ip = ev.ip();
|
||||||
|
|
||||||
|
// skip zero-sized intervals: these can occur when an instruction
|
||||||
|
// accesses a memory location more than once (e.g., INC, CMPXCHG)
|
||||||
|
if (left_margin.dyninstr > right_margin.dyninstr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we now have an interval-terminating R/W event to the memaddr
|
||||||
|
// we're currently looking at; the EC is defined by
|
||||||
|
// data_address, dynamic instruction start/end, the absolute PC at
|
||||||
|
// the end, and time start/end
|
||||||
|
access_info_t access;
|
||||||
|
access.access_type = access_type; // instruction fetch is always a read
|
||||||
|
access.data_address = data_address;
|
||||||
|
access.data_width = 1; // exactly one byte
|
||||||
|
if (!add_trace_event(left_margin, right_margin, access)) {
|
||||||
|
LOG << "add_trace_event failed" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// next interval must start at next instruction; the aforementioned
|
||||||
|
// skipping mechanism wouldn't work otherwise
|
||||||
|
newOpenEC(data_address, curtime + 1, instr + 1, ev.ip());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
if (!binary) {
|
||||||
|
// Parse command line again, for jump-from and jump-to
|
||||||
|
// operations
|
||||||
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
|
if (!cmd.parse()) {
|
||||||
|
std::cerr << "Error parsing arguments." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read FROM memory file
|
||||||
|
if (cmd[NO_GP].count() > 0) {
|
||||||
|
do_gp = false;
|
||||||
|
}
|
||||||
|
if (cmd[FLAGS].count() > 0) {
|
||||||
|
do_flags = true;
|
||||||
|
}
|
||||||
|
if (cmd[IP].count() > 0) {
|
||||||
|
do_ip = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disassemble the binary if necessary */
|
||||||
|
llvm::InitializeAllTargetInfos();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
|
llvm::InitializeAllDisassemblers();
|
||||||
|
|
||||||
|
if (error_code ec = createBinary(m_elf->getFilename(), binary)) {
|
||||||
|
LOG << m_elf->getFilename() << "': " << ec.message() << ".\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectFile *obj = dyn_cast<ObjectFile, Binary>(binary.get());
|
||||||
|
|
||||||
|
disas.reset(new LLVMDisassembler(obj));
|
||||||
|
disas->disassemble();
|
||||||
|
LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||||
|
LOG << "instructions disassembled: " << instr_map.size() << " Triple: " << disas->GetTriple() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LLVMDisassembler::InstrMap &instr_map = disas->getInstrMap();
|
||||||
|
if (instr_map.find(ev.ip()) == instr_map.end()) {
|
||||||
|
LOG << "Could not find instruction for IP: " << std::hex << ev.ip() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const LLVMDisassembler::Instr &opcode = instr_map.at(ev.ip());
|
||||||
|
//const MCRegisterInfo ®_info = disas->getRegisterInfo();
|
||||||
|
|
||||||
|
fail::LLVMtoFailTranslator & ltof = disas->getTranslator() ;
|
||||||
|
|
||||||
|
for (std::vector<LLVMDisassembler::register_t>::const_iterator it = opcode.reg_uses.begin();
|
||||||
|
it != opcode.reg_uses.end(); ++it) {
|
||||||
|
const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it);
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!addRegisterTrace(curtime, instr, ev, info, 'R')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<LLVMDisassembler::register_t>::const_iterator it = opcode.reg_defs.begin();
|
||||||
|
it != opcode.reg_defs.end(); ++it) {
|
||||||
|
const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it);
|
||||||
|
/* 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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!addRegisterTrace(curtime, instr, ev, info, 'W'))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LLVMtoFailTranslator::reginfo_t info_pc(RID_PC);
|
||||||
|
if (do_ip) {
|
||||||
|
if (!addRegisterTrace(curtime, instr, ev, info_pc, 'R'))
|
||||||
|
return false;
|
||||||
|
if (!addRegisterTrace(curtime, instr, ev, info_pc, 'W'))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !__puma
|
||||||
49
tools/import-trace/RegisterImporter.hpp
Normal file
49
tools/import-trace/RegisterImporter.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef __REGISTER_IMPORTER_H__
|
||||||
|
#define __REGISTER_IMPORTER_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include "util/CommandLine.hpp"
|
||||||
|
#include "Importer.hpp"
|
||||||
|
|
||||||
|
#ifndef __puma
|
||||||
|
#include "util/llvmdisassembler/LLVMDisassembler.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterImporter : public Importer {
|
||||||
|
#ifndef __puma
|
||||||
|
llvm::OwningPtr<llvm::object::Binary> binary;
|
||||||
|
llvm::OwningPtr<fail::LLVMDisassembler> disas;
|
||||||
|
|
||||||
|
bool addRegisterTrace(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev,
|
||||||
|
const fail::LLVMtoFailTranslator::reginfo_t &info,
|
||||||
|
char access_type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
fail::CommandLine::option_handle NO_GP, FLAGS, IP;
|
||||||
|
bool do_gp, do_flags, do_ip;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegisterImporter() : Importer(), do_gp(true), do_flags(false), do_ip(false) {}
|
||||||
|
/**
|
||||||
|
* Callback function that can be used to add command line options
|
||||||
|
* to the cmd interface
|
||||||
|
*/
|
||||||
|
virtual bool cb_commandline_init();
|
||||||
|
|
||||||
|
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev);
|
||||||
|
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
|
const Trace_Event &ev) {
|
||||||
|
/* ignore on purpose */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void open_unused_ec_intervals() {
|
||||||
|
/* empty, Memory Map has a different meaning in this importer */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,5 +1,3 @@
|
|||||||
#include "util/optionparser/optionparser.h"
|
|
||||||
#include "util/optionparser/optionparser_ext.hpp"
|
|
||||||
#include "util/CommandLine.hpp"
|
#include "util/CommandLine.hpp"
|
||||||
#include "util/Database.hpp"
|
#include "util/Database.hpp"
|
||||||
#include "util/ElfReader.hpp"
|
#include "util/ElfReader.hpp"
|
||||||
@ -8,9 +6,14 @@
|
|||||||
#include "util/Logger.hpp"
|
#include "util/Logger.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "MemoryImporter.hpp"
|
#include "MemoryImporter.hpp"
|
||||||
|
|
||||||
|
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||||
|
#include "InstructionImporter.hpp"
|
||||||
|
#include "RegisterImporter.hpp"
|
||||||
|
#include "RandomJumpImporter.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
using namespace fail;
|
using namespace fail;
|
||||||
using std::cerr;
|
using std::cerr;
|
||||||
@ -47,7 +50,7 @@ ProtoIStream openProtoStream(std::string input_file) {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
std::string trace_file, username, hostname, database, benchmark;
|
std::string trace_file, username, hostname, database, benchmark;
|
||||||
std::string variant, importer_args;
|
std::string variant;
|
||||||
ElfReader *elf_file = 0;
|
ElfReader *elf_file = 0;
|
||||||
MemoryMap *memorymap = 0;
|
MemoryMap *memorymap = 0;
|
||||||
|
|
||||||
@ -75,9 +78,6 @@ int main(int argc, char *argv[]) {
|
|||||||
CommandLine::option_handle IMPORTER =
|
CommandLine::option_handle IMPORTER =
|
||||||
cmd.addOption("i", "importer", Arg::Required,
|
cmd.addOption("i", "importer", Arg::Required,
|
||||||
"-i/--importer \tWhich import method to use (default: MemoryImporter)");
|
"-i/--importer \tWhich import method to use (default: MemoryImporter)");
|
||||||
CommandLine::option_handle IMPORTER_ARGS =
|
|
||||||
cmd.addOption("I", "importer-args", Arg::Required,
|
|
||||||
"-I/--importer-args \tWhich import method to use (default: "")");
|
|
||||||
CommandLine::option_handle ELF_FILE =
|
CommandLine::option_handle ELF_FILE =
|
||||||
cmd.addOption("e", "elf-file", Arg::Required,
|
cmd.addOption("e", "elf-file", Arg::Required,
|
||||||
"-e/--elf-file \tELF File (default: UNSET)");
|
"-e/--elf-file \tELF File (default: UNSET)");
|
||||||
@ -118,9 +118,22 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
if (cmd[IMPORTER].count() > 0) {
|
if (cmd[IMPORTER].count() > 0) {
|
||||||
std::string imp(cmd[IMPORTER].first()->arg);
|
std::string imp(cmd[IMPORTER].first()->arg);
|
||||||
if (imp == "BasicImporter" || imp == "MemoryImporter") {
|
if (imp == "BasicImporter" || imp == "MemoryImporter" || imp == "memory" || imp == "mem") {
|
||||||
LOG << "Using MemoryImporter" << endl;
|
LOG << "Using MemoryImporter" << endl;
|
||||||
importer = new MemoryImporter();
|
importer = new MemoryImporter();
|
||||||
|
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||||
|
} else if (imp == "InstructionImporter" || imp == "code") {
|
||||||
|
LOG << "Using InstructionImporter" << endl;
|
||||||
|
importer = new InstructionImporter();
|
||||||
|
|
||||||
|
} else if (imp == "RegisterImporter" || imp == "regs") {
|
||||||
|
LOG << "Using RegisterImporter" << endl;
|
||||||
|
importer = new RegisterImporter();
|
||||||
|
|
||||||
|
} else if (imp == "RandomJumpImporter") {
|
||||||
|
LOG << "Using RandomJumpImporter" << endl;
|
||||||
|
importer = new RandomJumpImporter();
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
LOG << "Unkown import method: " << imp << endl;
|
LOG << "Unkown import method: " << imp << endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -131,7 +144,16 @@ int main(int argc, char *argv[]) {
|
|||||||
importer = new MemoryImporter();
|
importer = new MemoryImporter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (importer && !(importer->cb_commandline_init())) {
|
||||||
|
std::cerr << "Cannot call importers command line initialization!" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd[HELP]) {
|
if (cmd[HELP]) {
|
||||||
|
// Since the importer might have added command line options,
|
||||||
|
// we need to reparse all arguments in order to prevent a
|
||||||
|
// segfault within optionparser
|
||||||
|
cmd.parse();
|
||||||
cmd.printUsage();
|
cmd.printUsage();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@ -154,13 +176,10 @@ int main(int argc, char *argv[]) {
|
|||||||
else
|
else
|
||||||
benchmark = "none";
|
benchmark = "none";
|
||||||
|
|
||||||
if (cmd[IMPORTER_ARGS].count() > 0)
|
|
||||||
importer_args = std::string(cmd[IMPORTER_ARGS].first()->arg);
|
|
||||||
|
|
||||||
if (cmd[ELF_FILE].count() > 0) {
|
if (cmd[ELF_FILE].count() > 0) {
|
||||||
elf_file = new ElfReader(cmd[ELF_FILE].first()->arg);
|
elf_file = new ElfReader(cmd[ELF_FILE].first()->arg);
|
||||||
}
|
}
|
||||||
importer->set_elf_file(elf_file);
|
importer->set_elf(elf_file);
|
||||||
|
|
||||||
if (cmd[MEMORYMAP].count() > 0) {
|
if (cmd[MEMORYMAP].count() > 0) {
|
||||||
memorymap = new MemoryMap();
|
memorymap = new MemoryMap();
|
||||||
|
|||||||
Reference in New Issue
Block a user