static bool parseJumpIndexTable(ExecutableContainer *c, InstPtr index_insn, const vector<VA> &jmptable_entries, raw_ostream &out) { VA reloc_offset = index_insn->get_reloc_offset(); if (reloc_offset == 0) { out << "Unsupported jump index write; no relocation\n"; // this jump index probably doesn't use a table return false; } VA addrInInst = index_insn->get_loc() + reloc_offset; VA indexTableEntry; VA symbolSize; if(!c->relocate_addr(addrInInst, indexTableEntry, symbolSize)) { out << "Not a jump index table: can't relocate relocation in index insn\n"; // can't relocate, something bad happened return false; } // assume we always index the start of the index table // ... might not be correct // this means we set initial entry to zero, the first element int initial_entry = 0; uint8_t b; int bindex = 0; // loop while all the bytes we read can be table indexes vector<uint8_t> index_entries; while( (indexTableEntry+bindex) < c->getExtent() ) { c->readByte(indexTableEntry+bindex, &b); if (b > jmptable_entries.size()) { break; } out << "Read index table byte: " << to_string<uint32_t>((uint32_t)b, hex) << "\n"; index_entries.push_back(b); bindex++; } JumpIndexTable *jit = new JumpIndexTable(index_entries, initial_entry); index_insn->set_jump_index_table(JumpIndexTablePtr(jit)); return true; }
//GENERIC_TRANSLATION_32MI(MOV32mi, // doMIMov<32>(ip, block, ADDR(0), OP(5)), // doMIMov<32>(ip, block, STD_GLOBAL_OP(0), OP(5)), // doMIMovV<32>(ip, block, ADDR_NOREF(0), GLOBAL_DATA_OFFSET(block, natM, ip)) // ) // static InstTransResult translate_MOV32mi(NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst) { InstTransResult ret; Function *F = block->getParent(); if( ip->has_call_tgt() ) { Value *callback_fn = makeCallbackForLocalFunction( block->getParent()->getParent(), ip->get_call_tgt(0) ); Value *addrInt = new PtrToIntInst( callback_fn, llvm::Type::getInt32Ty(block->getContext()), "", block); ret = doMIMovV<32>(ip, block, ADDR(0), addrInt); } else if( ip->is_data_offset() ) { if( ip->get_reloc_offset() < OP(5).getOffset() ) { doMIMov<32>(ip, block, STD_GLOBAL_OP(0), OP(5)); } else { doMIMovV<32>(ip, block, ADDR_NOREF(0), GLOBAL_DATA_OFFSET(block, natM, ip)); } ret = ContinueBlock; } else { ret = doMIMov<32>(ip, block, ADDR(0), OP(5)); } return ret; }
static bool handlePossibleJumpTable(ExecutableContainer *c, NativeBlockPtr B, InstPtr jmpinst, VA curAddr, stack<VA> &funcs, stack<VA> &blockChildren, raw_ostream &out) { LASSERT(jmpinst->get_inst().getOpcode() == X86::JMP32m, "handlePossibleJumpTable needs a JMP32m opcode" ); // is this a jump table, step 0 // does this instruction have a relocation? VA reloc_offset = jmpinst->get_reloc_offset(); if (reloc_offset == 0) { out << "Not a jump table: no relocation in JMP32m\n"; // bail, this is not a jump table return false; } // this relocation has to point to a relocation VA addrInInst = curAddr + reloc_offset; VA jmpTableEntry, someFunction; if(!c->relocate_addr(addrInInst, jmpTableEntry)) { out << "Not a jump table: can't relocate relocation in JMP32m\n"; // can't relocate, something bad happened return false; } if(!c->relocate_addr(jmpTableEntry, someFunction)) { // could not relocate the default jump table entry. // not good out << "Not a jump table: can't relocate first jump table entry\n"; return false; } bool is_reloc_code = isAddrOfType(c, someFunction, ExecutableContainer::CodeSection); if(!is_reloc_code) { // jump table entry not point to code out << "Not a jump table: first entry doesn't point to code\n"; return false; } // read jump table entries and add them as new function // entry points vector<VA> jmptable_entries; int new_funs; int original_zero; // this reads negative jump table indexes, but vectors are not negative // indexed. the negative most, which should be the new index 0, is now // index N. Reverse the vector so it will be index 0, and save the current // size as the original zeroth element new_funs = addJmpTableEntries(c, jmptable_entries, jmpTableEntry, -4, out); std::reverse(jmptable_entries.begin(), jmptable_entries.end()); out << "Added: " << to_string<int>(new_funs, dec) << " functions to jmptable\n"; original_zero = new_funs; // add original entry at the zero position jmptable_entries.push_back(someFunction); out << "Added JMPTABLE entry [" << to_string<uint32_t>(jmpTableEntry, hex) << "] => " << to_string<uint32_t>(someFunction, hex) << "\n"; // add the positive table entries new_funs = addJmpTableEntries(c, jmptable_entries, jmpTableEntry, 4, out); out << "Added: " << to_string<int>(new_funs, dec) << " functions to jmptable\n"; // associate instruction with jump table JumpTable *jt = new JumpTable(jmptable_entries, original_zero); jmpinst->set_jump_table(JumpTablePtr(jt)); stack<VA> *toPush = NULL; // if this jump table is in the format // jmp [reg*4+imm32], then it is conformant // and we can turn it into an llvm switch(); bool is_conformant = isConformantJumpInst(jmpinst); if(is_conformant) { toPush = &blockChildren; out << "GOT A CONFORMANT JUMP INST\n"; } else { toPush = &funcs; } // add these jump table entries as new entry points for(std::vector<VA>::const_iterator itr = jmptable_entries.begin(); itr != jmptable_entries.end(); itr++) { out << "Adding block via jmptable: " << to_string<VA>(*itr, hex) << "\n"; toPush->push(*itr); if(is_conformant) { B->add_follow(*itr); } } processJumpIndexTable(c, B, jmpinst, jmptable_entries, out); return true; }