static InstTransResult doCmpxchgRR(InstPtr ip,    BasicBlock      *&b,
                            const MCOperand &dstReg,
                            const MCOperand &srcReg) 
{
    NASSERT(dstReg.isReg());
    NASSERT(srcReg.isReg());


    Value   *acc;

    switch(width) {
        case 8:
            acc = R_READ<width>(b, X86::AL);
            break;
        case 16:
            acc = R_READ<width>(b, X86::AX);
            break;
        case 32:
            acc = R_READ<width>(b, X86::EAX);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }

    Value   *dstReg_v = R_READ<width>(b, dstReg.getReg());
    Value   *srcReg_v = R_READ<width>(b, srcReg.getReg());

    doCmpVV<width>(ip, b, acc, dstReg_v);

    Value   *Cmp = new ICmpInst(*b, CmpInst::ICMP_EQ, acc, dstReg_v);

    F_WRITE(b, ZF, Cmp);

    ///
    // ZF = Acc == DST
    // acc = select(ZF, acc, dst)
    // dst = select(ZF, src, dst)
    Value *new_acc = SelectInst::Create(Cmp, acc, dstReg_v, "", b);
    Value *new_dst = SelectInst::Create(Cmp, srcReg_v, dstReg_v, "", b); 

    R_WRITE<width>(b, dstReg.getReg(), new_dst);

    switch(width) {
        case 8:
            R_WRITE<width>(b, X86::AL, new_acc);
            break;
        case 16:
            R_WRITE<width>(b, X86::AX, new_acc);
            break;
        case 32:
            R_WRITE<width>(b, X86::EAX, new_acc);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }


    return ContinueBlock;
}
Exemple #2
0
SystemArchType SystemArch(llvm::Module *) {
  auto arch = ArchType();
  if (arch == llvm::Triple::x86) {
    return _X86_;
  } else if (arch == llvm::Triple::x86_64) {
    return _X86_64_;
  } else {
    throw TErr(__LINE__, __FILE__, "Unsupported architecture");
  }
}
Exemple #3
0
static bool LiftBlockIntoFunction(TranslationContext &ctx) {
  auto didError = false;

  //first, either create or look up the LLVM basic block for this native
  //block. we are either creating it for the first time, or, we are
  //going to look up a blank block
  auto block_name = ctx.natB->get_name();
  auto curLLVMBlock = ctx.va_to_bb[ctx.natB->get_base()];

  //then, create a basic block for every follow of this block, if we do not
  //already have that basic block in our LLVM CFG
  const auto &follows = ctx.natB->get_follows();
  for (auto succ_block_va : follows) {
    if (!ctx.va_to_bb.count(succ_block_va)) {
      throw TErr(__LINE__, __FILE__, "Missing successor block!");
    }
  }

  //now, go through each statement and translate it into LLVM IR
  //statements that branch SHOULD be the last statement in a block
  for (auto inst : ctx.natB->get_insts()) {
    ctx.natI = inst;
    switch (LiftInstIntoBlock(ctx, curLLVMBlock, true)) {
      case ContinueBlock:
        break;
      case EndBlock:
      case EndCFG:
        goto done;
      case TranslateErrorUnsupported:
        didError = !IgnoreUnsupportedInsts;
        goto done;
      case TranslateError:
        didError = true;
        goto done;
    }
  }
done:

  if (curLLVMBlock->getTerminator()) {
    return didError;
  }

  // we may need to insert a branch inst to the successor
  // if the block ended on a non-terminator (this happens since we
  // may split blocks in cfg recovery to avoid code duplication)
  if (follows.size() == 1) {
    llvm::BranchInst::Create(ctx.va_to_bb[follows.front()], curLLVMBlock);
  } else {
    new llvm::UnreachableInst(curLLVMBlock->getContext(), curLLVMBlock);
  }

  return didError;
}
Exemple #4
0
NTSTATUS EXTERNAL
DriverEntry(
    __in PDRIVER_OBJECT  DrvObj,
    __in PUNICODE_STRING RegPath
    )
{
    
    NTSTATUS                    status = STATUS_SUCCESS;
    HID_MINIDRIVER_REGISTRATION hidMinidriverRegistration = {0};

    TEnter(Func,("(DrvObj=%p,RegPath=%p)\n", DrvObj, RegPath));

    gDriverObj = DrvObj;
    DrvObj->MajorFunction[IRP_MJ_CREATE] =
    DrvObj->MajorFunction[IRP_MJ_CLOSE] = HbtnCreateClose;

    DrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HbtnInternalIoctl;

    DrvObj->MajorFunction[IRP_MJ_PNP]   = HbtnPnp;
    DrvObj->MajorFunction[IRP_MJ_POWER] = HbtnPower;
    DrvObj->DriverUnload                = HbtnUnload;
    DrvObj->DriverExtension->AddDevice  = HbtnAddDevice;

    //
    // Register with HIDCLASS.SYS module
    //
    RtlZeroMemory(&hidMinidriverRegistration,
                  sizeof(hidMinidriverRegistration));

    hidMinidriverRegistration.Revision            = HID_REVISION;
    hidMinidriverRegistration.DriverObject        = DrvObj;
    hidMinidriverRegistration.RegistryPath        = RegPath;
    hidMinidriverRegistration.DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
    hidMinidriverRegistration.DevicesArePolled    = FALSE;

    status = HidRegisterMinidriver(&hidMinidriverRegistration);

    if (!NT_SUCCESS(status))
    {
        LogError(ERRLOG_MINIDRV_REG_FAILED,
                 status,
                 UNIQUE_ERRID(0x10), NULL, NULL);
         TErr(("failed to register mini driver.\n"));
    }

    TExit(Func,("=%x\n", status));
    return status;
}       //DriverEntry
Exemple #5
0
llvm::CallingConv::ID getLLVMCC(ExternalCodeRef::CallingConvention cc) {
  switch (cc) {
    case ExternalCodeRef::CallerCleanup:
      return llvm::CallingConv::C;
    case ExternalCodeRef::CalleeCleanup:
      return llvm::CallingConv::X86_StdCall;
    case ExternalCodeRef::FastCall:
      return llvm::CallingConv::X86_FastCall;
    case ExternalCodeRef::McsemaCall:
      // mcsema internal calls are cdecl with one argument
      return llvm::CallingConv::C;
    default:
      throw TErr(__LINE__, __FILE__, "Unknown calling convention!");
      break;
  }

  return llvm::CallingConv::C;
}
static InstTransResult doCmpxchgRM(InstPtr ip,    BasicBlock      *&b,
                            Value           *dstAddr,
                            const MCOperand &srcReg) 
{
    NASSERT(dstAddr != NULL);
    NASSERT(srcReg.isReg());


    Value   *acc;

    switch(width) {
        case 8:
            acc = R_READ<width>(b, X86::AL);
            break;
        case 16:
            acc = R_READ<width>(b, X86::AX);
            break;
        case 32:
            acc = R_READ<width>(b, X86::EAX);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }

    //Value   *mem_v = M_READ<width>(ip, b, dstAddr);
    Value   *m_addr = NULL;

    unsigned addrspace = ip->get_addr_space();

    if( dstAddr->getType()->isPointerTy() == false ) {
		llvm::Type    *ptrTy = 
            Type::getIntNPtrTy(b->getContext(), width, addrspace);
        m_addr = new llvm::IntToPtrInst(dstAddr, ptrTy, "", b); 
	} 
    else if( dstAddr->getType() != Type::getIntNPtrTy(
                b->getContext(), width, addrspace) ) 
    {
		//we need to bitcast the pointer value to a pointer type of the appropriate width
		m_addr = CastInst::CreatePointerCast(dstAddr, 
                Type::getIntNPtrTy(b->getContext(), width, addrspace), "", b);
	} else {
        m_addr = dstAddr;
    }

    Value   *srcReg_v = R_READ<width>(b, srcReg.getReg());


    AtomicCmpXchgInst *cmpx = new AtomicCmpXchgInst(
            m_addr, 
            acc, 
            srcReg_v, 
            llvm::SequentiallyConsistent,
            llvm::SequentiallyConsistent,
            llvm::CrossThread, 
            b);
    cmpx->setVolatile(true);

    Value *cmpx_val = ExtractValueInst::Create(cmpx, 0, "cmpxchg_cmpx_val", b);
    Value *was_eq = ExtractValueInst::Create(cmpx, 1, "cmpxchg_was_eq", b);

    doCmpVV<width>(ip, b, acc, cmpx_val);


    F_WRITE(b, ZF, was_eq);

    Value *new_acc = SelectInst::Create(was_eq, acc, cmpx_val, "", b);

    switch(width) {
        case 8:
            R_WRITE<width>(b, X86::AL, new_acc);
            break;
        case 16:
            R_WRITE<width>(b, X86::AX, new_acc);
            break;
        case 32:
            R_WRITE<width>(b, X86::EAX, new_acc);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }


    return ContinueBlock;
}
Exemple #7
0
VOID __cdecl
LogDbgMsg(
    IN NTSTATUS ErrorCode,
    IN NTSTATUS NTStatus OPTIONAL,
    _In_z_ LPCSTR pszFormat,
    ...
    )
{
    #define MAX_ERRMSG_LEN      ((ERROR_LOG_MAXIMUM_SIZE -                     \
                                  FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)) \
                                 /sizeof(WCHAR))
    static char szErrMsg[MAX_ERRMSG_LEN] = {0};

    TEnter(Func, ("(ErrorCode=%x,NTStatus=%x,Format=%s)",
                  ErrorCode, NTStatus, pszFormat));

    TAssert(gDriverObj != NULL);
    if (gDriverObj != NULL)
    {
        va_list arglist;
        NTSTATUS status;
        size_t iLen = 0;
        ULONG_PTR iTotalLen;
        PIO_ERROR_LOG_PACKET ErrEntry;

        va_start(arglist, pszFormat);
        status = RtlStringCchVPrintfA(szErrMsg,
                               ARRAYSIZE(szErrMsg),
                               pszFormat,
                               arglist);
        va_end(arglist);
        if (NT_SUCCESS(status))
        {
            status = RtlStringCchLengthA(szErrMsg, ARRAYSIZE(szErrMsg), &iLen);
        }

        if (NT_SUCCESS(status))
        {
            iTotalLen = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) +
                        (iLen + 1)*sizeof(WCHAR);
            iTotalLen = max(iTotalLen, sizeof(IO_ERROR_LOG_PACKET));
            ErrEntry = IoAllocateErrorLogEntry(gDriverObj, (UCHAR)iTotalLen);
            if (ErrEntry)
            {
                ErrEntry->NumberOfStrings = 1;
                ErrEntry->ErrorCode = ErrorCode;
                ErrEntry->StringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET,
                                                      DumpData);
                mbstowcs((WCHAR *)ErrEntry->DumpData, szErrMsg, iLen);
                ErrEntry->FinalStatus = NTStatus;
                IoWriteErrorLogEntry(ErrEntry);
            }
            else
            {
                TWarn(("Failed to allocate error log entry (len=%d).",
                       (int)iTotalLen));
            }

            if (ErrorCode == ERRLOG_DEBUG_INFORMATION)
            {
                TInfo(("%s", szErrMsg));
            }
            else if (ErrorCode == ERRLOG_DEBUG_WARNING)
            {
                TWarn(("%s", szErrMsg));
            }
            else if (ErrorCode == ERRLOG_DEBUG_ERROR)
            {
                TErr(("%s", szErrMsg));
            }
        }
    }

    TExit(Func, ("!"));
    return;
}       //LogDbgMsg
Exemple #8
0
// Iterate over the list of external functions and insert them as
// global functions.
static void InitExternalCode(NativeModulePtr natMod, llvm::Module *M) {
  for (auto e : natMod->getExtCalls()) {
    auto conv = e->getCallingConvention();
    auto argCount = e->getNumArgs();
    auto symName = e->getSymbolName();
    auto funcSign = e->getFunctionSignature();

    // Create the function if it is not already there.
    auto &C = M->getContext();
    auto F = M->getFunction(symName);
    if (F) {
      continue;
    }

    if (ExternalCodeRef::McsemaCall == conv) {
       // normal mcsema function prototypes
      F = llvm::dyn_cast<llvm::Function>(M->getOrInsertFunction(
          ArchNameMcSemaCall(symName), LiftedFunctionType()));
      ArchSetCallingConv(M, F);
      F->setLinkage(llvm::GlobalValue::ExternalLinkage);
      continue;
    }

    std::vector<llvm::Type *> arguments;
    llvm::Type *returnType = nullptr;

    // Create arguments.
    const auto Arch = SystemArch(M);
    const auto OS = SystemOS(M);
    for (auto i = 0; i < argCount; i++) {
      if (_X86_64_ == Arch) {
        if (llvm::Triple::Win32 == OS) {
          if (funcSign.c_str()[i] == 'F') {
            arguments.push_back(llvm::Type::getDoubleTy(C));
          } else {
            arguments.push_back(llvm::Type::getInt64Ty(C));
          }
        } else if (llvm::Triple::Linux == OS) {
          arguments.push_back(llvm::Type::getInt64Ty(C));

        } else {
          TASSERT(false, "Unknown OS Type!");
        }
      } else {
        arguments.push_back(llvm::Type::getInt32Ty(C));
      }
    }

    //create function type
    switch (e->getReturnType()) {
      case ExternalCodeRef::NoReturn:
      case ExternalCodeRef::VoidTy:
        returnType = llvm::Type::getVoidTy(C);
        break;

      case ExternalCodeRef::Unknown:
      case ExternalCodeRef::IntTy:
        if (natMod->is64Bit()) {
          returnType = llvm::Type::getInt64Ty(C);
        } else {
          returnType = llvm::Type::getInt32Ty(C);
        }
        break;

      default:
        throw TErr(
            __LINE__, __FILE__,
            "Encountered an unknown return type while translating function");
    }

    auto FTy = llvm::FunctionType::get(returnType, arguments, false);
    if (e->isWeak()) {
      F = llvm::Function::Create(FTy, llvm::GlobalValue::ExternalWeakLinkage,
                                 symName, M);
    } else {
      F = llvm::Function::Create(FTy, llvm::GlobalValue::ExternalLinkage,
                                 symName, M);
    }

    if (e->getReturnType() == ExternalCodeRef::NoReturn) {
      F->setDoesNotReturn();
    }

    //set calling convention
    if (natMod->is64Bit()) {
      ArchSetCallingConv(M, F);
    } else {
      F->setCallingConv(getLLVMCC(conv));
    }
  }
}
Exemple #9
0
static bool InsertFunctionIntoModule(NativeModulePtr mod,
                                     NativeFunctionPtr func, llvm::Module *M) {
  auto &C = M->getContext();
  auto F = M->getFunction(func->get_name());
  if (!F) {
    throw TErr(__LINE__, __FILE__, "Could not get func " + func->get_name());
  }

  if (!F->empty()) {
    std::cout << "WARNING: Asking to re-insert function: " << func->get_name()
              << std::endl << "\tReturning current function instead"
              << std::endl;
    return true;
  }

  auto entryBlock = llvm::BasicBlock::Create(F->getContext(), "entry", F);
  ArchAllocRegisterVars(entryBlock);

  TranslationContext ctx;
  ctx.natM = mod;
  ctx.natF = func;
  ctx.natI = nullptr;
  ctx.M = M;
  ctx.F = F;

  // Create basic blocks for each basic block in the original function.
  for (auto block_info : func->get_blocks()) {
    ctx.va_to_bb[block_info.first] = llvm::BasicBlock::Create(
        C, block_info.second->get_name(), F);
  }

  // Create a branch from the end of the entry block to the first block
  llvm::BranchInst::Create(ctx.va_to_bb[func->get_start()], entryBlock);

  try {
    // Lift every basic block into the functions.
    auto error = false;
    for (auto block_info : func->get_blocks()) {
      ctx.natB = block_info.second;
      error = LiftBlockIntoFunction(ctx) || error;
      ctx.natB = nullptr;
    }

    // For ease of debugging generated code, don't allow lifted functions to
    // be inlined. This will make lifted and native call graphs one-to-one.
    F->addFnAttr(llvm::Attribute::NoInline);

    //we should be done, having inserted every block into the module
    return !error;

  } catch (std::exception &e) {
    std::cerr << "error: " << std::endl << e.what() << std::endl
              << "in function " << std::hex
              << ctx.natF->get_start() << std::endl;
    if (ctx.natB) {
      std::cerr << "in block " << std::hex << ctx.natB->get_base() << std::endl;
      if (ctx.natI) {
        std::cerr << "in inst " << std::hex << ctx.natI->get_loc() << std::endl;
      }
    }
    return false;
  }

  
}
static InstTransResult doCmpxchgRR(InstPtr ip,    BasicBlock      *&b,
                            const MCOperand &dstReg,
                            const MCOperand &srcReg) 
{
    NASSERT(dstReg.isReg());
    NASSERT(srcReg.isReg());

    Function    *F = b->getParent();
    BasicBlock  *AccEQDest = 
        BasicBlock::Create(b->getContext(), "AccEQDest", F);
    BasicBlock  *AccNEDest = 
        BasicBlock::Create(b->getContext(), "AccNEDest", F);
    BasicBlock  *done = 
        BasicBlock::Create(b->getContext(), "done", F);

    Value   *acc;

    switch(width) {
        case 8:
            acc = R_READ<width>(b, X86::AL);
            break;
        case 16:
            acc = R_READ<width>(b, X86::AX);
            break;
        case 32:
            acc = R_READ<width>(b, X86::EAX);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }

    Value   *dstReg_v = R_READ<width>(b, dstReg.getReg());
    Value   *srcReg_v = R_READ<width>(b, srcReg.getReg());

    doCmpVV<width>(ip, b, acc, dstReg_v);

    Value   *Cmp = new ICmpInst(*b, CmpInst::ICMP_EQ, acc, dstReg_v);
    BranchInst::Create(AccEQDest, AccNEDest, Cmp, b);

    // Acc == Dst
    F_SET(AccEQDest, "ZF");
    R_WRITE<width>(AccEQDest, dstReg.getReg(), srcReg_v);
    BranchInst::Create(done, AccEQDest);

    // Acc != Dst
    F_CLEAR(AccNEDest, "ZF");
    switch(width) {
        case 8:
            R_WRITE<width>(AccNEDest, X86::AL, dstReg_v);
            break;
        case 16:
            R_WRITE<width>(AccNEDest, X86::AX, dstReg_v);
            break;
        case 32:
            R_WRITE<width>(AccNEDest, X86::EAX, dstReg_v);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }
    BranchInst::Create(done, AccNEDest);

    b = done;

    return ContinueBlock;
}
static InstTransResult doCmpxchgRM(InstPtr ip,    BasicBlock      *&b,
                            Value           *dstAddr,
                            const MCOperand &srcReg) 
{
    NASSERT(dstAddr != NULL);
    NASSERT(srcReg.isReg());

    Function    *F = b->getParent();
    BasicBlock  *AccEQDest = 
        BasicBlock::Create(b->getContext(), "AccEQDest", F);
    BasicBlock  *AccNEDest = 
        BasicBlock::Create(b->getContext(), "AccNEDest", F);
    BasicBlock  *done = 
        BasicBlock::Create(b->getContext(), "done", F);

    Value   *acc;

    switch(width) {
        case 8:
            acc = R_READ<width>(b, X86::AL);
            break;
        case 16:
            acc = R_READ<width>(b, X86::AX);
            break;
        case 32:
            acc = R_READ<width>(b, X86::EAX);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }

    //Value   *mem_v = M_READ<width>(ip, b, dstAddr);
    Value   *m_addr = NULL;

    unsigned addrspace = ip->get_addr_space();

    if( dstAddr->getType()->isPointerTy() == false ) {
		llvm::Type    *ptrTy = 
            Type::getIntNPtrTy(b->getContext(), width, addrspace);
        m_addr = new llvm::IntToPtrInst(dstAddr, ptrTy, "", b); 
	} 
    else if( dstAddr->getType() != Type::getIntNPtrTy(
                b->getContext(), width, addrspace) ) 
    {
		//we need to bitcast the pointer value to a pointer type of the appropriate width
		m_addr = CastInst::CreatePointerCast(dstAddr, 
                Type::getIntNPtrTy(b->getContext(), width, addrspace), "", b);
	} else {
        m_addr = dstAddr;
    }

    Value   *srcReg_v = R_READ<width>(b, srcReg.getReg());


    AtomicCmpXchgInst *cmpx = new AtomicCmpXchgInst(
            m_addr, 
            acc, 
            srcReg_v, 
            llvm::SequentiallyConsistent,
            llvm::CrossThread, 
            b);
    cmpx->setVolatile(true);

    // needed for flags settings
    doCmpVV<width>(ip, b, acc, cmpx);

    Value   *Cmp = new ICmpInst(*b, CmpInst::ICMP_EQ, cmpx, acc);
    BranchInst::Create(AccEQDest, AccNEDest, Cmp, b);

    // Acc == Dst
    F_SET(AccEQDest, "ZF");
    //M_WRITE<width>(ip, AccEQDest, dstAddr, srcReg_v);
    BranchInst::Create(done, AccEQDest);

    // Acc != Dst
    F_CLEAR(AccNEDest, "ZF");
    switch(width) {
        case 8:
            R_WRITE<width>(AccNEDest, X86::AL, cmpx);
            break;
        case 16:
            R_WRITE<width>(AccNEDest, X86::AX, cmpx);
            break;
        case 32:
            R_WRITE<width>(AccNEDest, X86::EAX, cmpx);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }
    BranchInst::Create(done, AccNEDest);

    b = done;

    return ContinueBlock;
}
Exemple #12
0
Value *getAddrFromExpr( BasicBlock      *b,
                        NativeModulePtr mod,
                        const MCOperand &Obase,
                        const MCOperand &Oscale,
                        const MCOperand &Oindex,
                        const int64_t Odisp,
                        const MCOperand &Oseg,
                        bool dataOffset) 
{
    TASSERT(Obase.isReg(), "");
    TASSERT(Oscale.isImm(), "");
    TASSERT(Oindex.isReg(), "");
    TASSERT(Oseg.isReg(), "");

    unsigned    baseReg = Obase.getReg();
    int64_t     disp = Odisp;
	
	// specific function for 64 bit
    Value       *d = NULL;
    IntegerType *iTy = IntegerType::getInt64Ty(b->getContext());

    if( dataOffset ||  
        (mod && disp && baseReg != X86::RBP && baseReg!= X86::RSP) ) 
    {
        VA  baseGlobal;
        if( addrIsInData(disp, mod, baseGlobal, dataOffset ? 0 : 0x1000) ) {
            //we should be able to find a reference to this in global data 
            Module  *M = b->getParent()->getParent();
            string  sn = "data_0x" + to_string<VA>(baseGlobal, hex);
            GlobalVariable *gData = M->getNamedGlobal(sn);

            //if we thought it was a global, we should be able to
            //pin it to a global array we made during module setup
            if( gData == NULL) 
              throw TErr(__LINE__, __FILE__, "Global variable not found");

            // since globals are now a structure 
            // we cannot simply slice into them.
            // Need to get ptr and then add integer displacement to ptr
            Value   *globalGEPV[] =  
                {   ConstantInt::get(Type::getInt64Ty(b->getContext()), 0), 
                    ConstantInt::get(Type::getInt32Ty(b->getContext()), 0)};
            Instruction *globalGEP = 
                GetElementPtrInst::Create(gData,  globalGEPV, "", b);
            Type    *ty = Type::getInt64Ty(b->getContext());
            Value   *intVal = new PtrToIntInst(globalGEP, ty, "", b);
            uint32_t addr_offset = disp-baseGlobal;
            Value   *int_adjusted = 
                BinaryOperator::CreateAdd(intVal, CONST_V<64>(b, addr_offset), "", b);
            //then, assign this to the outer 'd' so that the rest of the 
            //logic picks up on that address instead of another address 
            d = int_adjusted;
        } 
    } else {

        //there is no disp value, or its relative to esp/ebp in which case
        //we might not want to do anything
    }

    if( d == NULL ) {
        //create a constant integer out of the raw displacement
        //we were unable to assign the displacement to an address
        d = ConstantInt::getSigned(iTy, disp);
    }

    Value   *rVal = NULL;

    //read the base register (if given)
    if( baseReg != X86::NoRegister && baseReg != X86::RIP) {
        rVal = R_READ<64>(b, baseReg);
    } else {
        //if the base is not present, just use 0
        rVal = CONST_V<64>(b, 0);
    }


    Value   *dispComp;
    dispComp = 
        BinaryOperator::Create( Instruction::Add, rVal, d, "", b);

    //add the index amount, if present
	if( Oindex.getReg() != X86::NoRegister ) {
		Value       *index = R_READ<64>(b, Oindex.getReg());
        
        int64_t scaleAmt = Oscale.getImm();
        if( scaleAmt > 1 ) {
            index = 
                BinaryOperator::CreateMul(index,CONST_V<64>(b, scaleAmt),"",b);
        }

		dispComp = 
			BinaryOperator::CreateAdd(dispComp, index, "", b);
        
    }

    //convert the resulting integer into a pointer type
    PointerType *piTy = Type::getInt64PtrTy(b->getContext());
    Value       *dispPtr = new IntToPtrInst(dispComp, piTy, "", b);
    
    return dispPtr;
}