From e75ed40ce036dd83541a3213e5df04d9c1d329d2 Mon Sep 17 00:00:00 2001 From: Mark Long Date: Sun, 30 Oct 2016 22:45:45 -0500 Subject: [PATCH] Major fixes to disassembler --- src/binaryfile/disassembler.cxx | 290 ++++++++++++++++------------- src/binaryfile/disassembler.h | 29 ++- src/ui/viewers/texthexdumpviewer.h | 1 + src/ui/viewers/viewerbase.cpp | 2 +- src/util/util.h | 5 +- 5 files changed, 191 insertions(+), 136 deletions(-) diff --git a/src/binaryfile/disassembler.cxx b/src/binaryfile/disassembler.cxx index 849e8a5..f27649b 100644 --- a/src/binaryfile/disassembler.cxx +++ b/src/binaryfile/disassembler.cxx @@ -8,14 +8,17 @@ Disassembler::Disassembler(QByteArray memimage) { m_memimage = memimage, makeOpcodeTable(); m_memusagemap.clearData(); + } + QList Disassembler::disassemble(quint16 from, quint16 to, QList entryPoints, bool processRecursively) { QList retval; - qDebug() << "Disassemble: From"< Disassembler::disassemble(quint16 from, quint16 to, bool stopping = false; quint16 next = from; - if (entryPoints.count()) + while (entryPoints.count()) { next = entryPoints.takeFirst(); - m_jumps.append(entryPoints); + //m_jumps.append(entryPoints); + m_stack.push(next); } while (!stopping) @@ -59,19 +63,31 @@ QList Disassembler::disassemble(quint16 from, quint16 to, if (item.isBranch()) { qDebug() << "Is Branch"; - if (!m_jumps.contains(item.targetAddress())) - { - m_jumps.append(item.targetAddress()); - } + m_stack.push(item.targetAddress()); +// if (!m_jumps.contains(item.targetAddress())) +// { +// m_jumps.append(item.targetAddress()); +// qDebug() << "Appending branch" << uint16ToHex(item.targetAddress()) << "to jump table"; + +// } } if (item.isJsr() && !item.canNotFollow()) { if (item.targetAddress() <= to) //TODO: Remove this to not limit disassembly to program range - if (!m_jumps.contains(item.targetAddress())) + { + if (m_stack.push(item.targetAddress())) + //if (!m_jumps.contains(item.targetAddress())) { - m_jumps.append(item.targetAddress()); + qDebug() << "Appending" << uint16ToHex(item.targetAddress()) << "to jump table"; + + //m_jumps.append(item.targetAddress()); } + else + { + qDebug() << "Not adding" << uint16ToHex(item.targetAddress()) << "to jump table"; + } + } } if (next <= to) //TODO: Remove this to not limit disassembly to program range @@ -99,19 +115,21 @@ QList Disassembler::disassemble(quint16 from, quint16 to, m_memusagemap.merge(memuse); if (processRecursively) - while (m_jumps.size()) - { - quint16 num = m_jumps.takeFirst(); - if (!m_memusagemap[num].testFlag(Operation)) + //while (m_jumps.size()) + while (!m_stack.isEmpty()) { - if (num >= from && num <= to) // TODO: remove this to not limit disassembly to program range + // quint16 num = m_jumps.takeFirst(); + quint16 num = m_stack.pop(); + if (!m_memusagemap[num].testFlag(Operation)) { - qDebug() << "Calling recursively to"<() << num,false)); - qDebug() << "Return from recursive call."; + if (num >= from && num <= to) // TODO: remove this to not limit disassembly to program range + { + qDebug() << "Calling recursively to"<() << num,false)); + qDebug() << "Return from recursive call."; + } } } - } #endif qSort(retval); @@ -173,7 +191,11 @@ bool Disassembler::disassembleOp(quint16 address, DisassembledItem &retval, Memo if (op.numArgs() == 1) argval = (quint8) hexValues[1]; else if (op.numArgs() == 2) - argval = (quint8) hexValues[1] + ((quint8) hexValues[2] * 256); + { + argval = makeWord(hexValues[1],hexValues[2]); + } + + for (int idx = 0; idx < hexValues.length(); idx++) { hexValueString.append(QString("%1 ").arg((quint8) hexValues[idx],2,16,QChar('0'))); @@ -184,109 +206,112 @@ bool Disassembler::disassembleOp(quint16 address, DisassembledItem &retval, Memo // Disassemble instruction switch (op.addressMode()) { - case AM_InvalidOp: { - disassemblyLine = op.mnemonic(); - retval.setIsInvalidOp(true); - break; - } - case AM_Absolute:{ - disassemblyLine = QString("%1 _ARG16_").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_AbsoluteIndexedIndirect:{ - disassemblyLine = QString("%1 (_ARG16_,x)").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_AbsoluteIndexedWithX:{ - disassemblyLine = QString("%1 _ARG16_,x").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_AbsoluteIndexedWithY:{ - disassemblyLine = QString("%1 _ARG16_,y").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_AbsoluteIndirect:{ - disassemblyLine = QString("%1 (_ARG16_)").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_Immediate:{ - disassemblyLine = QString("%1 #%2").arg(op.mnemonic()).arg((quint8) hexValues[1],2,16,QChar('0')).toUpper(); - retval.setRawArgument(argval); - break; - } - case AM_Implied:{ - disassemblyLine = op.mnemonic(); - break; - } - case AM_Accumulator:{ - disassemblyLine = op.mnemonic(); - break; - } - case AM_ProgramCounterRelative:{ - qint8 offset = (qint8) hexValues[1]; - quint16 offsetAddress = address+2+offset; + case AM_InvalidOp: { + disassemblyLine = op.mnemonic(); + retval.setIsInvalidOp(true); + break; + } + case AM_Absolute:{ + disassemblyLine = QString("%1 _ARG16_").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_AbsoluteIndexedIndirect:{ + disassemblyLine = QString("%1 (_ARG16_,x)").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_AbsoluteIndexedWithX:{ + disassemblyLine = QString("%1 _ARG16_,x").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_AbsoluteIndexedWithY:{ + disassemblyLine = QString("%1 _ARG16_,y").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_AbsoluteIndirect:{ + disassemblyLine = QString("%1 (_ARG16_)").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_Immediate:{ + disassemblyLine = QString("%1 #%2").arg(op.mnemonic()).arg((quint8) hexValues[1],2,16,QChar('0')).toUpper(); + retval.setRawArgument(argval); + break; + } + case AM_Implied:{ + disassemblyLine = op.mnemonic(); + break; + } + case AM_Accumulator:{ + disassemblyLine = op.mnemonic(); + break; + } + case AM_ProgramCounterRelative:{ + qint8 offset = (qint8) hexValues[1]; + quint16 offsetAddress = address+2+offset; - retval.setTargetAddress(offsetAddress); + retval.setTargetAddress(offsetAddress); - disassemblyLine = QString("%1 _ARG16_ {%2%3}").arg(op.mnemonic()) - .arg((offset<0)?"-":"+") - .arg(abs(offset)); - retval.setRawArgument(offsetAddress); - break; - } - case AM_ZeroPage:{ - disassemblyLine = QString("%1 _ARG8_").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_ZeroPageIndirectIndexedWithY:{ - disassemblyLine = QString("%1 (_ARG8_),Y").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_ZeroPageIndexedIndirect:{ - disassemblyLine = QString("%1 (_ARG8_,x)").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_ZeroPageIndexedWithX:{ - disassemblyLine = QString("%1 _ARG8_,x").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_ZeroPageIndexedWithY:{ - disassemblyLine = QString("%1 _ARG8_,y").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - case AM_ZeroPageIndirect:{ - disassemblyLine = QString("%1 (_ARG8_)").arg(op.mnemonic()); - retval.setRawArgument(argval); - break; - } - default:{ - disassemblyLine = op.mnemonic(); - retval.setIsInvalidOp(true); - qDebug() << "Unhandled Address Mode: " << op.addressMode(); - break; - } + disassemblyLine = QString("%1 _ARG16_ {%2%3}").arg(op.mnemonic()) + .arg((offset<0)?"-":"+") + .arg(abs(offset)); + retval.setRawArgument(offsetAddress); + break; + } + case AM_ZeroPage:{ + disassemblyLine = QString("%1 _ARG8_").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_ZeroPageIndirectIndexedWithY:{ + disassemblyLine = QString("%1 (_ARG8_),Y").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_ZeroPageIndexedIndirect:{ + disassemblyLine = QString("%1 (_ARG8_,x)").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_ZeroPageIndexedWithX:{ + disassemblyLine = QString("%1 _ARG8_,x").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_ZeroPageIndexedWithY:{ + disassemblyLine = QString("%1 _ARG8_,y").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + case AM_ZeroPageIndirect:{ + disassemblyLine = QString("%1 (_ARG8_)").arg(op.mnemonic()); + retval.setRawArgument(argval); + break; + } + default:{ + disassemblyLine = op.mnemonic(); + retval.setIsInvalidOp(true); + qDebug() << "Unhandled Address Mode: " << op.addressMode(); + break; + } } if (opcode == 0x20 || opcode == 0x4c) { - retval.setTargetAddress(hexValues[2]*256 + hexValues[1]); + retval.setTargetAddress(makeWord(hexValues[1],hexValues[2])); } if (opcode == 0x4c) { - qDebug() << "JMP: Setting next flow address to"< #include #include +#include enum AddressMode { AM_InvalidOp, @@ -29,6 +30,30 @@ enum AddressMode { }; ////////////////////////////////////////////////////////////////////////////// +class AddressStack +{ + public: + AddressStack() { } + + bool push(quint16 address, bool force = false) { + if (force || (!m_stack.contains(address))) + { + qDebug() << " PUSH: " << uint16ToHex(address); + m_stack.push(address); + return true; + } + return false; + } + + bool isEmpty() { return m_stack.isEmpty(); } + quint16 pop() { return m_stack.pop(); } + + private: + QStack m_stack; +}; + +////////////////////////////////////////////////////////////////////////////// + struct AssyInstruction { public: @@ -93,7 +118,7 @@ public: bool stopsProcessing() { if (isReturn()) qDebug() << "Is Return"; if (isInvalidOp()) qDebug() << "Is Invalid Op" << uint8ToHex(m_instruction.opcode()); - if (canNotFollow()) qDebug() << "Can not follow indirect jump"; + if (canNotFollow()) qDebug() << "Not following jump"; if (isBreak()) qDebug() << "Is Break"; return isBreak() || isInvalidOp() || isReturn() || canNotFollow(); } @@ -168,7 +193,7 @@ private: QHash m_opcodeinfo; QByteArray m_memimage; - QList m_jumps; + AddressStack m_stack; MemoryUsageMap m_memusagemap; diff --git a/src/ui/viewers/texthexdumpviewer.h b/src/ui/viewers/texthexdumpviewer.h index 9361e2a..1dd356f 100644 --- a/src/ui/viewers/texthexdumpviewer.h +++ b/src/ui/viewers/texthexdumpviewer.h @@ -39,6 +39,7 @@ public slots: protected: QString makeTextStr(QByteArray data); QString makeHexStr(QByteArray data); + private: Ui::TextHexDumpViewer *ui; diff --git a/src/ui/viewers/viewerbase.cpp b/src/ui/viewers/viewerbase.cpp index 5a479dc..3efcdc4 100644 --- a/src/ui/viewers/viewerbase.cpp +++ b/src/ui/viewers/viewerbase.cpp @@ -111,7 +111,7 @@ void ViewerBase::setFile(GenericFile *file) } else if (dynamic_cast(file)) { - BinaryFile *bf = dynamic_cast(file); + TextFile *bf = dynamic_cast(file); TextHexDumpViewer *thdv = new TextHexDumpViewer(); thdv->setFile(bf); diff --git a/src/util/util.h b/src/util/util.h index 225145f..790473b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -69,7 +69,10 @@ inline QString uint32ToHex(quint32 val) { return retval; } - +inline quint16 makeWord(quint8 lo, quint8 hi) +{ + return hi*256 + lo; +}