Beispiel #1
0
void ARM64InstPrinter::printAMIndexed(const MCInst *MI, unsigned OpNum,
                                      unsigned Scale, raw_ostream &O) {
  const MCOperand MO1 = MI->getOperand(OpNum + 1);
  O << '[' << getRegisterName(MI->getOperand(OpNum).getReg());
  if (MO1.isImm()) {
    if (MO1.getImm() != 0)
      O << ", #" << (MO1.getImm() * Scale);
  } else {
    assert (MO1.isExpr() && "Unexpected operand type!");
    O << ", " << *MO1.getExpr();
  }
  O << ']';
}
Beispiel #2
0
// assume the immediate references code if:
// * we are dealing with a fully linked ELF
// * The immediate is in the range of a valid code or data section
static bool setHeuristicRef(ExecutableContainer *c,
        InstPtr I,
        int opnum,
        stack<VA> &funcs,
        raw_ostream &out,
        const std::string whichInst)
{
    MCOperand op;
    std::string imp_name;
    ElfTarget *elft = dynamic_cast<ElfTarget*>(c);
    op = I->get_inst().getOperand(opnum);
    LASSERT(op.isImm(), "No immediate operand for " + whichInst);
    VA imm = op.getImm();


    if(elft && elft->isLinked()) {
       if (elft->is_in_code(imm)) {
            // this instruction references code
            I->set_call_tgt(imm);
            // make sure we disassemble at this new address
            funcs.push(imm);
            out << "Found new function entry from " << whichInst << ": " << to_string<VA>(imm, hex) << "\n";
            return true;
       } else if (elft->is_in_data(imm)) {
            out << "Adding local data ref to: " << to_string<VA>(imm, hex) << "\n";
            I->set_data_offset(imm);
       } else if (c->find_import_name(imm, imp_name)) {
           out << "Import name is: " << imp_name << "\n";
       }
    }

    return false;
}
Beispiel #3
0
static InstTransResult doSubRI(InstPtr ip, BasicBlock *&b,
                               const MCOperand &dst,
                               const MCOperand &src1,
                               const MCOperand &src2)
{
    NASSERT(src1.isReg());
    NASSERT(src2.isImm());
    NASSERT(dst.isReg());

	// Read from src1.
    Value *srcReg = R_READ<dstWidth>(b, src1.getReg());

	// Create the constant value.
	Value *c = CONST_V<srcWidth>(b, src2.getImm());
	
	CastInst *cInst = CastInst::CreateIntegerCast(c, srcReg->getType(), true, "", b);  
	
	// Do the operation.
	Value *subRes = doSubVV<dstWidth>(ip, b, srcReg, cInst);

	// Store the result in dst.
	R_WRITE<dstWidth>(b, dst.getReg(), subRes);

    return ContinueBlock;
}
unsigned SparcMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                  SmallVectorImpl<MCFixup> &Fixups,
                  const MCSubtargetInfo &STI) const {

  if (MO.isReg())
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());

  if (MO.isImm())
    return MO.getImm();

  assert(MO.isExpr());
  const MCExpr *Expr = MO.getExpr();
  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
    MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
    Fixups.push_back(MCFixup::create(0, Expr, Kind));
    return 0;
  }

  int64_t Res;
  if (Expr->evaluateAsAbsolute(Res))
    return Res;

  llvm_unreachable("Unhandled expression!");
  return 0;
}
Beispiel #5
0
uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
                                              const MCOperand &MO,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const {
  if (MO.isReg()) {
    if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
      return MRI.getEncodingValue(MO.getReg());
    return getHWReg(MO.getReg());
  }

  if (MO.isExpr()) {
    const MCSymbolRefExpr *Expr = cast<MCSymbolRefExpr>(MO.getExpr());
    // We put rodata at the end of code section, then map the entire
    // code secetion as vtx buf. Thus the section relative address is the
    // correct one.
    // Each R600 literal instruction has two operands
    // We can't easily get the order of the current one, so compare against
    // the first one and adjust offset.
    const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 4;
    Fixups.push_back(MCFixup::create(offset, Expr, FK_SecRel_4, MI.getLoc()));
    return 0;
  }

  assert(MO.isImm());
  return MO.getImm();
}
Beispiel #6
0
static InstTransResult doPSLLri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src)
{
    NASSERT(src.isImm());

    Value *shift_count = CONST_V<128>(b, src.getImm());

    return doNewShift<width, Instruction::Shl>(b, dst, shift_count, CONST_V<128>(b, 0));
}
Beispiel #7
0
void SystemZInstPrinter::printOperand(const MCOperand &MO, raw_ostream &O) {
    if (MO.isReg())
        O << '%' << getRegisterName(MO.getReg());
    else if (MO.isImm())
        O << MO.getImm();
    else if (MO.isExpr())
        O << *MO.getExpr();
    else
        llvm_unreachable("Invalid operand");
}
Beispiel #8
0
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned
AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const {
  if (MO.isReg())
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());

  assert(MO.isImm() && "did not expect relocated expression");
  return static_cast<unsigned>(MO.getImm());
}
Beispiel #9
0
static InstTransResult doMIMov(InstPtr ip, BasicBlock *&b,
                        Value           *dstAddr,
                        const MCOperand &src)
{
    //MOV <m>, <imm>
    //store the constant in src into dstAddr
    NASSERT(dstAddr != NULL);
    NASSERT(src.isImm());

    return doMIMovV<width>(ip, b, dstAddr, CONST_V<width>(b, src.getImm()));
}
Beispiel #10
0
static InstTransResult doPEXTRWmr(InstPtr ip, BasicBlock *&b, Value *memAddr, const MCOperand &src, const MCOperand &order)
{
    NASSERT(src.isReg());
    NASSERT(order.isImm());

    Value *vec = R_READ<128>(b, src.getReg());
    
    Value *item = doExtraction<128,16>(b, vec, order.getImm());

    M_WRITE<16>(ip, b, memAddr, item);
    return ContinueBlock;
}
Beispiel #11
0
static InstTransResult doRIMov(InstPtr ip, BasicBlock *&b,
                        const MCOperand &src,
                        const MCOperand &dst)
{
    //MOV <r>, <imm>
    NASSERT(src.isImm());
    NASSERT(dst.isReg());

    //write the constant into the supplied register
    R_WRITE<width>(b, dst.getReg(), CONST_V<width>(b, src.getImm()));

    return ContinueBlock;
}
Beispiel #12
0
static InstTransResult doPSHUFDri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src, const MCOperand &order)
{
    NASSERT(dst.isReg());
    NASSERT(src.isReg());
    NASSERT(order.isImm());

    Value *input = R_READ<128>(b, src.getReg());
    
    Value *shuffled = doShuffle<128,32>(b, input, order.getImm());

    R_WRITE<128>(b, dst.getReg(), shuffled);
    return ContinueBlock;
}
Beispiel #13
0
static InstTransResult doPSHUFDmi(InstPtr ip, BasicBlock *&b, const MCOperand &dst, Value *mem_addr, const MCOperand &order)
{
    NASSERT(dst.isReg());
    NASSERT(order.isImm());


    Value *input = M_READ<128>(ip, b, mem_addr);
    
    Value *shuffled = doShuffle<128,32>(b, input, order.getImm());

    R_WRITE<128>(b, dst.getReg(), shuffled);
    return ContinueBlock;
}
unsigned
RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                                      SmallVectorImpl<MCFixup> &Fixups,
                                      const MCSubtargetInfo &STI) const {

  if (MO.isReg())
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());

  if (MO.isImm())
    return static_cast<unsigned>(MO.getImm());

  llvm_unreachable("Unhandled expression!");
  return 0;
}
Beispiel #15
0
static InstTransResult doPINSRWrmi(InstPtr ip, BasicBlock *&b, const MCOperand &dst, Value *memAddr, const MCOperand &order)
{

    NASSERT(dst.isReg());
    NASSERT(order.isImm());

    Value *vec = R_READ<128>(b, dst.getReg());
    Value *elem = M_READ<16>(ip, b, memAddr);
    
    Value *new_vec = doInsertion<128,16>(b, vec, elem, order.getImm());

    R_WRITE<128>(b, dst.getReg(), new_vec);
    return ContinueBlock;
}
Beispiel #16
0
static InstTransResult doPINSRWrri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src, const MCOperand &order)
{
    NASSERT(dst.isReg());
    NASSERT(src.isReg());
    NASSERT(order.isImm());

    Value *vec = R_READ<128>(b, dst.getReg());
    Value *elem = R_READ<16>(b, src.getReg());
    
    Value *new_vec = doInsertion<128,16>(b, vec, elem, order.getImm());

    R_WRITE<128>(b, dst.getReg(), new_vec);
    return ContinueBlock;
}
Beispiel #17
0
static InstTransResult doXorMI(InstPtr ip, BasicBlock *&b,
                               Value           *addr,
                               const MCOperand &imm)
{
    TASSERT(addr != NULL, "");
    TASSERT(imm.isImm(), "");

    Value *fromMem = M_READ<width>(ip, b, addr);
    Value *fromImm = CONST_V<width>(b, imm.getImm());

    Value *res = doXorVV<width>(ip, b, fromMem, fromImm);
    M_WRITE<width>(ip, b, addr, res);

    return ContinueBlock;
}
Beispiel #18
0
MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
                                          MCInst const &Inst,
                                          MCOperand const &MO) {
  assert(HexagonMCInstrInfo::isExtendable(MCII, Inst) ||
         HexagonMCInstrInfo::isExtended(MCII, Inst));

  MCInst XMI;
  XMI.setOpcode(Hexagon::A4_ext);
  if (MO.isImm())
    XMI.addOperand(MCOperand::createImm(MO.getImm() & (~0x3f)));
  else if (MO.isExpr())
    XMI.addOperand(MCOperand::createExpr(MO.getExpr()));
  else
    llvm_unreachable("invalid extendable operand");
  return XMI;
}
Beispiel #19
0
static InstTransResult doSubMI(InstPtr ip, BasicBlock *&b,
                               Value           *addr,
                               const MCOperand &imm)
{
    NASSERT(addr != NULL);
    NASSERT(imm.isImm());

    Value *mem_v = M_READ<width>(ip, b, addr);
    Value *c = CONST_V<width>(b, imm.getImm());

    Value *res = doSubVV<width>(ip, b, mem_v, c);

    M_WRITE<width>(ip, b, addr, res);

    return ContinueBlock;
}
Beispiel #20
0
static InstTransResult doXorRI(InstPtr ip, BasicBlock *&b,
                               const MCOperand &dst,
                               const MCOperand &o1,
                               const MCOperand &o2)
{
    TASSERT(dst.isReg(), "");
    TASSERT(o1.isReg(), "");
    TASSERT(o2.isImm(), "");

    Value *o1_v = R_READ<width>(b, o1.getReg());
    Value *o2_v = CONST_V<width>(b, o2.getImm());

    R_WRITE<width>(b, dst.getReg(), doXorVV<width>(ip, b, o1_v, o2_v));

    return ContinueBlock;
}
void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
                                        ARMAsmPrinter &AP) {
  OutMI.setOpcode(MI->getOpcode());

  // In the MC layer, we keep modified immediates in their encoded form
  bool EncodeImms = false;
  switch (MI->getOpcode()) {
  default: break;
  case ARM::MOVi:
  case ARM::MVNi:
  case ARM::CMPri:
  case ARM::CMNri:
  case ARM::TSTri:
  case ARM::TEQri:
  case ARM::MSRi:
  case ARM::ADCri:
  case ARM::ADDri:
  case ARM::ADDSri:
  case ARM::SBCri:
  case ARM::SUBri:
  case ARM::SUBSri:
  case ARM::ANDri:
  case ARM::ORRri:
  case ARM::EORri:
  case ARM::BICri:
  case ARM::RSBri:
  case ARM::RSBSri:
  case ARM::RSCri:
    EncodeImms = true;
    break;
  }

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    if (AP.lowerOperand(MO, MCOp)) {
      if (MCOp.isImm() && EncodeImms) {
        int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
        if (Enc != -1)
          MCOp.setImm(Enc);
      }
      OutMI.addOperand(MCOp);
    }
  }
}
Beispiel #22
0
static InstTransResult doSbbRI(InstPtr ip, BasicBlock *&b,
                               const MCOperand &o1,
                               const MCOperand &o2,
                               const MCOperand &dst)
{
    NASSERT(o1.isReg());
    NASSERT(o2.isImm());
    NASSERT(dst.isReg());

    Value *r1 = R_READ<width>(b, o1.getReg());
    Value *c = CONST_V<width>(b, o2.getImm());

    Value *res = doSbbVV<width>(ip, b, r1, c);

    R_WRITE<width>(b, dst.getReg(), res);

    return ContinueBlock;
}
Beispiel #23
0
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned Cpu0MCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                  SmallVectorImpl<MCFixup> &Fixups,
                  const MCSubtargetInfo &STI) const {
  if (MO.isReg()) {
    unsigned Reg = MO.getReg();
    unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
    return RegNo;
  } else if (MO.isImm()) {
    return static_cast<unsigned>(MO.getImm());
  } else if (MO.isFPImm()) {
    return static_cast<unsigned>(APFloat(MO.getFPImm())
        .bitcastToAPInt().getHiBits(32).getLimitedValue());
  }
  // MO must be an Expr.
  assert(MO.isExpr());
  return getExprOpValue(MO.getExpr(),Fixups, STI);
}
Beispiel #24
0
static InstTransResult doIMulRRI(InstPtr ip,   BasicBlock      *&b,
                            const MCOperand &dst,
                            const MCOperand &lhs,
                            const MCOperand &rhs)
{
    NASSERT(dst.isReg());
    NASSERT(lhs.isReg());
    NASSERT(rhs.isImm());

    Value   *res = 
        doIMulVVV<width>(ip, b,
                        R_READ<width>(b, lhs.getReg()),
                        CONST_V<width>(b, rhs.getImm()));

    R_WRITE<width>(b, dst.getReg(), res);

    return ContinueBlock;
}
Beispiel #25
0
void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
                               SmallVectorImpl<MCInst> &Instructions) {
  MCOperand MCRegOp = Inst.getOperand(0);
  MCOperand MCValOp = Inst.getOperand(1);
  assert(MCRegOp.isReg());
  assert(MCValOp.isImm() || MCValOp.isExpr());

  // the imm operand can be either an expression or an immediate.
  bool IsImm = Inst.getOperand(1).isImm();
  uint64_t ImmValue = IsImm ? MCValOp.getImm() : 0;
  const MCExpr *ValExpr;
  if (IsImm)
    ValExpr = MCConstantExpr::Create(ImmValue, getContext());
  else
    ValExpr = MCValOp.getExpr();

  MCOperand PrevReg = MCOperand::createReg(Sparc::G0);

  if (!IsImm || (ImmValue & ~0x1fff)) {
    MCInst TmpInst;
    const MCExpr *Expr =
        SparcMCExpr::Create(SparcMCExpr::VK_Sparc_HI, ValExpr, getContext());
    TmpInst.setLoc(IDLoc);
    TmpInst.setOpcode(SP::SETHIi);
    TmpInst.addOperand(MCRegOp);
    TmpInst.addOperand(MCOperand::createExpr(Expr));
    Instructions.push_back(TmpInst);
    PrevReg = MCRegOp;
  }

  if (!IsImm || ((ImmValue & 0x1fff) != 0 || ImmValue == 0)) {
    MCInst TmpInst;
    const MCExpr *Expr =
        SparcMCExpr::Create(SparcMCExpr::VK_Sparc_LO, ValExpr, getContext());
    TmpInst.setLoc(IDLoc);
    TmpInst.setOpcode(SP::ORri);
    TmpInst.addOperand(MCRegOp);
    TmpInst.addOperand(PrevReg);
    TmpInst.addOperand(MCOperand::createExpr(Expr));
    Instructions.push_back(TmpInst);
  }
}
Beispiel #26
0
static InstTransResult doPEXTRWri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src, const MCOperand &order)
{
    NASSERT(dst.isReg());
    NASSERT(src.isReg());
    NASSERT(order.isImm());

    Value *vec = R_READ<128>(b, src.getReg());
    
    Value *item = doExtraction<128,16>(b, vec, order.getImm());

    // upper bits are set to zero
    Value *extItem  = new ZExtInst(
            item,
            Type::getInt32Ty(b->getContext()),
            "",
            b);

    R_WRITE<32>(b, dst.getReg(), extItem);
    return ContinueBlock;
}
Beispiel #27
0
static InstTransResult doIMulRRI8(InstPtr ip,  BasicBlock      *&b,
                            const MCOperand &dst,
                            const MCOperand &lhs,
                            const MCOperand &rhs)
{
    NASSERT(dst.isReg());
    NASSERT(lhs.isReg());
    NASSERT(rhs.isImm());

    Value   *vRhs = CONST_V<8>(b, rhs.getImm());
    Type    *sx = Type::getIntNTy(b->getContext(), width);
    Value   *vRhs_x = new SExtInst(vRhs, sx, "", b); 

    Value   *res = 
        doIMulVVV<width>(ip, b,
                        R_READ<width>(b, lhs.getReg()),
                        vRhs_x);

    R_WRITE<width>(b, dst.getReg(), res);

    return ContinueBlock;
}
Beispiel #28
0
static InstTransResult doSubRI(InstPtr ip, BasicBlock *&b,
                               const MCOperand &dst,
                               const MCOperand &src1,
                               const MCOperand &src2)
{
    NASSERT(src1.isReg());
    NASSERT(src2.isImm());
    NASSERT(dst.isReg());

	// Read from src1.
    Value *srcReg = R_READ<width>(b, src1.getReg());

	// Create the constant value.
	Value *c = CONST_V<width>(b, src2.getImm());

	// Do the operation.
	Value *subRes = doSubVV<width>(ip, b, srcReg, c);

	// Store the result in dst.
	R_WRITE<width>(b, dst.getReg(), subRes);

    return ContinueBlock;
}
static InstTransResult doRetI(BasicBlock *&b, const MCOperand &o) {
    TASSERT(o.isImm(), "Operand not immediate");

    Value   *c = CONST_V<32>(b, o.getImm());
    Value   *rESP = R_READ<32>(b, X86::ESP);
    Value       *fromStack = M_READ_0<32>(b, rESP);
    TASSERT(fromStack != NULL, "Could not read value from stack");

    //add the immediate to ESP
    Value       *rESP_1 = 
        BinaryOperator::CreateAdd(rESP, c, "", b);

    //add pointer width to ESP
    Value       *nESP =
        BinaryOperator::CreateAdd(rESP_1, CONST_V<32>(b, 4), "", b);

    //write back to ESP
    R_WRITE<32>(b, X86::ESP, nESP); 

    //spill all locals into the structure
    writeLocalsToContext(b, 32, ABIRetStore);
    ReturnInst::Create(b->getContext(), b); 
    return EndCFG;
}
Beispiel #30
0
NativeBlockPtr decodeBlock( ExecutableContainer *c, 
                            ExternalFunctionMap &f,
                            LLVMByteDecoder     &d,
                            stack<VA>           &blockChildren,
                            VA                  e,
                            stack<VA>           &funcs,
                            raw_ostream         &out)
{
  NativeBlockPtr  B = NativeBlockPtr(new NativeBlock(e, d.getPrinter()));
  VA              curAddr = e;
  bool            has_follow = true;

out << "Processing block: " << B->get_name() << "\n";
do
  {
    InstPtr I = d.getInstFromBuff(curAddr, c);

    //I, if a terminator, will have true and false targets 
    //filled in. I could be an indirect branch of some kind,
    //we will deal with that here. we will also deal with the 
    //instruction if it is a data instruction with relocation
   
    out << to_string<VA>(I->get_loc(), hex) << ":";
    out << I->printInst() << "\n";

    if(I->get_tr() != 0) {
      B->add_follow(I->get_tr());
      has_follow = false;
      out << "Adding block: " << to_string<VA>(I->get_tr(), hex) << "\n";
      blockChildren.push(I->get_tr());
    }

    if(I->get_fa() != 0) {
      B->add_follow(I->get_fa());
      has_follow = false;
      out << "Adding block: " << to_string<VA>(I->get_fa(), hex) << "\n";
      blockChildren.push(I->get_fa());
    }

    if(I->terminator()) {
      has_follow = false;
    }

    //do we need to add a data reference to this instruction?
    //again, because there is no offset information in the 
    //instruction decoder, for now we just ask if every addr
    //in the inst is relocated
    for(uint32_t i = 0; i < I->get_len(); i++) {
      VA addrInInst = curAddr+i;
      if(c->is_addr_relocated(addrInInst)) {
        VA  addr = 0;
        std::string has_imp;

        // this instruction has a relocation
        // save the relocation offset for later
        I->set_reloc_offset(i);

        //get the offset for this address
        //add it as a data offset to the instruction
        if (c->find_import_name(addrInInst, has_imp) )  {

            if(f.is_data(has_imp)) 
            {
                ExternalDataRefPtr data_p = makeExtDataRefFromString(has_imp, f);
                out << "Adding external data ref: " << has_imp << "\n";
                I->set_ext_data_ref(data_p);
            }
            else
            {
                ExternalCodeRefPtr code_p = makeExtCodeRefFromString(has_imp, f);
                LASSERT(code_p, "Failed to get ext call from map for symbol: "+has_imp);
                //maybe, this call doesn't return, in which case, 
                //we should kill the decoding of this flow
                if(code_p->getReturnType() == ExternalCodeRef::NoReturn) {
                    has_follow = false;
                }
                out << "Adding external code ref: " << has_imp << "\n";
                I->set_ext_call_target(code_p);
            }
                    
        } else if(c->relocate_addr(addrInInst, addr)) {
            bool can_ref_code = canInstructionReferenceCode(I);
            bool is_reloc_code = isAddrOfType(c, addr, ExecutableContainer::CodeSection);
            bool is_reloc_data = isAddrOfType(c, addr, ExecutableContainer::DataSection);
            unsigned opc = I->get_inst().getOpcode();

            if(isBranchViaMemory(I)) {
                out << "Detect branch via memory, relocation handled later\n";      
            }
            // this instruction can reference code and does
            // reference code
            // so we assume the code points to a function
            else if( can_ref_code && is_reloc_code ) {
                list<VA> new_funcs;
                if(dataInCodeHeuristic(c, I, addr, new_funcs)) {
                    // add new functions to our functions list
                    for(list<VA>::const_iterator nfi = new_funcs.begin();
                            nfi != new_funcs.end();
                            nfi++)
                    {
                        funcs.push(*nfi);
                    }

                    I->set_data_offset(addr);
                } else {
                    I->set_call_tgt(addr);
                    out << "Adding: 0x" << to_string<VA>(addr, hex) << " as target\n";
                    funcs.push(addr);
                }
            } 
            // this instruction can't reference code and points to .text
            // or references data. Treat as data element
            // TODO: extract this from .text and shove into .data?
            else if(( !can_ref_code && is_reloc_code) || is_reloc_data )
            {
              I->set_data_offset(addr);
            } else {
              out << "WARNING: relocation points to neither code nor data:" << to_string<VA>(addr, hex) << "\n";
            }

        } else {
            out << "*NOT* Relocating relocatable addr:" << to_string<uint32_t>(addrInInst, hex) << "\n";
        }
        break;
      }
    }

    //is this instruction an external call?
    //in a COFF binary, the pcrel call can refer to an 
    //external symbol that has been relocated
    //so, get the string that corresponds, and 
    //provide the translation using the function map
    MCOperand op;
    string  imp;
    switch(I->get_inst().getOpcode()) {
      case X86::JMP32m:
          {
            string  thunkSym;
            bool r = c->find_import_name(curAddr+2, thunkSym);
            if(r) {
                // this goes to an external API call
                out << "Adding external code ref via JMP: " << thunkSym << "\n";
                ExternalCodeRefPtr p = makeExtCodeRefFromString(thunkSym, f);
                I->set_ext_call_target(p);
                has_follow = false;
            } else {
                // this is an internal jmp. probably a jump table.
                bool did_jmptable = handlePossibleJumpTable(c, B, I, curAddr, funcs, blockChildren, out); 

                LASSERT(did_jmptable, "JMP32m processing aborted: couldn't parse jumptable");
            }
          }
          break;
      case X86::CALLpcrel32:
        //this could be an external call in COFF, or not
        op = I->get_inst().getOperand(0);
        LASSERT(op.isImm(), "Nonsense for CALLpcrel32");
        if(op.getImm() !=0) {
          VA    callTgt = curAddr+op.getImm()+I->get_len();
          bool  foldFunc = false;
          //speculate about callTgt
          InstPtr spec = d.getInstFromBuff(callTgt, c);
          if(spec->terminator() && spec->get_inst().getOpcode() == X86::JMP32m) {
            string  thunkSym;
            bool r = c->find_import_name(callTgt+2, thunkSym);
            LASSERT(r, "Need to find thunk import addr");
            ExternalCodeRefPtr p = makeExtCodeRefFromString(thunkSym, f);
            I->set_ext_call_target(p);
            foldFunc = true;
            if(p->getReturnType() == ExternalCodeRef::NoReturn) {
              has_follow = false;
            }
          }
          if(foldFunc == false) {
            //add this to our list of funcs to search
            funcs.push(callTgt);
          }
        } else {
          //check to see if this is an external call...
          if(I->has_ext_call_target() == false) {
            // may be a local call
            VA addr=curAddr+1, relo_addr=0;
            out << "Symbol not found, maybe a local call\n";
            if(c->relocate_addr(addr, relo_addr)){
                out << "Found local call to: " << to_string<VA>(relo_addr, hex) << "\n";
                I->set_call_tgt(relo_addr);
                out << "Adding: 0x" << to_string<VA>(relo_addr, hex) << " as target\n";
                funcs.push(relo_addr);
            } else {
                out << "Could not relocate addr for local call at: ";
                out << to_string<VA>(curAddr, hex) << "\n";
            }
          } else {
            out << "External call to: " << I->get_ext_call_target()->getSymbolName() << "\n";
          }
        }
        break;

      case X86::CALL32m:
        //this should be a call to an external, or we have no idea
        //so we need to try and look up the symbol that we're calling at this address...
        if(c->find_import_name(curAddr+2, imp)) {
          ExternalCodeRefPtr p = makeExtCodeRefFromString(imp, f);
          LASSERT(p, "Failed to get ext call from map for symbol"+imp);
          
          out << "Calling symbol: " << p->getSymbolName() << "\n";
          if(p->getReturnType() == ExternalCodeRef::NoReturn) {
            has_follow = false;
          }
          I->set_ext_call_target(p);
        } else {
          out << "Cannot find symbol at address ";
          out << to_string<VA>(curAddr, hex) << "\n";
        }
        break;
    }

    B->add_inst(I);
    curAddr += I->get_len();
  } while(has_follow);

  //we have built a basic block, it might contain
  //multiple calls, but it only has one terminator
  //which is either a ret or a branch
  return B;
}