void doJumpTableViaSwitch( NativeModulePtr natM, BasicBlock *& block, InstPtr ip, MCInst &inst) { llvm::dbgs() << __FUNCTION__ << ": Doing jumpt table via switch\n"; Function *F = block->getParent(); Module *M = F->getParent(); // we know this conforms to // jmp [reg*4+displacement] // sanity check const MCOperand& scale = OP(1); const MCOperand& index = OP(2); TASSERT(index.isReg(), "Conformant jump tables need index to be a register"); TASSERT(scale.isImm() && scale.getImm() == 4, "Conformant jump tables have scale == 4"); MCSJumpTablePtr jmpptr = ip->get_jump_table(); // to ensure no negative entries Value *adjustment = CONST_V<32>(block, jmpptr->getInitialEntry()); Value *reg_val = R_READ<32>(block, index.getReg()); Value *real_index = BinaryOperator::Create(Instruction::Add, adjustment, reg_val, "", block); // create a default block that just traps BasicBlock *defaultBlock = BasicBlock::Create(block->getContext(), "", block->getParent(), 0); Function *trapFn = Intrinsic::getDeclaration(M, Intrinsic::trap); CallInst::Create(trapFn, "", defaultBlock); ReturnInst::Create(defaultBlock->getContext(), defaultBlock); // end default block const std::vector<VA> &jmpblocks = jmpptr->getJumpTable(); // create a switch inst SwitchInst *theSwitch = SwitchInst::Create( real_index, defaultBlock, jmpblocks.size(), block); // populate switch int myindex = 0; for(std::vector<VA>::const_iterator itr = jmpblocks.begin(); itr != jmpblocks.end(); itr++) { std::string bbname = "block_0x"+to_string<VA>(*itr, std::hex); BasicBlock *toBlock = bbFromStrName(bbname, F); TASSERT(toBlock != NULL, "Could not find block: "+bbname); theSwitch->addCase(CONST_V<32>(block, myindex), toBlock); ++myindex; } }
void doJumpTableViaSwitchReg( BasicBlock *& block, InstPtr ip, Value *regVal, BasicBlock *&default_block) { llvm::dbgs() << __FUNCTION__ << ": Doing jumpt table via switch(reg)\n"; Function *F = block->getParent(); Module *M = F->getParent(); MCSJumpTablePtr jmpptr = ip->get_jump_table(); // create a default block that just traps default_block = BasicBlock::Create(block->getContext(), "", block->getParent(), 0); // end default block const std::vector<VA> &jmpblocks = jmpptr->getJumpTable(); std::unordered_set<VA> uniq_blocks(jmpblocks.begin(), jmpblocks.end()); // create a switch inst SwitchInst *theSwitch = SwitchInst::Create( regVal, default_block, uniq_blocks.size(), block); // populate switch for(auto blockVA : uniq_blocks) { std::string bbname = "block_0x"+to_string<VA>(blockVA, std::hex); BasicBlock *toBlock = bbFromStrName(bbname, F); llvm::dbgs() << __FUNCTION__ << ": Mapping from " << to_string<VA>(blockVA, std::hex) << " => " << bbname << "\n"; TASSERT(toBlock != NULL, "Could not find block: "+bbname); theSwitch->addCase(CONST_V<32>(block, blockVA), toBlock); } }