1 #include "RoseInsnFactory.h"
2 //#include "../rose/x86InstructionSemantics.h"
3 //#include "../rose/powerpcInstructionSemantics.h"
5 #include "Instruction.h"
7 #include "Expression.h"
8 #include "Dereference.h"
12 #include "../rose/SgAsmInstruction.h"
13 #include "../rose/SgAsmPowerpcInstruction.h"
14 #include "../rose/SgAsmx86Instruction.h"
15 #include "../rose/SgAsmExpression.h"
17 #include "ExpressionConversionVisitor.h"
19 using namespace Dyninst;
20 using namespace InstructionAPI;
21 using namespace DataflowAPI;
23 SgAsmInstruction *RoseInsnFactory::convert(const InstructionAPI::Instruction::Ptr &insn, uint64_t addr) {
24 SgAsmInstruction *rinsn = createInsn();
26 rinsn->set_address(addr);
27 rinsn->set_mnemonic(insn->format());
28 setOpcode(rinsn, insn->getOperation().getID(), insn->getOperation().getPrefixID(), insn->getOperation().format());
30 // semantics don't support 64-bit code
33 //rinsn->set_operandSize(x86_insnsize_32);
34 //rinsn->set_addressSize(x86_insnsize_32);
36 std::vector<unsigned char> rawBytes;
37 for (unsigned i = 0; i < insn->size(); ++i) rawBytes.push_back(insn->rawByte(i));
38 rinsn->set_raw_bytes(rawBytes);
41 SgAsmOperandList *roperands = new SgAsmOperandList;
43 //cerr << "Converting " << insn->format() << " @" << hex << addr << dec << endl;
45 //cerr << "checking instruction: " << insn->format() << " for special handling" << endl;
46 if (handleSpecialCases(insn->getOperation().getID(), rinsn, roperands)) {
47 rinsn->set_operandList(roperands);
51 //cerr << "no special handling by opcode, checking if we should mangle operands..." << endl;
52 std::vector<InstructionAPI::Operand> operands;
53 insn->getOperands(operands);
54 //cerr << "\t " << operands.size() << " operands" << endl;
55 massageOperands(insn, operands);
57 //cerr << "converting insn " << insn->format() << endl;
58 for (std::vector<InstructionAPI::Operand>::iterator opi = operands.begin();
59 opi != operands.end();
61 InstructionAPI::Operand &currOperand = *opi;
62 //cerr << "Converting operand " << currOperand.format() << endl;
63 roperands->append_operand(convertOperand(currOperand.getValue(), addr));
65 rinsn->set_operandList(roperands);
69 SgAsmExpression *RoseInsnFactory::convertOperand(const Expression::Ptr expression, uint64_t addr) {
70 if(!expression) return NULL;
71 ExpressionConversionVisitor visitor(arch(), addr);
72 expression->apply(&visitor);
73 return visitor.getRoseExpression();
76 ///////////// X86 //////////////////
78 SgAsmInstruction *RoseInsnX86Factory::createInsn() {
79 return new SgAsmx86Instruction;
82 // Note: convertKind is defined in convertOpcodes.C
84 void RoseInsnX86Factory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID prefix, std::string) {
85 SgAsmx86Instruction *tmp = static_cast<SgAsmx86Instruction *>(insn);
87 tmp->set_kind(convertKind(opcode, prefix));
90 void RoseInsnX86Factory::setSizes(SgAsmInstruction *insn) {
91 // FIXME when we go 64-bit...
92 SgAsmx86Instruction *tmp = static_cast<SgAsmx86Instruction *>(insn);
93 tmp->set_operandSize(x86_insnsize_32);
94 tmp->set_addressSize(x86_insnsize_32);
97 bool RoseInsnX86Factory::handleSpecialCases(entryID, SgAsmInstruction *, SgAsmOperandList *) {
103 void RoseInsnX86Factory::massageOperands(const InstructionAPI::Instruction::Ptr &insn,
104 std::vector<InstructionAPI::Operand> &operands) {
105 switch (insn->getOperation().getID()) {
107 // ROSE expects there to be a "memory reference" statement wrapping the
108 // address calculation. It then unwraps it.
109 Dereference::Ptr tmp = Dereference::Ptr(new Dereference(operands[1].getValue(), u32));
110 operands[1] = Operand(tmp, operands[1].isRead(), operands[1].isWritten());
164 //////////// PPC ///////////////////
165 // Note: convertKind is defined in convertOpcodes.C
167 SgAsmInstruction *RoseInsnPPCFactory::createInsn() {
168 return new SgAsmPowerpcInstruction;
171 void RoseInsnPPCFactory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID /*prefix*/, std::string mnem) {
172 SgAsmPowerpcInstruction *tmp = static_cast<SgAsmPowerpcInstruction *>(insn);
173 kind = convertKind(opcode, mnem);
178 void RoseInsnPPCFactory::setSizes(SgAsmInstruction *) {
182 bool RoseInsnPPCFactory::handleSpecialCases(entryID iapi_opcode,
183 SgAsmInstruction *insn,
184 SgAsmOperandList *rose_operands) {
185 SgAsmPowerpcInstruction *rose_insn = static_cast<SgAsmPowerpcInstruction *>(insn);
187 switch(iapi_opcode) {
191 case power_op_bclr: {
192 unsigned int raw = 0;
193 int branch_target = 0;
194 unsigned int bo = 0, bi = 0;
195 std::vector<unsigned char> bytes = rose_insn->get_raw_bytes();
196 for(unsigned i = 0; i < bytes.size(); i++) {
200 bool isAbsolute = (bool)(raw & 0x00000002);
201 bool isLink = (bool)(raw & 0x00000001);
202 rose_insn->set_kind(makeRoseBranchOpcode(iapi_opcode, isAbsolute, isLink));
203 if(power_op_b == iapi_opcode) {
204 branch_target = ((raw >> 2) & 0x00FFFFFF) << 2;
205 branch_target = (branch_target << 8) >> 8;
207 if(power_op_bc == iapi_opcode) {
208 branch_target = ((raw >> 2) & 0x00003FFF) << 2;
209 branch_target = (branch_target << 18) >> 18;
210 //cerr << "14-bit branch target: " << branch_target << endl;
212 bo = ((raw >> 21) & 0x0000001F);
213 bi = ((raw >> 16) & 0x0000001F);
214 rose_operands->append_operand(new SgAsmByteValueExpression(bo));
215 rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_cr, bi,
216 powerpc_condreggranularity_bit));
219 rose_operands->append_operand(new SgAsmDoubleWordValueExpression(branch_target));
220 } else if(power_op_bcctr == iapi_opcode) {
221 rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_spr, powerpc_spr_ctr));
223 assert(power_op_bclr == iapi_opcode);
224 rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_spr, powerpc_spr_lr));
230 case power_op_svcs: {
231 //cerr << "special-casing syscall insn" << endl;
232 unsigned int raw = 0;
233 std::vector<unsigned char> bytes = rose_insn->get_raw_bytes();
234 for(unsigned i = 0; i < bytes.size(); i++) {
238 unsigned int lev = (raw >> 5) & 0x7F;
239 rose_operands->append_operand(new SgAsmByteValueExpression(lev));
240 //cerr << "LEV = " << lev << endl;
249 void RoseInsnPPCFactory::massageOperands(const InstructionAPI::Instruction::Ptr &insn,
250 std::vector<InstructionAPI::Operand> &operands) {
251 if(insn->writesMemory())
252 std::swap(operands[0], operands[1]);
253 entryID opcode = insn->getOperation().getID();
254 // Anything that's writing RA, ROSE expects in RA, RS, RB/immediates form.
255 // Any store, however, ROSE expects in RS, RA, RB/displacement form. Very confusing,
256 // but we handle it cleanly here.
257 if(!operands[0].isWritten() && operands.size() >= 2 &&
258 operands[1].isWritten() && !operands[1].writesMemory()) {
259 std::cerr << "swapping RS and RA in " << insn->format() << std::endl;
260 std::swap(operands[0], operands[1]);
262 if(opcode == power_op_cmp ||
263 opcode == power_op_cmpl ||
264 opcode == power_op_cmpi ||
265 opcode == power_op_cmpli) {
266 operands.push_back(Operand(Immediate::makeImmediate(Result(u8, 1)), false, false));
267 std::swap(operands[2], operands[3]);
268 std::swap(operands[1], operands[2]);
270 if(insn->getOperation().format().find(".") != std::string::npos &&
271 insn->getOperation().getID() != power_op_stwcx_rc) {
275 // Convert to ROSE so we can use numeric greater than/less than
277 if(kind >= powerpc_lbz && kind <= powerpc_lwzx) {
280 if(kind >= powerpc_stb && kind <= powerpc_stwx) {