├── README.md ├── LICENSE ├── xdisasmcore.cmake ├── xdisasmcore.pri ├── Modules ├── capstone_bridge.h ├── xmacho_commands.h ├── x7zip_properties.h ├── capstone_bridge.cpp ├── x7zip_properties.cpp └── xmacho_commands.cpp ├── xdisasmcore.h ├── xdisasmabstract.h ├── xdisasmabstract.cpp └── xdisasmcore.cpp /README.md: -------------------------------------------------------------------------------- 1 | # XDisasmCore 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 hors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /xdisasmcore.cmake: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_CURRENT_LIST_DIR}) 2 | include_directories(${CMAKE_CURRENT_LIST_DIR}/Modules) 3 | 4 | if (NOT DEFINED XBINARY_SOURCES) 5 | include(${CMAKE_CURRENT_LIST_DIR}/../Formats/xbinary.cmake) 6 | set(XDISASMCORE_SOURCES ${XDISASMCORE_SOURCES} ${XBINARY_SOURCES}) 7 | endif() 8 | if (NOT DEFINED XCAPSTONE_SOURCES) 9 | include(${CMAKE_CURRENT_LIST_DIR}/../XCapstone/xcapstone.cmake) 10 | set(XDISASMCORE_SOURCES ${XDISASMCORE_SOURCES} ${XCAPSTONE_SOURCES}) 11 | endif() 12 | 13 | set(XDISASMCORE_SOURCES 14 | ${XDISASMCORE_SOURCES} 15 | ${CMAKE_CURRENT_LIST_DIR}/Modules/capstone_bridge.cpp 16 | ${CMAKE_CURRENT_LIST_DIR}/Modules/capstone_bridge.h 17 | ${CMAKE_CURRENT_LIST_DIR}/Modules/x7zip_properties.cpp 18 | ${CMAKE_CURRENT_LIST_DIR}/Modules/x7zip_properties.h 19 | ${CMAKE_CURRENT_LIST_DIR}/Modules/xmacho_commands.cpp 20 | ${CMAKE_CURRENT_LIST_DIR}/Modules/xmacho_commands.h 21 | ${CMAKE_CURRENT_LIST_DIR}/xdisasmcore.cpp 22 | ${CMAKE_CURRENT_LIST_DIR}/xdisasmcore.h 23 | ${CMAKE_CURRENT_LIST_DIR}/xdisasmabstract.cpp 24 | ${CMAKE_CURRENT_LIST_DIR}/xdisasmabstract.h 25 | ) 26 | -------------------------------------------------------------------------------- /xdisasmcore.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | INCLUDEPATH += $$PWD/Modules 4 | DEPENDPATH += $$PWD/Modules 5 | 6 | HEADERS += \ 7 | $$PWD/Modules/x7zip_properties.h \ 8 | $$PWD/Modules/xmacho_commands.h \ 9 | $$PWD/Modules/capstone_bridge.h \ 10 | $$PWD/xdisasmcore.h \ 11 | $$PWD/xdisasmabstract.h 12 | 13 | SOURCES += \ 14 | $$PWD/Modules/x7zip_properties.cpp \ 15 | $$PWD/Modules/xmacho_commands.cpp \ 16 | $$PWD/Modules/capstone_bridge.cpp \ 17 | $$PWD/xdisasmcore.cpp \ 18 | $$PWD/xdisasmabstract.cpp 19 | 20 | !contains(XCONFIG, xbinary) { 21 | XCONFIG += xbinary 22 | include($$PWD/../Formats/xbinary.pri) 23 | } 24 | 25 | contains(XCONFIG, use_capstone_x86) { 26 | !contains(XCONFIG, xcapstone_x86) { 27 | XCONFIG += xcapstone_x86 28 | include($$PWD/../XCapstone/xcapstone_x86.pri) 29 | } 30 | } 31 | 32 | !contains(XCONFIG, use_capstone_x86) { 33 | !contains(XCONFIG, xcapstone) { 34 | XCONFIG += xcapstone 35 | include($$PWD/../XCapstone/xcapstone.pri) 36 | } 37 | } 38 | 39 | DISTFILES += \ 40 | $$PWD/LICENSE \ 41 | $$PWD/README.md \ 42 | $$PWD/xdisasmcore.cmake 43 | -------------------------------------------------------------------------------- /Modules/capstone_bridge.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #ifndef CAPSTONE_BRIDGE_H 23 | #define CAPSTONE_BRIDGE_H 24 | 25 | #include "../xdisasmabstract.h" 26 | #include "xcapstone.h" 27 | 28 | class Capstone_Bridge : public XDisasmAbstract { 29 | Q_OBJECT 30 | public: 31 | explicit Capstone_Bridge(XBinary::DM disasmMode, XBinary::SYNTAX syntax = XBinary::SYNTAX_DEFAULT, QObject *pParent = nullptr); 32 | ~Capstone_Bridge(); 33 | 34 | virtual QList _disasm(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, qint32 nLimit, 35 | XBinary::PDSTRUCT *pPdStruct); 36 | 37 | private: 38 | csh m_handle; 39 | XBinary::DM m_disasmMode; 40 | XBinary::DMFAMILY m_disasmFamily; 41 | XBinary::SYNTAX m_syntax; 42 | }; 43 | 44 | #endif // CAPSTONE_BRIDGE_H 45 | -------------------------------------------------------------------------------- /Modules/xmacho_commands.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #ifndef XMACHO_COMMANDS_H 23 | #define XMACHO_COMMANDS_H 24 | 25 | #include "../xdisasmabstract.h" 26 | #include "xmach.h" 27 | 28 | class XMachO_Commands : public XDisasmAbstract { 29 | Q_OBJECT 30 | 31 | public: 32 | explicit XMachO_Commands(XBinary::DM disasmMode, QObject *pParent = nullptr); 33 | 34 | virtual QList _disasm(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, qint32 nLimit, 35 | XBinary::PDSTRUCT *pPdStruct); 36 | 37 | private: 38 | quint64 _handleULEB128(QList *pListResults, char *pData, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, const QString &sPrefix); 39 | QString _handleAnsiString(QList *pListResults, char *pData, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, 40 | const QString &sPrefix); 41 | 42 | private: 43 | XBinary::DM m_disasmMode; 44 | }; 45 | 46 | #endif // XMACHO_COMMANDS_H 47 | -------------------------------------------------------------------------------- /Modules/x7zip_properties.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #ifndef X7ZIP_PROPERTIES_H 23 | #define X7ZIP_PROPERTIES_H 24 | 25 | #include "../xdisasmabstract.h" 26 | #include "xsevenzip.h" 27 | 28 | class X7Zip_Properties : public XDisasmAbstract { 29 | Q_OBJECT 30 | public: 31 | explicit X7Zip_Properties(QObject *pParent = nullptr); 32 | 33 | virtual QList _disasm(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, qint32 nLimit, 34 | XBinary::PDSTRUCT *pPdStruct); 35 | 36 | private: 37 | void _addTagId(QList *pListResults, quint64 nValue, XSevenZip::EIdEnum id, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 38 | void _handleTag(QList *pListResults, char *pData, XSevenZip::EIdEnum id, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 39 | quint64 _handleNumber(QList *pListResults, char *pData, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 40 | quint8 _handleByte(QList *pListResults, char *pData, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 41 | quint32 _handleUINT32(QList *pListResults, char *pData, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 42 | QByteArray _handleArray(QList *pListResults, char *pData, qint32 nDataSize, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 43 | }; 44 | 45 | #endif // X7ZIP_PROPERTIES_H 46 | -------------------------------------------------------------------------------- /xdisasmcore.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #ifndef XDISASMCORE_H 23 | #define XDISASMCORE_H 24 | 25 | #include "xoptions.h" 26 | #include "xcapstone.h" 27 | #include "xdisasmabstract.h" 28 | #include "Modules/capstone_bridge.h" 29 | #include "Modules/x7zip_properties.h" 30 | #include "Modules/xmacho_commands.h" 31 | 32 | #ifdef QT_GUI_LIB 33 | #include 34 | #include 35 | #endif 36 | 37 | class XDisasmCore : public QObject { 38 | Q_OBJECT 39 | public: 40 | enum ST { 41 | ST_UNKNOWN = 0, 42 | ST_FULL, 43 | ST_MASK, 44 | ST_REL 45 | }; 46 | 47 | struct SIGNATURE_RECORD { 48 | XADDR nAddress; 49 | QString sOpcode; 50 | QByteArray baOpcode; 51 | qint32 nDispOffset; 52 | qint32 nDispSize; 53 | qint32 nImmOffset; 54 | qint32 nImmSize; 55 | bool bIsConst; 56 | }; 57 | 58 | enum OG { 59 | OG_UNKNOWN = 0, 60 | OG_ARROWS, 61 | OG_ARROWS_SELECTED, 62 | OG_REGS, 63 | OG_NUMBERS, 64 | OG_OPCODE, 65 | OG_REFS, 66 | OG_REGS_GENERAL, 67 | OG_REGS_STACK, 68 | OG_REGS_SEGMENT, 69 | OG_REGS_DEBUG, 70 | OG_REGS_IP, 71 | OG_REGS_FLAGS, 72 | OG_REGS_FPU, 73 | OG_REGS_XMM, 74 | OG_OPCODE_CALL, 75 | OG_OPCODE_RET, 76 | OG_OPCODE_PUSH, 77 | OG_OPCODE_POP, 78 | OG_OPCODE_NOP, 79 | OG_OPCODE_JMP, 80 | OG_OPCODE_CONDJMP, 81 | OG_OPCODE_INT3, 82 | OG_OPCODE_SYSCALL 83 | }; 84 | 85 | explicit XDisasmCore(QObject *pParent = nullptr); 86 | ~XDisasmCore(); 87 | 88 | void setMode(XBinary::DM disasmMode); 89 | void setSyntax(XBinary::SYNTAX syntax); 90 | void setOptions(XOptions *pOptions); 91 | 92 | XBinary::DMFAMILY getDisasmFamily(); 93 | XBinary::DM getDisasmMode(); 94 | 95 | XDisasmAbstract::DISASM_RESULT disAsm(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 96 | XDisasmAbstract::DISASM_RESULT disAsm(QIODevice *pDevice, qint64 nOffset, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 97 | 98 | QList disAsmList(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, 99 | qint32 nLimit = -1, XBinary::PDSTRUCT *pPdStruct = 0); 100 | 101 | XBinary::SYNTAX getSyntax(); 102 | 103 | QString getSignature(QIODevice *pDevice, XBinary::_MEMORY_MAP *pMemoryMap, XADDR nAddress, ST signatureType, qint32 nCount); 104 | QList getSignatureRecords(QIODevice *pDevice, XBinary::_MEMORY_MAP *pMemoryMap, qint64 nOffset, qint32 nCount, ST signatureType); 105 | static QString replaceWildChar(const QString &sString, qint32 nOffset, qint32 nSize, QChar cWild); // Move to XBinary 106 | 107 | QString getNumberString(qint64 nValue); 108 | 109 | XOptions::COLOR_RECORD getColorRecord(OG og); 110 | static QMap getColorRecordsMap(XOptions *pOptions, XBinary::DM disasmMode); 111 | static XOptions::COLOR_RECORD getColorRecord(XOptions *pOptions, XOptions::ID id); 112 | #ifdef QT_GUI_LIB 113 | void drawDisasmText(QPainter *pPainter, QRectF rectText, const XDisasmAbstract::DISASM_RESULT &disasmResult); 114 | void drawOperand(QPainter *pPainter, QRectF rectText, const QString &sOperand); 115 | void drawColorText(QPainter *pPainter, const QRectF &rect, const QString &sText, const XOptions::COLOR_RECORD &colorRecord); 116 | #endif 117 | XOptions::COLOR_RECORD getOpcodeColor(quint32 nOpcode); 118 | 119 | private: 120 | XOptions *m_pOptions; 121 | XBinary::DM m_disasmMode; 122 | XBinary::DMFAMILY m_disasmFamily; 123 | XBinary::SYNTAX m_syntax; 124 | qint32 m_nOpcodeSize; 125 | XDisasmAbstract *m_pDisasmAbstract; 126 | QMap m_mapColors; 127 | #ifdef QT_GUI_LIB 128 | QTextOption m_qTextOptions; 129 | #endif 130 | }; 131 | 132 | #endif // XDISASMCORE_H 133 | -------------------------------------------------------------------------------- /xdisasmabstract.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #ifndef XDISASMABSTRACT_H 23 | #define XDISASMABSTRACT_H 24 | 25 | #include "xbinary.h" 26 | #include "xcapstone.h" 27 | 28 | class XDisasmAbstract : public QObject { 29 | Q_OBJECT 30 | 31 | public: 32 | struct STATE { 33 | bool bIsStop; 34 | XADDR nAddress; 35 | qint32 nLimit; 36 | qint64 nMaxSize; 37 | qint32 nCurrentCount; 38 | qint64 nCurrentOffset; 39 | }; 40 | 41 | enum RELTYPE { 42 | RELTYPE_NONE = 0, 43 | RELTYPE_ALL, 44 | RELTYPE_JMP = 0x10, 45 | RELTYPE_JMP_UNCOND, 46 | RELTYPE_JMP_COND, 47 | RELTYPE_CALL = 0x20 48 | }; 49 | 50 | enum MEMTYPE { 51 | MEMTYPE_NONE = 0, 52 | MEMTYPE_READ, 53 | MEMTYPE_WRITE, 54 | MEMTYPE_ACCESS 55 | }; 56 | 57 | struct DISASM_RESULT { 58 | bool bIsValid; 59 | bool bMemError; 60 | XADDR nAddress; 61 | qint32 nSize; 62 | quint32 nOpcode; 63 | QString sMnemonic; 64 | QString sOperands; 65 | RELTYPE relType; 66 | XADDR nXrefToRelative; 67 | MEMTYPE memType; 68 | XADDR nXrefToMemory; 69 | qint32 nMemorySize; 70 | XADDR nNextAddress; 71 | bool bIsConst; // For signatures 72 | bool bIsRet; 73 | bool bIsCall; 74 | bool bIsJmp; 75 | bool bIsCondJmp; 76 | quint32 nDispOffset; 77 | quint32 nDispSize; 78 | quint32 nImmOffset; 79 | quint32 nImmSize; 80 | }; 81 | 82 | struct DISASM_OPTIONS { 83 | bool bIsUppercase; 84 | bool bNoStrings; 85 | }; 86 | 87 | enum REGS { 88 | REGS_UNKNOWN = 0, 89 | REGS_GENERAL, 90 | REGS_FPU, 91 | REGS_XMM, 92 | REGS_STACK, 93 | REGS_SEGMENT, 94 | REGS_FLAGS, 95 | REGS_DEBUG, 96 | REGS_IP 97 | }; 98 | 99 | explicit XDisasmAbstract(QObject *pParent = nullptr); 100 | virtual QList _disasm(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, qint32 nLimit, 101 | XBinary::PDSTRUCT *pPdStruct) = 0; 102 | 103 | static QString getNumberString(qint64 nValue, XBinary::DM disasmMode, XBinary::SYNTAX syntax); 104 | static QString getOpcodeFullString(const DISASM_RESULT &disasmResult); 105 | static bool isBranchOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); // mb TODO rename 106 | static bool isJumpOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 107 | static bool isRetOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 108 | static bool isPushOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 109 | static bool isPopOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 110 | static bool isCallOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 111 | static bool isCondJumpOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 112 | static bool isNopOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 113 | static bool isInt3Opcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 114 | static bool isSyscallOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID); 115 | static bool isGeneralRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 116 | static bool isStackRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 117 | static bool isSegmentRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 118 | static bool isDebugRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 119 | static bool isInstructionPointerRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 120 | static bool isFlagsRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 121 | static bool isFPURegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 122 | static bool isXMMRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 123 | static bool isRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 124 | static bool isRef(XBinary::DMFAMILY dmFamily, const QString &sOperand, XBinary::SYNTAX syntax); 125 | static bool isNumber(XBinary::DMFAMILY dmFamily, const QString &sNumber, XBinary::SYNTAX syntax); 126 | 127 | static QString removeRegPrefix(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax); 128 | 129 | void _addDisasmResult(QList *pListResults, DISASM_RESULT &disasmResult, STATE *pState, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 130 | void _addDisasmResult(QList *pListResults, XADDR nAddress, qint32 nSize, const QString &sMnemonic, const QString &sString, STATE *pState, 131 | const XDisasmAbstract::DISASM_OPTIONS &disasmOptions); 132 | }; 133 | 134 | #endif // XDISASMABSTRACT_H 135 | -------------------------------------------------------------------------------- /Modules/capstone_bridge.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #include "capstone_bridge.h" 23 | 24 | Capstone_Bridge::Capstone_Bridge(XBinary::DM disasmMode, XBinary::SYNTAX syntax, QObject *pParent) : XDisasmAbstract(pParent) 25 | { 26 | XCapstone::openHandle(disasmMode, &m_handle, true, syntax); 27 | 28 | m_disasmMode = disasmMode; 29 | m_disasmFamily = XBinary::getDisasmFamily(disasmMode); 30 | m_syntax = syntax; 31 | } 32 | 33 | Capstone_Bridge::~Capstone_Bridge() 34 | { 35 | if (m_handle) { 36 | XCapstone::closeHandle(&m_handle); 37 | } 38 | } 39 | 40 | QList Capstone_Bridge::_disasm(char *pData, qint32 nDataSize, XADDR nAddress, const DISASM_OPTIONS &disasmOptions, qint32 nLimit, 41 | XBinary::PDSTRUCT *pPdStruct) 42 | { 43 | QList listResult; 44 | 45 | STATE state = {}; 46 | state.nCurrentCount = 0; 47 | state.nCurrentOffset = 0; 48 | state.nLimit = nLimit; 49 | state.nMaxSize = nDataSize; 50 | state.nAddress = nAddress; 51 | 52 | while (XBinary::isPdStructNotCanceled(pPdStruct) && (!(state.bIsStop))) { 53 | XDisasmAbstract::DISASM_RESULT result = {}; 54 | result.nAddress = nAddress; 55 | 56 | cs_insn *pInsn = nullptr; 57 | 58 | // cs_reg_name 59 | 60 | quint64 nNumberOfOpcodes = cs_disasm(m_handle, (uint8_t *)pData, nDataSize, nAddress, 1, &pInsn); 61 | 62 | if (nNumberOfOpcodes > 0) { 63 | result.bIsValid = true; 64 | result.bIsRet = isRetOpcode(m_disasmFamily, pInsn->id); 65 | result.bIsCall = isCallOpcode(m_disasmFamily, pInsn->id); 66 | result.bIsJmp = isJumpOpcode(m_disasmFamily, pInsn->id); 67 | result.bIsCondJmp = isCondJumpOpcode(m_disasmFamily, pInsn->id); 68 | result.nOpcode = pInsn->id; 69 | result.sMnemonic = pInsn->mnemonic; 70 | result.sOperands = pInsn->op_str; 71 | result.nSize = pInsn->size; 72 | result.nNextAddress = nAddress + result.nSize; 73 | 74 | if (m_disasmFamily == XBinary::DMFAMILY_X86) { 75 | result.nDispOffset = pInsn->detail->x86.encoding.disp_offset; 76 | result.nDispSize = pInsn->detail->x86.encoding.disp_size; 77 | result.nImmOffset = pInsn->detail->x86.encoding.imm_offset; 78 | result.nImmSize = pInsn->detail->x86.encoding.imm_size; 79 | } 80 | 81 | // Relatives 82 | for (qint32 i = 0; i < pInsn->detail->groups_count; i++) { 83 | if (pInsn->detail->groups[i] == CS_GRP_BRANCH_RELATIVE) { 84 | if (m_disasmFamily == XBinary::DMFAMILY_X86) { 85 | for (qint32 j = 0; j < pInsn->detail->x86.op_count; j++) { 86 | // TODO mb use groups 87 | if (pInsn->detail->x86.operands[j].type == X86_OP_IMM) { 88 | if (result.bIsCall) { 89 | result.relType = XDisasmAbstract::RELTYPE_CALL; 90 | } else if (result.bIsJmp) { 91 | result.relType = XDisasmAbstract::RELTYPE_JMP_UNCOND; 92 | } else if (result.bIsCondJmp) { 93 | result.relType = XDisasmAbstract::RELTYPE_JMP_COND; 94 | } else { 95 | result.relType = XDisasmAbstract::RELTYPE_JMP; 96 | } 97 | 98 | result.nXrefToRelative = pInsn->detail->x86.operands[j].imm; 99 | result.nNextAddress = result.nXrefToRelative; 100 | result.bIsConst = true; 101 | 102 | break; 103 | } 104 | } 105 | } else if (m_disasmFamily == XBinary::DMFAMILY_ARM) { 106 | for (qint32 j = 0; j < pInsn->detail->arm.op_count; j++) { 107 | if (pInsn->detail->arm.operands[j].type == ARM_OP_IMM) { 108 | result.relType = XDisasmAbstract::RELTYPE_JMP; // TODO 109 | result.nXrefToRelative = pInsn->detail->arm.operands[j].imm; 110 | result.nNextAddress = result.nXrefToRelative; 111 | result.bIsConst = true; 112 | 113 | break; 114 | } 115 | } 116 | } else if (m_disasmFamily == XBinary::DMFAMILY_ARM64) { 117 | for (qint32 j = 0; j < pInsn->detail->arm64.op_count; j++) { 118 | if (pInsn->detail->arm64.operands[j].type == ARM64_OP_IMM) { 119 | result.relType = XDisasmAbstract::RELTYPE_JMP; // TODO 120 | result.nXrefToRelative = pInsn->detail->arm64.operands[j].imm; 121 | result.nNextAddress = result.nXrefToRelative; 122 | result.bIsConst = true; 123 | 124 | break; 125 | } 126 | } 127 | } 128 | 129 | break; 130 | } 131 | } 132 | 133 | // Memory 134 | if (m_disasmFamily == XBinary::DMFAMILY_X86) { 135 | for (qint32 i = 0; i < pInsn->detail->x86.op_count; i++) { 136 | if (pInsn->detail->x86.operands[i].type == X86_OP_MEM) { 137 | bool bLEA = (pInsn->id == X86_INS_LEA); 138 | 139 | // mb TODO flag 140 | if ((pInsn->detail->x86.operands[i].mem.base == X86_REG_INVALID) && (pInsn->detail->x86.operands[i].mem.index == X86_REG_INVALID)) { 141 | result.memType = XDisasmAbstract::MEMTYPE_READ; // TODO 142 | result.nXrefToMemory = pInsn->detail->x86.operands[i].mem.disp; 143 | result.nMemorySize = pInsn->detail->x86.operands[i].size; 144 | 145 | if (bLEA) { 146 | result.nMemorySize = 0; 147 | } 148 | 149 | break; 150 | } else if ((pInsn->detail->x86.operands[i].mem.base == X86_REG_RIP) && (pInsn->detail->x86.operands[i].mem.index == X86_REG_INVALID)) { 151 | result.memType = XDisasmAbstract::MEMTYPE_READ; // TODO 152 | result.nXrefToMemory = nAddress + pInsn->size + pInsn->detail->x86.operands[i].mem.disp; 153 | result.nMemorySize = pInsn->detail->x86.operands[i].size; 154 | 155 | if (bLEA) { 156 | result.nMemorySize = 0; 157 | } 158 | 159 | QString sOldString; 160 | QString sNewString; 161 | 162 | // TODO Check 163 | if ((m_syntax == XBinary::SYNTAX_DEFAULT) || (m_syntax == XBinary::SYNTAX_INTEL) || (m_syntax == XBinary::SYNTAX_MASM)) { 164 | if (pInsn->detail->x86.operands[i].mem.disp >= 0) { 165 | if (result.sOperands.contains("rip + ")) { 166 | sOldString = QString("rip + %1").arg(getNumberString(pInsn->detail->x86.operands[i].mem.disp, m_disasmMode, m_syntax)); 167 | } 168 | } else { 169 | if (result.sOperands.contains("rip - ")) { 170 | sOldString = QString("rip - %1").arg(getNumberString(0 - pInsn->detail->x86.operands[i].mem.disp, m_disasmMode, m_syntax)); 171 | } 172 | } 173 | } else if (m_syntax == XBinary::SYNTAX_ATT) { 174 | if (result.sOperands.contains("(%rip)")) { 175 | sOldString = QString("%1(%rip)").arg(getNumberString(pInsn->detail->x86.operands[i].mem.disp, m_disasmMode, m_syntax)); 176 | } 177 | } 178 | 179 | if (sOldString != "") { 180 | sNewString = getNumberString(result.nXrefToMemory, m_disasmMode, m_syntax); 181 | result.sOperands = result.sOperands.replace(sOldString, sNewString); 182 | } 183 | 184 | break; 185 | } 186 | } 187 | } 188 | } 189 | 190 | // if (disasmMode == XBinary::DM_X86_64) { 191 | // if (result.sString.contains("[rip + 0x")) { 192 | // // TODO 193 | // qint32 nNumberOfOpcodes = pInsn->detail->x86.op_count; 194 | 195 | // for (qint32 i = 0; i < nNumberOfOpcodes; i++) { 196 | 197 | // } 198 | // } 199 | // } 200 | 201 | cs_free(pInsn, nNumberOfOpcodes); 202 | } else { 203 | if (cs_errno(m_handle) == CS_ERR_MEM) { 204 | state.bIsStop = true; 205 | result.bMemError = true; 206 | } 207 | 208 | if (m_disasmFamily == XBinary::DMFAMILY_ARM) { 209 | result.sMnemonic = tr("Invalid opcode"); 210 | result.nSize = 2; 211 | } else if (m_disasmFamily == XBinary::DMFAMILY_ARM64) { 212 | result.sMnemonic = tr("Invalid opcode"); 213 | result.nSize = 4; 214 | } else if (m_disasmFamily == XBinary::DMFAMILY_M68K) { 215 | result.sMnemonic = tr("Invalid opcode"); 216 | result.nSize = 2; 217 | } else { 218 | result.sMnemonic = "db"; 219 | result.sOperands = getNumberString(*((uint8_t *)pData), m_disasmMode, m_syntax); 220 | result.nSize = 1; 221 | } 222 | } 223 | 224 | _addDisasmResult(&listResult, result, &state, disasmOptions); 225 | 226 | pData += result.nSize; 227 | nAddress += result.nSize; 228 | } 229 | 230 | return listResult; 231 | } 232 | -------------------------------------------------------------------------------- /Modules/x7zip_properties.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #include "x7zip_properties.h" 23 | 24 | X7Zip_Properties::X7Zip_Properties(QObject *pParent) : XDisasmAbstract(pParent) 25 | { 26 | } 27 | 28 | void X7Zip_Properties::_addTagId(QList *pListResults, quint64 nValue, XSevenZip::EIdEnum id, STATE *pState, const DISASM_OPTIONS &disasmOptions) 29 | { 30 | if (pState->bIsStop) { 31 | return; 32 | } 33 | 34 | if (nValue == id) { 35 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, 1, XSevenZip::idToSring(id), "", pState, disasmOptions); 36 | } else { 37 | pState->bIsStop = true; 38 | } 39 | } 40 | 41 | void X7Zip_Properties::_handleTag(QList *pListResults, char *pData, XSevenZip::EIdEnum id, STATE *pState, const DISASM_OPTIONS &disasmOptions) 42 | { 43 | if (pState->bIsStop) { 44 | return; 45 | } 46 | 47 | XBinary::PACKED_UINT puTag = XBinary::_read_packedNumber(pData + pState->nCurrentOffset, pState->nMaxSize - pState->nCurrentOffset); 48 | 49 | if (puTag.bIsValid) { 50 | if (id == puTag.nValue) { 51 | _addTagId(pListResults, puTag.nValue, id, pState, disasmOptions); 52 | if (puTag.nValue == XSevenZip::k7zIdHeader) { 53 | _handleTag(pListResults, pData, XSevenZip::k7zIdMainStreamsInfo, pState, disasmOptions); 54 | _handleTag(pListResults, pData, XSevenZip::k7zIdFilesInfo, pState, disasmOptions); 55 | } else if (puTag.nValue == XSevenZip::k7zIdMainStreamsInfo) { 56 | _handleTag(pListResults, pData, XSevenZip::k7zIdPackInfo, pState, disasmOptions); 57 | _handleTag(pListResults, pData, XSevenZip::k7zIdUnpackInfo, pState, disasmOptions); 58 | XBinary::PACKED_UINT puExtra = XBinary::_read_packedNumber(pData + pState->nCurrentOffset, pState->nMaxSize - pState->nCurrentOffset); 59 | if (puExtra.bIsValid) { 60 | if (puExtra.nValue == XSevenZip::k7zIdSubStreamsInfo) { 61 | _handleTag(pListResults, pData, XSevenZip::k7zIdSubStreamsInfo, pState, disasmOptions); 62 | } 63 | } 64 | _handleTag(pListResults, pData, XSevenZip::k7zIdEnd, pState, disasmOptions); 65 | } else if (puTag.nValue == XSevenZip::k7zIdEncodedHeader) { 66 | _handleTag(pListResults, pData, XSevenZip::k7zIdPackInfo, pState, disasmOptions); 67 | _handleTag(pListResults, pData, XSevenZip::k7zIdUnpackInfo, pState, disasmOptions); 68 | _handleTag(pListResults, pData, XSevenZip::k7zIdEnd, pState, disasmOptions); 69 | } else if (puTag.nValue == XSevenZip::k7zIdPackInfo) { 70 | _handleNumber(pListResults, pData, pState, disasmOptions); // Pack Position 71 | quint64 nCount = _handleNumber(pListResults, pData, pState, disasmOptions); // Count of Pack Streams, NUMBER 72 | for (quint64 i = 0; (i < nCount) && (!(pState->bIsStop)); i++) { 73 | _handleNumber(pListResults, pData, pState, disasmOptions); // Size 74 | } 75 | for (quint64 i = 0; (i < nCount) && (!(pState->bIsStop)); i++) { 76 | _handleNumber(pListResults, pData, pState, disasmOptions); // CRC // Check UINT32 77 | } 78 | _handleTag(pListResults, pData, XSevenZip::k7zIdEnd, pState, disasmOptions); 79 | } else if (puTag.nValue == XSevenZip::k7zIdUnpackInfo) { 80 | _handleTag(pListResults, pData, XSevenZip::k7zIdFolder, pState, disasmOptions); 81 | _handleTag(pListResults, pData, XSevenZip::k7zIdEnd, pState, disasmOptions); 82 | } else if (puTag.nValue == XSevenZip::k7zIdSubStreamsInfo) { 83 | while (!(pState->bIsStop)) { 84 | XBinary::PACKED_UINT puExtra = XBinary::_read_packedNumber(pData + pState->nCurrentOffset, pState->nMaxSize - pState->nCurrentOffset); 85 | if (puExtra.bIsValid) { 86 | if (puExtra.nValue == XSevenZip::k7zIdCRC) { 87 | // TODO mb create a new if 88 | _addTagId(pListResults, puExtra.nValue, XSevenZip::k7zIdCRC, pState, disasmOptions); 89 | quint64 nCRCCount = _handleNumber(pListResults, pData, pState, disasmOptions); // Count of CRC 90 | for (quint64 i = 0; (i < nCRCCount) && (!(pState->bIsStop)); i++) { 91 | _handleUINT32(pListResults, pData, pState, disasmOptions); // UnpackDigest, UINT32 92 | } 93 | } else { 94 | break; 95 | } 96 | } else { 97 | pState->bIsStop = true; 98 | } 99 | } 100 | _handleTag(pListResults, pData, XSevenZip::k7zIdEnd, pState, disasmOptions); 101 | } else if (puTag.nValue == XSevenZip::k7zIdFilesInfo) { 102 | quint64 nNumberOfFiles = _handleNumber(pListResults, pData, pState, disasmOptions); // Number of Files 103 | for (quint64 i = 0; (i < nNumberOfFiles) && (!(pState->bIsStop)); i++) { 104 | _handleNumber(pListResults, pData, pState, disasmOptions); // File ID, NUMBER 105 | } 106 | } else if (puTag.nValue == XSevenZip::k7zIdFolder) { 107 | quint64 nNumberOfFolders = _handleNumber(pListResults, pData, pState, disasmOptions); // Number of Folders 108 | quint8 nExt = _handleByte(pListResults, pData, pState, disasmOptions); // External 109 | if (nExt == 0) { 110 | _handleNumber(pListResults, pData, pState, disasmOptions); // Number of Coders, NUMBER 111 | quint8 nFlag = _handleByte(pListResults, pData, pState, disasmOptions); // Flag 112 | qint32 nCodecSize = nFlag & 0x0F; 113 | bool bIsComplex = (nFlag & 0x10) != 0; 114 | bool bHasAttr = (nFlag & 0x20) != 0; 115 | _handleArray(pListResults, pData, nCodecSize, pState, disasmOptions); 116 | if (bIsComplex) { 117 | // TODO 118 | } 119 | if (bHasAttr) { 120 | quint64 nPropertySize = _handleNumber(pListResults, pData, pState, disasmOptions); // PropertiesSize 121 | _handleArray(pListResults, pData, nPropertySize, pState, disasmOptions); 122 | } 123 | } else if (nExt == 1) { 124 | _handleNumber(pListResults, pData, pState, disasmOptions); // Data Stream Index, NUMBER 125 | } 126 | 127 | while (!(pState->bIsStop)) { 128 | XBinary::PACKED_UINT puExtra = XBinary::_read_packedNumber(pData + pState->nCurrentOffset, pState->nMaxSize - pState->nCurrentOffset); 129 | if (puExtra.bIsValid) { 130 | if (puExtra.nValue == XSevenZip::k7zIdCodersUnpackSize) { 131 | _addTagId(pListResults, puExtra.nValue, XSevenZip::k7zIdCodersUnpackSize, pState, disasmOptions); 132 | for (quint64 i = 0; (i < nNumberOfFolders) && (!(pState->bIsStop)); i++) { 133 | _handleNumber(pListResults, pData, pState, disasmOptions); // Unpacksize, NUMBER 134 | } 135 | } else if (puExtra.nValue == XSevenZip::k7zIdCRC) { 136 | _addTagId(pListResults, puExtra.nValue, XSevenZip::k7zIdCRC, pState, disasmOptions); 137 | quint64 nCRCCount = _handleNumber(pListResults, pData, pState, disasmOptions); // Count of CRC 138 | for (quint64 i = 0; (i < nCRCCount) && (!(pState->bIsStop)); i++) { 139 | _handleUINT32(pListResults, pData, pState, disasmOptions); // UnpackDigest, UINT32 140 | } 141 | } else { 142 | break; 143 | } 144 | } else { 145 | pState->bIsStop = true; 146 | } 147 | } 148 | } 149 | } else { 150 | pState->bIsStop = true; 151 | } 152 | } else { 153 | pState->bIsStop = true; 154 | } 155 | } 156 | 157 | quint64 X7Zip_Properties::_handleNumber(QList *pListResults, char *pData, STATE *pState, const DISASM_OPTIONS &disasmOptions) 158 | { 159 | if (pState->bIsStop) { 160 | return 0; 161 | } 162 | 163 | quint64 nResult = 0; 164 | 165 | XBinary::PACKED_UINT puTag = XBinary::_read_packedNumber(pData + pState->nCurrentOffset, pState->nMaxSize - pState->nCurrentOffset); 166 | 167 | if (puTag.bIsValid) { 168 | nResult = puTag.nValue; 169 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, puTag.nByteSize, "NUMBER", QString("0x%1").arg(QString::number(puTag.nValue, 16)), 170 | pState, disasmOptions); 171 | } else { 172 | pState->bIsStop = true; 173 | } 174 | 175 | return nResult; 176 | } 177 | 178 | quint8 X7Zip_Properties::_handleByte(QList *pListResults, char *pData, STATE *pState, const DISASM_OPTIONS &disasmOptions) 179 | { 180 | if (pState->bIsStop) { 181 | return 0; 182 | } 183 | 184 | quint8 nResult = 0; 185 | 186 | if (pState->nCurrentOffset + 1 <= pState->nMaxSize) { 187 | nResult = XBinary::_read_uint8(pData + pState->nCurrentOffset); 188 | 189 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, 1, "BYTE", QString("0x%1").arg(QString::number(nResult, 16)), pState, disasmOptions); 190 | } else { 191 | pState->bIsStop = true; 192 | } 193 | 194 | return nResult; 195 | } 196 | 197 | quint32 X7Zip_Properties::_handleUINT32(QList *pListResults, char *pData, STATE *pState, const DISASM_OPTIONS &disasmOptions) 198 | { 199 | if (pState->bIsStop) { 200 | return 0; 201 | } 202 | 203 | quint32 nResult = 0; 204 | 205 | if (pState->nCurrentOffset + 4 <= pState->nMaxSize) { 206 | nResult = XBinary::_read_uint32(pData + pState->nCurrentOffset); 207 | 208 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, 4, "UINT32", QString("0x%1").arg(QString::number(nResult, 16)), pState, disasmOptions); 209 | } else { 210 | pState->bIsStop = true; 211 | } 212 | 213 | return nResult; 214 | } 215 | 216 | QByteArray X7Zip_Properties::_handleArray(QList *pListResults, char *pData, qint32 nDataSize, STATE *pState, const DISASM_OPTIONS &disasmOptions) 217 | { 218 | if (pState->bIsStop) { 219 | return 0; 220 | } 221 | 222 | QByteArray baResult; 223 | 224 | if (pState->nCurrentOffset + nDataSize <= pState->nMaxSize) { 225 | baResult = XBinary::_read_byteArray(pData + pState->nCurrentOffset, nDataSize); 226 | 227 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, nDataSize, "ARRAY", baResult.toHex(), pState, disasmOptions); 228 | } else { 229 | pState->bIsStop = true; 230 | } 231 | 232 | return baResult; 233 | } 234 | 235 | QList X7Zip_Properties::_disasm(char *pData, qint32 nDataSize, XADDR nAddress, const DISASM_OPTIONS &disasmOptions, qint32 nLimit, 236 | XBinary::PDSTRUCT *pPdStruct) 237 | { 238 | Q_UNUSED(pPdStruct) 239 | 240 | QList listResult; 241 | 242 | STATE state = {}; 243 | state.nCurrentCount = 0; 244 | state.nCurrentOffset = 0; 245 | state.nLimit = nLimit; 246 | state.nMaxSize = nDataSize; 247 | state.nAddress = nAddress; 248 | 249 | XBinary::PACKED_UINT puTag = XBinary::_read_packedNumber(pData, state.nMaxSize - state.nCurrentOffset); 250 | 251 | if (puTag.bIsValid) { 252 | if (puTag.nValue == XSevenZip::k7zIdHeader) { 253 | _handleTag(&listResult, pData, XSevenZip::k7zIdHeader, &state, disasmOptions); 254 | } else if (puTag.nValue == XSevenZip::k7zIdEncodedHeader) { 255 | _handleTag(&listResult, pData, XSevenZip::k7zIdEncodedHeader, &state, disasmOptions); 256 | } 257 | } 258 | 259 | return listResult; 260 | } 261 | -------------------------------------------------------------------------------- /Modules/xmacho_commands.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #include "xmacho_commands.h" 23 | 24 | XMachO_Commands::XMachO_Commands(XBinary::DM disasmMode, QObject *pParent) : XDisasmAbstract(pParent) 25 | { 26 | m_disasmMode = disasmMode; 27 | } 28 | 29 | quint64 XMachO_Commands::_handleULEB128(QList *pListResults, char *pData, STATE *pState, const DISASM_OPTIONS &disasmOptions, const QString &sPrefix) 30 | { 31 | if (pState->bIsStop) { 32 | return 0; 33 | } 34 | 35 | quint64 nResult = 0; 36 | 37 | XBinary::PACKED_UINT puTag = XBinary::_read_uleb128(pData + pState->nCurrentOffset, pState->nMaxSize - pState->nCurrentOffset); 38 | 39 | if (puTag.bIsValid) { 40 | nResult = puTag.nValue; 41 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, puTag.nByteSize, sPrefix, QString("0x%1").arg(QString::number(puTag.nValue, 16)), 42 | pState, disasmOptions); 43 | } else { 44 | pState->bIsStop = true; 45 | } 46 | 47 | return nResult; 48 | } 49 | 50 | QString XMachO_Commands::_handleAnsiString(QList *pListResults, char *pData, STATE *pState, const DISASM_OPTIONS &disasmOptions, const QString &sPrefix) 51 | { 52 | if (pState->bIsStop) { 53 | return 0; 54 | } 55 | 56 | qint64 nMaxSize = qMin(pState->nMaxSize - pState->nCurrentOffset, (qint64)256); 57 | QString sResult = XBinary::_read_ansiString(pData + pState->nCurrentOffset, nMaxSize); 58 | 59 | if (sResult != "") { 60 | _addDisasmResult(pListResults, pState->nAddress + pState->nCurrentOffset, sResult.size() + 1, sPrefix, sResult, pState, disasmOptions); 61 | } else { 62 | pState->bIsStop = true; 63 | } 64 | 65 | return sResult; 66 | } 67 | 68 | QList XMachO_Commands::_disasm(char *pData, qint32 nDataSize, XADDR nAddress, const DISASM_OPTIONS &disasmOptions, qint32 nLimit, 69 | XBinary::PDSTRUCT *pPdStruct) 70 | { 71 | QList listResult; 72 | 73 | STATE state = {}; 74 | state.nCurrentCount = 0; 75 | state.nCurrentOffset = 0; 76 | state.nLimit = nLimit; 77 | state.nMaxSize = nDataSize; 78 | state.nAddress = nAddress; 79 | 80 | if (m_disasmMode == XBinary::DM_CUSTOM_MACH_EXPORT) { 81 | while (!(state.bIsStop) && XBinary::isPdStructNotCanceled(pPdStruct)) { 82 | quint64 nTerminalSize = _handleULEB128(&listResult, pData, &state, disasmOptions, "TERMINAL_SIZE"); 83 | 84 | if (nTerminalSize > 0) { 85 | _handleULEB128(&listResult, pData, &state, disasmOptions, "FLAGS"); 86 | _handleULEB128(&listResult, pData, &state, disasmOptions, "SYMBOL_OFFSET"); 87 | } 88 | 89 | quint64 nChildCount = _handleULEB128(&listResult, pData, &state, disasmOptions, "CHILD_COUNT"); 90 | 91 | for (quint64 i = 0; i < nChildCount; i++) { 92 | _handleAnsiString(&listResult, pData, &state, disasmOptions, "NODE_LABEL"); 93 | _handleULEB128(&listResult, pData, &state, disasmOptions, "NODE_OFFSET"); 94 | } 95 | 96 | if ((nTerminalSize == 0) && (nChildCount == 0)) { 97 | state.bIsStop = true; 98 | } 99 | } 100 | } else if ((m_disasmMode == XBinary::DM_CUSTOM_MACH_REBASE) || (m_disasmMode == XBinary::DM_CUSTOM_MACH_BIND) || (m_disasmMode == XBinary::DM_CUSTOM_MACH_WEAK)) { 101 | while (!(state.bIsStop)) { 102 | quint8 nOpcode = XBinary::_read_uint8(pData + state.nCurrentOffset); 103 | 104 | bool bString = false; 105 | bool bUleb1 = false; 106 | bool bUleb2 = false; 107 | bool bImm = false; 108 | 109 | QString sMnemonic; 110 | 111 | if (m_disasmMode == XBinary::DM_CUSTOM_MACH_REBASE) { 112 | switch (nOpcode & XMACH_DEF::S_REBASE_OPCODE_MASK) { 113 | case XMACH_DEF::S_REBASE_OPCODE_SET_TYPE_IMM: 114 | sMnemonic = QString("SET_TYPE_IMM"); 115 | bImm = true; 116 | break; 117 | case XMACH_DEF::S_REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 118 | sMnemonic = QString("SET_SEGMENT_AND_OFFSET_ULEB"); 119 | bImm = true; 120 | bUleb1 = true; 121 | break; 122 | case XMACH_DEF::S_REBASE_OPCODE_ADD_ADDR_ULEB: 123 | sMnemonic = QString("ADD_ADDR_ULEB"); 124 | bUleb1 = true; 125 | break; 126 | case XMACH_DEF::S_REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 127 | sMnemonic = QString("ADD_ADDR_IMM_SCALED"); 128 | bImm = true; 129 | break; 130 | case XMACH_DEF::S_REBASE_OPCODE_DO_REBASE_IMM_TIMES: 131 | sMnemonic = QString("DO_REBASE_IMM_TIMES"); 132 | bImm = true; 133 | break; 134 | case XMACH_DEF::S_REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 135 | sMnemonic = QString("DO_REBASE_ULEB_TIMES"); 136 | bUleb1 = true; 137 | break; 138 | case XMACH_DEF::S_REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 139 | sMnemonic = QString("DO_REBASE_ADD_ADDR_ULEB"); 140 | bUleb1 = true; 141 | break; 142 | case XMACH_DEF::S_REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 143 | sMnemonic = QString("DO_REBASE_ULEB_TIMES_SKIPPING_ULEB"); 144 | bUleb1 = true; 145 | bUleb2 = true; 146 | break; 147 | default: 148 | if (nOpcode == 0) { 149 | sMnemonic = QString("DONE"); 150 | } else { 151 | state.bIsStop = true; 152 | } 153 | } 154 | } else if ((m_disasmMode == XBinary::DM_CUSTOM_MACH_BIND) || (m_disasmMode == XBinary::DM_CUSTOM_MACH_WEAK)) { 155 | switch (nOpcode & XMACH_DEF::S_BIND_OPCODE_MASK) { 156 | case XMACH_DEF::S_BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 157 | sMnemonic = QString("SET_DYLIB_ORDINAL_IMM"); 158 | bImm = true; 159 | break; 160 | case XMACH_DEF::S_BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 161 | sMnemonic = QString("SET_DYLIB_ORDINAL_ULEB"); 162 | bUleb1 = true; 163 | break; 164 | case XMACH_DEF::S_BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 165 | sMnemonic = QString("SET_DYLIB_SPECIAL_IMM"); 166 | bImm = true; 167 | break; 168 | case XMACH_DEF::S_BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 169 | sMnemonic = QString("SET_SYMBOL_TRAILING_FLAGS_IMM"); 170 | bImm = true; 171 | bString = true; 172 | break; 173 | case XMACH_DEF::S_BIND_OPCODE_SET_TYPE_IMM: 174 | sMnemonic = QString("SET_TYPE_IMM"); 175 | bImm = true; 176 | break; 177 | case XMACH_DEF::S_BIND_OPCODE_SET_ADDEND_SLEB: 178 | sMnemonic = QString("SET_ADDEND_SLEB"); 179 | bUleb1 = true; 180 | break; 181 | case XMACH_DEF::S_BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 182 | sMnemonic = QString("SET_SEGMENT_AND_OFFSET_ULEB"); 183 | bImm = true; 184 | bUleb1 = true; 185 | break; 186 | case XMACH_DEF::S_BIND_OPCODE_ADD_ADDR_ULEB: 187 | sMnemonic = QString("ADD_ADDR_ULEB"); 188 | bUleb1 = true; 189 | break; 190 | case XMACH_DEF::S_BIND_OPCODE_DO_BIND: sMnemonic = QString("DO_BIND"); break; 191 | case XMACH_DEF::S_BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 192 | sMnemonic = QString("DO_BIND_ADD_ADDR_ULEB"); 193 | bUleb1 = true; 194 | break; 195 | case XMACH_DEF::S_BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 196 | sMnemonic = QString("DO_BIND_ADD_ADDR_IMM_SCALED"); 197 | bImm = true; 198 | break; 199 | case XMACH_DEF::S_BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 200 | sMnemonic = QString("DO_BIND_ULEB_TIMES_SKIPPING_ULEB"); 201 | bUleb1 = true; 202 | bUleb2 = true; 203 | break; 204 | case XMACH_DEF::S_BIND_OPCODE_THREADED: 205 | sMnemonic = QString("THREADED"); 206 | bImm = true; 207 | break; 208 | default: 209 | if (nOpcode == 0) { 210 | sMnemonic = QString("DONE"); 211 | } else { 212 | state.bIsStop = true; 213 | } 214 | } 215 | } 216 | 217 | QString sString; 218 | XBinary::PACKED_UINT puTag1 = {}; 219 | XBinary::PACKED_UINT puTag2 = {}; 220 | 221 | if (!state.bIsStop) { 222 | if (bImm) { 223 | if (m_disasmMode == XBinary::DM_CUSTOM_MACH_REBASE) { 224 | sString = XBinary::appendText(sString, QString::number(nOpcode & XMACH_DEF::S_REBASE_IMMEDIATE_MASK, 16), ", "); 225 | } else if ((m_disasmMode == XBinary::DM_CUSTOM_MACH_BIND) || (m_disasmMode == XBinary::DM_CUSTOM_MACH_WEAK)) { 226 | sString = XBinary::appendText(sString, QString::number(nOpcode & XMACH_DEF::S_BIND_IMMEDIATE_MASK, 16), ", "); 227 | } 228 | } 229 | } 230 | 231 | qint32 nOpcodeSize = 1; 232 | 233 | if (!state.bIsStop) { 234 | if (bString) { 235 | qint64 nMaxSize = qMin(state.nMaxSize - state.nCurrentOffset + nOpcodeSize, (qint64)256); 236 | QString _sString = XBinary::_read_ansiString(pData + state.nCurrentOffset + nOpcodeSize, nMaxSize - nOpcodeSize); 237 | nOpcodeSize += _sString.size() + 1; 238 | 239 | sString = XBinary::appendText(sString, _sString, ", "); 240 | } 241 | } 242 | 243 | if (!state.bIsStop) { 244 | if (bUleb1) { 245 | puTag1 = XBinary::_read_uleb128(pData + state.nCurrentOffset + nOpcodeSize, state.nMaxSize - state.nCurrentOffset - nOpcodeSize); 246 | 247 | if (puTag1.bIsValid) { 248 | sString = XBinary::appendText(sString, QString::number(puTag1.nValue, 16), ", "); 249 | nOpcodeSize += puTag1.nByteSize; 250 | } else { 251 | state.bIsStop = true; 252 | } 253 | } 254 | } 255 | 256 | if (!state.bIsStop) { 257 | if (bUleb2) { 258 | puTag2 = XBinary::_read_uleb128(pData + state.nCurrentOffset + nOpcodeSize, state.nMaxSize - state.nCurrentOffset - nOpcodeSize); 259 | 260 | if (puTag2.bIsValid) { 261 | sString = XBinary::appendText(sString, QString::number(puTag2.nValue, 16), ", "); 262 | nOpcodeSize += puTag2.nByteSize; 263 | } else { 264 | state.bIsStop = true; 265 | } 266 | } 267 | } 268 | 269 | if (!state.bIsStop) { 270 | _addDisasmResult(&listResult, state.nAddress + state.nCurrentOffset, nOpcodeSize, sMnemonic, sString, &state, disasmOptions); 271 | } 272 | 273 | // if (nOpcode == 0) { 274 | // state.bIsStop = true; 275 | // } 276 | } 277 | } else { 278 | _addDisasmResult(&listResult, nAddress, nDataSize, "ARRAY", "TST", &state, disasmOptions); 279 | } 280 | 281 | return listResult; 282 | } 283 | -------------------------------------------------------------------------------- /xdisasmabstract.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #include "xdisasmabstract.h" 23 | 24 | XDisasmAbstract::XDisasmAbstract(QObject *pParent) : QObject(pParent) 25 | { 26 | } 27 | 28 | QString XDisasmAbstract::getNumberString(qint64 nValue, XBinary::DM disasmMode, XBinary::SYNTAX syntax) 29 | { 30 | QString sResult; 31 | 32 | if ((disasmMode == XBinary::DM_X86_16) || (disasmMode == XBinary::DM_X86_32) || (disasmMode == XBinary::DM_X86_64)) { 33 | if (nValue < 0) { 34 | sResult += "- "; 35 | } 36 | nValue = qAbs(nValue); 37 | 38 | if (nValue < 10) { 39 | sResult += QString::number(nValue); 40 | } else { 41 | if ((syntax == XBinary::SYNTAX_DEFAULT) || (syntax == XBinary::SYNTAX_INTEL) || (syntax == XBinary::SYNTAX_ATT)) { 42 | sResult += QString("0x%1").arg(QString::number(nValue, 16)); 43 | } else if (syntax == XBinary::SYNTAX_MASM) { 44 | sResult += QString("%1h").arg(QString::number(nValue, 16)); 45 | } 46 | } 47 | } else { 48 | sResult += QString("0x%1").arg(QString::number(nValue, 16)); 49 | } 50 | 51 | return sResult; 52 | } 53 | 54 | QString XDisasmAbstract::getOpcodeFullString(const DISASM_RESULT &disasmResult) 55 | { 56 | QString sResult = disasmResult.sMnemonic; 57 | 58 | if (disasmResult.sOperands != "") { 59 | sResult += " " + disasmResult.sOperands; 60 | } 61 | 62 | return sResult; 63 | } 64 | 65 | void XDisasmAbstract::_addDisasmResult(QList *pListResults, DISASM_RESULT &disasmResult, STATE *pState, 66 | const XDisasmAbstract::DISASM_OPTIONS &disasmOptions) 67 | { 68 | if (pState->nLimit == 0) { 69 | if (!disasmResult.bIsValid) { 70 | pState->bIsStop = true; 71 | } 72 | } 73 | 74 | if (!(pState->bIsStop)) { 75 | if (disasmOptions.bIsUppercase) { 76 | disasmResult.sMnemonic = disasmResult.sMnemonic.toUpper(); 77 | disasmResult.sOperands = disasmResult.sOperands.toUpper(); 78 | } 79 | 80 | pListResults->append(disasmResult); 81 | pState->nCurrentCount++; 82 | pState->nCurrentOffset += disasmResult.nSize; 83 | } 84 | 85 | if ((pState->nLimit > 0) && (pState->nCurrentCount > pState->nLimit)) { 86 | pState->bIsStop = true; 87 | } else if (pState->nCurrentOffset >= pState->nMaxSize) { 88 | pState->bIsStop = true; 89 | } 90 | } 91 | 92 | void XDisasmAbstract::_addDisasmResult(QList *pListResults, XADDR nAddress, qint32 nSize, const QString &sMnemonic, const QString &sString, STATE *pState, 93 | const XDisasmAbstract::DISASM_OPTIONS &disasmOptions) 94 | { 95 | DISASM_RESULT disasmResult = {}; 96 | disasmResult.bIsValid = true; 97 | disasmResult.nAddress = nAddress; 98 | disasmResult.nSize = nSize; 99 | disasmResult.sMnemonic = sMnemonic; 100 | disasmResult.sOperands = sString; 101 | 102 | _addDisasmResult(pListResults, disasmResult, pState, disasmOptions); 103 | } 104 | 105 | bool XDisasmAbstract::isBranchOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 106 | { 107 | return isJumpOpcode(dmFamily, nOpcodeID) || isCondJumpOpcode(dmFamily, nOpcodeID) || isCallOpcode(dmFamily, nOpcodeID); 108 | } 109 | 110 | bool XDisasmAbstract::isJumpOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 111 | { 112 | bool bResult = false; 113 | 114 | if (dmFamily == XBinary::DMFAMILY_X86) { 115 | if (nOpcodeID == X86_INS_JMP) { 116 | bResult = true; 117 | } 118 | } else if (dmFamily == XBinary::DMFAMILY_ARM) { 119 | if ((nOpcodeID == ARM_INS_B) || (nOpcodeID == ARM_INS_BX)) { 120 | bResult = true; 121 | } 122 | } else if (dmFamily == XBinary::DMFAMILY_ARM64) { 123 | if ((nOpcodeID == ARM64_INS_B) || (nOpcodeID == ARM64_INS_BR)) { 124 | bResult = true; 125 | } 126 | } else if (dmFamily == XBinary::DMFAMILY_BPF) { 127 | if (nOpcodeID == BPF_INS_JMP) { 128 | bResult = true; 129 | } 130 | } else if (dmFamily == XBinary::DMFAMILY_SPARC) { 131 | if (nOpcodeID == SPARC_INS_JMP) { 132 | bResult = true; 133 | } 134 | } else if (dmFamily == XBinary::DMFAMILY_MIPS) { 135 | if (nOpcodeID == MIPS_INS_J) { 136 | bResult = true; 137 | } 138 | } else if (dmFamily == XBinary::DMFAMILY_MOS65XX) { 139 | if (nOpcodeID == MOS65XX_INS_JMP) { 140 | bResult = true; 141 | } 142 | } else if (dmFamily == XBinary::DMFAMILY_M68K) { 143 | if ((nOpcodeID == M68K_INS_BRA) || (nOpcodeID == M68K_INS_JMP)) { 144 | bResult = true; 145 | } 146 | } 147 | 148 | // TODO Other archs 149 | 150 | return bResult; 151 | } 152 | 153 | bool XDisasmAbstract::isRetOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 154 | { 155 | bool bResult = false; 156 | 157 | if (dmFamily == XBinary::DMFAMILY_X86) { 158 | if ((nOpcodeID == X86_INS_RET) || (nOpcodeID == X86_INS_RETF) || (nOpcodeID == X86_INS_RETFQ) || (nOpcodeID == X86_INS_IRET) || (nOpcodeID == X86_INS_IRETD) || 159 | (nOpcodeID == X86_INS_IRETQ)) { 160 | bResult = true; 161 | } 162 | } else if (dmFamily == XBinary::DMFAMILY_ARM64) { 163 | if ((nOpcodeID == ARM64_INS_RET) || (nOpcodeID == ARM64_INS_RETAA) || (nOpcodeID == ARM64_INS_RETAB)) { 164 | bResult = true; 165 | } 166 | } else if (dmFamily == XBinary::DMFAMILY_BPF) { 167 | if ((nOpcodeID == BPF_INS_RET) || (nOpcodeID == BPF_INS_EXIT)) { 168 | bResult = true; 169 | } 170 | } else if (dmFamily == XBinary::DMFAMILY_SPARC) { 171 | if ((nOpcodeID == SPARC_INS_RET) || (nOpcodeID == SPARC_INS_RETL)) { 172 | bResult = true; 173 | } 174 | } else if (dmFamily == XBinary::DMFAMILY_MIPS) { 175 | if ((nOpcodeID == MIPS_INS_JR) || (nOpcodeID == MIPS_INS_ERET)) { // JR ra or exception return 176 | bResult = true; 177 | } 178 | } else if (dmFamily == XBinary::DMFAMILY_MOS65XX) { 179 | if ((nOpcodeID == MOS65XX_INS_RTS) || (nOpcodeID == MOS65XX_INS_RTI)) { 180 | bResult = true; 181 | } 182 | } else if (dmFamily == XBinary::DMFAMILY_M68K) { 183 | if ((nOpcodeID == M68K_INS_RTS) || (nOpcodeID == M68K_INS_RTE) || (nOpcodeID == M68K_INS_RTR) || (nOpcodeID == M68K_INS_RTD)) { 184 | bResult = true; 185 | } 186 | } else if (dmFamily == XBinary::DMFAMILY_PPC) { 187 | if (nOpcodeID == PPC_INS_BLR) { // Branch to link register (return) 188 | bResult = true; 189 | } 190 | } 191 | // TODO Other archs 192 | 193 | return bResult; 194 | } 195 | 196 | bool XDisasmAbstract::isPushOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 197 | { 198 | bool bResult = false; 199 | 200 | if (dmFamily == XBinary::DMFAMILY_X86) { 201 | if ((nOpcodeID == X86_INS_PUSH) || (nOpcodeID == X86_INS_PUSHF) || (nOpcodeID == X86_INS_PUSHFD) || (nOpcodeID == X86_INS_PUSHFQ)) { 202 | bResult = true; 203 | } 204 | } else if (dmFamily == XBinary::DMFAMILY_ARM) { 205 | // PUSH exists for ARM Thumb; classic ARM uses STMDB SP! which Capstone decodes differently 206 | if (nOpcodeID == ARM_INS_PUSH) { 207 | bResult = true; 208 | } 209 | } else if (dmFamily == XBinary::DMFAMILY_M68K) { 210 | // PEA pushes effective address onto the stack 211 | if (nOpcodeID == M68K_INS_PEA) { 212 | bResult = true; 213 | } 214 | } else if (dmFamily == XBinary::DMFAMILY_MOS65XX) { 215 | // 6502 push instructions 216 | if ((nOpcodeID == MOS65XX_INS_PHA) || (nOpcodeID == MOS65XX_INS_PHP)) { 217 | bResult = true; 218 | } 219 | } 220 | // TODO Other archs 221 | 222 | return bResult; 223 | } 224 | 225 | bool XDisasmAbstract::isPopOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 226 | { 227 | bool bResult = false; 228 | 229 | if (dmFamily == XBinary::DMFAMILY_X86) { 230 | if ((nOpcodeID == X86_INS_POP) || (nOpcodeID == X86_INS_POPF) || (nOpcodeID == X86_INS_POPFD) || (nOpcodeID == X86_INS_POPFQ)) { 231 | bResult = true; 232 | } 233 | } else if (dmFamily == XBinary::DMFAMILY_ARM) { 234 | // POP exists for ARM Thumb 235 | if (nOpcodeID == ARM_INS_POP) { 236 | bResult = true; 237 | } 238 | } else if (dmFamily == XBinary::DMFAMILY_MOS65XX) { 239 | // 6502/65xx pull instructions 240 | if ((nOpcodeID == MOS65XX_INS_PLA) || (nOpcodeID == MOS65XX_INS_PLX) || (nOpcodeID == MOS65XX_INS_PLY) || (nOpcodeID == MOS65XX_INS_PLP)) { 241 | bResult = true; 242 | } 243 | } 244 | // TODO Other archs 245 | 246 | return bResult; 247 | } 248 | 249 | bool XDisasmAbstract::isCallOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 250 | { 251 | bool bResult = false; 252 | 253 | if (dmFamily == XBinary::DMFAMILY_X86) { 254 | if (nOpcodeID == X86_INS_CALL) { 255 | bResult = true; 256 | } 257 | } else if (dmFamily == XBinary::DMFAMILY_ARM) { 258 | if ((nOpcodeID == ARM_INS_BL) || (nOpcodeID == ARM_INS_BLX)) { 259 | bResult = true; 260 | } 261 | } else if (dmFamily == XBinary::DMFAMILY_ARM64) { 262 | if ((nOpcodeID == ARM64_INS_BL) || (nOpcodeID == ARM64_INS_BLR)) { 263 | bResult = true; 264 | } 265 | } else if (dmFamily == XBinary::DMFAMILY_MIPS) { 266 | if ((nOpcodeID == MIPS_INS_JAL) || (nOpcodeID == MIPS_INS_JALR)) { 267 | bResult = true; 268 | } 269 | } else if (dmFamily == XBinary::DMFAMILY_SPARC) { 270 | if ((nOpcodeID == SPARC_INS_CALL) || (nOpcodeID == SPARC_INS_JMPL)) { 271 | bResult = true; 272 | } 273 | } else if (dmFamily == XBinary::DMFAMILY_MOS65XX) { 274 | if (nOpcodeID == MOS65XX_INS_JSR) { 275 | bResult = true; 276 | } 277 | } else if (dmFamily == XBinary::DMFAMILY_M68K) { 278 | if ((nOpcodeID == M68K_INS_BSR) || (nOpcodeID == M68K_INS_JSR)) { 279 | bResult = true; 280 | } 281 | } else if (dmFamily == XBinary::DMFAMILY_PPC) { 282 | if ((nOpcodeID == PPC_INS_BL) || (nOpcodeID == PPC_INS_BLA)) { 283 | bResult = true; 284 | } 285 | } else if (dmFamily == XBinary::DMFAMILY_BPF) { 286 | if (nOpcodeID == BPF_INS_CALL) { 287 | bResult = true; 288 | } 289 | } else if (dmFamily == XBinary::DMFAMILY_WASM) { 290 | if (nOpcodeID == WASM_INS_CALL) { 291 | bResult = true; 292 | } 293 | } 294 | // TODO Other archs 295 | 296 | return bResult; 297 | } 298 | 299 | bool XDisasmAbstract::isCondJumpOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 300 | { 301 | bool bResult = false; 302 | 303 | if (dmFamily == XBinary::DMFAMILY_X86) { 304 | if ((nOpcodeID == X86_INS_JA) || (nOpcodeID == X86_INS_JAE) || (nOpcodeID == X86_INS_JB) || (nOpcodeID == X86_INS_JBE) || (nOpcodeID == X86_INS_JCXZ) || 305 | (nOpcodeID == X86_INS_JE) || (nOpcodeID == X86_INS_JECXZ) || (nOpcodeID == X86_INS_JG) || (nOpcodeID == X86_INS_JGE) || (nOpcodeID == X86_INS_JL) || 306 | (nOpcodeID == X86_INS_JLE) || (nOpcodeID == X86_INS_JNE) || (nOpcodeID == X86_INS_JNO) || (nOpcodeID == X86_INS_JNP) || (nOpcodeID == X86_INS_JNS) || 307 | (nOpcodeID == X86_INS_JO) || (nOpcodeID == X86_INS_JP) || (nOpcodeID == X86_INS_JRCXZ) || (nOpcodeID == X86_INS_JS) || (nOpcodeID == X86_INS_LOOP) || 308 | (nOpcodeID == X86_INS_LOOPE) || (nOpcodeID == X86_INS_LOOPNE)) { 309 | bResult = true; 310 | } 311 | } 312 | 313 | return bResult; 314 | } 315 | 316 | bool XDisasmAbstract::isNopOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 317 | { 318 | bool bResult = false; 319 | 320 | if (dmFamily == XBinary::DMFAMILY_X86) { 321 | if (nOpcodeID == X86_INS_NOP) { 322 | bResult = true; 323 | } 324 | } else if (dmFamily == XBinary::DMFAMILY_M68K) { 325 | if (nOpcodeID == M68K_INS_NOP) { 326 | bResult = true; 327 | } 328 | } else if (dmFamily == XBinary::DMFAMILY_MOS65XX) { 329 | if (nOpcodeID == MOS65XX_INS_NOP) { 330 | bResult = true; 331 | } 332 | } else if (dmFamily == XBinary::DMFAMILY_MIPS) { 333 | if (nOpcodeID == MIPS_INS_NOP) { 334 | bResult = true; 335 | } 336 | } else if (dmFamily == XBinary::DMFAMILY_SPARC) { 337 | if (nOpcodeID == SPARC_INS_NOP) { 338 | bResult = true; 339 | } 340 | } else if (dmFamily == XBinary::DMFAMILY_WASM) { 341 | if (nOpcodeID == WASM_INS_NOP) { 342 | bResult = true; 343 | } 344 | } 345 | 346 | return bResult; 347 | } 348 | 349 | bool XDisasmAbstract::isInt3Opcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 350 | { 351 | bool bResult = false; 352 | 353 | if (dmFamily == XBinary::DMFAMILY_X86) { 354 | if (nOpcodeID == X86_INS_INT3) { 355 | bResult = true; 356 | } 357 | } 358 | // TODO Other archs 359 | 360 | return bResult; 361 | } 362 | 363 | bool XDisasmAbstract::isSyscallOpcode(XBinary::DMFAMILY dmFamily, quint32 nOpcodeID) 364 | { 365 | bool bResult = false; 366 | 367 | if (dmFamily == XBinary::DMFAMILY_X86) { 368 | if (nOpcodeID == X86_INS_SYSCALL) { 369 | bResult = true; 370 | } 371 | } 372 | // TODO Other archs 373 | 374 | return bResult; 375 | } 376 | 377 | bool XDisasmAbstract::isGeneralRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 378 | { 379 | bool bResult = false; 380 | 381 | if (dmFamily == XBinary::DMFAMILY_X86) { 382 | QString _sRegister = sRegister; 383 | 384 | if (syntax == XBinary::SYNTAX_ATT) { 385 | qint32 nSize = sRegister.size(); 386 | 387 | if (nSize >= 2) { 388 | if (_sRegister.at(0) == QChar('%')) { 389 | bResult = true; 390 | _sRegister = _sRegister.right(_sRegister.size() - 1); 391 | } 392 | } 393 | } else { 394 | bResult = true; 395 | } 396 | 397 | if (bResult) { 398 | if ((_sRegister == "al") || (_sRegister == "ah") || (_sRegister == "bl") || (_sRegister == "bh") || (_sRegister == "cl") || (_sRegister == "ch") || 399 | (_sRegister == "dl") || (_sRegister == "dh") || (_sRegister == "ax") || (_sRegister == "bx") || (_sRegister == "cx") || (_sRegister == "dx") || 400 | (_sRegister == "si") || (_sRegister == "di") || (_sRegister == "sp") || (_sRegister == "bp") || (_sRegister == "eax") || (_sRegister == "ebx") || 401 | (_sRegister == "ecx") || (_sRegister == "edx") || (_sRegister == "esi") || (_sRegister == "edi") || (_sRegister == "esp") || (_sRegister == "ebp") || 402 | (_sRegister == "rax") || (_sRegister == "rbx") || (_sRegister == "rcx") || (_sRegister == "rdx") || (_sRegister == "rsi") || (_sRegister == "rdi") || 403 | (_sRegister == "rsp") || (_sRegister == "rbp") || (_sRegister == "r8") || (_sRegister == "r9") || (_sRegister == "r10") || (_sRegister == "r11") || 404 | (_sRegister == "r12") || (_sRegister == "r13") || (_sRegister == "r14") || (_sRegister == "r15") || (_sRegister == "r8b") || (_sRegister == "r9b") || 405 | (_sRegister == "r10b") || (_sRegister == "r11b") || (_sRegister == "r12b") || (_sRegister == "r13b") || (_sRegister == "r14b") || 406 | (_sRegister == "r15b") || (_sRegister == "r8d") || (_sRegister == "r9d") || (_sRegister == "r10d") || (_sRegister == "r11d") || (_sRegister == "r12d") || 407 | (_sRegister == "r13d") || (_sRegister == "r14d") || (_sRegister == "r15d")) { 408 | bResult = true; 409 | } else { 410 | bResult = false; 411 | } 412 | } 413 | } else if (dmFamily == XBinary::DMFAMILY_ARM) { 414 | qint32 nSize = sRegister.size(); 415 | 416 | if (nSize >= 2) { 417 | if (sRegister.at(0) == QChar('r')) { 418 | bResult = true; 419 | } 420 | } 421 | } else if (dmFamily == XBinary::DMFAMILY_ARM64) { 422 | qint32 nSize = sRegister.size(); 423 | 424 | if (nSize >= 2) { 425 | if (sRegister.at(0) == QChar('x')) { 426 | bResult = true; 427 | } 428 | } 429 | } 430 | // TODO Other archs 431 | 432 | return bResult; 433 | } 434 | 435 | bool XDisasmAbstract::isStackRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 436 | { 437 | bool bResult = false; 438 | 439 | if (dmFamily == XBinary::DMFAMILY_X86) { 440 | QString _sRegister = removeRegPrefix(dmFamily, sRegister, syntax); 441 | 442 | if (_sRegister != "") { 443 | if ((_sRegister == "sp") || (_sRegister == "bp") || (_sRegister == "esp") || (_sRegister == "ebp") || (_sRegister == "rsp") || (_sRegister == "rbp")) { 444 | bResult = true; 445 | } else { 446 | bResult = false; 447 | } 448 | } 449 | } else if ((dmFamily == XBinary::DMFAMILY_ARM) || (dmFamily == XBinary::DMFAMILY_ARM64)) { 450 | if (sRegister == "sp") { 451 | bResult = true; 452 | } 453 | } 454 | // TODO Other archs 455 | 456 | return bResult; 457 | } 458 | 459 | bool XDisasmAbstract::isSegmentRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 460 | { 461 | Q_UNUSED(syntax) 462 | 463 | bool bResult = false; 464 | 465 | if (dmFamily == XBinary::DMFAMILY_X86) { 466 | QString _sRegister = removeRegPrefix(dmFamily, sRegister, syntax); 467 | 468 | if (_sRegister != "") { 469 | if ((sRegister == "es") || (sRegister == "gs") || (sRegister == "ss") || (sRegister == "ds") || (sRegister == "cs") || (sRegister == "fs")) { 470 | bResult = true; 471 | } else { 472 | bResult = false; 473 | } 474 | } 475 | } 476 | // TODO Other archs 477 | 478 | return bResult; 479 | } 480 | 481 | bool XDisasmAbstract::isDebugRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 482 | { 483 | Q_UNUSED(syntax) 484 | 485 | bool bResult = false; 486 | 487 | if (dmFamily == XBinary::DMFAMILY_X86) { 488 | if ((sRegister == "dr0") || (sRegister == "dr1") || (sRegister == "dr2") || (sRegister == "dr3") || (sRegister == "dr6") || (sRegister == "dr7")) { 489 | bResult = true; 490 | } 491 | } 492 | // TODO Other archs 493 | 494 | return bResult; 495 | } 496 | 497 | bool XDisasmAbstract::isInstructionPointerRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 498 | { 499 | Q_UNUSED(syntax) 500 | 501 | bool bResult = false; 502 | 503 | if (dmFamily == XBinary::DMFAMILY_X86) { 504 | if ((sRegister == "ip") || (sRegister == "eip") || (sRegister == "rip")) { 505 | bResult = true; 506 | } 507 | } else if ((dmFamily == XBinary::DMFAMILY_ARM) || (dmFamily == XBinary::DMFAMILY_ARM64)) { 508 | if (sRegister == "pc") { 509 | bResult = true; 510 | } 511 | } 512 | // TODO Other archs 513 | 514 | return bResult; 515 | } 516 | 517 | bool XDisasmAbstract::isFlagsRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 518 | { 519 | Q_UNUSED(syntax) 520 | 521 | bool bResult = false; 522 | 523 | if (dmFamily == XBinary::DMFAMILY_X86) { 524 | if ((sRegister == "flags") || (sRegister == "eflags") || (sRegister == "rflags")) { 525 | bResult = true; 526 | } 527 | } 528 | // TODO Other archs 529 | 530 | return bResult; 531 | } 532 | 533 | bool XDisasmAbstract::isFPURegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 534 | { 535 | Q_UNUSED(syntax) 536 | Q_UNUSED(sRegister) 537 | 538 | bool bResult = false; 539 | 540 | if (dmFamily == XBinary::DMFAMILY_X86) { 541 | // TODO 542 | } 543 | // TODO Other archs 544 | 545 | return bResult; 546 | } 547 | 548 | bool XDisasmAbstract::isXMMRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 549 | { 550 | Q_UNUSED(syntax) 551 | 552 | bool bResult = false; 553 | 554 | if (dmFamily == XBinary::DMFAMILY_X86) { 555 | qint32 nSize = sRegister.size(); 556 | 557 | if (syntax == XBinary::SYNTAX_ATT) { 558 | if (nSize >= 5) { 559 | if (sRegister.left(4) == "%xmm") { 560 | bResult = true; 561 | } 562 | } 563 | } else { 564 | if (nSize >= 4) { 565 | if (sRegister.left(3) == "xmm") { 566 | bResult = true; 567 | } 568 | } 569 | } 570 | } 571 | 572 | return bResult; 573 | } 574 | 575 | bool XDisasmAbstract::isRegister(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 576 | { 577 | return (isGeneralRegister(dmFamily, sRegister, syntax) || isSegmentRegister(dmFamily, sRegister, syntax) || isDebugRegister(dmFamily, sRegister, syntax) || 578 | isInstructionPointerRegister(dmFamily, sRegister, syntax) || isFlagsRegister(dmFamily, sRegister, syntax) || isFPURegister(dmFamily, sRegister, syntax) || 579 | isXMMRegister(dmFamily, sRegister, syntax)); 580 | } 581 | 582 | bool XDisasmAbstract::isRef(XBinary::DMFAMILY dmFamily, const QString &sOperand, XBinary::SYNTAX syntax) 583 | { 584 | bool bResult = false; 585 | 586 | Q_UNUSED(dmFamily) 587 | Q_UNUSED(syntax) 588 | 589 | if (sOperand.contains("<")) { 590 | bResult = true; 591 | } 592 | 593 | return bResult; 594 | } 595 | 596 | bool XDisasmAbstract::isNumber(XBinary::DMFAMILY dmFamily, const QString &sNumber, XBinary::SYNTAX syntax) 597 | { 598 | bool bResult = false; 599 | 600 | if (dmFamily == XBinary::DMFAMILY_X86) { 601 | if ((syntax == XBinary::SYNTAX_DEFAULT) || (syntax == XBinary::SYNTAX_INTEL)) { 602 | qint32 nSize = sNumber.size(); 603 | if (nSize == 1) { 604 | bResult = true; 605 | } else if (nSize >= 2) { 606 | if (sNumber.left(2) == "0x") { 607 | bResult = true; 608 | } else if (sNumber.at(0) == QChar('-')) { 609 | bResult = true; 610 | } 611 | } 612 | } else if (syntax == XBinary::SYNTAX_MASM) { 613 | qint32 nSize = sNumber.size(); 614 | if (nSize == 1) { 615 | bResult = true; 616 | } else if (nSize > 1) { 617 | if (sNumber.right(1) == "h") { 618 | bResult = true; 619 | } 620 | } 621 | } else if (syntax == XBinary::SYNTAX_ATT) { 622 | qint32 nSize = sNumber.size(); 623 | if ((nSize >= 2) && (sNumber.at(0) == QChar('$')) && (!sNumber.contains(", "))) { 624 | bResult = true; 625 | } 626 | } 627 | } else if ((dmFamily == XBinary::DMFAMILY_ARM) || (dmFamily == XBinary::DMFAMILY_ARM64)) { 628 | // TODO 629 | } 630 | // TODO Other archs 631 | 632 | return bResult; 633 | } 634 | 635 | QString XDisasmAbstract::removeRegPrefix(XBinary::DMFAMILY dmFamily, const QString &sRegister, XBinary::SYNTAX syntax) 636 | { 637 | QString sResult = sRegister; 638 | 639 | if (dmFamily == XBinary::DMFAMILY_X86) { 640 | if (syntax == XBinary::SYNTAX_ATT) { 641 | qint32 nSize = sRegister.size(); 642 | 643 | sResult = ""; 644 | 645 | if (nSize >= 2) { 646 | if (sRegister.at(0) == QChar('%')) { 647 | sResult = sRegister.right(sRegister.size() - 1); 648 | } 649 | } 650 | } 651 | } 652 | 653 | return sResult; 654 | } 655 | -------------------------------------------------------------------------------- /xdisasmcore.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #include "xdisasmcore.h" 23 | 24 | XDisasmCore::XDisasmCore(QObject *pParent) : QObject(pParent) 25 | { 26 | m_disasmMode = XBinary::DM_UNKNOWN; 27 | m_disasmFamily = XBinary::DMFAMILY_UNKNOWN; 28 | m_pDisasmAbstract = nullptr; 29 | m_nOpcodeSize = 15; 30 | m_syntax = XBinary::SYNTAX_DEFAULT; 31 | m_pOptions = nullptr; 32 | #ifdef QT_GUI_LIB 33 | m_qTextOptions.setWrapMode(QTextOption::NoWrap); 34 | #endif 35 | } 36 | 37 | XDisasmCore::~XDisasmCore() 38 | { 39 | if (m_pDisasmAbstract) { 40 | delete m_pDisasmAbstract; 41 | // XCapstone::closeHandle(&m_handle); 42 | } 43 | } 44 | 45 | void XDisasmCore::setMode(XBinary::DM disasmMode) 46 | { 47 | if (m_disasmMode != disasmMode) { 48 | if (m_pDisasmAbstract) { 49 | delete m_pDisasmAbstract; 50 | m_pDisasmAbstract = nullptr; 51 | } 52 | 53 | if (XCapstone::isModeValid(disasmMode)) { 54 | m_pDisasmAbstract = new Capstone_Bridge(disasmMode, m_syntax); 55 | } else if (disasmMode == XBinary::DM_CUSTOM_7ZIP_PROPERTIES) { 56 | m_pDisasmAbstract = new X7Zip_Properties(); 57 | } else if ((disasmMode == XBinary::DM_CUSTOM_MACH_BIND) || (disasmMode == XBinary::DM_CUSTOM_MACH_WEAK) || (disasmMode == XBinary::DM_CUSTOM_MACH_EXPORT) || 58 | (disasmMode == XBinary::DM_CUSTOM_MACH_REBASE)) { 59 | m_pDisasmAbstract = new XMachO_Commands(disasmMode); 60 | } 61 | 62 | m_disasmMode = disasmMode; 63 | m_disasmFamily = XBinary::getDisasmFamily(disasmMode); 64 | } 65 | } 66 | 67 | void XDisasmCore::setSyntax(XBinary::SYNTAX syntax) 68 | { 69 | if (m_syntax != syntax) { 70 | m_syntax = syntax; 71 | XBinary::DM disasmMode = m_disasmMode; 72 | m_disasmMode = XBinary::DM_UNKNOWN; 73 | setMode(disasmMode); // Reload 74 | } 75 | } 76 | 77 | void XDisasmCore::setOptions(XOptions *pOptions) 78 | { 79 | m_pOptions = pOptions; 80 | setSyntax(XBinary::stringToSyntaxId(pOptions->getValue(XOptions::ID_DISASM_SYNTAX).toString())); 81 | 82 | m_mapColors = getColorRecordsMap(pOptions, m_disasmMode); 83 | } 84 | 85 | XBinary::DMFAMILY XDisasmCore::getDisasmFamily() 86 | { 87 | return m_disasmFamily; 88 | } 89 | 90 | XBinary::DM XDisasmCore::getDisasmMode() 91 | { 92 | return m_disasmMode; 93 | } 94 | 95 | XBinary::SYNTAX XDisasmCore::getSyntax() 96 | { 97 | return m_syntax; 98 | } 99 | 100 | QString XDisasmCore::getSignature(QIODevice *pDevice, XBinary::_MEMORY_MAP *pMemoryMap, XADDR nAddress, ST signatureType, qint32 nCount) 101 | { 102 | QString sResult; 103 | 104 | XDisasmAbstract::DISASM_OPTIONS disasmOptions = {}; 105 | 106 | while (nCount > 0) { 107 | qint64 nOffset = XBinary::addressToOffset(pMemoryMap, nAddress); 108 | 109 | if (nOffset == -1) { 110 | break; 111 | } 112 | 113 | QByteArray baData = XBinary::read_array(pDevice, nOffset, 15); 114 | 115 | XDisasmAbstract::DISASM_RESULT _disasmResult = disAsm(baData.data(), baData.size(), nAddress, disasmOptions); 116 | 117 | if (_disasmResult.bIsValid) { 118 | baData.resize(_disasmResult.nSize); 119 | 120 | QString sHEX = baData.toHex().data(); 121 | 122 | if ((signatureType == ST_FULL) || (signatureType == ST_MASK)) { 123 | nAddress += _disasmResult.nSize; 124 | 125 | if (signatureType == ST_MASK) { 126 | if (_disasmResult.nDispSize) { 127 | sHEX = replaceWildChar(sHEX, _disasmResult.nDispOffset, _disasmResult.nDispSize, '.'); 128 | } 129 | 130 | if (_disasmResult.nImmSize) { 131 | sHEX = replaceWildChar(sHEX, _disasmResult.nImmOffset, _disasmResult.nImmSize, '.'); 132 | } 133 | } 134 | } else if (signatureType == ST_REL) { 135 | bool bIsJump = false; 136 | 137 | nAddress = _disasmResult.nNextAddress; 138 | 139 | if ((pMemoryMap->fileType == XBinary::FT_COM) && (_disasmResult.nImmSize == 2)) { 140 | if (nAddress > 0xFFFF) { 141 | nAddress &= 0xFFFF; 142 | } 143 | } 144 | 145 | if (XDisasmAbstract::isBranchOpcode(m_disasmFamily, _disasmResult.nOpcode)) { 146 | // TODO another archs !!! 147 | if (m_disasmFamily == XBinary::DMFAMILY_X86) { 148 | if (_disasmResult.nImmSize) { 149 | sHEX = replaceWildChar(sHEX, _disasmResult.nImmOffset, _disasmResult.nImmSize, '$'); 150 | } 151 | 152 | bIsJump = true; 153 | } 154 | } 155 | 156 | if (!bIsJump) { 157 | if (_disasmResult.nDispSize) { 158 | sHEX = replaceWildChar(sHEX, _disasmResult.nDispOffset, _disasmResult.nDispSize, '.'); 159 | } 160 | 161 | if (_disasmResult.nImmSize) { 162 | sHEX = replaceWildChar(sHEX, _disasmResult.nImmOffset, _disasmResult.nImmSize, '.'); 163 | } 164 | } 165 | } 166 | 167 | sResult += sHEX; 168 | } else { 169 | break; 170 | } 171 | 172 | nCount--; 173 | } 174 | 175 | return sResult; 176 | } 177 | 178 | QList XDisasmCore::getSignatureRecords(QIODevice *pDevice, XBinary::_MEMORY_MAP *pMemoryMap, qint64 nOffset, qint32 nCount, 179 | ST signatureType) 180 | { 181 | QList listResult; 182 | 183 | XDisasmAbstract::DISASM_OPTIONS disasmOptions = {}; 184 | 185 | bool bStopBranch = false; 186 | 187 | for (qint32 i = 0; (i < nCount) && (!bStopBranch); i++) { 188 | if (nOffset != -1) { 189 | XADDR nAddress = XBinary::offsetToAddress(pMemoryMap, nOffset); 190 | 191 | QByteArray baData = XBinary::read_array(pDevice, nOffset, 15); 192 | 193 | XDisasmAbstract::DISASM_RESULT _disasmResult = disAsm(baData.data(), baData.size(), nAddress, disasmOptions); 194 | 195 | if (_disasmResult.bIsValid) { 196 | bStopBranch = !XBinary::isOffsetValid(pMemoryMap, nOffset + _disasmResult.nSize - 1); 197 | 198 | if (!bStopBranch) { 199 | XDisasmCore::SIGNATURE_RECORD record = {}; 200 | 201 | record.nAddress = nAddress; 202 | record.sOpcode = _disasmResult.sMnemonic; 203 | 204 | if (_disasmResult.sOperands != "") { 205 | record.sOpcode += " " + _disasmResult.sOperands; 206 | } 207 | 208 | baData.resize(_disasmResult.nSize); 209 | 210 | record.baOpcode = baData; 211 | 212 | record.nDispOffset = _disasmResult.nDispOffset; 213 | record.nDispSize = _disasmResult.nDispSize; 214 | record.nImmOffset = _disasmResult.nImmOffset; 215 | record.nImmSize = _disasmResult.nImmSize; 216 | 217 | if ((signatureType == ST_FULL) || (signatureType == ST_MASK)) { 218 | nAddress += _disasmResult.nSize; 219 | } else if (signatureType == ST_REL) { 220 | nAddress = _disasmResult.nNextAddress; 221 | record.bIsConst = _disasmResult.bIsConst; 222 | } 223 | 224 | if ((pMemoryMap->fileType == XBinary::FT_COM) && (_disasmResult.nImmSize == 2)) { 225 | if (nAddress > 0xFFFF) { 226 | nAddress &= 0xFFFF; 227 | } 228 | } 229 | 230 | listResult.append(record); 231 | } 232 | } else { 233 | bStopBranch = true; 234 | } 235 | 236 | nOffset = XBinary::addressToOffset(pMemoryMap, nAddress); 237 | } 238 | } 239 | 240 | return listResult; 241 | } 242 | 243 | QString XDisasmCore::replaceWildChar(const QString &sString, qint32 nOffset, qint32 nSize, QChar cWild) 244 | { 245 | QString sResult = sString; 246 | QString sWild; 247 | 248 | sWild = sWild.fill(cWild, nSize * 2); 249 | 250 | sResult = sResult.replace(nOffset * 2, nSize * 2, sWild); 251 | 252 | return sResult; 253 | } 254 | 255 | QString XDisasmCore::getNumberString(qint64 nValue) 256 | { 257 | return XDisasmAbstract::getNumberString(nValue, m_disasmMode, m_syntax); 258 | } 259 | #ifdef QT_GUI_LIB 260 | void XDisasmCore::drawDisasmText(QPainter *pPainter, QRectF rectText, const XDisasmAbstract::DISASM_RESULT &disasmResult) 261 | { 262 | if (pPainter) { 263 | pPainter->save(); 264 | 265 | XOptions::COLOR_RECORD colorRecord = XOptions::COLOR_RECORD(); 266 | 267 | if (!disasmResult.sMnemonic.isEmpty()) { 268 | QRectF _rectMnemonic = rectText; 269 | _rectMnemonic.setWidth(QFontMetrics(pPainter->font()).size(Qt::TextSingleLine, disasmResult.sMnemonic).width()); 270 | 271 | colorRecord = getOpcodeColor(disasmResult.nOpcode); 272 | 273 | drawColorText(pPainter, _rectMnemonic, disasmResult.sMnemonic, colorRecord); 274 | } 275 | 276 | if (!disasmResult.sOperands.isEmpty()) { 277 | QRectF _rectOperands = rectText; 278 | qreal _dLeft = QFontMetrics(pPainter->font()).size(Qt::TextSingleLine, disasmResult.sMnemonic + " ").width(); 279 | _rectOperands.setLeft(_rectOperands.left() + _dLeft); 280 | 281 | if (!XDisasmAbstract::isNopOpcode(m_disasmFamily, disasmResult.nOpcode)) { 282 | QString sCurrent; 283 | QRectF _rectCurrent = _rectOperands; 284 | qint32 nNumberOfChars = disasmResult.sOperands.size(); 285 | 286 | for (qint32 i = 0; i < nNumberOfChars; i++) { 287 | QChar ch = disasmResult.sOperands.at(i); 288 | if ((ch == ',') || (ch == '[') || (ch == ']') || (ch == '+') || (ch == '-') || (ch == '*') || (ch == '(') || (ch == ')') || (ch == ':') || 289 | (ch == ' ')) { 290 | if (!sCurrent.isEmpty()) { 291 | drawOperand(pPainter, _rectCurrent, sCurrent); 292 | } 293 | sCurrent = ""; 294 | 295 | pPainter->drawText(_rectOperands, ch, m_qTextOptions); 296 | } else { 297 | sCurrent.append(ch); 298 | } 299 | 300 | qreal _dLeft = QFontMetrics(pPainter->font()).size(Qt::TextSingleLine, disasmResult.sOperands.at(i)).width(); 301 | _rectOperands.setLeft(_rectOperands.left() + _dLeft); 302 | 303 | if (sCurrent.isEmpty()) { 304 | _rectCurrent = _rectOperands; 305 | } 306 | } 307 | 308 | if (!sCurrent.isEmpty()) { 309 | drawOperand(pPainter, _rectCurrent, sCurrent); 310 | } 311 | } else { 312 | drawColorText(pPainter, _rectOperands, disasmResult.sOperands, colorRecord); 313 | } 314 | } 315 | 316 | pPainter->restore(); 317 | } 318 | } 319 | #endif 320 | #ifdef QT_GUI_LIB 321 | void XDisasmCore::drawOperand(QPainter *pPainter, QRectF rectText, const QString &sOperand) 322 | { 323 | bool bRef = false; 324 | bool bGeneralReg = false; 325 | bool bStackReg = false; 326 | bool bSegmentReg = false; 327 | bool bDebugReg = false; 328 | bool bInstructionPointerReg = false; 329 | bool bFlagsReg = false; 330 | bool bFPUReg = false; 331 | bool bXMMReg = false; 332 | bool bNumber = false; 333 | 334 | if (XDisasmAbstract::isRef(m_disasmFamily, sOperand, m_syntax)) { 335 | bRef = true; 336 | } else if (XDisasmAbstract::isGeneralRegister(m_disasmFamily, sOperand, m_syntax)) { 337 | bGeneralReg = true; 338 | } else if (XDisasmAbstract::isStackRegister(m_disasmFamily, sOperand, m_syntax)) { 339 | bStackReg = true; 340 | } else if (XDisasmAbstract::isSegmentRegister(m_disasmFamily, sOperand, m_syntax)) { 341 | bSegmentReg = true; 342 | } else if (XDisasmAbstract::isDebugRegister(m_disasmFamily, sOperand, m_syntax)) { 343 | bDebugReg = true; 344 | } else if (XDisasmAbstract::isInstructionPointerRegister(m_disasmFamily, sOperand, m_syntax)) { 345 | bInstructionPointerReg = true; 346 | } else if (XDisasmAbstract::isFlagsRegister(m_disasmFamily, sOperand, m_syntax)) { 347 | bFlagsReg = true; 348 | } else if (XDisasmAbstract::isFPURegister(m_disasmFamily, sOperand, m_syntax)) { 349 | bFPUReg = true; 350 | } else if (XDisasmAbstract::isXMMRegister(m_disasmFamily, sOperand, m_syntax)) { 351 | bXMMReg = true; 352 | } else if (XDisasmAbstract::isNumber(m_disasmFamily, sOperand, m_syntax)) { 353 | bNumber = true; 354 | } 355 | 356 | XOptions::COLOR_RECORD colorRecord; 357 | 358 | if (bRef) { 359 | colorRecord = getColorRecord(XDisasmCore::OG_REFS); 360 | } else if (bNumber) { 361 | colorRecord = getColorRecord(XDisasmCore::OG_NUMBERS); 362 | } else if (bGeneralReg || bStackReg || bSegmentReg || bDebugReg || bInstructionPointerReg || bFlagsReg || bFPUReg || bXMMReg) { 363 | if (bGeneralReg) { 364 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_GENERAL); 365 | } else if (bStackReg) { 366 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_STACK); 367 | } else if (bSegmentReg) { 368 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_SEGMENT); 369 | } else if (bDebugReg) { 370 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_DEBUG); 371 | } else if (bInstructionPointerReg) { 372 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_IP); 373 | } else if (bFlagsReg) { 374 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_FLAGS); 375 | } else if (bFPUReg) { 376 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_FPU); 377 | } else if (bXMMReg) { 378 | colorRecord = getColorRecord(XDisasmCore::OG_REGS_XMM); 379 | } 380 | 381 | if ((colorRecord.sColorMain == "") && (colorRecord.sColorBackground == "")) { 382 | colorRecord = getColorRecord(XDisasmCore::OG_REGS); 383 | } 384 | } 385 | 386 | bool bSave = false; 387 | 388 | if ((colorRecord.sColorMain != "") || (colorRecord.sColorBackground != "")) { 389 | bSave = true; 390 | } 391 | 392 | if (bSave) { 393 | pPainter->save(); 394 | } 395 | 396 | if (colorRecord.sColorBackground != "") { 397 | pPainter->fillRect(rectText, QBrush(XOptions::stringToColor(colorRecord.sColorBackground))); 398 | } 399 | 400 | if (colorRecord.sColorMain != "") { 401 | pPainter->setPen(XOptions::stringToColor(colorRecord.sColorMain)); 402 | } 403 | 404 | pPainter->drawText(rectText, sOperand, m_qTextOptions); 405 | 406 | if (bSave) { 407 | pPainter->restore(); 408 | } 409 | } 410 | #endif 411 | #ifdef QT_GUI_LIB 412 | void XDisasmCore::drawColorText(QPainter *pPainter, const QRectF &rect, const QString &sText, const XOptions::COLOR_RECORD &colorRecord) 413 | { 414 | if ((colorRecord.sColorMain != "") || (colorRecord.sColorBackground != "")) { 415 | pPainter->save(); 416 | 417 | QRectF _rectString = rect; 418 | _rectString.setWidth(QFontMetrics(pPainter->font()).size(Qt::TextSingleLine, sText).width()); 419 | 420 | if (colorRecord.sColorBackground != "") { 421 | pPainter->fillRect(_rectString, QBrush(XOptions::stringToColor(colorRecord.sColorBackground))); 422 | } 423 | 424 | if (colorRecord.sColorMain != "") { 425 | pPainter->setPen(XOptions::stringToColor(colorRecord.sColorMain)); 426 | } 427 | 428 | pPainter->drawText(_rectString, sText, m_qTextOptions); 429 | 430 | pPainter->restore(); 431 | } else { 432 | pPainter->drawText(rect, sText, m_qTextOptions); 433 | } 434 | } 435 | #endif 436 | XOptions::COLOR_RECORD XDisasmCore::getOpcodeColor(quint32 nOpcode) 437 | { 438 | XOptions::COLOR_RECORD result = {}; 439 | 440 | if (XDisasmAbstract::isCallOpcode(m_disasmFamily, nOpcode)) { 441 | result = getColorRecord(XDisasmCore::OG_OPCODE_CALL); 442 | } else if (XDisasmAbstract::isCondJumpOpcode(m_disasmFamily, nOpcode)) { 443 | result = getColorRecord(XDisasmCore::OG_OPCODE_CONDJMP); 444 | } else if (XDisasmAbstract::isRetOpcode(m_disasmFamily, nOpcode)) { 445 | result = getColorRecord(XDisasmCore::OG_OPCODE_RET); 446 | } else if (XDisasmAbstract::isPushOpcode(m_disasmFamily, nOpcode)) { 447 | result = getColorRecord(XDisasmCore::OG_OPCODE_PUSH); 448 | } else if (XDisasmAbstract::isPopOpcode(m_disasmFamily, nOpcode)) { 449 | result = getColorRecord(XDisasmCore::OG_OPCODE_POP); 450 | } else if (XDisasmAbstract::isNopOpcode(m_disasmFamily, nOpcode)) { 451 | result = getColorRecord(XDisasmCore::OG_OPCODE_NOP); 452 | } else if (XDisasmAbstract::isJumpOpcode(m_disasmFamily, nOpcode)) { 453 | result = getColorRecord(XDisasmCore::OG_OPCODE_JMP); 454 | } else if (XDisasmAbstract::isInt3Opcode(m_disasmFamily, nOpcode)) { 455 | result = getColorRecord(XDisasmCore::OG_OPCODE_INT3); 456 | } else if (XDisasmAbstract::isSyscallOpcode(m_disasmFamily, nOpcode)) { 457 | result = getColorRecord(XDisasmCore::OG_OPCODE_SYSCALL); 458 | } 459 | 460 | if ((result.sColorMain == "") && (result.sColorBackground == "")) { 461 | result = getColorRecord(XDisasmCore::OG_OPCODE); 462 | } 463 | 464 | return result; 465 | } 466 | 467 | XOptions::COLOR_RECORD XDisasmCore::getColorRecord(XOptions *pOptions, XOptions::ID id) 468 | { 469 | XOptions::COLOR_RECORD result = {}; 470 | 471 | QString sCode = pOptions->getValue(id).toString(); 472 | QString sColorCode = sCode.section("|", 0, 0); 473 | QString sBackgroundCode = sCode.section("|", 1, 1); 474 | 475 | if (sColorCode != "") { 476 | result.sColorMain = sColorCode; 477 | } 478 | 479 | if (sBackgroundCode != "") { 480 | result.sColorBackground = sBackgroundCode; 481 | } 482 | 483 | return result; 484 | } 485 | 486 | QMap XDisasmCore::getColorRecordsMap(XOptions *pOptions, XBinary::DM disasmMode) 487 | { 488 | XBinary::DMFAMILY dmFamily = XBinary::getDisasmFamily(disasmMode); 489 | 490 | QMap mapResult; 491 | 492 | mapResult.insert(XDisasmCore::OG_ARROWS, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARROWS)); 493 | mapResult.insert(XDisasmCore::OG_ARROWS_SELECTED, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARROWS_SELECTED)); 494 | mapResult.insert(XDisasmCore::OG_REGS, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_REGS)); 495 | mapResult.insert(XDisasmCore::OG_NUMBERS, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_NUMBERS)); 496 | mapResult.insert(XDisasmCore::OG_OPCODE, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_OPCODE)); 497 | mapResult.insert(XDisasmCore::OG_REFS, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_REFS)); 498 | 499 | if (dmFamily == XBinary::DMFAMILY_X86) { 500 | mapResult.insert(XDisasmCore::OG_REGS_GENERAL, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_GENERAL)); 501 | mapResult.insert(XDisasmCore::OG_REGS_STACK, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_STACK)); 502 | mapResult.insert(XDisasmCore::OG_REGS_SEGMENT, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_SEGMENT)); 503 | mapResult.insert(XDisasmCore::OG_REGS_DEBUG, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_DEBUG)); 504 | mapResult.insert(XDisasmCore::OG_REGS_IP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_IP)); 505 | mapResult.insert(XDisasmCore::OG_REGS_FLAGS, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_FLAGS)); 506 | mapResult.insert(XDisasmCore::OG_REGS_FPU, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_FPU)); 507 | mapResult.insert(XDisasmCore::OG_REGS_XMM, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_REGS_XMM)); 508 | mapResult.insert(XDisasmCore::OG_OPCODE_CALL, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_CALL)); 509 | mapResult.insert(XDisasmCore::OG_OPCODE_CONDJMP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_COND_JMP)); 510 | mapResult.insert(XDisasmCore::OG_OPCODE_RET, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_RET)); 511 | mapResult.insert(XDisasmCore::OG_OPCODE_PUSH, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_PUSH)); 512 | mapResult.insert(XDisasmCore::OG_OPCODE_POP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_POP)); 513 | mapResult.insert(XDisasmCore::OG_OPCODE_NOP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_NOP)); 514 | mapResult.insert(XDisasmCore::OG_OPCODE_JMP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_JMP)); 515 | mapResult.insert(XDisasmCore::OG_OPCODE_INT3, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_INT3)); 516 | mapResult.insert(XDisasmCore::OG_OPCODE_SYSCALL, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_X86_OPCODE_SYSCALL)); 517 | // TODO 518 | } else if ((dmFamily == XBinary::DMFAMILY_ARM) || (dmFamily == XBinary::DMFAMILY_ARM64)) { 519 | mapResult.insert(XDisasmCore::OG_REGS_GENERAL, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_REGS_GENERAL)); 520 | mapResult.insert(XDisasmCore::OG_OPCODE_JMP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_OPCODE_BRANCH)); 521 | mapResult.insert(XDisasmCore::OG_OPCODE_CALL, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_OPCODE_BRANCHLINK)); 522 | mapResult.insert(XDisasmCore::OG_OPCODE_RET, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_OPCODE_RET)); 523 | mapResult.insert(XDisasmCore::OG_OPCODE_PUSH, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_OPCODE_PUSH)); 524 | mapResult.insert(XDisasmCore::OG_OPCODE_POP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_OPCODE_POP)); 525 | mapResult.insert(XDisasmCore::OG_OPCODE_NOP, getColorRecord(pOptions, XOptions::ID_DISASM_COLOR_ARM_OPCODE_NOP)); 526 | } 527 | 528 | return mapResult; 529 | } 530 | 531 | XOptions::COLOR_RECORD XDisasmCore::getColorRecord(OG og) 532 | { 533 | return m_mapColors.value(og); 534 | } 535 | 536 | XDisasmAbstract::DISASM_RESULT XDisasmCore::disAsm(QIODevice *pDevice, qint64 nOffset, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions) 537 | { 538 | QByteArray baData = XBinary::read_array(pDevice, nOffset, m_nOpcodeSize); 539 | 540 | return disAsm(baData.data(), baData.size(), nAddress, disasmOptions); 541 | } 542 | 543 | QList XDisasmCore::disAsmList(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions, 544 | qint32 nLimit, XBinary::PDSTRUCT *pPdStruct) 545 | { 546 | QList listResult; 547 | 548 | if (m_pDisasmAbstract) { 549 | listResult = m_pDisasmAbstract->_disasm(pData, nDataSize, nAddress, disasmOptions, nLimit, pPdStruct); 550 | } 551 | 552 | return listResult; 553 | } 554 | 555 | XDisasmAbstract::DISASM_RESULT XDisasmCore::disAsm(char *pData, qint32 nDataSize, XADDR nAddress, const XDisasmAbstract::DISASM_OPTIONS &disasmOptions) 556 | { 557 | XDisasmAbstract::DISASM_RESULT result = {}; 558 | 559 | if (m_pDisasmAbstract) { 560 | QList list = disAsmList(pData, nDataSize, nAddress, disasmOptions, 1); 561 | 562 | if (list.count()) { 563 | result = list.at(0); 564 | } 565 | } 566 | 567 | return result; 568 | } 569 | --------------------------------------------------------------------------------