diff --git a/docs/GeneratedIRReference.rst b/docs/GeneratedIRReference.rst index b2429211f..3cd182d28 100644 --- a/docs/GeneratedIRReference.rst +++ b/docs/GeneratedIRReference.rst @@ -216,6 +216,9 @@ two values: the input architecture. :``string PCRegisterName``: the name of the CSV representing the program counter. :``string SPRegisterName``: the name of the CSV representing the stack pointer. +:``string RARegisterName``: the name of the CSV representing the return address; + e.g., in ARM, it is represented by the link register. +:``i64 MinimalFinalStackOffset``: the minimal stack offset for the ABI. :``string[] ABIRegisters``: list of name of the CSV involved in the ABI, and that, therefore need to be serialized before passing from the translated realm to the native realm and @@ -226,7 +229,7 @@ Here's how this information appears in our example: .. code-block:: llvm !revng.input.architecture = !{!1} - !1 = !{!"x86_64", i32 1, i32 0, !"pc", !"rsp", !2} + !1 = !{!"x86_64", i32 1, i32 0, !"pc", !"rsp", "", 8, !2} !2 = !{!"rax", !"rbx", !"rcx", !"rdx", !"rbp", ... } x86-64 has no instruction alignment requirements, no delay slot and the CSV diff --git a/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h b/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h index ea762b321..5286a4fe1 100644 --- a/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h +++ b/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h @@ -47,6 +47,9 @@ public: InstructionAlignment(0), DelaySlotSize(0), PC(nullptr), + SP(nullptr), + RA(nullptr), + MinimalFSO(0), Dispatcher(nullptr), DispatcherFail(nullptr), AnyPC(nullptr), @@ -156,6 +159,11 @@ public: /// \brief Return the CSV representing the stack pointer llvm::GlobalVariable *spReg() const { return SP; } + /// \brief Return the CSV representing the return address register + llvm::GlobalVariable *raReg() const { return RA; } + + int64_t minimalFSO() const { return MinimalFSO; } + llvm::Triple::ArchType arch() const { return ArchType; } /// \brief Check if \p GV is the stack pointer CSV @@ -461,6 +469,8 @@ private: uint32_t DelaySlotSize; llvm::GlobalVariable *PC; llvm::GlobalVariable *SP; + llvm::GlobalVariable *RA; + int64_t MinimalFSO; llvm::BasicBlock *Dispatcher; llvm::BasicBlock *DispatcherFail; llvm::BasicBlock *AnyPC; diff --git a/include/revng/Support/revng.h b/include/revng/Support/revng.h index 99d6476ca..4cb5f3e95 100644 --- a/include/revng/Support/revng.h +++ b/include/revng/Support/revng.h @@ -4,6 +4,7 @@ // This file is distributed under the MIT License. See LICENSE.md for details. // +#include #include #include #include @@ -281,6 +282,8 @@ public: llvm::ArrayRef NoReturnSyscalls, uint32_t DelaySlotSize, llvm::StringRef StackPointerRegister, + llvm::StringRef ReturnAddressRegister, + int64_t MinimalFinalStackOffset, llvm::SmallVector ABIRegisters, unsigned PCMContextIndex, llvm::StringRef WriteRegisterAsm, @@ -300,6 +303,8 @@ public: NoReturnSyscalls(NoReturnSyscalls), DelaySlotSize(DelaySlotSize), StackPointerRegister(StackPointerRegister), + ReturnAddressRegister(ReturnAddressRegister), + MinimalFinalStackOffset(MinimalFinalStackOffset), ABIRegisters(ABIRegisters), PCMContextIndex(PCMContextIndex), WriteRegisterAsm(WriteRegisterAsm), @@ -323,6 +328,10 @@ public: return SyscallNumberRegister; } llvm::StringRef stackPointerRegister() const { return StackPointerRegister; } + llvm::StringRef returnAddressRegister() const { + return ReturnAddressRegister; + } + int64_t minimalFinalStackOffset() const { return MinimalFinalStackOffset; } llvm::ArrayRef noReturnSyscalls() const { return NoReturnSyscalls; } uint32_t delaySlotSize() const { return DelaySlotSize; } const llvm::SmallVector &abiRegisters() const { @@ -364,6 +373,8 @@ private: llvm::ArrayRef NoReturnSyscalls; uint32_t DelaySlotSize; llvm::StringRef StackPointerRegister; + llvm::StringRef ReturnAddressRegister; + int64_t MinimalFinalStackOffset; llvm::SmallVector ABIRegisters; unsigned PCMContextIndex; llvm::StringRef WriteRegisterAsm; diff --git a/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp b/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp index 4129577e2..a9630bdde 100644 --- a/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp +++ b/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp @@ -50,6 +50,8 @@ void GeneratedCodeBasicInfo::run(Module &M) { DelaySlotSize = QMD.extract(Tuple, Index++); PC = M.getGlobalVariable(QMD.extract(Tuple, Index++), true); SP = M.getGlobalVariable(QMD.extract(Tuple, Index++), true); + RA = M.getGlobalVariable(QMD.extract(Tuple, Index++), true); + MinimalFSO = QMD.extract(Tuple, Index++); auto Operands = QMD.extract(Tuple, Index++)->operands(); for (const MDOperand &Operand : Operands) { StringRef Name = QMD.extract(Operand.get()); diff --git a/tools/revng-lift/BinaryFile.cpp b/tools/revng-lift/BinaryFile.cpp index 66b9b423f..06ec7e826 100644 --- a/tools/revng-lift/BinaryFile.cpp +++ b/tools/revng-lift/BinaryFile.cpp @@ -217,6 +217,8 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : StringRef SyscallHelper = ""; StringRef SyscallNumberRegister = ""; StringRef StackPointerRegister = ""; + StringRef ReturnAddressRegister = ""; + int64_t MinimalFinalStackOffset = 0; ArrayRef NoReturnSyscalls = {}; SmallVector ABIRegisters; uint32_t DelaySlotSize = 0; @@ -240,6 +242,7 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : SyscallHelper = "helper_raise_interrupt"; SyscallNumberRegister = "eax"; StackPointerRegister = "esp"; + MinimalFinalStackOffset = 4; NoReturnSyscalls = { 0xfc, // exit_group 0x01, // exit @@ -266,6 +269,7 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : SyscallHelper = "helper_syscall"; SyscallNumberRegister = "rax"; StackPointerRegister = "rsp"; + MinimalFinalStackOffset = 8; NoReturnSyscalls = { 0xe7, // exit_group 0x3c, // exit @@ -341,6 +345,7 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : SyscallHelper = "helper_exception_with_syndrome"; SyscallNumberRegister = "r7"; StackPointerRegister = "r13"; + ReturnAddressRegister = "r14"; NoReturnSyscalls = { 0xf8, // exit_group 0x1, // exit @@ -370,6 +375,7 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : SyscallHelper = "helper_exception_with_syndrome"; SyscallNumberRegister = "x8"; StackPointerRegister = "sp"; + ReturnAddressRegister = "lr"; NoReturnSyscalls = { 0x5e, // exit_group 0x5d, // exit @@ -398,6 +404,7 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : SyscallHelper = "helper_raise_exception"; SyscallNumberRegister = "v0"; StackPointerRegister = "sp"; + ReturnAddressRegister = "ra"; NoReturnSyscalls = { 0x1096, // exit_group 0xfa1, // exit @@ -430,6 +437,7 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : SyscallHelper = "helper_exception"; SyscallNumberRegister = "r1"; StackPointerRegister = "r15"; + ReturnAddressRegister = "r14"; InstructionAlignment = 2; NoReturnSyscalls = { 0xf8, // exit_group @@ -470,6 +478,8 @@ BinaryFile::BinaryFile(std::string FilePath, uint64_t PreferedBaseAddress) : NoReturnSyscalls, DelaySlotSize, StackPointerRegister, + ReturnAddressRegister, + MinimalFinalStackOffset, ABIRegisters, PCMContextIndex, WriteRegisterAsm, diff --git a/tools/revng-lift/CodeGenerator.cpp b/tools/revng-lift/CodeGenerator.cpp index 4ad70e6f2..909f38f77 100644 --- a/tools/revng-lift/CodeGenerator.cpp +++ b/tools/revng-lift/CodeGenerator.cpp @@ -963,6 +963,7 @@ void CodeGenerator::translate(Optional RawVirtualAddress) { // DelaySlotSize, // PCRegisterName, // SPRegisterName, + // RARegisterName, // ABIRegisters // } @@ -978,6 +979,8 @@ void CodeGenerator::translate(Optional RawVirtualAddress) { QMD.get(Arch.delaySlotSize()), QMD.get("pc"), QMD.get(Arch.stackPointerRegister()), + QMD.get(Arch.returnAddressRegister()), + QMD.get(Arch.minimalFinalStackOffset()), QMD.tuple(ArrayRef(ABIRegMetadata)), }); MDName = "revng.input.architecture";