Files
revng-revng/lib/PipelineC/Tracing/Inspector.cpp
Alessandro Di Federico 5820908675 Remove and ban \file
2025-12-16 17:41:55 +01:00

106 lines
3.1 KiB
C++

/// 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);
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 revng::createError("Command number OOB");
const revng::tracing::Command &Command = this->Commands[CommandNo];
if (!BufferRegistry.has(Command.Name)
|| !BufferRegistry[Command.Name].contains(ArgNo))
return revng::createError("No buffer information");
return extractBuffer(Command.Arguments[ArgNo]);
}
} // namespace revng::tracing