diff --git a/bytecode.cpp b/bytecode.cpp index c6b7cbaf..6bee2799 100644 --- a/bytecode.cpp +++ b/bytecode.cpp @@ -600,3 +600,18 @@ void bc_disasm(std::ostream& pyc_output, PycRef code, PycModule* mod, pyc_output << "\n"; } } + +void bc_exceptiontable(std::ostream& pyc_output, PycRef code, + int indent) +{ + for (const auto& entry : code->exceptionTableEntries()) { + + for (int i=0; i " << entry.target << " [" << entry.stack_depth + << "] " << (entry.push_lasti ? "lasti": "") + << "\n"; + } +} diff --git a/bytecode.h b/bytecode.h index 7e4179e8..3c0d9d3c 100644 --- a/bytecode.h +++ b/bytecode.h @@ -32,3 +32,5 @@ void print_const(std::ostream& pyc_output, PycRef obj, PycModule* mod void bc_next(PycBuffer& source, PycModule* mod, int& opcode, int& operand, int& pos); void bc_disasm(std::ostream& pyc_output, PycRef code, PycModule* mod, int indent, unsigned flags); +void bc_exceptiontable(std::ostream& pyc_output, PycRef code, + int indent); diff --git a/pyc_code.cpp b/pyc_code.cpp index ba63eed4..b88f666e 100644 --- a/pyc_code.cpp +++ b/pyc_code.cpp @@ -128,3 +128,44 @@ PycRef PycCode::getCellVar(PycModule* mod, int idx) const ? m_freeVars->get(idx - m_cellVars->size()).cast() : m_cellVars->get(idx).cast(); } + +int _parse_varint(PycBuffer& data, int& pos) { + int b = data.getByte(); + pos += 1; + + int val = b & 0x3F; + while (b & 0x40) { + val <<= 6; + + b = data.getByte(); + pos += 1; + + val |= (b & 0x3F); + } + return val; +} + +std::vector PycCode::exceptionTableEntries() const +{ + PycBuffer data(m_exceptTable->value(), m_exceptTable->length()); + + std::vector entries; + + int pos = 0; + while (!data.atEof()) { + + int start = _parse_varint(data, pos) * 2; + int length = _parse_varint(data, pos) * 2; + int end = start + length; + + int target = _parse_varint(data, pos) * 2; + int dl = _parse_varint(data, pos); + + int depth = dl >> 1; + bool lasti = bool(dl & 1); + + entries.push_back(PycExceptionTableEntry(start, end, target, depth, lasti)); + } + + return entries; +} diff --git a/pyc_code.h b/pyc_code.h index e6b2ce9b..6485729a 100644 --- a/pyc_code.h +++ b/pyc_code.h @@ -8,6 +8,18 @@ class PycData; class PycModule; +class PycExceptionTableEntry { +public: + int start_offset; // inclusive + int end_offset; // exclusive + int target; + int stack_depth; + bool push_lasti; + + PycExceptionTableEntry(int m_start_offset, int m_end_offset, int m_target, int m_stack_depth, bool m_push_lasti) : + start_offset(m_start_offset), end_offset(m_end_offset), target(m_target), stack_depth(m_stack_depth), push_lasti(m_push_lasti) {}; +}; + class PycCode : public PycObject { public: typedef std::vector> globals_t; @@ -87,6 +99,8 @@ class PycCode : public PycObject { m_globalsUsed.emplace_back(std::move(varname)); } + std::vector exceptionTableEntries() const; + private: int m_argCount, m_posOnlyArgCount, m_kwOnlyArgCount, m_numLocals; int m_stackSize, m_flags; diff --git a/pycdas.cpp b/pycdas.cpp index b73410fe..7b326b16 100644 --- a/pycdas.cpp +++ b/pycdas.cpp @@ -145,16 +145,16 @@ void output_object(PycRef obj, PycModule* mod, int indent, iputs(pyc_output, indent + 1, "[Disassembly]\n"); bc_disasm(pyc_output, codeObj, mod, indent + 2, flags); + if (mod->verCompare(3, 11) >= 0) { + iputs(pyc_output, indent + 1, "[Exception Table]\n"); + bc_exceptiontable(pyc_output, codeObj, indent+2); + } + if (mod->verCompare(1, 5) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) { iprintf(pyc_output, indent + 1, "First Line: %d\n", codeObj->firstLine()); iputs(pyc_output, indent + 1, "[Line Number Table]\n"); output_object(codeObj->lnTable().cast(), mod, indent + 2, flags, pyc_output); } - - if (mod->verCompare(3, 11) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) { - iputs(pyc_output, indent + 1, "[Exception Table]\n"); - output_object(codeObj->exceptTable().cast(), mod, indent + 2, flags, pyc_output); - } } break; case PycObject::TYPE_STRING: