bool
EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
{
    uint32_t src, base;

    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());

    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
    {
        RegisterValue data_src;
        RegisterInfo reg_info_src;

        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
            return false;

        Context context;
        context.type = eContextRegisterLoad;

        if (!WriteRegister (context, &reg_info_src, data_src))
            return false;

        return true;
    }

    return false;
}
bool
EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
{
    bool success = false;
    const uint32_t imm16 = insn.getOperand(2).getImm();
    uint32_t imm = SignedBits(imm16, 15, 0);
    uint64_t result;
    uint32_t src, dst;

    dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
    src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());

    /* Check if this is addiu sp,<src>,imm16 */
    if (dst == gcc_dwarf_sp_mips64)
    {
        /* read <src> register */
        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success);
        if (!success)
            return false;

        result = src_opd_val + imm;

        Context context;
        RegisterInfo reg_info_sp;
        if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp))
            context.SetRegisterPlusOffset (reg_info_sp, imm);

        /* We are allocating bytes on stack */
        context.type = eContextAdjustStackPointer;

        WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
    }
    
    return true;
}
Beispiel #3
0
static std::string getLocalName(const llvm::MCInst& inst, unsigned iop) {
	const llvm::MCOperand& op = inst.getOperand(iop);

	if (op.isReg() && strcmp(MRI->getName(op.getReg()), "RBP") == 0) {
		char buf[128];

		snprintf(buf, 128, "local_%x", -inst.getOperand(iop + 3).getImm());
		return std::string(buf);
	} else {
		return std::string("UNK");
	}
}
bool
EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
{
    bool success = false;
    uint32_t imm16 = insn.getOperand(2).getImm();
    uint32_t imm = SignedBits(imm16, 15, 0);
    uint32_t src, base;

    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());

    /* We look for sp based non-volatile register stores */
    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
    {
        uint32_t address;
        RegisterInfo reg_info_base;
        RegisterInfo reg_info_src;

        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
            || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
            return false;

        /* read SP */
        address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
        if (!success)
            return false;

        /* destination address */
        address = address + imm;

        Context context;
        RegisterValue data_src;
        context.type = eContextPushRegisterOnStack;
        context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);

        uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
        Error error;

        if (!ReadRegister (&reg_info_base, data_src))
            return false;

        if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
            return false;

        if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
            return false;

        return true;
    }

    return false;
}
Beispiel #5
0
static void printInst(const llvm::MCInst& inst) {
	const llvm::MCInstrDesc& id = MII->get(inst.getOpcode());
	llvm::outs() << MII->getName(inst.getOpcode()) << " (" << inst.getNumOperands() << ") ";

	for (int iop = 0; iop < inst.getNumOperands(); ++iop) {
		const llvm::MCOperand& op = inst.getOperand(iop);

		if (op.isReg()) {
			unsigned reg = op.getReg();
			const char* rcName;
			char clsn[128];

			if (id.OpInfo[iop].RegClass < MRI->getNumRegClasses()) {
				const llvm::MCRegisterClass& rc = MRI->getRegClass(id.OpInfo[iop].RegClass);
				rcName = rc.getName();
			} else {
				snprintf(clsn, sizeof(clsn), "CLS%d", id.OpInfo[iop].RegClass);
				rcName = clsn;
			}
			llvm::outs() << MRI->getName(reg) << "(" << rcName << ", " << (uint64_t)id.OpInfo[iop].OperandType << ")";
		} else if (op.isImm()) {
			llvm::outs() << op.getImm() << "(" << (uint64_t)id.OpInfo[iop].OperandType << ")";
		} else {
			llvm::outs() << "<UNK>";
		}

		llvm::outs() << ", ";
	}

	llvm::outs() << "\n";
}
Beispiel #6
0
// Convert the given assembly instruction into an inline ASM operation in lieu
// of decompiling it. The output instruction will look something like this
// (although note that i128 doesn't work properly with LLVM codegen for the
// inline ASM instructions, necessitating a vector instead).
// %151 = load i128, i128* %XMM0_read
// %152 = bitcast i128 %151 to <16 x i8>
// %153 = load i128, i128* %XMM1_read
// %154 = bitcast i128 %153 to <16 x i8>
// %AESDECrr = call <16 x i8> asm "\09aesdec\09%xmm1, %xmm0", "={XMM0},{XMM0},{XMM1}"(<16 x i8> %152, <16 x i8> %154)
// %155 = bitcast <16 x i8> %AESDECrr to i128
// store volatile i128 %155, i128* %XMM0_write
void ArchBuildInlineAsm(llvm::MCInst &inst, llvm::BasicBlock *block) {
  auto opcode = inst.getOpcode();

  // Use the printer to build the ASM string. We'll need to escape the $ in
  // register names with $$.
  std::stringstream asmString;
  {
    std::string outS;
    llvm::raw_string_ostream strOut(outS);
    gIP->printInst(&inst, strOut, "", *gSTI);
    for (char c : strOut.str()) {
      if (c == '$')
        asmString << "$$";
      else
        asmString << c;
    }
  }

  // Next, find all the registers being used as definitions or uses in the
  // inline ASM. This will write up the constraints for us, as well as
  // provide us with a list of types (for the inline ASM output) and a list of
  // values to pass into the string.
  llvm::SmallVector<llvm::Value *, 3> operands;
  llvm::SmallVector<llvm::Type *, 3> resultTypes;
  std::stringstream constraints;
  for (unsigned i = 0; i < inst.getNumOperands(); i++) {
    llvm::MCOperand &op = inst.getOperand(i);
    if (op.isReg()) {
      unsigned regSize = ArchRegisterSize(op.getReg());
      if (constraints.tellp() > 0) constraints << ",";
      if (i < gMII->get(opcode).getNumDefs()) {
        constraints << "=";

        if (regSize > 64) {
          // LLVM can't handle register constraints of i128, so we
          // need to map this to <16 x i8>.
          resultTypes.push_back(llvm::VectorType::get(
            llvm::Type::getInt8Ty(block->getContext()), regSize / 8));
        } else {
          resultTypes.push_back(llvm::IntegerType::get(block->getContext(),
            regSize));
        }
      } else {
        auto readReg = GENERIC_MC_READREG(block, op.getReg(), regSize);
        if (regSize > 64) {
          // LLVM can't handle register constraints of i128, so we
          // need to map this to <16 x i8>.
          readReg = llvm::CastInst::Create(llvm::Instruction::BitCast, readReg,
            llvm::VectorType::get(llvm::Type::getInt8Ty(block->getContext()), regSize / 8),
            "", block);
        }
        operands.push_back(readReg);
      }
      constraints << "{" << gMRI->getName(op.getReg()) << "}";
    }
  }

  // With all of these pieces, piece together the actual call to the inline ASM
  // string.
  llvm::SmallVector<llvm::Type *, 3> argTypes;
  for (auto val : operands)
    argTypes.push_back(val->getType());

  llvm::Type *returnTy;
  if (resultTypes.empty())
    returnTy = llvm::Type::getVoidTy(block->getContext());
  else if (resultTypes.size() == 1)
    returnTy = resultTypes[0];
  else
    returnTy = llvm::StructType::get(block->getContext(), resultTypes);

  auto asmTy = llvm::FunctionType::get(returnTy, argTypes, false);
  auto callee = llvm::InlineAsm::get(asmTy, asmString.str(), constraints.str(),
      false);
  llvm::Value *resultPack =
    llvm::CallInst::Create(callee, operands, "", block);

  // Unpack the called registers into the LLVM values.
  for (unsigned i = 0; i < resultTypes.size(); i++) {
    llvm::Value *result = resultTypes.size() == 1 ? resultPack :
      llvm::ExtractValueInst::Create(resultPack, i, "", block);
    llvm::Type *ty = resultTypes[i];
    // Cast vector outputs to iXYZ for R_WRITE.
    if (ty->isVectorTy()) {
      ty = llvm::Type::getIntNTy(block->getContext(),
        ty->getVectorNumElements() * 8);
      result = llvm::CastInst::Create(llvm::Instruction::BitCast, result,
        ty, "", block);
    }
    unsigned regNo = inst.getOperand(i).getReg();
    GENERIC_MC_WRITEREG(block, regNo, result);
  }
}