diff --git a/codegenerator.cpp b/codegenerator.cpp index c8446d290..3c639644b 100644 --- a/codegenerator.cpp +++ b/codegenerator.cpp @@ -679,7 +679,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress, dbg << "Entry address: 0x" << std::hex << VirtualAddress << std::endl; - BasicBlock *Head = JumpTargets.getBlockAt(VirtualAddress, true); + BasicBlock *Head = JumpTargets.getBlockAt(VirtualAddress); // Fake jump to the dispatcher. This way all the blocks are always reachable. // Also, use this branch as the delimiter to create local variables. @@ -790,7 +790,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress, // case force a fallthrough auto &IL = InstructionList; if (j == IL->instruction_count - 1) - Builder.CreateBr(notNull(JumpTargets.getBlockAt(EndPC, false))); + Builder.CreateBr(notNull(JumpTargets.getBlockAt(EndPC))); break; } @@ -835,7 +835,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress, } // End loop over instructions if (ForceNewBlock) - JumpTargets.getBlockAt(EndPC, false); + JumpTargets.getBlockAt(EndPC); // We might have a leftover block, probably due to the block created after // the last call to exit_tb diff --git a/instructiontranslator.cpp b/instructiontranslator.cpp index 457de4ef8..a390c6529 100644 --- a/instructiontranslator.cpp +++ b/instructiontranslator.cpp @@ -509,7 +509,6 @@ void InstructionTranslator::finalizeNewPCMarkers(std::string &CoveragePath, Output << "0x" << PC << ",0x" << Size << "," << (IsJT ? "1" : "0") - << "," << (JumpTargets.isReliablePC(PC) ? "1" : "0") << std::endl; if (EnableTracing) { @@ -560,7 +559,7 @@ InstructionTranslator::newInstruction(PTCInstruction *Instr, { MDOriginalString, MDPC }); if (ForceNew) - JumpTargets.getBlockAt(PC, false); + JumpTargets.getBlockAt(PC); if (!IsFirst) { // Check if this PC already has a block and use it @@ -752,7 +751,7 @@ InstructionTranslator::translate(PTCInstruction *Instr, if (Constant != nullptr) { uint64_t Address = Constant->getLimitedValue(); if (PC != Address) - JumpTargets.getBlockAt(Address, PC != NextPC); + JumpTargets.getBlockAt(Address); } } } diff --git a/jumptargetmanager.cpp b/jumptargetmanager.cpp index f29922fd0..cee3a1c66 100644 --- a/jumptargetmanager.cpp +++ b/jumptargetmanager.cpp @@ -114,12 +114,12 @@ bool TranslateDirectBranchesPass::pinJTs(Function &F) { if (Destinations.size() == 1) { auto *Comparison = Builder.CreateICmpEQ(C(Destinations[0]), PCLoad); Builder.CreateCondBr(Comparison, - JTM->getBlockAt(Destinations[0], false), + JTM->getBlockAt(Destinations[0]), FailBB); } else { auto *Switch = Builder.CreateSwitch(PCLoad, FailBB, Destinations.size()); for (uint64_t Destination : Destinations) - Switch->addCase(C(Destination), JTM->getBlockAt(Destination, false)); + Switch->addCase(C(Destination), JTM->getBlockAt(Destination)); } // Notify new branches only if the amount of possible targets actually @@ -151,14 +151,13 @@ bool TranslateDirectBranchesPass::pinConstantStore(Function &F) { } else { uint64_t NextPC = JTM->getNextPC(PCWrite); if (NextPC != 0 && JTM->isOSRAEnabled() && isSumJump(PCWrite)) - JTM->getBlockAt(NextPC, false); + JTM->getBlockAt(NextPC); auto *Address = dyn_cast(PCWrite->getValueOperand()); if (Address != nullptr) { // Compute the actual PC and get the associated BasicBlock uint64_t TargetPC = Address->getSExtValue(); - bool IsReliable = NextPC != 0 && TargetPC != NextPC; - BasicBlock *TargetBlock = JTM->getBlockAt(TargetPC, IsReliable); + BasicBlock *TargetBlock = JTM->getBlockAt(TargetPC); // Remove unreachable right after the exit_tb BasicBlock::iterator CallIt(Call); @@ -253,7 +252,7 @@ bool TranslateDirectBranchesPass::forceFallthroughAfterHelper(CallInst *Call) { Value *NextPCConst = Builder.getIntN(PCRegTy->getIntegerBitWidth(), NextPC); Builder.CreateCondBr(Builder.CreateICmpEQ(Builder.CreateLoad(PCReg), NextPCConst), - JTM->getBlockAt(NextPC, false), + JTM->getBlockAt(NextPC), JTM->dispatcher()); return true; @@ -442,7 +441,7 @@ void JumpTargetManager::findCodePointers(const unsigned char *Start, uint64_t Value = read(endian), 1>(Start); - getBlockAt(Value, false); + getBlockAt(Value); } } @@ -484,12 +483,12 @@ BasicBlock *JumpTargetManager::newPC(uint64_t PC, bool& ShouldContinue) { return JTIt->second; } - // Check if already translated this PC even if it's not associated to a basic - // block. This typically happens with variable-length instruction encodings. - auto OIAIt = OriginalInstructionAddresses.find(PC); - if (OIAIt != OriginalInstructionAddresses.end()) { + // Check if we already translated this PC even if it's not associated to a + // basic block (i.e., we have to split its basic block). This typically + // happens with variable-length instruction encodings. + if (OriginalInstructionAddresses.count(PC) != 0) { ShouldContinue = false; - return getBlockAt(PC, false); + return getBlockAt(PC); } // We don't know anything about this PC @@ -712,7 +711,7 @@ void JumpTargetManager::handleSumJump(Instruction *SumJump) { // Take the next PC uint64_t NextPC = getNextPC(SumJump); assert(NextPC != 0); - BasicBlock *BB = getBlockAt(NextPC, false); + BasicBlock *BB = getBlockAt(NextPC); assert(BB && !BB->empty()); std::set Visited; @@ -739,7 +738,7 @@ void JumpTargetManager::handleSumJump(Instruction *SumJump) { return; // Split and update iterators to proceed - BB = getBlockAt(PC, false); + BB = getBlockAt(PC); // Do we have a block? if (BB == nullptr) @@ -1016,13 +1015,10 @@ void JumpTargetManager::unvisit(BasicBlock *BB) { } /// Get or create a block for the given PC -BasicBlock *JumpTargetManager::getBlockAt(uint64_t PC, bool Reliable) { +BasicBlock *JumpTargetManager::getBlockAt(uint64_t PC) { if (!isExecutableAddress(PC) || !isInstructionAligned(PC)) return nullptr; - if (Reliable) - ReliablePCs.insert(PC); - // Do we already have a BasicBlock for this PC? BlockMap::iterator TargetIt = JumpTargets.find(PC); if (TargetIt != JumpTargets.end()) { diff --git a/jumptargetmanager.h b/jumptargetmanager.h index 5b4449a4a..f7dd35020 100644 --- a/jumptargetmanager.h +++ b/jumptargetmanager.h @@ -236,47 +236,17 @@ public: return false; } - /// \brief Return true if the given PC is "reliable" - /// - /// A PC is "reliable" if it's a reliable jump target or is contained in a - /// basic block start by a reliable jump target. - /// A jump target is reliable if it was obtained from an explicit write to the - /// PC and it wasn't a fallthroug jump. - bool isReliablePC(uint64_t PC) { - // Get the PC of the basic block "not less than" the PC - auto It = JumpTargets.lower_bound(PC); - - uint64_t BBPC = 0; - if (It == JumpTargets.end()) { - BBPC = JumpTargets.rbegin()->first; - assert(BBPC < PC); - } else { - - BBPC = It->first; - - // If it's not the PC itself, it's the PC of the next basic - // block, so go back one position - if (BBPC != PC) { - assert(It != JumpTargets.begin()); - BBPC = (--It)->first; - } - } - - return ReliablePCs.count(BBPC); - } - /// \brief Get or create a block for the given PC /// /// This function can return `nullptr`. /// /// \param PC the PC for which a `BasicBlock` is requested. - /// \param Reliable whether \p PC was obtained in a "reliable" way or not. /// /// \return a `BasicBlock`, it might be newly created and empty, empty and /// created in the past or even a `BasicBlock` already containing the /// translated code. It might also return `nullptr` if the PC is not /// valid or another error occurred. - llvm::BasicBlock *getBlockAt(uint64_t PC, bool Reliable); + llvm::BasicBlock *getBlockAt(uint64_t PC); /// \brief Removes a `BasicBlock` from the SET's visited list void unvisit(llvm::BasicBlock *BB); @@ -450,7 +420,6 @@ private: std::vector& Segments; Architecture& SourceArchitecture; - std::set ReliablePCs; bool EnableOSRA; std::map OriginalBBStats; diff --git a/set.cpp b/set.cpp index 28e321533..79f7415b4 100644 --- a/set.cpp +++ b/set.cpp @@ -23,7 +23,6 @@ using namespace llvm; using std::make_pair; -// TODO: drop reliable jump target concept /// \brief Stack to keep track of the operations generating a specific value /// /// The OperationsStacks offers the following features: @@ -41,7 +40,7 @@ public: const DataLayout &DL) : JTM(JTM), DL(DL) { } ~OperationsStack() { - reset(false, None); + reset(None); } void explore(Constant *NewOperand); @@ -56,13 +55,11 @@ public: /// \brief Clean the operations stack /// - /// \param Reliable whether the PC we're going to collect have to be - /// considered reliable or not. /// \param Tracking what to track, see TrackingType. This parameter only /// affects what is being explicitly tracked by the OperationsStack, /// which can be obtained through the trackedValues method. It does not /// affect the collection of jump targets, which is always enabled. - void reset(bool Reliable, TrackingType Tracking) { + void reset(TrackingType Tracking) { // Delete all the temporary instructions we created for (Instruction *I : Operations) if (I->getParent() == nullptr) @@ -70,15 +67,14 @@ public: Operations.clear(); OperationsSet.clear(); - IsReliable = Reliable; TrackedValues.clear(); Approximate = false; this->Tracking = Tracking; } void registerPCs() const { - for (auto Pair : NewPCs) - JTM->getBlockAt(Pair.first, Pair.second); + for (uint64_t PC : NewPCs) + JTM->getBlockAt(PC); } void cut(unsigned Height) { @@ -153,10 +149,9 @@ private: std::vector Operations; std::set OperationsSet; - std::set> NewPCs; + std::set NewPCs; std::set TrackedValues; - bool IsReliable; bool Approximate; TrackingType Tracking; }; @@ -236,7 +231,7 @@ void OperationsStack::explore(Constant *NewOperand) { uint64_t PC = materialize(NewOperand); if (PC != 0 && JTM->isInterestingPC(PC)) - NewPCs.insert({ PC, IsReliable }); + NewPCs.insert(PC); if (PC != 0 && (Tracking == All || (Tracking == PCsOnly && JTM->isPC(PC)))) @@ -386,10 +381,7 @@ bool SET::run() { // Clean the OperationsStack and, if we're dealing with a store to the PC, // ask it to track all the possible values that the PC will assume. - // TODO: hardcoded - OS.reset(/* IsPCStore */ false, - IsPCStore ? OperationsStack::PCsOnly : - OperationsStack::None); + OS.reset(IsPCStore ? OperationsStack::PCsOnly : OperationsStack::None); assert(WorkList.empty()); if (IsStore) WorkList.push_back(make_pair(Store->getValueOperand(), 0));