diff --git a/codegenerator.cpp b/codegenerator.cpp index 53afa4803..e58753e29 100644 --- a/codegenerator.cpp +++ b/codegenerator.cpp @@ -584,9 +584,6 @@ void CodeGenerator::translate(uint64_t VirtualAddress, IRBuilder<> Builder(Context); - if (VirtualAddress == 0) - VirtualAddress = EntryPoint; - // Create main function auto *MainType = FunctionType::get(Builder.getVoidTy(), false); auto *MainFunction = Function::Create(MainType, @@ -607,12 +604,20 @@ void CodeGenerator::translate(uint64_t VirtualAddress, VariableManager Variables(*TheModule, *HelpersModule); + auto *PCReg = Variables.getByEnvOffset(ptc.pc, "pc").first; JumpTargetManager JumpTargets(MainFunction, - Variables.getByEnvOffset(ptc.pc, "pc"), + PCReg, SourceArchitecture, Segments); - BasicBlock *Head = JumpTargets.getBlockAt(VirtualAddress); + if (VirtualAddress == 0) { + JumpTargets.harvestGlobalData(); + VirtualAddress = EntryPoint; + } + + dbg << "Entry address: 0x" << std::hex << VirtualAddress << std::endl; + + BasicBlock *Head = JumpTargets.getBlockAt(VirtualAddress, true); // Fake jump to the dispatcher. This way all the blocks are always reachable. // Also, use this branch as the delimiter to create local variables. diff --git a/jumptargetmanager.cpp b/jumptargetmanager.cpp index ee5bc8c91..90c7320d3 100644 --- a/jumptargetmanager.cpp +++ b/jumptargetmanager.cpp @@ -194,6 +194,12 @@ bool JumpTargetsFromConstantsPass::runOnFunction(Function &F) { return false; } +template +static cl::opt *getOption(StringMap& Options, + const char *Name) { + return static_cast *>(Options[Name]); +} + JumpTargetManager::JumpTargetManager(Function *TheFunction, Value *PCReg, Architecture& SourceArchitecture, @@ -206,47 +212,51 @@ JumpTargetManager::JumpTargetManager(Function *TheFunction, PCReg(PCReg), ExitTB(nullptr), Dispatcher(nullptr), - DispatcherSwitch(nullptr) { + DispatcherSwitch(nullptr), + Segments(Segments), + SourceArchitecture(SourceArchitecture) { FunctionType *ExitTBTy = FunctionType::get(Type::getVoidTy(Context), { }, false); ExitTB = cast(TheModule.getOrInsertFunction("exitTB", ExitTBTy)); createDispatcher(TheFunction, PCReg, true); - for (auto& Segment : Segments) { - if (Segment.IsExecutable) { + for (auto& Segment : Segments) + if (Segment.IsExecutable) ExecutableRanges.push_back(std::make_pair(Segment.StartVirtualAddress, Segment.EndVirtualAddress)); - } + // Configure GlobalValueNumbering + 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); + // getOption(Options, "max-recurse-depth")->setInitialValue(10); +} + +void JumpTargetManager::harvestGlobalData() { + for (auto& Segment : Segments) { auto *Data = cast(Segment.Variable->getInitializer()); const unsigned char *DataStart = Data->getRawDataValues().bytes_begin(); const unsigned char *DataEnd = Data->getRawDataValues().bytes_end(); + using endianness = support::endianness; if (SourceArchitecture.pointerSize() == 64) { if (SourceArchitecture.isLittleEndian()) - findCodePointers(DataStart, - DataEnd); + findCodePointers(DataStart, DataEnd); else - findCodePointers(DataStart, - DataEnd); + findCodePointers(DataStart, DataEnd); } else if (SourceArchitecture.pointerSize() == 32) { if (SourceArchitecture.isLittleEndian()) - findCodePointers(DataStart, - DataEnd); + findCodePointers(DataStart, DataEnd); else - findCodePointers(DataStart, - DataEnd); + findCodePointers(DataStart, DataEnd); } } DBG("jtcount", dbg - << "JumpTargets found in global data: " << Unexplored.size() << "\n"); - - // Configure GlobalValueNumbering - StringMap& Options(cl::getRegisteredOptions()); - auto *GVNLoadPre = static_cast *>(Options["enable-load-pre"]); - GVNLoadPre->setInitialValue(false); + << "JumpTargets found in global data: " << std::dec + << Unexplored.size() << "\n"); } template @@ -261,8 +271,8 @@ void JumpTargetManager::findCodePointers(const unsigned char *Start, } /// Handle a new program counter. We might already have a basic block for that -/// program counter, or we could even have a translation for it. Return one -/// of these, if appropriate. +/// program counter, or we could even have a translation for it. Return one of +/// these, if appropriate. /// /// \param PC the new program counter. /// \param ShouldContinue an out parameter indicating whether the returned diff --git a/jumptargetmanager.h b/jumptargetmanager.h index fb2955b6a..c8d83f829 100644 --- a/jumptargetmanager.h +++ b/jumptargetmanager.h @@ -83,6 +83,8 @@ public: Architecture& SourceArchitecture, std::vector& Segments); + void harvestGlobalData(); + /// Handle a new program counter. We might already have a basic block for that /// program counter, or we could even have a translation for it. Return one /// of these, if appropriate. @@ -179,6 +181,9 @@ private: llvm::BasicBlock *Dispatcher; llvm::SwitchInst *DispatcherSwitch; std::set Visited; + + std::vector& Segments; + Architecture& SourceArchitecture; }; #endif // _JUMPTARGETMANAGER_H