mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
Pass PlainMetaAddress by pointer
This commit is contained in:
@@ -39,10 +39,10 @@ provide a quick summary of the required functions as they are implemented in
|
||||
possible to catch attempts to open ``/proc/self/map`` and redirect it
|
||||
somewhere else transparently.
|
||||
|
||||
:unknownPC: Function handling the situation in which the code at an address that
|
||||
should be executed has not been translated (see
|
||||
`GeneratedIRReference.rst`_). It is basically an error handling
|
||||
function that is supposed to never return.
|
||||
:unknown_pc: Function handling the situation in which the code at an address that
|
||||
should be executed has not been translated (see
|
||||
`GeneratedIRReference.rst`_). It is basically an error handling
|
||||
function that is supposed to never return.
|
||||
|
||||
:newpc: As seen in `GeneratedIRReference.rst`_, each input instruction is
|
||||
delimited by a call to a ``newpc`` function. This function is not just a
|
||||
|
||||
@@ -294,7 +294,7 @@ program to the first basic block containing the code generated due to A.
|
||||
counter might be actually invalid or it could belong
|
||||
to a function in a dynamic library. In this case, we
|
||||
simply leave the translated realm and jump there.
|
||||
:``dispatcher.default``: calls the ``unknownPC`` function, whose definition is
|
||||
:``dispatcher.default``: calls the ``unknown_pc`` function, whose definition is
|
||||
left to the user. The default implementation in
|
||||
``support.c`` aborts the program execution.
|
||||
:``anypc``: handles the situation in which we were not able to fully enumerate
|
||||
@@ -342,7 +342,7 @@ Here's how it looks like in our example:
|
||||
br i1 %46, label %dispatcher.default, label %setjmp
|
||||
|
||||
dispatcher.default: ; preds = %dispatcher.entry
|
||||
call void @unknownPC()
|
||||
call void @unknown_pc()
|
||||
unreachable
|
||||
|
||||
anypc: ; preds = %entrypoint
|
||||
|
||||
@@ -14,8 +14,8 @@ typedef struct {
|
||||
} PlainMetaAddress;
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
PlainMetaAddress build_PlainMetaAddress(uint32_t Epoch,
|
||||
uint16_t AddressSpace,
|
||||
uint16_t Type,
|
||||
uint64_t Address)
|
||||
__attribute__((const));
|
||||
void set_PlainMetaAddress(PlainMetaAddress *This,
|
||||
uint32_t Epoch,
|
||||
uint16_t AddressSpace,
|
||||
uint16_t Type,
|
||||
uint64_t Address);
|
||||
|
||||
@@ -55,10 +55,10 @@ protected:
|
||||
|
||||
protected:
|
||||
unsigned Alignment;
|
||||
llvm::GlobalVariable *AddressCSV;
|
||||
llvm::GlobalVariable *EpochCSV;
|
||||
llvm::GlobalVariable *AddressSpaceCSV;
|
||||
llvm::GlobalVariable *TypeCSV;
|
||||
llvm::GlobalVariable *AddressCSV = nullptr;
|
||||
llvm::GlobalVariable *EpochCSV = nullptr;
|
||||
llvm::GlobalVariable *AddressSpaceCSV = nullptr;
|
||||
llvm::GlobalVariable *TypeCSV = nullptr;
|
||||
|
||||
std::set<llvm::GlobalVariable *> CSVsAffectingPC;
|
||||
|
||||
@@ -67,12 +67,7 @@ public:
|
||||
using DispatcherTargets = std::vector<DispatcherTarget>;
|
||||
|
||||
protected:
|
||||
ProgramCounterHandler(unsigned Alignment) :
|
||||
Alignment(Alignment),
|
||||
AddressCSV(nullptr),
|
||||
EpochCSV(nullptr),
|
||||
AddressSpaceCSV(nullptr),
|
||||
TypeCSV(nullptr) {}
|
||||
ProgramCounterHandler(unsigned Alignment) : Alignment(Alignment) {}
|
||||
|
||||
public:
|
||||
virtual ~ProgramCounterHandler() {}
|
||||
@@ -124,9 +119,12 @@ public:
|
||||
setPC(Builder, Address);
|
||||
}
|
||||
|
||||
llvm::Value *buildCurrentPCPlainMetaAddress(llvm::IRBuilder<> &Builder) const;
|
||||
llvm::Value *buildPlainMetaAddress(llvm::IRBuilder<> &Builder,
|
||||
const MetaAddress &Address) const;
|
||||
void setCurrentPCPlainMetaAddress(llvm::IRBuilder<> &Builder) const;
|
||||
void setLastPCPlainMetaAddress(llvm::IRBuilder<> &Builder,
|
||||
const MetaAddress &Address) const;
|
||||
void setPlainMetaAddress(llvm::IRBuilder<> &Builder,
|
||||
llvm::StringRef GlobalName,
|
||||
const MetaAddress &Address) const;
|
||||
|
||||
protected:
|
||||
virtual void initializePCInternal(llvm::IRBuilder<> &Builder,
|
||||
|
||||
@@ -234,11 +234,8 @@ void IFI::emitCall(IRBuilder<> &Builder,
|
||||
|
||||
auto *PCH = GCBI.programCounterHandler();
|
||||
|
||||
auto AddArguments = [&Arguments, &Builder](llvm::Value *V) {
|
||||
llvm::copy(unpack(Builder, V), std::back_inserter(Arguments));
|
||||
};
|
||||
AddArguments(PCH->buildPlainMetaAddress(Builder, SourcePC));
|
||||
AddArguments(PCH->buildCurrentPCPlainMetaAddress(Builder));
|
||||
PCH->setLastPCPlainMetaAddress(Builder, SourcePC);
|
||||
PCH->setCurrentPCPlainMetaAddress(Builder);
|
||||
|
||||
auto *NewCall = Builder.CreateCall(Callee, Arguments);
|
||||
NewCall->setDebugLoc(DbgLocation);
|
||||
|
||||
@@ -965,15 +965,16 @@ void JumpTargetManager::prepareDispatcher() {
|
||||
TheFunction);
|
||||
Builder.SetInsertPoint(DispatcherFail);
|
||||
|
||||
FunctionCallee UnknownPC = TheModule.getFunction("unknownPC");
|
||||
FunctionCallee UnknownPC = TheModule.getFunction("unknown_pc");
|
||||
{
|
||||
auto *UnknownPCFunction = cast<Function>(skipCasts(UnknownPC.getCallee()));
|
||||
FunctionTags::Exceptional.addTo(UnknownPCFunction);
|
||||
}
|
||||
|
||||
Builder.CreateCall(UnknownPC,
|
||||
unpack(Builder,
|
||||
PCH->buildCurrentPCPlainMetaAddress(Builder)));
|
||||
PCH->setCurrentPCPlainMetaAddress(Builder);
|
||||
|
||||
Builder.CreateCall(UnknownPC);
|
||||
|
||||
auto *FailUnreachable = Builder.CreateUnreachable();
|
||||
setBlockType(FailUnreachable, BlockType::DispatcherFailureBlock);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/Support/ModRef.h"
|
||||
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/ProgramCounterHandler.h"
|
||||
|
||||
using namespace llvm;
|
||||
@@ -360,49 +361,62 @@ bool PCH::isPCAffectingHelper(Instruction *I) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static llvm::Value *buildPlainMetaAddressImpl(llvm::IRBuilder<> &Builder,
|
||||
Value *Epoch,
|
||||
Value *AddressSpace,
|
||||
Value *Type,
|
||||
Value *Address) {
|
||||
static void setPlainMetaAddressImpl(IRBuilder<> &Builder,
|
||||
StringRef GlobalName,
|
||||
Value *Epoch,
|
||||
Value *AddressSpace,
|
||||
Value *Type,
|
||||
Value *Address) {
|
||||
using namespace llvm;
|
||||
|
||||
BasicBlock *BB = Builder.GetInsertBlock();
|
||||
Module *M = BB->getParent()->getParent();
|
||||
|
||||
Function *MetaAddressConstuctor = M->getFunction("build_PlainMetaAddress");
|
||||
MetaAddressConstuctor->setMemoryEffects(MemoryEffects::none());
|
||||
GlobalVariable *Global = M->getGlobalVariable(GlobalName);
|
||||
revng_assert(Global != nullptr);
|
||||
|
||||
Function *MetaAddressConstuctor = M->getFunction("set_PlainMetaAddress");
|
||||
auto WriteArguments = MemoryEffects::argMemOnly(ModRefInfo::Mod);
|
||||
MetaAddressConstuctor->setMemoryEffects(WriteArguments);
|
||||
MetaAddressConstuctor->addFnAttr(Attribute::WillReturn);
|
||||
MetaAddressConstuctor->addFnAttr(Attribute::NoUnwind);
|
||||
auto *FT = MetaAddressConstuctor->getFunctionType();
|
||||
return Builder
|
||||
.CreateCall(MetaAddressConstuctor,
|
||||
{ Builder.CreateZExt(Epoch, FT->getParamType(0)),
|
||||
Builder.CreateZExt(AddressSpace, FT->getParamType(1)),
|
||||
Builder.CreateZExt(Type, FT->getParamType(2)),
|
||||
Builder.CreateZExt(Address, FT->getParamType(3)) });
|
||||
Builder.CreateCall(MetaAddressConstuctor,
|
||||
{ Global,
|
||||
Builder.CreateZExt(Epoch, FT->getParamType(1)),
|
||||
Builder.CreateZExt(AddressSpace, FT->getParamType(2)),
|
||||
Builder.CreateZExt(Type, FT->getParamType(3)),
|
||||
Builder.CreateZExt(Address, FT->getParamType(4)) });
|
||||
}
|
||||
|
||||
Value *PCH::buildCurrentPCPlainMetaAddress(IRBuilder<> &Builder) const {
|
||||
return buildPlainMetaAddressImpl(Builder,
|
||||
createLoad(Builder, EpochCSV),
|
||||
createLoad(Builder, AddressSpaceCSV),
|
||||
createLoad(Builder, TypeCSV),
|
||||
createLoad(Builder, AddressCSV));
|
||||
void PCH::setCurrentPCPlainMetaAddress(IRBuilder<> &Builder) const {
|
||||
setPlainMetaAddressImpl(Builder,
|
||||
"current_pc",
|
||||
createLoad(Builder, EpochCSV),
|
||||
createLoad(Builder, AddressSpaceCSV),
|
||||
createLoad(Builder, TypeCSV),
|
||||
createLoad(Builder, AddressCSV));
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
ProgramCounterHandler::buildPlainMetaAddress(llvm::IRBuilder<> &Builder,
|
||||
const MetaAddress &Address) const {
|
||||
void PCH::setLastPCPlainMetaAddress(IRBuilder<> &Builder,
|
||||
const MetaAddress &Address) const {
|
||||
setPlainMetaAddress(Builder, "last_pc", Address);
|
||||
}
|
||||
|
||||
void ProgramCounterHandler::setPlainMetaAddress(llvm::IRBuilder<> &Builder,
|
||||
StringRef GlobalName,
|
||||
const MetaAddress &Address)
|
||||
const {
|
||||
auto CI = [](llvm::GlobalVariable *Example, uint64_t Value) -> ConstantInt * {
|
||||
auto *Type = Example->getValueType();
|
||||
return ConstantInt::get(cast<IntegerType>(Type), Value);
|
||||
};
|
||||
return buildPlainMetaAddressImpl(Builder,
|
||||
CI(EpochCSV, Address.Epoch),
|
||||
CI(AddressSpaceCSV, Address.AddressSpace),
|
||||
CI(TypeCSV, Address.Type),
|
||||
CI(AddressCSV, Address.Address));
|
||||
setPlainMetaAddressImpl(Builder,
|
||||
GlobalName,
|
||||
CI(EpochCSV, Address.Epoch),
|
||||
CI(AddressSpaceCSV, Address.AddressSpace),
|
||||
CI(TypeCSV, Address.Type),
|
||||
CI(AddressCSV, Address.Address));
|
||||
}
|
||||
|
||||
std::pair<NextJumpTarget::Values, MetaAddress>
|
||||
|
||||
+13
-11
@@ -8,24 +8,26 @@
|
||||
|
||||
#include "support.h"
|
||||
|
||||
PlainMetaAddress last_pc;
|
||||
PlainMetaAddress current_pc;
|
||||
|
||||
// The only purpose of this function is keeping alive the references to some
|
||||
// symbols that are needed by revng
|
||||
intptr_t ignore(void);
|
||||
intptr_t ignore(void) {
|
||||
return (intptr_t) &saved_registers + (intptr_t) &setjmp
|
||||
+ (intptr_t) &jmp_buffer + (intptr_t) &is_executable
|
||||
+ (intptr_t) &unknownPC + (intptr_t) &_abort
|
||||
+ (intptr_t) &unknown_pc + (intptr_t) &_abort
|
||||
+ (intptr_t) &_unreachable;
|
||||
}
|
||||
|
||||
PlainMetaAddress build_PlainMetaAddress(uint32_t Epoch,
|
||||
uint16_t AddressSpace,
|
||||
uint16_t Type,
|
||||
uint64_t Address) {
|
||||
PlainMetaAddress Result;
|
||||
Result.Epoch = Epoch;
|
||||
Result.AddressSpace = AddressSpace;
|
||||
Result.Type = Type;
|
||||
Result.Address = Address;
|
||||
return Result;
|
||||
void set_PlainMetaAddress(PlainMetaAddress *This,
|
||||
uint32_t Epoch,
|
||||
uint16_t AddressSpace,
|
||||
uint16_t Type,
|
||||
uint64_t Address) {
|
||||
This->Epoch = Epoch;
|
||||
This->AddressSpace = AddressSpace;
|
||||
This->Type = Type;
|
||||
This->Address = Address;
|
||||
}
|
||||
|
||||
+11
-16
@@ -252,10 +252,10 @@ void g_assertion_message_expr(const char *domain,
|
||||
const char *expr) {
|
||||
}
|
||||
|
||||
void unknownPC(PlainMetaAddress PC) {
|
||||
void unknown_pc() {
|
||||
int arg;
|
||||
fprintf(stderr, "Unknown PC:");
|
||||
fprint_metaaddress(stderr, &PC);
|
||||
fprint_metaaddress(stderr, ¤t_pc);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
for (arg = 0; arg < saved_argc; arg++) {
|
||||
@@ -268,8 +268,7 @@ void unknownPC(PlainMetaAddress PC) {
|
||||
}
|
||||
|
||||
void jump_to_symbol(char *Symbol) {
|
||||
PlainMetaAddress Empty = { 0 };
|
||||
_abort(Symbol, Empty, Empty);
|
||||
_abort(Symbol);
|
||||
}
|
||||
|
||||
#ifdef TRACE
|
||||
@@ -467,14 +466,14 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
static noreturn void fail(const char *reason,
|
||||
PlainMetaAddress source,
|
||||
PlainMetaAddress destination) {
|
||||
PlainMetaAddress *source,
|
||||
PlainMetaAddress *destination) {
|
||||
// Dump information about the exception
|
||||
fprintf(stderr, "Exception: %s", reason);
|
||||
fprintf(stderr, " (");
|
||||
fprint_metaaddress(stderr, &source);
|
||||
fprint_metaaddress(stderr, source);
|
||||
fprintf(stderr, " -> ");
|
||||
fprint_metaaddress(stderr, &destination);
|
||||
fprint_metaaddress(stderr, destination);
|
||||
fprintf(stderr, ")\n");
|
||||
|
||||
// Declare the exception object
|
||||
@@ -486,14 +485,10 @@ static noreturn void fail(const char *reason,
|
||||
abort();
|
||||
}
|
||||
|
||||
noreturn void _abort(const char *reason,
|
||||
PlainMetaAddress source,
|
||||
PlainMetaAddress destination) {
|
||||
fail(reason, source, destination);
|
||||
noreturn void _abort(const char *reason) {
|
||||
fail(reason, &last_pc, ¤t_pc);
|
||||
}
|
||||
|
||||
noreturn void _unreachable(const char *reason,
|
||||
PlainMetaAddress source,
|
||||
PlainMetaAddress destination) {
|
||||
fail(reason, source, destination);
|
||||
noreturn void _unreachable(const char *reason) {
|
||||
fail(reason, &last_pc, ¤t_pc);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,9 @@ typedef uint64_t target_reg;
|
||||
|
||||
#endif
|
||||
|
||||
extern PlainMetaAddress last_pc;
|
||||
extern PlainMetaAddress current_pc;
|
||||
|
||||
// Register values before the signal was triggered
|
||||
extern target_reg *saved_registers;
|
||||
|
||||
@@ -109,12 +112,8 @@ extern jmp_buf jmp_buffer;
|
||||
|
||||
bool is_executable(uint64_t pc);
|
||||
void set_register(uint32_t register_id, uint64_t value);
|
||||
void unknownPC(PlainMetaAddress PC);
|
||||
void unknown_pc();
|
||||
|
||||
noreturn void _abort(const char *reason,
|
||||
PlainMetaAddress source,
|
||||
PlainMetaAddress destination);
|
||||
noreturn void _abort(const char *reason);
|
||||
|
||||
noreturn void _unreachable(const char *reason,
|
||||
PlainMetaAddress source,
|
||||
PlainMetaAddress destination);
|
||||
noreturn void _unreachable(const char *reason);
|
||||
|
||||
Reference in New Issue
Block a user