formatting, typos, comments, details
Change-Id: Iae5f1acb653a694622e9ac2bad93efcfca588f3a
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
#ifndef __EXPERIMENT_DATA_HPP__
|
#ifndef __EXPERIMENT_DATA_HPP__
|
||||||
#define __EXPERIMENT_DATA_HPP__
|
#define __EXPERIMENT_DATA_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <google/protobuf/message.h>
|
#include <google/protobuf/message.h>
|
||||||
|
|||||||
@ -16,52 +16,52 @@ void SocketComm::init()
|
|||||||
|
|
||||||
bool SocketComm::sendMsg(int sockfd, google::protobuf::Message& msg)
|
bool SocketComm::sendMsg(int sockfd, google::protobuf::Message& msg)
|
||||||
{
|
{
|
||||||
int size = htonl(msg.ByteSize());
|
int size = htonl(msg.ByteSize());
|
||||||
std::string buf;
|
std::string buf;
|
||||||
if (safe_write(sockfd, &size, sizeof(size)) == -1
|
if (safe_write(sockfd, &size, sizeof(size)) == -1
|
||||||
|| !msg.SerializeToString(&buf)
|
|| !msg.SerializeToString(&buf)
|
||||||
|| safe_write(sockfd, buf.c_str(), buf.size()) == -1) {
|
|| safe_write(sockfd, buf.c_str(), buf.size()) == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketComm::rcvMsg(int sockfd, google::protobuf::Message& msg)
|
bool SocketComm::rcvMsg(int sockfd, google::protobuf::Message& msg)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int bufsiz;
|
int bufsiz;
|
||||||
if ((buf = getBuf(sockfd, &bufsiz))) {
|
if ((buf = getBuf(sockfd, &bufsiz))) {
|
||||||
std::string st(buf, bufsiz);
|
std::string st(buf, bufsiz);
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
return msg.ParseFromString(st);
|
return msg.ParseFromString(st);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketComm::dropMsg(int sockfd)
|
bool SocketComm::dropMsg(int sockfd)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int bufsiz;
|
int bufsiz;
|
||||||
if ((buf = getBuf(sockfd, &bufsiz))) {
|
if ((buf = getBuf(sockfd, &bufsiz))) {
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * SocketComm::getBuf(int sockfd, int *size)
|
char * SocketComm::getBuf(int sockfd, int *size)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
if (safe_read(sockfd, size, sizeof(int)) == -1) {
|
if (safe_read(sockfd, size, sizeof(int)) == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*size = ntohl(*size);
|
*size = ntohl(*size);
|
||||||
buf = new char[*size];
|
buf = new char[*size];
|
||||||
if (safe_read(sockfd, buf, *size) == -1) {
|
if (safe_read(sockfd, buf, *size) == -1) {
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SocketComm::timedAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int timeout)
|
int SocketComm::timedAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int timeout)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SOCKET_COMM_HPP__
|
#ifndef __SOCKET_COMM_HPP__
|
||||||
#define __SOCKET_COMM_HPP__
|
#define __SOCKET_COMM_HPP__
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -56,11 +56,11 @@ public:
|
|||||||
static int timedAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int timeout);
|
static int timedAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static char * getBuf(int sockfd, int *size);
|
static char *getBuf(int sockfd, int *size);
|
||||||
static ssize_t safe_write(int fd, const void *buf, size_t count);
|
static ssize_t safe_write(int fd, const void *buf, size_t count);
|
||||||
static ssize_t safe_read(int fd, void *buf, size_t count);
|
static ssize_t safe_read(int fd, void *buf, size_t count);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
#endif // __SOCKET_COMM_HPP__
|
#endif // __SOCKET_COMM_HPP__
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __FAIL_CONFIG_HPP__
|
#ifndef __FAIL_CONFIG_HPP__
|
||||||
#define __FAIL_CONFIG_HPP__
|
#define __FAIL_CONFIG_HPP__
|
||||||
|
|
||||||
// #define / #undef the following configuration macros to enable/disable the
|
// #define / #undef the following configuration macros to enable/disable the
|
||||||
// various event sources, fault injection sinks, and miscellaneous other
|
// various event sources, fault injection sinks, and miscellaneous other
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __CAMPAIGN_HPP__
|
#ifndef __CAMPAIGN_HPP__
|
||||||
#define __CAMPAIGN_HPP__
|
#define __CAMPAIGN_HPP__
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CAMPAIGN_MANAGER_HPP__
|
#ifndef __CAMPAIGN_MANAGER_HPP__
|
||||||
#define __CAMPAIGN_MANAGER_HPP__
|
#define __CAMPAIGN_MANAGER_HPP__
|
||||||
|
|
||||||
#include "sal/SALInst.hpp"
|
#include "sal/SALInst.hpp"
|
||||||
#include "comm/ExperimentData.hpp"
|
#include "comm/ExperimentData.hpp"
|
||||||
@ -16,7 +16,7 @@ namespace fail {
|
|||||||
/**
|
/**
|
||||||
* \class CampaignManager
|
* \class CampaignManager
|
||||||
*
|
*
|
||||||
* The CampaignManager allows a user-campaign access to all constant
|
* The CampaignManager allows a user-campaign access to all constant
|
||||||
* simulator information and forwards single experiments to the JobServer.
|
* simulator information and forwards single experiments to the JobServer.
|
||||||
*/
|
*/
|
||||||
class CampaignManager {
|
class CampaignManager {
|
||||||
@ -30,12 +30,12 @@ public:
|
|||||||
* Executes a user campaign
|
* Executes a user campaign
|
||||||
*/
|
*/
|
||||||
bool runCampaign(Campaign* c)
|
bool runCampaign(Campaign* c)
|
||||||
{
|
{
|
||||||
if (!m_jobserver) {
|
if (!m_jobserver) {
|
||||||
m_jobserver = new JobServer;
|
m_jobserver = new JobServer;
|
||||||
}
|
}
|
||||||
m_currentCampaign = c;
|
m_currentCampaign = c;
|
||||||
bool ret = c->run();
|
bool ret = c->run();
|
||||||
m_jobserver->done();
|
m_jobserver->done();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ public:
|
|||||||
* Returns a const reference for acquiring constant simulator specific information.
|
* Returns a const reference for acquiring constant simulator specific information.
|
||||||
* e.g., Registernames, to ease experiment data construction.
|
* e.g., Registernames, to ease experiment data construction.
|
||||||
* The campaign description is not allowed to change the simulator
|
* The campaign description is not allowed to change the simulator
|
||||||
* state, as the actual simulation runs within another process (Minion)
|
* state, as the actual simulation runs within another process (Minion)
|
||||||
* @return constant reference to the current simulator backend.
|
* @return constant reference to the current simulator backend.
|
||||||
*/
|
*/
|
||||||
SimulatorController const& getSimulator() const { return simulator; }
|
SimulatorController const& getSimulator() const { return simulator; }
|
||||||
|
|||||||
@ -29,13 +29,13 @@ bool DatabaseCampaign::run() {
|
|||||||
if (!cb_commandline_init()) return false;
|
if (!cb_commandline_init()) return false;
|
||||||
|
|
||||||
CommandLine::option_handle VARIANT = cmd.addOption("v", "variant", Arg::Required,
|
CommandLine::option_handle VARIANT = cmd.addOption("v", "variant", Arg::Required,
|
||||||
"-v/--variant \tVariant label (default: \"none\")");
|
"-v/--variant \tVariant label (default: \"none\"; use % and _ as wildcard characters)");
|
||||||
CommandLine::option_handle BENCHMARK = cmd.addOption("b", "benchmark", Arg::Required,
|
CommandLine::option_handle BENCHMARK = cmd.addOption("b", "benchmark", Arg::Required,
|
||||||
"-b/--benchmark \tBenchmark label (default: \"none\")\n");
|
"-b/--benchmark \tBenchmark label (default: \"none\"; use % and _ as wildcard characters)\n");
|
||||||
CommandLine::option_handle PRUNER = cmd.addOption("p", "prune-method", Arg::Required,
|
CommandLine::option_handle PRUNER = cmd.addOption("p", "prune-method", Arg::Required,
|
||||||
"-p/--prune-method \tWhich import method to use (default: basic)");
|
"-p/--prune-method \tWhich import method to use (default: basic)");
|
||||||
|
|
||||||
if(!cmd.parse()) {
|
if (!cmd.parse()) {
|
||||||
log_send << "Error parsing arguments." << std::endl;
|
log_send << "Error parsing arguments." << std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ bool DatabaseCampaign::run() {
|
|||||||
std::vector<Database::Variant> variants = db->get_variants(variant, benchmark);
|
std::vector<Database::Variant> variants = db->get_variants(variant, benchmark);
|
||||||
for (std::vector<Database::Variant>::const_iterator it = variants.begin();
|
for (std::vector<Database::Variant>::const_iterator it = variants.begin();
|
||||||
it != variants.end(); ++it) {
|
it != variants.end(); ++it) {
|
||||||
if(!run_variant(*it)) {
|
if (!run_variant(*it)) {
|
||||||
log_send << "run_variant failed for " << it->variant << "/" << it->benchmark <<std::endl;
|
log_send << "run_variant failed for " << it->variant << "/" << it->benchmark <<std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
|||||||
|
|
||||||
MYSQL_RES *pilots = db->query_stream ((sql_select + sql_body).c_str());
|
MYSQL_RES *pilots = db->query_stream ((sql_select + sql_body).c_str());
|
||||||
|
|
||||||
log_send << "Found " << experiment_count << " unfinished experiments in database. ("
|
log_send << "Found " << experiment_count << " unfinished experiments in database. ("
|
||||||
<< variant.variant << "/" << variant.benchmark << ")" << std::endl;
|
<< variant.variant << "/" << variant.benchmark << ")" << std::endl;
|
||||||
|
|
||||||
sent_pilots = 0;
|
sent_pilots = 0;
|
||||||
|
|||||||
@ -61,7 +61,7 @@ public:
|
|||||||
virtual bool cb_commandline_init() { return true; }
|
virtual bool cb_commandline_init() { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to the campagin to get the result message descriptor
|
* Callback to the campaign to get the result message descriptor
|
||||||
*/
|
*/
|
||||||
virtual const google::protobuf::Descriptor * cb_result_message() = 0;
|
virtual const google::protobuf::Descriptor * cb_result_message() = 0;
|
||||||
|
|
||||||
|
|||||||
@ -159,7 +159,7 @@ void JobServer::run()
|
|||||||
// TODO: Log-level?
|
// TODO: Log-level?
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::thread* th;
|
boost::thread* th;
|
||||||
while (!m_finish){
|
while (!m_finish) {
|
||||||
// Accept connection
|
// Accept connection
|
||||||
int cs = SocketComm::timedAccept(s, (struct sockaddr*)&clientaddr, &clen, 100);
|
int cs = SocketComm::timedAccept(s, (struct sockaddr*)&clientaddr, &clen, 100);
|
||||||
if (cs < 0) {
|
if (cs < 0) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __JOB_SERVER_H__
|
#ifndef __JOB_SERVER_H__
|
||||||
#define __JOB_SERVER_H__
|
#define __JOB_SERVER_H__
|
||||||
|
|
||||||
#include "Minion.hpp"
|
#include "Minion.hpp"
|
||||||
#include "util/SynchronizedQueue.hpp"
|
#include "util/SynchronizedQueue.hpp"
|
||||||
@ -110,7 +110,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Adds a new experiment data set to the job queue.
|
* Adds a new experiment data set to the job queue.
|
||||||
* @param data Pointer to an expoeriment data object
|
* @param data Pointer to an expoeriment data object
|
||||||
*/
|
*/
|
||||||
void addParam(ExperimentData* data);
|
void addParam(ExperimentData* data);
|
||||||
/**
|
/**
|
||||||
* Retrieve an experiment result. Blocks if we currently have no results.
|
* Retrieve an experiment result. Blocks if we currently have no results.
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MINION_HPP__
|
#ifndef __MINION_HPP__
|
||||||
#define __MINION_HPP__
|
#define __MINION_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -14,14 +14,14 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class Minion
|
* \class Minion
|
||||||
*
|
*
|
||||||
* Contains all informations about a minion.
|
* Contains all informations about a minion.
|
||||||
*/
|
*/
|
||||||
class Minion {
|
class Minion {
|
||||||
private:
|
private:
|
||||||
std::string hostname;
|
std::string hostname;
|
||||||
bool isWorking;
|
bool isWorking;
|
||||||
ExperimentData* currentExperimentData;
|
ExperimentData* currentExperimentData;
|
||||||
int sockfd;
|
int sockfd;
|
||||||
public:
|
public:
|
||||||
Minion() : isWorking(false), currentExperimentData(0), sockfd(-1) { }
|
Minion() : isWorking(false), currentExperimentData(0), sockfd(-1) { }
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __COROUTINE_MANAGER_HPP__
|
#ifndef __COROUTINE_MANAGER_HPP__
|
||||||
#define __COROUTINE_MANAGER_HPP__
|
#define __COROUTINE_MANAGER_HPP__
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __EXPERIMENT_FLOW_HPP__
|
#ifndef __EXPERIMENT_FLOW_HPP__
|
||||||
#define __EXPERIMENT_FLOW_HPP__
|
#define __EXPERIMENT_FLOW_HPP__
|
||||||
|
|
||||||
#include "sal/SALInst.hpp"
|
#include "sal/SALInst.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,10 @@ JobClient::JobClient(const std::string& server, int port)
|
|||||||
{
|
{
|
||||||
SocketComm::init();
|
SocketComm::init();
|
||||||
m_server_ent = gethostbyname(m_server.c_str());
|
m_server_ent = gethostbyname(m_server.c_str());
|
||||||
cout << "JobServer: " << m_server.c_str() << endl;
|
|
||||||
if(m_server_ent == NULL) {
|
cout << "JobServer: " << m_server.c_str() << endl;
|
||||||
|
|
||||||
|
if (m_server_ent == NULL) {
|
||||||
perror("[Client@gethostbyname()]");
|
perror("[Client@gethostbyname()]");
|
||||||
// TODO: Log-level?
|
// TODO: Log-level?
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -109,7 +111,6 @@ bool JobClient::getParam(ExperimentData& exp)
|
|||||||
|
|
||||||
FailControlMessage_Command JobClient::tryToGetExperimentData(ExperimentData& exp)
|
FailControlMessage_Command JobClient::tryToGetExperimentData(ExperimentData& exp)
|
||||||
{
|
{
|
||||||
|
|
||||||
FailControlMessage ctrlmsg;
|
FailControlMessage ctrlmsg;
|
||||||
|
|
||||||
//Are there other jobs for the experiment
|
//Are there other jobs for the experiment
|
||||||
@ -144,7 +145,7 @@ FailControlMessage_Command JobClient::tryToGetExperimentData(ExperimentData& exp
|
|||||||
switch (ctrlmsg.command()) {
|
switch (ctrlmsg.command()) {
|
||||||
case FailControlMessage::WORK_FOLLOWS:
|
case FailControlMessage::WORK_FOLLOWS:
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0 ; i < ctrlmsg.job_size() ; i++) {
|
for (i = 0; i < ctrlmsg.job_size(); i++) {
|
||||||
ExperimentData* temp_exp = new ExperimentData(exp.getMessage().New());
|
ExperimentData* temp_exp = new ExperimentData(exp.getMessage().New());
|
||||||
|
|
||||||
if (!SocketComm::rcvMsg(m_sockfd, temp_exp->getMessage())) {
|
if (!SocketComm::rcvMsg(m_sockfd, temp_exp->getMessage())) {
|
||||||
@ -187,8 +188,6 @@ FailControlMessage_Command JobClient::tryToGetExperimentData(ExperimentData& exp
|
|||||||
} else {
|
} else {
|
||||||
return ctrlmsg.command();
|
return ctrlmsg.command();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JobClient::sendResult(ExperimentData& result)
|
bool JobClient::sendResult(ExperimentData& result)
|
||||||
@ -198,7 +197,7 @@ bool JobClient::sendResult(ExperimentData& result)
|
|||||||
temp_exp->getMessage().CopyFrom(result.getMessage());
|
temp_exp->getMessage().CopyFrom(result.getMessage());
|
||||||
temp_exp->setWorkloadID(result.getWorkloadID());
|
temp_exp->setWorkloadID(result.getWorkloadID());
|
||||||
|
|
||||||
m_results.push_back( temp_exp );
|
m_results.push_back(temp_exp);
|
||||||
|
|
||||||
if (m_parameters.size() != 0) {
|
if (m_parameters.size() != 0) {
|
||||||
//If job request time is over send back all existing results
|
//If job request time is over send back all existing results
|
||||||
@ -259,7 +258,7 @@ bool JobClient::sendResultsToServer()
|
|||||||
cout << "[Client] Sending back result [";
|
cout << "[Client] Sending back result [";
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < m_results.size() ; i++) {
|
for (i = 0; i < m_results.size(); i++) {
|
||||||
ctrlmsg.add_workloadid(m_results[i]->getWorkloadID());
|
ctrlmsg.add_workloadid(m_results[i]->getWorkloadID());
|
||||||
cout << std::dec << m_results[i]->getWorkloadID();
|
cout << std::dec << m_results[i]->getWorkloadID();
|
||||||
cout << " ";
|
cout << " ";
|
||||||
@ -272,7 +271,7 @@ bool JobClient::sendResultsToServer()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ctrlmsg.job_size() ; i++) {
|
for (i = 0; i < ctrlmsg.job_size(); i++) {
|
||||||
if (!SocketComm::sendMsg(m_sockfd, m_results.front()->getMessage())) {
|
if (!SocketComm::sendMsg(m_sockfd, m_results.front()->getMessage())) {
|
||||||
close(m_sockfd);
|
close(m_sockfd);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __JOB_CLIENT_H__
|
#ifndef __JOB_CLIENT_H__
|
||||||
#define __JOB_CLIENT_H__
|
#define __JOB_CLIENT_H__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// Architecture.hpp: wraps architecture definition headers
|
// Architecture.hpp: wraps architecture definition headers
|
||||||
#ifndef __ARCHITECTURE_HPP__
|
#ifndef __ARCHITECTURE_HPP__
|
||||||
#define __ARCHITECTURE_HPP__
|
#define __ARCHITECTURE_HPP__
|
||||||
|
|
||||||
#include "config/FailConfig.hpp"
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __CPU_HPP__
|
#ifndef __CPU_HPP__
|
||||||
#define __CPU_HPP__
|
#define __CPU_HPP__
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@ -26,7 +26,7 @@ bool CPUState::addSuppressedInterrupt(unsigned interruptNum)
|
|||||||
// Check if already existing:
|
// Check if already existing:
|
||||||
if (isSuppressedInterrupt(interruptNum+32))
|
if (isSuppressedInterrupt(interruptNum+32))
|
||||||
return false; // already added: nothing to do here
|
return false; // already added: nothing to do here
|
||||||
|
|
||||||
// FIXME: addSuppressedInterrupt(ANY_INTERRUPT) can still be called more
|
// FIXME: addSuppressedInterrupt(ANY_INTERRUPT) can still be called more
|
||||||
// than once. This is not handled by the if-statement above.
|
// than once. This is not handled by the if-statement above.
|
||||||
if (interruptNum == ANY_INTERRUPT)
|
if (interruptNum == ANY_INTERRUPT)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __CPU_STATE_HPP__
|
#ifndef __CPU_STATE_HPP__
|
||||||
#define __CPU_STATE_HPP__
|
#define __CPU_STATE_HPP__
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
#ifndef __CONCRETE_CPU_HPP__
|
#ifndef __CONCRETE_CPU_HPP__
|
||||||
#define __CONCRETE_CPU_HPP__
|
#define __CONCRETE_CPU_HPP__
|
||||||
|
|
||||||
#if defined BUILD_BOCHS
|
#if defined BUILD_BOCHS
|
||||||
#include "bochs/BochsCPU.hpp"
|
#include "bochs/BochsCPU.hpp"
|
||||||
#elif defined BUILD_GEM5
|
#elif defined BUILD_GEM5
|
||||||
#if defined BUILD_ARM
|
#if defined BUILD_ARM
|
||||||
#include "gem5/Gem5ArmCPU.hpp"
|
#include "gem5/Gem5ArmCPU.hpp"
|
||||||
#else
|
#else
|
||||||
#error Active config currently not supported!
|
#error Active config currently not supported!
|
||||||
#endif
|
#endif
|
||||||
#elif defined BUILD_QEMU
|
#elif defined BUILD_QEMU
|
||||||
#include "qemu/QEMUConfig.hpp"
|
#include "qemu/QEMUConfig.hpp"
|
||||||
#elif defined BUILD_T32
|
#elif defined BUILD_T32
|
||||||
#include "t32/T32Config.hpp"
|
#include "t32/T32Config.hpp"
|
||||||
#if defined BUILD_ARM
|
#if defined BUILD_ARM
|
||||||
#include "t32/T32ArmCPU.hpp"
|
#include "t32/T32ArmCPU.hpp"
|
||||||
#else
|
#else
|
||||||
#error Active config currently not supported!
|
#error Active config currently not supported!
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#error SAL Config Target not defined
|
#error SAL Config Target not defined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // __CONCRETE_CPU_HPP__
|
#endif // __CONCRETE_CPU_HPP__
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __EVENT_HPP__
|
#ifndef __EVENT_HPP__
|
||||||
#define __EVENT_HPP__
|
#define __EVENT_HPP__
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __LISTENER_HPP__
|
#ifndef __LISTENER_HPP__
|
||||||
#define __LISTENER_HPP__
|
#define __LISTENER_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -205,12 +205,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined CONFIG_EVENT_BREAKPOINTS
|
#if defined CONFIG_EVENT_BREAKPOINTS
|
||||||
#define BP_CTOR_SCOPE public
|
#define BP_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define BP_CTOR_SCOPE protected
|
#define BP_CTOR_SCOPE protected
|
||||||
// This prevents an experiment from instantiating an object of BPSingleListener
|
// This prevents an experiment from instantiating an object of BPSingleListener
|
||||||
// without having enabled the appropriate configuration flag, i.e.,
|
// without having enabled the appropriate configuration flag, i.e.,
|
||||||
// CONFIG_EVENT_BREAKPOINTS = ON.
|
// CONFIG_EVENT_BREAKPOINTS = ON.
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class BPSingleListener
|
* \class BPSingleListener
|
||||||
@ -252,9 +252,9 @@ public: // reset scope in order to allow compiling the various other Fail* sourc
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined CONFIG_EVENT_BREAKPOINTS_RANGE
|
#if defined CONFIG_EVENT_BREAKPOINTS_RANGE
|
||||||
#define BPRANGE_CTOR_SCOPE public
|
#define BPRANGE_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define BPRANGE_CTOR_SCOPE protected
|
#define BPRANGE_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class BPRangeListener
|
* \class BPRangeListener
|
||||||
@ -300,12 +300,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined CONFIG_EVENT_MEMREAD || defined CONFIG_EVENT_MEMWRITE
|
#if defined CONFIG_EVENT_MEMREAD || defined CONFIG_EVENT_MEMWRITE
|
||||||
#define WP_CTOR_SCOPE public
|
#define WP_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define WP_CTOR_SCOPE protected
|
#define WP_CTOR_SCOPE protected
|
||||||
// Note: "private" works only in case of a "final class" (a leaf class) because when using
|
// Note: "private" works only in case of a "final class" (a leaf class) because when using
|
||||||
// "private", the derived classes wouldn't compile anymore (even if they are not used anyway).
|
// "private", the derived classes wouldn't compile anymore (even if they are not used anyway).
|
||||||
// Clearly, MemAccessListener is *not* a leaf class.
|
// Clearly, MemAccessListener is *not* a leaf class.
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class MemAccessListener
|
* \class MemAccessListener
|
||||||
@ -413,9 +413,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_MEMREAD
|
#ifdef CONFIG_EVENT_MEMREAD
|
||||||
#define WPREAD_CTOR_SCOPE public
|
#define WPREAD_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define WPREAD_CTOR_SCOPE protected
|
#define WPREAD_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class MemReadListener
|
* \class MemReadListener
|
||||||
@ -430,9 +430,9 @@ WPREAD_CTOR_SCOPE:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_MEMWRITE
|
#ifdef CONFIG_EVENT_MEMWRITE
|
||||||
#define WPWRITE_CTOR_SCOPE public
|
#define WPWRITE_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define WPWRITE_CTOR_SCOPE protected
|
#define WPWRITE_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class MemWriteListener
|
* \class MemWriteListener
|
||||||
@ -447,9 +447,9 @@ WPWRITE_CTOR_SCOPE:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined CONFIG_EVENT_INTERRUPT || defined CONFIG_EVENT_TRAP
|
#if defined CONFIG_EVENT_INTERRUPT || defined CONFIG_EVENT_TRAP
|
||||||
#define TROUBLE_CTOR_SCOPE public
|
#define TROUBLE_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define TROUBLE_CTOR_SCOPE protected
|
#define TROUBLE_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class TroubleListener
|
* \class TroubleListener
|
||||||
@ -513,9 +513,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_INTERRUPT
|
#ifdef CONFIG_EVENT_INTERRUPT
|
||||||
#define INT_CTOR_SCOPE public
|
#define INT_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define INT_CTOR_SCOPE protected
|
#define INT_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class InterruptListener
|
* \class InterruptListener
|
||||||
@ -540,9 +540,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_TRAP
|
#ifdef CONFIG_EVENT_TRAP
|
||||||
#define TRAP_CTOR_SCOPE public
|
#define TRAP_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define TRAP_CTOR_SCOPE protected
|
#define TRAP_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class TrapListener
|
* \class TrapListener
|
||||||
@ -556,9 +556,9 @@ TRAP_CTOR_SCOPE:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_GUESTSYS
|
#ifdef CONFIG_EVENT_GUESTSYS
|
||||||
#define GUESTSYS_CTOR_SCOPE public
|
#define GUESTSYS_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define GUESTSYS_CTOR_SCOPE protected
|
#define GUESTSYS_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class GuestListener
|
* \class GuestListener
|
||||||
@ -592,9 +592,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_IOPORT
|
#ifdef CONFIG_EVENT_IOPORT
|
||||||
#define IOPORT_CTOR_SCOPE public
|
#define IOPORT_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define IOPORT_CTOR_SCOPE protected
|
#define IOPORT_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class IOPortListener
|
* \class IOPortListener
|
||||||
@ -661,9 +661,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_JUMP
|
#ifdef CONFIG_EVENT_JUMP
|
||||||
#define JUMP_CTOR_SCOPE public
|
#define JUMP_CTOR_SCOPE public
|
||||||
#else
|
#else
|
||||||
#define JUMP_CTOR_SCOPE protected
|
#define JUMP_CTOR_SCOPE protected
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* \class JumpListener
|
* \class JumpListener
|
||||||
|
|||||||
@ -37,7 +37,7 @@ void ListenerManager::remove(BaseListener* li)
|
|||||||
for (index_t i = 0; i < m_BufferList.size(); ) {
|
for (index_t i = 0; i < m_BufferList.size(); ) {
|
||||||
if (m_BufferList[i]->getParent() == simulator.m_Flows.getCurrent()) {
|
if (m_BufferList[i]->getParent() == simulator.m_Flows.getCurrent()) {
|
||||||
m_BufferList[i]->onDeletion();
|
m_BufferList[i]->onDeletion();
|
||||||
if(m_BufferList[i]->getPerformanceBuffer() != NULL)
|
if (m_BufferList[i]->getPerformanceBuffer() != NULL)
|
||||||
m_BufferList[i]->getPerformanceBuffer()->remove(i);
|
m_BufferList[i]->getPerformanceBuffer()->remove(i);
|
||||||
m_remove(i);
|
m_remove(i);
|
||||||
// Inspect the element at m_BufferList[i] a 2nd time
|
// Inspect the element at m_BufferList[i] a 2nd time
|
||||||
@ -117,7 +117,7 @@ void ListenerManager::remove(ExperimentFlow* flow)
|
|||||||
std::set<PerfBufferBase*> perfBufLists;
|
std::set<PerfBufferBase*> perfBufLists;
|
||||||
for (bufferlist_t::iterator it = m_BufferList.begin(); it != m_BufferList.end(); it++) {
|
for (bufferlist_t::iterator it = m_BufferList.begin(); it != m_BufferList.end(); it++) {
|
||||||
(*it)->onDeletion(); // invoke listener handler
|
(*it)->onDeletion(); // invoke listener handler
|
||||||
if((*it)->getPerformanceBuffer() != NULL)
|
if ((*it)->getPerformanceBuffer() != NULL)
|
||||||
perfBufLists.insert((*it)->getPerformanceBuffer());
|
perfBufLists.insert((*it)->getPerformanceBuffer());
|
||||||
(*it)->setPerformanceBuffer(NULL);
|
(*it)->setPerformanceBuffer(NULL);
|
||||||
(*it)->setLocation(INVALID_INDEX);
|
(*it)->setLocation(INVALID_INDEX);
|
||||||
@ -184,7 +184,7 @@ ListenerManager::iterator ListenerManager::makeActive(iterator it)
|
|||||||
// this slot stores the element which has previously been stored in the last slot):
|
// this slot stores the element which has previously been stored in the last slot):
|
||||||
// This is required because the provided iterator "it" isn't valid anymore (due
|
// This is required because the provided iterator "it" isn't valid anymore (due
|
||||||
// to the deletion of the last element within m_remove(index_t)).
|
// to the deletion of the last element within m_remove(index_t)).
|
||||||
|
|
||||||
iterator it_next = begin() + dist; // O(1)
|
iterator it_next = begin() + dist; // O(1)
|
||||||
// Note: "begin() + dist" yields end() if dist is "large enough" (as computed above)
|
// Note: "begin() + dist" yields end() if dist is "large enough" (as computed above)
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __LISTENER_MANAGER_HPP__
|
#ifndef __LISTENER_MANAGER_HPP__
|
||||||
#define __LISTENER_MANAGER_HPP__
|
#define __LISTENER_MANAGER_HPP__
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -184,7 +184,7 @@ public:
|
|||||||
* regarding their location and performance-buffer reference, i.e. their index and
|
* regarding their location and performance-buffer reference, i.e. their index and
|
||||||
* performance-buffer pointer will be invalidated (by setting \c INVALID_INDEX and
|
* performance-buffer pointer will be invalidated (by setting \c INVALID_INDEX and
|
||||||
* \c NULL, respectively).
|
* \c NULL, respectively).
|
||||||
* To actually fire the listeners, call triggerActiveListeners().
|
* To actually fire the listeners, call triggerActiveListeners().
|
||||||
* @param pLi the listener object pointer to trigger; \c pLi will be removed in
|
* @param pLi the listener object pointer to trigger; \c pLi will be removed in
|
||||||
* \c pLi->getPerformanceBuffer(). If the performance buffer-list ptr is
|
* \c pLi->getPerformanceBuffer(). If the performance buffer-list ptr is
|
||||||
* \c NULL, nothing will be done.
|
* \c NULL, nothing will be done.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __MEMORY_HPP__
|
#ifndef __MEMORY_HPP__
|
||||||
#define __MEMORY_HPP__
|
#define __MEMORY_HPP__
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@ -6,34 +6,34 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
class MemoryInstruction {
|
class MemoryInstruction {
|
||||||
regdata_t address;
|
regdata_t address;
|
||||||
regdata_t value;
|
regdata_t value;
|
||||||
uint8_t width;
|
uint8_t width;
|
||||||
bool writeAccess;
|
bool writeAccess;
|
||||||
public:
|
public:
|
||||||
MemoryInstruction(regdata_t address = ADDR_INV, regdata_t value = 0, uint8_t width = 0, bool writeAccess = false) :
|
MemoryInstruction(regdata_t address = ADDR_INV, regdata_t value = 0, uint8_t width = 0, bool writeAccess = false) :
|
||||||
address(address), value(value), width(width), writeAccess(writeAccess) { };
|
address(address), value(value), width(width), writeAccess(writeAccess) { };
|
||||||
|
|
||||||
bool isWriteAccess(void) const { return writeAccess; }
|
bool isWriteAccess(void) const { return writeAccess; }
|
||||||
regdata_t getAddress() const { return address; }
|
regdata_t getAddress() const { return address; }
|
||||||
regdata_t getValue() const { return value; }
|
regdata_t getValue() const { return value; }
|
||||||
uint8_t getWidth() const { return width; }
|
uint8_t getWidth() const { return width; }
|
||||||
|
|
||||||
bool isValid(void) const { return address != ADDR_INV; }
|
bool isValid(void) const { return address != ADDR_INV; }
|
||||||
|
|
||||||
void setAddress(regdata_t addr) { address = addr; }
|
void setAddress(regdata_t addr) { address = addr; }
|
||||||
void setValue(regdata_t val) { value = val; }
|
void setValue(regdata_t val) { value = val; }
|
||||||
void setWidth(uint8_t w) { width = w; }
|
void setWidth(uint8_t w) { width = w; }
|
||||||
void setWriteAccess(bool iswrite) { writeAccess = iswrite; }
|
void setWriteAccess(bool iswrite) { writeAccess = iswrite; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemoryInstructionAnalyzer {
|
class MemoryInstructionAnalyzer {
|
||||||
public:
|
public:
|
||||||
virtual bool eval(address_t opcode, MemoryInstruction & result) = 0;
|
virtual bool eval(address_t opcode, MemoryInstruction& result) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern MemoryInstructionAnalyzer & meminstruction;
|
extern MemoryInstructionAnalyzer& meminstruction;
|
||||||
} // end of namespace fail
|
} // end of namespace fail
|
||||||
|
|
||||||
#endif // __MEMORYINSTRUCTION_HPP__
|
#endif // __MEMORYINSTRUCTION_HPP__
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __REGISTER_HPP__
|
#ifndef __REGISTER_HPP__
|
||||||
#define __REGISTER_HPP__
|
#define __REGISTER_HPP__
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const unsigned ANY_TRAP = static_cast<unsigned> (-1);
|
|||||||
const unsigned ANY_INTERRUPT = static_cast<unsigned> (-1);
|
const unsigned ANY_INTERRUPT = static_cast<unsigned> (-1);
|
||||||
const timer_id_t INVALID_TIMER = static_cast<timer_id_t> (0);
|
const timer_id_t INVALID_TIMER = static_cast<timer_id_t> (0);
|
||||||
#else
|
#else
|
||||||
#error SAL Config Target not defined
|
#error SAL Config Target not defined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __SAL_CONFIG_HPP__
|
#ifndef __SAL_CONFIG_HPP__
|
||||||
#define __SAL_CONFIG_HPP__
|
#define __SAL_CONFIG_HPP__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
// Type-config depends on the current selected simulator:
|
// Type-config depends on the current selected simulator:
|
||||||
#if defined BUILD_BOCHS
|
#if defined BUILD_BOCHS
|
||||||
#include "bochs/BochsConfig.hpp"
|
#include "bochs/BochsConfig.hpp"
|
||||||
#elif defined BUILD_GEM5
|
#elif defined BUILD_GEM5
|
||||||
#include "gem5/Gem5Config.hpp"
|
#include "gem5/Gem5Config.hpp"
|
||||||
#elif defined BUILD_QEMU
|
#elif defined BUILD_QEMU
|
||||||
#include "qemu/QEMUConfig.hpp"
|
#include "qemu/QEMUConfig.hpp"
|
||||||
#elif defined BUILD_T32
|
#elif defined BUILD_T32
|
||||||
#include "t32/T32Config.hpp"
|
#include "t32/T32Config.hpp"
|
||||||
#else
|
#else
|
||||||
#error SAL Config Target not defined
|
#error SAL Config Target not defined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __SAL_INSTANCE_HPP__
|
#ifndef __SAL_INSTANCE_HPP__
|
||||||
#define __SAL_INSTANCE_HPP__
|
#define __SAL_INSTANCE_HPP__
|
||||||
|
|
||||||
#include "SALConfig.hpp"
|
#include "SALConfig.hpp"
|
||||||
#include "config/VariantConfig.hpp"
|
#include "config/VariantConfig.hpp"
|
||||||
|
|||||||
@ -84,7 +84,7 @@ void SimulatorController::onBreakpoint(ConcreteCPU* cpu, address_t instrPtr, add
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len,
|
void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len,
|
||||||
bool is_write, address_t instrPtr)
|
bool is_write, address_t instrPtr)
|
||||||
{
|
{
|
||||||
MemAccessEvent::access_type_t accesstype =
|
MemAccessEvent::access_type_t accesstype =
|
||||||
is_write ? MemAccessEvent::MEM_WRITE
|
is_write ? MemAccessEvent::MEM_WRITE
|
||||||
@ -114,7 +114,7 @@ void SimulatorController::onInterrupt(ConcreteCPU* cpu, unsigned interruptNum, b
|
|||||||
{
|
{
|
||||||
ListenerManager::iterator it = m_LstList.begin();
|
ListenerManager::iterator it = m_LstList.begin();
|
||||||
InterruptEvent tmp(nmi, interruptNum, cpu);
|
InterruptEvent tmp(nmi, interruptNum, cpu);
|
||||||
while (it != m_LstList.end()) { // check for active listeners
|
while (it != m_LstList.end()) { // check for active listeners
|
||||||
BaseListener* pev = *it;
|
BaseListener* pev = *it;
|
||||||
InterruptListener* pie = dynamic_cast<InterruptListener*>(pev);
|
InterruptListener* pie = dynamic_cast<InterruptListener*>(pev);
|
||||||
if (!pie || !pie->isMatching(&tmp)) {
|
if (!pie || !pie->isMatching(&tmp)) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __SIMULATOR_CONTROLLER_HPP__
|
#ifndef __SIMULATOR_CONTROLLER_HPP__
|
||||||
#define __SIMULATOR_CONTROLLER_HPP__
|
#define __SIMULATOR_CONTROLLER_HPP__
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -83,7 +83,7 @@ public:
|
|||||||
* @param is_write \c true if memory is written, \c false if read
|
* @param is_write \c true if memory is written, \c false if read
|
||||||
* @param instrPtr the address of the instruction causing the memory
|
* @param instrPtr the address of the instruction causing the memory
|
||||||
* access
|
* access
|
||||||
*
|
*
|
||||||
* FIXME: should instrPtr be part of this interface?
|
* FIXME: should instrPtr be part of this interface?
|
||||||
*/
|
*/
|
||||||
void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr);
|
void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __ARM_ARCHITECURE_HPP__
|
#ifndef __ARM_ARCHITECURE_HPP__
|
||||||
#define __ARM_ARCHITECURE_HPP__
|
#define __ARM_ARCHITECURE_HPP__
|
||||||
|
|
||||||
#include "../CPU.hpp"
|
#include "../CPU.hpp"
|
||||||
#include "../CPUState.hpp"
|
#include "../CPUState.hpp"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __ARM_CPU_STATE_HPP__
|
#ifndef __ARM_CPU_STATE_HPP__
|
||||||
#define __ARM_CPU_STATE_HPP__
|
#define __ARM_CPU_STATE_HPP__
|
||||||
|
|
||||||
#include "../CPU.hpp"
|
#include "../CPU.hpp"
|
||||||
#include "../CPUState.hpp"
|
#include "../CPUState.hpp"
|
||||||
|
|||||||
@ -1266,7 +1266,7 @@ static int evaluate_mrs_msr(uint32_t opcode,
|
|||||||
uint32_t address, struct arm_instruction *instruction)
|
uint32_t address, struct arm_instruction *instruction)
|
||||||
{
|
{
|
||||||
int R = (opcode & 0x00400000) >> 22;
|
int R = (opcode & 0x00400000) >> 22;
|
||||||
std::string PSR = (R) ? "SPSR" : "CPSR";
|
std::string PSR = (R) ? "SPSR" : "CPSR";
|
||||||
|
|
||||||
/* Move register to status register (MSR) */
|
/* Move register to status register (MSR) */
|
||||||
if (opcode & 0x00200000) {
|
if (opcode & 0x00200000) {
|
||||||
@ -1922,64 +1922,64 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void arm_load_store_instr::evaluate() {
|
void arm_load_store_instr::evaluate() {
|
||||||
fail::Register * reg = fail::simulator.getCPU(0).getRegister(Rd);
|
fail::Register * reg = fail::simulator.getCPU(0).getRegister(Rd);
|
||||||
value = fail::simulator.getCPU(0).getRegisterContent(reg);
|
value = fail::simulator.getCPU(0).getRegisterContent(reg);
|
||||||
uint32_t offs = 0;
|
uint32_t offs = 0;
|
||||||
|
|
||||||
std::cout << " Value Register: r" << (int)(Rd) << " = 0x" << std::hex << value << std::endl;
|
std::cout << " Value Register: r" << (int)(Rd) << " = 0x" << std::hex << value << std::endl;
|
||||||
|
|
||||||
// Address holding register:
|
// Address holding register:
|
||||||
reg = fail::simulator.getCPU(0).getRegister(Rn);
|
reg = fail::simulator.getCPU(0).getRegister(Rn);
|
||||||
address = fail::simulator.getCPU(0).getRegisterContent(reg);
|
address = fail::simulator.getCPU(0).getRegisterContent(reg);
|
||||||
|
|
||||||
if(offset_mode == 0) { // immediate
|
if (offset_mode == 0) { // immediate
|
||||||
offs = offset.offset;
|
offs = offset.offset;
|
||||||
} else { // (scaled) register
|
} else { // (scaled) register
|
||||||
reg = fail::simulator.getCPU(0).getRegister(offset.reg.Rm);
|
reg = fail::simulator.getCPU(0).getRegister(offset.reg.Rm);
|
||||||
// get scale register
|
// get scale register
|
||||||
uint32_t rm = fail::simulator.getCPU(0).getRegisterContent(reg);
|
uint32_t rm = fail::simulator.getCPU(0).getRegisterContent(reg);
|
||||||
// get shift value
|
// get shift value
|
||||||
uint8_t shimm = offset.reg.shift_imm;
|
uint8_t shimm = offset.reg.shift_imm;
|
||||||
|
|
||||||
switch(offset.reg.shift) {
|
switch (offset.reg.shift) {
|
||||||
case 0: // LSL
|
case 0: // LSL
|
||||||
offs = rm << shimm;
|
offs = rm << shimm;
|
||||||
break;
|
break;
|
||||||
case 1: // LSR
|
case 1: // LSR
|
||||||
offs = rm >> shimm;
|
offs = rm >> shimm;
|
||||||
break;
|
break;
|
||||||
case 2: // ASR
|
case 2: // ASR
|
||||||
offs = (rm >> shimm) | (rm & (1 << 31));
|
offs = (rm >> shimm) | (rm & (1 << 31));
|
||||||
break;
|
break;
|
||||||
case 3: // ROR
|
case 3: // ROR
|
||||||
offs = ror(rm, shimm);
|
offs = ror(rm, shimm);
|
||||||
break;
|
break;
|
||||||
case 4: // RRX
|
case 4: // RRX
|
||||||
// This might be wrong!
|
// This might be wrong!
|
||||||
// RRX rotates right 1 bit, the carry flag is moved to 31
|
// RRX rotates right 1 bit, the carry flag is moved to 31
|
||||||
// and to original bit 0 is moved to the carry flag.
|
// and to original bit 0 is moved to the carry flag.
|
||||||
// Now we have a problem: The original carry flag is updated,
|
// Now we have a problem: The original carry flag is updated,
|
||||||
|
|
||||||
// The offset is either:
|
// The offset is either:
|
||||||
offs = rm >> 1;
|
offs = rm >> 1;
|
||||||
// OR: offs = (rm >> 1) | (1 << 31); // if CF = 1
|
// OR: offs = (rm >> 1) | (1 << 31); // if CF = 1
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the offset to the address register
|
// Apply the offset to the address register
|
||||||
if(index_mode == 1) { // pre indexed
|
if (index_mode == 1) { // pre indexed
|
||||||
// the calculated address was already written back into Rn
|
// the calculated address was already written back into Rn
|
||||||
} else if (index_mode == 2) { // post indexed
|
} else if (index_mode == 2) { // post indexed
|
||||||
// the address got the offset after the mem access
|
// the address got the offset after the mem access
|
||||||
address = address - offs;
|
address = address - offs;
|
||||||
} else { // we have to apply the offset ourselfs
|
} else { // we have to apply the offset ourselfs
|
||||||
address = address + offs;
|
address = address + offs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::cout << " Address Register: r" << (int)(Rn) << " = 0x" << std::hex << address << std::endl;
|
std::cout << " Address Register: r" << (int)(Rn) << " = 0x" << std::hex << address << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2793,7 +2793,7 @@ static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
|
|||||||
struct arm_instruction *instruction)
|
struct arm_instruction *instruction)
|
||||||
{
|
{
|
||||||
unsigned cond = (opcode >> 4) & 0x0f;
|
unsigned cond = (opcode >> 4) & 0x0f;
|
||||||
std::string x = "", y = "", z = "";
|
std::string x = "", y = "", z = "";
|
||||||
|
|
||||||
if (opcode & 0x01)
|
if (opcode & 0x01)
|
||||||
z = (opcode & 0x02) ? "T" : "E";
|
z = (opcode & 0x02) ? "T" : "E";
|
||||||
@ -3431,7 +3431,7 @@ static int t2ev_store_single(uint32_t opcode, uint32_t address,
|
|||||||
if (rn == 0xf)
|
if (rn == 0xf)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
instruction->type = ARM_STR;
|
instruction->type = ARM_STR;
|
||||||
if (opcode & 0x0800)
|
if (opcode & 0x0800)
|
||||||
op |= 1;
|
op |= 1;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -3439,29 +3439,29 @@ static int t2ev_store_single(uint32_t opcode, uint32_t address,
|
|||||||
case 0x8:
|
case 0x8:
|
||||||
case 0x9:
|
case 0x9:
|
||||||
size = "B";
|
size = "B";
|
||||||
instruction->type = ARM_STRB;
|
instruction->type = ARM_STRB;
|
||||||
goto imm12;
|
goto imm12;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
size = "B";
|
size = "B";
|
||||||
instruction->type = ARM_STRB;
|
instruction->type = ARM_STRB;
|
||||||
goto imm8;
|
goto imm8;
|
||||||
case 0x0:
|
case 0x0:
|
||||||
size = "B";
|
size = "B";
|
||||||
instruction->type = ARM_STRB;
|
instruction->type = ARM_STRB;
|
||||||
break;
|
break;
|
||||||
/* halfword */
|
/* halfword */
|
||||||
case 0xa:
|
case 0xa:
|
||||||
case 0xb:
|
case 0xb:
|
||||||
size = "H";
|
size = "H";
|
||||||
instruction->type = ARM_STRH;
|
instruction->type = ARM_STRH;
|
||||||
goto imm12;
|
goto imm12;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
size = "H";
|
size = "H";
|
||||||
instruction->type = ARM_STRH;
|
instruction->type = ARM_STRH;
|
||||||
goto imm8;
|
goto imm8;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
size = "H";
|
size = "H";
|
||||||
instruction->type = ARM_STRH;
|
instruction->type = ARM_STRH;
|
||||||
break;
|
break;
|
||||||
/* word */
|
/* word */
|
||||||
case 0xc:
|
case 0xc:
|
||||||
@ -3479,12 +3479,12 @@ static int t2ev_store_single(uint32_t opcode, uint32_t address,
|
|||||||
sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
|
sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
|
||||||
size, rt, rn, (int) opcode & 0x0f,
|
size, rt, rn, (int) opcode & 0x0f,
|
||||||
(int) (opcode >> 4) & 0x03);
|
(int) (opcode >> 4) & 0x03);
|
||||||
instruction->info.load_store.Rn = rn; //MH
|
instruction->info.load_store.Rn = rn; //MH
|
||||||
instruction->info.load_store.Rd = rt; //MH
|
instruction->info.load_store.Rd = rt; //MH
|
||||||
instruction->info.load_store.offset_mode = 1; // scaled reg
|
instruction->info.load_store.offset_mode = 1; // scaled reg
|
||||||
instruction->info.load_store.offset.reg.Rm = (int)(opcode & 0x0f);
|
instruction->info.load_store.offset.reg.Rm = (int)(opcode & 0x0f);
|
||||||
instruction->info.load_store.offset.reg.shift = 0; // LSL = 0
|
instruction->info.load_store.offset.reg.shift = 0; // LSL = 0
|
||||||
instruction->info.load_store.offset.reg.shift_imm = (int)((opcode >> 4) & 0x03);
|
instruction->info.load_store.offset.reg.shift_imm = (int)((opcode >> 4) & 0x03);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
@ -3493,17 +3493,17 @@ imm12:
|
|||||||
sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
|
sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
|
||||||
size, rt, rn, immed, immed);
|
size, rt, rn, immed, immed);
|
||||||
instruction->info.load_store.Rn = rn; //MH
|
instruction->info.load_store.Rn = rn; //MH
|
||||||
instruction->info.load_store.Rd = rt; //MH
|
instruction->info.load_store.Rd = rt; //MH
|
||||||
instruction->info.load_store.offset_mode = 0; // immediate
|
instruction->info.load_store.offset_mode = 0; // immediate
|
||||||
instruction->info.load_store.offset.offset = immed;
|
instruction->info.load_store.offset.offset = immed;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
imm8:
|
imm8:
|
||||||
immed = opcode & 0x00ff;
|
immed = opcode & 0x00ff;
|
||||||
instruction->info.load_store.Rn = rn; //MH
|
instruction->info.load_store.Rn = rn; //MH
|
||||||
instruction->info.load_store.Rd = rt; //MH
|
instruction->info.load_store.Rd = rt; //MH
|
||||||
instruction->info.load_store.offset_mode = 0; // immediate
|
instruction->info.load_store.offset_mode = 0; // immediate
|
||||||
instruction->info.load_store.offset.offset = immed;
|
instruction->info.load_store.offset.offset = immed;
|
||||||
|
|
||||||
switch (opcode & 0x700) {
|
switch (opcode & 0x700) {
|
||||||
case 0x600:
|
case 0x600:
|
||||||
@ -3518,11 +3518,11 @@ imm8:
|
|||||||
if (opcode & 0x100) {
|
if (opcode & 0x100) {
|
||||||
if (opcode & 0x400) { /* pre-indexed */
|
if (opcode & 0x400) { /* pre-indexed */
|
||||||
p2 = "]!";
|
p2 = "]!";
|
||||||
instruction->info.load_store.index_mode = 1; // pre indexed
|
instruction->info.load_store.index_mode = 1; // pre indexed
|
||||||
} else { /* post-indexed */
|
} else { /* post-indexed */
|
||||||
p1 = "]";
|
p1 = "]";
|
||||||
p2 = "";
|
p2 = "";
|
||||||
instruction->info.load_store.index_mode = 2; // post indexed
|
instruction->info.load_store.index_mode = 2; // post indexed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3684,11 +3684,11 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
|
|||||||
switch (op1op2) {
|
switch (op1op2) {
|
||||||
case 0:
|
case 0:
|
||||||
mnemonic = "STREX";
|
mnemonic = "STREX";
|
||||||
instruction->type = ARM_STREX;
|
instruction->type = ARM_STREX;
|
||||||
goto strex;
|
goto strex;
|
||||||
case 1:
|
case 1:
|
||||||
mnemonic = "LDREX";
|
mnemonic = "LDREX";
|
||||||
instruction->type = ARM_LDREX;
|
instruction->type = ARM_LDREX;
|
||||||
goto ldrex;
|
goto ldrex;
|
||||||
case 2:
|
case 2:
|
||||||
case 6:
|
case 6:
|
||||||
@ -3697,7 +3697,7 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
|
|||||||
case 12:
|
case 12:
|
||||||
case 14:
|
case 14:
|
||||||
mnemonic = "STRD";
|
mnemonic = "STRD";
|
||||||
instruction->type = ARM_LDRD;
|
instruction->type = ARM_LDRD;
|
||||||
goto immediate;
|
goto immediate;
|
||||||
case 3:
|
case 3:
|
||||||
case 7:
|
case 7:
|
||||||
@ -3706,7 +3706,7 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
|
|||||||
case 13:
|
case 13:
|
||||||
case 15:
|
case 15:
|
||||||
mnemonic = "LDRD";
|
mnemonic = "LDRD";
|
||||||
instruction->type = ARM_LDRD;
|
instruction->type = ARM_LDRD;
|
||||||
if (rn == 15)
|
if (rn == 15)
|
||||||
goto literal;
|
goto literal;
|
||||||
else
|
else
|
||||||
@ -3715,11 +3715,11 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
|
|||||||
switch (op3) {
|
switch (op3) {
|
||||||
case 4:
|
case 4:
|
||||||
mnemonic = "STREXB";
|
mnemonic = "STREXB";
|
||||||
instruction->type = ARM_STREXB;
|
instruction->type = ARM_STREXB;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
mnemonic = "STREXH";
|
mnemonic = "STREXH";
|
||||||
instruction->type = ARM_STREXH;
|
instruction->type = ARM_STREXH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
@ -3737,11 +3737,11 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
case 4:
|
case 4:
|
||||||
mnemonic = "LDREXB";
|
mnemonic = "LDREXB";
|
||||||
instruction->type = ARM_LDREXB;
|
instruction->type = ARM_LDREXB;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
mnemonic = "LDREXH";
|
mnemonic = "LDREXH";
|
||||||
instruction->type = ARM_LDREXH;
|
instruction->type = ARM_LDREXH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
@ -3756,10 +3756,10 @@ strex:
|
|||||||
if (imm) {
|
if (imm) {
|
||||||
sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
|
sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
|
||||||
mnemonic, rd, rt, rn, imm, imm);
|
mnemonic, rd, rt, rn, imm, imm);
|
||||||
} else {
|
} else {
|
||||||
sprintf(cp, "%s\tr%u, r%u, [r%u]",
|
sprintf(cp, "%s\tr%u, r%u, [r%u]",
|
||||||
mnemonic, rd, rt, rn);
|
mnemonic, rd, rt, rn);
|
||||||
}
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
ldrex:
|
ldrex:
|
||||||
@ -4093,7 +4093,7 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
|
|||||||
sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
|
sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
|
||||||
(int) (opcode >> 12) & 0xf,
|
(int) (opcode >> 12) & 0xf,
|
||||||
thumb_alignpc4(address) + immed);
|
thumb_alignpc4(address) + immed);
|
||||||
//MH TODO pc relative
|
//MH TODO pc relative
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4103,9 +4103,9 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
|
|||||||
(int) (opcode >> 12) & 0xf,
|
(int) (opcode >> 12) & 0xf,
|
||||||
rn, immed, immed);
|
rn, immed, immed);
|
||||||
|
|
||||||
instruction->info.load_store.Rn = rn;
|
instruction->info.load_store.Rn = rn;
|
||||||
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
||||||
instruction->info.load_store.offset.offset = immed;
|
instruction->info.load_store.offset.offset = immed;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4115,12 +4115,12 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
|
|||||||
rn,
|
rn,
|
||||||
(int) (opcode >> 0) & 0xf,
|
(int) (opcode >> 0) & 0xf,
|
||||||
(int) (opcode >> 4) & 0x3);
|
(int) (opcode >> 4) & 0x3);
|
||||||
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
||||||
instruction->info.load_store.Rn = rn;
|
instruction->info.load_store.Rn = rn;
|
||||||
instruction->info.load_store.offset_mode = 1;
|
instruction->info.load_store.offset_mode = 1;
|
||||||
instruction->info.load_store.offset.reg.Rm = (int) (opcode >> 0) & 0xf;
|
instruction->info.load_store.offset.reg.Rm = (int) (opcode >> 0) & 0xf;
|
||||||
instruction->info.load_store.offset.reg.shift = 0; // LSL
|
instruction->info.load_store.offset.reg.shift = 0; // LSL
|
||||||
instruction->info.load_store.offset.reg.shift_imm = (int) (opcode >> 4) & 0x3;
|
instruction->info.load_store.offset.reg.shift_imm = (int) (opcode >> 4) & 0x3;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4132,10 +4132,10 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
|
|||||||
(int) (opcode >> 12) & 0xf,
|
(int) (opcode >> 12) & 0xf,
|
||||||
rn, immed, immed);
|
rn, immed, immed);
|
||||||
|
|
||||||
instruction->info.load_store.Rn = rn;
|
instruction->info.load_store.Rn = rn;
|
||||||
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
||||||
instruction->info.load_store.offset.offset = immed;
|
instruction->info.load_store.offset.offset = immed;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
|
if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
|
||||||
@ -4150,11 +4150,11 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
|
|||||||
if (opcode & 0x100) {
|
if (opcode & 0x100) {
|
||||||
if (opcode & 0x400) { /* pre-indexed */
|
if (opcode & 0x400) { /* pre-indexed */
|
||||||
p2 = "]!";
|
p2 = "]!";
|
||||||
instruction->info.load_store.index_mode = 1;
|
instruction->info.load_store.index_mode = 1;
|
||||||
} else { /* post-indexed */
|
} else { /* post-indexed */
|
||||||
p1 = "]";
|
p1 = "]";
|
||||||
p2 = "";
|
p2 = "";
|
||||||
instruction->info.load_store.index_mode = 2;
|
instruction->info.load_store.index_mode = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4164,10 +4164,10 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
|
|||||||
(opcode & 0x200) ? "" : "-",
|
(opcode & 0x200) ? "" : "-",
|
||||||
immed, p2, immed);
|
immed, p2, immed);
|
||||||
|
|
||||||
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
instruction->info.load_store.Rd = (int) (opcode >> 12) & 0xf;
|
||||||
instruction->info.load_store.Rn = rn;
|
instruction->info.load_store.Rn = rn;
|
||||||
instruction->info.load_store.offset_mode = 0;
|
instruction->info.load_store.offset_mode = 0;
|
||||||
instruction->info.load_store.offset.offset = immed;
|
instruction->info.load_store.offset.offset = immed;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4181,7 +4181,7 @@ static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
|
|||||||
int rt = (opcode >> 12) & 0xf;
|
int rt = (opcode >> 12) & 0xf;
|
||||||
int op2 = (opcode >> 6) & 0x3f;
|
int op2 = (opcode >> 6) & 0x3f;
|
||||||
unsigned immed;
|
unsigned immed;
|
||||||
std::string p1 = "", p2 = "]";
|
std::string p1 = "", p2 = "]";
|
||||||
char *mnemonic;
|
char *mnemonic;
|
||||||
|
|
||||||
switch ((opcode >> 23) & 0x3) {
|
switch ((opcode >> 23) & 0x3) {
|
||||||
@ -4450,7 +4450,7 @@ int thumb2_opcode(uint32_t address, uint32_t opcode, struct arm_instruction *ins
|
|||||||
case 0xe8000000:
|
case 0xe8000000:
|
||||||
/* 32-bit instructions */
|
/* 32-bit instructions */
|
||||||
instruction->instruction_size = 4;
|
instruction->instruction_size = 4;
|
||||||
instruction->opcode = opcode;
|
instruction->opcode = opcode;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
|
/* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
|
||||||
|
|||||||
@ -58,9 +58,9 @@ enum arm_instruction_type {
|
|||||||
ARM_LDRH,
|
ARM_LDRH,
|
||||||
ARM_LDRSB,
|
ARM_LDRSB,
|
||||||
ARM_LDRSH,
|
ARM_LDRSH,
|
||||||
ARM_LDREX,
|
ARM_LDREX,
|
||||||
ARM_LDREXB,
|
ARM_LDREXB,
|
||||||
ARM_LDREXH,
|
ARM_LDREXH,
|
||||||
ARM_LDM,
|
ARM_LDM,
|
||||||
|
|
||||||
ARM_STR,
|
ARM_STR,
|
||||||
@ -69,9 +69,9 @@ enum arm_instruction_type {
|
|||||||
ARM_STRBT,
|
ARM_STRBT,
|
||||||
|
|
||||||
ARM_STRH,
|
ARM_STRH,
|
||||||
ARM_STREX,
|
ARM_STREX,
|
||||||
ARM_STREXB,
|
ARM_STREXB,
|
||||||
ARM_STREXH,
|
ARM_STREXH,
|
||||||
ARM_STM,
|
ARM_STM,
|
||||||
|
|
||||||
/* Status register access instructions */
|
/* Status register access instructions */
|
||||||
@ -167,10 +167,10 @@ struct arm_load_store_instr {
|
|||||||
} reg;
|
} reg;
|
||||||
} offset;
|
} offset;
|
||||||
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint8_t width;
|
uint8_t width;
|
||||||
void evaluate(void);
|
void evaluate(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_load_store_multiple_instr {
|
struct arm_load_store_multiple_instr {
|
||||||
@ -196,21 +196,21 @@ struct arm_instruction {
|
|||||||
struct arm_load_store_multiple_instr load_store_multiple;
|
struct arm_load_store_multiple_instr load_store_multiple;
|
||||||
} info;
|
} info;
|
||||||
|
|
||||||
bool isBranchInstruction(void) const {
|
bool isBranchInstruction(void) const {
|
||||||
return (type == ARM_B) || (type == ARM_BL) || (type == ARM_BX) || (type == ARM_BLX);
|
return (type == ARM_B) || (type == ARM_BL) || (type == ARM_BX) || (type == ARM_BLX);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isLoadInstruction(void) const {
|
bool isLoadInstruction(void) const {
|
||||||
return (type >= ARM_LDR) && (type <= ARM_LDM);
|
return (type >= ARM_LDR) && (type <= ARM_LDM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isStoreInstruction(void) const {
|
bool isStoreInstruction(void) const {
|
||||||
return (type >= ARM_STR) && (type <= ARM_STM);
|
return (type >= ARM_STR) && (type <= ARM_STM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMemoryAccess(void) const {
|
bool isMemoryAccess(void) const {
|
||||||
return isLoadInstruction() || isStoreInstruction();
|
return isLoadInstruction() || isStoreInstruction();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
|
int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
|
||||||
|
|||||||
@ -4,113 +4,112 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
static ArmMemoryInstructionAnalyzer anal;
|
static ArmMemoryInstructionAnalyzer anal;
|
||||||
MemoryInstructionAnalyzer & meminstruction = anal;
|
MemoryInstructionAnalyzer& meminstruction = anal;
|
||||||
|
|
||||||
address_t ArmMemoryInstructionAnalyzer::findPrevious(address_t address){
|
address_t ArmMemoryInstructionAnalyzer::findPrevious(address_t address){
|
||||||
if(m_dis.hasInstructionAt(address)) {
|
if (m_dis.hasInstructionAt(address)) {
|
||||||
return address;
|
return address;
|
||||||
} else if (m_dis.hasInstructionAt(address - 2)) {
|
} else if (m_dis.hasInstructionAt(address - 2)) {
|
||||||
return address - 2;
|
return address - 2;
|
||||||
} else {
|
} else {
|
||||||
return ADDR_INV;
|
return ADDR_INV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmMemoryInstructionAnalyzer::evaluate(arm_instruction & inst, MemoryInstruction& result){
|
void ArmMemoryInstructionAnalyzer::evaluate(arm_instruction & inst, MemoryInstruction& result){
|
||||||
cout << "Memory Access: " << inst.text << " - Size: " << inst.instruction_size << " Type " << inst.type << endl;
|
cout << "Memory Access: " << inst.text << " - Size: " << inst.instruction_size << " Type " << inst.type << endl;
|
||||||
inst.info.load_store.evaluate();
|
inst.info.load_store.evaluate();
|
||||||
result.setValue(inst.info.load_store.value);
|
result.setValue(inst.info.load_store.value);
|
||||||
result.setAddress(inst.info.load_store.address);
|
result.setAddress(inst.info.load_store.address);
|
||||||
result.setWidth(4); // TODO;
|
result.setWidth(4); // TODO;
|
||||||
result.setWriteAccess(inst.isStoreInstruction());
|
result.setWriteAccess(inst.isStoreInstruction());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Cortex M3 Lauterbach is a pain in the ass, as a Memory Watchpoint does not stop
|
// The Cortex M3 Lauterbach is a pain in the ass, as a Memory Watchpoint does not stop
|
||||||
// at the accessing instruction, but 1 or 2 instructions later.
|
// at the accessing instruction, but 1 or 2 instructions later.
|
||||||
bool ArmMemoryInstructionAnalyzer::eval_cm3(address_t address, MemoryInstruction& result){
|
bool ArmMemoryInstructionAnalyzer::eval_cm3(address_t address, MemoryInstruction& result){
|
||||||
|
|
||||||
arm_instruction inst;
|
arm_instruction inst;
|
||||||
uint32_t opcode =0;
|
uint32_t opcode =0;
|
||||||
address = findPrevious(address);
|
address = findPrevious(address);
|
||||||
opcode = m_dis.disassemble(address).opcode;
|
opcode = m_dis.disassemble(address).opcode;
|
||||||
|
|
||||||
// OpenOCDs thumb2_opcode evaluation is not complete yet. :(
|
// OpenOCDs thumb2_opcode evaluation is not complete yet. :(
|
||||||
thumb2_opcode(address, opcode, &inst);
|
thumb2_opcode(address, opcode, &inst);
|
||||||
|
|
||||||
if(inst.isMemoryAccess()){
|
if (inst.isMemoryAccess()) {
|
||||||
evaluate(inst, result);
|
evaluate(inst, result);
|
||||||
return true;
|
return true;
|
||||||
}else{
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
arm_instruction inst;
|
arm_instruction inst;
|
||||||
uint32_t opcode =0;
|
uint32_t opcode =0;
|
||||||
address = findPrevious(address); // Cortex M3: memory access is at the previous instruction
|
address = findPrevious(address); // Cortex M3: memory access is at the previous instruction
|
||||||
opcode = m_dis.disassemble(address).opcode;
|
opcode = m_dis.disassemble(address).opcode;
|
||||||
|
|
||||||
// OpenOCDs thumb2_opcode evaluation is not complete yet. :(
|
// OpenOCDs thumb2_opcode evaluation is not complete yet. :(
|
||||||
thumb2_opcode(address, opcode, &inst);
|
thumb2_opcode(address, opcode, &inst);
|
||||||
|
|
||||||
if(inst.isMemoryAccess()){
|
if (inst.isMemoryAccess()) {
|
||||||
evaluate(inst, result);
|
evaluate(inst, result);
|
||||||
return true;
|
return true;
|
||||||
} else if(inst.isBranchInstruction()){
|
} else if (inst.isBranchInstruction()) {
|
||||||
// The memory access took place within the function previously branched
|
// The memory access took place within the function previously branched
|
||||||
int regop = inst.info.b_bl_bx_blx.reg_operand;
|
int regop = inst.info.b_bl_bx_blx.reg_operand;
|
||||||
uint32_t addr = inst.info.b_bl_bx_blx.target_address;
|
uint32_t addr = inst.info.b_bl_bx_blx.target_address;
|
||||||
//cout << " Reg:" << hex << regop << " address " << hex << addr << endl;
|
//cout << " Reg:" << hex << regop << " address " << hex << addr << endl;
|
||||||
// Lets look into this function
|
// Lets look into this function
|
||||||
if( regop == -1 ){
|
if ( regop == -1 ) {
|
||||||
// address should be set..
|
// address should be set..
|
||||||
const ElfSymbol & sym = m_elf.getSymbol(addr|1); // | 1 to set first bit -> thumbmode
|
const ElfSymbol & sym = m_elf.getSymbol(addr|1); // | 1 to set first bit -> thumbmode
|
||||||
addr += sym.getSize(); // Go to end of function.
|
addr += sym.getSize(); // Go to end of function.
|
||||||
// THIS IS DANGEROUS: The memory access can be anywhere within this function, one instruction before a ret.
|
// THIS IS DANGEROUS: The memory access can be anywhere within this function, one instruction before a ret.
|
||||||
// OR, the memory access itself can result in leaving the function :e.g., ldr pc, [r3]
|
// OR, the memory access itself can result in leaving the function :e.g., ldr pc, [r3]
|
||||||
// We cannot be sure :( Here we assume the first memory access from the back.
|
// We cannot be sure :( Here we assume the first memory access from the back.
|
||||||
do { // go backwards until there is a memory instruction.
|
do { // go backwards until there is a memory instruction.
|
||||||
addr = findPrevious(addr); // find previous
|
addr = findPrevious(addr); // find previous
|
||||||
thumb2_opcode(addr, m_dis.disassemble(addr).opcode, &inst);
|
thumb2_opcode(addr, m_dis.disassemble(addr).opcode, &inst);
|
||||||
} while( !inst.isMemoryAccess() );
|
} while ( !inst.isMemoryAccess() );
|
||||||
evaluate(inst, result);
|
evaluate(inst, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// There was a memory access before, but the previous instruction
|
// There was a memory access before, but the previous instruction
|
||||||
// is neither an access nor a branch.
|
// is neither an access nor a branch.
|
||||||
// This can happen if we came here from anywhere, e.g. by ldr pc, [r4]
|
// This can happen if we came here from anywhere, e.g. by ldr pc, [r4]
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmMemoryInstructionAnalyzer::eval_ca9(address_t address, MemoryInstruction& result){
|
bool ArmMemoryInstructionAnalyzer::eval_ca9(address_t address, MemoryInstruction& result){
|
||||||
arm_instruction inst;
|
arm_instruction inst;
|
||||||
uint32_t opcode = m_dis.disassemble(address).opcode;
|
uint32_t opcode = m_dis.disassemble(address).opcode;
|
||||||
arm_evaluate_opcode(address, opcode, &inst);
|
arm_evaluate_opcode(address, opcode, &inst);
|
||||||
if( inst.isMemoryAccess() ){
|
if ( inst.isMemoryAccess() ) {
|
||||||
evaluate(inst, result);
|
evaluate(inst, result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CORTEXM3
|
#define CORTEXM3
|
||||||
|
|
||||||
|
|
||||||
bool ArmMemoryInstructionAnalyzer::eval(address_t address, MemoryInstruction & result){
|
bool ArmMemoryInstructionAnalyzer::eval(address_t address, MemoryInstruction & result){
|
||||||
#ifdef CORTEXM3
|
#ifdef CORTEXM3
|
||||||
#warning "Memory Accesses cannot be evaluated completely!"
|
#warning "Memory Accesses cannot be evaluated completely!"
|
||||||
return eval_cm3(address, result);
|
return eval_cm3(address, result);
|
||||||
#elif defined CORTEXA9
|
#elif defined CORTEXA9
|
||||||
return eval_ca9(address, result);
|
return eval_ca9(address, result);
|
||||||
#else
|
#else
|
||||||
#warning "Memory Accesses are not evaluated!"
|
#warning "Memory Accesses are not evaluated!"
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,27 +8,24 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
class ArmMemoryInstructionAnalyzer : public MemoryInstructionAnalyzer {
|
class ArmMemoryInstructionAnalyzer : public MemoryInstructionAnalyzer {
|
||||||
fail::ElfReader m_elf;
|
fail::ElfReader m_elf;
|
||||||
fail::Disassembler m_dis;
|
fail::Disassembler m_dis;
|
||||||
|
|
||||||
address_t findPrevious(address_t addr);
|
address_t findPrevious(address_t addr);
|
||||||
void evaluate(arm_instruction & inst, MemoryInstruction& result);
|
void evaluate(arm_instruction & inst, MemoryInstruction& result);
|
||||||
bool eval_ca9(address_t address, MemoryInstruction& result);
|
bool eval_ca9(address_t address, MemoryInstruction& result);
|
||||||
bool eval_cm3(address_t address, MemoryInstruction& result);
|
bool eval_cm3(address_t address, MemoryInstruction& result);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ArmMemoryInstructionAnalyzer() {
|
ArmMemoryInstructionAnalyzer() {
|
||||||
m_dis.init();
|
m_dis.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool eval(address_t opcode, MemoryInstruction & result);
|
bool eval(address_t opcode, MemoryInstruction & result);
|
||||||
|
};
|
||||||
};
|
|
||||||
|
|
||||||
} //end of namespace fail
|
} //end of namespace fail
|
||||||
|
|
||||||
|
|
||||||
#endif // __ARMMEMORYINSTRUCITON_HPP__
|
#endif // __ARMMEMORYINSTRUCITON_HPP__
|
||||||
|
|
||||||
|
|||||||
@ -12,19 +12,19 @@ regdata_t BochsCPU::getRegisterContent(const Register* reg) const
|
|||||||
|
|
||||||
if (reg->getId() == RID_FLAGS) { // EFLAGS register?
|
if (reg->getId() == RID_FLAGS) { // EFLAGS register?
|
||||||
return static_cast<regdata_t>(BX_CPU(id)->read_eflags());
|
return static_cast<regdata_t>(BX_CPU(id)->read_eflags());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SIM_SUPPORT_64
|
#ifdef SIM_SUPPORT_64
|
||||||
if (reg->getId() == RID_PC) // program counter?
|
if (reg->getId() == RID_PC) // program counter?
|
||||||
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx);
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx);
|
||||||
else // 64 bit general purpose registers
|
else // 64 bit general purpose registers
|
||||||
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[reg->getId()].rrx);
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[reg->getId()].rrx);
|
||||||
#else // 32 bit mode
|
#else // 32 bit mode
|
||||||
if (reg->getId() == RID_PC)
|
if (reg->getId() == RID_PC)
|
||||||
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
||||||
else // 32 bit general purpose registers
|
else // 32 bit general purpose registers
|
||||||
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[reg->getId()].dword.erx);
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[reg->getId()].dword.erx);
|
||||||
#endif // SIM_SUPPORT_64
|
#endif // SIM_SUPPORT_64
|
||||||
}
|
}
|
||||||
|
|
||||||
void BochsCPU::setRegisterContent(const Register* reg, regdata_t value)
|
void BochsCPU::setRegisterContent(const Register* reg, regdata_t value)
|
||||||
@ -46,17 +46,17 @@ void BochsCPU::setRegisterContent(const Register* reg, regdata_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
regdata_t* pData;
|
regdata_t* pData;
|
||||||
#ifdef SIM_SUPPORT_64
|
#ifdef SIM_SUPPORT_64
|
||||||
if (reg->getId() == RID_PC) // program counter?
|
if (reg->getId() == RID_PC) // program counter?
|
||||||
pData = &(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx);
|
pData = &(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx);
|
||||||
else // 64 bit general purpose registers
|
else // 64 bit general purpose registers
|
||||||
pData = &(BX_CPU(id)->gen_reg[reg->getId()].rrx);
|
pData = &(BX_CPU(id)->gen_reg[reg->getId()].rrx);
|
||||||
#else // 32 bit mode
|
#else // 32 bit mode
|
||||||
if (reg->getId() == RID_PC)
|
if (reg->getId() == RID_PC)
|
||||||
pData = &(BX_CPU(id)->gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
pData = &(BX_CPU(id)->gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
||||||
else // 32 bit general purpose registers
|
else // 32 bit general purpose registers
|
||||||
pData = &(BX_CPU(id)->gen_reg[reg->getId()].dword.erx);
|
pData = &(BX_CPU(id)->gen_reg[reg->getId()].dword.erx);
|
||||||
#endif // SIM_SUPPORT_64
|
#endif // SIM_SUPPORT_64
|
||||||
*pData = value;
|
*pData = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __BOCHS_CPU_HPP__
|
#ifndef __BOCHS_CPU_HPP__
|
||||||
#define __BOCHS_CPU_HPP__
|
#define __BOCHS_CPU_HPP__
|
||||||
|
|
||||||
#include "../x86/X86Architecture.hpp"
|
#include "../x86/X86Architecture.hpp"
|
||||||
#include "../x86/X86CPUState.hpp"
|
#include "../x86/X86CPUState.hpp"
|
||||||
@ -11,12 +11,12 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class BochsCPU
|
* \class BochsCPU
|
||||||
*
|
*
|
||||||
* \c BochsCPU is the concrete CPU implementation for the Bochs x86 simulator. It
|
* \c BochsCPU is the concrete CPU implementation for the Bochs x86 simulator. It
|
||||||
* implements the CPU interfaces \c X86Architecture and \c X86CPUState.
|
* implements the CPU interfaces \c X86Architecture and \c X86CPUState.
|
||||||
* \c X86Architecture refers to architectural information (e.g. register \a count)
|
* \c X86Architecture refers to architectural information (e.g. register \a count)
|
||||||
* while \c X86CPUState encapsulates the CPU state (e.g. register \a content).
|
* while \c X86CPUState encapsulates the CPU state (e.g. register \a content).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class BochsCPU : public X86Architecture, public X86CPUState {
|
class BochsCPU : public X86Architecture, public X86CPUState {
|
||||||
private:
|
private:
|
||||||
@ -29,7 +29,7 @@ public:
|
|||||||
BochsCPU(unsigned int id) : m_Id(id) { }
|
BochsCPU(unsigned int id) : m_Id(id) { }
|
||||||
/**
|
/**
|
||||||
* Virtual Destructor is required.
|
* Virtual Destructor is required.
|
||||||
*/
|
*/
|
||||||
virtual ~BochsCPU() { }
|
virtual ~BochsCPU() { }
|
||||||
/**
|
/**
|
||||||
* Retrieves the content of the register \c reg.
|
* Retrieves the content of the register \c reg.
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __BOCHS_CONFIG_HPP__
|
#ifndef __BOCHS_CONFIG_HPP__
|
||||||
#define __BOCHS_CONFIG_HPP__
|
#define __BOCHS_CONFIG_HPP__
|
||||||
|
|
||||||
#include "bochs.h"
|
#include "bochs.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -15,15 +15,15 @@ namespace fail {
|
|||||||
typedef bx_address guest_address_t; //!< the guest memory address type
|
typedef bx_address guest_address_t; //!< the guest memory address type
|
||||||
typedef Bit8u* host_address_t; //!< the host memory address type
|
typedef Bit8u* host_address_t; //!< the host memory address type
|
||||||
#if BX_SUPPORT_X86_64
|
#if BX_SUPPORT_X86_64
|
||||||
typedef Bit64u register_data_t; //!< register data type (64 bit)
|
typedef Bit64u register_data_t; //!< register data type (64 bit)
|
||||||
#else
|
#else
|
||||||
typedef Bit32u register_data_t; //!< register data type (32 bit)
|
typedef Bit32u register_data_t; //!< register data type (32 bit)
|
||||||
#endif
|
#endif
|
||||||
typedef int timer_t; //!< type of timer IDs
|
typedef int timer_t; //!< type of timer IDs
|
||||||
|
|
||||||
// 'Publish' 64 bit ability (if enabled in Bochs):
|
// 'Publish' 64 bit ability (if enabled in Bochs):
|
||||||
#if BX_SUPPORT_X86_64
|
#if BX_SUPPORT_X86_64
|
||||||
#define SIM_SUPPORT_64
|
#define SIM_SUPPORT_64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -80,14 +80,14 @@ void BochsController::onIOPort(ConcreteCPU* cpu, unsigned char data, unsigned po
|
|||||||
bool BochsController::save(const std::string& path)
|
bool BochsController::save(const std::string& path)
|
||||||
{
|
{
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
stat = mkdir(path.c_str(), 0777);
|
stat = mkdir(path.c_str(), 0777);
|
||||||
if (!(stat == 0 || errno == EEXIST)) {
|
if (!(stat == 0 || errno == EEXIST)) {
|
||||||
return false;
|
return false;
|
||||||
// std::cout << "[FAIL] Can not create target-directory to save!" << std::endl;
|
// std::cout << "[FAIL] Can not create target-directory to save!" << std::endl;
|
||||||
// TODO: (Non-)Verbose-Mode? Log-level? Maybe better: use return value to indicate failure?
|
// TODO: (Non-)Verbose-Mode? Log-level? Maybe better: use return value to indicate failure?
|
||||||
}
|
}
|
||||||
|
|
||||||
save_bochs_request = true;
|
save_bochs_request = true;
|
||||||
BX_CPU(0)->async_event |= 1;
|
BX_CPU(0)->async_event |= 1;
|
||||||
sr_path = path;
|
sr_path = path;
|
||||||
@ -164,12 +164,12 @@ const std::string& BochsController::getMnemonic() const
|
|||||||
ConcreteCPU& BochsController::detectCPU(BX_CPU_C* pCPU) const
|
ConcreteCPU& BochsController::detectCPU(BX_CPU_C* pCPU) const
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
#if BX_SUPPORT_SMP
|
#if BX_SUPPORT_SMP
|
||||||
for (; i < BX_SMP_PROCESSORS; i++) {
|
for (; i < BX_SMP_PROCESSORS; i++) {
|
||||||
if (BX_CPU_C[i] == pCPU) // cmp this ptr with all possible CPU objects
|
if (BX_CPU_C[i] == pCPU) // cmp this ptr with all possible CPU objects
|
||||||
break; // index "i" found! -> stop!
|
break; // index "i" found! -> stop!
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return getCPU(i);
|
return getCPU(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __BOCHS_CONTROLLER_HPP__
|
#ifndef __BOCHS_CONTROLLER_HPP__
|
||||||
#define __BOCHS_CONTROLLER_HPP__
|
#define __BOCHS_CONTROLLER_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -25,7 +25,7 @@ class ExperimentFlow;
|
|||||||
/**
|
/**
|
||||||
* \class BochsController
|
* \class BochsController
|
||||||
* Bochs-specific implementation of a SimulatorController.
|
* Bochs-specific implementation of a SimulatorController.
|
||||||
*
|
*
|
||||||
* @note The instruction (IP) pointer modification handler (onBreakpoint())
|
* @note The instruction (IP) pointer modification handler (onBreakpoint())
|
||||||
* is called (from the Breakpoints aspect) *every* time the Bochs-internal IP
|
* is called (from the Breakpoints aspect) *every* time the Bochs-internal IP
|
||||||
* changes. The handler itself evaluates if a breakpoint event needs to be
|
* changes. The handler itself evaluates if a breakpoint event needs to be
|
||||||
@ -65,7 +65,7 @@ public:
|
|||||||
* object within the ListenerManager and fires such an event by calling
|
* object within the ListenerManager and fires such an event by calling
|
||||||
* \c triggerActiveListeners().
|
* \c triggerActiveListeners().
|
||||||
* @param thisPtr a pointer to the TimerListener-object triggered
|
* @param thisPtr a pointer to the TimerListener-object triggered
|
||||||
*
|
*
|
||||||
* FIXME: Due to Bochs internal timer and ips-configuration related stuff,
|
* FIXME: Due to Bochs internal timer and ips-configuration related stuff,
|
||||||
* the simulator sometimes panics with "keyboard error:21" (see line
|
* the simulator sometimes panics with "keyboard error:21" (see line
|
||||||
* 1777 in bios/rombios.c, function keyboard_init()) if a TimerListener
|
* 1777 in bios/rombios.c, function keyboard_init()) if a TimerListener
|
||||||
@ -112,7 +112,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void fireInterrupt(unsigned irq);
|
void fireInterrupt(unsigned irq);
|
||||||
/**
|
/**
|
||||||
* Fire done: Callback from Simulator
|
* Fire done: Callback from Simulator
|
||||||
*/
|
*/
|
||||||
void fireInterruptDone();
|
void fireInterruptDone();
|
||||||
virtual simtime_t getTimerTicks() { return bx_pc_system.time_ticks(); }
|
virtual simtime_t getTimerTicks() { return bx_pc_system.time_ticks(); }
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __BOCHS_HELPERS_HPP__
|
#ifndef __BOCHS_HELPERS_HPP__
|
||||||
#define __BOCHS_HELPERS_HPP__
|
#define __BOCHS_HELPERS_HPP__
|
||||||
|
|
||||||
#include "cpu/cpu.h"
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __BOCHS_LISTENER_HPP__
|
#ifndef __BOCHS_LISTENER_HPP__
|
||||||
#define __BOCHS_LISTENER_HPP__
|
#define __BOCHS_LISTENER_HPP__
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __BOCHS_MEMORY_HPP__
|
#ifndef __BOCHS_MEMORY_HPP__
|
||||||
#define __BOCHS_MEMORY_HPP__
|
#define __BOCHS_MEMORY_HPP__
|
||||||
|
|
||||||
#include "../Memory.hpp"
|
#include "../Memory.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __FAIL_BOCHS_GLOBALS_HPP__
|
#ifndef __FAIL_BOCHS_GLOBALS_HPP__
|
||||||
#define __FAIL_BOCHS_GLOBALS_HPP__
|
#define __FAIL_BOCHS_GLOBALS_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -8,9 +8,9 @@
|
|||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
#ifdef DANCEOS_RESTORE
|
#ifdef DANCEOS_RESTORE
|
||||||
extern bx_bool restore_bochs_request;
|
extern bx_bool restore_bochs_request;
|
||||||
extern bx_bool save_bochs_request;
|
extern bx_bool save_bochs_request;
|
||||||
extern std::string sr_path;
|
extern std::string sr_path;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bx_bool reboot_bochs_request;
|
extern bx_bool reboot_bochs_request;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __GEM5_ARM_CPU_HPP__
|
#ifndef __GEM5_ARM_CPU_HPP__
|
||||||
#define __GEM5_ARM_CPU_HPP__
|
#define __GEM5_ARM_CPU_HPP__
|
||||||
|
|
||||||
#include "../arm/ArmArchitecture.hpp"
|
#include "../arm/ArmArchitecture.hpp"
|
||||||
#include "../arm/ArmCPUState.hpp"
|
#include "../arm/ArmCPUState.hpp"
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __GEM5_CONFIG_HPP__
|
#ifndef __GEM5_CONFIG_HPP__
|
||||||
#define __GEM5_CONFIG_HPP__
|
#define __GEM5_CONFIG_HPP__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __GEM5_CONTROLLER_HPP__
|
#ifndef __GEM5_CONTROLLER_HPP__
|
||||||
#define __GEM5_CONTROLLER_HPP__
|
#define __GEM5_CONTROLLER_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ public:
|
|||||||
virtual simtime_t getTimerTicksPerSecond();
|
virtual simtime_t getTimerTicksPerSecond();
|
||||||
#if defined(CONFIG_EVENT_BREAKPOINTS) ||\
|
#if defined(CONFIG_EVENT_BREAKPOINTS) ||\
|
||||||
defined(CONFIG_EVENT_BREAKPOINTS_RANGE)
|
defined(CONFIG_EVENT_BREAKPOINTS_RANGE)
|
||||||
void setMnemonic(const std::string& mn) { m_Mnemonic = mn; }
|
void setMnemonic(const std::string& mn) { m_Mnemonic = mn; }
|
||||||
const std::string& getMnemonic() const { return m_Mnemonic; }
|
const std::string& getMnemonic() const { return m_Mnemonic; }
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __GEM5_MEMORY_HPP__
|
#ifndef __GEM5_MEMORY_HPP__
|
||||||
#define __GEM5_MEMORY_HPP__
|
#define __GEM5_MEMORY_HPP__
|
||||||
|
|
||||||
#include "../Memory.hpp"
|
#include "../Memory.hpp"
|
||||||
#include "Gem5Wrapper.hpp"
|
#include "Gem5Wrapper.hpp"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __GEM5_WRAPPER_HPP__
|
#ifndef __GEM5_WRAPPER_HPP__
|
||||||
#define __GEM5_WRAPPER_HPP__
|
#define __GEM5_WRAPPER_HPP__
|
||||||
|
|
||||||
#include "../Register.hpp"
|
#include "../Register.hpp"
|
||||||
#include "../SALConfig.hpp"
|
#include "../SALConfig.hpp"
|
||||||
|
|||||||
@ -10,7 +10,7 @@ ResultSet& PerfVectorBreakpoints::gather(BPEvent* pData)
|
|||||||
static ResultSet res;
|
static ResultSet res;
|
||||||
res.clear(); // FIXME: This should not free the memory of the underlying std::vector.
|
res.clear(); // FIXME: This should not free the memory of the underlying std::vector.
|
||||||
// Search for all indices of matching listener objects:
|
// Search for all indices of matching listener objects:
|
||||||
for(std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
for (std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
||||||
BPListener* pLi = static_cast<BPListener*>(simulator.dereference(*it));
|
BPListener* pLi = static_cast<BPListener*>(simulator.dereference(*it));
|
||||||
if (pLi->isMatching(pData)) {
|
if (pLi->isMatching(pData)) {
|
||||||
// Update trigger IPtr:
|
// Update trigger IPtr:
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#ifndef __BREAKPOINT_BUFFER_HPP__
|
#ifndef __BREAKPOINT_BUFFER_HPP__
|
||||||
#define __BREAKPOINT_BUFFER_HPP__
|
#define __BREAKPOINT_BUFFER_HPP__
|
||||||
|
|
||||||
#include "BufferInterface.hpp"
|
#include "BufferInterface.hpp"
|
||||||
|
|
||||||
// TODOs:
|
// TODOs:
|
||||||
// - Make these implementations even faster (see below: continue PerfVecSortedSingleBP).
|
// - Make these implementations even faster (see below: continue PerfVecSortedSingleBP).
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
@ -20,7 +20,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class PerfVecSortedSingleBP
|
* \class PerfVecSortedSingleBP
|
||||||
*
|
*
|
||||||
* This class implements a faster mechanism to store BPSingleListener
|
* This class implements a faster mechanism to store BPSingleListener
|
||||||
* based on binary search on their corresponding instruction pointer.
|
* based on binary search on their corresponding instruction pointer.
|
||||||
*/
|
*/
|
||||||
@ -52,7 +52,7 @@ public:
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CompareInstrPtr(index_t arg1, index_t arg2, void* pStuff)
|
static bool CompareInstrPtr(index_t arg1, index_t arg2, void* pStuff)
|
||||||
{
|
{
|
||||||
SimulatorController* pSim = static_cast<SimulatorController*>(pStuff);
|
SimulatorController* pSim = static_cast<SimulatorController*>(pStuff);
|
||||||
@ -80,9 +80,9 @@ public:
|
|||||||
|
|
||||||
while (first <= last) {
|
while (first <= last) {
|
||||||
int mid = (first + last) / 2; // compute mid point.
|
int mid = (first + last) / 2; // compute mid point.
|
||||||
if (VAL(key) > VAL(vec[mid]))
|
if (VAL(key) > VAL(vec[mid]))
|
||||||
first = mid + 1; // repeat search in top half.
|
first = mid + 1; // repeat search in top half.
|
||||||
else if (VAL(key) < VAL(vec[mid]))
|
else if (VAL(key) < VAL(vec[mid]))
|
||||||
last = mid - 1; // repeat search in bottom half.
|
last = mid - 1; // repeat search in bottom half.
|
||||||
else
|
else
|
||||||
return mid; // found it. return position
|
return mid; // found it. return position
|
||||||
@ -100,7 +100,7 @@ public:
|
|||||||
// TODO: Improve this by using binary search, too!
|
// TODO: Improve this by using binary search, too!
|
||||||
ResultSet res;
|
ResultSet res;
|
||||||
// Search for all indices of matching listener objects:
|
// Search for all indices of matching listener objects:
|
||||||
for(std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
for (std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
||||||
BPListener* pLi = static_cast<BPListener*>(simulator.dereference(*it));
|
BPListener* pLi = static_cast<BPListener*>(simulator.dereference(*it));
|
||||||
if (pLi->isMatching(pData)) {
|
if (pLi->isMatching(pData)) {
|
||||||
// Update trigger IPtr:
|
// Update trigger IPtr:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __BUFFER_INTERFACE_HPP__
|
#ifndef __BUFFER_INTERFACE_HPP__
|
||||||
#define __BUFFER_INTERFACE_HPP__
|
#define __BUFFER_INTERFACE_HPP__
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -58,7 +58,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class DefPerfVector
|
* \class DefPerfVector
|
||||||
*
|
*
|
||||||
* Default \c std::vector based performance implementation (abstract)
|
* Default \c std::vector based performance implementation (abstract)
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|||||||
@ -11,7 +11,7 @@ ResultSet& PerfVectorWatchpoints::gather(MemAccessEvent* pData)
|
|||||||
static ResultSet res;
|
static ResultSet res;
|
||||||
res.clear(); // FIXME: This should not free the memory of the underlying std::vector.
|
res.clear(); // FIXME: This should not free the memory of the underlying std::vector.
|
||||||
// Search for all indices of matching listener objects:
|
// Search for all indices of matching listener objects:
|
||||||
for(std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
for (std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
||||||
MemAccessListener* pmal = static_cast<MemAccessListener*>(simulator.dereference(*it));
|
MemAccessListener* pmal = static_cast<MemAccessListener*>(simulator.dereference(*it));
|
||||||
if (pmal->isMatching(pData)) {
|
if (pmal->isMatching(pData)) {
|
||||||
// Update trigger data:
|
// Update trigger data:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __WATCHPOINT_BUFFER_HPP__
|
#ifndef __WATCHPOINT_BUFFER_HPP__
|
||||||
#define __WATCHPOINT_BUFFER_HPP__
|
#define __WATCHPOINT_BUFFER_HPP__
|
||||||
|
|
||||||
#include "BufferInterface.hpp"
|
#include "BufferInterface.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __QEMU_CONFIG_HPP__
|
#ifndef __QEMU_CONFIG_HPP__
|
||||||
#define __QEMU_CONFIG_HPP__
|
#define __QEMU_CONFIG_HPP__
|
||||||
|
|
||||||
// FIXME: qemu/targphys.h defines address types (but relies on a global preprocessor macro)
|
// FIXME: qemu/targphys.h defines address types (but relies on a global preprocessor macro)
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __QEMU_CONTROLLER_HPP__
|
#ifndef __QEMU_CONTROLLER_HPP__
|
||||||
#define __QEMU_CONTROLLER_HPP__
|
#define __QEMU_CONTROLLER_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __QEMU_MEMORY_HPP__
|
#ifndef __QEMU_MEMORY_HPP__
|
||||||
#define __QEMU_MEMORY_HPP__
|
#define __QEMU_MEMORY_HPP__
|
||||||
|
|
||||||
#include "../Memory.hpp"
|
#include "../Memory.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __QEMU_REGISTER_HPP__
|
#ifndef __QEMU_REGISTER_HPP__
|
||||||
#define __QEMU_REGISTER_HPP__
|
#define __QEMU_REGISTER_HPP__
|
||||||
|
|
||||||
#include "../Register.hpp"
|
#include "../Register.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -8,50 +8,50 @@ static const uint64_t lower = 0x00000000ffffffff;
|
|||||||
|
|
||||||
regdata_t T32ArmCPU::getRegisterContent(const Register* reg) const
|
regdata_t T32ArmCPU::getRegisterContent(const Register* reg) const
|
||||||
{
|
{
|
||||||
// T32_ReadRegister wants a mask of bits representig the registers to read:
|
// T32_ReadRegister wants a mask of bits representig the registers to read:
|
||||||
// e.g., reading R1 and R4 and R63
|
// e.g., reading R1 and R4 and R63
|
||||||
// mask1
|
// mask1
|
||||||
// 0000 0000 0000 0000 0001 0010 -> R1/R4
|
// 0000 0000 0000 0000 0001 0010 -> R1/R4
|
||||||
// mask2
|
// mask2
|
||||||
// 1000 0000 0000 0000 0000 0000 -> R63
|
// 1000 0000 0000 0000 0000 0000 -> R63
|
||||||
uint64_t mask = (1 << reg->getIndex());
|
uint64_t mask = (1 << reg->getIndex());
|
||||||
|
|
||||||
if(mask){
|
if (mask) {
|
||||||
if( T32_ReadRegister(static_cast<dword>(mask & lower ), static_cast<dword>(mask >> 32), m_regbuffer) == 0 ){
|
if ( T32_ReadRegister(static_cast<dword>(mask & lower ), static_cast<dword>(mask >> 32), m_regbuffer) == 0 ) {
|
||||||
// No error, return value.
|
// No error, return value.
|
||||||
return m_regbuffer[reg->getIndex()];
|
return m_regbuffer[reg->getIndex()];
|
||||||
} else {
|
} else {
|
||||||
/// TODO Error handling!
|
/// TODO Error handling!
|
||||||
std::cout << "could not read register :(" << std::endl;
|
std::cout << "could not read register :(" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0; // we should not come here.
|
return 0; // we should not come here.
|
||||||
}
|
}
|
||||||
|
|
||||||
void T32ArmCPU::setRegisterContent(const Register* reg, regdata_t value)
|
void T32ArmCPU::setRegisterContent(const Register* reg, regdata_t value)
|
||||||
{
|
{
|
||||||
uint64_t mask = (1 << reg->getIndex());
|
uint64_t mask = (1 << reg->getIndex());
|
||||||
|
|
||||||
// set value to be set by T32:
|
// set value to be set by T32:
|
||||||
m_regbuffer[reg->getIndex()] = value;
|
m_regbuffer[reg->getIndex()] = value;
|
||||||
if(mask){
|
if (mask) {
|
||||||
if( T32_WriteRegister(static_cast<dword>(mask & lower), static_cast<dword>(mask >> 32), m_regbuffer) == 0 ){
|
if ( T32_WriteRegister(static_cast<dword>(mask & lower), static_cast<dword>(mask >> 32), m_regbuffer) == 0 ) {
|
||||||
// No error, return value.
|
// No error, return value.
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
/// TODO Error handling!
|
/// TODO Error handling!
|
||||||
std::cout << "could not write register :(" << std::endl;
|
std::cout << "could not write register :(" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
address_t T32ArmCPU::getInstructionPointer() const
|
address_t T32ArmCPU::getInstructionPointer() const
|
||||||
{
|
{
|
||||||
// TODO: programpointer is only valid when Emulation is stopped! -> T32_GetState)
|
// TODO: programpointer is only valid when Emulation is stopped! -> T32_GetState)
|
||||||
address_t programpointer;
|
address_t programpointer;
|
||||||
T32_ReadPP( &programpointer );
|
T32_ReadPP( &programpointer );
|
||||||
return programpointer;
|
return programpointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __T32_ARM_CPU_HPP__
|
#ifndef __T32_ARM_CPU_HPP__
|
||||||
#define __T32_ARM_CPU_HPP__
|
#define __T32_ARM_CPU_HPP__
|
||||||
|
|
||||||
#include "../arm/ArmArchitecture.hpp"
|
#include "../arm/ArmArchitecture.hpp"
|
||||||
#include "../arm/ArmCPUState.hpp"
|
#include "../arm/ArmCPUState.hpp"
|
||||||
@ -39,7 +39,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Retrieves the current instruction pointer (IP aka program counter, PC for short)
|
* Retrieves the current instruction pointer (IP aka program counter, PC for short)
|
||||||
* for the current CPU \c this.
|
* for the current CPU \c this.
|
||||||
* @return the current instruction ptr address
|
* @return the current instruction ptr address
|
||||||
*/
|
*/
|
||||||
address_t getInstructionPointer() const;
|
address_t getInstructionPointer() const;
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ public:
|
|||||||
unsigned int getId() const { return m_Id; }
|
unsigned int getId() const { return m_Id; }
|
||||||
private:
|
private:
|
||||||
unsigned int m_Id; //!< the unique ID of this CPU
|
unsigned int m_Id; //!< the unique ID of this CPU
|
||||||
mutable dword m_regbuffer[64]; //!< internal buffer for reading/writing registers, wow mutable really makes sense sometimes.
|
mutable dword m_regbuffer[64]; //!< internal buffer for reading/writing registers, wow mutable really makes sense sometimes.
|
||||||
// char* cpuname? OMAP4430APP1 ??
|
// char* cpuname? OMAP4430APP1 ??
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -6,35 +6,36 @@
|
|||||||
#define __T32_CONSTANTS_HPP__
|
#define __T32_CONSTANTS_HPP__
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
namespace T32 {
|
namespace T32 {
|
||||||
//!< Breakpoint configuration
|
|
||||||
struct BP {
|
//!< Breakpoint configuration
|
||||||
enum {
|
struct BP {
|
||||||
EXECUTION = 1<<0,
|
enum {
|
||||||
HLL_STEP = 1<<1,
|
EXECUTION = 1<<0,
|
||||||
SPOT = 1<<2,
|
HLL_STEP = 1<<1,
|
||||||
READ = 1<<3,
|
SPOT = 1<<2,
|
||||||
WRITE = 1<<4,
|
READ = 1<<3,
|
||||||
ALPHA = 1<<5,
|
WRITE = 1<<4,
|
||||||
BETA = 1<<6,
|
ALPHA = 1<<5,
|
||||||
CHARLY = 1<<7,
|
BETA = 1<<6,
|
||||||
CLEAR = 1<<8,
|
CHARLY = 1<<7,
|
||||||
};
|
CLEAR = 1<<8,
|
||||||
}; // struct BP
|
};
|
||||||
|
}; // struct BP
|
||||||
|
|
||||||
|
|
||||||
//!< Memory access variants
|
//!< Memory access variants
|
||||||
struct MEMACCESS {
|
struct MEMACCESS {
|
||||||
enum {
|
enum {
|
||||||
DATA = 0,
|
DATA = 0,
|
||||||
PROGRAM = 1,
|
PROGRAM = 1,
|
||||||
AD = 12,
|
AD = 12,
|
||||||
AP = 13,
|
AP = 13,
|
||||||
USR = 15,
|
USR = 15,
|
||||||
};
|
};
|
||||||
}; // struct MEMACCESS
|
}; // struct MEMACCESS
|
||||||
|
|
||||||
}; // namespace T32
|
}; // namespace T32
|
||||||
}; // namespace fail
|
}; // namespace fail
|
||||||
#endif // __T32_CONSTANTS_HPP__
|
#endif // __T32_CONSTANTS_HPP__
|
||||||
|
|
||||||
|
|||||||
@ -4,11 +4,11 @@
|
|||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
void T32Controller::startup(){
|
void T32Controller::startup(){
|
||||||
// Do some T32-specific startup
|
// Do some T32-specific startup
|
||||||
addCPU(new ConcreteCPU(0));
|
addCPU(new ConcreteCPU(0));
|
||||||
// Startup generic SimulatorController
|
// Startup generic SimulatorController
|
||||||
// TODO pass on command-line parameters
|
// TODO pass on command-line parameters
|
||||||
SimulatorController::startup();
|
SimulatorController::startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,8 @@ namespace fail {
|
|||||||
*/
|
*/
|
||||||
class T32Controller : public SimulatorController {
|
class T32Controller : public SimulatorController {
|
||||||
public:
|
public:
|
||||||
void startup();
|
void startup();
|
||||||
T32Controller() : SimulatorController(new T32MemoryManager()) { };
|
T32Controller() : SimulatorController(new T32MemoryManager()) { };
|
||||||
~T32Controller();
|
~T32Controller();
|
||||||
|
|
||||||
/* ********************************************************************
|
/* ********************************************************************
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __T32_MEMORY_HPP__
|
#ifndef __T32_MEMORY_HPP__
|
||||||
#define __T32_MEMORY_HPP__
|
#define __T32_MEMORY_HPP__
|
||||||
|
|
||||||
#include "../Memory.hpp"
|
#include "../Memory.hpp"
|
||||||
#include <t32.h>
|
#include <t32.h>
|
||||||
@ -21,26 +21,26 @@ public:
|
|||||||
|
|
||||||
byte_t getByte(guest_address_t addr)
|
byte_t getByte(guest_address_t addr)
|
||||||
{
|
{
|
||||||
char b;
|
char b;
|
||||||
getBytes(addr, 1, &b);
|
getBytes(addr, 1, &b);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getBytes(guest_address_t addr, size_t cnt, void *dest)
|
void getBytes(guest_address_t addr, size_t cnt, void *dest)
|
||||||
{
|
{
|
||||||
int access = T32::MEMACCESS::DATA; // TODO what access class do we need?!
|
int access = T32::MEMACCESS::DATA; // TODO what access class do we need?!
|
||||||
T32_ReadMemory( addr, access, (byte*)(dest), cnt);
|
T32_ReadMemory( addr, access, (byte*)(dest), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setByte(guest_address_t addr, byte_t data)
|
void setByte(guest_address_t addr, byte_t data)
|
||||||
{
|
{
|
||||||
setBytes(addr, 1, &data);
|
setBytes(addr, 1, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBytes(guest_address_t addr, size_t cnt, void const *src)
|
void setBytes(guest_address_t addr, size_t cnt, void const *src)
|
||||||
{
|
{
|
||||||
int access = T32::MEMACCESS::DATA; // TODO what access class do we really need?!
|
int access = T32::MEMACCESS::DATA; // TODO what access class do we really need?!
|
||||||
T32_WriteMemory(addr, access, (byte*)(src), cnt);
|
T32_WriteMemory(addr, access, (byte*)(src), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,35 +8,35 @@ X86Architecture::X86Architecture()
|
|||||||
{
|
{
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Add the general purpose register:
|
// Add the general purpose register:
|
||||||
#ifdef SIM_SUPPORT_64
|
#ifdef SIM_SUPPORT_64
|
||||||
// -- 64 bit register --
|
// -- 64 bit register --
|
||||||
const std::string names[] = { "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8",
|
const std::string names[] = { "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8",
|
||||||
"R9", "R10", "R11", "R12", "R13", "R14", "R15" };
|
"R9", "R10", "R11", "R12", "R13", "R14", "R15" };
|
||||||
for (unsigned short i = 0; i < 16; i++) {
|
for (unsigned short i = 0; i < 16; i++) {
|
||||||
Register* pReg = new Register(i, 64);
|
Register* pReg = new Register(i, 64);
|
||||||
pReg->setName(names[i]);
|
pReg->setName(names[i]);
|
||||||
m_addRegister(pReg, RT_GP);
|
m_addRegister(pReg, RT_GP);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// -- 32 bit register --
|
// -- 32 bit register --
|
||||||
const std::string names[] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" };
|
const std::string names[] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" };
|
||||||
for (unsigned short i = 0; i < 8; i++) {
|
for (unsigned short i = 0; i < 8; i++) {
|
||||||
Register* pReg = new Register(i, 32);
|
Register* pReg = new Register(i, 32);
|
||||||
pReg->setName(names[i]);
|
pReg->setName(names[i]);
|
||||||
m_addRegister(pReg, RT_GP);
|
m_addRegister(pReg, RT_GP);
|
||||||
}
|
}
|
||||||
#endif // SIM_SUPPORT_64
|
#endif // SIM_SUPPORT_64
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Add the program counter (PC) register:
|
// Add the program counter (PC) register:
|
||||||
#ifdef SIM_SUPPORT_64
|
#ifdef SIM_SUPPORT_64
|
||||||
Register* pPCReg = new Register(RID_PC, 64);
|
Register* pPCReg = new Register(RID_PC, 64);
|
||||||
pPCReg->setName("RIP");
|
pPCReg->setName("RIP");
|
||||||
#else
|
#else
|
||||||
Register* pPCReg = new Register(RID_PC, 32);
|
Register* pPCReg = new Register(RID_PC, 32);
|
||||||
pPCReg->setName("EIP");
|
pPCReg->setName("EIP");
|
||||||
#endif // SIM_SUPPORT_64
|
#endif // SIM_SUPPORT_64
|
||||||
m_addRegister(pPCReg, RT_IP);
|
m_addRegister(pPCReg, RT_IP);
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Add the status register (EFLAGS):
|
// Add the status register (EFLAGS):
|
||||||
Register* pFlagReg = new Register(RID_FLAGS, 32);
|
Register* pFlagReg = new Register(RID_FLAGS, 32);
|
||||||
pFlagReg->setName("EFLAGS");
|
pFlagReg->setName("EFLAGS");
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __X86_ARCHITECTURE_HPP__
|
#ifndef __X86_ARCHITECTURE_HPP__
|
||||||
#define __X86_ARCHITECTURE_HPP__
|
#define __X86_ARCHITECTURE_HPP__
|
||||||
|
|
||||||
#include "../CPU.hpp"
|
#include "../CPU.hpp"
|
||||||
#include "../CPUState.hpp"
|
#include "../CPUState.hpp"
|
||||||
@ -35,8 +35,8 @@ enum GPRegisterId {
|
|||||||
#else // 32 bit register id's:
|
#else // 32 bit register id's:
|
||||||
RID_EAX = 0, RID_ECX, RID_EDX, RID_EBX, RID_ESP, RID_EBP, RID_ESI, RID_EDI,
|
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):
|
#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_CAX = 0, RID_CCX, RID_CDX, RID_CBX, RID_CSP, RID_CBP, RID_CSI, RID_CDI,
|
||||||
RID_LAST_GP_ID
|
RID_LAST_GP_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __X86_CPU_STATE_HPP__
|
#ifndef __X86_CPU_STATE_HPP__
|
||||||
#define __X86_CPU_STATE_HPP__
|
#define __X86_CPU_STATE_HPP__
|
||||||
|
|
||||||
#include "../CPU.hpp"
|
#include "../CPU.hpp"
|
||||||
#include "../CPUState.hpp"
|
#include "../CPUState.hpp"
|
||||||
@ -23,7 +23,7 @@ public:
|
|||||||
* @return the current (E)FLAGS processor register content
|
* @return the current (E)FLAGS processor register content
|
||||||
*/
|
*/
|
||||||
virtual regdata_t getFlagsRegister() const = 0;
|
virtual regdata_t getFlagsRegister() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns \c true if the corresponding flag is set, or \c false
|
* Returns \c true if the corresponding flag is set, or \c false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
|
|||||||
@ -5,65 +5,65 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
CommandLine CommandLine::m_instance;
|
CommandLine CommandLine::m_instance;
|
||||||
|
|
||||||
void CommandLine::collect_args(argument_count &argc, argument_value &argv) {
|
void CommandLine::collect_args(argument_count &argc, argument_value &argv) {
|
||||||
// Filter out all command line arguments that start with -Wf,
|
// Filter out all command line arguments that start with -Wf,
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
if (strncmp(argv[i], "-Wf,", 4) == 0) {
|
if (strncmp(argv[i], "-Wf,", 4) == 0) {
|
||||||
this->argv.push_back(argv[i] + 4);
|
this->argv.push_back(argv[i] + 4);
|
||||||
|
|
||||||
// also copy argv[argc], which equals 0
|
// also copy argv[argc], which equals 0
|
||||||
for (int x = i + 1; x <= argc; ++x) {
|
for (int x = i + 1; x <= argc; ++x) {
|
||||||
argv[x - 1] = argv[x];
|
argv[x - 1] = argv[x];
|
||||||
}
|
}
|
||||||
i --;
|
i --;
|
||||||
argc --;
|
argc --;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLine::option_handle CommandLine::addOption(const std::string &shortopt,
|
CommandLine::option_handle CommandLine::addOption(
|
||||||
const std::string &longopt,
|
const std::string &shortopt,
|
||||||
const option::CheckArg & check_arg,
|
const std::string &longopt,
|
||||||
const std::string &help) {
|
const option::CheckArg & check_arg,
|
||||||
|
const std::string &help) {
|
||||||
|
|
||||||
const unsigned int handle = this->options.size();
|
const unsigned int handle = this->options.size();
|
||||||
option::Descriptor desc = {handle, 0, strdup(shortopt.c_str()),
|
option::Descriptor desc = {handle, 0, strdup(shortopt.c_str()),
|
||||||
strdup(longopt.c_str()),
|
strdup(longopt.c_str()),
|
||||||
check_arg, strdup(help.c_str())};
|
check_arg, strdup(help.c_str())};
|
||||||
this->options.push_back(desc);
|
this->options.push_back(desc);
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLine::parse() {
|
bool CommandLine::parse() {
|
||||||
// Terminate the descriptor list
|
// Terminate the descriptor list
|
||||||
option::Descriptor desc = {0, 0, 0, 0, 0, 0};
|
option::Descriptor desc = {0, 0, 0, 0, 0, 0};
|
||||||
this->options.push_back(desc);
|
this->options.push_back(desc);
|
||||||
|
|
||||||
// Generate the options stats
|
// Generate the options stats
|
||||||
option::Stats stats(this->options.data(), argv.size(), argv.data());
|
option::Stats stats(this->options.data(), argv.size(), argv.data());
|
||||||
|
|
||||||
if (parsed_options)
|
if (parsed_options)
|
||||||
delete[] parsed_options;
|
delete[] parsed_options;
|
||||||
if (parsed_buffer)
|
if (parsed_buffer)
|
||||||
delete[] parsed_buffer;
|
delete[] parsed_buffer;
|
||||||
if (m_parser)
|
if (m_parser)
|
||||||
delete m_parser;
|
delete m_parser;
|
||||||
|
|
||||||
parsed_options = new option::Option[stats.options_max];
|
parsed_options = new option::Option[stats.options_max];
|
||||||
parsed_buffer = new option::Option[stats.buffer_max];
|
parsed_buffer = new option::Option[stats.buffer_max];
|
||||||
|
|
||||||
m_parser = new option::Parser(this->options.data(), argv.size(), argv.data(),
|
m_parser = new option::Parser(this->options.data(), argv.size(), argv.data(),
|
||||||
parsed_options, parsed_buffer);
|
parsed_options, parsed_buffer);
|
||||||
|
|
||||||
|
|
||||||
// Pop the terminating entry
|
// Pop the terminating entry
|
||||||
this->options.pop_back();
|
this->options.pop_back();
|
||||||
|
|
||||||
return !m_parser->error();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return !m_parser->error();
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|||||||
@ -17,93 +17,94 @@
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
/**
|
|
||||||
* @class CommandLine
|
|
||||||
* @brief Implements a command line interface, that filters the
|
|
||||||
* simulators command line. It is a Singleton.
|
|
||||||
*/
|
|
||||||
class CommandLine {
|
|
||||||
public:
|
|
||||||
typedef int argument_count;
|
|
||||||
typedef char **argument_value;
|
|
||||||
private:
|
|
||||||
static CommandLine m_instance;
|
|
||||||
|
|
||||||
std::vector<const char *> argv;
|
/**
|
||||||
std::vector<option::Descriptor> options;
|
* @class CommandLine
|
||||||
option::Option *parsed_options, *parsed_buffer;
|
* @brief Implements a command line interface, that filters the
|
||||||
option::Parser *m_parser;
|
* simulators command line. It is a Singleton.
|
||||||
public:
|
*/
|
||||||
/// Handle for accessing the parsed data of an option
|
class CommandLine {
|
||||||
typedef int option_handle;
|
public:
|
||||||
|
typedef int argument_count;
|
||||||
|
typedef char **argument_value;
|
||||||
|
private:
|
||||||
|
static CommandLine m_instance;
|
||||||
|
|
||||||
/**
|
std::vector<const char *> argv;
|
||||||
* Singleton accessor
|
std::vector<option::Descriptor> options;
|
||||||
*
|
option::Option *parsed_options, *parsed_buffer;
|
||||||
* @return reference to the CommandLine singleton object
|
option::Parser *m_parser;
|
||||||
*/
|
public:
|
||||||
static CommandLine &Inst() { return m_instance; }
|
/// Handle for accessing the parsed data of an option
|
||||||
|
typedef int option_handle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the simulator to filter all fail arguments from
|
* Singleton accessor
|
||||||
* argc, argv
|
*
|
||||||
*/
|
* @return reference to the CommandLine singleton object
|
||||||
void collect_args(argument_count &, argument_value &);
|
*/
|
||||||
|
static CommandLine &Inst() { return m_instance; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a argument manually
|
* Called by the simulator to filter all fail arguments from
|
||||||
*/
|
* argc, argv
|
||||||
void add_args(const char *value) { argv.push_back(value); }
|
*/
|
||||||
|
void collect_args(argument_count &, argument_value &);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a option to the command line interface of the fail-client
|
* Add a argument manually
|
||||||
*
|
*/
|
||||||
* @param shortopt e.g "m" for -m
|
void add_args(const char *value) { argv.push_back(value); }
|
||||||
* @param longopt e.g. "memory-region" for --memory-region=
|
|
||||||
* @param check_arg argument is required.
|
|
||||||
* @param help help text to be printed for -h
|
|
||||||
*
|
|
||||||
* @return return handle to option
|
|
||||||
*/
|
|
||||||
option_handle addOption(const std::string &shortopt,
|
|
||||||
const std::string &longopt,
|
|
||||||
const option::CheckArg & check_arg,
|
|
||||||
const std::string &help);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Add a option to the command line interface of the fail-client
|
||||||
* do the actual parsing, called by the experiment
|
*
|
||||||
*
|
* @param shortopt e.g "m" for -m
|
||||||
* @return true on success
|
* @param longopt e.g. "memory-region" for --memory-region=
|
||||||
*/
|
* @param check_arg argument is required.
|
||||||
bool parse();
|
* @param help help text to be printed for -h
|
||||||
|
*
|
||||||
|
* @return return handle to option
|
||||||
|
*/
|
||||||
|
option_handle addOption(const std::string &shortopt,
|
||||||
|
const std::string &longopt,
|
||||||
|
const option::CheckArg & check_arg,
|
||||||
|
const std::string &help);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accessor for the command line option objects
|
*
|
||||||
*
|
* do the actual parsing, called by the experiment
|
||||||
* @param handle option handle
|
*
|
||||||
*
|
* @return true on success
|
||||||
* @return reference to the option parser object
|
*/
|
||||||
*/
|
bool parse();
|
||||||
option::Option &operator[](option_handle handle) {
|
|
||||||
assert(parsed_options != 0);
|
/**
|
||||||
assert(handle >= 0 && handle < (int)options.size());
|
* Accessor for the command line option objects
|
||||||
return parsed_options[handle];
|
*
|
||||||
}
|
* @param handle option handle
|
||||||
/**
|
*
|
||||||
* Print help message.
|
* @return reference to the option parser object
|
||||||
*/
|
*/
|
||||||
void printUsage() {
|
option::Option &operator[](option_handle handle) {
|
||||||
int columns = getenv("COLUMNS")? atoi(getenv("COLUMNS")) : 80;
|
assert(parsed_options != 0);
|
||||||
option::printUsage(fwrite, stdout, options.data(), columns);
|
assert(handle >= 0 && handle < (int)options.size());
|
||||||
}
|
return parsed_options[handle];
|
||||||
/**
|
}
|
||||||
* Return the internal option::Parser object for further usage.
|
/**
|
||||||
*/
|
* Print help message.
|
||||||
option::Parser *parser() {
|
*/
|
||||||
return m_parser;
|
void printUsage() {
|
||||||
}
|
int columns = getenv("COLUMNS")? atoi(getenv("COLUMNS")) : 80;
|
||||||
};
|
option::printUsage(fwrite, stdout, options.data(), columns);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return the internal option::Parser object for further usage.
|
||||||
|
*/
|
||||||
|
option::Parser *parser() {
|
||||||
|
return m_parser;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
|
|||||||
@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
const std::string Demangler::DEMANGLE_FAILED = "[Demangler] Demangle failed.";
|
const std::string Demangler::DEMANGLE_FAILED = "[Demangler] Demangle failed.";
|
||||||
|
|
||||||
std::string Demangler::demangle(const std::string& name){
|
std::string Demangler::demangle(const std::string& name){
|
||||||
const char* res = cplus_demangle(name.c_str(), 0);
|
const char* res = cplus_demangle(name.c_str(), 0);
|
||||||
if(res != NULL){
|
if (res != NULL) {
|
||||||
return std::string(res);
|
return std::string(res);
|
||||||
}else{
|
} else {
|
||||||
return Demangler::DEMANGLE_FAILED;
|
return Demangler::DEMANGLE_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|||||||
@ -5,19 +5,19 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
class Demangler {
|
class Demangler {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the demangled symbol name of a mangled string.
|
* Get the demangled symbol name of a mangled string.
|
||||||
* @param name The mangled symbol
|
* @param name The mangled symbol
|
||||||
* @return The according demangled name if found, else Demangler::DEMANGLE_FAILED
|
* @return The according demangled name if found, else Demangler::DEMANGLE_FAILED
|
||||||
*/
|
*/
|
||||||
static std::string demangle(const std::string & name);
|
static std::string demangle(const std::string & name);
|
||||||
|
|
||||||
//! Inform about failed demangling.
|
//! Inform about failed demangling.
|
||||||
static const std::string DEMANGLE_FAILED;
|
static const std::string DEMANGLE_FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
|
|||||||
@ -13,100 +13,99 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
const std::string DISASSEMBLER::FAILED = "[Disassembler] Disassemble failed.";
|
const std::string DISASSEMBLER::FAILED = "[Disassembler] Disassemble failed.";
|
||||||
|
|
||||||
Disassembler::Disassembler() : m_log("Fail*Disassembler", false){ }
|
Disassembler::Disassembler() : m_log("Fail*Disassembler", false) { }
|
||||||
|
|
||||||
int Disassembler::init() {
|
int Disassembler::init() {
|
||||||
// try to open elf file from environment variable
|
// try to open elf file from environment variable
|
||||||
char * elfpath = getenv("FAIL_ELF_PATH");
|
char * elfpath = getenv("FAIL_ELF_PATH");
|
||||||
if(elfpath == NULL){
|
if (elfpath == NULL) {
|
||||||
m_log << "FAIL_ELF_PATH not set :(" << std::endl;
|
m_log << "FAIL_ELF_PATH not set :(" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}else{
|
} else {
|
||||||
return init(elfpath);
|
return init(elfpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disassembler::init(const char* path){
|
int Disassembler::init(const char* path) {
|
||||||
// Disassemble ELF
|
// Disassemble ELF
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
std::string command = std::string(ARCH_TOOL_PREFIX) + std::string("objdump -d ") + std::string(path);
|
std::string command = std::string(ARCH_TOOL_PREFIX) + std::string("objdump -d ") + std::string(path);
|
||||||
m_log << "Executing: " << command << std::endl;
|
m_log << "Executing: " << command << std::endl;
|
||||||
redi::ipstream objdump( command );
|
redi::ipstream objdump( command );
|
||||||
std::string str;
|
std::string str;
|
||||||
while(std::getline(objdump, str)){
|
while (std::getline(objdump, str)) {
|
||||||
evaluate(str);
|
evaluate(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
objdump.close();
|
objdump.close();
|
||||||
if(objdump.rdbuf()->exited()){
|
if (objdump.rdbuf()->exited()) {
|
||||||
int ex = objdump.rdbuf()->status();
|
int ex = objdump.rdbuf()->status();
|
||||||
if(ex != 0){
|
if (ex != 0) {
|
||||||
m_code.clear();
|
m_code.clear();
|
||||||
m_log << "Could not disassemble!" << std::endl;
|
m_log << "Could not disassemble!" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_log << "disassembled " << m_code.size() << " lines." << std::endl;
|
m_log << "disassembled " << m_code.size() << " lines." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return m_code.size();
|
return m_code.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i) {
|
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i) {
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
os << std::hex << ((int)(i.address)) << "\t" << i.opcode << "\t" << i.instruction << "\t" << i.comment;
|
os << std::hex << ((int)(i.address)) << "\t" << i.opcode << "\t" << i.instruction << "\t" << i.comment;
|
||||||
#endif
|
#endif
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disassembler::evaluate(const std::string& line){
|
void Disassembler::evaluate(const std::string& line) {
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
// Only read in real code lines:
|
// Only read in real code lines:
|
||||||
// Code lines start with a leading whitespace! (hopefully in each objdump implementation!)
|
// Code lines start with a leading whitespace! (hopefully in each objdump implementation!)
|
||||||
if(line.size() > 0 && isspace(line[0])){
|
if (line.size() > 0 && isspace(line[0])) {
|
||||||
// a line looks like: 800156c:\tdd14 \tble.n 8001598 <_ZN2hw3hal7T32Term8PutBlockEPci+0x30>
|
// a line looks like: 800156c:\tdd14 \tble.n 8001598 <_ZN2hw3hal7T32Term8PutBlockEPci+0x30>
|
||||||
boost::regex expr("\\s+([A-Fa-f0-9]+):\\t(.*?)\\t(.+?)(;.*)?$");
|
boost::regex expr("\\s+([A-Fa-f0-9]+):\\t(.*?)\\t(.+?)(;.*)?$");
|
||||||
boost::smatch res;
|
boost::smatch res;
|
||||||
if(boost::regex_search(line, res, expr)){
|
if (boost::regex_search(line, res, expr)) {
|
||||||
std::string address = res[1];
|
std::string address = res[1];
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::hex << address;
|
ss << std::hex << address;
|
||||||
address_t addr = 0;
|
address_t addr = 0;
|
||||||
ss >> addr;
|
ss >> addr;
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str("");
|
ss.str("");
|
||||||
|
|
||||||
std::string opcode = res[2];
|
std::string opcode = res[2];
|
||||||
// delete trailing/leading whitespaces
|
// delete trailing/leading whitespaces
|
||||||
boost::trim(opcode);
|
boost::trim(opcode);
|
||||||
// delete inner whitespaces and merge nibbles
|
// delete inner whitespaces and merge nibbles
|
||||||
opcode.erase(std::remove(opcode.begin(), opcode.end(), ' '), opcode.end());
|
opcode.erase(std::remove(opcode.begin(), opcode.end(), ' '), opcode.end());
|
||||||
ss << std::hex << opcode;
|
ss << std::hex << opcode;
|
||||||
unsigned opc = 0;
|
unsigned opc = 0;
|
||||||
ss >> opc;
|
ss >> opc;
|
||||||
|
|
||||||
std::string instruction = res[3];
|
std::string instruction = res[3];
|
||||||
boost::trim(instruction);
|
boost::trim(instruction);
|
||||||
std::string comment = res[4];
|
std::string comment = res[4];
|
||||||
boost::trim(comment);
|
boost::trim(comment);
|
||||||
|
|
||||||
m_code.insert(std::make_pair(addr, Instruction(addr, opc, instruction, comment)));
|
m_code.insert(std::make_pair(addr, Instruction(addr, opc, instruction, comment)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction g_InstructionNotFound;
|
|
||||||
const Instruction & Disassembler::disassemble(address_t address) const {
|
|
||||||
InstructionMap_t::const_iterator it = m_code.find(address);
|
|
||||||
if(it == m_code.end()){
|
|
||||||
return g_InstructionNotFound;
|
|
||||||
}else{
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static Instruction g_InstructionNotFound;
|
||||||
|
const Instruction & Disassembler::disassemble(address_t address) const {
|
||||||
|
InstructionMap_t::const_iterator it = m_code.find(address);
|
||||||
|
if (it == m_code.end()) {
|
||||||
|
return g_InstructionNotFound;
|
||||||
|
} else {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __DISASSEMBLER_HPP
|
#ifndef __DISASSEMBLER_HPP
|
||||||
#define __DISASSEMBLER_HPP
|
#define __DISASSEMBLER_HPP
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Logger.hpp"
|
#include "Logger.hpp"
|
||||||
@ -9,70 +9,70 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
struct DISASSEMBLER {
|
struct DISASSEMBLER {
|
||||||
//! Inform about failed disassembly
|
//! Inform about failed disassembly
|
||||||
static const std::string FAILED;
|
static const std::string FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Instruction
|
* @class Instruction
|
||||||
* @brief An Instruction represents an disassembled opcode
|
* @brief An Instruction represents an disassembled opcode
|
||||||
*/
|
*/
|
||||||
struct Instruction {
|
struct Instruction {
|
||||||
address_t address; //!< The instruction address
|
address_t address; //!< The instruction address
|
||||||
regdata_t opcode; //!< The opcode itself
|
regdata_t opcode; //!< The opcode itself
|
||||||
std::string instruction; //!< The disassembled instruction
|
std::string instruction; //!< The disassembled instruction
|
||||||
std::string comment; //!< Comment (rest of line after ; )
|
std::string comment; //!< Comment (rest of line after ; )
|
||||||
Instruction(address_t address = ADDR_INV, regdata_t opcode = 0, const std::string& instr = DISASSEMBLER::FAILED, const std::string& comment = "")
|
Instruction(address_t address = ADDR_INV, regdata_t opcode = 0, const std::string& instr = DISASSEMBLER::FAILED, const std::string& comment = "")
|
||||||
: address(address), opcode(opcode), instruction(instr), comment(comment) { };
|
: address(address), opcode(opcode), instruction(instr), comment(comment) { };
|
||||||
};
|
};
|
||||||
//<! This allows to print an Instruction via Logger or cout
|
//<! This allows to print an Instruction via Logger or cout
|
||||||
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i);
|
std::ostream& operator <<(std::ostream & os, const fail::Instruction & i);
|
||||||
|
|
||||||
class Disassembler {
|
class Disassembler {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
Disassembler();
|
Disassembler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get disassembler instruction
|
* Get disassembler instruction
|
||||||
* @param address The instruction address
|
* @param address The instruction address
|
||||||
* @return The according disassembled instruction if found, else DISASSEMBLER::FAILED
|
* @return The according disassembled instruction if found, else DISASSEMBLER::FAILED
|
||||||
*/
|
*/
|
||||||
const Instruction & disassemble(address_t address) const;
|
const Instruction & disassemble(address_t address) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if there is an instruction at a given address
|
* Test if there is an instruction at a given address
|
||||||
* @param address The address to test
|
* @param address The address to test
|
||||||
* @return true if found, else false
|
* @return true if found, else false
|
||||||
*/
|
*/
|
||||||
bool hasInstructionAt(address_t address) const {
|
bool hasInstructionAt(address_t address) const {
|
||||||
return m_code.find(address) != m_code.end();;
|
return m_code.find(address) != m_code.end();;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate new ELF file
|
* Evaluate new ELF file
|
||||||
* @param elfpath Path to ELF file.
|
* @param elfpath Path to ELF file.
|
||||||
* @return Number of disassembled lines.
|
* @return Number of disassembled lines.
|
||||||
*/
|
*/
|
||||||
int init(const char* elfpath);
|
int init(const char* elfpath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate new ELF file from env variable $FAIL_ELF_PATH
|
* Evaluate new ELF file from env variable $FAIL_ELF_PATH
|
||||||
* @return Number of disassembled lines.
|
* @return Number of disassembled lines.
|
||||||
* @note The path is guessed from a FAIL_ELF_PATH environment variable
|
* @note The path is guessed from a FAIL_ELF_PATH environment variable
|
||||||
*/
|
*/
|
||||||
int init(void);
|
int init(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger m_log;
|
Logger m_log;
|
||||||
typedef std::map<address_t, Instruction> InstructionMap_t;
|
typedef std::map<address_t, Instruction> InstructionMap_t;
|
||||||
InstructionMap_t m_code;
|
InstructionMap_t m_code;
|
||||||
void evaluate(const std::string &);
|
void evaluate(const std::string &);
|
||||||
};
|
};
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
||||||
#endif // DISASSEMBLER_HPP
|
#endif // DISASSEMBLER_HPP
|
||||||
|
|||||||
@ -11,245 +11,243 @@ const std::string ELF::NOTFOUND = "[ELFReader] Function not found.";
|
|||||||
static const ElfSymbol g_SymbolNotFound;
|
static const ElfSymbol g_SymbolNotFound;
|
||||||
|
|
||||||
bool operator==(const std::string & str, const ElfSymbol & sym) {
|
bool operator==(const std::string & str, const ElfSymbol & sym) {
|
||||||
return sym.getName() == str;
|
return sym.getName() == str;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(guest_address_t address, const ElfSymbol & sym) {
|
bool operator==(guest_address_t address, const ElfSymbol & sym) {
|
||||||
return sym.getAddress() == address;
|
return sym.getAddress() == address;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<< (std::ostream &out, const ElfSymbol &symbol) {
|
std::ostream& operator<< (std::ostream &out, const ElfSymbol &symbol) {
|
||||||
return (out << symbol.getName()
|
return (out << symbol.getName()
|
||||||
<< " @ 0x" << std::hex << symbol.getAddress()
|
<< " @ 0x" << std::hex << symbol.getAddress()
|
||||||
<< " size " << std::dec << symbol.getSize());
|
<< " size " << std::dec << symbol.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ElfReader::ElfReader() : m_log("Fail*Elfinfo", false){
|
ElfReader::ElfReader() : m_log("Fail*Elfinfo", false) {
|
||||||
// try to open elf file from environment variable
|
// try to open elf file from environment variable
|
||||||
char * elfpath = getenv("FAIL_ELF_PATH");
|
char * elfpath = getenv("FAIL_ELF_PATH");
|
||||||
if(elfpath == NULL){
|
if (elfpath == NULL) {
|
||||||
m_log << "FAIL_ELF_PATH not set :(" << std::endl;
|
m_log << "FAIL_ELF_PATH not set :(" << std::endl;
|
||||||
}else{
|
} else {
|
||||||
setup(elfpath);
|
setup(elfpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfReader::ElfReader(const char* path) : m_log("Fail*Elfinfo", false){
|
ElfReader::ElfReader(const char* path) : m_log("Fail*Elfinfo", false) {
|
||||||
setup(path);
|
setup(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfReader::setup(const char* path) {
|
void ElfReader::setup(const char* path) {
|
||||||
// Try to open the ELF file
|
// Try to open the ELF file
|
||||||
FILE * fp = fopen(path, "r");
|
FILE * fp = fopen(path, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
m_log << "Error: Could not open " << path << std::endl;
|
m_log << "Error: Could not open " << path << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_filename = std::string(path);
|
m_filename = std::string(path);
|
||||||
|
|
||||||
// Evaluate headers
|
// Evaluate headers
|
||||||
Elf32_Ehdr ehdr;
|
Elf32_Ehdr ehdr;
|
||||||
Elf32_Shdr sec_hdr;
|
Elf32_Shdr sec_hdr;
|
||||||
int num_hdrs,i;
|
int num_hdrs,i;
|
||||||
fseek(fp,(off_t)0,SEEK_SET);
|
fseek(fp,(off_t)0,SEEK_SET);
|
||||||
read_ELF_file_header(fp, &ehdr);
|
read_ELF_file_header(fp, &ehdr);
|
||||||
num_hdrs=ehdr.e_shnum;
|
num_hdrs=ehdr.e_shnum;
|
||||||
m_log << "Evaluating ELF File: " << path << std::endl;
|
m_log << "Evaluating ELF File: " << path << std::endl;
|
||||||
// Parse symbol table and generate internal map
|
// Parse symbol table and generate internal map
|
||||||
for(i=0;i<num_hdrs;i++)
|
for (i=0;i<num_hdrs;i++)
|
||||||
{
|
{
|
||||||
if(read_ELF_section_header(i,&sec_hdr,fp)==-1)
|
if (read_ELF_section_header(i,&sec_hdr,fp)==-1)
|
||||||
{
|
{
|
||||||
m_log << "Wrong Section to read" << std::endl;
|
m_log << "Wrong Section to read" << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((sec_hdr.sh_type==SHT_SYMTAB)||(sec_hdr.sh_type==SHT_DYNSYM))
|
if ((sec_hdr.sh_type==SHT_SYMTAB)||(sec_hdr.sh_type==SHT_DYNSYM))
|
||||||
{
|
{
|
||||||
process_symboltable(i,fp);
|
process_symboltable(i,fp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Parse section information
|
// Parse section information
|
||||||
if(read_ELF_section_header(ehdr.e_shstrndx,&sec_hdr,fp)==-1)
|
if (read_ELF_section_header(ehdr.e_shstrndx,&sec_hdr,fp)==-1)
|
||||||
{
|
{
|
||||||
m_log << "Error: reading section string table sect_num = " << ehdr.e_shstrndx << std::endl;
|
m_log << "Error: reading section string table sect_num = " << ehdr.e_shstrndx << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* buff=(char*)malloc(sec_hdr.sh_size);
|
char* buff=(char*)malloc(sec_hdr.sh_size);
|
||||||
if (!buff)
|
if (!buff)
|
||||||
{
|
{
|
||||||
m_log << "Malloc failed to allocate buffer for shstrtab" << std::endl;
|
m_log << "Malloc failed to allocate buffer for shstrtab" << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
//seek to the offset in the file,
|
// seek to the offset in the file,
|
||||||
fseek(fp,(off_t)sec_hdr.sh_offset,SEEK_SET);
|
fseek(fp,(off_t)sec_hdr.sh_offset,SEEK_SET);
|
||||||
fread(buff,sec_hdr.sh_size,1,fp);
|
fread(buff,sec_hdr.sh_size,1,fp);
|
||||||
m_log << "Total number of sections: " << num_hdrs << std::endl;
|
m_log << "Total number of sections: " << num_hdrs << std::endl;
|
||||||
|
|
||||||
for(i=0;i<num_hdrs;i++)
|
for (i=0;i<num_hdrs;i++)
|
||||||
{
|
{
|
||||||
if(read_ELF_section_header(i,&sec_hdr,fp)==-1)
|
if (read_ELF_section_header(i,&sec_hdr,fp)==-1)
|
||||||
{
|
{
|
||||||
m_log << "Wrong Section to read\n" << std::endl;
|
m_log << "Wrong Section to read\n" << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
process_section(&sec_hdr, buff);
|
process_section(&sec_hdr, buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(buff)
|
if (buff)
|
||||||
free(buff);
|
free(buff);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
// printDemangled();
|
// printDemangled();
|
||||||
// printSections();
|
// printSections();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ElfReader::process_section(Elf32_Shdr *sect_hdr, char* sect_name_buff){
|
int ElfReader::process_section(Elf32_Shdr *sect_hdr, char* sect_name_buff) {
|
||||||
// Add section name, start address and size to list
|
// Add section name, start address and size to list
|
||||||
int idx=sect_hdr->sh_name;
|
int idx=sect_hdr->sh_name;
|
||||||
// m_sections_map.push_back( sect_hdr->sh_addr, sect_hdr->sh_size, sect_name_buff+idx );
|
// m_sections_map.push_back( sect_hdr->sh_addr, sect_hdr->sh_size, sect_name_buff+idx );
|
||||||
m_sectiontable.push_back( ElfSymbol(sect_name_buff+idx, sect_hdr->sh_addr, sect_hdr->sh_size, ElfSymbol::SECTION) );
|
m_sectiontable.push_back( ElfSymbol(sect_name_buff+idx, sect_hdr->sh_addr, sect_hdr->sh_size, ElfSymbol::SECTION) );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ElfReader::process_symboltable(int sect_num, FILE* fp){
|
int ElfReader::process_symboltable(int sect_num, FILE* fp) {
|
||||||
|
|
||||||
Elf32_Shdr sect_hdr;
|
Elf32_Shdr sect_hdr;
|
||||||
Elf32_Sym mysym;
|
Elf32_Sym mysym;
|
||||||
char *name_buf=NULL;
|
char *name_buf=NULL;
|
||||||
int num_sym,link,i,idx;
|
int num_sym,link,i,idx;
|
||||||
off_t sym_data_offset;
|
off_t sym_data_offset;
|
||||||
int sym_data_size;
|
int sym_data_size;
|
||||||
if(read_ELF_section_header(sect_num,§_hdr,fp)==-1)
|
if (read_ELF_section_header(sect_num,§_hdr,fp)==-1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
//we have to check to which strtab it is linked
|
// we have to check to which strtab it is linked
|
||||||
link=sect_hdr.sh_link;
|
link=sect_hdr.sh_link;
|
||||||
sym_data_offset=sect_hdr.sh_offset;
|
sym_data_offset=sect_hdr.sh_offset;
|
||||||
sym_data_size=sect_hdr.sh_size;
|
sym_data_size=sect_hdr.sh_size;
|
||||||
num_sym=sym_data_size/sizeof(Elf32_Sym);
|
num_sym=sym_data_size/sizeof(Elf32_Sym);
|
||||||
|
|
||||||
//read the coresponding strtab
|
// read the coresponding strtab
|
||||||
if(read_ELF_section_header(link,§_hdr,fp)==-1)
|
if (read_ELF_section_header(link,§_hdr,fp)==-1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
//get the size of strtab in file and allocate a buffer
|
// get the size of strtab in file and allocate a buffer
|
||||||
name_buf=(char*)malloc(sect_hdr.sh_size);
|
name_buf=(char*)malloc(sect_hdr.sh_size);
|
||||||
if(!name_buf)
|
if (!name_buf)
|
||||||
return -1;
|
return -1;
|
||||||
//get the offset of strtab in file and seek to it
|
// get the offset of strtab in file and seek to it
|
||||||
fseek(fp,sect_hdr.sh_offset,SEEK_SET);
|
fseek(fp,sect_hdr.sh_offset,SEEK_SET);
|
||||||
//read all data from the section to the buffer.
|
// read all data from the section to the buffer.
|
||||||
fread(name_buf,sect_hdr.sh_size,1,fp);
|
fread(name_buf,sect_hdr.sh_size,1,fp);
|
||||||
//so we have the namebuf now seek to symtab data
|
// so we have the namebuf now seek to symtab data
|
||||||
fseek(fp,sym_data_offset,SEEK_SET);
|
fseek(fp,sym_data_offset,SEEK_SET);
|
||||||
|
|
||||||
for(i=0;i<num_sym;i++)
|
for (i=0;i<num_sym;i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
fread(&mysym,sizeof(Elf32_Sym),1,fp);
|
fread(&mysym,sizeof(Elf32_Sym),1,fp);
|
||||||
idx=mysym.st_name;
|
idx=mysym.st_name;
|
||||||
|
|
||||||
int type = ELF32_ST_TYPE(mysym.st_info);
|
int type = ELF32_ST_TYPE(mysym.st_info);
|
||||||
if((type != STT_SECTION) && (type != STT_FILE)){
|
if ((type != STT_SECTION) && (type != STT_FILE)) {
|
||||||
m_symboltable.push_back( ElfSymbol(name_buf+idx, mysym.st_value, mysym.st_size, ElfSymbol::SYMBOL,
|
m_symboltable.push_back( ElfSymbol(name_buf+idx, mysym.st_value, mysym.st_size, ElfSymbol::SYMBOL,
|
||||||
type) );
|
type) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (name_buf);
|
free (name_buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ElfSymbol& ElfReader::getSymbol(guest_address_t address){
|
const ElfSymbol& ElfReader::getSymbol(guest_address_t address) {
|
||||||
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
for (container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it) {
|
||||||
if(it->contains(address)){
|
if (it->contains(address)) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_SymbolNotFound;
|
return g_SymbolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Symbol search
|
// Symbol search
|
||||||
const ElfSymbol& ElfReader::getSymbol( const std::string& name ){
|
const ElfSymbol& ElfReader::getSymbol( const std::string& name ) {
|
||||||
container_t::const_iterator it;
|
container_t::const_iterator it;
|
||||||
// Fist, try to find as mangled symbol
|
// Fist, try to find as mangled symbol
|
||||||
it = std::find(m_symboltable.begin(), m_symboltable.end(), name);
|
it = std::find(m_symboltable.begin(), m_symboltable.end(), name);
|
||||||
if(it != m_symboltable.end()){
|
if (it != m_symboltable.end()) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, try to find as demangled symbol
|
// Then, try to find as demangled symbol
|
||||||
std::string dname = Demangler::demangle(name);
|
std::string dname = Demangler::demangle(name);
|
||||||
if(dname == Demangler::DEMANGLE_FAILED){
|
if (dname == Demangler::DEMANGLE_FAILED) {
|
||||||
return g_SymbolNotFound;
|
return g_SymbolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = std::find(m_symboltable.begin(), m_symboltable.end(), dname);
|
it = std::find(m_symboltable.begin(), m_symboltable.end(), dname);
|
||||||
if(it != m_symboltable.end()){
|
if (it != m_symboltable.end()) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_SymbolNotFound;
|
return g_SymbolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section search
|
// Section search
|
||||||
const ElfSymbol& ElfReader::getSection(guest_address_t address){
|
const ElfSymbol& ElfReader::getSection(guest_address_t address) {
|
||||||
for(container_t::const_iterator it = m_sectiontable.begin(); it != m_sectiontable.end(); ++it){
|
for (container_t::const_iterator it = m_sectiontable.begin(); it != m_sectiontable.end(); ++it) {
|
||||||
if(it->contains(address)){
|
if (it->contains(address)) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return g_SymbolNotFound;
|
return g_SymbolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ElfSymbol& ElfReader::getSection( const std::string& name ){
|
const ElfSymbol& ElfReader::getSection( const std::string& name ) {
|
||||||
for(container_t::const_iterator it = m_sectiontable.begin(); it !=m_sectiontable.end(); ++it){
|
for (container_t::const_iterator it = m_sectiontable.begin(); it !=m_sectiontable.end(); ++it) {
|
||||||
if(it->getName() == name){
|
if (it->getName() == name) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return g_SymbolNotFound;
|
return g_SymbolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Pretty" Print
|
// "Pretty" Print
|
||||||
void ElfReader::printDemangled(){
|
void ElfReader::printDemangled() {
|
||||||
m_log << "Demangled: " << std::endl;
|
m_log << "Demangled: " << std::endl;
|
||||||
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
for (container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it) {
|
||||||
std::string str = Demangler::demangle(it->getName());
|
std::string str = Demangler::demangle(it->getName());
|
||||||
if(str == Demangler::DEMANGLE_FAILED){
|
if (str == Demangler::DEMANGLE_FAILED) {
|
||||||
str = it->getName();
|
str = it->getName();
|
||||||
}
|
}
|
||||||
m_log << "0x" << std::hex << it->getAddress() << "\t" << str.c_str() << "\t" << it->getSize() << std::endl;
|
m_log << "0x" << std::hex << it->getAddress() << "\t" << str.c_str() << "\t" << it->getSize() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfReader::printMangled(){
|
void ElfReader::printMangled() {
|
||||||
for(container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it){
|
for (container_t::const_iterator it = m_symboltable.begin(); it !=m_symboltable.end(); ++it) {
|
||||||
m_log << "0x" << std::hex << it->getAddress() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl;
|
m_log << "0x" << std::hex << it->getAddress() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfReader::printSections() {
|
void ElfReader::printSections() {
|
||||||
for(container_t::const_iterator it = m_sectiontable.begin(); it !=m_sectiontable.end(); ++it){
|
for (container_t::const_iterator it = m_sectiontable.begin(); it !=m_sectiontable.end(); ++it) {
|
||||||
m_log << "0x" << it->getAddress() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl;
|
m_log << "0x" << it->getAddress() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end-of-namespace fail
|
} // end-of-namespace fail
|
||||||
|
|
||||||
|
|||||||
@ -12,164 +12,163 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
struct ELF {
|
struct ELF {
|
||||||
static const std::string NOTFOUND;
|
static const std::string NOTFOUND;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ElfSymbol {
|
class ElfSymbol {
|
||||||
std::string name;
|
std::string name;
|
||||||
guest_address_t address;
|
guest_address_t address;
|
||||||
size_t size;
|
size_t size;
|
||||||
int m_type;
|
int m_type;
|
||||||
int m_symbol_type;
|
int m_symbol_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum { SECTION = 1, SYMBOL = 2, UNDEF = 3, };
|
enum { SECTION = 1, SYMBOL = 2, UNDEF = 3, };
|
||||||
|
|
||||||
ElfSymbol(const std::string & name = ELF::NOTFOUND, guest_address_t addr = ADDR_INV, size_t size = -1, int type = UNDEF,
|
ElfSymbol(const std::string & name = ELF::NOTFOUND, guest_address_t addr = ADDR_INV,
|
||||||
int symbol_type = 0)
|
size_t size = -1, int type = UNDEF, int symbol_type = 0)
|
||||||
: name(name), address(addr), size(size), m_type(type), m_symbol_type(symbol_type) {};
|
: name(name), address(addr), size(size), m_type(type), m_symbol_type(symbol_type) {};
|
||||||
|
|
||||||
const std::string& getName() const { return name; };
|
const std::string& getName() const { return name; };
|
||||||
std::string getDemangledName() const { return Demangler::demangle(name); };
|
std::string getDemangledName() const { return Demangler::demangle(name); };
|
||||||
guest_address_t getAddress() const { return address; };
|
guest_address_t getAddress() const { return address; };
|
||||||
size_t getSize() const { return size; };
|
size_t getSize() const { return size; };
|
||||||
guest_address_t getStart() const { return getAddress(); }; // alias
|
guest_address_t getStart() const { return getAddress(); }; // alias
|
||||||
guest_address_t getEnd() const { return address + size; };
|
guest_address_t getEnd() const { return address + size; };
|
||||||
int getSymbolType() const { return m_symbol_type; };
|
int getSymbolType() const { return m_symbol_type; };
|
||||||
|
|
||||||
bool isSection() const { return m_type == SECTION; };
|
bool isSection() const { return m_type == SECTION; };
|
||||||
bool isSymbol() const { return m_type == SYMBOL; };
|
bool isSymbol() const { return m_type == SYMBOL; };
|
||||||
bool isValid() const { return name != ELF::NOTFOUND; };
|
bool isValid() const { return name != ELF::NOTFOUND; };
|
||||||
|
|
||||||
bool operator==(const std::string& rhs) const {
|
bool operator==(const std::string& rhs) const {
|
||||||
if(rhs == name){
|
if (rhs == name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if( rhs == Demangler::demangle(name) ){
|
if ( rhs == Demangler::demangle(name) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const guest_address_t rhs) const {
|
bool operator==(const guest_address_t rhs) const {
|
||||||
return rhs == address;
|
return rhs == address;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(guest_address_t ad) const {
|
bool contains(guest_address_t ad) const {
|
||||||
return (ad >= address) && (ad < address+size);
|
return (ad >= address) && (ad < address+size);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* \fn
|
* \fn
|
||||||
* \relates ElfSymbol
|
* \relates ElfSymbol
|
||||||
* overloaded stream operator for printing ElfSymbol
|
* overloaded stream operator for printing ElfSymbol
|
||||||
*/
|
*/
|
||||||
std::ostream& operator<< (std::ostream &out, const ElfSymbol &symbol);
|
std::ostream& operator<< (std::ostream &out, const ElfSymbol &symbol);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class ElfReader
|
* \class ElfReader
|
||||||
* Parses an ELF file and provides a list of symbol names
|
* Parses an ELF file and provides a list of symbol names
|
||||||
* and corresponding addresses
|
* and corresponding addresses
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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;
|
||||||
typedef container_t::const_iterator symbol_iterator;
|
typedef container_t::const_iterator symbol_iterator;
|
||||||
typedef container_t::const_iterator section_iterator;
|
typedef container_t::const_iterator section_iterator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param path Path to the ELF file.
|
* @param path Path to the ELF file.
|
||||||
*/
|
*/
|
||||||
ElfReader(const char* path);
|
ElfReader(const char* path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @note The path is guessed from a FAIL_ELF_PATH environment variable
|
* @note The path is guessed from a FAIL_ELF_PATH environment variable
|
||||||
*/
|
*/
|
||||||
ElfReader();
|
ElfReader();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the list of available mangled symbols
|
* Print the list of available mangled symbols
|
||||||
* @note This includes both C and C++ symbols
|
* @note This includes both C and C++ symbols
|
||||||
*/
|
*/
|
||||||
void printMangled();
|
void printMangled();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a list of demangled symbols.
|
* Print a list of demangled symbols.
|
||||||
*/
|
*/
|
||||||
void printDemangled();
|
void printDemangled();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the list of all available sections.
|
* Print the list of all available sections.
|
||||||
*/
|
*/
|
||||||
void printSections();
|
void printSections();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get symbol by address
|
* Get symbol by address
|
||||||
* @param address Address within range of the symbol
|
* @param address Address within range of the symbol
|
||||||
* @return The according symbol name if symbol.address <= address < symbol.address + symbol.size , else g_SymbolNotFound
|
* @return The according symbol name if symbol.address <= address < symbol.address + symbol.size , else g_SymbolNotFound
|
||||||
*/
|
*/
|
||||||
const ElfSymbol& getSymbol(guest_address_t address);
|
const ElfSymbol& getSymbol(guest_address_t address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get symbol by name
|
* Get symbol by name
|
||||||
* @param address Name of the symbol
|
* @param address Name of the symbol
|
||||||
* @return The according symbol name if section was found, else g_SymbolNotFound
|
* @return The according symbol name if section was found, else g_SymbolNotFound
|
||||||
*/
|
*/
|
||||||
const ElfSymbol& getSymbol( const std::string& name );
|
const ElfSymbol& getSymbol( const std::string& name );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get section by address
|
* Get section by address
|
||||||
* @param address An address to search for a section containing that address.
|
* @param address An address to search for a section containing that address.
|
||||||
* @return The according section name if section was found, else g_SymbolNotFound
|
* @return The according section name if section was found, else g_SymbolNotFound
|
||||||
*/
|
*/
|
||||||
const ElfSymbol& getSection(guest_address_t address);
|
const ElfSymbol& getSection(guest_address_t address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get section by name
|
* Get section by name
|
||||||
* @param name The name of the section
|
* @param name The name of the section
|
||||||
* @return The according section if section was found, else g_SymbolNotFound
|
* @return The according section if section was found, else g_SymbolNotFound
|
||||||
*/
|
*/
|
||||||
const ElfSymbol& getSection( const std::string& name );
|
const ElfSymbol& getSection( const std::string& name );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get symboltable iterator. Derefences to a ElfSymbol
|
* Get symboltable iterator. Derefences to a ElfSymbol
|
||||||
* @return iterator
|
* @return iterator
|
||||||
*/
|
*/
|
||||||
container_t::const_iterator sym_begin() { return m_symboltable.begin(); }
|
container_t::const_iterator sym_begin() { return m_symboltable.begin(); }
|
||||||
container_t::const_iterator sym_end() { return m_symboltable.end(); }
|
container_t::const_iterator sym_end() { return m_symboltable.end(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get section iterator. Derefences to a ElfSymbol
|
* Get section iterator. Derefences to a ElfSymbol
|
||||||
* @return iterator
|
* @return iterator
|
||||||
*/
|
*/
|
||||||
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; }
|
const std::string & getFilename() { return m_filename; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger m_log;
|
Logger m_log;
|
||||||
std::string m_filename;
|
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);
|
||||||
int process_section(Elf32_Shdr *sect_hdr, char* sect_name_buff);
|
int process_section(Elf32_Shdr *sect_hdr, char* sect_name_buff);
|
||||||
|
|
||||||
container_t m_symboltable;
|
container_t m_symboltable;
|
||||||
container_t m_sectiontable;
|
container_t m_sectiontable;
|
||||||
|
|
||||||
guest_address_t getAddress(const std::string& name);
|
guest_address_t getAddress(const std::string& name);
|
||||||
std::string getName(guest_address_t address);
|
std::string getName(guest_address_t address);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace fail
|
} // end-of-namespace fail
|
||||||
|
|
||||||
#endif //__ELFREADER_HPP__
|
#endif //__ELFREADER_HPP__
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __LOGGER_HPP__
|
#ifndef __LOGGER_HPP__
|
||||||
#define __LOGGER_HPP__
|
#define __LOGGER_HPP__
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __MEMORYMAP_HPP__
|
#ifndef __MEMORYMAP_HPP__
|
||||||
#define __MEMORYMAP_HPP__
|
#define __MEMORYMAP_HPP__
|
||||||
|
|
||||||
#ifdef BOOST_1_46_OR_NEWER
|
#ifdef BOOST_1_46_OR_NEWER
|
||||||
#include <boost/icl/interval_set.hpp>
|
#include <boost/icl/interval_set.hpp>
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Determines whether a given memory access at address \a addr with width
|
* Determines whether a given memory access at address \a addr with width
|
||||||
* \a size hits the map.
|
* \a size hits the map.
|
||||||
*/
|
*/
|
||||||
bool isMatching(address_t addr, int size = 1)
|
bool isMatching(address_t addr, int size = 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -9,20 +9,20 @@ ProtoOStream::ProtoOStream(std::ostream *outfile) : m_outfile(outfile)
|
|||||||
m_log.showTime(false);
|
m_log.showTime(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProtoOStream::writeMessage(google::protobuf::Message* m)
|
bool ProtoOStream::writeMessage(google::protobuf::Message *m)
|
||||||
{
|
{
|
||||||
m_size = htonl(m->ByteSize());
|
m_size = htonl(m->ByteSize());
|
||||||
m_outfile->write(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
m_outfile->write(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
||||||
|
|
||||||
if (m_outfile->bad()) {
|
if (m_outfile->bad()) {
|
||||||
m_log << "Could not write to file!" << std::endl;
|
m_log << "Could not write to file!" << std::endl;
|
||||||
// TODO: log-Level?
|
// TODO: log-Level?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->SerializeToOstream(m_outfile);
|
m->SerializeToOstream(m_outfile);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtoIStream::ProtoIStream(std::istream *infile) : m_infile(infile)
|
ProtoIStream::ProtoIStream(std::istream *infile) : m_infile(infile)
|
||||||
@ -38,23 +38,23 @@ void ProtoIStream::reset()
|
|||||||
m_infile->seekg(0, std::ios::beg);
|
m_infile->seekg(0, std::ios::beg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProtoIStream::getNext(google::protobuf::Message* m)
|
bool ProtoIStream::getNext(google::protobuf::Message *m)
|
||||||
{
|
{
|
||||||
m_infile->read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
m_infile->read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
||||||
if (!m_infile->good())
|
if (!m_infile->good())
|
||||||
return false;
|
return false;
|
||||||
m_size = ntohl(m_size);
|
m_size = ntohl(m_size);
|
||||||
|
|
||||||
// FIXME reuse buffer (efficiency)
|
// FIXME reuse buffer (efficiency)
|
||||||
// FIXME new[] may fail (i.e., return 0)
|
// FIXME new[] may fail (i.e., return 0)
|
||||||
char *buf = new char[m_size];
|
char *buf = new char[m_size];
|
||||||
m_infile->read(buf, m_size);
|
m_infile->read(buf, m_size);
|
||||||
if (!m_infile->good())
|
if (!m_infile->good())
|
||||||
// FIXME we're leaking buf[]
|
// FIXME we're leaking buf[]
|
||||||
return false;
|
return false;
|
||||||
std::string st(buf, m_size);
|
std::string st(buf, m_size);
|
||||||
m->ParseFromString(st);
|
m->ParseFromString(st);
|
||||||
|
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* \brief One way to manage large protobuf-messages
|
* \brief One way to manage large protobuf-messages
|
||||||
*
|
*
|
||||||
* Google protobuf is not designed for large messages. That leads to
|
* Google protobuf is not designed for large messages. That leads to
|
||||||
@ -8,14 +8,14 @@
|
|||||||
* written sequentially in a file. Written in the format:
|
* written sequentially in a file. Written in the format:
|
||||||
*
|
*
|
||||||
* \code
|
* \code
|
||||||
* | 4 bytes length-information of the first message | first message
|
* | 4 bytes length-information of the first message | first message
|
||||||
* | 4 bytes length-information of the second message | second message
|
* | 4 bytes length-information of the second message | second message
|
||||||
* | ...
|
* | ...
|
||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __PROTOSTREAM_HPP__
|
#ifndef __PROTOSTREAM_HPP__
|
||||||
#define __PROTOSTREAM_HPP__
|
#define __PROTOSTREAM_HPP__
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -28,7 +28,7 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class ProtoOStream
|
* \class ProtoOStream
|
||||||
*
|
*
|
||||||
* This class can be used to sequentially write a large number of
|
* This class can be used to sequentially write a large number of
|
||||||
* protocol buffer messages to a \c std::ostream.
|
* protocol buffer messages to a \c std::ostream.
|
||||||
*/
|
*/
|
||||||
@ -41,16 +41,16 @@ public:
|
|||||||
ProtoOStream(std::ostream *outfile);
|
ProtoOStream(std::ostream *outfile);
|
||||||
virtual ~ProtoOStream() { }
|
virtual ~ProtoOStream() { }
|
||||||
/**
|
/**
|
||||||
* Writes a message to a file.
|
* Writes a message to a file.
|
||||||
* @param m The protobuf-message to be written
|
* @param m The protobuf-message to be written
|
||||||
* @return Returns \c true on success, \c false otherwise
|
* @return Returns \c true on success, \c false otherwise
|
||||||
*/
|
*/
|
||||||
bool writeMessage(google::protobuf::Message* m);
|
bool writeMessage(google::protobuf::Message *m);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class ProtoIStream
|
* \class ProtoIStream
|
||||||
*
|
*
|
||||||
* This class can be used to read protocol buffer messages sequentially
|
* This class can be used to read protocol buffer messages sequentially
|
||||||
* from a \c std::istream.
|
* from a \c std::istream.
|
||||||
*/
|
*/
|
||||||
@ -73,7 +73,7 @@ public:
|
|||||||
* @param m The output protobuf message
|
* @param m The output protobuf message
|
||||||
* @return Returns \c true on success, \c false otherwise
|
* @return Returns \c true on success, \c false otherwise
|
||||||
*/
|
*/
|
||||||
bool getNext(google::protobuf::Message* m);
|
bool getNext(google::protobuf::Message * m);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -14,54 +14,54 @@ namespace fail {
|
|||||||
* concatenating strings with a separator.
|
* concatenating strings with a separator.
|
||||||
*
|
*
|
||||||
* The behaviour is similar to the python list().join(",") construct.
|
* The behaviour is similar to the python list().join(",") construct.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct StringJoiner : public std::deque<std::string> {
|
struct StringJoiner : public std::deque<std::string> {
|
||||||
/**
|
/**
|
||||||
* \brief join all strings in the container,
|
* \brief join all strings in the container,
|
||||||
*
|
*
|
||||||
* Join all the collected strings to one string. The separator is
|
* Join all the collected strings to one string. The separator is
|
||||||
* inserted between each element.
|
* inserted between each element.
|
||||||
*/
|
*/
|
||||||
std::string join(const char *j) {
|
std::string join(const char *j) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (size() == 0)
|
if (size() == 0)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
ss << front();
|
ss << front();
|
||||||
|
|
||||||
std::deque<std::string>::const_iterator i = begin() + 1;
|
std::deque<std::string>::const_iterator i = begin() + 1;
|
||||||
|
|
||||||
while (i != end()) {
|
while (i != end()) {
|
||||||
ss << j << *i;
|
ss << j << *i;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief append strings to list.
|
* \brief append strings to list.
|
||||||
*
|
*
|
||||||
* Appends the given value to the list of values if it isn't the
|
* Appends the given value to the list of values if it isn't the
|
||||||
* empty string. "" will be ignored.
|
* empty string. "" will be ignored.
|
||||||
*/
|
*/
|
||||||
void push_back(const value_type &x) {
|
void push_back(const value_type &x) {
|
||||||
if (x.compare("") == 0)
|
if (x.compare("") == 0)
|
||||||
return;
|
return;
|
||||||
std::deque<value_type>::push_back(x);
|
std::deque<value_type>::push_back(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief append strings to list.
|
* \brief append strings to list.
|
||||||
*
|
*
|
||||||
* Appends the given value to the list of values if it isn't the
|
* Appends the given value to the list of values if it isn't the
|
||||||
* empty string. "" will be ignored.
|
* empty string. "" will be ignored.
|
||||||
*/
|
*/
|
||||||
void push_front(const value_type &x) {
|
void push_front(const value_type &x) {
|
||||||
if (x.compare("") == 0)
|
if (x.compare("") == 0)
|
||||||
return;
|
return;
|
||||||
std::deque<value_type>::push_front(x);
|
std::deque<value_type>::push_front(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SYNCHRONIZED_COUNTER_HPP__
|
#ifndef __SYNCHRONIZED_COUNTER_HPP__
|
||||||
#define __SYNCHRONIZED_COUNTER_HPP__
|
#define __SYNCHRONIZED_COUNTER_HPP__
|
||||||
|
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
@ -14,7 +14,7 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class ssd
|
* \class ssd
|
||||||
*
|
*
|
||||||
* Provides a thread safe (synchronized) counter. When a method is called,
|
* Provides a thread safe (synchronized) counter. When a method is called,
|
||||||
* the internal mutex is automatically locked. On return, the lock is
|
* the internal mutex is automatically locked. On return, the lock is
|
||||||
* automatically released ("scoped lock").
|
* automatically released ("scoped lock").
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SYNCHRONIZED_MAP_HPP__
|
#ifndef __SYNCHRONIZED_MAP_HPP__
|
||||||
#define __SYNCHRONIZED_MAP_HPP__
|
#define __SYNCHRONIZED_MAP_HPP__
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ class SynchronizedMap {
|
|||||||
private:
|
private:
|
||||||
typedef std::map< Tkey, Tvalue > Tmap;
|
typedef std::map< Tkey, Tvalue > Tmap;
|
||||||
typedef typename Tmap::iterator Tit;
|
typedef typename Tmap::iterator Tit;
|
||||||
|
|
||||||
Tmap m_map; //! Use STL map to store data
|
Tmap m_map; //! Use STL map to store data
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::mutex m_mutex; //! The mutex to synchronise on
|
boost::mutex m_mutex; //! The mutex to synchronise on
|
||||||
@ -75,7 +75,7 @@ public:
|
|||||||
* Add data to the map, return false if already present
|
* Add data to the map, return false if already present
|
||||||
* @param key Map key
|
* @param key Map key
|
||||||
* @param value value according to key
|
* @param value value according to key
|
||||||
* @return false if key already present
|
* @return false if key already present
|
||||||
*/
|
*/
|
||||||
bool insert(const Tkey& key, const Tvalue& value)
|
bool insert(const Tkey& key, const Tvalue& value)
|
||||||
{
|
{
|
||||||
@ -83,20 +83,20 @@ public:
|
|||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
if( m_map.find(key) == m_map.end() ){ // not present, add it
|
if ( m_map.find(key) == m_map.end() ) { // not present, add it
|
||||||
m_map[key] = value;
|
m_map[key] = value;
|
||||||
return true;
|
return true;
|
||||||
}else{ // item is already in, oops
|
} else { // item is already in, oops
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Lock is automatically released here
|
} // Lock is automatically released here
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove value from the map.
|
* Remove value from the map.
|
||||||
* @param key The Map key to remove
|
* @param key The Map key to remove
|
||||||
* @return false if key was not present
|
* @return false if key was not present
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool remove(const Tkey& key, Tvalue& value)
|
bool remove(const Tkey& key, Tvalue& value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SYNCHRONIZED_QUEUE_HPP__
|
#ifndef __SYNCHRONIZED_QUEUE_HPP__
|
||||||
#define __SYNCHRONIZED_QUEUE_HPP__
|
#define __SYNCHRONIZED_QUEUE_HPP__
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ public:
|
|||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
return m_queue.size();
|
return m_queue.size();
|
||||||
}
|
}
|
||||||
// Add data to the queue and notify others
|
// Add data to the queue and notify others
|
||||||
void Enqueue(const T& data)
|
void Enqueue(const T& data)
|
||||||
@ -95,7 +95,7 @@ public:
|
|||||||
* Get data from the queue. Non blocking variant.
|
* Get data from the queue. Non blocking variant.
|
||||||
* @param d Pointer to copy queue element to
|
* @param d Pointer to copy queue element to
|
||||||
* @return false if no element in queue
|
* @return false if no element in queue
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool Dequeue_nb(T& d)
|
bool Dequeue_nb(T& d)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,7 +18,7 @@ std::string WallclockTimer::getRuntimeAsString() const
|
|||||||
{
|
{
|
||||||
std::stringstream result;
|
std::stringstream result;
|
||||||
result << getRuntimeAsDouble();
|
result << getRuntimeAsDouble();
|
||||||
|
|
||||||
return result.str().c_str();
|
return result.str().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ double WallclockTimer::getRuntimeAsDouble() const
|
|||||||
{
|
{
|
||||||
double result;
|
double result;
|
||||||
struct timeval current;
|
struct timeval current;
|
||||||
|
|
||||||
if (m_IsRunning) {
|
if (m_IsRunning) {
|
||||||
gettimeofday(¤t, NULL);
|
gettimeofday(¤t, NULL);
|
||||||
result = current.tv_sec - m_Start.tv_sec;
|
result = current.tv_sec - m_Start.tv_sec;
|
||||||
@ -35,7 +35,7 @@ double WallclockTimer::getRuntimeAsDouble() const
|
|||||||
result = m_End.tv_sec - m_Start.tv_sec;
|
result = m_End.tv_sec - m_Start.tv_sec;
|
||||||
result = result + (((double)m_End.tv_usec-m_Start.tv_usec)/1000000);
|
result = result + (((double)m_End.tv_usec-m_Start.tv_usec)/1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ void WallclockTimer::stopTimer()
|
|||||||
if (m_IsRunning) {
|
if (m_IsRunning) {
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
gettimeofday(&m_End, NULL);
|
gettimeofday(&m_End, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WallclockTimer::reset()
|
void WallclockTimer::reset()
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* \brief The WallclockTimer measures the elapsed time
|
* \brief The WallclockTimer measures the elapsed time
|
||||||
*
|
*
|
||||||
* The WallclockTimer measures the time which is elapsed between start
|
* The WallclockTimer measures the time which is elapsed between start
|
||||||
* and stop of the timer.
|
* and stop of the timer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __WALLCLOCKTIMER_HPP__
|
#ifndef __WALLCLOCKTIMER_HPP__
|
||||||
#define __WALLCLOCKTIMER_HPP__
|
#define __WALLCLOCKTIMER_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -16,7 +16,7 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class WallclockTimer
|
* \class WallclockTimer
|
||||||
*
|
*
|
||||||
* The class WallclockTimer contains all functions for start,
|
* The class WallclockTimer contains all functions for start,
|
||||||
* stop, reset and to get the elapsed time.
|
* stop, reset and to get the elapsed time.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -6,7 +6,7 @@ using namespace llvm::object;
|
|||||||
|
|
||||||
|
|
||||||
LLVMtoFailTranslator & LLVMDisassembler::getTranslator() {
|
LLVMtoFailTranslator & LLVMDisassembler::getTranslator() {
|
||||||
if ( ltofail == 0 ){
|
if ( ltofail == 0 ) {
|
||||||
std::cout << "ArchType: " << llvm::Triple::getArchTypeName( llvm::Triple::ArchType(object->getArch()) ) << std::endl;
|
std::cout << "ArchType: " << llvm::Triple::getArchTypeName( llvm::Triple::ArchType(object->getArch()) ) << std::endl;
|
||||||
|
|
||||||
switch ( llvm::Triple::ArchType(object->getArch()) ) {
|
switch ( llvm::Triple::ArchType(object->getArch()) ) {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using namespace fail;
|
|||||||
|
|
||||||
const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) {
|
const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) {
|
||||||
ltof_map_t::iterator it = llvm_to_fail_map.find(regid);
|
ltof_map_t::iterator it = llvm_to_fail_map.find(regid);
|
||||||
if( it != llvm_to_fail_map.end() ) {// found
|
if ( it != llvm_to_fail_map.end() ) {// found
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
} else { // not found
|
} else { // not found
|
||||||
std::cout << "Fail ID for LLVM Register id " << std::dec << regid << " not found :(" << std::endl;
|
std::cout << "Fail ID for LLVM Register id " << std::dec << regid << " not found :(" << std::endl;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#ifndef __ABO_SIMPLE_ARM_EXPERIMENT_HPP__
|
#ifndef __ABO_SIMPLE_ARM_EXPERIMENT_HPP__
|
||||||
#define __ABO_SIMPLE_ARM_EXPERIMENT_HPP__
|
#define __ABO_SIMPLE_ARM_EXPERIMENT_HPP__
|
||||||
|
|
||||||
#include "efw/ExperimentFlow.hpp"
|
#include "efw/ExperimentFlow.hpp"
|
||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __CHECKSUM_OOSTUBS_CAMPAIGN_HPP__
|
#ifndef __CHECKSUM_OOSTUBS_CAMPAIGN_HPP__
|
||||||
#define __CHECKSUM_OOSTUBS_CAMPAIGN_HPP__
|
#define __CHECKSUM_OOSTUBS_CAMPAIGN_HPP__
|
||||||
|
|
||||||
#include "cpn/Campaign.hpp"
|
#include "cpn/Campaign.hpp"
|
||||||
#include "comm/ExperimentData.hpp"
|
#include "comm/ExperimentData.hpp"
|
||||||
|
|||||||
@ -36,7 +36,7 @@ bool ChecksumOOStuBSExperiment::run()
|
|||||||
char const *statename = "checksum-oostubs.state";
|
char const *statename = "checksum-oostubs.state";
|
||||||
Logger log("Checksum-OOStuBS", false);
|
Logger log("Checksum-OOStuBS", false);
|
||||||
BPSingleListener bp;
|
BPSingleListener bp;
|
||||||
|
|
||||||
log << "startup" << endl;
|
log << "startup" << endl;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -107,7 +107,7 @@ bool ChecksumOOStuBSExperiment::run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
log << dec << "tracing finished after " << instr_counter << endl;
|
log << dec << "tracing finished after " << instr_counter << endl;
|
||||||
|
|
||||||
uint32_t results[OOSTUBS_RESULTS_BYTES / sizeof(uint32_t)];
|
uint32_t results[OOSTUBS_RESULTS_BYTES / sizeof(uint32_t)];
|
||||||
simulator.getMemoryManager().getBytes(OOSTUBS_RESULTS_ADDR, sizeof(results), results);
|
simulator.getMemoryManager().getBytes(OOSTUBS_RESULTS_ADDR, sizeof(results), results);
|
||||||
for (unsigned i = 0; i < sizeof(results) / sizeof(*results); ++i) {
|
for (unsigned i = 0; i < sizeof(results) / sizeof(*results); ++i) {
|
||||||
@ -124,7 +124,7 @@ bool ChecksumOOStuBSExperiment::run()
|
|||||||
}
|
}
|
||||||
of.close();
|
of.close();
|
||||||
log << "trace written to " << tracefile << endl;
|
log << "trace written to " << tracefile << endl;
|
||||||
|
|
||||||
#elif 1
|
#elif 1
|
||||||
// STEP 3: The actual experiment.
|
// STEP 3: The actual experiment.
|
||||||
#if !LOCAL
|
#if !LOCAL
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#ifndef __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
#ifndef __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||||
#define __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
#define __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||||
|
|
||||||
#include "efw/ExperimentFlow.hpp"
|
#include "efw/ExperimentFlow.hpp"
|
||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __EXPERIMENT_INFO_HPP__
|
#ifndef __EXPERIMENT_INFO_HPP__
|
||||||
#define __EXPERIMENT_INFO_HPP__
|
#define __EXPERIMENT_INFO_HPP__
|
||||||
|
|
||||||
// FIXME autogenerate this
|
// FIXME autogenerate this
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ bool CoolChecksumCampaign::run()
|
|||||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||||
d->msg.set_instr_offset(instr_offset);
|
d->msg.set_instr_offset(instr_offset);
|
||||||
d->msg.set_bit_offset(bit_offset);
|
d->msg.set_bit_offset(bit_offset);
|
||||||
|
|
||||||
campaignmanager.addParam(d);
|
campaignmanager.addParam(d);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
@ -107,8 +107,8 @@ bool CoolChecksumCampaign::run()
|
|||||||
address_t instr_absolute = 0; // FIXME this one probably should also be recorded ...
|
address_t instr_absolute = 0; // FIXME this one probably should also be recorded ...
|
||||||
Trace_Event ev;
|
Trace_Event ev;
|
||||||
ps.reset();
|
ps.reset();
|
||||||
|
|
||||||
while(ps.getNext(&ev)) {
|
while (ps.getNext(&ev)) {
|
||||||
// only count instruction events
|
// only count instruction events
|
||||||
if (!ev.has_memaddr()) {
|
if (!ev.has_memaddr()) {
|
||||||
// new instruction
|
// new instruction
|
||||||
@ -131,7 +131,7 @@ bool CoolChecksumCampaign::run()
|
|||||||
// we now have an interval-terminating R/W
|
// we now have an interval-terminating R/W
|
||||||
// event to the memaddr we're currently looking
|
// event to the memaddr we're currently looking
|
||||||
// at:
|
// at:
|
||||||
|
|
||||||
// complete the equivalence interval
|
// complete the equivalence interval
|
||||||
current_ec.instr2 = instr;
|
current_ec.instr2 = instr;
|
||||||
current_ec.instr2_absolute = instr_absolute;
|
current_ec.instr2_absolute = instr_absolute;
|
||||||
@ -150,7 +150,7 @@ bool CoolChecksumCampaign::run()
|
|||||||
} else {
|
} else {
|
||||||
log << "WAT" << endl;
|
log << "WAT" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// next interval must start at next
|
// next interval must start at next
|
||||||
// instruction; the aforementioned
|
// instruction; the aforementioned
|
||||||
// skipping mechanism wouldn't work
|
// skipping mechanism wouldn't work
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __COOLCAMPAIGN_HPP__
|
#ifndef __COOLCAMPAIGN_HPP__
|
||||||
#define __COOLCAMPAIGN_HPP__
|
#define __COOLCAMPAIGN_HPP__
|
||||||
|
|
||||||
#include "cpn/Campaign.hpp"
|
#include "cpn/Campaign.hpp"
|
||||||
#include "comm/ExperimentData.hpp"
|
#include "comm/ExperimentData.hpp"
|
||||||
|
|||||||
@ -30,7 +30,7 @@ bool CoolChecksumExperiment::run()
|
|||||||
{
|
{
|
||||||
Logger log("CoolChecksum", false);
|
Logger log("CoolChecksum", false);
|
||||||
BPSingleListener bp;
|
BPSingleListener bp;
|
||||||
|
|
||||||
log << "startup" << endl;
|
log << "startup" << endl;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#ifndef __COOLEXPERIMENT_HPP__
|
#ifndef __COOLEXPERIMENT_HPP__
|
||||||
#define __COOLEXPERIMENT_HPP__
|
#define __COOLEXPERIMENT_HPP__
|
||||||
|
|
||||||
#include "efw/ExperimentFlow.hpp"
|
#include "efw/ExperimentFlow.hpp"
|
||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef __EXPERIMENT_INFO_HPP__
|
#ifndef __EXPERIMENT_INFO_HPP__
|
||||||
#define __EXPERIMENT_INFO_HPP__
|
#define __EXPERIMENT_INFO_HPP__
|
||||||
|
|
||||||
#define COOL_FAULTSPACE_PRUNING 0
|
#define COOL_FAULTSPACE_PRUNING 0
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user