Files
revng-revng/tools/trace/inspect/Main.cpp
Giacomo Vercesi a2b7d0e0bf PipelineC: add tracing
Add support for tracing onto the PipelineC. This is done by:
1. Creating wrapper functions for each PipelineC function with the
   script in `scripts/PipelineC_add_tracing.py`. These will call a
   special function called `wrap` which will ultimately call a method
   with a `_` prepended to the name
2. Conversion of all PipelineC methods in `PipelineC.cpp` to `static`
   and their rename with a `_` in front, in order for them to work with
   the wrapper function in (1)
3. Generation of 2 additional include files, one for types and one for
   functions, to be used by users of tracing files in order to have
   introspection.

These steps allow the creation of a trace file with the use of the
`REVNG_C_API_TRACE_PATH` environment variable. The traces can then be
used in conjunction with the `revng trace run` and `revng trace
inspect` commands.
2023-04-20 14:43:13 +02:00

114 lines
3.5 KiB
C++

//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <iostream>
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ToolOutputFile.h"
#include "revng/PipelineC/Tracing/Trace.h"
#include "revng/Support/CommandLine.h"
#include "revng/Support/InitRevng.h"
using llvm::StringRef;
using revng::tracing::BufferLocation;
using revng::tracing::Trace;
namespace Options {
using namespace llvm::cl;
using std::string;
static OptionCategory ThisToolCategory("Tool options", "");
static opt<string> Input(Positional,
cat(ThisToolCategory),
desc("<input trace file>"),
value_desc("input trace file"));
static opt<bool> ListBuffers("list-buffers",
desc("List the buffers present on the trace"),
cat(ThisToolCategory),
init(false));
static opt<string> ExtractBuffer("extract-buffer",
cat(ThisToolCategory),
desc("Buffer to extract"),
value_desc("COMMANDNO:ARGNO"));
static alias ExtractBufferA("e",
cat(ThisToolCategory),
desc("Alias for --extract-buffer"),
aliasopt(ExtractBuffer));
static opt<string> Output("output",
cat(ThisToolCategory),
desc("Output file when extracting"),
value_desc("file"));
static alias OutputA("o",
cat(ThisToolCategory),
desc("Alias for --output"),
aliasopt(Output));
} // namespace Options
static llvm::ExitOnError AbortOnError;
int main(int argc, const char *argv[]) {
revng::InitRevng X(argc, argv);
llvm::cl::HideUnrelatedOptions({ &Options::ThisToolCategory });
llvm::cl::ParseCommandLineOptions(argc, argv);
if (Options::ListBuffers xor Options::ExtractBuffer.empty()) {
dbg << "Please specify either --list-buffers or --extract-buffer\n";
return EXIT_FAILURE;
}
if (Options::ListBuffers) {
Trace TheTrace = AbortOnError(Trace::fromFile(Options::Input));
std::vector<BufferLocation> Result = TheTrace.listBuffers();
for (auto &Location : Result) {
std::cout << "Buffer on command " << Location.CommandName << " (Command #"
<< Location.CommandNumber << "), argument #"
<< Location.ArgumentNumber << "\n";
}
return EXIT_SUCCESS;
}
if (!Options::ExtractBuffer.empty()) {
if (Options::Output.empty()) {
dbg << "Please specify an output file\n";
return EXIT_FAILURE;
}
size_t CommandNo = 0;
size_t ArgNo = 0;
auto [CommandNoStr,
ArgNoStr] = StringRef(Options::ExtractBuffer).split(":");
if (CommandNoStr.getAsInteger(10, CommandNo)
|| ArgNoStr.getAsInteger(10, ArgNo)) {
dbg << "Error parsing extract value\n";
return EXIT_FAILURE;
}
Trace TheTrace = AbortOnError(Trace::fromFile(Options::Input));
using Buffer = std::vector<char>;
Buffer Result = AbortOnError(TheTrace.getBuffer(CommandNo, ArgNo));
std::error_code EC;
llvm::ToolOutputFile OutputFile(Options::Output,
EC,
llvm::sys::fs::OF_None);
OutputFile.os() << llvm::StringRef(Result.data(), Result.size());
OutputFile.keep();
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}