formatting, typos, comments, details
Change-Id: Iae5f1acb653a694622e9ac2bad93efcfca588f3a
This commit is contained in:
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user