Files
revng-revng/lib/PipelineC/Tracing/Inspector.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

110 lines
3.3 KiB
C++

/// \file Runner.cpp
/// \brief Implements the logic for inspecting a trace file. Right now this
/// entails listing and extracting buffers
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "llvm/Support/Base64.h"
#include "revng/ADT/ConstexprString.h"
#include "revng/PipelineC/PipelineC.h"
#include "revng/PipelineC/Tracing/Common.h"
#include "revng/PipelineC/Tracing/Trace.h"
static class BufferRegistry {
private:
llvm::StringMap<std::set<size_t>> Registry;
public:
BufferRegistry() {
// Add autogenerated registerRunner calls to register the
// other functions automatically
#define FUNCTION(fname) registerFunction<#fname>(fname);
#include "revng/PipelineC/Functions.inc"
#undef FUNCTION
}
public:
bool has(const llvm::StringRef Name) { return Registry.count(Name) != 0; }
std::set<size_t> &operator[](const llvm::StringRef Name) {
return Registry[Name];
}
private:
template<ConstexprString Name, typename ArgTupleT, size_t I = 0>
void handleArguments() {
using ArgT = std::tuple_element_t<I, ArgTupleT>;
constexpr int LH = LengthHint<Name, I>;
if constexpr (anyOf<ArgT, char *, const char *>() && LH >= 0) {
std::string StrName(Name);
Registry[StrName].insert(I);
}
if constexpr (I + 1 < std::tuple_size_v<ArgTupleT>)
handleArguments<Name, ArgTupleT, I + 1>();
}
template<ConstexprString Name, typename ReturnT, typename... Args>
void handleFunction(std::function<ReturnT(Args...)> Function) {
if constexpr (sizeof...(Args) > 0)
handleArguments<Name, std::tuple<Args...>>();
}
template<ConstexprString Name, typename FunctionT>
void registerFunction(FunctionT Function) {
handleFunction<Name>(std::function{ Function });
}
} BufferRegistry;
inline llvm::Expected<std::vector<char>>
extractBuffer(const revng::tracing::Argument &Arg) {
revng_assert(Arg.isScalar());
std::vector<char> Result;
llvm::Error Err = llvm::decodeBase64(Arg.getScalar(), Result);
if (Err)
return std::move(Err);
llvm::consumeError(std::move(Err));
return Result;
}
namespace revng::tracing {
std::vector<BufferLocation> Trace::listBuffers() const {
std::vector<BufferLocation> Result;
for (size_t CommandI = 0; CommandI < this->Commands.size(); CommandI++) {
auto &Command = this->Commands[CommandI];
if (BufferRegistry.has(Command.Name)) {
for (size_t ArgI : BufferRegistry[Command.Name]) {
Result.push_back({ Command.Name, CommandI, ArgI });
}
}
}
return Result;
}
llvm::Expected<std::vector<char>>
Trace::getBuffer(const BufferLocation &Location) const {
return getBuffer(Location.CommandNumber, Location.ArgumentNumber);
};
llvm::Expected<std::vector<char>>
Trace::getBuffer(size_t CommandNo, size_t ArgNo) const {
if (CommandNo > this->Commands.size())
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Command number OOB");
const revng::tracing::Command &Command = this->Commands[CommandNo];
if (!BufferRegistry.has(Command.Name)
|| !BufferRegistry[Command.Name].contains(ArgNo))
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No buffer information");
return extractBuffer(Command.Arguments[ArgNo]);
}
} // namespace revng::tracing