Skip to content

Commit a05ddec

Browse files
authored
Merge pull request #564 from whoami730/exceptions
Parse and display exception table
2 parents 5777203 + d8c6fdf commit a05ddec

File tree

5 files changed

+77
-5
lines changed

5 files changed

+77
-5
lines changed

bytecode.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,3 +600,18 @@ void bc_disasm(std::ostream& pyc_output, PycRef<PycCode> code, PycModule* mod,
600600
pyc_output << "\n";
601601
}
602602
}
603+
604+
void bc_exceptiontable(std::ostream& pyc_output, PycRef<PycCode> code,
605+
int indent)
606+
{
607+
for (const auto& entry : code->exceptionTableEntries()) {
608+
609+
for (int i=0; i<indent; i++)
610+
pyc_output << " ";
611+
612+
pyc_output << entry.start_offset << " to " << entry.end_offset
613+
<< " -> " << entry.target << " [" << entry.stack_depth
614+
<< "] " << (entry.push_lasti ? "lasti": "")
615+
<< "\n";
616+
}
617+
}

bytecode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ void print_const(std::ostream& pyc_output, PycRef<PycObject> obj, PycModule* mod
3232
void bc_next(PycBuffer& source, PycModule* mod, int& opcode, int& operand, int& pos);
3333
void bc_disasm(std::ostream& pyc_output, PycRef<PycCode> code, PycModule* mod,
3434
int indent, unsigned flags);
35+
void bc_exceptiontable(std::ostream& pyc_output, PycRef<PycCode> code,
36+
int indent);

pyc_code.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,44 @@ PycRef<PycString> PycCode::getCellVar(PycModule* mod, int idx) const
128128
? m_freeVars->get(idx - m_cellVars->size()).cast<PycString>()
129129
: m_cellVars->get(idx).cast<PycString>();
130130
}
131+
132+
int _parse_varint(PycBuffer& data, int& pos) {
133+
int b = data.getByte();
134+
pos += 1;
135+
136+
int val = b & 0x3F;
137+
while (b & 0x40) {
138+
val <<= 6;
139+
140+
b = data.getByte();
141+
pos += 1;
142+
143+
val |= (b & 0x3F);
144+
}
145+
return val;
146+
}
147+
148+
std::vector<PycExceptionTableEntry> PycCode::exceptionTableEntries() const
149+
{
150+
PycBuffer data(m_exceptTable->value(), m_exceptTable->length());
151+
152+
std::vector<PycExceptionTableEntry> entries;
153+
154+
int pos = 0;
155+
while (!data.atEof()) {
156+
157+
int start = _parse_varint(data, pos) * 2;
158+
int length = _parse_varint(data, pos) * 2;
159+
int end = start + length;
160+
161+
int target = _parse_varint(data, pos) * 2;
162+
int dl = _parse_varint(data, pos);
163+
164+
int depth = dl >> 1;
165+
bool lasti = bool(dl & 1);
166+
167+
entries.push_back(PycExceptionTableEntry(start, end, target, depth, lasti));
168+
}
169+
170+
return entries;
171+
}

pyc_code.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88
class PycData;
99
class PycModule;
1010

11+
class PycExceptionTableEntry {
12+
public:
13+
int start_offset; // inclusive
14+
int end_offset; // exclusive
15+
int target;
16+
int stack_depth;
17+
bool push_lasti;
18+
19+
PycExceptionTableEntry(int m_start_offset, int m_end_offset, int m_target, int m_stack_depth, bool m_push_lasti) :
20+
start_offset(m_start_offset), end_offset(m_end_offset), target(m_target), stack_depth(m_stack_depth), push_lasti(m_push_lasti) {};
21+
};
22+
1123
class PycCode : public PycObject {
1224
public:
1325
typedef std::vector<PycRef<PycString>> globals_t;
@@ -87,6 +99,8 @@ class PycCode : public PycObject {
8799
m_globalsUsed.emplace_back(std::move(varname));
88100
}
89101

102+
std::vector<PycExceptionTableEntry> exceptionTableEntries() const;
103+
90104
private:
91105
int m_argCount, m_posOnlyArgCount, m_kwOnlyArgCount, m_numLocals;
92106
int m_stackSize, m_flags;

pycdas.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,16 @@ void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
154154
iputs(pyc_output, indent + 1, "[Disassembly]\n");
155155
bc_disasm(pyc_output, codeObj, mod, indent + 2, flags);
156156

157+
if (mod->verCompare(3, 11) >= 0) {
158+
iputs(pyc_output, indent + 1, "[Exception Table]\n");
159+
bc_exceptiontable(pyc_output, codeObj, indent+2);
160+
}
161+
157162
if (mod->verCompare(1, 5) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) {
158163
iprintf(pyc_output, indent + 1, "First Line: %d\n", codeObj->firstLine());
159164
iputs(pyc_output, indent + 1, "[Line Number Table]\n");
160165
output_object(codeObj->lnTable().cast<PycObject>(), mod, indent + 2, flags, pyc_output);
161166
}
162-
163-
if (mod->verCompare(3, 11) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) {
164-
iputs(pyc_output, indent + 1, "[Exception Table]\n");
165-
output_object(codeObj->exceptTable().cast<PycObject>(), mod, indent + 2, flags, pyc_output);
166-
}
167167
}
168168
break;
169169
case PycObject::TYPE_STRING:

0 commit comments

Comments
 (0)