Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to make disassembly more forgiving #19

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions pyevmasm/evmasm.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from binascii import hexlify, unhexlify
from builtins import map, next, range, object
from future.builtins import next, bytes
from copy imports copy

"""
Example use::
Expand Down Expand Up @@ -596,13 +597,15 @@ def assemble_all(asmcode, pc=0):
pc += instr.size


def disassemble_one(bytecode, pc=0):
def disassemble_one(bytecode, pc=0, silent=False):
""" Disassemble a single instruction from a bytecode

:param bytecode: the bytecode stream
:type bytecode: str | bytes | bytearray | iterator
:param pc: program counter of the instruction(optional)
:type pc: int
:param silent: if True disassemble unrecognized instructions as INVALID or incomplete intruction operands as zero
:type silent: bool
:return: an Instruction object
:rtype: Instruction

Expand All @@ -624,22 +627,32 @@ def disassemble_one(bytecode, pc=0):

assert isinstance(opcode, int)

instruction = instruction_table[opcode]

if silent:
if opcode not in instruction_table:
instruction = copy(instruction_table[opcode])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this just get instruction_table[0xfe] for INVALID? Also is there something in the yellow paper that describes the behavior when an unimplemented instruction is run? Just want to make sure it's semantically the same as INVALID, but I don't see anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opps I ment to get 0xfe.

Unimplemented instruction is defined in the yellow (if I remember correctly) as the same as an INVALID. Only diff is that it may get redefined I guess ..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    try:
        instruction = copy(instruction_table[opcode])
    except KeyError:
        if silent:
            instruction = copy(instruction_table[0xfe])
        else:
            raise

??

instruction = copy(instruction_table[opcode])
instruction.pc = pc

if silent:
from itertools import chain, repeat
bytecode = chain(bytecode, repeat(0))

if instruction.has_operand:
instruction.parse_operand(bytecode)

return instruction


def disassemble_all(bytecode, pc=0):
def disassemble_all(bytecode, pc=0, silent=False):
""" Disassemble all instructions in bytecode

:param bytecode: an evm bytecode (binary)
:type bytecode: str | bytes | bytearray | iterator
:param pc: program counter of the first instruction(optional)
:type pc: int
:param silent: if True disassemble unrecognized instructions as INVALID or incomplete intruction operands as zero
:type silent: bool
:return: An generator of Instruction objects
:rtype: list[Instruction]

Expand Down Expand Up @@ -670,19 +683,21 @@ def disassemble_all(bytecode, pc=0):

bytecode = iter(bytecode)
while True:
instr = disassemble_one(bytecode, pc=pc)
instr = disassemble_one(bytecode, pc=pc, silent=silent)
if not instr:
return
pc += instr.size
yield instr


def disassemble(bytecode, pc=0):
def disassemble(bytecode, pc=0, silent=False):
""" Disassemble an EVM bytecode

:param bytecode: binary representation of an evm bytecode
:type bytecode: str | bytes | bytearray
:param pc: program counter of the first instruction(optional)
:param silent: if True disassemble unrecognized instructions as INVALID or incomplete intruction operands as zero
:type silent: bool
:type pc: int
:return: the text representation of the assembler code

Expand All @@ -697,7 +712,7 @@ def disassemble(bytecode, pc=0):
PUSH2 0x100

"""
return '\n'.join(map(str, disassemble_all(bytecode, pc=pc)))
return '\n'.join(map(str, disassemble_all(bytecode, pc=pc, silent=silent)))


def assemble(asmcode, pc=0):
Expand Down