static void StreamChar(llvm::raw_ostream& o, const char v) { if (isprint(v)) o << '\'' << v << '\''; else { o << "\\0x"; o.write_hex(v); } }
void printName(llvm::raw_ostream &out, ObjectPtr x) { switch (x->objKind) { case IDENTIFIER : { Identifier *y = (Identifier *)x.ptr(); if (_safeNames > 0) { out << "#"; for (unsigned i = 0; i < y->str.size(); ++i) { char ch = y->str[i]; if (isSafe(ch)) out << ch; else out << 'c' << (unsigned int)ch; } } else { out << "\""; for (unsigned i = 0; i < y->str.size(); ++i) { char ch = y->str[i]; switch (ch) { case '\0': out << "\\0"; break; case '\n': out << "\\n"; break; case '\r': out << "\\r"; break; case '\t': out << "\\t"; break; case '\f': out << "\\f"; break; case '\\': out << "\\\\"; break; case '\'': out << "\\'"; break; case '\"': out << "\\\""; break; default: if (ch >= '\x20' && ch <= '\x7E') out << ch; else { out << "\\x"; if (ch < 16) out << '0'; out.write_hex((unsigned long long int)ch); } break; } } out << "\""; } break; } case GLOBAL_VARIABLE : { GlobalVariable *y = (GlobalVariable *)x.ptr(); out << y->name->str; break; } case GLOBAL_ALIAS : { GlobalAlias *y = (GlobalAlias *)x.ptr(); out << y->name->str; break; } case RECORD_DECL : { RecordDecl *y = (RecordDecl *)x.ptr(); out << y->name->str; break; } case VARIANT_DECL : { VariantDecl *y = (VariantDecl *)x.ptr(); out << y->name->str; break; } case PROCEDURE : { Procedure *y = (Procedure *)x.ptr(); out << y->name->str; break; } case MODULE : { Module *m = (Module *)x.ptr(); out << m->moduleName; break; } case INTRINSIC : { IntrinsicSymbol *intrin = (IntrinsicSymbol *)x.ptr(); out << intrin->name->str; break; } case PRIM_OP : { out << primOpName((PrimOp *)x.ptr()); break; } case TYPE : { typePrint(out, (Type *)x.ptr()); break; } case VALUE_HOLDER : { ValueHolder *y = (ValueHolder *)x.ptr(); if (isStaticOrTupleOfStatics(y->type)) { printStaticOrTupleOfStatics(out, y->type); } else { EValuePtr ev = new EValue(y->type, y->buf); printValue(out, ev); } break; } case EXTERNAL_PROCEDURE : { ExternalProcedure *proc = (ExternalProcedure*)x.ptr(); out << "external " << proc->name->str; break; } default : { out << "UnknownNamedObject(" << x->objKind << ")"; break; } } }
DisassembleResult Disassemble(llvm::raw_ostream &pOutput, const char *pTriple, const char *pFuncName, const uint8_t *pFunc, size_t pFuncSize) { DisassembleResult result = kDisassembleSuccess; uint64_t i = 0; const llvm::MCSubtargetInfo *subtarget_info = NULL; const llvm::MCDisassembler *disassembler = NULL; const llvm::MCInstrInfo *mc_inst_info = NULL; const llvm::MCRegisterInfo *mc_reg_info = NULL; const llvm::MCAsmInfo *asm_info = NULL; llvm::MCInstPrinter *inst_printer = NULL; BufferMemoryObject *input_function = NULL; std::string error; const llvm::Target* target = llvm::TargetRegistry::lookupTarget(pTriple, error); if (target == NULL) { ALOGE("Invalid target triple for disassembler: %s (%s)!", pTriple, error.c_str()); return kDisassembleUnknownTarget; } subtarget_info = target->createMCSubtargetInfo(pTriple, /* CPU */"", /* Features */"");; if (subtarget_info == NULL) { result = kDisassembleFailedSetup; goto bail; } disassembler = target->createMCDisassembler(*subtarget_info); mc_inst_info = target->createMCInstrInfo(); mc_reg_info = target->createMCRegInfo(pTriple); asm_info = target->createMCAsmInfo(pTriple); if ((disassembler == NULL) || (mc_inst_info == NULL) || (mc_reg_info == NULL) || (asm_info == NULL)) { result = kDisassembleFailedSetup; goto bail; } inst_printer = target->createMCInstPrinter(asm_info->getAssemblerDialect(), *asm_info, *mc_inst_info, *mc_reg_info, *subtarget_info); if (inst_printer == NULL) { result = kDisassembleFailedSetup; goto bail; } input_function = new (std::nothrow) BufferMemoryObject(pFunc, pFuncSize); if (input_function == NULL) { result = kDisassembleOutOfMemory; goto bail; } // Disassemble the given function pOutput << "Disassembled code: " << pFuncName << "\n"; while (i < pFuncSize) { llvm::MCInst inst; uint64_t inst_size; llvm::MCDisassembler::DecodeStatus decode_result = disassembler->getInstruction(inst, inst_size, *input_function, i, llvm::nulls(), llvm::nulls()); switch (decode_result) { case llvm::MCDisassembler::Fail: { ALOGW("Invalid instruction encoding encountered at %llu of function %s " "under %s.", i, pFuncName, pTriple); i++; break; } case llvm::MCDisassembler::SoftFail: { ALOGW("Potentially undefined instruction encoding encountered at %llu " "of function %s under %s.", i, pFuncName, pTriple); // fall-through } case llvm::MCDisassembler::Success : { const uint8_t *inst_addr = pFunc + i; pOutput.indent(4); pOutput << "0x"; pOutput.write_hex(reinterpret_cast<uintptr_t>(inst_addr)); pOutput << ": 0x"; pOutput.write_hex(*reinterpret_cast<const uint32_t *>(inst_addr)); inst_printer->printInst(&inst, pOutput, /* Annot */""); pOutput << "\n"; i += inst_size; break; } } } pOutput << "\n"; bail: // Clean up delete input_function; delete inst_printer; delete asm_info; delete mc_reg_info; delete mc_inst_info; delete disassembler; delete subtarget_info; return result; }