| //===-- EDMain.cpp - LLVM Enhanced Disassembly C API ----------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements the enhanced disassembler's public C API. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // FIXME: This code isn't layered right, the headers should be moved to | |
| // include llvm/MC/MCDisassembler or something. | |
| #include "../../lib/MC/MCDisassembler/EDDisassembler.h" | |
| #include "../../lib/MC/MCDisassembler/EDInst.h" | |
| #include "../../lib/MC/MCDisassembler/EDOperand.h" | |
| #include "../../lib/MC/MCDisassembler/EDToken.h" | |
| #include "llvm-c/EnhancedDisassembly.h" | |
| using namespace llvm; | |
| int EDGetDisassembler(EDDisassemblerRef *disassembler, | |
| const char *triple, | |
| EDAssemblySyntax_t syntax) { | |
| EDDisassembler::initialize(); | |
| EDDisassembler::AssemblySyntax Syntax; | |
| switch (syntax) { | |
| default: assert(0 && "Unknown assembly syntax!"); | |
| case kEDAssemblySyntaxX86Intel: | |
| Syntax = EDDisassembler::kEDAssemblySyntaxX86Intel; | |
| break; | |
| case kEDAssemblySyntaxX86ATT: | |
| Syntax = EDDisassembler::kEDAssemblySyntaxX86ATT; | |
| break; | |
| case kEDAssemblySyntaxARMUAL: | |
| Syntax = EDDisassembler::kEDAssemblySyntaxARMUAL; | |
| break; | |
| } | |
| EDDisassemblerRef ret = EDDisassembler::getDisassembler(triple, Syntax); | |
| if (!ret) | |
| return -1; | |
| *disassembler = ret; | |
| return 0; | |
| } | |
| int EDGetRegisterName(const char** regName, | |
| EDDisassemblerRef disassembler, | |
| unsigned regID) { | |
| const char *name = ((EDDisassembler*)disassembler)->nameWithRegisterID(regID); | |
| if (!name) | |
| return -1; | |
| *regName = name; | |
| return 0; | |
| } | |
| int EDRegisterIsStackPointer(EDDisassemblerRef disassembler, | |
| unsigned regID) { | |
| return ((EDDisassembler*)disassembler)->registerIsStackPointer(regID) ? 1 : 0; | |
| } | |
| int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler, | |
| unsigned regID) { | |
| return ((EDDisassembler*)disassembler)->registerIsProgramCounter(regID) ? 1:0; | |
| } | |
| unsigned int EDCreateInsts(EDInstRef *insts, | |
| unsigned int count, | |
| EDDisassemblerRef disassembler, | |
| ::EDByteReaderCallback byteReader, | |
| uint64_t address, | |
| void *arg) { | |
| unsigned int index; | |
| for (index = 0; index < count; ++index) { | |
| EDInst *inst = ((EDDisassembler*)disassembler)->createInst(byteReader, | |
| address, arg); | |
| if (!inst) | |
| return index; | |
| insts[index] = inst; | |
| address += inst->byteSize(); | |
| } | |
| return count; | |
| } | |
| void EDReleaseInst(EDInstRef inst) { | |
| delete ((EDInst*)inst); | |
| } | |
| int EDInstByteSize(EDInstRef inst) { | |
| return ((EDInst*)inst)->byteSize(); | |
| } | |
| int EDGetInstString(const char **buf, | |
| EDInstRef inst) { | |
| return ((EDInst*)inst)->getString(*buf); | |
| } | |
| int EDInstID(unsigned *instID, EDInstRef inst) { | |
| *instID = ((EDInst*)inst)->instID(); | |
| return 0; | |
| } | |
| int EDInstIsBranch(EDInstRef inst) { | |
| return ((EDInst*)inst)->isBranch(); | |
| } | |
| int EDInstIsMove(EDInstRef inst) { | |
| return ((EDInst*)inst)->isMove(); | |
| } | |
| int EDBranchTargetID(EDInstRef inst) { | |
| return ((EDInst*)inst)->branchTargetID(); | |
| } | |
| int EDMoveSourceID(EDInstRef inst) { | |
| return ((EDInst*)inst)->moveSourceID(); | |
| } | |
| int EDMoveTargetID(EDInstRef inst) { | |
| return ((EDInst*)inst)->moveTargetID(); | |
| } | |
| int EDNumTokens(EDInstRef inst) { | |
| return ((EDInst*)inst)->numTokens(); | |
| } | |
| int EDGetToken(EDTokenRef *token, | |
| EDInstRef inst, | |
| int index) { | |
| return ((EDInst*)inst)->getToken(*(EDToken**)token, index); | |
| } | |
| int EDGetTokenString(const char **buf, | |
| EDTokenRef token) { | |
| return ((EDToken*)token)->getString(*buf); | |
| } | |
| int EDOperandIndexForToken(EDTokenRef token) { | |
| return ((EDToken*)token)->operandID(); | |
| } | |
| int EDTokenIsWhitespace(EDTokenRef token) { | |
| return ((EDToken*)token)->type() == EDToken::kTokenWhitespace; | |
| } | |
| int EDTokenIsPunctuation(EDTokenRef token) { | |
| return ((EDToken*)token)->type() == EDToken::kTokenPunctuation; | |
| } | |
| int EDTokenIsOpcode(EDTokenRef token) { | |
| return ((EDToken*)token)->type() == EDToken::kTokenOpcode; | |
| } | |
| int EDTokenIsLiteral(EDTokenRef token) { | |
| return ((EDToken*)token)->type() == EDToken::kTokenLiteral; | |
| } | |
| int EDTokenIsRegister(EDTokenRef token) { | |
| return ((EDToken*)token)->type() == EDToken::kTokenRegister; | |
| } | |
| int EDTokenIsNegativeLiteral(EDTokenRef token) { | |
| if (((EDToken*)token)->type() != EDToken::kTokenLiteral) | |
| return -1; | |
| return ((EDToken*)token)->literalSign(); | |
| } | |
| int EDLiteralTokenAbsoluteValue(uint64_t *value, EDTokenRef token) { | |
| if (((EDToken*)token)->type() != EDToken::kTokenLiteral) | |
| return -1; | |
| return ((EDToken*)token)->literalAbsoluteValue(*value); | |
| } | |
| int EDRegisterTokenValue(unsigned *registerID, | |
| EDTokenRef token) { | |
| if (((EDToken*)token)->type() != EDToken::kTokenRegister) | |
| return -1; | |
| return ((EDToken*)token)->registerID(*registerID); | |
| } | |
| int EDNumOperands(EDInstRef inst) { | |
| return ((EDInst*)inst)->numOperands(); | |
| } | |
| int EDGetOperand(EDOperandRef *operand, | |
| EDInstRef inst, | |
| int index) { | |
| return ((EDInst*)inst)->getOperand(*(EDOperand**)operand, index); | |
| } | |
| int EDOperandIsRegister(EDOperandRef operand) { | |
| return ((EDOperand*)operand)->isRegister(); | |
| } | |
| int EDOperandIsImmediate(EDOperandRef operand) { | |
| return ((EDOperand*)operand)->isImmediate(); | |
| } | |
| int EDOperandIsMemory(EDOperandRef operand) { | |
| return ((EDOperand*)operand)->isMemory(); | |
| } | |
| int EDRegisterOperandValue(unsigned *value, EDOperandRef operand) { | |
| if (!((EDOperand*)operand)->isRegister()) | |
| return -1; | |
| *value = ((EDOperand*)operand)->regVal(); | |
| return 0; | |
| } | |
| int EDImmediateOperandValue(uint64_t *value, EDOperandRef operand) { | |
| if (!((EDOperand*)operand)->isImmediate()) | |
| return -1; | |
| *value = ((EDOperand*)operand)->immediateVal(); | |
| return 0; | |
| } | |
| int EDEvaluateOperand(uint64_t *result, EDOperandRef operand, | |
| ::EDRegisterReaderCallback regReader, void *arg) { | |
| return ((EDOperand*)operand)->evaluate(*result, regReader, arg); | |
| } | |
| #ifdef __BLOCKS__ | |
| struct ByteReaderWrapper { | |
| EDByteBlock_t byteBlock; | |
| }; | |
| static int readerWrapperCallback(uint8_t *byte, | |
| uint64_t address, | |
| void *arg) { | |
| struct ByteReaderWrapper *wrapper = (struct ByteReaderWrapper *)arg; | |
| return wrapper->byteBlock(byte, address); | |
| } | |
| unsigned int EDBlockCreateInsts(EDInstRef *insts, | |
| int count, | |
| EDDisassemblerRef disassembler, | |
| EDByteBlock_t byteBlock, | |
| uint64_t address) { | |
| struct ByteReaderWrapper wrapper; | |
| wrapper.byteBlock = byteBlock; | |
| return EDCreateInsts(insts, | |
| count, | |
| disassembler, | |
| readerWrapperCallback, | |
| address, | |
| (void*)&wrapper); | |
| } | |
| int EDBlockEvaluateOperand(uint64_t *result, EDOperandRef operand, | |
| EDRegisterBlock_t regBlock) { | |
| return ((EDOperand*)operand)->evaluate(*result, regBlock); | |
| } | |
| int EDBlockVisitTokens(EDInstRef inst, ::EDTokenVisitor_t visitor) { | |
| return ((EDInst*)inst)->visitTokens((llvm::EDTokenVisitor_t)visitor); | |
| } | |
| #else | |
| extern "C" unsigned int EDBlockCreateInsts() { | |
| return 0; | |
| } | |
| extern "C" int EDBlockEvaluateOperand() { | |
| return -1; | |
| } | |
| extern "C" int EDBlockVisitTokens() { | |
| return -1; | |
| } | |
| #endif |