bool PCWidget::PCtoReg(const codeGen &templ, const RelocBlock *t, CodeBuffer &buffer) { bool ignored; Register reg = convertRegID(a_.reg(), ignored); if(templ.addrSpace()->proc()) { #if defined(arch_x86) || defined(arch_x86_64) std::vector<unsigned char> newInsn; newInsn.push_back(static_cast<unsigned char>(0xb8 + reg)); // MOV family, destination of the register encoded by // 'reg', source is an Iv immediate Address EIP = addr_ + insn_->size(); unsigned char *tmp = (unsigned char *) &EIP; newInsn.insert(newInsn.end(), tmp, tmp + sizeof(unsigned int)); buffer.addPIC(newInsn, tracker(t)); #else // Move immediate to register? codeGen gen(16); insnCodeGen::loadImmIntoReg(gen, reg, addr_); buffer.addPIC(gen, tracker(t)); #endif } else { IPPatch *newPatch = new IPPatch(IPPatch::Reg, addr_, reg, thunkAddr_, insn_, t->block(), t->func()); buffer.addPatch(newPatch, tracker(t)); } return true; }
bool PCWidget::PCtoReturnAddr(const codeGen &templ, const RelocBlock *t, CodeBuffer &buffer) { if(templ.addrSpace()->proc()) { std::vector<unsigned char> newInsn; #if defined(arch_x86_64) codeGen gen(16); Address RIP = addr_ + insn_.size(); insnCodeGen::generatePush64(gen, RIP); buffer.addPIC(gen, tracker(t)); #elif defined(arch_x86) newInsn.push_back(0x68); // push Address EIP = addr_ + insn_.size(); unsigned char *tmp = (unsigned char *) &EIP; newInsn.insert(newInsn.end(), tmp, tmp+sizeof(unsigned int)); buffer.addPIC(newInsn, tracker(t)); #else // We want to get a value into LR, which is the return address. // Fun for the whole family... we need a spare register. Argh! codeGen gen(16); gen.applyTemplate(templ); // Must be in LR instPoint *point = templ.point(); // If we do not have a point then we have to invent one if (!point || (point->type() != instPoint::PreInsn && point->insnAddr() != addr())) { point = instPoint::preInsn(t->func(), t->block(), addr(), insn_, true); } assert(point); registerSpace *rs = registerSpace::actualRegSpace(point); gen.setRegisterSpace(rs); int stackSize = 0; pdvector<Register> freeReg; pdvector<Register> excludeReg; Address origRet = addr() + insn_.size(); Register scratch = gen.rs()->getScratchRegister(gen, true); if (scratch == REG_NULL) { stackSize = insnCodeGen::createStackFrame(gen, 1, freeReg, excludeReg); assert(stackSize == 1); scratch = freeReg[0]; } insnCodeGen::loadImmIntoReg(gen, scratch, origRet); insnCodeGen::generateMoveToLR(gen, scratch); buffer.addPIC(gen, tracker(t)); #endif } else { IPPatch *newPatch = new IPPatch(IPPatch::Push, addr_, insn_, t->block(), t->func()); buffer.addPatch(newPatch, tracker(t)); } return true; }
bool CFWidget::generateIndirectCall(CodeBuffer &buffer, Register /*reg*/, Instruction insn, const RelocBlock *trace, Address /*origAddr*/) { NS_power::instruction ugly_insn(insn.ptr()); IFORM_LK_SET(ugly_insn, 1); codeGen gen(4); insnCodeGen::generate(gen, ugly_insn); // TODO don't ignore the register parameter buffer.addPIC(gen, tracker(trace)); return true; }
bool CFWidget::generateIndirect(CodeBuffer &buffer, Register, const RelocBlock *trace, Instruction insn) { // Copying an indirect jump; unlike x86 we don't do // call -> indirect conversion yet. // ... though that would be really freaking easy. NS_power::instruction ugly_insn(insn.ptr()); IFORM_LK_SET(ugly_insn, 0); codeGen gen(4); insnCodeGen::generate(gen, ugly_insn); // TODO don't ignore the register parameter buffer.addPIC(gen, tracker(trace)); return true; }