forked from rose-compiler/rose
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(Binary Analysis) New instruction frequency tools
RPM-15
- Loading branch information
Showing
8 changed files
with
351 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
static const char *purpose = "compare instruction frequencies"; | ||
static const char *description = | ||
"Reads instruction frequencies from files specified on the command-line, then compares the first file with " | ||
"all the remaining files. The files must have been created with @sa{bat-insnfreq}(1)."; | ||
|
||
#include <rose.h> | ||
#include <CommandLine.h> // rose | ||
#include <Diagnostics.h> // rose | ||
|
||
#include <batSupport.h> | ||
#include <boost/filesystem.hpp> | ||
#include <Sawyer/CommandLine.h> | ||
|
||
using namespace Bat; | ||
using namespace Rose; | ||
using namespace Rose::BinaryAnalysis; | ||
using namespace Sawyer::Message::Common; | ||
|
||
static Sawyer::Message::Facility mlog; | ||
|
||
static std::vector<boost::filesystem::path> | ||
parseCommandLine(int argc, char *argv[]) { | ||
using namespace Sawyer::CommandLine; | ||
|
||
SwitchGroup generic = Rose::CommandLine::genericSwitches(); | ||
|
||
Parser parser = Rose::CommandLine::createEmptyParser(purpose, description); | ||
parser.errorStream(mlog[FATAL]); | ||
parser.doc("Synopsis", "@prop{programName} [@v{switches}] @v{freq_files}..."); | ||
|
||
std::vector<std::string> input = parser.parse(argc, argv).apply().unreachedArgs(); | ||
if (input.size() < 2) { | ||
mlog[FATAL] <<"at least two frequency files must be specified\n"; | ||
exit(1); | ||
} | ||
return std::vector<boost::filesystem::path>(input.begin(), input.end()); | ||
} | ||
|
||
int | ||
main(int argc, char *argv[]) { | ||
ROSE_INITIALIZE; | ||
Diagnostics::initAndRegister(&mlog, "tool"); | ||
mlog.comment("instruction frequencies"); | ||
Bat::checkRoseVersionNumber(MINIMUM_ROSE_LIBRARY_VERSION, mlog[FATAL]); | ||
Bat::registerSelfTests(); | ||
std::vector<boost::filesystem::path> fileNames = parseCommandLine(argc, argv); | ||
|
||
// Read the first histogram | ||
InsnHistogram a = loadInsnHistogram(fileNames[0]); | ||
std::vector<InsnHistogram> aQuartiles = splitInsnHistogram(a, 4); | ||
|
||
// Compare the first histogram with the rest | ||
std::vector<std::pair<boost::filesystem::path, double>> output; | ||
for (size_t i = 1; i < fileNames.size(); ++i) { | ||
InsnHistogram b = loadInsnHistogram(fileNames[i]); | ||
double diff = compareInsnHistograms(aQuartiles, b); | ||
output.push_back(std::make_pair(fileNames[i], diff)); | ||
} | ||
|
||
// Produce output | ||
std::sort(output.begin(), output.end(), [](auto &a, auto &b) { return a.second < b.second; }); | ||
for (const auto &pair: output) | ||
std::cout <<(boost::format("%7.3f%%") % (100.0*pair.second)) <<"\t" <<pair.first <<"\n"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
static const char *purpose = "count instructions"; | ||
static const char *description = | ||
"Scans the memory regions marked as executable and does a linear disassembly. The instruction mnemonics are listed along " | ||
"with the number of times they occur."; | ||
|
||
#include <rose.h> | ||
#include <CommandLine.h> // rose | ||
#include <Diagnostics.h> // rose | ||
#include <Partitioner2/Engine.h> // rose | ||
#include <Partitioner2/Partitioner.h> // rose | ||
|
||
#include <batSupport.h> | ||
#include <boost/filesystem.hpp> | ||
#include <boost/format.hpp> | ||
#include <Sawyer/CommandLine.h> | ||
|
||
using namespace Bat; | ||
using namespace Rose; | ||
using namespace Rose::BinaryAnalysis; | ||
using namespace Sawyer::Message::Common; | ||
namespace P2 = Rose::BinaryAnalysis::Partitioner2; | ||
|
||
static Sawyer::Message::Facility mlog; | ||
static SerialIo::Format stateFormat = SerialIo::BINARY; | ||
static boost::filesystem::path saveAs, augmentFrom; | ||
|
||
static std::vector<boost::filesystem::path> | ||
parseCommandLine(int argc, char *argv[]) { | ||
using namespace Sawyer::CommandLine; | ||
|
||
SwitchGroup generic = Rose::CommandLine::genericSwitches(); | ||
generic.insert(Bat::stateFileFormatSwitch(stateFormat)); | ||
generic.insert(Switch("output", 'o') | ||
.argument("file", anyParser(saveAs)) | ||
.doc("Save output in the specified file, overwriting the file if it already existed. The default " | ||
"is to print the output as a textual table to standard output.")); | ||
|
||
generic.insert(Switch("input", 'i') | ||
.argument("file", anyParser(augmentFrom)) | ||
.doc("Initialize the histogram with data from the specified file. This can be used to accumulate " | ||
"instruction frequencies across multiple specimens.")); | ||
|
||
Parser parser = Rose::CommandLine::createEmptyParser(purpose, description); | ||
parser.errorStream(mlog[FATAL]); | ||
parser.with(generic); | ||
parser.doc("Synopsis", "@prop{programName} [@v{switches}] [@v{rba_files}...]"); | ||
|
||
std::vector<std::string> input = parser.parse(argc, argv).apply().unreachedArgs(); | ||
return std::vector<boost::filesystem::path>(input.begin(), input.end()); | ||
} | ||
|
||
int | ||
main(int argc, char *argv[]) { | ||
ROSE_INITIALIZE; | ||
Diagnostics::initAndRegister(&mlog, "tool"); | ||
mlog.comment("instruction frequencies"); | ||
Bat::checkRoseVersionNumber(MINIMUM_ROSE_LIBRARY_VERSION, mlog[FATAL]); | ||
Bat::registerSelfTests(); | ||
std::vector<boost::filesystem::path> rbaFiles = parseCommandLine(argc, argv); | ||
|
||
// Initialize the histogram. | ||
InsnHistogram histogram; | ||
if (!augmentFrom.empty()) { | ||
if (!boost::filesystem::exists(augmentFrom) && augmentFrom == saveAs) { | ||
// As a special case, it's not an error if the augment-from file does not exist but would be created as the output | ||
// of this tool. This is so that this tool can be used in a shell "for" loop like: | ||
// rm result.dat | ||
// for f in *.rba; do | ||
// bat-insnfreq -a result.dat -o result.dat "$f" | ||
// done | ||
} else { | ||
try { | ||
histogram = loadInsnHistogram(augmentFrom); | ||
} catch (const SerialIo::Exception &e) { | ||
mlog[FATAL] <<e.what() <<"\n"; | ||
exit(1); | ||
} | ||
} | ||
} | ||
|
||
// Compute the histogram | ||
for (const boost::filesystem::path &rbaFile: rbaFiles) { | ||
P2::Engine engine; | ||
P2::Partitioner partitioner = engine.loadPartitioner(rbaFile, stateFormat); | ||
MemoryMap::Ptr map = partitioner.memoryMap(); | ||
ASSERT_not_null(map); | ||
mergeInsnHistogram(histogram, computeInsnHistogram(partitioner.instructionProvider(), map)); | ||
} | ||
|
||
// Emit results | ||
if (!saveAs.empty()) { | ||
saveInsnHistogram(histogram, saveAs); | ||
} else { | ||
printInsnHistogram(histogram, std::cout); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.