scanner16.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # Copyright (c) 2019, 2021-2022 by Rocky Bernstein
  2. """
  3. Python 1.6 bytecode decompiler massaging.
  4. This massages tokenized 1.6 bytecode to make it more amenable for
  5. grammar parsing.
  6. """
  7. import uncompyle6.scanners.scanner21 as scan
  8. # from uncompyle6.scanners.scanner26 import ingest as ingest26
  9. # bytecode verification, verify(), uses JUMP_OPs from here
  10. from xdis.opcodes import opcode_16
  11. JUMP_OPS = opcode_16.JUMP_OPS
  12. # We base this off of 2.2 instead of the other way around
  13. # because we cleaned things up this way.
  14. # The history is that 2.7 support is the cleanest,
  15. # then from that we got 2.6 and so on.
  16. class Scanner16(scan.Scanner21):
  17. def __init__(self, show_asm=False):
  18. scan.Scanner21.__init__(self, show_asm)
  19. self.opc = opcode_16
  20. self.opname = opcode_16.opname
  21. self.version = (1, 6)
  22. self.genexpr_name = '<generator expression>'
  23. return
  24. def ingest(self, co, classname=None, code_objects={}, show_asm=None):
  25. """
  26. Create "tokens" the bytecode of an Python code object. Largely these
  27. are the opcode name, but in some cases that has been modified to make parsing
  28. easier.
  29. returning a list of uncompyle6 Token's.
  30. Some transformations are made to assist the deparsing grammar:
  31. - various types of LOAD_CONST's are categorized in terms of what they load
  32. - COME_FROM instructions are added to assist parsing control structures
  33. - operands with stack argument counts or flag masks are appended to the opcode name, e.g.:
  34. * BUILD_LIST, BUILD_SET
  35. * MAKE_FUNCTION and FUNCTION_CALLS append the number of positional arguments
  36. - EXTENDED_ARGS instructions are removed
  37. Also, when we encounter certain tokens, we add them to a set which will cause custom
  38. grammar rules. Specifically, variable arg tokens like MAKE_FUNCTION or BUILD_LIST
  39. cause specific rules for the specific number of arguments they take.
  40. """
  41. tokens, customize = scan.Scanner21.ingest(self, co, classname, code_objects, show_asm)
  42. for t in tokens:
  43. if t.op == self.opc.UNPACK_LIST:
  44. t.kind = 'UNPACK_LIST_%d' % t.attr
  45. pass
  46. return tokens, customize