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