diff --git a/SmallMap.h b/SmallMap.h index 5a171a75b..9cd256cc1 100644 --- a/SmallMap.h +++ b/SmallMap.h @@ -23,16 +23,18 @@ private: // Define some helpers template - struct are_same : std::false_type { }; + struct are_same : std::false_type {}; template - struct are_same : are_same { }; + struct are_same : are_same {}; template - struct are_same : std::true_type { }; + struct are_same : std::true_type {}; template - struct first { using type = P; }; + struct first { + using type = P; + }; // Assert correct usage static_assert(are_same::value_type...>::value, @@ -46,22 +48,28 @@ private: public: template - Iteratall(T I) : Iterator(I) { } + Iteratall(T I) : Iterator(I) {} private: struct PostincrementVisitor : public boost::static_visitor { - template - Iteratall operator()(T &It) const { return Iteratall(It++); } + template + Iteratall operator()(T &It) const { + return Iteratall(It++); + } }; struct PreincrementVisitor : public boost::static_visitor { - template - Iteratall operator()(T &It) const { return Iteratall(++It); } + template + Iteratall operator()(T &It) const { + return Iteratall(++It); + } }; struct DereferenceVisitor : public boost::static_visitor { - template - reference operator()(T &It) const { return *It; } + template + reference operator()(T &It) const { + return *It; + } }; struct CompareVisitor : public boost::static_visitor { @@ -93,23 +101,18 @@ public: return boost::apply_visitor(CompareVisitor(), Iterator, Other.Iterator); } - bool operator!=(const Iteratall &Other) const { - return !(*this == Other); - } + bool operator!=(const Iteratall &Other) const { return !(*this == Other); } reference operator*() const { return boost::apply_visitor(DereferenceVisitor(), Iterator); } - pointer operator->() const { - return &**this; - } + pointer operator->() const { return &**this; } private: boost::variant Iterator; }; - /// \brief map that usually contains less than N elements /// /// SmallMap keeps a std::array of pairs inline which are search linearly if @@ -119,10 +122,9 @@ private: /// default constructor to be used. /// /// \tparam N number of elements to keep inline. -template > +template> class SmallMap { private: - // Define some helper types using NonConstPair = std::pair; using NonConstContainer = std::array; @@ -146,16 +148,14 @@ private: std::map Map; private: - VIterator smallBegin() { - return reinterpret_cast(Vector.begin()); - } + VIterator smallBegin() { return reinterpret_cast(Vector.begin()); } ConstVIterator smallBegin() const { return reinterpret_cast(Vector.begin()); } public: - SmallMap() : IsSorted(true), Size(0) { } + SmallMap() : IsSorted(true), Size(0) {} SmallMap(const SmallMap &) = default; SmallMap &operator=(const SmallMap &Other) = default; @@ -163,8 +163,7 @@ public: SmallMap &operator=(SmallMap &&Other) = default; public: - using iterator = Iteratall::iterator>; + using iterator = Iteratall::iterator>; using const_iterator = Iteratall::const_iterator>; using size_type = size_t; @@ -177,7 +176,7 @@ public: if (IsSorted || !isSmall() || Size <= 1) return; - auto Compare = [] (const Pair &A, const Pair &B) { + auto Compare = [](const Pair &A, const Pair &B) { return std::less()(A.first, B.first); }; std::sort(Vector.begin(), Vector.begin() + Size, Compare); @@ -314,7 +313,6 @@ private: return I; return smallBegin() + Size; } - }; #endif // _SMALLMAP_H diff --git a/binaryfile.cpp b/binaryfile.cpp index e9af2a033..3242241d5 100644 --- a/binaryfile.cpp +++ b/binaryfile.cpp @@ -35,7 +35,8 @@ using std::make_pair; BinaryFile::BinaryFile(std::string FilePath, bool UseSections, - uint64_t BaseAddress) : BaseAddress(0) { + uint64_t BaseAddress) : + BaseAddress(0) { auto BinaryOrErr = object::createBinary(FilePath); assert(BinaryOrErr && "Couldn't open the input file"); @@ -48,7 +49,7 @@ BinaryFile::BinaryFile(std::string FilePath, StringRef SyscallHelper = ""; StringRef SyscallNumberRegister = ""; StringRef StackPointerRegister = ""; - ArrayRef NoReturnSyscalls = { }; + ArrayRef NoReturnSyscalls = {}; SmallVector ABIRegisters; uint32_t DelaySlotSize = 0; unsigned PCMContextIndex = ABIRegister::NotInMContext; @@ -65,9 +66,9 @@ BinaryFile::BinaryFile(std::string FilePath, SyscallNumberRegister = "eax"; StackPointerRegister = "esp"; NoReturnSyscalls = { - 0xfc, // exit_group - 0x01, // exit - 0x0b // execve + 0xfc, // exit_group + 0x01, // exit + 0x0b // execve }; HasRelocationAddend = false; BaseRelativeRelocation = llvm::ELF::R_386_RELATIVE; @@ -119,15 +120,29 @@ BinaryFile::BinaryFile(std::string FilePath, // REGISTER_OFFSET(RIP); // TODO: here we're hardcoding the offsets in the QEMU struct - ABIRegisters = { { "rax", 0xD }, { "rbx", 0xB }, { "rcx", 0xE }, - { "rdx", 0xC }, { "rbp", 0xA }, { "rsp", 0xF }, - { "rsi", 0x9 }, { "rdi", 0x8 }, { "r8", 0x0 }, - { "r9", 0x1 }, { "r10", 0x2 }, { "r11", 0x3 }, - { "r12", 0x4 }, { "r13", 0x5 }, { "r14", 0x6 }, - { "r15", 0x7 }, { "xmm0", "state_0x8558" }, - { "xmm1", "state_0x8598" }, { "xmm2", "state_0x85d8" }, - { "xmm3", "state_0x8618" }, { "xmm4", "state_0x8658" }, - { "xmm5", "state_0x8698" }, { "xmm6", "state_0x86d8" }, + ABIRegisters = { { "rax", 0xD }, + { "rbx", 0xB }, + { "rcx", 0xE }, + { "rdx", 0xC }, + { "rbp", 0xA }, + { "rsp", 0xF }, + { "rsi", 0x9 }, + { "rdi", 0x8 }, + { "r8", 0x0 }, + { "r9", 0x1 }, + { "r10", 0x2 }, + { "r11", 0x3 }, + { "r12", 0x4 }, + { "r13", 0x5 }, + { "r14", 0x6 }, + { "r15", 0x7 }, + { "xmm0", "state_0x8558" }, + { "xmm1", "state_0x8598" }, + { "xmm2", "state_0x85d8" }, + { "xmm3", "state_0x8618" }, + { "xmm4", "state_0x8658" }, + { "xmm5", "state_0x8698" }, + { "xmm6", "state_0x86d8" }, { "xmm7", "state_0x8718" } }; WriteRegisterAsm = "movq $0, %REGISTER"; ReadRegisterAsm = "movq %REGISTER, $0"; @@ -146,8 +161,8 @@ BinaryFile::BinaryFile(std::string FilePath, 0x1, // exit 0xb // execve }; - ABIRegisters = { { "r0" }, { "r1" }, { "r2" }, { "r3" }, { "r4" }, - { "r5" }, { "r6" }, { "r7" }, { "r8" }, { "r9" }, + ABIRegisters = { { "r0" }, { "r1" }, { "r2" }, { "r3" }, { "r4" }, + { "r5" }, { "r6" }, { "r7" }, { "r8" }, { "r9" }, { "r10" }, { "r11" }, { "r12" }, { "r13" }, { "r14" } }; HasRelocationAddend = false; BaseRelativeRelocation = llvm::ELF::R_ARM_RELATIVE; @@ -165,10 +180,10 @@ BinaryFile::BinaryFile(std::string FilePath, 0xfab // execve }; DelaySlotSize = 1; - ABIRegisters = { {"v0" }, { "v1" }, { "a0" }, { "a1" }, { "a2" }, { "a3" }, - { "s0" }, { "s1" }, { "s2" }, { "s3" }, { "s4" }, - { "s5" }, { "s6" }, { "s7" }, { "gp" }, { "sp" }, - { "fp" }, { "ra" } }; + ABIRegisters = + { { "v0" }, { "v1" }, { "a0" }, { "a1" }, { "a2" }, { "a3" }, + { "s0" }, { "s1" }, { "s2" }, { "s3" }, { "s4" }, { "s5" }, + { "s6" }, { "s7" }, { "gp" }, { "sp" }, { "fp" }, { "ra" } }; HasRelocationAddend = false; // TODO: check if this is correct // BaseRelativeRelocation = llvm::ELF::R_MIPS_REL32; @@ -182,8 +197,8 @@ BinaryFile::BinaryFile(std::string FilePath, InstructionAlignment = 2; NoReturnSyscalls = { 0xf8, // exit_group - 0x1, // exit - 0xb, // execve + 0x1, // exit + 0xb, // execve }; HasRelocationAddend = true; BaseRelativeRelocation = llvm::ELF::R_390_RELATIVE; @@ -255,7 +270,7 @@ private: uint64_t Address; public: - FilePortion() : HasAddress(false), HasSize(false), Size(0), Address(0) { } + FilePortion() : HasAddress(false), HasSize(false), Size(0), Address(0) {} public: void setAddress(uint64_t Address) { @@ -268,9 +283,7 @@ public: this->Size = Size; } - bool isAvailable() const { - return HasAddress; - } + bool isAvailable() const { return HasAddress; } bool isExact() const { assert(HasAddress); @@ -313,7 +326,6 @@ public: abort(); } - }; template @@ -384,12 +396,10 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, // Collect symbol names for (auto &Symbol : TheELF.symbols(SymtabShdr)) { - Symbols.push_back({ - Symbol.getName(StrtabContent).get(), + Symbols.push_back({ Symbol.getName(StrtabContent).get(), Symbol.st_value, Symbol.st_size, - Symbol.getType() == ELF::STT_FUNC - }); + Symbol.getType() == ELF::STT_FUNC }); } } @@ -406,47 +416,44 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, using Elf_Dyn = const typename object::ELFFile::Elf_Dyn; for (Elf_Phdr &ProgramHeader : TheELF.program_headers()) { switch (ProgramHeader.p_type) { - case ELF::PT_LOAD: - { - SegmentInfo Segment; - auto Start = relocate(ProgramHeader.p_vaddr); - Segment.StartVirtualAddress = Start; - Segment.EndVirtualAddress = Start + ProgramHeader.p_memsz; - Segment.IsReadable = ProgramHeader.p_flags & ELF::PF_R; - Segment.IsWriteable = ProgramHeader.p_flags & ELF::PF_W; - Segment.IsExecutable = ProgramHeader.p_flags & ELF::PF_X; + case ELF::PT_LOAD: { + SegmentInfo Segment; + auto Start = relocate(ProgramHeader.p_vaddr); + Segment.StartVirtualAddress = Start; + Segment.EndVirtualAddress = Start + ProgramHeader.p_memsz; + Segment.IsReadable = ProgramHeader.p_flags & ELF::PF_R; + Segment.IsWriteable = ProgramHeader.p_flags & ELF::PF_W; + Segment.IsExecutable = ProgramHeader.p_flags & ELF::PF_X; - auto ActualAddress = TheELF.base() + ProgramHeader.p_offset; - Segment.Data = ArrayRef(ActualAddress, ProgramHeader.p_filesz); + auto ActualAddress = TheELF.base() + ProgramHeader.p_offset; + Segment.Data = ArrayRef(ActualAddress, ProgramHeader.p_filesz); - // If it's an executable segment, and we've been asked so, register - // which sections actually contain code - if (UseSections && Segment.IsExecutable) { - using Elf_Shdr = const typename object::ELFFile::Elf_Shdr; - auto Inserter = std::back_inserter(Segment.ExecutableSections); - for (Elf_Shdr &SectionHeader : TheELF.sections()) { - if (SectionHeader.sh_flags & ELF::SHF_EXECINSTR) { - auto SectionStart = relocate(SectionHeader.sh_addr); - auto SectionEnd = SectionStart + SectionHeader.sh_size; - Inserter = make_pair(SectionStart, SectionEnd); - } + // If it's an executable segment, and we've been asked so, register + // which sections actually contain code + if (UseSections && Segment.IsExecutable) { + using Elf_Shdr = const typename object::ELFFile::Elf_Shdr; + auto Inserter = std::back_inserter(Segment.ExecutableSections); + for (Elf_Shdr &SectionHeader : TheELF.sections()) { + if (SectionHeader.sh_flags & ELF::SHF_EXECINSTR) { + auto SectionStart = relocate(SectionHeader.sh_addr); + auto SectionEnd = SectionStart + SectionHeader.sh_size; + Inserter = make_pair(SectionStart, SectionEnd); } } - - Segments.push_back(Segment); - - // Check if it's the segment containing the program headers - auto ProgramHeaderStart = ProgramHeader.p_offset; - auto ProgramHeaderEnd = ProgramHeader.p_offset + ProgramHeader.p_filesz; - if (ProgramHeaderStart <= ElfHeader->e_phoff - && ElfHeader->e_phoff < ProgramHeaderEnd) { - uint64_t PhdrAddress = (relocate(ProgramHeader.p_vaddr) - + ElfHeader->e_phoff - - ProgramHeader.p_offset); - ProgramHeaders.Address = PhdrAddress; - } } - break; + + Segments.push_back(Segment); + + // Check if it's the segment containing the program headers + auto ProgramHeaderStart = ProgramHeader.p_offset; + auto ProgramHeaderEnd = ProgramHeader.p_offset + ProgramHeader.p_filesz; + if (ProgramHeaderStart <= ElfHeader->e_phoff + && ElfHeader->e_phoff < ProgramHeaderEnd) { + uint64_t PhdrAddress = (relocate(ProgramHeader.p_vaddr) + + ElfHeader->e_phoff - ProgramHeader.p_offset); + ProgramHeaders.Address = PhdrAddress; + } + } break; case ELF::PT_GNU_EH_FRAME: assert(!EHFrameHdrAddress); @@ -461,7 +468,6 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, and ".dynamic and PT_DYNAMIC have different addresses"); break; } - } assert((DynamicPhdr != nullptr) == (DynamicAddress.hasValue())); @@ -493,7 +499,7 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, for (Elf_Dyn &DynamicTag : *TheELF.dynamic_table(DynamicPhdr)) { auto TheTag = DynamicTag.getTag(); - switch(TheTag) { + switch (TheTag) { case ELF::DT_NEEDED: NeededLibraryNameOffsets.push_back(DynamicTag.getVal()); break; @@ -529,7 +535,6 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, assert(TheTag == (HasAddend ? ELF::DT_RELASZ : ELF::DT_RELSZ)); ReldynPortion.setSize(DynamicTag.getVal()); break; - } } @@ -538,7 +543,7 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, if (DynstrPortion.isAvailable()) { StringRef Dynstr = DynstrPortion.extractString(Segments); - for(auto Offset : NeededLibraryNameOffsets) { + for (auto Offset : NeededLibraryNameOffsets) { StringRef LibraryName = Dynstr.slice(Offset, Dynstr.size()); NeededLibraryNames.push_back(LibraryName.data()); } @@ -558,7 +563,6 @@ void BinaryFile::parseELF(object::ObjectFile *TheBinary, if (Symbol.st_value != 0 and Symbol.getType() == ELF::STT_FUNC) CodePointers.insert(relocate(Symbol.st_value)); } - } } @@ -594,7 +598,6 @@ uint64_t BinaryFile::parseRelocations(const FilePortion &Relocations) { return SymbolsCount; } - // // .eh_frame-related functions // @@ -606,7 +609,7 @@ public: Address(Address), Start(Buffer.data()), Cursor(Buffer.data()), - End(Buffer.data() + Buffer.size()) { } + End(Buffer.data() + Buffer.size()) {} template T readNext() { @@ -644,7 +647,7 @@ public: return Result; } - Pointer readPointer(unsigned Encoding, uint64_t Base=0) { + Pointer readPointer(unsigned Encoding, uint64_t Base = 0) { assert((Encoding & ~(0x70 | 0x0F | dwarf::DW_EH_PE_indirect)) == 0); if ((Encoding & 0x70) == dwarf::DW_EH_PE_pcrel) @@ -718,13 +721,24 @@ private: const uint8_t *Start; const uint8_t *Cursor; const uint8_t *End; - }; -template<> bool DwarfReader::is64() const { return false; } -template<> bool DwarfReader::is64() const { return false; } -template<> bool DwarfReader::is64() const { return true; } -template<> bool DwarfReader::is64() const { return true; } +template<> +bool DwarfReader::is64() const { + return false; +} +template<> +bool DwarfReader::is64() const { + return false; +} +template<> +bool DwarfReader::is64() const { + return true; +} +template<> +bool DwarfReader::is64() const { + return true; +} template std::pair @@ -815,8 +829,7 @@ void BinaryFile::parseEHFrame(uint64_t EHFrameAddress, // Parse a null terminated augmentation string SmallString<8> AugmentationString; - for (uint8_t Char = EHFrameReader.readNextU8(); - Char != 0; + for (uint8_t Char = EHFrameReader.readNextU8(); Char != 0; Char = EHFrameReader.readNextU8()) AugmentationString.push_back(Char); @@ -845,46 +858,43 @@ void BinaryFile::parseEHFrame(uint64_t EHFrameAddress, for (unsigned I = 1, e = AugmentationString.size(); I != e; ++I) { char Char = AugmentationString[I]; switch (Char) { - case 'e': - assert((I + 1) != e && AugmentationString[I + 1] == 'h' && - "Expected 'eh' in augmentation string"); - break; - case 'L': - // This is the only information we really care about, all the rest - // is processed just so we can get here - assert(!LSDAPointerEncoding && "Duplicate LSDA encoding"); - LSDAPointerEncoding = EHFrameReader.readNextU8(); - break; - case 'P': { - assert(!PersonalityEncoding && "Duplicate personality"); - PersonalityEncoding = EHFrameReader.readNextU8(); - // Personality - Pointer Personality; - Personality = EHFrameReader.readPointer(*PersonalityEncoding); - uint64_t PersonalityPtr = getPointer(Personality); - DBG("ehframe", { - dbg << "Personality function: " << PersonalityPtr << "\n"; - }); - // TODO: technically this is not a landing pad - LandingPads.insert(PersonalityPtr); - break; - } - case 'R': - assert(!FDEPointerEncoding && "Duplicate FDE encoding"); - FDEPointerEncoding = EHFrameReader.readNextU8(); - break; - case 'z': - llvm_unreachable("'z' must be first in the augmentation string"); + case 'e': + assert((I + 1) != e && AugmentationString[I + 1] == 'h' + && "Expected 'eh' in augmentation string"); + break; + case 'L': + // This is the only information we really care about, all the rest + // is processed just so we can get here + assert(!LSDAPointerEncoding && "Duplicate LSDA encoding"); + LSDAPointerEncoding = EHFrameReader.readNextU8(); + break; + case 'P': { + assert(!PersonalityEncoding && "Duplicate personality"); + PersonalityEncoding = EHFrameReader.readNextU8(); + // Personality + Pointer Personality; + Personality = EHFrameReader.readPointer(*PersonalityEncoding); + uint64_t PersonalityPtr = getPointer(Personality); + DBG("ehframe", + { dbg << "Personality function: " << PersonalityPtr << "\n"; }); + // TODO: technically this is not a landing pad + LandingPads.insert(PersonalityPtr); + break; + } + case 'R': + assert(!FDEPointerEncoding && "Duplicate FDE encoding"); + FDEPointerEncoding = EHFrameReader.readNextU8(); + break; + case 'z': + llvm_unreachable("'z' must be first in the augmentation string"); } } } // Cache this entry - CachedCIEs[StartOffset] = { - FDEPointerEncoding, - LSDAPointerEncoding, - AugmentationLength.hasValue() - }; + CachedCIEs[StartOffset] = { FDEPointerEncoding, + LSDAPointerEncoding, + AugmentationLength.hasValue() }; } else { // This is an FDE @@ -901,8 +911,8 @@ void BinaryFile::parseEHFrame(uint64_t EHFrameAddress, // Ensure we have at least the pointer encoding const DecodedCIE &CIE = CIEIt->getSecond(); - assert(CIE.FDEPointerEncoding && - "FDE references CIE which did not set pointer encoding"); + assert(CIE.FDEPointerEncoding + && "FDE references CIE which did not set pointer encoding"); // PCBegin auto PCBeginPointer = EHFrameReader.readPointer(*CIE.FDEPointerEncoding); @@ -925,7 +935,6 @@ void BinaryFile::parseEHFrame(uint64_t EHFrameAddress, // Skip all the remaining parts EHFrameReader.moveTo(EndOffset); } - } template @@ -975,9 +984,9 @@ void BinaryFile::parseLSDA(uint64_t FDEStart, uint64_t LSDAAddress) { if (LandingPad != 0) { DBG("ehframe", { - if (LandingPads.count(LandingPad) == 0) - dbg << "New landing pad found: " << std::hex << LandingPad << "\n"; - }); + if (LandingPads.count(LandingPad) == 0) + dbg << "New landing pad found: " << std::hex << LandingPad << "\n"; + }); LandingPads.insert(LandingPad); } } diff --git a/binaryfile.h b/binaryfile.h index e5baecac7..7af801e81 100644 --- a/binaryfile.h +++ b/binaryfile.h @@ -12,8 +12,8 @@ // LLVM includes #include "llvm/ADT/Optional.h" -#include "llvm/Object/ELFTypes.h" #include "llvm/Object/Binary.h" +#include "llvm/Object/ELFTypes.h" // Local includes #include "revamb.h" @@ -22,7 +22,7 @@ namespace llvm { namespace object { class ObjectFile; } -} +} // namespace llvm /// \brief Simple data structure to describe an ELF segment // TODO: information hiding @@ -56,14 +56,11 @@ struct SegmentInfo { return; if (ExecutableSections.size() > 0) { - std::copy(ExecutableSections.begin(), - ExecutableSections.end(), - Inserter); + std::copy(ExecutableSections.begin(), ExecutableSections.end(), Inserter); } else { Inserter = std::make_pair(StartVirtualAddress, EndVirtualAddress); } } - }; /// \brief Simple data structure to describe a symbol in an image format @@ -154,11 +151,11 @@ inline uint64_t readPointer(const uint8_t *Buf) { /// \brief A pair on steroids to wrap a value or a pointer to a value class Pointer { public: - Pointer() { } + Pointer() {} Pointer(bool IsIndirect, uint64_t Value) : IsIndirect(IsIndirect), - Value(Value) { } + Value(Value) {} bool isIndirect() const { return IsIndirect; } uint64_t value() const { return Value; } @@ -166,7 +163,6 @@ public: private: bool IsIndirect; uint64_t Value; - }; class FilePortion; @@ -179,9 +175,7 @@ public: /// \param UseSections whether information in sections, if available, should /// be employed or not. This is useful to precisely identify exeutable /// code. - BinaryFile(std::string FilePath, - bool UseSections, - uint64_t BaseAddress); + BinaryFile(std::string FilePath, bool UseSections, uint64_t BaseAddress); llvm::Optional> getAddressData(uint64_t Address) const { @@ -275,9 +269,7 @@ private: template void parseLSDA(uint64_t FDEStart, uint64_t LSDAAddress); - uint64_t relocate(uint64_t Address) const { - return BaseAddress + Address; - } + uint64_t relocate(uint64_t Address) const { return BaseAddress + Address; } /// \brief Collect image base-relative relocation addresses and count symbols /// diff --git a/classsentinel.h b/classsentinel.h index aa0702ad2..82f550014 100644 --- a/classsentinel.h +++ b/classsentinel.h @@ -67,7 +67,7 @@ private: /// sentil was allocated, possibly creating false negatives. class ClassSentinel { public: - ClassSentinel() : Moved(false), Destroyed(false) { } + ClassSentinel() : Moved(false), Destroyed(false) {} ClassSentinel(const ClassSentinel &) = default; ClassSentinel &operator=(const ClassSentinel &) = default; ClassSentinel(ClassSentinel &&Other) : Moved(false), Destroyed(false) { diff --git a/codegenerator.cpp b/codegenerator.cpp index 1e283d06d..1c49ba82e 100644 --- a/codegenerator.cpp +++ b/codegenerator.cpp @@ -8,18 +8,18 @@ // Standard includes #include -#include -#include -#include #include +#include #include #include +#include #include +#include // Boost includes #include -#include #include +#include // LLVM includes #include "llvm/Analysis/LoopInfo.h" @@ -33,8 +33,8 @@ #include "llvm/IRReader/IRReader.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_os_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -55,8 +55,7 @@ using namespace llvm; using std::make_pair; template -inline std::array -make_array(Args&&... args) { +inline std::array make_array(Args &&... args) { return { { std::forward(args)... } }; } @@ -77,7 +76,7 @@ static std::unique_ptr parseIR(StringRef Path, LLVMContext &Context) { } CodeGenerator::CodeGenerator(BinaryFile &Binary, - Architecture& Target, + Architecture &Target, std::string Output, std::string Helpers, std::string EarlyLinked, @@ -101,8 +100,7 @@ CodeGenerator::CodeGenerator(BinaryFile &Binary, DetectFunctionBoundaries(DetectFunctionBoundaries), EnableLinking(EnableLinking), ExternalCSVs(ExternalCSVs), - UseDebugSymbols(UseDebugSymbols) -{ + UseDebugSymbols(UseDebugSymbols) { OriginalInstrMDKind = Context.getMDKindID("oi"); PTCInstrMDKind = Context.getMDKindID("pi"); DbgMDKind = Context.getMDKindID("dbg"); @@ -136,8 +134,8 @@ CodeGenerator::CodeGenerator(BinaryFile &Binary, auto *RegisterType = Type::getIntNTy(Context, Binary.architecture().pointerSize()); - auto createConstGlobal = [this, &RegisterType] (const Twine &Name, - uint64_t Value) { + auto createConstGlobal = [this, &RegisterType](const Twine &Name, + uint64_t Value) { return new GlobalVariable(*TheModule, RegisterType, true, @@ -174,9 +172,7 @@ CodeGenerator::CodeGenerator(BinaryFile &Binary, // If we have extra data at the end we need to create a copy of the // segment and append the NULL bytes auto FullData = make_unique(Segment.size()); - ::memcpy(FullData.get(), - Segment.Data.data(), - Segment.Data.size()); + ::memcpy(FullData.get(), Segment.Data.data(), Segment.Data.size()); ::bzero(FullData.get() + Segment.Data.size(), Segment.size() - Segment.Data.size()); auto DataRef = ArrayRef(FullData.get(), Segment.size()); @@ -196,11 +192,9 @@ CodeGenerator::CodeGenerator(BinaryFile &Binary, Segment.Variable->setSection("." + Name); // Write the linking info CSV - LinkingInfoStream << "." << Name - << ",0x" << std::hex << Segment.StartVirtualAddress - << ",0x" << std::hex << Segment.EndVirtualAddress - << "\n"; - + LinkingInfoStream << "." << Name << ",0x" << std::hex + << Segment.StartVirtualAddress << ",0x" << std::hex + << Segment.EndVirtualAddress << "\n"; } // Write needed libraries CSV @@ -219,11 +213,9 @@ Function *CodeGenerator::importHelperFunctionDefinition(StringRef Name) { std::string SegmentInfo::generateName() { // Create name from start and size std::stringstream NameStream; - NameStream << "o_" - << (IsReadable ? "r" : "") - << (IsWriteable ? "w" : "") - << (IsExecutable ? "x" : "") - << "_0x" << std::hex << StartVirtualAddress; + NameStream << "o_" << (IsReadable ? "r" : "") << (IsWriteable ? "w" : "") + << (IsExecutable ? "x" : "") << "_0x" << std::hex + << StartVirtualAddress; return NameStream.str(); } @@ -261,7 +253,7 @@ class CpuLoopFunctionPass : public llvm::FunctionPass { public: static char ID; - CpuLoopFunctionPass() : llvm::FunctionPass(ID) { } + CpuLoopFunctionPass() : llvm::FunctionPass(ID) {} void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; @@ -271,17 +263,14 @@ public: char CpuLoopFunctionPass::ID = 0; using RegisterCLF = RegisterPass; -static RegisterCLF X("cpu-loop", - "cpu_loop FunctionPass", - false, - false); +static RegisterCLF X("cpu-loop", "cpu_loop FunctionPass", false, false); void CpuLoopFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); } template -auto find_unique(Range&& TheRange, UnaryPredicate Predicate) +auto find_unique(Range &&TheRange, UnaryPredicate Predicate) -> decltype(*TheRange.begin()) { const auto Begin = TheRange.begin(); @@ -296,8 +285,7 @@ auto find_unique(Range&& TheRange, UnaryPredicate Predicate) } template -auto find_unique(Range&& TheRange) - -> decltype(*TheRange.begin()) { +auto find_unique(Range &&TheRange) -> decltype(*TheRange.begin()) { const auto Begin = TheRange.begin(); const auto End = TheRange.end(); @@ -323,7 +311,7 @@ bool CpuLoopFunctionPass::runOnFunction(Function &F) { BasicBlock *Header = OutermostLoop->getHeader(); // Check that the header has only one predecessor inside the loop - auto IsInLoop = [&OutermostLoop] (BasicBlock *Predecessor) { + auto IsInLoop = [&OutermostLoop](BasicBlock *Predecessor) { return OutermostLoop->contains(Predecessor); }; BasicBlock *Footer = find_unique(predecessors(Header), IsInLoop); @@ -338,20 +326,20 @@ bool CpuLoopFunctionPass::runOnFunction(Function &F) { ReturnInst::Create(F.getParent()->getContext(), Footer); // Part 2: replace the call to cpu_*_exec with exception_index - auto IsCpuExec = [] (Function& TheFunction) { + auto IsCpuExec = [](Function &TheFunction) { StringRef Name = TheFunction.getName(); return Name.startswith("cpu_") && Name.endswith("_exec"); }; - Function& CpuExec = find_unique(F.getParent()->functions(), IsCpuExec); + Function &CpuExec = find_unique(F.getParent()->functions(), IsCpuExec); - User *CallUser = find_unique(CpuExec.users(), [&F] (User *TheUser) { - auto *TheInstruction = dyn_cast(TheUser); + User *CallUser = find_unique(CpuExec.users(), [&F](User *TheUser) { + auto *TheInstruction = dyn_cast(TheUser); - if (TheInstruction == nullptr) - return false; + if (TheInstruction == nullptr) + return false; - return TheInstruction->getParent()->getParent() == &F; - }); + return TheInstruction->getParent()->getParent() == &F; + }); auto *Call = cast(CallUser); assert(Call->getCalledFunction() == &CpuExec); @@ -368,12 +356,11 @@ class CpuLoopExitPass : public llvm::ModulePass { public: static char ID; - CpuLoopExitPass() : llvm::ModulePass(ID), VM(0) { } - CpuLoopExitPass(VariableManager *VM) : - llvm::ModulePass(ID), - VM(VM) { } + CpuLoopExitPass() : llvm::ModulePass(ID), VM(0) {} + CpuLoopExitPass(VariableManager *VM) : llvm::ModulePass(ID), VM(VM) {} + + bool runOnModule(llvm::Module &M) override; - bool runOnModule(llvm::Module& M) override; private: VariableManager *VM; }; @@ -381,10 +368,7 @@ private: char CpuLoopExitPass::ID = 0; using RegisterCLE = RegisterPass; -static RegisterCLE Y("cpu-loop-exit", - "cpu_loop_exit Pass", - false, - false); +static RegisterCLE Y("cpu-loop-exit", "cpu_loop_exit Pass", false, false); static void purgeNoReturn(Function *F) { auto &Context = F->getParent()->getContext(); @@ -411,7 +395,7 @@ static ReturnInst *createRet(Instruction *Position) { if (ReturnType->isVoidTy()) { return ReturnInst::Create(F->getParent()->getContext(), nullptr, Position); } else if (ReturnType->isIntegerTy()) { - auto *Zero = ConstantInt::get(static_cast(ReturnType), 0); + auto *Zero = ConstantInt::get(static_cast(ReturnType), 0); return ReturnInst::Create(F->getParent()->getContext(), Zero, Position); } else { assert("Return type not supported"); @@ -431,7 +415,7 @@ static ReturnInst *createRet(Instruction *Position) { /// or not. /// Then when we reach the root function, set cpu_loop_exiting to false after /// the call. -bool CpuLoopExitPass::runOnModule(llvm::Module& M) { +bool CpuLoopExitPass::runOnModule(llvm::Module &M) { Function *CpuLoopExit = M.getFunction("cpu_loop_exit"); // Nothing to do here @@ -538,7 +522,7 @@ bool CpuLoopExitPass::runOnModule(llvm::Module& M) { Branch), ConstantInt::getTrue(BoolType)); - BranchInst::Create(QuitBB, NewBB, Compare, Branch); + BranchInst::Create(QuitBB, NewBB, Compare, Branch); Branch->eraseFromParent(); // Add to the work list only if it hasn't been fixed already @@ -570,7 +554,6 @@ static void purgeDeadBlocks(Function *F) { Kill.push_back(&BB); } while (!Kill.empty()); - } void CodeGenerator::translate(uint64_t VirtualAddress) { @@ -582,7 +565,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { importHelperFunctionDefinition("target_set_brk"); TheModule->getOrInsertFunction("syscall_init", - FT::get(Type::getVoidTy(Context), { }, false)); + FT::get(Type::getVoidTy(Context), {}, false)); // Instantiate helpers VariableManager Variables(*TheModule, *HelpersModule, TargetArchitecture); @@ -594,9 +577,9 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { IRBuilder<> Builder(Context); // Create main function - auto *MainType = FT::get(Builder.getVoidTy(), - { SPReg->getType()->getPointerElementType() }, - false); + auto *MainType = FT::get(Builder.getVoidTy(), + { SPReg->getType()->getPointerElementType() }, + false); auto *MainFunction = Function::Create(MainType, Function::ExternalLinkage, "root", @@ -623,17 +606,18 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { // } const SmallVector &ABIRegisters = Arch.abiRegisters(); - SmallVector ABIRegMetadata; + SmallVector ABIRegMetadata; for (auto Register : ABIRegisters) ABIRegMetadata.push_back(MDString::get(Context, Register.name())); - auto *Tuple = MDTuple::get(Context, { - QMD.get(Arch.instructionAlignment()), - QMD.get(Arch.delaySlotSize()), - QMD.get("pc"), - QMD.get(Arch.stackPointerRegister()), - QMD.tuple(ArrayRef(ABIRegMetadata)), - }); + auto *Tuple = MDTuple::get(Context, + { + QMD.get(Arch.instructionAlignment()), + QMD.get(Arch.delaySlotSize()), + QMD.get("pc"), + QMD.get(Arch.stackPointerRegister()), + QMD.tuple(ArrayRef(ABIRegMetadata)), + }); InputArchMD->addOperand(Tuple); // Create an instance of JumpTargetManager @@ -696,7 +680,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { Variables.newFunction(Delimiter, InstructionList.get()); unsigned j = 0; - MDNode* MDOriginalInstr = nullptr; + MDNode *MDOriginalInstr = nullptr; bool StopTranslation = false; uint64_t PC = VirtualAddress; uint64_t NextPC = 0; @@ -740,48 +724,46 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { Blocks.clear(); Blocks.push_back(Builder.GetInsertBlock()); - switch(Opcode) { + switch (Opcode) { case PTC_INSTRUCTION_op_discard: // Instructions we don't even consider break; - case PTC_INSTRUCTION_op_debug_insn_start: - { - // Find next instruction, if there is one - PTCInstruction *NextInstruction = nullptr; - for (unsigned k = j + 1; k < InstructionCount; k++) { - PTCInstruction *I = &InstructionList->instructions[k]; - if (I->opc == PTC_INSTRUCTION_op_debug_insn_start - && ToIgnore.count(k) == 0) { - NextInstruction = I; - break; - } + case PTC_INSTRUCTION_op_debug_insn_start: { + // Find next instruction, if there is one + PTCInstruction *NextInstruction = nullptr; + for (unsigned k = j + 1; k < InstructionCount; k++) { + PTCInstruction *I = &InstructionList->instructions[k]; + if (I->opc == PTC_INSTRUCTION_op_debug_insn_start + && ToIgnore.count(k) == 0) { + NextInstruction = I; + break; } + } - std::tie(Result, - MDOriginalInstr, - PC, - NextPC) = Translator.newInstruction(&Instruction, - NextInstruction, - EndPC, - false, - ForceNewBlock); + std::tie(Result, + MDOriginalInstr, + PC, + NextPC) = Translator.newInstruction(&Instruction, + NextInstruction, + EndPC, + false, + ForceNewBlock); - ForceNewBlock = false; - } break; - case PTC_INSTRUCTION_op_call: - { - Result = Translator.translateCall(&Instruction); + ForceNewBlock = false; + } break; + case PTC_INSTRUCTION_op_call: { + Result = Translator.translateCall(&Instruction); - // Sometimes libtinycode terminates a basic block with a call, in this - // case force a fallthrough - auto &IL = InstructionList; - if (j == IL->instruction_count - 1) { - BasicBlock *Target = JumpTargets.registerJT(EndPC, - JTReason::PostHelper); - Builder.CreateBr(notNull(Target)); - } + // Sometimes libtinycode terminates a basic block with a call, in this + // case force a fallthrough + auto &IL = InstructionList; + if (j == IL->instruction_count - 1) { + BasicBlock *Target = JumpTargets.registerJT(EndPC, + JTReason::PostHelper); + Builder.CreateBr(notNull(Target)); + } - } break; + } break; default: Result = Translator.translate(&Instruction, PC, NextPC); @@ -811,7 +793,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { dumpInstruction(PTCStringStream, InstructionList.get(), j); std::string PTCString = PTCStringStream.str() + "\n"; MDString *MDPTCString = MDString::get(Context, PTCString); - MDNode* MDPTCInstr = MDNode::getDistinct(Context, MDPTCString); + MDNode *MDPTCInstr = MDNode::getDistinct(Context, MDPTCString); // Set metadata for all the new instructions for (BasicBlock *Block : Blocks) { @@ -910,7 +892,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { if (TheFunction != nullptr) { assert(HelpersModule->getFunction("abort") != nullptr); BasicBlock *NewBody = replaceFunction(TheFunction); - CallInst::Create(HelpersModule->getFunction("abort"), { }, NewBody); + CallInst::Create(HelpersModule->getFunction("abort"), {}, NewBody); new UnreachableInst(Context, NewBody); } } @@ -924,21 +906,21 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { // non-static symbols not directly imported as static. { std::set Declarations; - for (auto& GV : TheModule->functions()) + for (auto &GV : TheModule->functions()) if (GV.isDeclaration()) Declarations.insert(GV.getName()); - for (auto& GV : TheModule->globals()) + for (auto &GV : TheModule->globals()) if (GV.isDeclaration()) Declarations.insert(GV.getName()); - for (auto& GV : HelpersModule->functions()) + for (auto &GV : HelpersModule->functions()) if (!GV.isDeclaration() && Declarations.find(GV.getName()) == Declarations.end() && GV.hasExternalLinkage()) GV.setLinkage(GlobalValue::InternalLinkage); - for (auto& GV : HelpersModule->globals()) + for (auto &GV : HelpersModule->globals()) if (!GV.isDeclaration() && Declarations.find(GV.getName()) == Declarations.end() && GV.hasExternalLinkage()) @@ -993,7 +975,6 @@ void CodeGenerator::translate(uint64_t VirtualAddress) { Variables.finalize(ExternalCSVs); Debug->generateDebugInfo(); - } void CodeGenerator::serialize() { diff --git a/codegenerator.h b/codegenerator.h index 164fac26b..d65517636 100644 --- a/codegenerator.h +++ b/codegenerator.h @@ -7,8 +7,8 @@ // Standard includes #include -#include #include +#include // LLVM includes #include "llvm/ADT/ArrayRef.h" @@ -32,7 +32,7 @@ namespace object { class ObjectFile; }; -}; +}; // namespace llvm class DebugHelper; @@ -114,7 +114,7 @@ private: private: Architecture TargetArchitecture; - llvm::LLVMContext& Context; + llvm::LLVMContext &Context; std::unique_ptr TheModule; std::unique_ptr HelpersModule; std::unique_ptr EarlyLinkedModule; diff --git a/collectcfg.cpp b/collectcfg.cpp index f43a92816..62ca48e6d 100644 --- a/collectcfg.cpp +++ b/collectcfg.cpp @@ -10,8 +10,8 @@ #include "llvm/IR/Instructions.h" // Local includes -#include "datastructures.h" #include "collectcfg.h" +#include "datastructures.h" #include "ir-helpers.h" using namespace llvm; @@ -25,8 +25,8 @@ void CollectCFG::serialize(std::ostream &Output) { BasicBlock *Source = P.first; std::sort(P.second.begin(), P.second.end(), CompareByName()); for (BasicBlock *Destination : P.second) - Output << Source->getName().data() << "," - << Destination->getName().data() << "\n"; + Output << Source->getName().data() << "," << Destination->getName().data() + << "\n"; } } @@ -35,8 +35,7 @@ bool CollectCFG::isNewInstruction(BasicBlock *BB) { return false; auto *Call = dyn_cast(&*BB->begin()); - if (Call == nullptr - || Call->getCalledFunction() == nullptr + if (Call == nullptr || Call->getCalledFunction() == nullptr || Call->getCalledFunction()->getName() != "newpc") return false; @@ -71,7 +70,6 @@ bool CollectCFG::runOnFunction(Function &F) { } else if (BlackList.count(Successor) == 0) { Queue.insert(Successor); } - } } } diff --git a/collectcfg.h b/collectcfg.h index 0a34a3231..cd7341efb 100644 --- a/collectcfg.h +++ b/collectcfg.h @@ -11,9 +11,9 @@ #include // LLVM includes -#include "llvm/Pass.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Pass.h" template struct CompareByName { @@ -27,7 +27,7 @@ public: static char ID; public: - CollectCFG() : llvm::FunctionPass(ID) { } + CollectCFG() : llvm::FunctionPass(ID) {} bool runOnFunction(llvm::Function &F) override; @@ -49,7 +49,6 @@ private: using Comparer = CompareByName; std::map, Comparer> Result; std::set BlackList; - }; #endif // _COLLECTCFG_H diff --git a/collectfunctionboundaries.h b/collectfunctionboundaries.h index f47569cd6..29c55465a 100644 --- a/collectfunctionboundaries.h +++ b/collectfunctionboundaries.h @@ -11,8 +11,8 @@ #include // LLVM includes -#include "llvm/Pass.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Pass.h" namespace llvm { class BasicBlock; @@ -23,7 +23,7 @@ public: static char ID; public: - CollectFunctionBoundaries() : llvm::FunctionPass(ID) { } + CollectFunctionBoundaries() : llvm::FunctionPass(ID) {} bool runOnFunction(llvm::Function &F) override; diff --git a/collectnoreturn.cpp b/collectnoreturn.cpp index c506b4845..f6b4b9e2a 100644 --- a/collectnoreturn.cpp +++ b/collectnoreturn.cpp @@ -25,10 +25,7 @@ struct CompareByName { char CollectNoreturn::ID = 0; using RegisterCNR = RegisterPass; -static RegisterCNR X("cnoreturn", - "Collect noreturn Pass", - true, - true); +static RegisterCNR X("cnoreturn", "Collect noreturn Pass", true, true); void CollectNoreturn::serialize(std::ostream &Output) { Output << "noreturn\n"; diff --git a/collectnoreturn.h b/collectnoreturn.h index 581616142..75a45f3fb 100644 --- a/collectnoreturn.h +++ b/collectnoreturn.h @@ -21,7 +21,7 @@ public: static char ID; public: - CollectNoreturn() : llvm::FunctionPass(ID) { } + CollectNoreturn() : llvm::FunctionPass(ID) {} bool runOnFunction(llvm::Function &F) override; diff --git a/cpustateaccessanalysis.cpp b/cpustateaccessanalysis.cpp index b7e9536e6..82e15f85f 100644 --- a/cpustateaccessanalysis.cpp +++ b/cpustateaccessanalysis.cpp @@ -1714,7 +1714,7 @@ void CPUSAOA::computeOffsetsFromSources(const WorkItem &Item, bool IsLoad) { raw_string_ostream OStream(InstrLog); Instr->print(OStream); CSVAccessLog << InstrLog << DoLog; - for (const auto & CS2O : LoadCSOff.second) { + for (const auto &CS2O : LoadCSOff.second) { CSVAccessLog << "CallSite: "; std::string CallLog; raw_string_ostream CallOStream(CallLog); @@ -1739,7 +1739,7 @@ void CPUSAOA::computeOffsetsFromSources(const WorkItem &Item, bool IsLoad) { raw_string_ostream OStream(InstrLog); Instr->print(OStream); CSVAccessLog << InstrLog << DoLog; - for (const auto & CS2O : StoreCSOff.second) { + for (const auto &CS2O : StoreCSOff.second) { CSVAccessLog << "CallSite: "; std::string CallLog; raw_string_ostream CallOStream(CallLog); @@ -2922,7 +2922,7 @@ bool CPUStateAccessAnalysis::run() { for (const auto &Fun2Unknowns : FunToUnknowns) for (const auto &U : Fun2Unknowns.second) - FixAccessLog << Fun2Unknowns.first << ": " << U << DoLog; + FixAccessLog << Fun2Unknowns.first << ": " << U << DoLog; } return Found; diff --git a/datastructures.h b/datastructures.h index e44ff2471..8f2d82bb0 100644 --- a/datastructures.h +++ b/datastructures.h @@ -24,13 +24,9 @@ public: } } - bool empty() const { - return Queue.empty(); - } + bool empty() const { return Queue.empty(); } - T head() const { - return Queue.front(); - } + T head() const { return Queue.front(); } T pop() { T Result = head(); @@ -76,9 +72,7 @@ public: } } - bool empty() const { - return Queue.empty(); - } + bool empty() const { return Queue.empty(); } T pop() { T Result = Queue.back(); @@ -88,9 +82,7 @@ public: } /// \brief Reverses the stack in its current status - void reverse() { - std::reverse(Queue.begin(), Queue.end()); - } + void reverse() { std::reverse(Queue.begin(), Queue.end()); } size_t size() const { return Queue.size(); } diff --git a/debug.cpp b/debug.cpp index 24b794606..4b88d1bd2 100644 --- a/debug.cpp +++ b/debug.cpp @@ -40,9 +40,7 @@ void enableDebugFeature(std::string Name) { } void disableDebugFeature(std::string Name) { - auto It = std::find(DebugFeatures.begin(), - DebugFeatures.end(), - Name); + auto It = std::find(DebugFeatures.begin(), DebugFeatures.end(), Name); if (It != DebugFeatures.end()) DebugFeatures.erase(It); diff --git a/debug.h b/debug.h index aa16be33b..bd02cc976 100644 --- a/debug.h +++ b/debug.h @@ -8,8 +8,8 @@ // Standard includes #include #include -#include #include +#include #include // LLVM includes @@ -24,7 +24,7 @@ extern bool DebuggingEnabled; extern std::ostream &dbg; -#define debug_function __attribute__((used,noinline)) +#define debug_function __attribute__((used, noinline)) bool isDebugFeatureEnabled(std::string Name); void enableDebugFeature(std::string Name); @@ -34,10 +34,11 @@ void disableDebugFeature(std::string Name); /// /// \note This approach is deprecated, please consider using Logger and letting /// the DCE do its job for you. -#define DBG(feature, code) do { \ - if (DebuggingEnabled && isDebugFeatureEnabled(feature)) { \ - code; \ - } \ +#define DBG(feature, code) \ + do { \ + if (DebuggingEnabled && isDebugFeatureEnabled(feature)) { \ + code; \ + } \ } while (0) /// \brief Enables a debug feature and disables it when goes out of scope @@ -45,8 +46,9 @@ class ScopedDebugFeature { public: /// \param Name the name of the debugging feature /// \param Enable whether to actually enable it or not - ScopedDebugFeature(std::string Name, bool Enable) - : Name(Name), Enabled(Enable) { + ScopedDebugFeature(std::string Name, bool Enable) : + Name(Name), + Enabled(Enable) { if (Enabled) enableDebugFeature(Name); } @@ -62,7 +64,7 @@ private: }; /// \brief Stream an instance of this class to call Logger::emit() -struct LogTerminator { }; +struct LogTerminator {}; extern LogTerminator DoLog; /// \brief Logger that self-registers itself, can be disable, has a name and @@ -70,19 +72,20 @@ extern LogTerminator DoLog; /// /// The typical usage of this class is to be a static global variable in a /// translation unit. -template +template class Logger { private: static unsigned IndentLevel; + public: Logger(llvm::StringRef Name) : Name(Name), Enabled(false) { init(); } - void indent(unsigned Level=1) { + void indent(unsigned Level = 1) { if (isEnabled()) IndentLevel += Level; } - void unindent(unsigned Level=1) { + void unindent(unsigned Level = 1) { if (isEnabled()) { assert(IndentLevel - Level >= 0); IndentLevel -= Level; @@ -129,7 +132,7 @@ private: }; /// \brief Indent all loggers within the scope of this object -template +template class LoggerIndent { public: LoggerIndent(Logger &L) : L(L) { L.indent(); } @@ -144,10 +147,10 @@ private: /// You can create an instance of this object associated to a Logger, so that /// when the object goes out of scope (typically, on return), the emit method /// will be invoked. -template +template class LogOnReturn { public: - LogOnReturn(Logger &L) : L(L) { } + LogOnReturn(Logger &L) : L(L) {} ~LogOnReturn() { L.emit(); } private: @@ -193,7 +196,7 @@ inline void writeToLog(Logger &This, const LogTerminator T, int Ignore) { /// of this class is collecting them. class LoggersRegistry { public: - LoggersRegistry() { } + LoggersRegistry() {} void add(Logger *L) { Loggers.push_back(L); } void add(Logger *L) { (void) L; } diff --git a/debughelper.cpp b/debughelper.cpp index 66b231711..8c3ef5e88 100644 --- a/debughelper.cpp +++ b/debughelper.cpp @@ -35,7 +35,7 @@ static MDString *getMD(const Instruction *Instruction, unsigned Kind) { assert(Node != nullptr); - const MDOperand& Operand = Node->getOperand(0); + const MDOperand &Operand = Node->getOperand(0); Metadata *MDOperand = Operand.get(); @@ -70,7 +70,6 @@ static void writeMetadataIfNew(const Instruction *TheInstruction, if (TheInstruction == nullptr || PrevMD != MD) Output << Prefix << MD->getString(); - } } @@ -86,8 +85,7 @@ using DAW = DebugAnnotationWriter; DAW::DebugAnnotationWriter(LLVMContext &Context, bool DebugInfo) : Context(Context), - DebugInfo(DebugInfo) -{ + DebugInfo(DebugInfo) { OriginalInstrMDKind = Context.getMDKindID("oi"); PTCInstrMDKind = Context.getMDKindID("pi"); DbgMDKind = Context.getMDKindID("dbg"); @@ -132,8 +130,7 @@ DebugHelper::DebugHelper(std::string Output, DebugPath(Debug), Builder(*TheModule), Type(Type), - TheModule(TheModule) -{ + TheModule(TheModule) { OriginalInstrMDKind = TheModule->getContext().getMDKindID("oi"); PTCInstrMDKind = TheModule->getContext().getMDKindID("pi"); DbgMDKind = TheModule->getContext().getMDKindID("dbg"); @@ -193,66 +190,63 @@ void DebugHelper::generateDebugInfo() { switch (Type) { case DebugInfoType::PTC: - case DebugInfoType::OriginalAssembly: - { - // Generate the source file and the debugging information in tandem + case DebugInfoType::OriginalAssembly: { + // Generate the source file and the debugging information in tandem - unsigned LineIndex = 1; - unsigned MetadataKind = Type == DebugInfoType::PTC ? - PTCInstrMDKind : OriginalInstrMDKind; + unsigned LineIndex = 1; + unsigned MetadataKind = Type == DebugInfoType::PTC ? PTCInstrMDKind : + OriginalInstrMDKind; - MDString *Last = nullptr; - std::ofstream Source(DebugPath); - for (Function &CurrentFunction : TheModule->functions()) { - if (DISubprogram *CurrentSubprogram = CurrentFunction.getSubprogram()) { - for (BasicBlock& Block : CurrentFunction) { - for (Instruction& Instruction : Block) { - MDString *Body = getMD(&Instruction, MetadataKind); + MDString *Last = nullptr; + std::ofstream Source(DebugPath); + for (Function &CurrentFunction : TheModule->functions()) { + if (DISubprogram *CurrentSubprogram = CurrentFunction.getSubprogram()) { + for (BasicBlock &Block : CurrentFunction) { + for (Instruction &Instruction : Block) { + MDString *Body = getMD(&Instruction, MetadataKind); - if (Body != nullptr && Last != Body) { - Last = Body; - std::string BodyString = Body->getString().str(); + if (Body != nullptr && Last != Body) { + Last = Body; + std::string BodyString = Body->getString().str(); - Source << BodyString; + Source << BodyString; - auto *Location = DILocation::get(TheModule->getContext(), - LineIndex, - 0, - CurrentSubprogram); - Instruction.setMetadata(DbgMDKind, Location); - LineIndex += std::count(BodyString.begin(), - BodyString.end(), - '\n'); - } + auto *Location = DILocation::get(TheModule->getContext(), + LineIndex, + 0, + CurrentSubprogram); + Instruction.setMetadata(DbgMDKind, Location); + LineIndex += std::count(BodyString.begin(), + BodyString.end(), + '\n'); } } } } + } - Builder.finalize(); - } break; - case DebugInfoType::LLVMIR: - { - // Use the annotator to obtain line and column of the textual LLVM IR for - // each instruction. Discard the output since it will contain errors, - // regenerating it later will give a correct result. - Builder.finalize(); + Builder.finalize(); + } break; + case DebugInfoType::LLVMIR: { + // Use the annotator to obtain line and column of the textual LLVM IR for + // each instruction. Discard the output since it will contain errors, + // regenerating it later will give a correct result. + Builder.finalize(); - raw_null_ostream NullStream; - TheModule->print(NullStream, annotator(true /* DebugInfo */)); + raw_null_ostream NullStream; + TheModule->print(NullStream, annotator(true /* DebugInfo */)); - std::ofstream Output(DebugPath); - raw_os_ostream Stream(Output); - TheModule->print(Stream, annotator(false)); + std::ofstream Output(DebugPath); + raw_os_ostream Stream(Output); + TheModule->print(Stream, annotator(false)); - } break; + } break; default: break; } - } -void DebugHelper::print(std::ostream& Output, bool DebugInfo) { +void DebugHelper::print(std::ostream &Output, bool DebugInfo) { raw_os_ostream OutputStream(Output); TheModule->print(OutputStream, annotator(DebugInfo)); } diff --git a/debughelper.h b/debughelper.h index 36edfe920..26f4bffff 100644 --- a/debughelper.h +++ b/debughelper.h @@ -22,7 +22,7 @@ class Module; class DICompileUnit; class DISubprogram; class Function; -} +} // namespace llvm /// \brief AssemblyAnnotationWriter decorating the output withe debug /// information @@ -45,8 +45,7 @@ public: /// \param Scope the scope, typically a `DISubprogram`. /// \param DebugInfo whether to decorate the IR being serialized with debug /// metadata refering to the produce IR itself or not. - DebugAnnotationWriter(llvm::LLVMContext& Context, - bool DebugInfo); + DebugAnnotationWriter(llvm::LLVMContext &Context, bool DebugInfo); virtual void emitInstructionAnnot(const llvm::Instruction *TheInstruction, llvm::formatted_raw_ostream &Output); @@ -82,7 +81,7 @@ public: void generateDebugInfo(); /// Serializes to the given stream the module, with or without debug info - void print(std::ostream& Output, bool DebugInfo); + void print(std::ostream &Output, bool DebugInfo); /// Copy the debug file to the output path, if they are the same bool copySource(); diff --git a/dump.cpp b/dump.cpp index f107b472f..ee8cdcabe 100644 --- a/dump.cpp +++ b/dump.cpp @@ -10,8 +10,8 @@ // LLVM includes #include "llvm/ADT/StringRef.h" #include "llvm/IR/AssemblyAnnotationWriter.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/SourceMgr.h" @@ -24,9 +24,9 @@ #include "debug.h" #include "debughelper.h" #include "isolatefunctions.h" +#include "revng/StackAnalysis/stackanalysis.h" #include "statistics.h" #include "valgrindhelpers.h" -#include "revng/StackAnalysis/stackanalysis.h" using namespace llvm; @@ -51,40 +51,46 @@ static bool parseArgs(int Argc, const char *Argv[], ProgramParameters &Result) { struct argparse Arguments; struct argparse_option Options[] = { OPT_HELP(), - OPT_STRING('d', "debug", - &DebugLoggingString, - "enable verbose logging."), - OPT_STRING('c', "cfg", + OPT_STRING('d', "debug", &DebugLoggingString, "enable verbose logging."), + OPT_STRING('c', + "cfg", &Result.CFGPath, "path where the CFG should be stored."), - OPT_STRING('n', "noreturn", + OPT_STRING('n', + "noreturn", &Result.NoreturnPath, "path where the list of noreturn basic blocks should be " "stored."), - OPT_STRING('f', "functions-boundaries", + OPT_STRING('f', + "functions-boundaries", &Result.FunctionBoundariesPath, "path where the list of function boundaries blocks should be " "stored."), - OPT_STRING('s', "stack-analysis", + OPT_STRING('s', + "stack-analysis", &Result.StackAnalysisPath, "path where the result of the stack analysis should be stored."), - OPT_BOOLEAN('T', "stats", + OPT_BOOLEAN('T', + "stats", &Result.PrintStats, "print statistics upon exit or SIGINT."), - OPT_STRING('i', "functions-isolation", + OPT_STRING('i', + "functions-isolation", &Result.FunctionIsolationPath, "path where a new LLVM module containing the reorganization of " "the basic blocks into the corresponding functions identified " "by function boundaries analysis performed by revamb should be " "stored."), - OPT_BOOLEAN('T', "stats", + OPT_BOOLEAN('T', + "stats", &Result.PrintStats, "print statistics upon exit or SIGINT."), OPT_END(), }; argparse_init(&Arguments, Options, Usage, 0); - argparse_describe(&Arguments, "\nrevamb-dump.", + argparse_describe(&Arguments, + "\nrevamb-dump.", "\nDump several high-level information from the " "revamb-generated LLVM IR.\n"); Argc = argparse_parse(&Arguments, Argc, Argv); @@ -117,8 +123,9 @@ public: static char ID; public: - DumpPass(ProgramParameters &Parameters) : FunctionPass(ID), - Parameters(Parameters) { } + DumpPass(ProgramParameters &Parameters) : + FunctionPass(ID), + Parameters(Parameters) {} bool runOnFunction(Function &F) override; @@ -139,7 +146,6 @@ public: if (Parameters.FunctionIsolationPath != nullptr) AU.addRequired(); - } private: @@ -191,8 +197,7 @@ bool DumpPass::runOnFunction(Function &F) { if (Parameters.FunctionBoundariesPath != nullptr) { auto &Analysis = getAnalysis(); - Analysis.serialize(pathToStream(Parameters.FunctionBoundariesPath, - Output)); + Analysis.serialize(pathToStream(Parameters.FunctionBoundariesPath, Output)); } if (Parameters.StackAnalysisPath != nullptr) { @@ -209,9 +214,8 @@ bool DumpPass::runOnFunction(Function &F) { return false; } - int main(int argc, const char *argv[]) { - ProgramParameters Parameters = { }; + ProgramParameters Parameters = {}; if (!parseArgs(argc, argv, Parameters)) return EXIT_FAILURE; diff --git a/early-linked.c b/early-linked.c index 33b7717cd..008f01744 100644 --- a/early-linked.c +++ b/early-linked.c @@ -11,8 +11,6 @@ // The only purpose of this function is keeping alive the references to some // symbols that are needed by revamb intptr_t ignore(void) { - return (intptr_t) &saved_registers - + (intptr_t) &setjmp - + (intptr_t) &jmp_buffer - + (intptr_t) &is_executable; + return (intptr_t) &saved_registers + (intptr_t) &setjmp + + (intptr_t) &jmp_buffer + (intptr_t) &is_executable; } diff --git a/externaljumpshandler.cpp b/externaljumpshandler.cpp index e19219ef5..fa0b64213 100644 --- a/externaljumpshandler.cpp +++ b/externaljumpshandler.cpp @@ -27,9 +27,8 @@ using namespace llvm; using std::string; -static string &replace(string &Target, - const StringRef Search, - const StringRef Replace) { +static string & +replace(string &Target, const StringRef Search, const StringRef Replace) { size_t Position = Target.find(Search.data()); assert(Position != string::npos); Target.replace(Position, Search.size(), Replace); @@ -80,9 +79,7 @@ BasicBlock *ExternalJumpsHandler::createReturnFromExternal() { true, InlineAsm::AsmDialect::AD_ATT); Builder.CreateCall(Asm, CSV); - } - } } @@ -101,7 +98,8 @@ ExternalJumpsHandler::ExternalJumpsHandler(BinaryFile &TheBinary, Arch(TheBinary.architecture()), JumpTargets(JumpTargets), RegisterType(JumpTargets.pcReg()->getType()->getPointerElementType()), - VoidFunctionType(FunctionType::get(Type::getVoidTy(Context), false)) { } + VoidFunctionType(FunctionType::get(Type::getVoidTy(Context), false)) { +} BasicBlock *ExternalJumpsHandler::createSerializeAndJumpOut() { // Create the serialize and branch Basic Block @@ -169,7 +167,7 @@ llvm::BasicBlock *ExternalJumpsHandler::createSetjmp(BasicBlock *FirstReturn, void ExternalJumpsHandler::buildExecutableSegmentsList() { SmallVector ExecutableSegments; - auto Int = [this] (uint64_t V) { return ConstantInt::get(RegisterType, V); }; + auto Int = [this](uint64_t V) { return ConstantInt::get(RegisterType, V); }; for (auto &Segment : TheBinary.segments()) { if (Segment.IsExecutable) { ExecutableSegments.push_back(Int(Segment.StartVirtualAddress)); diff --git a/externaljumpshandler.h b/externaljumpshandler.h index d3bb208bf..7e9d09a7e 100644 --- a/externaljumpshandler.h +++ b/externaljumpshandler.h @@ -9,9 +9,9 @@ #include // LLVM includes -#include "llvm/Pass.h" -#include "llvm/IR/Instruction.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Pass.h" // Local includes #include "binaryfile.h" @@ -49,8 +49,8 @@ private: public: /// \param TheFunction the root function. ExternalJumpsHandler(BinaryFile &TheBinary, - JumpTargetManager &JumpTargets, - llvm::Function &TheFunction); + JumpTargetManager &JumpTargets, + llvm::Function &TheFunction); public: /// \brief Creates the jump out and jump back in handling infrastructure. @@ -70,8 +70,8 @@ private: /// pointer in particular) and then go to serialize_and_jump_out. /// The second return of setjmp instead will deserialize the CPU state and go /// back to the dispatcher. - llvm::BasicBlock *createSetjmp(llvm::BasicBlock *FirstReturn, - llvm::BasicBlock *SecondReturn); + llvm::BasicBlock * + createSetjmp(llvm::BasicBlock *FirstReturn, llvm::BasicBlock *SecondReturn); /// \brief Extends the dispatcher to handle jumps to basic blocks not handled /// by us. diff --git a/functionboundariesdetection.cpp b/functionboundariesdetection.cpp index 4f9cb68f0..5f2b304c2 100644 --- a/functionboundariesdetection.cpp +++ b/functionboundariesdetection.cpp @@ -15,20 +15,20 @@ // Boost includes #include -#include #include +#include // LLVM includes -#include "llvm/ADT/iterator_range.h" -#include "llvm/ADT/ilist.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" // Local includes -#include "debug.h" #include "datastructures.h" +#include "debug.h" #include "functionboundariesdetection.h" #include "ir-helpers.h" #include "jumptargetmanager.h" @@ -47,10 +47,7 @@ using interval = boost::icl::interval; char FBDP::ID = 0; using RegisterFBDP = RegisterPass; -static RegisterFBDP X("fbdp", - "Function Boundaries Detection Pass", - true, - true); +static RegisterFBDP X("fbdp", "Function Boundaries Detection Pass", true, true); class FunctionBoundariesDetectionImpl { public: @@ -59,7 +56,7 @@ public: bool UseDebugSymbols) : F(F), JTM(JTM), - UseDebugSymbols(UseDebugSymbols) { } + UseDebugSymbols(UseDebugSymbols) {} map> run(); @@ -83,7 +80,7 @@ private: class CFEPRelation { public: - CFEPRelation(BasicBlock *CFEP) : CFEP(CFEP), Distance(0), Type(0) { } + CFEPRelation(BasicBlock *CFEP) : CFEP(CFEP), Distance(0), Type(0) {} void setType(RelationType T) { Type |= T; } bool hasType(RelationType T) const { return Type & T; } @@ -104,7 +101,7 @@ private: class CFEP { public: - CFEP() : Reasons(0) { } + CFEP() : Reasons(0) {} void setReason(CFEPReason Reason) { Reasons |= Reason; } bool hasReason(CFEPReason Reason) { return Reasons & Reason; } @@ -158,7 +155,7 @@ private: SmallVector &BBRelations = Relations[Affected]; auto It = std::find_if(BBRelations.begin(), BBRelations.end(), - [CFEP] (CFEPRelation &R) { + [CFEP](CFEPRelation &R) { return R.cfep() == CFEP; }); if (It != BBRelations.end()) { @@ -198,7 +195,6 @@ private: std::map> Functions; }; - void FBD::initPostDispatcherIt() { // Skip dispatcher and friends auto It = F.begin(); @@ -271,7 +267,6 @@ void FBD::collectReturnInstructions() { IsReturn = false; break; } - } IsReturn &= JumpsToDispatcher; @@ -282,7 +277,6 @@ void FBD::collectReturnInstructions() { // of a register Returns.insert(Terminator); } - } } @@ -395,9 +389,9 @@ void FBD::cfepProcessPhase1() { // address, unless it's a call to a noreturn function. if (JTM->noReturn().isNoreturnBasicBlock(RelatedBB)) { DBG("nra", { - dbg << "Stopping at " << getName(RelatedBB) - << " since it's a noreturn call\n"; - }); + dbg << "Stopping at " << getName(RelatedBB) + << " since it's a noreturn call\n"; + }); } else { BasicBlock *ReturnBB = FCIt->second; setRelation(CFEP, ReturnBB, Return); @@ -415,7 +409,6 @@ void FBD::cfepProcessPhase1() { setRelation(CFEP, S, Jump); WorkList.insert(S); } - } } @@ -460,9 +453,7 @@ void FBD::cfepProcessPhase1() { registerCFEP(S, SkippingJump); CFEPWorkList.insert(S); } - } - } } } @@ -484,9 +475,8 @@ void FBD::filterCFEPs() { Keep = true; // Check no relation of Jump type and 0-distance exist for (CFEPRelation &Relation : Relations[CFEPHead]) - Keep = Keep - && !Relation.isNonSkippingJump() - && !Relation.hasType(Return); + Keep = Keep && !Relation.isNonSkippingJump() + && !Relation.hasType(Return); } if (!Keep && !AddressTaken) { @@ -494,30 +484,26 @@ void FBD::filterCFEPs() { Keep = Relations.size() > 1; if (Keep) for (CFEPRelation &Relation : CFEPRelations) - Keep = Keep && (Relation.hasType(Head) - || Relation.isSkippingJump()); + Keep = Keep && (Relation.hasType(Head) || Relation.isSkippingJump()); } if (Keep) { DBG("functions", { - dbg << std::hex << "0x" << getBasicBlockPC(CFEPHead) - << " is a FEP: " - << " Callee? " << C.hasReason(Callee) - << " GlobalData? " << C.hasReason(GlobalData) - << " InCode? " << C.hasReason(InCode) - << " SkippingJump? " << C.hasReason(SkippingJump) - << " FunctionSymbol?" << C.hasReason(FunctionSymbol) - << "\n"; - }); + dbg << std::hex << "0x" << getBasicBlockPC(CFEPHead) << " is a FEP: " + << " Callee? " << C.hasReason(Callee) << " GlobalData? " + << C.hasReason(GlobalData) << " InCode? " << C.hasReason(InCode) + << " SkippingJump? " << C.hasReason(SkippingJump) + << " FunctionSymbol?" << C.hasReason(FunctionSymbol) << "\n"; + }); It++; } else { DBG("functions", { - dbg << std::hex << "0x" << getBasicBlockPC(CFEPHead) - << " is a not a FEP:"; - for (CFEPRelation &Relation : Relations[CFEPHead]) - dbg << " {" << Relation.describe() << "}"; - dbg << "\n"; - }); + dbg << std::hex << "0x" << getBasicBlockPC(CFEPHead) + << " is a not a FEP:"; + for (CFEPRelation &Relation : Relations[CFEPHead]) + dbg << " {" << Relation.describe() << "}"; + dbg << "\n"; + }); It = CFEPs.erase(It); } } @@ -549,7 +535,6 @@ void FBD::cfepProcessPhase2() { if (!isCFEP(S)) WorkList.insert(S); } - } } @@ -577,24 +562,23 @@ void FBD::createMetadata() { for (BasicBlock *Member : P.second) ReversedFunctions[Member].push_back(FunctionMD); - } // Associate the terminator of each basic block with the previously created // metadata node for (auto &P : ReversedFunctions) { BasicBlock *BB = P.first; - if (!BB->empty() ) { + if (!BB->empty()) { Instruction *Terminator = BB->getTerminator(); assert(Terminator != nullptr); - auto *FuncMDs = MDTuple::get(Context, ArrayRef(P.second)); + auto *FuncMDs = MDTuple::get(Context, ArrayRef(P.second)); Terminator->setMetadata("func.member.of", FuncMDs); } } // Mark each return instruction for (TerminatorInst *T : Returns) - T->setMetadata("func.return", MDNode::get(Context, { })); + T->setMetadata("func.return", MDNode::get(Context, {})); } map> FBD::run() { @@ -628,8 +612,7 @@ map> FBD::run() { std::string FBD::CFEPRelation::describe() const { std::stringstream SS; - SS << getName(CFEP) - << " Distance: " << Distance; + SS << getName(CFEP) << " Distance: " << Distance; if (hasType(UnknownRelation)) SS << " UnknownRelation"; diff --git a/functionboundariesdetection.h b/functionboundariesdetection.h index 2236ceb8f..cea6cea87 100644 --- a/functionboundariesdetection.h +++ b/functionboundariesdetection.h @@ -23,11 +23,13 @@ public: static char ID; public: - FunctionBoundariesDetectionPass() : llvm::FunctionPass(ID), JTM(nullptr) { } + FunctionBoundariesDetectionPass() : llvm::FunctionPass(ID), JTM(nullptr) {} FunctionBoundariesDetectionPass(JumpTargetManager *JTM, std::string SerializePath, bool UseDebugSymbols) : - llvm::FunctionPass(ID), JTM(JTM), SerializePath(SerializePath) { } + llvm::FunctionPass(ID), + JTM(JTM), + SerializePath(SerializePath) {} void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.setPreservesAll(); diff --git a/functioncallidentification.cpp b/functioncallidentification.cpp index 101d89e51..a6e3a7dee 100644 --- a/functioncallidentification.cpp +++ b/functioncallidentification.cpp @@ -7,8 +7,8 @@ // // Local includes -#include "debug.h" #include "functioncallidentification.h" +#include "debug.h" using namespace llvm; @@ -33,12 +33,10 @@ bool FunctionCallIdentification::runOnFunction(llvm::Function &F) { PointerType *Int8PtrTy = Type::getInt8PtrTy(C); auto *PCTy = IntegerType::get(C, GCBI.pcRegSize() * 8); auto *PCPtrTy = cast(GCBI.pcReg()->getType()); - std::initializer_list FunctionArgsTy = { - Int8PtrTy, - Int8PtrTy, - PCTy, - PCPtrTy - }; + std::initializer_list FunctionArgsTy = { Int8PtrTy, + Int8PtrTy, + PCTy, + PCPtrTy }; using FT = FunctionType; auto *Ty = FT::get(Type::getVoidTy(C), FunctionArgsTy, false); Constant *FunctionCallC = M->getOrInsertFunction("function_call", Ty); @@ -89,7 +87,7 @@ bool FunctionCallIdentification::runOnFunction(llvm::Function &F) { &LastPC, &StorePCFound, &LinkRegister, - &PCPtrTy] (RBasicBlockRange R) { + &PCPtrTy](RBasicBlockRange R) { for (Instruction &I : R) { if (auto *Store = dyn_cast(&I)) { Value *V = Store->getValueOperand(); @@ -141,7 +139,6 @@ bool FunctionCallIdentification::runOnFunction(llvm::Function &F) { // being pushed on the top of the stack LinkRegister = ConstantPointerNull::get(PCPtrTy); } - } } } else if (auto *Call = dyn_cast(&I)) { @@ -211,12 +208,11 @@ bool FunctionCallIdentification::runOnFunction(llvm::Function &F) { Callee = ConstantPointerNull::get(Int8PtrTy); } - const std::initializer_list Args { - Callee, - BlockAddress::get(ReturnBB), - ConstantInt::get(PCTy, ReturnPC), - LinkRegister - }; + const std::initializer_list Args{ Callee, + BlockAddress::get(ReturnBB), + ConstantInt::get(PCTy, + ReturnPC), + LinkRegister }; FallthroughAddresses.insert(ReturnPC); diff --git a/functioncallidentification.h b/functioncallidentification.h index d8422e8ec..5cfaa67fa 100644 --- a/functioncallidentification.h +++ b/functioncallidentification.h @@ -6,10 +6,10 @@ // // LLVM includes -#include "llvm/Pass.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" #include "llvm/Support/Casting.h" // Local includes @@ -31,7 +31,7 @@ public: static char ID; public: - FunctionCallIdentification() : llvm::FunctionPass(ID) { } + FunctionCallIdentification() : llvm::FunctionPass(ID) {} void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.setPreservesAll(); diff --git a/generatedcodebasicinfo.cpp b/generatedcodebasicinfo.cpp index ada286b7d..a5e4335ce 100644 --- a/generatedcodebasicinfo.cpp +++ b/generatedcodebasicinfo.cpp @@ -7,8 +7,8 @@ // // Standard includes -#include #include +#include // LLVM includes #include "llvm/IR/Function.h" @@ -22,10 +22,7 @@ using namespace llvm; char GeneratedCodeBasicInfo::ID = 0; using RegisterGCBI = RegisterPass; -static RegisterGCBI X("gcbi", - "Generated Code Basic Info", - true, - true); +static RegisterGCBI X("gcbi", "Generated Code Basic Info", true, true); bool GeneratedCodeBasicInfo::runOnFunction(llvm::Function &F) { DBG("passes", { dbg << "Starting GeneratedCodeBasicInfo\n"; }); @@ -63,13 +60,12 @@ bool GeneratedCodeBasicInfo::runOnFunction(llvm::Function &F) { assert(UnexpectedPC == nullptr); UnexpectedPC = &BB; break; - case JumpTargetBlock: - { - auto *Call = cast(&*BB.begin()); - assert(Call->getCalledFunction()->getName() == "newpc"); - JumpTargets[getLimitedValue(Call->getArgOperand(0))] = &BB; - break; - } + case JumpTargetBlock: { + auto *Call = cast(&*BB.begin()); + assert(Call->getCalledFunction()->getName() == "newpc"); + JumpTargets[getLimitedValue(Call->getArgOperand(0))] = &BB; + break; + } case UntypedBlock: // Nothing to do here break; @@ -77,9 +73,7 @@ bool GeneratedCodeBasicInfo::runOnFunction(llvm::Function &F) { } } - assert(Dispatcher != nullptr - && AnyPC != nullptr - && UnexpectedPC != nullptr); + assert(Dispatcher != nullptr && AnyPC != nullptr && UnexpectedPC != nullptr); DBG("passes", { dbg << "Ending GeneratedCodeBasicInfo\n"; }); @@ -138,7 +132,6 @@ GeneratedCodeBasicInfo::getPC(Instruction *TheInstruction) const { } } } - } // Couldn't find the current PC diff --git a/generatedcodebasicinfo.h b/generatedcodebasicinfo.h index 0c6bd7ca0..69b170368 100644 --- a/generatedcodebasicinfo.h +++ b/generatedcodebasicinfo.h @@ -24,7 +24,7 @@ class BasicBlock; class GlobalVariable; class Instruction; class MDNode; -} +} // namespace llvm static const char *BlockTypeMDName = "revamb.block.type"; static const char *JTReasonMDName = "revamb.jt.reasons"; @@ -53,7 +53,7 @@ public: DispatcherFail(nullptr), AnyPC(nullptr), UnexpectedPC(nullptr), - PCRegSize(0) { } + PCRegSize(0) {} void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.setPreservesAll(); @@ -263,17 +263,17 @@ private: }; template<> -struct BlackListTrait : - BlackListTraitBase { +struct BlackListTrait + : BlackListTraitBase { using BlackListTraitBase::BlackListTraitBase; bool isBlacklisted(llvm::BasicBlock *Value) { return !this->Obj.isTranslated(Value); } }; -inline -void GeneratedCodeBasicInfo::visitPredecessors(llvm::Instruction *I, - RVisitorFunction Visitor) { +inline void +GeneratedCodeBasicInfo::visitPredecessors(llvm::Instruction *I, + RVisitorFunction Visitor) { using BLT = BlackListTrait; ::visitPredecessors(I, Visitor, BLT(*this)); diff --git a/include/revng/StackAnalysis/functionssummary.h b/include/revng/StackAnalysis/functionssummary.h index dba4ac7af..cc06dd726 100644 --- a/include/revng/StackAnalysis/functionssummary.h +++ b/include/revng/StackAnalysis/functionssummary.h @@ -436,12 +436,12 @@ public: }; struct FunctionDescription { - FunctionDescription() : Type(FunctionType::Invalid) { } + FunctionDescription() : Type(FunctionType::Invalid) {} FunctionType::Values Type; std::map BasicBlocks; - std::map RegisterSlots; + std::map + RegisterSlots; std::vector CallSites; std::set ClobberedRegisters; }; @@ -505,7 +505,6 @@ public: private: void dumpInternal(const llvm::Module *M, StreamWrapperBase &&Stream) const; - }; } // namespace StackAnalysis diff --git a/include/revng/StackAnalysis/stackanalysis.h b/include/revng/StackAnalysis/stackanalysis.h index 724e30c51..a9fc9e8e7 100644 --- a/include/revng/StackAnalysis/stackanalysis.h +++ b/include/revng/StackAnalysis/stackanalysis.h @@ -25,7 +25,7 @@ public: static char ID; public: - StackAnalysis() : llvm::FunctionPass(ID) { } + StackAnalysis() : llvm::FunctionPass(ID) {} void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.setPreservesAll(); @@ -39,14 +39,11 @@ public: return GrandResult.Functions[Function].ClobberedRegisters; } - void serialize(std::ostream &Output) { - Output << TextRepresentation; - } + void serialize(std::ostream &Output) { Output << TextRepresentation; } private: FunctionsSummary GrandResult; std::string TextRepresentation; - }; } // namespace StackAnalysis diff --git a/instructiontranslator.cpp b/instructiontranslator.cpp index 083b57550..6142ead20 100644 --- a/instructiontranslator.cpp +++ b/instructiontranslator.cpp @@ -15,8 +15,8 @@ #include // LLVM includes -#include "llvm/IR/CFG.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" @@ -37,180 +37,172 @@ using IT = InstructionTranslator; namespace PTC { - template - class InstructionImpl; +template +class InstructionImpl; - enum ArgumentType { - In, - Out, - Const - }; +enum ArgumentType { In, Out, Const }; - template - using RAI = RandomAccessIterator; +template +using RAI = RandomAccessIterator; - template - class InstructionArgumentsIterator : - public RAI, false> { +template +class InstructionArgumentsIterator + : public RAI, false> { - public: - using base = RandomAccessIterator; +public: + using base = RandomAccessIterator; - InstructionArgumentsIterator& - operator=(const InstructionArgumentsIterator& r) { - base::operator=(r); - TheInstruction = r.TheInstruction; - return *this; - } - - - InstructionArgumentsIterator(const InstructionArgumentsIterator& r) : - base(r), - TheInstruction(r.TheInstruction) { } - - InstructionArgumentsIterator(const InstructionArgumentsIterator& r, - unsigned Index) : - base(Index), - TheInstruction(r.TheInstruction) { } - - InstructionArgumentsIterator(PTCInstruction *TheInstruction, - unsigned Index) : - base(Index), - TheInstruction(TheInstruction) { } - - bool isCompatible(const InstructionArgumentsIterator& r) const { - return TheInstruction == r.TheInstruction; - } - - public: - uint64_t get(unsigned Index) const; - - private: - PTCInstruction *TheInstruction; - }; - - template<> - inline uint64_t - InstructionArgumentsIterator::get(unsigned Index) const { - return ptc_call_instruction_in_arg(&ptc, TheInstruction, Index); + InstructionArgumentsIterator & + operator=(const InstructionArgumentsIterator &r) { + base::operator=(r); + TheInstruction = r.TheInstruction; + return *this; } - template<> - inline uint64_t - InstructionArgumentsIterator::get(unsigned Index) const { - return ptc_call_instruction_const_arg(&ptc, TheInstruction, Index); + InstructionArgumentsIterator(const InstructionArgumentsIterator &r) : + base(r), + TheInstruction(r.TheInstruction) {} + + InstructionArgumentsIterator(const InstructionArgumentsIterator &r, + unsigned Index) : + base(Index), + TheInstruction(r.TheInstruction) {} + + InstructionArgumentsIterator(PTCInstruction *TheInstruction, unsigned Index) : + base(Index), + TheInstruction(TheInstruction) {} + + bool isCompatible(const InstructionArgumentsIterator &r) const { + return TheInstruction == r.TheInstruction; } - template<> - inline uint64_t - InstructionArgumentsIterator::get(unsigned Index) const { - return ptc_call_instruction_out_arg(&ptc, TheInstruction, Index); - } +public: + uint64_t get(unsigned Index) const; - template<> - inline uint64_t - InstructionArgumentsIterator::get(unsigned Index) const { - return ptc_instruction_in_arg(&ptc, TheInstruction, Index); - } - - template<> - inline uint64_t - InstructionArgumentsIterator::get(unsigned Index) const { - return ptc_instruction_const_arg(&ptc, TheInstruction, Index); - } - - template<> - inline uint64_t - InstructionArgumentsIterator::get(unsigned Index) const { - return ptc_instruction_out_arg(&ptc, TheInstruction, Index); - } - - template - class InstructionImpl { - private: - template - using arguments = InstructionArgumentsIterator; - public: - InstructionImpl(PTCInstruction *TheInstruction) : - TheInstruction(TheInstruction), - InArguments(arguments(TheInstruction, 0), - arguments(TheInstruction, inArgCount())), - ConstArguments(arguments(TheInstruction, 0), - arguments(TheInstruction, constArgCount())), - OutArguments(arguments(TheInstruction, 0), - arguments(TheInstruction, outArgCount())) - { } - - PTCOpcode opcode() const { - return TheInstruction->opc; - } - - std::string helperName() const { - assert(IsCall); - PTCHelperDef *Helper = ptc_find_helper(&ptc, ConstArguments[0]); - assert(Helper != nullptr && Helper->name != nullptr); - return std::string(Helper->name); - } - - uint64_t pc() const { - assert(opcode() == PTC_INSTRUCTION_op_debug_insn_start); - uint64_t PC = ConstArguments[0]; - if (ConstArguments.size() > 1) - PC |= ConstArguments[1] << 32; - return PC; - } - - private: - PTCInstruction* TheInstruction; - - public: - const Range> InArguments; - const Range> ConstArguments; - const Range> OutArguments; - - private: - unsigned inArgCount() const; - unsigned constArgCount() const; - unsigned outArgCount() const; - }; - - using Instruction = InstructionImpl; - using CallInstruction = InstructionImpl; - - template<> - inline unsigned CallInstruction::inArgCount() const { - return ptc_call_instruction_in_arg_count(&ptc, TheInstruction); - } - - template<> - inline unsigned Instruction::inArgCount() const { - return ptc_instruction_in_arg_count(&ptc, TheInstruction); - } - - template<> - inline unsigned CallInstruction::constArgCount() const { - return ptc_call_instruction_const_arg_count(&ptc, TheInstruction); - } - - template<> - inline unsigned Instruction::constArgCount() const { - return ptc_instruction_const_arg_count(&ptc, TheInstruction); - } - - template<> - inline unsigned CallInstruction::outArgCount() const { - return ptc_call_instruction_out_arg_count(&ptc, TheInstruction); - } - - template<> - inline unsigned Instruction::outArgCount() const { - return ptc_instruction_out_arg_count(&ptc, TheInstruction); - } +private: + PTCInstruction *TheInstruction; +}; +template<> +inline uint64_t +InstructionArgumentsIterator::get(unsigned Index) const { + return ptc_call_instruction_in_arg(&ptc, TheInstruction, Index); } +template<> +inline uint64_t +InstructionArgumentsIterator::get(unsigned Index) const { + return ptc_call_instruction_const_arg(&ptc, TheInstruction, Index); +} + +template<> +inline uint64_t +InstructionArgumentsIterator::get(unsigned Index) const { + return ptc_call_instruction_out_arg(&ptc, TheInstruction, Index); +} + +template<> +inline uint64_t +InstructionArgumentsIterator::get(unsigned Index) const { + return ptc_instruction_in_arg(&ptc, TheInstruction, Index); +} + +template<> +inline uint64_t +InstructionArgumentsIterator::get(unsigned Index) const { + return ptc_instruction_const_arg(&ptc, TheInstruction, Index); +} + +template<> +inline uint64_t +InstructionArgumentsIterator::get(unsigned Index) const { + return ptc_instruction_out_arg(&ptc, TheInstruction, Index); +} + +template +class InstructionImpl { +private: + template + using arguments = InstructionArgumentsIterator; + +public: + InstructionImpl(PTCInstruction *TheInstruction) : + TheInstruction(TheInstruction), + InArguments(arguments(TheInstruction, 0), + arguments(TheInstruction, inArgCount())), + ConstArguments(arguments(TheInstruction, 0), + arguments(TheInstruction, constArgCount())), + OutArguments(arguments(TheInstruction, 0), + arguments(TheInstruction, outArgCount())) {} + + PTCOpcode opcode() const { return TheInstruction->opc; } + + std::string helperName() const { + assert(IsCall); + PTCHelperDef *Helper = ptc_find_helper(&ptc, ConstArguments[0]); + assert(Helper != nullptr && Helper->name != nullptr); + return std::string(Helper->name); + } + + uint64_t pc() const { + assert(opcode() == PTC_INSTRUCTION_op_debug_insn_start); + uint64_t PC = ConstArguments[0]; + if (ConstArguments.size() > 1) + PC |= ConstArguments[1] << 32; + return PC; + } + +private: + PTCInstruction *TheInstruction; + +public: + const Range> InArguments; + const Range> ConstArguments; + const Range> OutArguments; + +private: + unsigned inArgCount() const; + unsigned constArgCount() const; + unsigned outArgCount() const; +}; + +using Instruction = InstructionImpl; +using CallInstruction = InstructionImpl; + +template<> +inline unsigned CallInstruction::inArgCount() const { + return ptc_call_instruction_in_arg_count(&ptc, TheInstruction); +} + +template<> +inline unsigned Instruction::inArgCount() const { + return ptc_instruction_in_arg_count(&ptc, TheInstruction); +} + +template<> +inline unsigned CallInstruction::constArgCount() const { + return ptc_call_instruction_const_arg_count(&ptc, TheInstruction); +} + +template<> +inline unsigned Instruction::constArgCount() const { + return ptc_instruction_const_arg_count(&ptc, TheInstruction); +} + +template<> +inline unsigned CallInstruction::outArgCount() const { + return ptc_call_instruction_out_arg_count(&ptc, TheInstruction); +} + +template<> +inline unsigned Instruction::outArgCount() const { + return ptc_instruction_out_arg_count(&ptc, TheInstruction); +} + +} // namespace PTC + /// Converts a PTC condition into an LLVM predicate /// /// \param Condition the input PTC condition. @@ -458,7 +450,7 @@ static unsigned getRegisterSize(unsigned Opcode) { /// /// \return a compare instruction. template -static Value *CreateICmp(T& Builder, +static Value *CreateICmp(T &Builder, uint64_t RawCondition, Value *FirstOperand, Value *SecondOperand) { @@ -469,9 +461,9 @@ static Value *CreateICmp(T& Builder, } using LBM = IT::LabeledBlocksMap; -IT::InstructionTranslator(IRBuilder<>& Builder, - VariableManager& Variables, - JumpTargetManager& JumpTargets, +IT::InstructionTranslator(IRBuilder<> &Builder, + VariableManager &Variables, + JumpTargetManager &JumpTargets, std::vector Blocks, const Architecture &SourceArchitecture, const Architecture &TargetArchitecture) : @@ -494,11 +486,9 @@ IT::InstructionTranslator(IRBuilder<>& Builder, // * isJT (-1: unknown, 0: no, 1: yes) // * all the local variables used by this instruction auto *NewPCMarkerTy = FT::get(Type::getVoidTy(Context), - { + { Type::getInt64Ty(Context), Type::getInt64Ty(Context), - Type::getInt64Ty(Context), - Type::getInt32Ty(Context) - }, + Type::getInt32Ty(Context) }, true); NewPCMarker = Function::Create(NewPCMarkerTy, GlobalValue::ExternalLinkage, @@ -518,9 +508,7 @@ void IT::finalizeNewPCMarkers(std::string &CoveragePath) { uint64_t PC = (cast(Call->getArgOperand(0)))->getLimitedValue(); uint64_t Size = (cast(Call->getArgOperand(1)))->getLimitedValue(); bool IsJT = JumpTargets.isJumpTarget(PC); - Output << "0x" << PC - << ",0x" << Size - << "," << (IsJT ? "1" : "0") + Output << "0x" << PC << ",0x" << Size << "," << (IsJT ? "1" : "0") << std::endl; unsigned ArgCount = Call->getNumArgOperands(); @@ -583,12 +571,12 @@ IT::newInstruction(PTCInstruction *Instr, // A new original instruction, let's create a new metadata node // referencing it for all the next instructions to come uint64_t PC = TheInstruction.pc(); - uint64_t NextPC = Next != nullptr ? PTC::Instruction(Next).pc() : EndPC; + uint64_t NextPC = Next != nullptr ? PTC::Instruction(Next).pc() : EndPC; std::stringstream OriginalStringStream; disassembleOriginal(OriginalStringStream, PC); std::string OriginalString = OriginalStringStream.str(); - LLVMContext& Context = TheModule.getContext(); + LLVMContext &Context = TheModule.getContext(); MDString *MDOriginalString = MDString::get(Context, OriginalString); auto *MDPC = ConstantAsMetadata::get(Builder.getInt64(PC)); MDNode *MDOriginalInstr = MDNode::getDistinct(Context, @@ -610,7 +598,7 @@ IT::newInstruction(PTCInstruction *Instr, Builder.SetInsertPoint(DivergeTo); } else { // The block contains already translated code, early exit - return R { Stop, MDOriginalInstr, PC, NextPC }; + return R{ Stop, MDOriginalInstr, PC, NextPC }; } } } @@ -620,11 +608,9 @@ IT::newInstruction(PTCInstruction *Instr, // Insert a call to NewPCMarker capturing all the local temporaries // This prevents SROA from transforming them in SSA values, which is bad // in case we have to split a basic block - std::vector Args = { - Builder.getInt64(PC), - Builder.getInt64(NextPC - PC), - Builder.getInt32(-1) - }; + std::vector Args = { Builder.getInt64(PC), + Builder.getInt64(NextPC - PC), + Builder.getInt32(-1) }; for (AllocaInst *Local : Variables.locals()) Args.push_back(Local); @@ -639,7 +625,7 @@ IT::newInstruction(PTCInstruction *Instr, JumpTargets.registerInstruction(PC, Call); } - return R { Success, MDOriginalInstr, PC, NextPC }; + return R{ Success, MDOriginalInstr, PC, NextPC }; } static StoreInst *getLastUniqueWrite(BasicBlock *BB, const Value *Register) { @@ -694,7 +680,7 @@ IT::TranslationResult IT::translateCall(PTCInstruction *Instr) { InArgs.push_back(Load); } - auto GetValueType = [] (Value *Argument) { return Argument->getType(); }; + auto GetValueType = [](Value *Argument) { return Argument->getType(); }; std::vector InArgsType = (InArgs | GetValueType).toVector(); // TODO: handle multiple return arguments @@ -735,9 +721,8 @@ IT::TranslationResult IT::translateCall(PTCInstruction *Instr) { return Success; } -IT::TranslationResult IT::translate(PTCInstruction *Instr, - uint64_t PC, - uint64_t NextPC) { +IT::TranslationResult +IT::translate(PTCInstruction *Instr, uint64_t PC, uint64_t NextPC) { const PTC::Instruction TheInstruction(Instr); std::vector InArgs; @@ -792,7 +777,7 @@ ErrorOr> IT::translateOpcode(PTCOpcode Opcode, std::vector ConstArguments, std::vector InArguments) { - LLVMContext& Context = TheModule.getContext(); + LLVMContext &Context = TheModule.getContext(); unsigned RegisterSize = getRegisterSize(Opcode); Type *RegisterType = nullptr; if (RegisterSize == 32) @@ -806,119 +791,116 @@ IT::translateOpcode(PTCOpcode Opcode, switch (Opcode) { case PTC_INSTRUCTION_op_movi_i32: case PTC_INSTRUCTION_op_movi_i64: - return v { ConstantInt::get(RegisterType, ConstArguments[0]) }; + return v{ ConstantInt::get(RegisterType, ConstArguments[0]) }; case PTC_INSTRUCTION_op_discard: // Let's overwrite the discarded temporary with a 0 - return v { ConstantInt::get(RegisterType, 0) }; + return v{ ConstantInt::get(RegisterType, 0) }; case PTC_INSTRUCTION_op_mov_i32: case PTC_INSTRUCTION_op_mov_i64: - return v { Builder.CreateTrunc(InArguments[0], RegisterType) }; + return v{ Builder.CreateTrunc(InArguments[0], RegisterType) }; case PTC_INSTRUCTION_op_setcond_i32: - case PTC_INSTRUCTION_op_setcond_i64: - { - Value *Compare = CreateICmp(Builder, - ConstArguments[0], - InArguments[0], - InArguments[1]); - // TODO: convert single-bit registers to i1 - return v { Builder.CreateZExt(Compare, RegisterType) }; - } + case PTC_INSTRUCTION_op_setcond_i64: { + Value *Compare = CreateICmp(Builder, + ConstArguments[0], + InArguments[0], + InArguments[1]); + // TODO: convert single-bit registers to i1 + return v{ Builder.CreateZExt(Compare, RegisterType) }; + } case PTC_INSTRUCTION_op_movcond_i32: // Resist the fallthrough temptation - case PTC_INSTRUCTION_op_movcond_i64: - { - Value *Compare = CreateICmp(Builder, - ConstArguments[0], - InArguments[0], - InArguments[1]); - Value *Select = Builder.CreateSelect(Compare, - InArguments[2], - InArguments[3]); - return v { Select }; - } + case PTC_INSTRUCTION_op_movcond_i64: { + Value *Compare = CreateICmp(Builder, + ConstArguments[0], + InArguments[0], + InArguments[1]); + Value *Select = Builder.CreateSelect(Compare, + InArguments[2], + InArguments[3]); + return v{ Select }; + } case PTC_INSTRUCTION_op_qemu_ld_i32: case PTC_INSTRUCTION_op_qemu_ld_i64: case PTC_INSTRUCTION_op_qemu_st_i32: - case PTC_INSTRUCTION_op_qemu_st_i64: - { - PTCLoadStoreArg MemoryAccess; - MemoryAccess = ptc.parse_load_store_arg(ConstArguments[0]); + case PTC_INSTRUCTION_op_qemu_st_i64: { + PTCLoadStoreArg MemoryAccess; + MemoryAccess = ptc.parse_load_store_arg(ConstArguments[0]); - // What are we supposed to do in this case? - assert(MemoryAccess.access_type != PTC_MEMORY_ACCESS_UNKNOWN); + // What are we supposed to do in this case? + assert(MemoryAccess.access_type != PTC_MEMORY_ACCESS_UNKNOWN); - unsigned Alignment = 0; - if (MemoryAccess.access_type == PTC_MEMORY_ACCESS_UNALIGNED) - Alignment = 1; - else - Alignment = SourceArchitecture.defaultAlignment(); + unsigned Alignment = 0; + if (MemoryAccess.access_type == PTC_MEMORY_ACCESS_UNALIGNED) + Alignment = 1; + else + Alignment = SourceArchitecture.defaultAlignment(); - // Load size - IntegerType *MemoryType = nullptr; - switch (ptc_get_memory_access_size(MemoryAccess.type)) { - case PTC_MO_8: - MemoryType = Builder.getInt8Ty(); - break; - case PTC_MO_16: - MemoryType = Builder.getInt16Ty(); - break; - case PTC_MO_32: - MemoryType = Builder.getInt32Ty(); - break; - case PTC_MO_64: - MemoryType = Builder.getInt64Ty(); - break; - default: - llvm_unreachable("Unexpected load size"); - } - - // If necessary, handle endianess mismatch - // TODO: it might be a bit overkill, but it be nice to make this function - // template-parametric w.r.t. endianess mismatch - Function *BSwapFunction = nullptr; - if (MemoryType != Builder.getInt8Ty() && - SourceArchitecture.endianess() != TargetArchitecture.endianess()) - BSwapFunction = Intrinsic::getDeclaration(&TheModule, - Intrinsic::bswap, - { MemoryType }); - - bool SignExtend = ptc_is_sign_extended_load(MemoryAccess.type); - - Value *Pointer = nullptr; - if (Opcode == PTC_INSTRUCTION_op_qemu_ld_i32 || - Opcode == PTC_INSTRUCTION_op_qemu_ld_i64) { - - Pointer = Builder.CreateIntToPtr(InArguments[0], - MemoryType->getPointerTo()); - auto *Load = Builder.CreateAlignedLoad(Pointer, Alignment); - Variables.setNoAlias(Load); - Value *Loaded = Load; - - if (BSwapFunction != nullptr) - Loaded = Builder.CreateCall(BSwapFunction, Load); - - if (SignExtend) - return v { Builder.CreateSExt(Loaded, RegisterType) }; - else - return v { Builder.CreateZExt(Loaded, RegisterType) }; - - } else if (Opcode == PTC_INSTRUCTION_op_qemu_st_i32 || - Opcode == PTC_INSTRUCTION_op_qemu_st_i64) { - - Pointer = Builder.CreateIntToPtr(InArguments[1], - MemoryType->getPointerTo()); - Value *Value = Builder.CreateTrunc(InArguments[0], MemoryType); - - if (BSwapFunction != nullptr) - Value = Builder.CreateCall(BSwapFunction, Value); - - auto *Store = Builder.CreateAlignedStore(Value, Pointer, Alignment); - Variables.setNoAlias(Store); - - return v { }; - } else { - llvm_unreachable("Unknown load type"); - } + // Load size + IntegerType *MemoryType = nullptr; + switch (ptc_get_memory_access_size(MemoryAccess.type)) { + case PTC_MO_8: + MemoryType = Builder.getInt8Ty(); + break; + case PTC_MO_16: + MemoryType = Builder.getInt16Ty(); + break; + case PTC_MO_32: + MemoryType = Builder.getInt32Ty(); + break; + case PTC_MO_64: + MemoryType = Builder.getInt64Ty(); + break; + default: + llvm_unreachable("Unexpected load size"); } + + // If necessary, handle endianess mismatch + // TODO: it might be a bit overkill, but it be nice to make this function + // template-parametric w.r.t. endianess mismatch + Function *BSwapFunction = nullptr; + if (MemoryType != Builder.getInt8Ty() + && SourceArchitecture.endianess() != TargetArchitecture.endianess()) + BSwapFunction = Intrinsic::getDeclaration(&TheModule, + Intrinsic::bswap, + { MemoryType }); + + bool SignExtend = ptc_is_sign_extended_load(MemoryAccess.type); + + Value *Pointer = nullptr; + if (Opcode == PTC_INSTRUCTION_op_qemu_ld_i32 + || Opcode == PTC_INSTRUCTION_op_qemu_ld_i64) { + + Pointer = Builder.CreateIntToPtr(InArguments[0], + MemoryType->getPointerTo()); + auto *Load = Builder.CreateAlignedLoad(Pointer, Alignment); + Variables.setNoAlias(Load); + Value *Loaded = Load; + + if (BSwapFunction != nullptr) + Loaded = Builder.CreateCall(BSwapFunction, Load); + + if (SignExtend) + return v{ Builder.CreateSExt(Loaded, RegisterType) }; + else + return v{ Builder.CreateZExt(Loaded, RegisterType) }; + + } else if (Opcode == PTC_INSTRUCTION_op_qemu_st_i32 + || Opcode == PTC_INSTRUCTION_op_qemu_st_i64) { + + Pointer = Builder.CreateIntToPtr(InArguments[1], + MemoryType->getPointerTo()); + Value *Value = Builder.CreateTrunc(InArguments[0], MemoryType); + + if (BSwapFunction != nullptr) + Value = Builder.CreateCall(BSwapFunction, Value); + + auto *Store = Builder.CreateAlignedStore(Value, Pointer, Alignment); + Variables.setNoAlias(Store); + + return v{}; + } else { + llvm_unreachable("Unknown load type"); + } + } case PTC_INSTRUCTION_op_ld8u_i32: case PTC_INSTRUCTION_op_ld8s_i32: case PTC_INSTRUCTION_op_ld16u_i32: @@ -930,119 +912,116 @@ IT::translateOpcode(PTCOpcode Opcode, case PTC_INSTRUCTION_op_ld16s_i64: case PTC_INSTRUCTION_op_ld32u_i64: case PTC_INSTRUCTION_op_ld32s_i64: - case PTC_INSTRUCTION_op_ld_i64: - { - Value *Base = dyn_cast(InArguments[0])->getPointerOperand(); - if (Base == nullptr || !Variables.isEnv(Base)) { - // TODO: emit warning - return std::errc::invalid_argument; - } - - bool Signed; - switch (Opcode) { - case PTC_INSTRUCTION_op_ld_i32: - case PTC_INSTRUCTION_op_ld_i64: - - case PTC_INSTRUCTION_op_ld8u_i32: - case PTC_INSTRUCTION_op_ld16u_i32: - case PTC_INSTRUCTION_op_ld8u_i64: - case PTC_INSTRUCTION_op_ld16u_i64: - case PTC_INSTRUCTION_op_ld32u_i64: - Signed = false; - break; - case PTC_INSTRUCTION_op_ld8s_i32: - case PTC_INSTRUCTION_op_ld16s_i32: - case PTC_INSTRUCTION_op_ld8s_i64: - case PTC_INSTRUCTION_op_ld16s_i64: - case PTC_INSTRUCTION_op_ld32s_i64: - Signed = true; - break; - default: - llvm_unreachable("Unexpected opcode"); - } - - unsigned LoadSize; - switch (Opcode) { - case PTC_INSTRUCTION_op_ld8u_i32: - case PTC_INSTRUCTION_op_ld8s_i32: - case PTC_INSTRUCTION_op_ld8u_i64: - case PTC_INSTRUCTION_op_ld8s_i64: - LoadSize = 1; - break; - case PTC_INSTRUCTION_op_ld16u_i32: - case PTC_INSTRUCTION_op_ld16s_i32: - case PTC_INSTRUCTION_op_ld16u_i64: - case PTC_INSTRUCTION_op_ld16s_i64: - LoadSize = 2; - break; - case PTC_INSTRUCTION_op_ld_i32: - case PTC_INSTRUCTION_op_ld32u_i64: - case PTC_INSTRUCTION_op_ld32s_i64: - LoadSize = 4; - break; - case PTC_INSTRUCTION_op_ld_i64: - LoadSize = 8; - break; - default: - llvm_unreachable("Unexpected opcode"); - } - - Value *Result = Variables.loadFromEnvOffset(Builder, - LoadSize, - ConstArguments[0]); - assert(Result != nullptr); - - // Zero/sign extend in the target dimension - if (Signed) - return v { Builder.CreateSExt(Result, RegisterType) }; - else - return v { Builder.CreateZExt(Result, RegisterType) }; - + case PTC_INSTRUCTION_op_ld_i64: { + Value *Base = dyn_cast(InArguments[0])->getPointerOperand(); + if (Base == nullptr || !Variables.isEnv(Base)) { + // TODO: emit warning + return std::errc::invalid_argument; } + + bool Signed; + switch (Opcode) { + case PTC_INSTRUCTION_op_ld_i32: + case PTC_INSTRUCTION_op_ld_i64: + + case PTC_INSTRUCTION_op_ld8u_i32: + case PTC_INSTRUCTION_op_ld16u_i32: + case PTC_INSTRUCTION_op_ld8u_i64: + case PTC_INSTRUCTION_op_ld16u_i64: + case PTC_INSTRUCTION_op_ld32u_i64: + Signed = false; + break; + case PTC_INSTRUCTION_op_ld8s_i32: + case PTC_INSTRUCTION_op_ld16s_i32: + case PTC_INSTRUCTION_op_ld8s_i64: + case PTC_INSTRUCTION_op_ld16s_i64: + case PTC_INSTRUCTION_op_ld32s_i64: + Signed = true; + break; + default: + llvm_unreachable("Unexpected opcode"); + } + + unsigned LoadSize; + switch (Opcode) { + case PTC_INSTRUCTION_op_ld8u_i32: + case PTC_INSTRUCTION_op_ld8s_i32: + case PTC_INSTRUCTION_op_ld8u_i64: + case PTC_INSTRUCTION_op_ld8s_i64: + LoadSize = 1; + break; + case PTC_INSTRUCTION_op_ld16u_i32: + case PTC_INSTRUCTION_op_ld16s_i32: + case PTC_INSTRUCTION_op_ld16u_i64: + case PTC_INSTRUCTION_op_ld16s_i64: + LoadSize = 2; + break; + case PTC_INSTRUCTION_op_ld_i32: + case PTC_INSTRUCTION_op_ld32u_i64: + case PTC_INSTRUCTION_op_ld32s_i64: + LoadSize = 4; + break; + case PTC_INSTRUCTION_op_ld_i64: + LoadSize = 8; + break; + default: + llvm_unreachable("Unexpected opcode"); + } + + Value *Result = Variables.loadFromEnvOffset(Builder, + LoadSize, + ConstArguments[0]); + assert(Result != nullptr); + + // Zero/sign extend in the target dimension + if (Signed) + return v{ Builder.CreateSExt(Result, RegisterType) }; + else + return v{ Builder.CreateZExt(Result, RegisterType) }; + } case PTC_INSTRUCTION_op_st8_i32: case PTC_INSTRUCTION_op_st16_i32: case PTC_INSTRUCTION_op_st_i32: case PTC_INSTRUCTION_op_st8_i64: case PTC_INSTRUCTION_op_st16_i64: case PTC_INSTRUCTION_op_st32_i64: - case PTC_INSTRUCTION_op_st_i64: - { - unsigned StoreSize; - switch (Opcode) { - case PTC_INSTRUCTION_op_st8_i32: - case PTC_INSTRUCTION_op_st8_i64: - StoreSize = 1; - break; - case PTC_INSTRUCTION_op_st16_i32: - case PTC_INSTRUCTION_op_st16_i64: - StoreSize = 2; - break; - case PTC_INSTRUCTION_op_st_i32: - case PTC_INSTRUCTION_op_st32_i64: - StoreSize = 4; - break; - case PTC_INSTRUCTION_op_st_i64: - StoreSize = 8; - break; - default: - llvm_unreachable("Unexpected opcode"); - } - - Value *Base = dyn_cast(InArguments[1])->getPointerOperand(); - if (Base == nullptr || !Variables.isEnv(Base)) { - // TODO: emit warning - return std::errc::invalid_argument; - } - - bool Result = Variables.storeToEnvOffset(Builder, - StoreSize, - ConstArguments[0], - InArguments[0]); - assert(Result); - (void) Result; - - return v { }; + case PTC_INSTRUCTION_op_st_i64: { + unsigned StoreSize; + switch (Opcode) { + case PTC_INSTRUCTION_op_st8_i32: + case PTC_INSTRUCTION_op_st8_i64: + StoreSize = 1; + break; + case PTC_INSTRUCTION_op_st16_i32: + case PTC_INSTRUCTION_op_st16_i64: + StoreSize = 2; + break; + case PTC_INSTRUCTION_op_st_i32: + case PTC_INSTRUCTION_op_st32_i64: + StoreSize = 4; + break; + case PTC_INSTRUCTION_op_st_i64: + StoreSize = 8; + break; + default: + llvm_unreachable("Unexpected opcode"); } + + Value *Base = dyn_cast(InArguments[1])->getPointerOperand(); + if (Base == nullptr || !Variables.isEnv(Base)) { + // TODO: emit warning + return std::errc::invalid_argument; + } + + bool Result = Variables.storeToEnvOffset(Builder, + StoreSize, + ConstArguments[0], + InArguments[0]); + assert(Result); + (void) Result; + + return v{}; + } case PTC_INSTRUCTION_op_add_i32: case PTC_INSTRUCTION_op_sub_i32: case PTC_INSTRUCTION_op_mul_i32: @@ -1068,100 +1047,95 @@ IT::translateOpcode(PTCOpcode Opcode, case PTC_INSTRUCTION_op_xor_i64: case PTC_INSTRUCTION_op_shl_i64: case PTC_INSTRUCTION_op_shr_i64: - case PTC_INSTRUCTION_op_sar_i64: - { - // TODO: assert on sizes? - Instruction::BinaryOps BinaryOp = opcodeToBinaryOp(Opcode); - Value *Operation = Builder.CreateBinOp(BinaryOp, - InArguments[0], - InArguments[1]); - return v { Operation }; - } + case PTC_INSTRUCTION_op_sar_i64: { + // TODO: assert on sizes? + Instruction::BinaryOps BinaryOp = opcodeToBinaryOp(Opcode); + Value *Operation = Builder.CreateBinOp(BinaryOp, + InArguments[0], + InArguments[1]); + return v{ Operation }; + } case PTC_INSTRUCTION_op_div2_i32: case PTC_INSTRUCTION_op_divu2_i32: case PTC_INSTRUCTION_op_div2_i64: - case PTC_INSTRUCTION_op_divu2_i64: - { - Instruction::BinaryOps DivisionOp, RemainderOp; + case PTC_INSTRUCTION_op_divu2_i64: { + Instruction::BinaryOps DivisionOp, RemainderOp; - if (Opcode == PTC_INSTRUCTION_op_div2_i32 || - Opcode == PTC_INSTRUCTION_op_div2_i64) { - DivisionOp = Instruction::SDiv; - RemainderOp = Instruction::SRem; - } else if (Opcode == PTC_INSTRUCTION_op_divu2_i32 || - Opcode == PTC_INSTRUCTION_op_divu2_i64) { - DivisionOp = Instruction::UDiv; - RemainderOp = Instruction::URem; - } else { - llvm_unreachable("Unknown operation type"); - } - - // TODO: we're ignoring InArguments[1], which is the MSB - // TODO: assert on sizes? - Value *Division = Builder.CreateBinOp(DivisionOp, - InArguments[0], - InArguments[2]); - Value *Remainder = Builder.CreateBinOp(RemainderOp, - InArguments[0], - InArguments[2]); - return v { Division, Remainder }; + if (Opcode == PTC_INSTRUCTION_op_div2_i32 + || Opcode == PTC_INSTRUCTION_op_div2_i64) { + DivisionOp = Instruction::SDiv; + RemainderOp = Instruction::SRem; + } else if (Opcode == PTC_INSTRUCTION_op_divu2_i32 + || Opcode == PTC_INSTRUCTION_op_divu2_i64) { + DivisionOp = Instruction::UDiv; + RemainderOp = Instruction::URem; + } else { + llvm_unreachable("Unknown operation type"); } + + // TODO: we're ignoring InArguments[1], which is the MSB + // TODO: assert on sizes? + Value *Division = Builder.CreateBinOp(DivisionOp, + InArguments[0], + InArguments[2]); + Value *Remainder = Builder.CreateBinOp(RemainderOp, + InArguments[0], + InArguments[2]); + return v{ Division, Remainder }; + } case PTC_INSTRUCTION_op_rotr_i32: case PTC_INSTRUCTION_op_rotr_i64: case PTC_INSTRUCTION_op_rotl_i32: - case PTC_INSTRUCTION_op_rotl_i64: - { - Value *Bits = ConstantInt::get(RegisterType, RegisterSize); + case PTC_INSTRUCTION_op_rotl_i64: { + Value *Bits = ConstantInt::get(RegisterType, RegisterSize); - Instruction::BinaryOps FirstShiftOp, SecondShiftOp; - if (Opcode == PTC_INSTRUCTION_op_rotl_i32 || - Opcode == PTC_INSTRUCTION_op_rotl_i64) { - FirstShiftOp = Instruction::Shl; - SecondShiftOp = Instruction::LShr; - } else if (Opcode == PTC_INSTRUCTION_op_rotr_i32 || - Opcode == PTC_INSTRUCTION_op_rotr_i64) { - FirstShiftOp = Instruction::LShr; - SecondShiftOp = Instruction::Shl; - } else { - llvm_unreachable("Unexpected opcode"); - } - - Value *FirstShift = Builder.CreateBinOp(FirstShiftOp, - InArguments[0], - InArguments[1]); - Value *SecondShiftAmount = Builder.CreateSub(Bits, - InArguments[1]); - Value *SecondShift = Builder.CreateBinOp(SecondShiftOp, - InArguments[0], - SecondShiftAmount); - - return v { Builder.CreateOr(FirstShift, SecondShift) }; + Instruction::BinaryOps FirstShiftOp, SecondShiftOp; + if (Opcode == PTC_INSTRUCTION_op_rotl_i32 + || Opcode == PTC_INSTRUCTION_op_rotl_i64) { + FirstShiftOp = Instruction::Shl; + SecondShiftOp = Instruction::LShr; + } else if (Opcode == PTC_INSTRUCTION_op_rotr_i32 + || Opcode == PTC_INSTRUCTION_op_rotr_i64) { + FirstShiftOp = Instruction::LShr; + SecondShiftOp = Instruction::Shl; + } else { + llvm_unreachable("Unexpected opcode"); } + + Value *FirstShift = Builder.CreateBinOp(FirstShiftOp, + InArguments[0], + InArguments[1]); + Value *SecondShiftAmount = Builder.CreateSub(Bits, InArguments[1]); + Value *SecondShift = Builder.CreateBinOp(SecondShiftOp, + InArguments[0], + SecondShiftAmount); + + return v{ Builder.CreateOr(FirstShift, SecondShift) }; + } case PTC_INSTRUCTION_op_deposit_i32: - case PTC_INSTRUCTION_op_deposit_i64: - { - unsigned Position = ConstArguments[0]; - if (Position == RegisterSize) - return v { InArguments[0] }; + case PTC_INSTRUCTION_op_deposit_i64: { + unsigned Position = ConstArguments[0]; + if (Position == RegisterSize) + return v{ InArguments[0] }; - unsigned Length = ConstArguments[1]; - uint64_t Bits = 0; + unsigned Length = ConstArguments[1]; + uint64_t Bits = 0; - // Thou shall not << 32 - if (Length == RegisterSize) - Bits = getMaxValue(RegisterSize); - else - Bits = (1 << Length) - 1; + // Thou shall not << 32 + if (Length == RegisterSize) + Bits = getMaxValue(RegisterSize); + else + Bits = (1 << Length) - 1; - // result = (t1 & ~(bits << position)) | ((t2 & bits) << position) - uint64_t BaseMask = ~(Bits << Position); - Value *MaskedBase = Builder.CreateAnd(InArguments[0], BaseMask); - Value *Deposit = Builder.CreateAnd(InArguments[1], Bits); - Value *ShiftedDeposit = Builder.CreateShl(Deposit, Position); - Value *Result = Builder.CreateOr(MaskedBase, ShiftedDeposit); + // result = (t1 & ~(bits << position)) | ((t2 & bits) << position) + uint64_t BaseMask = ~(Bits << Position); + Value *MaskedBase = Builder.CreateAnd(InArguments[0], BaseMask); + Value *Deposit = Builder.CreateAnd(InArguments[1], Bits); + Value *ShiftedDeposit = Builder.CreateShl(Deposit, Position); + Value *Result = Builder.CreateOr(MaskedBase, ShiftedDeposit); - return v { Result }; - } + return v{ Result }; + } case PTC_INSTRUCTION_op_ext8s_i32: case PTC_INSTRUCTION_op_ext16s_i32: case PTC_INSTRUCTION_op_ext8u_i32: @@ -1171,301 +1145,289 @@ IT::translateOpcode(PTCOpcode Opcode, case PTC_INSTRUCTION_op_ext32s_i64: case PTC_INSTRUCTION_op_ext8u_i64: case PTC_INSTRUCTION_op_ext16u_i64: - case PTC_INSTRUCTION_op_ext32u_i64: - { - Type *SourceType = nullptr; - switch (Opcode) { - case PTC_INSTRUCTION_op_ext8s_i32: - case PTC_INSTRUCTION_op_ext8u_i32: - case PTC_INSTRUCTION_op_ext8s_i64: - case PTC_INSTRUCTION_op_ext8u_i64: - SourceType = Builder.getInt8Ty(); - break; - case PTC_INSTRUCTION_op_ext16s_i32: - case PTC_INSTRUCTION_op_ext16u_i32: - case PTC_INSTRUCTION_op_ext16s_i64: - case PTC_INSTRUCTION_op_ext16u_i64: - SourceType = Builder.getInt16Ty(); - break; - case PTC_INSTRUCTION_op_ext32s_i64: - case PTC_INSTRUCTION_op_ext32u_i64: - SourceType = Builder.getInt32Ty(); - break; - default: - llvm_unreachable("Unexpected opcode"); - } - - Value *Truncated = Builder.CreateTrunc(InArguments[0], SourceType); - - switch (Opcode) { - case PTC_INSTRUCTION_op_ext8s_i32: - case PTC_INSTRUCTION_op_ext8s_i64: - case PTC_INSTRUCTION_op_ext16s_i32: - case PTC_INSTRUCTION_op_ext16s_i64: - case PTC_INSTRUCTION_op_ext32s_i64: - return v { Builder.CreateSExt(Truncated, RegisterType) }; - case PTC_INSTRUCTION_op_ext8u_i32: - case PTC_INSTRUCTION_op_ext8u_i64: - case PTC_INSTRUCTION_op_ext16u_i32: - case PTC_INSTRUCTION_op_ext16u_i64: - case PTC_INSTRUCTION_op_ext32u_i64: - return v { Builder.CreateZExt(Truncated, RegisterType) }; - default: - llvm_unreachable("Unexpected opcode"); - } + case PTC_INSTRUCTION_op_ext32u_i64: { + Type *SourceType = nullptr; + switch (Opcode) { + case PTC_INSTRUCTION_op_ext8s_i32: + case PTC_INSTRUCTION_op_ext8u_i32: + case PTC_INSTRUCTION_op_ext8s_i64: + case PTC_INSTRUCTION_op_ext8u_i64: + SourceType = Builder.getInt8Ty(); + break; + case PTC_INSTRUCTION_op_ext16s_i32: + case PTC_INSTRUCTION_op_ext16u_i32: + case PTC_INSTRUCTION_op_ext16s_i64: + case PTC_INSTRUCTION_op_ext16u_i64: + SourceType = Builder.getInt16Ty(); + break; + case PTC_INSTRUCTION_op_ext32s_i64: + case PTC_INSTRUCTION_op_ext32u_i64: + SourceType = Builder.getInt32Ty(); + break; + default: + llvm_unreachable("Unexpected opcode"); } + + Value *Truncated = Builder.CreateTrunc(InArguments[0], SourceType); + + switch (Opcode) { + case PTC_INSTRUCTION_op_ext8s_i32: + case PTC_INSTRUCTION_op_ext8s_i64: + case PTC_INSTRUCTION_op_ext16s_i32: + case PTC_INSTRUCTION_op_ext16s_i64: + case PTC_INSTRUCTION_op_ext32s_i64: + return v{ Builder.CreateSExt(Truncated, RegisterType) }; + case PTC_INSTRUCTION_op_ext8u_i32: + case PTC_INSTRUCTION_op_ext8u_i64: + case PTC_INSTRUCTION_op_ext16u_i32: + case PTC_INSTRUCTION_op_ext16u_i64: + case PTC_INSTRUCTION_op_ext32u_i64: + return v{ Builder.CreateZExt(Truncated, RegisterType) }; + default: + llvm_unreachable("Unexpected opcode"); + } + } case PTC_INSTRUCTION_op_not_i32: case PTC_INSTRUCTION_op_not_i64: - return v { Builder.CreateXor(InArguments[0], getMaxValue(RegisterSize)) }; + return v{ Builder.CreateXor(InArguments[0], getMaxValue(RegisterSize)) }; case PTC_INSTRUCTION_op_neg_i32: - case PTC_INSTRUCTION_op_neg_i64: - { - auto *InitialValue = ConstantInt::get(RegisterType, 0); - return v { Builder.CreateSub(InitialValue, InArguments[0]) }; - } + case PTC_INSTRUCTION_op_neg_i64: { + auto *InitialValue = ConstantInt::get(RegisterType, 0); + return v{ Builder.CreateSub(InitialValue, InArguments[0]) }; + } case PTC_INSTRUCTION_op_andc_i32: case PTC_INSTRUCTION_op_andc_i64: case PTC_INSTRUCTION_op_orc_i32: case PTC_INSTRUCTION_op_orc_i64: case PTC_INSTRUCTION_op_eqv_i32: - case PTC_INSTRUCTION_op_eqv_i64: - { - Instruction::BinaryOps ExternalOp; - switch (Opcode) { - case PTC_INSTRUCTION_op_andc_i32: - case PTC_INSTRUCTION_op_andc_i64: - ExternalOp = Instruction::And; - break; - case PTC_INSTRUCTION_op_orc_i32: - case PTC_INSTRUCTION_op_orc_i64: - ExternalOp = Instruction::Or; - break; - case PTC_INSTRUCTION_op_eqv_i32: - case PTC_INSTRUCTION_op_eqv_i64: - ExternalOp = Instruction::Xor; - break; - default: - llvm_unreachable("Unexpected opcode"); - } + case PTC_INSTRUCTION_op_eqv_i64: { + Instruction::BinaryOps ExternalOp; + switch (Opcode) { + case PTC_INSTRUCTION_op_andc_i32: + case PTC_INSTRUCTION_op_andc_i64: + ExternalOp = Instruction::And; + break; + case PTC_INSTRUCTION_op_orc_i32: + case PTC_INSTRUCTION_op_orc_i64: + ExternalOp = Instruction::Or; + break; + case PTC_INSTRUCTION_op_eqv_i32: + case PTC_INSTRUCTION_op_eqv_i64: + ExternalOp = Instruction::Xor; + break; + default: + llvm_unreachable("Unexpected opcode"); + } - Value *Negate = Builder.CreateXor(InArguments[1], - getMaxValue(RegisterSize)); - Value *Result = Builder.CreateBinOp(ExternalOp, InArguments[0], Negate); - return v { Result }; - } + Value *Negate = Builder.CreateXor(InArguments[1], + getMaxValue(RegisterSize)); + Value *Result = Builder.CreateBinOp(ExternalOp, InArguments[0], Negate); + return v{ Result }; + } case PTC_INSTRUCTION_op_nand_i32: - case PTC_INSTRUCTION_op_nand_i64: - { - Value *AndValue = Builder.CreateAnd(InArguments[0], InArguments[1]); - Value *Result = Builder.CreateXor(AndValue, getMaxValue(RegisterSize)); - return v { Result }; - } + case PTC_INSTRUCTION_op_nand_i64: { + Value *AndValue = Builder.CreateAnd(InArguments[0], InArguments[1]); + Value *Result = Builder.CreateXor(AndValue, getMaxValue(RegisterSize)); + return v{ Result }; + } case PTC_INSTRUCTION_op_nor_i32: - case PTC_INSTRUCTION_op_nor_i64: - { - Value *OrValue = Builder.CreateOr(InArguments[0], InArguments[1]); - Value *Result = Builder.CreateXor(OrValue, getMaxValue(RegisterSize)); - return v { Result }; - } + case PTC_INSTRUCTION_op_nor_i64: { + Value *OrValue = Builder.CreateOr(InArguments[0], InArguments[1]); + Value *Result = Builder.CreateXor(OrValue, getMaxValue(RegisterSize)); + return v{ Result }; + } case PTC_INSTRUCTION_op_bswap16_i32: case PTC_INSTRUCTION_op_bswap32_i32: case PTC_INSTRUCTION_op_bswap16_i64: case PTC_INSTRUCTION_op_bswap32_i64: - case PTC_INSTRUCTION_op_bswap64_i64: - { - Type *SwapType = nullptr; - switch (Opcode) { - case PTC_INSTRUCTION_op_bswap16_i32: - case PTC_INSTRUCTION_op_bswap16_i64: - SwapType = Builder.getInt16Ty(); - break; - case PTC_INSTRUCTION_op_bswap32_i32: - case PTC_INSTRUCTION_op_bswap32_i64: - SwapType = Builder.getInt32Ty(); - break; - case PTC_INSTRUCTION_op_bswap64_i64: - SwapType = Builder.getInt64Ty(); - break; - default: - llvm_unreachable("Unexpected opcode"); - } - - Value *Truncated = Builder.CreateTrunc(InArguments[0], SwapType); - - Function *BSwapFunction = Intrinsic::getDeclaration(&TheModule, - Intrinsic::bswap, - { SwapType }); - Value *Swapped = Builder.CreateCall(BSwapFunction, Truncated); - - return v { Builder.CreateZExt(Swapped, RegisterType) }; + case PTC_INSTRUCTION_op_bswap64_i64: { + Type *SwapType = nullptr; + switch (Opcode) { + case PTC_INSTRUCTION_op_bswap16_i32: + case PTC_INSTRUCTION_op_bswap16_i64: + SwapType = Builder.getInt16Ty(); + break; + case PTC_INSTRUCTION_op_bswap32_i32: + case PTC_INSTRUCTION_op_bswap32_i64: + SwapType = Builder.getInt32Ty(); + break; + case PTC_INSTRUCTION_op_bswap64_i64: + SwapType = Builder.getInt64Ty(); + break; + default: + llvm_unreachable("Unexpected opcode"); } - case PTC_INSTRUCTION_op_set_label: - { - unsigned LabelId = ptc.get_arg_label_id(ConstArguments[0]); - std::stringstream LabelSS; - LabelSS << "bb." << JumpTargets.nameForAddress(LastPC); - LabelSS << "_L" << std::dec << LabelId; - std::string Label = LabelSS.str(); + Value *Truncated = Builder.CreateTrunc(InArguments[0], SwapType); - BasicBlock *Fallthrough = nullptr; - auto ExistingBasicBlock = LabeledBasicBlocks.find(Label); + Function *BSwapFunction = Intrinsic::getDeclaration(&TheModule, + Intrinsic::bswap, + { SwapType }); + Value *Swapped = Builder.CreateCall(BSwapFunction, Truncated); - if (ExistingBasicBlock == LabeledBasicBlocks.end()) { - Fallthrough = BasicBlock::Create(Context, Label, TheFunction); - Fallthrough->moveAfter(Builder.GetInsertBlock()); - LabeledBasicBlocks[Label] = Fallthrough; - } else { - // A basic block with that label already exist - Fallthrough = LabeledBasicBlocks[Label]; + return v{ Builder.CreateZExt(Swapped, RegisterType) }; + } + case PTC_INSTRUCTION_op_set_label: { + unsigned LabelId = ptc.get_arg_label_id(ConstArguments[0]); - // Ensure it's empty - assert(Fallthrough->begin() == Fallthrough->end()); + std::stringstream LabelSS; + LabelSS << "bb." << JumpTargets.nameForAddress(LastPC); + LabelSS << "_L" << std::dec << LabelId; + std::string Label = LabelSS.str(); - // Move it to the bottom - Fallthrough->removeFromParent(); - TheFunction->getBasicBlockList().push_back(Fallthrough); - } + BasicBlock *Fallthrough = nullptr; + auto ExistingBasicBlock = LabeledBasicBlocks.find(Label); - Builder.CreateBr(Fallthrough); + if (ExistingBasicBlock == LabeledBasicBlocks.end()) { + Fallthrough = BasicBlock::Create(Context, Label, TheFunction); + Fallthrough->moveAfter(Builder.GetInsertBlock()); + LabeledBasicBlocks[Label] = Fallthrough; + } else { + // A basic block with that label already exist + Fallthrough = LabeledBasicBlocks[Label]; - Blocks.push_back(Fallthrough); - Builder.SetInsertPoint(Fallthrough); - Variables.newBasicBlock(); + // Ensure it's empty + assert(Fallthrough->begin() == Fallthrough->end()); - return v { }; + // Move it to the bottom + Fallthrough->removeFromParent(); + TheFunction->getBasicBlockList().push_back(Fallthrough); } + + Builder.CreateBr(Fallthrough); + + Blocks.push_back(Fallthrough); + Builder.SetInsertPoint(Fallthrough); + Variables.newBasicBlock(); + + return v{}; + } case PTC_INSTRUCTION_op_br: case PTC_INSTRUCTION_op_brcond_i32: case PTC_INSTRUCTION_op_brcond2_i32: - case PTC_INSTRUCTION_op_brcond_i64: - { - // We take the last constant arguments, which is the LabelId both in - // conditional and unconditional jumps - unsigned LabelId = ptc.get_arg_label_id(ConstArguments.back()); + case PTC_INSTRUCTION_op_brcond_i64: { + // We take the last constant arguments, which is the LabelId both in + // conditional and unconditional jumps + unsigned LabelId = ptc.get_arg_label_id(ConstArguments.back()); - std::stringstream LabelSS; - LabelSS << "bb." << JumpTargets.nameForAddress(LastPC); - LabelSS << "_L" << std::dec << LabelId; - std::string Label = LabelSS.str(); + std::stringstream LabelSS; + LabelSS << "bb." << JumpTargets.nameForAddress(LastPC); + LabelSS << "_L" << std::dec << LabelId; + std::string Label = LabelSS.str(); - BasicBlock *Fallthrough = BasicBlock::Create(Context, - Label + "_ft", - TheFunction); + BasicBlock *Fallthrough = BasicBlock::Create(Context, + Label + "_ft", + TheFunction); - // Look for a matching label - BasicBlock *Target = nullptr; - auto ExistingBasicBlock = LabeledBasicBlocks.find(Label); + // Look for a matching label + BasicBlock *Target = nullptr; + auto ExistingBasicBlock = LabeledBasicBlocks.find(Label); - // No matching label, create a temporary block - if (ExistingBasicBlock == LabeledBasicBlocks.end()) { - Target = BasicBlock::Create(Context, Label, TheFunction); - LabeledBasicBlocks[Label] = Target; - } else { - Target = LabeledBasicBlocks[Label]; - } - - if (Opcode == PTC_INSTRUCTION_op_br) { - // Unconditional jump - Builder.CreateBr(Target); - } else if (Opcode == PTC_INSTRUCTION_op_brcond_i32 - || Opcode == PTC_INSTRUCTION_op_brcond_i64) { - // Conditional jump - Value *Compare = CreateICmp(Builder, - ConstArguments[0], - InArguments[0], - InArguments[1]); - Builder.CreateCondBr(Compare, Target, Fallthrough); - } else { - llvm_unreachable("Unhandled opcode"); - } - - Blocks.push_back(Fallthrough); - Builder.SetInsertPoint(Fallthrough); - Variables.newBasicBlock(); - - return v { }; + // No matching label, create a temporary block + if (ExistingBasicBlock == LabeledBasicBlocks.end()) { + Target = BasicBlock::Create(Context, Label, TheFunction); + LabeledBasicBlocks[Label] = Target; + } else { + Target = LabeledBasicBlocks[Label]; } - case PTC_INSTRUCTION_op_exit_tb: - { - auto *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); - Builder.CreateCall(JumpTargets.exitTB(), { Zero }); - Builder.CreateUnreachable(); - auto *NextBB = BasicBlock::Create(Context, "", TheFunction); - Blocks.push_back(NextBB); - Builder.SetInsertPoint(NextBB); - Variables.newBasicBlock(); - - return v { }; + if (Opcode == PTC_INSTRUCTION_op_br) { + // Unconditional jump + Builder.CreateBr(Target); + } else if (Opcode == PTC_INSTRUCTION_op_brcond_i32 + || Opcode == PTC_INSTRUCTION_op_brcond_i64) { + // Conditional jump + Value *Compare = CreateICmp(Builder, + ConstArguments[0], + InArguments[0], + InArguments[1]); + Builder.CreateCondBr(Compare, Target, Fallthrough); + } else { + llvm_unreachable("Unhandled opcode"); } + + Blocks.push_back(Fallthrough); + Builder.SetInsertPoint(Fallthrough); + Variables.newBasicBlock(); + + return v{}; + } + case PTC_INSTRUCTION_op_exit_tb: { + auto *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Builder.CreateCall(JumpTargets.exitTB(), { Zero }); + Builder.CreateUnreachable(); + + auto *NextBB = BasicBlock::Create(Context, "", TheFunction); + Blocks.push_back(NextBB); + Builder.SetInsertPoint(NextBB); + Variables.newBasicBlock(); + + return v{}; + } case PTC_INSTRUCTION_op_goto_tb: // Nothing to do here - return v { }; + return v{}; case PTC_INSTRUCTION_op_add2_i32: case PTC_INSTRUCTION_op_sub2_i32: case PTC_INSTRUCTION_op_add2_i64: - case PTC_INSTRUCTION_op_sub2_i64: - { - Value *FirstOpLow = nullptr; - Value *FirstOpHigh = nullptr; - Value *SecondOpLow = nullptr; - Value *SecondOpHigh = nullptr; + case PTC_INSTRUCTION_op_sub2_i64: { + Value *FirstOpLow = nullptr; + Value *FirstOpHigh = nullptr; + Value *SecondOpLow = nullptr; + Value *SecondOpHigh = nullptr; - IntegerType *DestinationType = Builder.getIntNTy(RegisterSize * 2); + IntegerType *DestinationType = Builder.getIntNTy(RegisterSize * 2); - FirstOpLow = Builder.CreateZExt(InArguments[0], DestinationType); - FirstOpHigh = Builder.CreateZExt(InArguments[1], DestinationType); - SecondOpLow = Builder.CreateZExt(InArguments[2], DestinationType); - SecondOpHigh = Builder.CreateZExt(InArguments[3], DestinationType); + FirstOpLow = Builder.CreateZExt(InArguments[0], DestinationType); + FirstOpHigh = Builder.CreateZExt(InArguments[1], DestinationType); + SecondOpLow = Builder.CreateZExt(InArguments[2], DestinationType); + SecondOpHigh = Builder.CreateZExt(InArguments[3], DestinationType); - FirstOpHigh = Builder.CreateShl(FirstOpHigh, RegisterSize); - SecondOpHigh = Builder.CreateShl(SecondOpHigh, RegisterSize); + FirstOpHigh = Builder.CreateShl(FirstOpHigh, RegisterSize); + SecondOpHigh = Builder.CreateShl(SecondOpHigh, RegisterSize); - Value *FirstOp = Builder.CreateOr(FirstOpHigh, FirstOpLow); - Value *SecondOp = Builder.CreateOr(SecondOpHigh, - SecondOpLow); + Value *FirstOp = Builder.CreateOr(FirstOpHigh, FirstOpLow); + Value *SecondOp = Builder.CreateOr(SecondOpHigh, SecondOpLow); - Instruction::BinaryOps BinaryOp = opcodeToBinaryOp(Opcode); + Instruction::BinaryOps BinaryOp = opcodeToBinaryOp(Opcode); - Value *Result = Builder.CreateBinOp(BinaryOp, FirstOp, SecondOp); + Value *Result = Builder.CreateBinOp(BinaryOp, FirstOp, SecondOp); - Value *ResultLow = Builder.CreateTrunc(Result, RegisterType); - Value *ShiftedResult = Builder.CreateLShr(Result, RegisterSize); - Value *ResultHigh = Builder.CreateTrunc(ShiftedResult, RegisterType); + Value *ResultLow = Builder.CreateTrunc(Result, RegisterType); + Value *ShiftedResult = Builder.CreateLShr(Result, RegisterSize); + Value *ResultHigh = Builder.CreateTrunc(ShiftedResult, RegisterType); - return v { ResultLow, ResultHigh }; - } + return v{ ResultLow, ResultHigh }; + } case PTC_INSTRUCTION_op_mulu2_i32: case PTC_INSTRUCTION_op_mulu2_i64: case PTC_INSTRUCTION_op_muls2_i32: - case PTC_INSTRUCTION_op_muls2_i64: - { - IntegerType *DestinationType = Builder.getIntNTy(RegisterSize * 2); + case PTC_INSTRUCTION_op_muls2_i64: { + IntegerType *DestinationType = Builder.getIntNTy(RegisterSize * 2); - Value *FirstOp = nullptr; - Value *SecondOp = nullptr; + Value *FirstOp = nullptr; + Value *SecondOp = nullptr; - if (Opcode == PTC_INSTRUCTION_op_mulu2_i32 - || Opcode == PTC_INSTRUCTION_op_mulu2_i64) { - FirstOp = Builder.CreateZExt(InArguments[0], DestinationType); - SecondOp = Builder.CreateZExt(InArguments[1], DestinationType); - } else if (Opcode == PTC_INSTRUCTION_op_muls2_i32 - || Opcode == PTC_INSTRUCTION_op_muls2_i64) { - FirstOp = Builder.CreateSExt(InArguments[0], DestinationType); - SecondOp = Builder.CreateSExt(InArguments[1], DestinationType); - } else { - llvm_unreachable("Unexpected opcode"); - } - - Value *Result = Builder.CreateMul(FirstOp, SecondOp); - - Value *ResultLow = Builder.CreateTrunc(Result, RegisterType); - Value *ShiftedResult = Builder.CreateLShr(Result, RegisterSize); - Value *ResultHigh = Builder.CreateTrunc(ShiftedResult, RegisterType); - - return v { ResultLow, ResultHigh }; + if (Opcode == PTC_INSTRUCTION_op_mulu2_i32 + || Opcode == PTC_INSTRUCTION_op_mulu2_i64) { + FirstOp = Builder.CreateZExt(InArguments[0], DestinationType); + SecondOp = Builder.CreateZExt(InArguments[1], DestinationType); + } else if (Opcode == PTC_INSTRUCTION_op_muls2_i32 + || Opcode == PTC_INSTRUCTION_op_muls2_i64) { + FirstOp = Builder.CreateSExt(InArguments[0], DestinationType); + SecondOp = Builder.CreateSExt(InArguments[1], DestinationType); + } else { + llvm_unreachable("Unexpected opcode"); } + + Value *Result = Builder.CreateMul(FirstOp, SecondOp); + + Value *ResultLow = Builder.CreateTrunc(Result, RegisterType); + Value *ShiftedResult = Builder.CreateLShr(Result, RegisterSize); + Value *ResultHigh = Builder.CreateTrunc(ShiftedResult, RegisterType); + + return v{ ResultLow, ResultHigh }; + } case PTC_INSTRUCTION_op_muluh_i32: case PTC_INSTRUCTION_op_mulsh_i32: case PTC_INSTRUCTION_op_muluh_i64: diff --git a/instructiontranslator.h b/instructiontranslator.h index ceec97025..8d1ed8dbf 100644 --- a/instructiontranslator.h +++ b/instructiontranslator.h @@ -16,9 +16,9 @@ #include "llvm/Support/ErrorOr.h" // Local includes -#include "revamb.h" -#include "ptcdump.h" #include "jumptargetmanager.h" +#include "ptcdump.h" +#include "revamb.h" // Forward declarations namespace llvm { @@ -27,7 +27,7 @@ class CallInst; class Function; class MDNode; class Module; -} +} // namespace llvm class JumpTargetManager; class VariableManager; @@ -46,9 +46,9 @@ public: /// further processing. /// \param SourceArchitecture the input architecture. /// \param TargetArchitecture the output architecture. - InstructionTranslator(llvm::IRBuilder<>& Builder, - VariableManager& Variables, - JumpTargetManager& JumpTargets, + InstructionTranslator(llvm::IRBuilder<> &Builder, + VariableManager &Variables, + JumpTargetManager &JumpTargets, std::vector Blocks, const Architecture &SourceArchitecture, const Architecture &TargetArchitecture); @@ -82,14 +82,12 @@ public: /// `uint64_t` representing the current and next PC. // TODO: rename to newPC // TODO: the signature of this function is ugly - std::tuple newInstruction(PTCInstruction *Instr, - PTCInstruction *Next, - uint64_t EndPC, - bool IsFirst, - bool ForceNew); + std::tuple + newInstruction(PTCInstruction *Instr, + PTCInstruction *Next, + uint64_t EndPC, + bool IsFirst, + bool ForceNew); /// \brief Translate an ordinary instruction /// @@ -98,9 +96,8 @@ public: /// \param NextPC the PC associated to instruction after \p Instr. /// /// \return see InstructionTranslator::TranslationResult. - TranslationResult translate(PTCInstruction *Instr, - uint64_t PC, - uint64_t NextPC); + TranslationResult + translate(PTCInstruction *Instr, uint64_t PC, uint64_t NextPC); /// \brief Translate a call to an helper /// @@ -129,10 +126,11 @@ private: translateOpcode(PTCOpcode Opcode, std::vector ConstArguments, std::vector InArguments); + private: - llvm::IRBuilder<>& Builder; - VariableManager& Variables; - JumpTargetManager& JumpTargets; + llvm::IRBuilder<> &Builder; + VariableManager &Variables; + JumpTargetManager &JumpTargets; std::map LabeledBasicBlocks; std::vector Blocks; llvm::Module &TheModule; diff --git a/ir-helpers.h b/ir-helpers.h index 34360aa2a..1914c3f67 100644 --- a/ir-helpers.h +++ b/ir-helpers.h @@ -6,8 +6,8 @@ // // Standard includes -#include #include +#include #include // LLVM includes @@ -35,8 +35,7 @@ inline bool contains(T Range, typename T::value_type V) { inline void purgeBranch(llvm::BasicBlock::iterator I) { auto *DeadBranch = llvm::dyn_cast(I); // We allow only a branch and nothing else - assert(DeadBranch != nullptr && - ++I == DeadBranch->getParent()->end()); + assert(DeadBranch != nullptr && ++I == DeadBranch->getParent()->end()); std::set Successors; for (unsigned C = 0; C < DeadBranch->getNumSuccessors(); C++) @@ -51,8 +50,8 @@ inline void purgeBranch(llvm::BasicBlock::iterator I) { BB->eraseFromParent(); } -inline llvm::ConstantInt *getConstValue(llvm::Constant *C, - const llvm::DataLayout &DL) { +inline llvm::ConstantInt * +getConstValue(llvm::Constant *C, const llvm::DataLayout &DL) { while (auto *Expr = llvm::dyn_cast(C)) { C = ConstantFoldConstantExpression(Expr, DL); @@ -71,19 +70,16 @@ inline llvm::ConstantInt *getConstValue(llvm::Constant *C, return Integer; } -inline uint64_t getSExtValue(llvm::Constant *C, - const llvm::DataLayout &DL){ +inline uint64_t getSExtValue(llvm::Constant *C, const llvm::DataLayout &DL) { return getConstValue(C, DL)->getSExtValue(); } -inline uint64_t getZExtValue(llvm::Constant *C, - const llvm::DataLayout &DL){ +inline uint64_t getZExtValue(llvm::Constant *C, const llvm::DataLayout &DL) { return getConstValue(C, DL)->getZExtValue(); } -inline uint64_t getExtValue(llvm::Constant *C, - bool Sign, - const llvm::DataLayout &DL){ +inline uint64_t +getExtValue(llvm::Constant *C, bool Sign, const llvm::DataLayout &DL) { if (Sign) return getSExtValue(C, DL); else @@ -131,7 +127,7 @@ inline std::tuple operandsByType(llvm::User *V) { for (llvm::Value *Op : V->operands()) if (!findOperand, 0, T...>(Op, Result)) - return std::tuple { }; + return std::tuple{}; return Result; } @@ -165,15 +161,15 @@ backward_range(llvm::Instruction *I) { template struct BlackListTraitBase { - BlackListTraitBase(C Obj) : Obj(Obj) { } + BlackListTraitBase(C Obj) : Obj(Obj) {} + protected: C Obj; }; /// \brief Trait to wrap an object of type C that can act as a blacklist for B template -struct BlackListTrait : BlackListTraitBase { -}; +struct BlackListTrait : BlackListTraitBase {}; template struct BlackListTrait : BlackListTraitBase { @@ -241,8 +237,7 @@ inline void visitSuccessors(llvm::Instruction *I, case Continue: if (!ExhaustOnly) { for (auto *Successor : successors(Range.begin()->getParent())) { - if (Visited.count(Successor) == 0 - && !BL.isBlacklisted(Successor)) { + if (Visited.count(Successor) == 0 && !BL.isBlacklisted(Successor)) { Visited.insert(Successor); Queue.push(make_range(Successor->begin(), Successor->end())); } @@ -345,7 +340,8 @@ inline std::string getName(const llvm::Instruction *I) { } else { const llvm::BasicBlock *Parent = I->getParent(); return getName(Parent) + ":" - + std::to_string(1 + std::distance(Parent->begin(), I->getIterator())); + + std::to_string(1 + + std::distance(Parent->begin(), I->getIterator())); } } @@ -425,8 +421,9 @@ inline const llvm::Module *getModule(const llvm::Value *I) { /// \brief Helper class to easily create and use LLVM metadata class QuickMetadata { public: - QuickMetadata(llvm::LLVMContext &Context) : C(Context), - Int32Ty(llvm::IntegerType::get(C, 32)) { } + QuickMetadata(llvm::LLVMContext &Context) : + C(Context), + Int32Ty(llvm::IntegerType::get(C, 32)) {} llvm::MDString *get(const char *String) { return llvm::MDString::get(C, String); @@ -441,17 +438,11 @@ public: return llvm::ConstantAsMetadata::get(Constant); } - llvm::MDTuple *tuple(const char *String) { - return tuple(get(String)); - } + llvm::MDTuple *tuple(const char *String) { return tuple(get(String)); } - llvm::MDTuple *tuple(llvm::StringRef String) { - return tuple(get(String)); - } + llvm::MDTuple *tuple(llvm::StringRef String) { return tuple(get(String)); } - llvm::MDTuple *tuple(uint32_t Integer) { - return tuple(get(Integer)); - } + llvm::MDTuple *tuple(uint32_t Integer) { return tuple(get(Integer)); } llvm::MDTuple *tuple(llvm::ArrayRef MDs) { return llvm::MDTuple::get(C, MDs); @@ -520,8 +511,7 @@ inline bool isFirst(T *I) { } /// \brief Check if among \p BB's predecessors there's \p Target -inline bool hasPredecessor(llvm::BasicBlock *BB, - llvm::BasicBlock *Target) { +inline bool hasPredecessor(llvm::BasicBlock *BB, llvm::BasicBlock *Target) { for (llvm::BasicBlock *Predecessor : predecessors(BB)) if (Predecessor == Target) return true; @@ -538,9 +528,7 @@ static std::array CastOpcodes = { // operand (recursively) inline const llvm::Value *skipCasts(const llvm::Value *V) { using namespace llvm; - while (isa(V) - or isa(V) - or isa(V) + while (isa(V) or isa(V) or isa(V) or (isa(V) and contains(CastOpcodes, cast(V)->getOpcode()))) V = cast(V)->getOperand(0); @@ -551,9 +539,7 @@ inline const llvm::Value *skipCasts(const llvm::Value *V) { // operand (recursively) inline llvm::Value *skipCasts(llvm::Value *V) { using namespace llvm; - while (isa(V) - or isa(V) - or isa(V) + while (isa(V) or isa(V) or isa(V) or (isa(V) and contains(CastOpcodes, cast(V)->getOpcode()))) V = cast(V)->getOperand(0); @@ -593,8 +579,7 @@ inline bool isCallToHelper(const llvm::Instruction *I) { return Callee != nullptr && Callee->getName().startswith("helper_"); } -inline llvm::CallInst *getCallTo(llvm::Instruction *I, - llvm::StringRef Name) { +inline llvm::CallInst *getCallTo(llvm::Instruction *I, llvm::StringRef Name) { if (isCallTo(I, Name)) return llvm::cast(I); else diff --git a/isolatefunctions.cpp b/isolatefunctions.cpp index 4f83e3c89..a3a200a83 100644 --- a/isolatefunctions.cpp +++ b/isolatefunctions.cpp @@ -27,7 +27,7 @@ class IsolateFunctionsImpl; // Define an alias for the data structure that will contain the LLVM functions using FunctionsMap = std::map; -typedef DenseMap ValueToValueMap; +typedef DenseMap ValueToValueMap; using IF = IsolateFunctions; using IFI = IsolateFunctionsImpl; @@ -41,24 +41,21 @@ public: Module *NewModule, GeneratedCodeBasicInfo &GCBI, ValueToValueMapTy &ModuleCloningVMap) : - RootFunction(RootFunction), - NewModule(NewModule), - GCBI(GCBI), - ModuleCloningVMap(ModuleCloningVMap), - Context(getContext(NewModule)), - PCBitSize(8 * GCBI.pcRegSize()) { - } + RootFunction(RootFunction), + NewModule(NewModule), + GCBI(GCBI), + ModuleCloningVMap(ModuleCloningVMap), + Context(getContext(NewModule)), + PCBitSize(8 * GCBI.pcRegSize()) {} void run(); private: - /// \brief Creates the call that simulates the throw of an exception void throwException(Reason Code, BasicBlock *BB, uint64_t AdditionalPC); /// \brief Instantiate a basic block that consists only of an exception throw - BasicBlock *createUnreachableBlock(StringRef Name, - Function *CurrentFunction); + BasicBlock *createUnreachableBlock(StringRef Name, Function *CurrentFunction); /// \brief Populate the @function_dispatcher, needed to handle the indirect /// function calls @@ -66,13 +63,11 @@ private: /// \brief Create the basic blocks that are hit on exit after an invoke /// instruction - BasicBlock *createInvokeReturnBlock(Function *Root, - BasicBlock *UnexpectedPC); + BasicBlock *createInvokeReturnBlock(Function *Root, BasicBlock *UnexpectedPC); /// \brief Create the basic blocks that represent the catch of the invoke /// instruction - BasicBlock *createCatchBlock(Function *Root, - BasicBlock *UnexpectedPC); + BasicBlock *createCatchBlock(Function *Root, BasicBlock *UnexpectedPC); /// \brief Replace the call to the @function_call marker with the actual call void replaceFunctionCall(BasicBlock *NewBB, @@ -151,29 +146,27 @@ void IFI::throwException(Reason Code, BasicBlock *BB, uint64_t AdditionalPC) { // Emit the call to exception_warning Builder.CreateCall(DebugException, - { - ReasonValue, + { ReasonValue, ConstantLastPC, ProgramCounter, - ConstantAdditionalPC - }, + ConstantAdditionalPC }, ""); // Emit the call to _Unwind_RaiseException Builder.CreateCall(RaiseException); } -BasicBlock *IFI::createUnreachableBlock(StringRef Name, - Function *CurrentFunction) { +BasicBlock * +IFI::createUnreachableBlock(StringRef Name, Function *CurrentFunction) { - // Create the basic block and add it in the function passed as parameter - BasicBlock* NewBB = BasicBlock::Create(Context, - Name, - CurrentFunction, - nullptr); + // Create the basic block and add it in the function passed as parameter + BasicBlock *NewBB = BasicBlock::Create(Context, + Name, + CurrentFunction, + nullptr); - throwException(StandardNonTranslatedBlock, NewBB, 0); - return NewBB; + throwException(StandardNonTranslatedBlock, NewBB, 0); + return NewBB; } void IFI::populateFunctionDispatcher() { @@ -218,8 +211,8 @@ void IFI::populateFunctionDispatcher() { } } -BasicBlock *IFI::createInvokeReturnBlock(Function *Root, - BasicBlock *UnexpectedPC) { +BasicBlock * +IFI::createInvokeReturnBlock(Function *Root, BasicBlock *UnexpectedPC) { // Create the first block BasicBlock *InvokeReturnBlock = BasicBlock::Create(Context, @@ -261,8 +254,7 @@ BasicBlock *IFI::createInvokeReturnBlock(Function *Root, return InvokeReturnBlock; } -BasicBlock *IFI::createCatchBlock(Function *Root, - BasicBlock *UnexpectedPC) { +BasicBlock *IFI::createCatchBlock(Function *Root, BasicBlock *UnexpectedPC) { // Create a basic block that represents the catch part of the exception BasicBlock *CatchBB = BasicBlock::Create(Context, @@ -277,7 +269,7 @@ BasicBlock *IFI::createCatchBlock(Function *Root, // Create the StructType necessary for the landingpad PointerType *RetTyPointerType = Type::getInt8PtrTy(Context); IntegerType *RetTyIntegerType = Type::getInt32Ty(Context); - std::vector InArgsType { RetTyPointerType, RetTyIntegerType }; + std::vector InArgsType{ RetTyPointerType, RetTyIntegerType }; StructType *RetTyStruct = StructType::create(Context, ArrayRef(InArgsType), "", @@ -300,7 +292,7 @@ void IFI::replaceFunctionCall(BasicBlock *NewBB, // Retrieve the called function and emit the call StringRef FunctionNameString; - if (BlockAddress *Callee = dyn_cast(Call->getOperand(0))){ + if (BlockAddress *Callee = dyn_cast(Call->getOperand(0))) { BasicBlock *CalleeEntry = Callee->getBasicBlock(); TerminatorInst *Terminator = CalleeEntry->getTerminator(); MDNode *Node = Terminator->getMetadata("func.entry"); @@ -390,9 +382,7 @@ bool IFI::cloneInstruction(BasicBlock *NewBB, // Function call handling CallInst *Call = cast(OldInstruction); - replaceFunctionCall(NewBB, - Call, - LocalVMap); + replaceFunctionCall(NewBB, Call, LocalVMap); // We return true if we emitted a function call to signal that we ended // the inspection of the current basic block and that we should exit from @@ -429,7 +419,7 @@ bool IFI::cloneInstruction(BasicBlock *NewBB, Function *OldFunction = Address->getFunction(); BasicBlock *OldBlock = Address->getBasicBlock(); Function *NewFunction = cast(LocalVMap[OldFunction]); - BasicBlock *NewBlock = cast(LocalVMap[OldBlock]); + BasicBlock *NewBlock = cast(LocalVMap[OldBlock]); BlockAddress *B = BlockAddress::get(NewFunction, NewBlock); CurrentUse.set(B); @@ -534,12 +524,10 @@ void IFI::run() { // Create the Arrayref necessary for the arguments of exception_warning auto *IntegerType = IntegerType::get(Context, PCBitSize); - std::vector ArgsType { - Type::getInt32Ty(Context), - IntegerType, - IntegerType, - IntegerType - }; + std::vector ArgsType{ Type::getInt32Ty(Context), + IntegerType, + IntegerType, + IntegerType }; // Declare the exception_warning function auto *DebugExceptionFT = FunctionType::get(Type::getVoidTy(Context), @@ -583,7 +571,6 @@ void IFI::run() { if (Value *SkippedCast = skipCasts(UserInstruction)) { FilteredUsers.insert(cast(SkippedCast)->getParent()); } - } for (BasicBlock *Parent : FilteredUsers) { UsedAllocas[Parent].push_back(Alloca); @@ -627,10 +614,10 @@ void IFI::run() { if (Functions.count(FunctionNameMD) == 0) { // Actual creation of an empty instance of a function - Function *Function = Function::Create(FT, - Function::ExternalLinkage, - FunctionNameString, - NewModule); + Function *Function = Function::Create(FT, + Function::ExternalLinkage, + FunctionNameString, + NewModule); Functions[FunctionNameMD] = Function; FunctionsPC[Function] = getBasicBlockPC(&BB); @@ -672,7 +659,7 @@ void IFI::run() { // function, preserving the original name. We need to take care that if // we are examining a basic block that is the entry point of a function // we need to place it in the as the first block of the function. - BasicBlock* NewBB; + BasicBlock *NewBB; if (Terminator->getMetadata("func.entry") && !ParentFunction->empty()) { NewBB = BasicBlock::Create(Context, BB.getName(), @@ -712,8 +699,8 @@ void IFI::run() { // instruction that has the role of preserving the actual shape of the // function control flow. This will be helpful in order to traverse the // BBs in reverse post-order. - BasicBlock* UnexpectedPC = nullptr; - BasicBlock* AnyPC = nullptr; + BasicBlock *UnexpectedPC = nullptr; + BasicBlock *AnyPC = nullptr; for (BasicBlock &NewBB : *AnalyzedFunction) { @@ -742,8 +729,7 @@ void IFI::run() { if (GCBI.getType(Successor) == AnyPCBlock) { // Check if it already exists and create an anypc block if (AnyPC == nullptr) { - AnyPC = createUnreachableBlock("anypc", - AnalyzedFunction); + AnyPC = createUnreachableBlock("anypc", AnalyzedFunction); LocalVMap[Successor] = AnyPC; NewToOldBBMap[AnyPC] = Successor; } @@ -786,7 +772,7 @@ void IFI::run() { Builder.SetInsertPoint(&NewBB); // Handle the degenerate case in which we didn't identified successors - if(Successors.size() == 0) { + if (Successors.size() == 0) { Builder.CreateUnreachable(); } else { @@ -868,9 +854,7 @@ void IFI::run() { // Actual copy of the instructions for (Instruction &OldInstruction : *OldBB) { - bool IsCall = cloneInstruction(NewBB, - &OldInstruction, - LocalVMap); + bool IsCall = cloneInstruction(NewBB, &OldInstruction, LocalVMap); // If the cloneInstruction function returns true it means that we // emitted a function call and also the branch to the fallthrough block, @@ -954,7 +938,6 @@ void IFI::run() { // verifyModule pass raw_os_ostream Stream(dbg); assert(verifyModule(*NewModule, &Stream) == false); - } bool IF::runOnFunction(Function &F) { diff --git a/isolatefunctions.h b/isolatefunctions.h index 305532524..46c2ba6fa 100644 --- a/isolatefunctions.h +++ b/isolatefunctions.h @@ -19,7 +19,7 @@ public: static char ID; public: - IsolateFunctions() : FunctionPass(ID) { } + IsolateFunctions() : FunctionPass(ID) {} bool runOnFunction(llvm::Function &F) override; diff --git a/iteratorwrapper.h b/iteratorwrapper.h index fea21c1f1..378d49e6a 100644 --- a/iteratorwrapper.h +++ b/iteratorwrapper.h @@ -9,9 +9,9 @@ #include template -class IteratorWrapper : - public std::iterator { +class IteratorWrapper + : public std::iterator { private: using type = IteratorWrapper; @@ -22,93 +22,68 @@ public: using difference_type = typename Wrapped::difference_type; using reference = typename Wrapped::reference; using pointer = typename Wrapped::pointer; -public: - IteratorWrapper(Wrapped Iterator) : Iterator(Iterator) { } - type& operator=(const type& r) { +public: + IteratorWrapper(Wrapped Iterator) : Iterator(Iterator) {} + + type &operator=(const type &r) { Iterator = r.Iterator; return *this; } - type& operator++() { + type &operator++() { ++Iterator; return *this; } - type& operator--() { + type &operator--() { --Iterator; return *this; } - type operator++(int) { - return type(Iterator++); - } + type operator++(int) { return type(Iterator++); } - type operator--(int) { - return type(Iterator--); - } + type operator--(int) { return type(Iterator--); } - type operator+(const difference_type& n) const { - return type(Iterator + n); - } + type operator+(const difference_type &n) const { return type(Iterator + n); } - type& operator+=(difference_type n) { + type &operator+=(difference_type n) { Iterator += n; return *this; } - type operator-(const difference_type& n) const { - return type(Iterator - n); - } + type operator-(const difference_type &n) const { return type(Iterator - n); } - type& operator-=(const difference_type& n) { + type &operator-=(const difference_type &n) { Iterator -= n; return *this; } - reference operator*() const { - return *Iterator; - } + reference operator*() const { return *Iterator; } - pointer operator->() const { - return Iterator.operator->(); - } + pointer operator->() const { return Iterator.operator->(); } - reference operator[](const difference_type& n) const { - return Iterator[n]; - } + reference operator[](const difference_type &n) const { return Iterator[n]; } - bool operator==(const type& r2) const { - return Iterator == r2.Iterator; - } + bool operator==(const type &r2) const { return Iterator == r2.Iterator; } - bool operator!=(const type& r2) { - return Iterator != r2.Iterator; - } + bool operator!=(const type &r2) { return Iterator != r2.Iterator; } - bool operator<(const type& r2) { - return Iterator < r2.Iterator; - } + bool operator<(const type &r2) { return Iterator < r2.Iterator; } - bool operator>(const type& r2) { - return Iterator > r2.Iterator; - } + bool operator>(const type &r2) { return Iterator > r2.Iterator; } - bool operator<=(const type& r2) { - return Iterator <= r2.Iterator; - } + bool operator<=(const type &r2) { return Iterator <= r2.Iterator; } - bool operator>=(const type& r2) { - return Iterator >= r2.Iterator; - } + bool operator>=(const type &r2) { return Iterator >= r2.Iterator; } template - type operator+(const IteratorWrapper& r2) { + type operator+(const IteratorWrapper &r2) { return type(Iterator + r2.Iterator); } template - difference_type operator-(const IteratorWrapper& r2) { + difference_type operator-(const IteratorWrapper &r2) { return Iterator - r2.Iterator; } diff --git a/jumptargetmanager.cpp b/jumptargetmanager.cpp index 334e6ca2a..3636fa995 100644 --- a/jumptargetmanager.cpp +++ b/jumptargetmanager.cpp @@ -16,8 +16,8 @@ // Boost includes #include -#include #include +#include // LLVM includes #include "llvm/ADT/Optional.h" @@ -84,7 +84,7 @@ bool TranslateDirectBranchesPass::pinJTs(Function &F) { LLVMContext &Context = getContext(&F); Value *PCReg = JTM->pcReg(); auto *RegType = cast(PCReg->getType()->getPointerElementType()); - auto C = [RegType] (uint64_t A) { return ConstantInt::get(RegType, A); }; + auto C = [RegType](uint64_t A) { return ConstantInt::get(RegType, A); }; BasicBlock *AnyPC = JTM->anyPC(); BasicBlock *UnexpectedPC = JTM->unexpectedPC(); // TODO: enforce CFG @@ -207,7 +207,7 @@ bool TranslateDirectBranchesPass::pinConstantStore(Function &F) { } else { // We're jumping to an invalid location, abort everything // TODO: emit a warning - CallInst::Create(F.getParent()->getFunction("abort"), { }, Call); + CallInst::Create(F.getParent()->getFunction("abort"), {}, Call); new UnreachableInst(Context, Call); } Call->eraseFromParent(); @@ -267,7 +267,6 @@ bool TranslateDirectBranchesPass::forceFallthroughAfterHelper(CallInst *Call) { return false; } } - } exitTBCleanup(Call); @@ -294,7 +293,7 @@ bool TranslateDirectBranchesPass::runOnFunction(Function &F) { } uint64_t TranslateDirectBranchesPass::getNextPC(Instruction *TheInstruction) { - DominatorTree& DT = getAnalysis().getDomTree(); + DominatorTree &DT = getAnalysis().getDomTree(); BasicBlock *Block = TheInstruction->getParent(); BasicBlock::reverse_iterator It(make_reverse_iterator(TheInstruction)); @@ -318,8 +317,8 @@ uint64_t TranslateDirectBranchesPass::getNextPC(Instruction *TheInstruction) { } auto *Node = DT.getNode(Block); - assert(Node != nullptr && - "BasicBlock not in the dominator tree, is it reachable?" ); + assert(Node != nullptr + && "BasicBlock not in the dominator tree, is it reachable?"); Block = Node->getIDom()->getBlock(); It = Block->rbegin(); @@ -357,8 +356,8 @@ JumpTargetManager::readRawValue(uint64_t Address, uint64_t Offset = Address - Segment.StartVirtualAddress; const unsigned char *Start = RawDataPtr + Offset; - using support::endian::read; using support::endianness; + using support::endian::read; switch (Size) { case 1: return read(Start); @@ -425,8 +424,8 @@ ConstantInt *JumpTargetManager::readConstantInt(Constant *ConstantAddress, } template -static cl::opt *getOption(StringMap& Options, - const char *Name) { +static cl::opt * +getOption(StringMap &Options, const char *Name) { return static_cast *>(Options[Name]); } @@ -459,7 +458,7 @@ JumpTargetManager::JumpTargetManager(Function *TheFunction, initializeSymbolMap(); // Configure GlobalValueNumbering - StringMap& Options(cl::getRegisteredOptions()); + StringMap &Options(cl::getRegisteredOptions()); getOption(Options, "enable-load-pre")->setInitialValue(false); getOption(Options, "memdep-block-scan-limit")->setInitialValue(100); // getOption(Options, "enable-pre")->setInitialValue(false); @@ -475,8 +474,7 @@ void JumpTargetManager::initializeSymbolMap() { for (const SymbolInfo &Symbol : Binary.symbols()) { // Discard symbols pointing to 0, with zero-sized names or present multiple // times. Note that we keep zero-size symbols. - if (Symbol.Address == 0 - || Symbol.Name.size() == 0 + if (Symbol.Address == 0 || Symbol.Name.size() == 0 || SeenCount[std::string(Symbol.Name)] > 1) continue; @@ -484,7 +482,7 @@ void JumpTargetManager::initializeSymbolMap() { unsigned Size = std::max(1UL, Symbol.Size); auto NewInterval = interval::right_open(Symbol.Address, Symbol.Address + Size); - SymbolMap += make_pair(NewInterval, SymbolInfoSet { &Symbol }); + SymbolMap += make_pair(NewInterval, SymbolInfoSet{ &Symbol }); } } @@ -531,7 +529,7 @@ void JumpTargetManager::harvestGlobalData() { for (uint64_t CodePointer : Binary.codePointers()) registerJT(CodePointer, JTReason::GlobalData); - for (auto& Segment : Binary.segments()) { + for (auto &Segment : Binary.segments()) { const Constant *Initializer = Segment.Variable->getInitializer(); if (isa(Initializer)) continue; @@ -563,21 +561,19 @@ void JumpTargetManager::harvestGlobalData() { } } - DBG("jtcount", dbg - << "JumpTargets found in global data: " << std::dec - << Unexplored.size() << "\n"); + DBG("jtcount", + dbg << "JumpTargets found in global data: " << std::dec + << Unexplored.size() << "\n"); } template void JumpTargetManager::findCodePointers(uint64_t StartVirtualAddress, const unsigned char *Start, const unsigned char *End) { - using support::endian::read; using support::endianness; + using support::endian::read; for (auto Pos = Start; Pos < End - sizeof(value_type); Pos++) { - uint64_t Value = read(endian), - 1>(Pos); + uint64_t Value = read(endian), 1>(Pos); BasicBlock *Result = registerJT(Value, JTReason::GlobalData); if (Result != nullptr) @@ -597,7 +593,7 @@ void JumpTargetManager::findCodePointers(uint64_t StartVirtualAddress, /// \return the basic block to use from now on, or null if the program counter /// is not associated to a basic block. // TODO: make this return a pair -BasicBlock *JumpTargetManager::newPC(uint64_t PC, bool& ShouldContinue) { +BasicBlock *JumpTargetManager::newPC(uint64_t PC, bool &ShouldContinue) { // Did we already meet this PC? auto JTIt = JumpTargets.find(PC); if (JTIt != JumpTargets.end()) { @@ -613,7 +609,6 @@ BasicBlock *JumpTargetManager::newPC(uint64_t PC, bool& ShouldContinue) { assert(Result->empty()); return Result; } - } // It wasn't planned to visit it, so we've already been there, just jump @@ -698,7 +693,6 @@ StoreInst *JumpTargetManager::getPrevPCWrite(Instruction *TheInstruction) { return nullptr; } - // TODO: this is outdated and we should drop it, we now have OSRA and friends /// \brief Tries to detect pc += register In general, we assume what we're /// translating is code emitted by a compiler. This means that usually all the @@ -759,7 +753,7 @@ static bool isSumJump(StoreInst *PCWrite) { case Instruction::LShr: case Instruction::AShr: case Instruction::And: - for (auto& Operand : BinOp->operands()) + for (auto &Operand : BinOp->operands()) if (!isa(Operand.get())) WorkList.push(Operand.get()); break; @@ -828,7 +822,6 @@ JumpTargetManager::getPC(Instruction *TheInstruction) const { } } } - } // Couldn't find the current PC @@ -887,7 +880,6 @@ void JumpTargetManager::handleSumJump(Instruction *SumJump) { // We've found an unparsed indirect jump return; } - } // Proceed to next instruction @@ -898,7 +890,6 @@ void JumpTargetManager::handleSumJump(Instruction *SumJump) { for (BasicBlock *Successor : successors(BB)) if (Visited.find(Successor) == Visited.end()) WorkList.push(Successor); - } } @@ -909,7 +900,7 @@ public: Dispatcher(Dispatcher), JumpTargetIndex(0), JumpTargetsCount(Dispatcher->getNumSuccessors()), - DL(Dispatcher->getParent()->getParent()->getParent()->getDataLayout()) { } + DL(Dispatcher->getParent()->getParent()->getParent()->getDataLayout()) {} void enqueue(BasicBlock *BB) { if (Visited.count(BB)) @@ -975,7 +966,7 @@ void JumpTargetManager::translateIndirectJumps() { auto I = ExitTB->use_begin(); while (I != ExitTB->use_end()) { - Use& ExitTBUse = *I++; + Use &ExitTBUse = *I++; if (auto *Call = dyn_cast(ExitTBUse.getUser())) { if (Call->getCalledFunction() == ExitTB) { @@ -1033,8 +1024,7 @@ void JumpTargetManager::unvisit(BasicBlock *BB) { Visited.erase(Current); for (BasicBlock *Successor : successors(BB)) { - if (Visited.find(Successor) != Visited.end() - && !Successor->empty()) { + if (Visited.find(Successor) != Visited.end() && !Successor->empty()) { auto *Call = dyn_cast(&*Successor->begin()); if (Call == nullptr || Call->getCalledFunction()->getName() != "newpc") { @@ -1060,8 +1050,7 @@ void JumpTargetManager::purgeTranslation(BasicBlock *Start) { while (!Queue.empty()) { BasicBlock *BB = Queue.pop(); for (BasicBlock *Successor : successors(BB)) { - if (isTranslatedBB(Successor) - && !isJumpTarget(Successor) + if (isTranslatedBB(Successor) && !isJumpTarget(Successor) && !hasPredecessor(Successor, Dispatcher)) { Queue.insert(Successor); } @@ -1186,7 +1175,7 @@ void JumpTargetManager::createDispatcher(Function *OutputFunction, Builder.SetInsertPoint(DispatcherFail); Module *TheModule = TheFunction->getParent(); - auto *UnknownPCTy = FunctionType::get(Type::getVoidTy(Context), { }, false); + auto *UnknownPCTy = FunctionType::get(Type::getVoidTy(Context), {}, false); Constant *UnknownPC = TheModule->getOrInsertFunction("unknownPC", UnknownPCTy); Builder.CreateCall(cast(UnknownPC)); @@ -1299,7 +1288,6 @@ void JumpTargetManager::rebuildDispatcher() { BasicBlock *BB = P.second.head(); if (CurrentCFGForm == SemanticPreservingCFG || !hasPredecessors(BB)) DispatcherSwitch->addCase(ConstantInt::get(SwitchType, PC), BB); - } } @@ -1361,9 +1349,9 @@ void JumpTargetManager::harvest() { // Restore the CFG setCFGForm(SemanticPreservingCFG); - DBG("jtcount", dbg << std::dec - << Unexplored.size() << " new jump targets and " - << NewBranches << " new branches were found\n"); + DBG("jtcount", + dbg << std::dec << Unexplored.size() << " new jump targets and " + << NewBranches << " new branches were found\n"); } if (EnableOSRA && empty()) { @@ -1400,17 +1388,16 @@ void JumpTargetManager::harvest() { // Restore the CFG setCFGForm(SemanticPreservingCFG); - DBG("jtcount", dbg << std::dec - << Unexplored.size() << " new jump targets and " - << NewBranches << " new branches were found\n"); + DBG("jtcount", + dbg << std::dec << Unexplored.size() << " new jump targets and " + << NewBranches << " new branches were found\n"); } while (empty() && NewBranches > 0); } if (empty()) { - DBG("jtcount", dbg<< "We're done looking for jump targets\n"); + DBG("jtcount", dbg << "We're done looking for jump targets\n"); } - } using BlockWithAddress = JumpTargetManager::BlockWithAddress; diff --git a/jumptargetmanager.h b/jumptargetmanager.h index e0e20b499..1fb93c0a6 100644 --- a/jumptargetmanager.h +++ b/jumptargetmanager.h @@ -12,8 +12,8 @@ #include // Boost includes -#include #include +#include #include // LLVM includes @@ -37,23 +37,24 @@ class Module; class SwitchInst; class StoreInst; class Value; -} +} // namespace llvm class JumpTargetManager; -template typename Map::const_iterator - containing(Map const& m, typename Map::key_type const& k) { +template +typename Map::const_iterator +containing(Map const &m, typename Map::key_type const &k) { typename Map::const_iterator it = m.upper_bound(k); - if(it != m.begin()) { + if (it != m.begin()) { return --it; } return m.end(); } -template typename Map::iterator - containing(Map & m, typename Map::key_type const& k) { +template +typename Map::iterator containing(Map &m, typename Map::key_type const &k) { typename Map::iterator it = m.upper_bound(k); - if(it != m.begin()) { + if (it != m.begin()) { return --it; } return m.end(); @@ -70,12 +71,11 @@ class TranslateDirectBranchesPass : public llvm::FunctionPass { public: static char ID; - TranslateDirectBranchesPass() : llvm::FunctionPass(ID), - JTM(nullptr) { } + TranslateDirectBranchesPass() : llvm::FunctionPass(ID), JTM(nullptr) {} TranslateDirectBranchesPass(JumpTargetManager *JTM) : FunctionPass(ID), - JTM(JTM) { } + JTM(JTM) {} void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; @@ -115,8 +115,8 @@ public: class JumpTarget { public: - JumpTarget() : BB(nullptr), Reasons(0) { } - JumpTarget(llvm::BasicBlock *BB) : BB(BB), Reasons(0) { } + JumpTarget() : BB(nullptr), Reasons(0) {} + JumpTarget(llvm::BasicBlock *BB) : BB(BB), Reasons(0) {} JumpTarget(llvm::BasicBlock *BB, JTReason::Values Reason) : BB(BB), Reasons(static_cast(Reason)) {} @@ -208,7 +208,7 @@ public: /// \return the basic block to use from now on, or `nullptr` if the program /// counter is not associated to a basic block. // TODO: return pair - llvm::BasicBlock *newPC(uint64_t PC, bool& ShouldContinue); + llvm::BasicBlock *newPC(uint64_t PC, bool &ShouldContinue); /// \brief Save the PC-Instruction association for future use void registerInstruction(uint64_t PC, llvm::Instruction *Instruction); @@ -246,8 +246,8 @@ public: /// executable segment bool isExecutableRange(uint64_t Start, uint64_t End) const { for (std::pair Range : ExecutableRanges) - if (Range.first <= Start && Start < Range.second - && Range.first <= End && End < Range.second) + if (Range.first <= Start && Start < Range.second && Range.first <= End + && End < Range.second) return true; return false; } @@ -265,9 +265,7 @@ public: } /// \brief Return true if the given PC is a jump target - bool isJumpTarget(uint64_t PC) const { - return JumpTargets.count(PC); - } + bool isJumpTarget(uint64_t PC) const { return JumpTargets.count(PC); } /// \brief Return true if the given basic block corresponds to a jump target bool isJumpTarget(llvm::BasicBlock *BB) { @@ -337,10 +335,8 @@ public: /// \brief Checks if \p BB is a basic block generated during translation bool isTranslatedBB(llvm::BasicBlock *BB) const { - return BB != anyPC() - && BB != unexpectedPC() - && BB != dispatcher() - && BB != dispatcherFail(); + return BB != anyPC() && BB != unexpectedPC() && BB != dispatcher() + && BB != dispatcherFail(); } /// \brief Return the dispatcher basic block. @@ -377,11 +373,7 @@ public: return Pair.first + Pair.second; } - enum Endianess { - OriginalEndianess, - DestinationEndianess - }; - + enum Endianess { OriginalEndianess, DestinationEndianess }; /// \brief Read an integer number from a segment /// @@ -401,9 +393,8 @@ public: llvm::Type *PointerTy, Endianess ReadEndianess); - llvm::Optional readRawValue(uint64_t Address, - unsigned Size, - Endianess ReadEndianess) const; + llvm::Optional + readRawValue(uint64_t Address, unsigned Size, Endianess ReadEndianess) const; /// \brief Increment the counter of emitted branches since the last reset void newBranch() { NewBranches++; } @@ -460,8 +451,7 @@ public: // TODO: can we drop this in favor of GeneratedCodeBasicInfo::isJump? bool isJump(llvm::TerminatorInst *T) const { for (llvm::BasicBlock *Successor : T->successors()) { - if (!(Successor == Dispatcher - || Successor == DispatcherFail + if (!(Successor == Dispatcher || Successor == DispatcherFail || isJumpTarget(getBasicBlockPC(Successor)))) return false; } @@ -484,7 +474,6 @@ public: std::string nameForAddress(uint64_t Address) const; private: - /// \brief Translate the non-constant jumps into jumps to the dispatcher void translateIndirectJumps(); @@ -532,8 +521,8 @@ private: // TODO: instead of a gigantic switch case we could map the original memory // area and write the address of the translated basic block at the jump // target - void createDispatcher(llvm::Function *OutputFunction, - llvm::Value *SwitchOnPtr); + void + createDispatcher(llvm::Function *OutputFunction, llvm::Value *SwitchOnPtr); template void findCodePointers(uint64_t StartVirtualAddress, @@ -550,7 +539,7 @@ private: llvm::Module &TheModule; llvm::LLVMContext &Context; - llvm::Function* TheFunction; + llvm::Function *TheFunction; /// Holds the association between a PC and the last generated instruction for /// the previous instruction. InstructionMap OriginalInstructionAddresses; @@ -585,16 +574,15 @@ private: }; template<> -struct BlackListTrait : - BlackListTraitBase { +struct BlackListTrait + : BlackListTraitBase { using BlackListTraitBase::BlackListTraitBase; bool isBlacklisted(llvm::BasicBlock *Value) { return !this->Obj.isTranslatedBB(Value); } }; -inline -BlackListTrait +inline BlackListTrait make_blacklist(const JumpTargetManager &JTM) { return BlackListTrait(JTM); } diff --git a/lazysmallbitvector.h b/lazysmallbitvector.h index 8dfb25662..5d60fd443 100644 --- a/lazysmallbitvector.h +++ b/lazysmallbitvector.h @@ -51,14 +51,20 @@ using enable_if_long = enable_if_either; template using enable_if_long_long = enable_if_either; -template inline -unsigned findFirstBit(enable_if_int Value) { return ffs(Value); } +template +inline unsigned findFirstBit(enable_if_int Value) { + return ffs(Value); +} -template inline -unsigned findFirstBit(enable_if_long Value) { return ffsl(Value); } +template +inline unsigned findFirstBit(enable_if_long Value) { + return ffsl(Value); +} -template inline -unsigned findFirstBit(enable_if_long_long Value) { return ffsll(Value); } +template +inline unsigned findFirstBit(enable_if_long_long Value) { + return ffsll(Value); +} template inline unsigned findFirstBit(T Value) { @@ -73,14 +79,13 @@ inline T excessDivide(T A, unsigned B) { class LazySmallBitVector; template -class LazySmallBitVectorIterator : - public boost::iterator_facade, - unsigned, - boost::forward_traversal_tag, - unsigned> -{ +class LazySmallBitVectorIterator + : public boost::iterator_facade, + unsigned, + boost::forward_traversal_tag, + unsigned> { public: - LazySmallBitVectorIterator() : BitVector(nullptr), NextBitIndex(0) { } + LazySmallBitVectorIterator() : BitVector(nullptr), NextBitIndex(0) {} LazySmallBitVectorIterator(LSBV *BitVector); LazySmallBitVectorIterator(LSBV *BitVector, unsigned Index); @@ -112,7 +117,6 @@ public: typedef bool value_type; private: - static const unsigned BitsPerPointer = sizeof(uintptr_t) * CHAR_BIT; static const unsigned MaxSmallSize = BitsPerPointer - 1; static const uintptr_t One = 1; @@ -144,17 +148,11 @@ private: memset(&at(From), 0, Count * sizeof(uintptr_t)); } - void zero(size_t From) { - zero(From, wordCount()); - } + void zero(size_t From) { zero(From, wordCount()); } - void zero() { - zero(0); - } + void zero() { zero(0); } - void setCapacity(size_t Count) { - Capacity = Count; - } + void setCapacity(size_t Count) { Capacity = Count; } LargeStorage &operator=(const LargeStorage &Other) { assert(Capacity >= Other.Capacity); @@ -168,7 +166,7 @@ private: }; public: - LazySmallBitVector() : Storage(1) { } + LazySmallBitVector() : Storage(1) {} LazySmallBitVector(const LazySmallBitVector &Other) : Storage(1) { *this = Other; @@ -243,13 +241,9 @@ public: } } - void zero(size_t From) { - zero(From, capacity() - From); - } + void zero(size_t From) { zero(From, capacity() - From); } - void zero() { - zero(0); - } + void zero() { zero(0); } bool operator[](unsigned Index) const { if (Index >= capacity()) @@ -276,9 +270,7 @@ public: } } - bool isZero() const { - return requiredBits() == 0; - } + bool isZero() const { return requiredBits() == 0; } LazySmallBitVector &operator=(const LazySmallBitVector &Other) { if (!(Other.isSmall() || Other.capacity() > 63)) @@ -451,7 +443,6 @@ public: unsigned Max = std::min(OtherPointersCount, ThisPointersCount); for (unsigned I = 0; I < Max; I++) Large.at(I) = Large.at(I) & OtherLarge.at(I); - } } @@ -477,11 +468,11 @@ public: unsigned SourceIndex = Amount / BitsPerPointer; unsigned Count = Large.wordCount() - SourceIndex; - auto Destination = [&Large] (unsigned I) -> uintptr_t & { + auto Destination = [&Large](unsigned I) -> uintptr_t & { return Large.at(I); }; - auto Source = [SourceIndex, &Large] (unsigned I) -> uintptr_t & { + auto Source = [SourceIndex, &Large](unsigned I) -> uintptr_t & { return Large.at(SourceIndex + I); }; @@ -518,7 +509,6 @@ public: // We have to enlarge alloc(NewSize); } - } LargeStorage &Large = getLarge(); @@ -535,11 +525,11 @@ public: LargeStorage &NewLarge = getLarge(); unsigned ToSkip = Amount / BitsPerPointer; - auto Destination = [ToSkip, &NewLarge] (unsigned I) -> uintptr_t & { + auto Destination = [ToSkip, &NewLarge](unsigned I) -> uintptr_t & { return NewLarge.at(ToSkip + I); }; - auto Source = [&NewLarge] (unsigned I) -> uintptr_t & { + auto Source = [&NewLarge](unsigned I) -> uintptr_t & { return NewLarge.at(I); }; @@ -579,11 +569,10 @@ public: Index++; if (Index * BitsPerPointer >= capacity()) return 0; - } while(Large.at(Index) == 0); + } while (Large.at(Index) == 0); return Index * BitsPerPointer + findFirstBit(Large.at(Index)); } - } const_iterator begin() const { return const_iterator(this); } @@ -681,8 +670,9 @@ inline void LazySmallBitVectorIterator::increment() { #define LSBVI LazySmallBitVectorIterator template -inline -LSBVI::LSBVI(LSBV *BitVector) : BitVector(BitVector), NextBitIndex(0) { +inline LSBVI::LSBVI(LSBV *BitVector) : + BitVector(BitVector), + NextBitIndex(0) { assert(BitVector != nullptr); if (!BitVector->isZero()) @@ -690,8 +680,7 @@ LSBVI::LSBVI(LSBV *BitVector) : BitVector(BitVector), NextBitIndex(0) { } template -inline -LSBVI::LSBVI(LSBV *BitVector, unsigned Index) : +inline LSBVI::LSBVI(LSBV *BitVector, unsigned Index) : BitVector(BitVector), NextBitIndex(Index) { assert(BitVector != nullptr); diff --git a/lib/StackAnalysis/asslot.h b/lib/StackAnalysis/asslot.h index 0e46eae89..35ea210f6 100644 --- a/lib/StackAnalysis/asslot.h +++ b/lib/StackAnalysis/asslot.h @@ -62,9 +62,7 @@ private: }; public: - explicit ASID(uint32_t ID) : ID(ID) { - assert(ID < LastID); - } + explicit ASID(uint32_t ID) : ID(ID) { assert(ID < LastID); } // Factory methods static ASID invalidID() { return ASID(InvalidID); } @@ -77,7 +75,7 @@ public: bool operator<(const ASID &Other) const { return ID < Other.ID; } bool operator==(const ASID &Other) const { return ID == Other.ID; } - bool operator!=(const ASID &Other) const { return not (*this == Other); } + bool operator!=(const ASID &Other) const { return not(*this == Other); } size_t hash() const; @@ -115,7 +113,6 @@ public: bool isStack() const { return ID == LastStackID; } bool isValid() const { return ID != InvalidID; } - }; /// \brief Class representing the address of an address space slot diff --git a/lib/StackAnalysis/cache.cpp b/lib/StackAnalysis/cache.cpp index 55dbc5646..57642d8bd 100644 --- a/lib/StackAnalysis/cache.cpp +++ b/lib/StackAnalysis/cache.cpp @@ -66,7 +66,7 @@ static bool areEquivalent(const LoadInst *A, const LoadInst *B) { } static bool mayAlias(const llvm::Value *A, const llvm::Value *B) { - return not ((isa(A) or isa(B)) and A != B); + return not((isa(A) or isa(B)) and A != B); } static bool noWritesTo(const Instruction *Start, @@ -75,8 +75,8 @@ static bool noWritesTo(const Instruction *Start, if (Start->getParent() != End->getParent()) return false; - for (const Instruction &I : llvm::make_range(Start->getIterator(), - End->getIterator())) + for (const Instruction &I : + llvm::make_range(Start->getIterator(), End->getIterator())) if (auto *Store = dyn_cast(&I)) if (mayAlias(Store->getPointerOperand(), Address)) return false; @@ -166,7 +166,6 @@ void Cache::identifyPartialStores(const Function *F) { if (LoadFromSame != nullptr) IdentityLoads.insert(LoadFromSame); - } } } diff --git a/lib/StackAnalysis/element.cpp b/lib/StackAnalysis/element.cpp index cbfbc8616..7214e7789 100644 --- a/lib/StackAnalysis/element.cpp +++ b/lib/StackAnalysis/element.cpp @@ -34,7 +34,7 @@ unsigned ASSlot::cmp(const ASSlot &Other, const Module *M) const { assert(!this->isInvalid() and !Other.isInvalid()); LoggerIndent<> Y(SaDiffLog); - bool Result = not (AS.lowerThanOrEqual(Other.AS) && Offset == Other.Offset); + bool Result = not(AS.lowerThanOrEqual(Other.AS) && Offset == Other.Offset); if (Result && Diff) { Other.dump(M, SaDiffLog); @@ -322,8 +322,7 @@ void Element::mergeASState(AddressSpace &ThisState, ThisState.ASOContent[P.first] = P.second; // Cleanup phase - for (auto It = ThisState.ASOContent.begin(); - It != ThisState.ASOContent.end(); + for (auto It = ThisState.ASOContent.begin(); It != ThisState.ASOContent.end(); /**/) { if (!It->second.hasDirectContent() && !It->second.hasTag()) diff --git a/lib/StackAnalysis/element.h b/lib/StackAnalysis/element.h index 234d5245e..e65d578a5 100644 --- a/lib/StackAnalysis/element.h +++ b/lib/StackAnalysis/element.h @@ -59,7 +59,7 @@ public: bool hasTag() const { return not TheTag.isInvalid(); } - bool isEmpty() const { return not (hasDirectContent() || hasTag()); } + bool isEmpty() const { return not(hasDirectContent() || hasTag()); } bool operator==(const Value &Other) const { return DirectContent == Other.DirectContent && TheTag == Other.TheTag; diff --git a/lib/StackAnalysis/functionabi.cpp b/lib/StackAnalysis/functionabi.cpp index be40a9354..17eed5f77 100644 --- a/lib/StackAnalysis/functionabi.cpp +++ b/lib/StackAnalysis/functionabi.cpp @@ -6,8 +6,8 @@ // // Local includes -#include "abiir.h" #include "functionabi.h" +#include "abiir.h" #include "monotoneframework.h" using std::conditional; @@ -40,8 +40,8 @@ static inline Comparison compare(T A, T B) { } template -unsigned cmp(const DefaultMap &This, - const DefaultMap &Other) { +unsigned +cmp(const DefaultMap &This, const DefaultMap &Other) { LoggerIndent<> Y(SaDiffLog); unsigned Result = 0; @@ -84,12 +84,16 @@ unsigned cmpWithModule(const DefaultMap &This, return Result; } -template -unsigned -nestedCmpWithModule(const MapOfMaps &This, - const MapOfMaps &Other, - ASID ID, - const Module *M) { +template +unsigned nestedCmpWithModule(const MapOfMaps &This, + const MapOfMaps &Other, + ASID ID, + const Module *M) { LoggerIndent<> Y(SaDiffLog); unsigned Result = 0; @@ -124,8 +128,8 @@ static void combine(V &This, const Q &Other) { } template -static void combine(DefaultMap &This, - const DefaultMap &Other) { +static void +combine(DefaultMap &This, const DefaultMap &Other) { combine(This.Default, Other.Default); @@ -530,9 +534,7 @@ public: void disable() { H::disable(this->Analyses); } void enable() { H::enable(this->Analyses); } - void write() { - H::transfer(this->Analyses, GeneralTransferFunction::Write); - } + void write() { H::transfer(this->Analyses, GeneralTransferFunction::Write); } void read() { H::transfer(this->Analyses, GeneralTransferFunction::Read); } @@ -743,9 +745,9 @@ private: /// \tparam Wrapper the template class to use for wrapping the elements of the /// tuple. /// \tparam Tuple the tuple to wrap. -template