class REF_TYPE(IntEnum):
class DVMBasicBlock:
class BasicBlocks:
class ExceptionAnalysis:
class Exceptions:
class MethodAnalysis:
class StringAnalysis:
class FieldAnalysis:
class ExternalClass:
class ExternalMethod:
class ClassAnalysis:
class MethodClassAnalysis(MethodAnalysis):
class Analysis:
    REF_NEW_INSTANCE = 0x22
    REF_CLASS_USAGE = 0x1c
    INVOKE_VIRTUAL = 0x6e
    INVOKE_SUPER = 0x6f
    INVOKE_DIRECT = 0x70
    INVOKE_STATIC = 0x71
    INVOKE_INTERFACE = 0x72
    INVOKE_VIRTUAL_RANGE = 0x74
    INVOKE_SUPER_RANGE = 0x75
    INVOKE_DIRECT_RANGE = 0x76
    INVOKE_STATIC_RANGE = 0x77
    INVOKE_INTERFACE_RANGE = 0x78
        CG = nx.MultiDiGraph()
    def __init__(self, start, vm, method, context):
    def get_notes(self):
    def set_notes(self, value):
    def add_note(self, note):
    def clear_notes(self):
    def get_instructions(self):
    def get_nb_instructions(self):
    def get_method(self):
    def get_name(self):
    def get_start(self):
    def get_end(self):
    def get_last(self):
    def get_next(self):
    def get_prev(self):
    def set_fathers(self, f):
    def get_last_length(self):
    def set_childs(self, values):
    def push(self, i):
    def get_special_ins(self, idx):
    def get_exception_analysis(self):
    def set_exception_analysis(self, exception_analysis):
    def show(self):
    def __init__(self):
    def push(self, bb):
    def pop(self, idx):
    def get_basic_block(self, idx):
    def __len__(self):
    def __iter__(self):
    def __getitem__(self, item):
    def gets(self):
    def __init__(self, exception, bb):
    def show_buff(self):
    def get(self):
    def __init__(self):
    def add(self, exceptions, basic_blocks):
    def get_exception(self, addr_start, addr_end):
    def gets(self):
    def get(self):
    def __init__(self, vm, method):
    def name(self):
    def descriptor(self):
    def access(self):
    def class_name(self):
    def full_name(self):
    def get_class_name(self):
    def get_access_flags_string(self):
    def get_descriptor(self):
    def _create_basic_block(self):
    def add_xref_read(self, classobj, fieldobj, offset):
    def add_xref_write(self, classobj, fieldobj, offset):
    def get_xref_read(self):
    def get_xref_write(self):
    def add_xref_to(self, classobj, methodobj, offset):
    def add_xref_from(self, classobj, methodobj, offset):
    def get_xref_from(self):
    def get_xref_to(self):
    def add_xref_new_instance(self, classobj, offset):
    def get_xref_new_instance(self):
    def add_xref_const_class(self, classobj, offset):
    def get_xref_const_class(self):
    def is_external(self):
    def is_android_api(self):
    def get_basic_blocks(self):
    def get_length(self):
    def get_vm(self):
    def get_method(self):
    def show(self):
    def show_xrefs(self):
    def __repr__(self):
    def __init__(self, value):
    def add_xref_from(self, classobj, methodobj, off):
    def get_xref_from(self, withoffset=False):
    def set_value(self, value):
    def get_value(self):
    def get_orig_value(self):
    def is_overwritten(self):
    def __str__(self):
    def __repr__(self):
    def __init__(self, field):
    def name(self):
    def add_xref_read(self, classobj, methodobj, offset):
    def add_xref_write(self, classobj, methodobj, offset):
    def get_xref_read(self, withoffset=False):
    def get_xref_write(self, withoffset=False):
    def get_field(self):
    def __str__(self):
    def __repr__(self):
    def __init__(self, name):
    def get_methods(self):
    def add_method(self, method):
    def get_name(self):
    def __repr__(self):
    def __init__(self, class_name, name, descriptor):
    def get_name(self):
    def get_class_name(self):
    def get_descriptor(self):
    def full_name(self):
    def permission_api_name(self):
    def get_access_flags_string(self):
    def __str__(self):
    def __repr__(self):
    def __init__(self, classobj):
    def add_method(self, method_analysis):
    def implements(self):
    def extends(self):
    def name(self):
    def is_external(self):
    def is_android_api(self):
    def get_methods(self):
    def get_fields(self):
    def get_nb_methods(self):
    def get_method_analysis(self, method):
    def get_field_analysis(self, field):
    def add_field_xref_read(self, method, classobj, field, off):
    def add_field_xref_write(self, method, classobj, field, off):
    def add_method_xref_to(self, method1, classobj, method2, offset):
    def add_method_xref_from(self, method1, classobj, method2, offset):
    def add_xref_to(self, ref_kind, classobj, methodobj, offset):
    def add_xref_from(self, ref_kind, classobj, methodobj, offset):
    def get_xref_from(self):
    def get_xref_to(self):
    def add_xref_new_instance(self, methobj, offset):
    def get_xref_new_instance(self):
    def add_xref_const_class(self, methobj, offset):
    def get_xref_const_class(self):
    def get_vm_class(self):
    def set_restriction_flag(self, flag):
    def set_domain_flag(self, flag):
    def __repr__(self):
    def __str__(self):
    def __init__(self, meth):
    def __init__(self, vm=None):
    def add(self, vm):
    def create_xref(self):
    def _create_xref(self, current_class):
    def get_method(self, method):
    def _resolve_method(self, class_name, method_name, method_descriptor):
    def get_method_by_name(self, class_name, method_name, method_descriptor):
    def get_method_analysis_by_name(self, class_name, method_name, method_descriptor):
    def get_field_analysis(self, field):
    def is_class_present(self, class_name):
    def get_class_analysis(self, class_name):
    def get_external_classes(self):
    def get_internal_classes(self):
    def get_strings_analysis(self):
    def get_strings(self):
    def get_classes(self):
    def get_methods(self):
    def get_fields(self):
    def find_classes(self, name=".*", no_external=False):
    def find_methods(self, classname=".*", methodname=".*", descriptor=".*",
            accessflags=".*", no_external=False):
    def find_strings(self, string=".*"):
    def find_fields(self, classname=".*", fieldname=".*", fieldtype=".*", accessflags=".*"):
    def __repr__(self):
    def get_call_graph(self, classname=".*", methodname=".*", descriptor=".*",
                       accessflags=".*", no_isolated=False, entry_points=[]):
        def _add_node(G, method):
    def create_ipython_exports(self):
    def get_permissions(self, apilevel=None):
    def get_permission_usage(self, permission, apilevel=None):
    def get_android_api_usage(self):
def is_ascii_obfuscation(vm): NS_ANDROID_URI = 'http://schemas.android.com/apk/res/android'
NS_ANDROID = '{{{}}}'.format(NS_ANDROID_URI)  # Namespace as used by etree
    _PK_END_OF_CENTRAL_DIR = b"\x50\x4b\x05\x06"
    _PK_CENTRAL_DIR = b"\x50\x4b\x01\x02"
    _APK_SIG_MAGIC = b"APK Sig Block 42"
    _APK_SIG_KEY_V2_SIGNATURE = 0x7109871a
    _APK_SIG_KEY_V3_SIGNATURE = 0xf05368c0
    _APK_SIG_ATTR_V2_STRIPPING_PROTECTION = 0xbeeff00d
    _APK_SIG_ALGO_IDS = {
        0x0101 : "RSASSA-PSS with SHA2-256 digest, SHA2-256 MGF1, 32 bytes of salt, trailer: 0xbc",
        0x0102 : "RSASSA-PSS with SHA2-512 digest, SHA2-512 MGF1, 64 bytes of salt, trailer: 0xbc",
        0x0103 : "RSASSA-PKCS1-v1_5 with SHA2-256 digest.", # This is for build systems which require deterministic signatures.
        0x0104 : "RSASSA-PKCS1-v1_5 with SHA2-512 digest.", # This is for build systems which require deterministic signatures.
        0x0201 : "ECDSA with SHA2-256 digest",
        0x0202 : "ECDSA with SHA2-512 digest",
        0x0301 : "DSA with SHA2-256 digest",
    }
        READ_CALL_LOG = 'android.permission.READ_CALL_LOG'
        READ_CONTACTS = 'android.permission.READ_CONTACTS'
        READ_EXTERNAL_STORAGE = 'android.permission.READ_EXTERNAL_STORAGE'
        READ_PHONE_STATE = 'android.permission.READ_PHONE_STATE'
        WRITE_CALL_LOG = 'android.permission.WRITE_CALL_LOG'
        WRITE_CONTACTS = 'android.permission.WRITE_CONTACTS'
        WRITE_EXTERNAL_STORAGE = 'android.permission.WRITE_EXTERNAL_STORAGE'
def parse_lxml_dom(tree):
def _dump_additional_attributes(additional_attributes):
def _dump_digests_or_signatures(digests_or_sigs):
    def __init__(self):
    def __str__(self):
    def __init__(self):
    def __str__(self):
    def __init__(self):
    def __str__(self):
    def __init__(self):
    def __str__(self):
    def __init__(self, filename, raw=False, magic_file=None, skip_analysis=False, testzip=False):
    def _ns(name):
    def _apk_analysis(self):
    def __getstate__(self):
    def __setstate__(self, state):
    def _get_res_string_value(self, string):
    def _get_permission_maxsdk(self, item):
    def is_valid_APK(self):
    def get_filename(self):
    def get_app_name(self):
    def get_app_icon(self, max_dpi=65536):
    def get_package(self):
    def get_androidversion_code(self):
    def get_androidversion_name(self):
    def get_files(self):
    def _get_file_magic_name(self, buffer):
    def files(self):
    def get_files_types(self):
    def _patch_magic(self, buffer, orig):
    def _get_crc32(self, filename):
    def get_files_crc32(self):
    def get_files_information(self):
    def get_raw(self):
    def get_file(self, filename):
    def get_dex(self):
    def get_dex_names(self):
    def get_all_dex(self):
    def is_multidex(self):
    def get_elements(self, tag_name, attribute, with_namespace=True):
    def _format_value(self, value):
    def get_element(self, tag_name, attribute, **attribute_filter):
    def get_all_attribute_value(
        self, tag_name, attribute, format_value=True, **attribute_filter
    ):
    def get_attribute_value(
        self, tag_name, attribute, format_value=False, **attribute_filter
    ):
    def get_value_from_tag(self, tag, attribute):
    def find_tags(self, tag_name, **attribute_filter):
    def find_tags_from_xml(
        self, xml_name, tag_name, **attribute_filter
    ):
    def is_tag_matched(self, tag, **attribute_filter):
    def get_main_activities(self):
    def get_main_activity(self):
    def get_activities(self):
    def get_services(self):
    def get_receivers(self):
    def get_providers(self):
    def get_res_value(self, name):
    def get_intent_filters(self, itemtype, name):
    def get_permissions(self):
    def get_uses_implied_permission_list(self):
    def get_details_permissions(self):
    def get_requested_permissions(self):
    def get_requested_aosp_permissions(self):
    def get_requested_aosp_permissions_details(self):
    def get_requested_third_party_permissions(self):
    def get_declared_permissions(self):
    def get_declared_permissions_details(self):
    def get_max_sdk_version(self):
    def get_min_sdk_version(self):
    def get_target_sdk_version(self):
    def get_effective_target_sdk_version(self):
    def get_libraries(self):
    def get_features(self):
    def is_wearable(self):
    def is_leanback(self):
    def is_androidtv(self):
    def get_certificate_der(self, filename):
    def get_certificate(self, filename):
    def new_zip(self, filename, deleted_files=None, new_files={}):
    def get_android_manifest_axml(self):
    def get_android_manifest_xml(self):
    def get_android_resources(self):
    def is_signed(self):
    def is_signed_v1(self):
    def is_signed_v2(self):
    def is_signed_v3(self):
    def read_uint32_le(self, io_stream):
    def parse_signatures_or_digests(self, digest_bytes):
    def parse_v2_v3_signature(self):
    def parse_v3_signing_block(self):
    def parse_v2_signing_block(self):
    def get_public_keys_der_v3(self):
    def get_public_keys_der_v2(self):
    def get_certificates_der_v3(self):
    def get_certificates_der_v2(self):
    def get_public_keys_v3(self):
    def get_public_keys_v2(self):
    def get_certificates_v3(self):
    def get_certificates_v2(self):
    def get_certificates_v1(self):
    def get_certificates(self):
    def get_signature_name(self):
    def get_signature_names(self):
    def get_signature(self):
    def get_signatures(self):
    def show(self):
def show_Certificate(cert, short=False):
def ensure_final_value(packageName, arsc, value):
def get_apkid(apkfile):
class Error(Exception):
class FileNotPresent(Error):
class BrokenAPKError(Error):
class APKV2SignedData:
class APKV3SignedData(APKV2SignedData):
class APKV2Signer:
class APKV3Signer(APKV2Signer):
class APK: DEX_FILE_MAGIC_35 = b'dex\n035\x00'
DEX_FILE_MAGIC_36 = b'dex\n036\x00'
DEX_FILE_MAGIC_37 = b'dex\n037\x00'
DEX_FILE_MAGIC_38 = b'dex\n038\x00'
DEX_FILE_MAGIC_39 = b'dex\n039\x00'
ODEX_FILE_MAGIC_35 = b'dey\n035\x00'
ODEX_FILE_MAGIC_36 = b'dey\n036\x00'
ODEX_FILE_MAGIC_37 = b'dey\n037\x00'
ODEX_FILE_MAGIC_38 = b'dey\n038\x00'
VALUE_BYTE = 0x00  # (none; must be 0)      ubyte[1]         signed one-byte integer value
VALUE_SHORT = 0x02  # size - 1 (0..1)  ubyte[size]    signed two-byte integer value, sign-extended
VALUE_CHAR = 0x03  # size - 1 (0..1)  ubyte[size]    unsigned two-byte integer value, zero-extended
VALUE_INT = 0x04  # size - 1 (0..3)  ubyte[size]    signed four-byte integer value, sign-extended
VALUE_LONG = 0x06  # size - 1 (0..7)  ubyte[size]    signed eight-byte integer value, sign-extended
VALUE_FLOAT = 0x10  # size - 1 (0..3)  ubyte[size]    four-byte bit pattern, zero-extended to the right, and interpreted as an IEEE754 32-bit floating point value
VALUE_DOUBLE = 0x11  # size - 1 (0..7)  ubyte[size]    eight-byte bit pattern, zero-extended to the right, and interpreted as an IEEE754 64-bit floating point value
VALUE_STRING = 0x17  # size - 1 (0..3)  ubyte[size]    unsigned (zero-extended) four-byte integer value, interpreted as an index into the string_ids section and representing a string value
VALUE_TYPE = 0x18  # size - 1 (0..3)  ubyte[size]    unsigned (zero-extended) four-byte integer value, interpreted as an index into the type_ids section and representing a reflective type/class value
VALUE_FIELD = 0x19  # size - 1 (0..3)  ubyte[size]    unsigned (zero-extended) four-byte integer value, interpreted as an index into the field_ids section and representing a reflective field value
VALUE_METHOD = 0x1a  # size - 1 (0..3)  ubyte[size]    unsigned (zero-extended) four-byte integer value, interpreted as an index into the method_ids section and representing a reflective method value
VALUE_ENUM = 0x1b  # size - 1 (0..3)  ubyte[size]    unsigned (zero-extended) four-byte integer value, interpreted as an index into the field_ids section and representing the value of an enumerated type constant
VALUE_ARRAY = 0x1c  # (none; must be 0)      encoded_array  an array of values, in the format specified by "encoded_array Format" below. The size of the value is implicit in the encoding.
VALUE_ANNOTATION = 0x1d  # (none; must be 0)      encoded_annotation     a sub-annotation, in the format specified by "encoded_annotation Format" below. The size of the value is implicit in the encoding.
VALUE_NULL = 0x1e  # (none; must be 0)      (none)  null reference value
VALUE_BOOLEAN = 0x1f  # boolean (0..1) (none)  one-bit value; 0 for false and 1 for true. The bit is represented in the value_arg.
DBG_END_SEQUENCE = 0x00  # (none)  terminates a debug info sequence for a code_item
DBG_ADVANCE_PC = 0x01  # uleb128 addr_diff       addr_diff: amount to add to address register    advances the address register without emitting a positions entry
DBG_ADVANCE_LINE = 0x02  # sleb128 line_diff       line_diff: amount to change line register by    advances the line register without emitting a positions entry
DBG_START_LOCAL = 0x03  # uleb128 register_num
DBG_START_LOCAL_EXTENDED = 0x04  # uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx
DBG_END_LOCAL = 0x05  # uleb128 register_num
DBG_RESTART_LOCAL = 0x06  # uleb128 register_num
DBG_SET_PROLOGUE_END = 0x07  # (none)  sets the prologue_end state machine register, indicating that the next position entry that is added should be considered the end of a
DBG_SET_EPILOGUE_BEGIN = 0x08  # (none)  sets the epilogue_begin state machine register, indicating that the next position entry that is added should be considered the beginning
DBG_SET_FILE = 0x09  # uleb128p1 name_idx
DBG_LINE_BASE = -4
DBG_LINE_RANGE = 15
MATH_DVM_OPCODES = {
    "add.": '+',
    "div.": '/',
    "mul.": '*',
    "or.": '|',
    "sub.": '-',
    "and.": '&',
    "xor.": '^',
    "shl.": "<<",
    "shr.": ">>",
}
FIELD_READ_DVM_OPCODES = [".get"]
FIELD_WRITE_DVM_OPCODES = [".put"]
BREAK_DVM_OPCODES = ["invoke.", "move.", ".put", "if."]
BRANCH_DVM_OPCODES = ["throw", "throw.", "if.", "goto", "goto.", "return",
                      "return.", "packed-switch$", "sparse-switch$"]
        WHITELIST = 0
        GREYLIST = 1
        BLACKLIST = 2
        GREYLIST_MAX_O = 3
        GREYLIST_MAX_P = 4
        GREYLIST_MAX_Q = 5
        GREYLIST_MAX_R = 6
        NONE = 0
        CORE_PLATFORM_API = 1
        TEST_API = 2
    OP = 0
DALVIK_OPCODES_FORMAT = {
    # From the Dalvik documentation:
    #
    # > Most format IDs consist of three characters, two digits followed by a letter.
    # > The first digit indicates the number of 16-bit code units in the format.
    # > The second digit indicates the maximum number of registers that the
    # > format contains (maximum, since some formats can accommodate a variable number of registers),
    # > with the special designation "r" indicating that a range of registers is encoded.
    # > The final letter semi-mnemonically indicates the type of any extra data encoded by the format.
    # > For example, format "21t" is of length two, contains one register reference,
    # > and additionally contains a branch target.
    #
    # This dict contains the Instruction type as a python class, the instruction
    # name and if the instruction contains typed arguments also the Kind
    # descriptor.

    0x00: [Instruction10x, ["nop"]],
    0x01: [Instruction12x, ["move"]],
    0x02: [Instruction22x, ["move/from16"]],
    0x03: [Instruction32x, ["move/16"]],
    0x04: [Instruction12x, ["move-wide"]],
    0x05: [Instruction22x, ["move-wide/from16"]],
    0x06: [Instruction32x, ["move-wide/16"]],
    0x07: [Instruction12x, ["move-object"]],
    0x08: [Instruction22x, ["move-object/from16"]],
    0x09: [Instruction32x, ["move-object/16"]],
    0x0a: [Instruction11x, ["move-result"]],
    0x0b: [Instruction11x, ["move-result-wide"]],
    0x0c: [Instruction11x, ["move-result-object"]],
    0x0d: [Instruction11x, ["move-exception"]],
    0x0e: [Instruction10x, ["return-void"]],
    0x0f: [Instruction11x, ["return"]],
    0x10: [Instruction11x, ["return-wide"]],
    0x11: [Instruction11x, ["return-object"]],
    0x12: [Instruction11n, ["const/4"]],
    0x13: [Instruction21s, ["const/16"]],
    0x14: [Instruction31i, ["const"]],
    0x15: [Instruction21h, ["const/high16"]],
    0x16: [Instruction21s, ["const-wide/16"]],
    0x17: [Instruction31i, ["const-wide/32"]],
    0x18: [Instruction51l, ["const-wide"]],
    0x19: [Instruction21h, ["const-wide/high16"]],
    0x1a: [Instruction21c, ["const-string", Kind.STRING]],
    0x1b: [Instruction31c, ["const-string/jumbo", Kind.STRING]],
    0x1c: [Instruction21c, ["const-class", Kind.TYPE]],
    0x1d: [Instruction11x, ["monitor-enter"]],
    0x1e: [Instruction11x, ["monitor-exit"]],
    0x1f: [Instruction21c, ["check-cast", Kind.TYPE]],
    0x20: [Instruction22c, ["instance-of", Kind.TYPE]],
    0x21: [Instruction12x, ["array-length"]],
    0x22: [Instruction21c, ["new-instance", Kind.TYPE]],
    0x23: [Instruction22c, ["new-array", Kind.TYPE]],
    0x24: [Instruction35c, ["filled-new-array", Kind.TYPE]],
    0x25: [Instruction3rc, ["filled-new-array/range", Kind.TYPE]],
    0x26: [Instruction31t, ["fill-array-data"]],
    0x27: [Instruction11x, ["throw"]],
    0x28: [Instruction10t, ["goto"]],
    0x29: [Instruction20t, ["goto/16"]],
    0x2a: [Instruction30t, ["goto/32"]],
    0x2b: [Instruction31t, ["packed-switch"]],
    0x2c: [Instruction31t, ["sparse-switch"]],
    0x2d: [Instruction23x, ["cmpl-float"]],
    0x2e: [Instruction23x, ["cmpg-float"]],
    0x2f: [Instruction23x, ["cmpl-double"]],
    0x30: [Instruction23x, ["cmpg-double"]],
    0x31: [Instruction23x, ["cmp-long"]],
    0x32: [Instruction22t, ["if-eq"]],
    0x33: [Instruction22t, ["if-ne"]],
    0x34: [Instruction22t, ["if-lt"]],
    0x35: [Instruction22t, ["if-ge"]],
    0x36: [Instruction22t, ["if-gt"]],
    0x37: [Instruction22t, ["if-le"]],
    0x38: [Instruction21t, ["if-eqz"]],
    0x39: [Instruction21t, ["if-nez"]],
    0x3a: [Instruction21t, ["if-ltz"]],
    0x3b: [Instruction21t, ["if-gez"]],
    0x3c: [Instruction21t, ["if-gtz"]],
    0x3d: [Instruction21t, ["if-lez"]],
    # unused
    0x3e: [Instruction00x, ["unused"]],
    0x3f: [Instruction00x, ["unused"]],
    0x40: [Instruction00x, ["unused"]],
    0x41: [Instruction00x, ["unused"]],
    0x42: [Instruction00x, ["unused"]],
    0x43: [Instruction00x, ["unused"]],

    0x44: [Instruction23x, ["aget"]],
    0x45: [Instruction23x, ["aget-wide"]],
    0x46: [Instruction23x, ["aget-object"]],
    0x47: [Instruction23x, ["aget-boolean"]],
    0x48: [Instruction23x, ["aget-byte"]],
    0x49: [Instruction23x, ["aget-char"]],
    0x4a: [Instruction23x, ["aget-short"]],
    0x4b: [Instruction23x, ["aput"]],
    0x4c: [Instruction23x, ["aput-wide"]],
    0x4d: [Instruction23x, ["aput-object"]],
    0x4e: [Instruction23x, ["aput-boolean"]],
    0x4f: [Instruction23x, ["aput-byte"]],
    0x50: [Instruction23x, ["aput-char"]],
    0x51: [Instruction23x, ["aput-short"]],
    0x52: [Instruction22c, ["iget", Kind.FIELD]],
    0x53: [Instruction22c, ["iget-wide", Kind.FIELD]],
    0x54: [Instruction22c, ["iget-object", Kind.FIELD]],
    0x55: [Instruction22c, ["iget-boolean", Kind.FIELD]],
    0x56: [Instruction22c, ["iget-byte", Kind.FIELD]],
    0x57: [Instruction22c, ["iget-char", Kind.FIELD]],
    0x58: [Instruction22c, ["iget-short", Kind.FIELD]],
    0x59: [Instruction22c, ["iput", Kind.FIELD]],
    0x5a: [Instruction22c, ["iput-wide", Kind.FIELD]],
    0x5b: [Instruction22c, ["iput-object", Kind.FIELD]],
    0x5c: [Instruction22c, ["iput-boolean", Kind.FIELD]],
    0x5d: [Instruction22c, ["iput-byte", Kind.FIELD]],
    0x5e: [Instruction22c, ["iput-char", Kind.FIELD]],
    0x5f: [Instruction22c, ["iput-short", Kind.FIELD]],
    0x60: [Instruction21c, ["sget", Kind.FIELD]],
    0x61: [Instruction21c, ["sget-wide", Kind.FIELD]],
    0x62: [Instruction21c, ["sget-object", Kind.FIELD]],
    0x63: [Instruction21c, ["sget-boolean", Kind.FIELD]],
    0x64: [Instruction21c, ["sget-byte", Kind.FIELD]],
    0x65: [Instruction21c, ["sget-char", Kind.FIELD]],
    0x66: [Instruction21c, ["sget-short", Kind.FIELD]],
    0x67: [Instruction21c, ["sput", Kind.FIELD]],
    0x68: [Instruction21c, ["sput-wide", Kind.FIELD]],
    0x69: [Instruction21c, ["sput-object", Kind.FIELD]],
    0x6a: [Instruction21c, ["sput-boolean", Kind.FIELD]],
    0x6b: [Instruction21c, ["sput-byte", Kind.FIELD]],
    0x6c: [Instruction21c, ["sput-char", Kind.FIELD]],
    0x6d: [Instruction21c, ["sput-short", Kind.FIELD]],
    0x6e: [Instruction35c, ["invoke-virtual", Kind.METH]],
    0x6f: [Instruction35c, ["invoke-super", Kind.METH]],
    0x70: [Instruction35c, ["invoke-direct", Kind.METH]],
    0x71: [Instruction35c, ["invoke-static", Kind.METH]],
    0x72: [Instruction35c, ["invoke-interface", Kind.METH]],
    # unused
    0x73: [Instruction00x, ["unused"]],

    0x74: [Instruction3rc, ["invoke-virtual/range", Kind.METH]],
    0x75: [Instruction3rc, ["invoke-super/range", Kind.METH]],
    0x76: [Instruction3rc, ["invoke-direct/range", Kind.METH]],
    0x77: [Instruction3rc, ["invoke-static/range", Kind.METH]],
    0x78: [Instruction3rc, ["invoke-interface/range", Kind.METH]],
    # unused
    0x79: [Instruction00x, ["unused"]],
    0x7a: [Instruction00x, ["unused"]],

    0x7b: [Instruction12x, ["neg-int"]],
    0x7c: [Instruction12x, ["not-int"]],
    0x7d: [Instruction12x, ["neg-long"]],
    0x7e: [Instruction12x, ["not-long"]],
    0x7f: [Instruction12x, ["neg-float"]],
    0x80: [Instruction12x, ["neg-double"]],
    0x81: [Instruction12x, ["int-to-long"]],
    0x82: [Instruction12x, ["int-to-float"]],
    0x83: [Instruction12x, ["int-to-double"]],
    0x84: [Instruction12x, ["long-to-int"]],
    0x85: [Instruction12x, ["long-to-float"]],
    0x86: [Instruction12x, ["long-to-double"]],
    0x87: [Instruction12x, ["float-to-int"]],
    0x88: [Instruction12x, ["float-to-long"]],
    0x89: [Instruction12x, ["float-to-double"]],
    0x8a: [Instruction12x, ["double-to-int"]],
    0x8b: [Instruction12x, ["double-to-long"]],
    0x8c: [Instruction12x, ["double-to-float"]],
    0x8d: [Instruction12x, ["int-to-byte"]],
    0x8e: [Instruction12x, ["int-to-char"]],
    0x8f: [Instruction12x, ["int-to-short"]],
    0x90: [Instruction23x, ["add-int"]],
    0x91: [Instruction23x, ["sub-int"]],
    0x92: [Instruction23x, ["mul-int"]],
    0x93: [Instruction23x, ["div-int"]],
    0x94: [Instruction23x, ["rem-int"]],
    0x95: [Instruction23x, ["and-int"]],
    0x96: [Instruction23x, ["or-int"]],
    0x97: [Instruction23x, ["xor-int"]],
    0x98: [Instruction23x, ["shl-int"]],
    0x99: [Instruction23x, ["shr-int"]],
    0x9a: [Instruction23x, ["ushr-int"]],
    0x9b: [Instruction23x, ["add-long"]],
    0x9c: [Instruction23x, ["sub-long"]],
    0x9d: [Instruction23x, ["mul-long"]],
    0x9e: [Instruction23x, ["div-long"]],
    0x9f: [Instruction23x, ["rem-long"]],
    0xa0: [Instruction23x, ["and-long"]],
    0xa1: [Instruction23x, ["or-long"]],
    0xa2: [Instruction23x, ["xor-long"]],
    0xa3: [Instruction23x, ["shl-long"]],
    0xa4: [Instruction23x, ["shr-long"]],
    0xa5: [Instruction23x, ["ushr-long"]],
    0xa6: [Instruction23x, ["add-float"]],
    0xa7: [Instruction23x, ["sub-float"]],
    0xa8: [Instruction23x, ["mul-float"]],
    0xa9: [Instruction23x, ["div-float"]],
    0xaa: [Instruction23x, ["rem-float"]],
    0xab: [Instruction23x, ["add-double"]],
    0xac: [Instruction23x, ["sub-double"]],
    0xad: [Instruction23x, ["mul-double"]],
    0xae: [Instruction23x, ["div-double"]],
    0xaf: [Instruction23x, ["rem-double"]],
    0xb0: [Instruction12x, ["add-int/2addr"]],
    0xb1: [Instruction12x, ["sub-int/2addr"]],
    0xb2: [Instruction12x, ["mul-int/2addr"]],
    0xb3: [Instruction12x, ["div-int/2addr"]],
    0xb4: [Instruction12x, ["rem-int/2addr"]],
    0xb5: [Instruction12x, ["and-int/2addr"]],
    0xb6: [Instruction12x, ["or-int/2addr"]],
    0xb7: [Instruction12x, ["xor-int/2addr"]],
    0xb8: [Instruction12x, ["shl-int/2addr"]],
    0xb9: [Instruction12x, ["shr-int/2addr"]],
    0xba: [Instruction12x, ["ushr-int/2addr"]],
    0xbb: [Instruction12x, ["add-long/2addr"]],
    0xbc: [Instruction12x, ["sub-long/2addr"]],
    0xbd: [Instruction12x, ["mul-long/2addr"]],
    0xbe: [Instruction12x, ["div-long/2addr"]],
    0xbf: [Instruction12x, ["rem-long/2addr"]],
    0xc0: [Instruction12x, ["and-long/2addr"]],
    0xc1: [Instruction12x, ["or-long/2addr"]],
    0xc2: [Instruction12x, ["xor-long/2addr"]],
    0xc3: [Instruction12x, ["shl-long/2addr"]],
    0xc4: [Instruction12x, ["shr-long/2addr"]],
    0xc5: [Instruction12x, ["ushr-long/2addr"]],
    0xc6: [Instruction12x, ["add-float/2addr"]],
    0xc7: [Instruction12x, ["sub-float/2addr"]],
    0xc8: [Instruction12x, ["mul-float/2addr"]],
    0xc9: [Instruction12x, ["div-float/2addr"]],
    0xca: [Instruction12x, ["rem-float/2addr"]],
    0xcb: [Instruction12x, ["add-double/2addr"]],
    0xcc: [Instruction12x, ["sub-double/2addr"]],
    0xcd: [Instruction12x, ["mul-double/2addr"]],
    0xce: [Instruction12x, ["div-double/2addr"]],
    0xcf: [Instruction12x, ["rem-double/2addr"]],
    0xd0: [Instruction22s, ["add-int/lit16"]],
    0xd1: [Instruction22s, ["rsub-int"]],
    0xd2: [Instruction22s, ["mul-int/lit16"]],
    0xd3: [Instruction22s, ["div-int/lit16"]],
    0xd4: [Instruction22s, ["rem-int/lit16"]],
    0xd5: [Instruction22s, ["and-int/lit16"]],
    0xd6: [Instruction22s, ["or-int/lit16"]],
    0xd7: [Instruction22s, ["xor-int/lit16"]],
    0xd8: [Instruction22b, ["add-int/lit8"]],
    0xd9: [Instruction22b, ["rsub-int/lit8"]],
    0xda: [Instruction22b, ["mul-int/lit8"]],
    0xdb: [Instruction22b, ["div-int/lit8"]],
    0xdc: [Instruction22b, ["rem-int/lit8"]],
    0xdd: [Instruction22b, ["and-int/lit8"]],
    0xde: [Instruction22b, ["or-int/lit8"]],
    0xdf: [Instruction22b, ["xor-int/lit8"]],
    0xe0: [Instruction22b, ["shl-int/lit8"]],
    0xe1: [Instruction22b, ["shr-int/lit8"]],
    0xe2: [Instruction22b, ["ushr-int/lit8"]],
    # unused
    0xe3: [Instruction00x, ["unused"]],
    0xe4: [Instruction00x, ["unused"]],
    0xe5: [Instruction00x, ["unused"]],
    0xe6: [Instruction00x, ["unused"]],
    0xe7: [Instruction00x, ["unused"]],
    0xe8: [Instruction00x, ["unused"]],
    0xe9: [Instruction00x, ["unused"]],
    0xea: [Instruction00x, ["unused"]],
    0xeb: [Instruction00x, ["unused"]],
    0xec: [Instruction00x, ["unused"]],
    0xed: [Instruction00x, ["unused"]],
    0xee: [Instruction00x, ["unused"]],
    0xef: [Instruction00x, ["unused"]],
    0xf0: [Instruction00x, ["unused"]],
    0xf1: [Instruction00x, ["unused"]],
    0xf2: [Instruction00x, ["unused"]],
    0xf3: [Instruction00x, ["unused"]],
    0xf4: [Instruction00x, ["unused"]],
    0xf5: [Instruction00x, ["unused"]],
    0xf6: [Instruction00x, ["unused"]],
    0xf7: [Instruction00x, ["unused"]],
    0xf8: [Instruction00x, ["unused"]],
    0xf9: [Instruction00x, ["unused"]],

    # FIXME: what is with the Kinds? Need to implement in get_kinds and opcodes too
    0xfa: [Instruction45cc, ["invoke-polymorphic", Kind.METH_PROTO]],  # Dalvik 038
    0xfb: [Instruction4rcc, ["invoke-polymorphic/range", Kind.METH_PROTO]],  # Dalvik 038
    0xfc: [Instruction35c, ["invoke-custom", Kind.CALL_SITE]],  # Dalvik 038
    0xfd: [Instruction3rc, ["invoke-custom/range", Kind.CALL_SITE]],  # Dalvik 038
    0xfe: [Instruction21c, ["const-method-handle", Kind.METH]],  # Dalvik 039
    0xff: [Instruction21c, ['const-method-type', Kind.PROTO]],  # Dalvik 039
}
DALVIK_OPCODES_PAYLOAD = {
    0x0100: [PackedSwitch],
    0x0200: [SparseSwitch],
    0x0300: [FillArrayData],
}
INLINE_METHODS = [
    ["Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "()V"
     ],
    ["Ljava/lang/String;", "charAt", "(I)C"],
    ["Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I"],
    ["Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z"],
    ["Ljava/lang/String;", "fastIndexOf", "(II)I"],
    ["Ljava/lang/String;", "isEmpty", "()Z"],
    ["Ljava/lang/String;", "length", "()I"],
    ["Ljava/lang/Math;", "abs", "(I)I"],
    ["Ljava/lang/Math;", "abs", "(J)J"],
    ["Ljava/lang/Math;", "abs", "(F)F"],
    ["Ljava/lang/Math;", "abs", "(D)D"],
    ["Ljava/lang/Math;", "min", "(II)I"],
    ["Ljava/lang/Math;", "max", "(II)I"],
    ["Ljava/lang/Math;", "sqrt", "(D)D"],
    ["Ljava/lang/Math;", "cos", "(D)D"],
    ["Ljava/lang/Math;", "sin", "(D)D"],
    ["Ljava/lang/Float;", "floatToIntBits", "(F)I"],
    ["Ljava/lang/Float;", "floatToRawIntBits", "(F)I"],
    ["Ljava/lang/Float;", "intBitsToFloat", "(I)F"],
    ["Ljava/lang/Double;", "doubleToLongBits", "(D)J"],
    ["Ljava/lang/Double;", "doubleToRawLongBits", "(D)J"],
    ["Ljava/lang/Double;", "longBitsToDouble", "(J)D"],
]
DALVIK_OPCODES_OPTIMIZED = {
    0xf2ff: [Instruction5rc, ["invoke-object-init/jumbo", Kind.METH]],
    0xf3ff: [Instruction52c, ["iget-volatile/jumbo", Kind.FIELD]],
    0xf4ff: [Instruction52c, ["iget-wide-volatile/jumbo", Kind.FIELD]],
    0xf5ff: [Instruction52c, ["iget-object-volatile/jumbo ", Kind.FIELD]],
    0xf6ff: [Instruction52c, ["iput-volatile/jumbo", Kind.FIELD]],
    0xf7ff: [Instruction52c, ["iput-wide-volatile/jumbo", Kind.FIELD]],
    0xf8ff: [Instruction52c, ["iput-object-volatile/jumbo", Kind.FIELD]],
    0xf9ff: [Instruction41c, ["sget-volatile/jumbo", Kind.FIELD]],
    0xfaff: [Instruction41c, ["sget-wide-volatile/jumbo", Kind.FIELD]],
    0xfbff: [Instruction41c, ["sget-object-volatile/jumbo", Kind.FIELD]],
    0xfcff: [Instruction41c, ["sput-volatile/jumbo", Kind.FIELD]],
    0xfdff: [Instruction41c, ["sput-wide-volatile/jumbo", Kind.FIELD]],
    0xfeff: [Instruction41c, ["sput-object-volatile/jumbo", Kind.FIELD]],
    0xffff: [Instruction40sc, ["throw-verification-error/jumbo", Kind.VARIES]],
}
class InvalidInstruction(Exception):
class HeaderItem:
class AnnotationOffItem:
class AnnotationSetItem:
class AnnotationSetRefItem:
class AnnotationSetRefList:
class FieldAnnotation:
class MethodAnnotation:
class ParameterAnnotation:
class AnnotationsDirectoryItem:
class HiddenApiClassDataItem:
    class RestrictionApiFlag(IntEnum):
    class DomapiApiFlag(IntEnum):
class TypeItem:
class TypeList:
class DBGBytecode:
class DebugInfoItem:
class DebugInfoItemEmpty:
class EncodedArray:
class EncodedValue:
class AnnotationElement:
class EncodedAnnotation:
class AnnotationItem:
class EncodedArrayItem:
class StringDataItem:
class StringIdItem:
class TypeIdItem:
class TypeHIdItem:
class ProtoIdItem:
class ProtoHIdItem:
class FieldIdItem:
class FieldHIdItem:
class MethodIdItem:
class MethodHIdItem:
class ProtoIdItemInvalid:
class FieldIdItemInvalid:
class MethodIdItemInvalid:
class EncodedField:
class EncodedMethod:
class ClassDataItem:
class ClassDefItem:
class ClassHDefItem:
class EncodedTypeAddrPair:
class EncodedCatchHandler:
class EncodedCatchHandlerList:
class Instruction:
class FillArrayData:
class SparseSwitch:
class PackedSwitch:
class Instruction35c(Instruction):
class Instruction10x(Instruction):
class Instruction21h(Instruction):
class Instruction11n(Instruction):
class Instruction21c(Instruction):
class Instruction21s(Instruction):
class Instruction22c(Instruction):
class Instruction22cs(Instruction):
class Instruction31t(Instruction):
class Instruction31c(Instruction):
class Instruction12x(Instruction):
class Instruction11x(Instruction):
class Instruction51l(Instruction):
class Instruction31i(Instruction):
class Instruction22x(Instruction):
class Instruction23x(Instruction):
class Instruction20t(Instruction):
class Instruction21t(Instruction):
class Instruction10t(Instruction):
class Instruction22t(Instruction):
class Instruction22s(Instruction):
class Instruction22b(Instruction):
class Instruction30t(Instruction):
class Instruction3rc(Instruction):
class Instruction32x(Instruction):
class Instruction20bc(Instruction):
class Instruction35mi(Instruction):
class Instruction35ms(Instruction):
class Instruction3rmi(Instruction):
class Instruction3rms(Instruction):
class Instruction41c(Instruction):
class Instruction40sc(Instruction):
class Instruction52c(Instruction):
class Instruction5rc(Instruction):
class Instruction45cc(Instruction):
class Instruction4rcc(Instruction):
class Instruction00x(Instruction):
class LinearSweepAlgorithm:
class DCode:
class TryItem:
class DalvikCode:
class CodeItem:
class MapItem:
class OffObj:
class ClassManager:
class MapList:
class DalvikPacker:
class DalvikVMFormat(bytecode.BuffHandle):
class OdexHeaderItem:
class OdexDependencies:
class DalvikOdexVMFormat(DalvikVMFormat):
class ExportObject:
def read_null_terminated_string(f):
def get_access_flags_string(value):
def get_type(atype, size=None):
def clean_name_instruction(instruction):
def static_operand_instruction(instruction):
def get_sbyte(cm, buff):
def get_byte(cm, buff):
def readuleb128(cm, buff):
def readuleb128p1(cm, buff):
def readsleb128(cm, buff):
def writeuleb128(cm, value):
def writesleb128(cm, value):
def determineNext(i, cur_idx, m):
def determineException(vm, m):
    def __init__(self, size, buff, cm):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def show(self):
    def set_off(self, off):
    def get_off(self):
    def __init__(self, buff, cm):
    def get_annotation_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def get_annotation_item(self):
    def __init__(self, buff, cm):
    def get_annotation_off_item(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_annotations_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def __init__(self, buff, cm):
    def get_list(self):
    def get_off(self):
    def set_off(self, off):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_field_idx(self):
    def get_annotations_off(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_method_idx(self):
    def get_annotations_off(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_method_idx(self):
    def get_annotations_off(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_class_annotations_off(self):
    def get_annotation_set_item(self):
    def get_annotated_fields_size(self):
    def get_annotated_methods_size(self):
    def get_annotated_parameters_size(self):
    def get_field_annotations(self):
    def get_method_annotations(self):
    def get_parameter_annotations(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_section_size(self):
    def get_flags(self, idx):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_type_idx(self):
    def get_string(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_pad(self):
    def get_type_list_off(self):
    def get_string(self):
    def get_size(self):
    def get_list(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, cm, op_value):
    def get_op_value(self):
    def add(self, value, ttype):
    def get_value(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def __init__(self, buff, cm):
    def get_parameters_size(self):
    def get_line_start(self):
    def get_parameter_names(self):
    def get_translated_parameter_names(self):
    def get_bytecodes(self):
    def show(self):
    def get_raw(self):
    def get_off(self):
    def __init__(self, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def reload(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_size(self):
    def get_values(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_value(self):
    def get_value_type(self):
    def get_value_arg(self):
    def _getintvalue(self, buf):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_name_idx(self):
    def get_value(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_type_idx(self):
    def get_size(self):
    def get_elements(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_visibility(self):
    def get_annotation(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_value(self):
    def set_off(self, off):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def get_off(self):
    def __init__(self, buff, cm):
    def get_utf16_size(self):
    def get_data(self):
    def set_off(self, off):
    def get_off(self):
    def get(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_string_data_off(self):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_descriptor_idx(self):
    def get_descriptor_idx_value(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, size, buff, cm):
    def get_type(self):
    def get(self, idx):
    def set_off(self, off):
    def get_off(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_shorty_idx(self):
    def get_return_type_idx(self):
    def get_parameters_off(self):
    def get_shorty_idx_value(self):
    def get_return_type_idx_value(self):
    def get_parameters_off_value(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, size, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def get(self, idx):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def reload(self):
    def get_class_idx(self):
    def get_type_idx(self):
    def get_name_idx(self):
    def get_class_name(self):
    def get_type(self):
    def get_descriptor(self):
    def get_name(self):
    def get_list(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, size, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def gets(self):
    def get(self, idx):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def reload(self):
    def get_class_idx(self):
    def get_proto_idx(self):
    def get_name_idx(self):
    def get_class_name(self):
    def get_proto(self):
    def get_descriptor(self):
    def get_real_descriptor(self):
    def get_name(self):
    def get_list(self):
    def get_triple(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, size, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def get(self, idx):
    def reload(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def get_params(self):
    def get_shorty(self):
    def get_return_type(self):
    def show(self):
    def get_class_name(self):
    def get_type(self):
    def get_descriptor(self):
    def get_name(self):
    def get_list(self):
    def show(self):
    def get_class_name(self):
    def get_descriptor(self):
    def get_proto(self):
    def get_name(self):
    def get_list(self):
    def show(self):
    def __init__(self, buff, cm):
    def load(self):
    def reload(self):
    def set_init_value(self, value):
    def get_init_value(self):
    def adjust_idx(self, val):
    def get_field_idx_diff(self):
    def get_field_idx(self):
    def get_access_flags(self):
    def get_class_name(self):
    def get_descriptor(self):
    def get_name(self):
    def get_access_flags_string(self):
    def set_name(self, value):
    def get_obj(self):
    def get_raw(self):
    def get_size(self):
    def show(self):
    def __str__(self):
    def __init__(self, buff, cm):
    def adjust_idx(self, val):
    def get_method_idx(self):
    def get_method_idx_diff(self):
    def get_access_flags(self):
    def get_code_off(self):
    def get_address(self):
    def get_access_flags_string(self):
    def load(self):
    def reload(self):
    def get_locals(self):
    def get_information(self):
    def each_params_by_register(self, nb, proto):
    def __str__(self):
    def full_name(self):
    def descriptor(self):
    def get_short_string(self):
        def _fmt_classname(cls):
    def show_info(self):
    def show(self):
    def show_notes(self):
    def source(self):
    def get_source(self):
    def get_length(self):
    def get_code(self):
    def is_cached_instructions(self):
    def get_instructions(self):
    def get_instructions_idx(self):
    def set_instructions(self, instructions):
    def get_instruction(self, idx, off=None):
    def get_debug(self):
    def get_descriptor(self):
    def get_class_name(self):
    def get_name(self):
    def get_triple(self):
    def add_inote(self, msg, idx, off=None):
    def add_note(self, msg):
    def set_code_idx(self, idx):
    def set_name(self, value):
    def get_raw(self):
    def get_size(self):
    def __init__(self, buff, cm):
    def get_static_fields_size(self):
    def get_instance_fields_size(self):
    def get_direct_methods_size(self):
    def get_virtual_methods_size(self):
    def get_static_fields(self):
    def get_instance_fields(self):
    def get_direct_methods(self):
    def get_virtual_methods(self):
    def get_methods(self):
    def get_fields(self):
    def set_off(self, off):
    def set_static_fields(self, value):
    def _load_elements(self, size, l, Type, buff, cm):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def get_off(self):
    def __init__(self, buff, cm):
    def reload(self):
    def __str__(self):
    def __repr__(self):
    def get_methods(self):
    def get_fields(self):
    def _get_annotation_type_ids(self):
    def get_annotations(self):
    def get_class_idx(self):
    def get_access_flags(self):
    def get_superclass_idx(self):
    def get_interfaces_off(self):
    def get_source_file_idx(self):
    def get_annotations_off(self):
    def get_class_data_off(self):
    def get_static_values_off(self):
    def get_class_data(self):
    def get_name(self):
    def get_superclassname(self):
    def get_interfaces(self):
    def get_access_flags_string(self):
    def show(self):
    def source(self):
    def get_source(self):
    def get_source_ext(self):
    def get_ast(self):
    def set_name(self, value):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, size, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def get_class_idx(self, idx):
    def get_method(self, name_class, name_method):
    def get_names(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, cm, buff):
    def get_type_idx(self):
    def get_addr(self):
    def get_obj(self):
    def show(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_size(self):
    def get_handlers(self):
    def get_catch_all_addr(self):
    def get_off(self):
    def set_off(self, off):
    def show(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_size(self):
    def get_list(self):
    def show(self):
    def get_off(self):
    def set_off(self, off):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
def get_kind(cm, kind, value):
    def get_kind(self):
    def get_name(self):
    def get_op_value(self):
    def get_literals(self):
    def show(self, idx):
    def show_buff(self, idx):
    def get_translated_kind(self):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_length(self):
    def get_raw(self):
    def get_ref_kind(self):
    def get_formatted_operands(self):
    def get_hex(self):
    def __str__(self):
    def disasm(self):
    def __init__(self, cm, buff):
    def add_note(self, msg):
    def get_notes(self):
    def get_op_value(self):
    def get_data(self):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_formatted_operands(self):
    def get_name(self):
    def show_buff(self, pos):
    def show(self, pos):
    def get_length(self):
    def get_raw(self):
    def get_hex(self):
    def disasm(self):
    def __init__(self, cm, buff):
    def add_note(self, msg):
    def get_notes(self):
    def get_op_value(self):
    def get_keys(self):
    def get_values(self):
    def get_targets(self):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_formatted_operands(self):
    def get_name(self):
    def show_buff(self, pos):
    def show(self, pos):
    def get_length(self):
    def get_raw(self):
    def get_hex(self):
    def disasm(self):
    def __init__(self, cm, buff):
    def add_note(self, msg):
    def get_notes(self):
    def get_op_value(self):
    def get_keys(self):
    def get_values(self):
    def get_targets(self):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_formatted_operands(self):
    def get_name(self):
    def show_buff(self, pos):
    def show(self, pos):
    def get_length(self):
    def get_raw(self):
    def get_hex(self):
    def disasm(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_string(self):
    def get_raw_string(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_off(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_string(self):
    def get_raw_string(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_off(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_off(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_off(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_off(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_literals(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_off(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_output(self, idx=-1):
    def get_operands(self, idx=-1):
    def get_ref_kind(self):
    def get_raw(self):
    def __init__(self, cm, buff):
    def get_raw(self):
    def get_output(self, idx=-1):
    def get_operands(self):
    def __init__(self, cm, buff):
    def get_raw(self):
    def get_output(self, idx=-1):
    def get_operands(self):
    def __init__(self, cm, buff):
def get_instruction(cm, op_value, buff):
def get_optimized_instruction(cm, op_value, buff):
def get_instruction_payload(op_value, cm, buff):
    def get_instructions(cm, size, insn, idx):
    def __init__(self, class_manager, offset, size, buff):
    def get_insn(self):
    def set_insn(self, insn):
    def set_idx(self, idx):
    def is_cached_instructions(self):
    def set_instructions(self, instructions):
    def get_instructions(self):
    def add_inote(self, msg, idx, off=None):
    def get_instruction(self, idx, off=None):
    def off_to_pos(self, off):
    def get_ins_off(self, off):
    def show(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def get_start_addr(self):
    def get_insn_count(self):
    def get_handler_off(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_registers_size(self):
    def get_ins_size(self):
    def get_outs_size(self):
    def get_tries_size(self):
    def get_debug_info_off(self):
    def get_insns_size(self):
    def get_handlers(self):
    def get_tries(self):
    def get_debug(self):
    def get_bc(self):
    def set_idx(self, idx):
    def get_length(self):
    def _begin_show(self):
    def show(self):
    def _end_show(self):
    def get_obj(self):
    def get_raw(self):
    def add_inote(self, msg, idx, off=None):
    def get_instruction(self, idx, off=None):
    def get_size(self):
    def set_off(self, off):
    def get_off(self):
    def __init__(self, size, buff, cm):
    def set_off(self, off):
    def get_off(self):
    def get_code(self, off):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def __init__(self, buff, cm):
    def get_off(self):
    def get_offset(self):
    def get_type(self):
    def get_size(self):
    def parse(self):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_length(self):
    def set_item(self, item):
    def __init__(self, o):
    def __init__(self, vm):
    def packer(self):
    def packer(self, p):
    def get_ascii_string(self, s):
    def get_odex_format(self):
    def get_obj_by_offset(self, offset):
    def get_item_by_offset(self, offset):
    def get_string_by_offset(self, offset):
    def get_lazy_analysis(self):
    def set_decompiler(self, decompiler):
    def get_engine(self):
    def get_all_engine(self):
    def add_type_item(self, type_item, c_item, item):
    def get_code(self, idx):
    def get_class_data_item(self, off):
    def get_encoded_array_item(self, off):
    def get_annotations_directory_item(self, off):
    def get_annotation_set_item(self, off):
    def get_annotation_off_item(self, off):
    def get_annotation_item(self, off):
    def get_hiddenapi_class_data_item(self, off):
    def get_string(self, idx):
    def get_raw_string(self, idx):
    def get_type_list(self, off):
    def get_type(self, idx):
    def get_type_ref(self, idx):
    def get_proto(self, idx):
    def get_field(self, idx):
    def get_field_ref(self, idx):
    def get_method(self, idx):
    def get_method_ref(self, idx):
    def set_hook_class_name(self, class_def, value):
    def set_hook_method_name(self, encoded_method, value):
    def set_hook_field_name(self, encoded_field, value):
    def set_hook_string(self, idx, value):
    def get_next_offset_item(self, idx):
    def get_debug_off(self, off):
    def __init__(self, cm, off, buff):
    def get_off(self):
    def set_off(self, off):
    def get_item_type(self, ttype):
    def show(self):
    def get_obj(self):
    def get_raw(self):
    def get_class_manager(self):
    def get_length(self):
    def __init__(self, endian_tag):
    def __getitem__(self, item):
    def __getstate__(self):
    def __setstate__(self, state):
    def __init__(self, buff, decompiler=None, config=None, using_api=None):
    def _preload(self, buff):
    def _load(self, buff):
    def _flush(self):
    def version(self):
    def get_vmanalysis(self):
    def set_vmanalysis(self, analysis):
    def get_api_version(self):
    def get_classes_def_item(self):
    def get_methods_id_item(self):
    def get_fields_id_item(self):
    def get_codes_item(self):
    def get_string_data_item(self):
    def get_debug_info_item(self):
    def get_header_item(self):
    def get_hidden_api(self):
    def get_class_manager(self):
    def show(self):
    def save(self):
    def fix_checksums(self, buff):
    def get_cm_field(self, idx):
    def get_cm_method(self, idx):
    def get_cm_string(self, idx):
    def get_cm_type(self, idx):
    def get_classes_names(self, update=False):
    def get_classes(self):
    def get_class(self, name):
    def get_method(self, name):
    def get_field(self, name):
    def get_all_fields(self):
    def get_fields(self):
    def get_methods(self):
    def get_len_methods(self):
    def get_method_by_idx(self, idx):
    def get_method_descriptor(self, class_name, method_name, descriptor):
    def get_methods_descriptor(self, class_name, method_name):
    def get_methods_class(self, class_name):
    def get_fields_class(self, class_name):
    def get_field_descriptor(self, class_name, field_name, descriptor):
    def get_strings(self):
    def get_regex_strings(self, regular_expressions):
    def get_format_type(self):
    def create_python_export(self):
    def _delete_python_export_class(self, _class):
    def _create_python_export_class(self, _class, delete=False):
    def _create_python_export_methods(self, _class, delete):
    def _create_python_export_fields(self, _class, delete):
    def get_BRANCH_DVM_OPCODES(self):
    def get_determineNext(self):
    def get_determineException(self):
    def set_decompiler(self, decompiler):
    def disassemble(self, offset, size):
    def _get_class_hierarchy(self):
    def print_classes_hierarchy(self):
        def print_map(node, l, lvl=0):
    def list_classes_hierarchy(self):
        def print_map(node, l):
    def get_format(self):
    def _get_objs(self, h, index, objs):
    def __init__(self, buff):
    def show(self):
    def get_raw(self):
    def __init__(self, buff):
    def get_dependencies(self):
    def get_raw(self):
    def _preload(self, buff):
    def save(self):
    def get_buff(self):
    def get_dependencies(self):
    def get_format_type(self):
def get_params_info(nb, proto):
def get_bytecodes_method(dex_object, ana_object, method):
def get_bytecodes_methodx(method, mx): class JSONWriter:
    def __init__(self, graph, method):
        self.graph = graph
        self.method = method

        self.visited_nodes = set()
        self.loop_follow = [None]
        self.if_follow = [None]
        self.switch_follow = [None]
        self.latch_node = [None]
        self.try_follow = [None]
        self.next_case = None
        self.need_break = True
        self.constructor = False

        self.context = []

    # This class is created as a context manager so that it can be used like
    # with self as foo:
    #   ...
    # which pushes a statement block on to the context stack and assigns it to foo
    # within the with block, all added instructions will be added to foo
    def __enter__(self):
        self.context.append(statement_block())
        return self.context[-1]

    def __exit__(self, *args):
        self.context.pop()
        return False

    # Add a statement to the current context
    def add(self, val):
        _append(self.context[-1], val)

    def visit_ins(self, op):
        self.add(visit_ins(op, isCtor=self.constructor))

    # Note: this is a mutating operation
    def get_ast(self):
        m = self.method
        flags = m.access
        if 'constructor' in flags:
            flags.remove('constructor')
            self.constructor = True

        params = m.lparams[:]
        if 'static' not in m.access:
            params = params[1:]

        # DAD doesn't create any params for abstract methods
        if len(params) != len(m.params_type):
            assert ('abstract' in flags or 'native' in flags)
            assert (not params)
            params = list(range(len(m.params_type)))

        paramdecls = []
        for ptype, name in zip(m.params_type, params):
            t = parse_descriptor(ptype)
            v = local('p{}'.format(name))
            paramdecls.append(var_decl(t, v))

        if self.graph is None:
            body = None
        else:
            with self as body:
                self.visit_node(self.graph.entry)

        return {
            'triple': m.triple,
            'flags': flags,
            'ret': parse_descriptor(m.type),
            'params': paramdecls,
            'comments': [],
            'body': body,
        }

    def _visit_condition(self, cond):
        if cond.isnot:
            cond.cond1.neg()
        left = parenthesis(self.get_cond(cond.cond1))
        right = parenthesis(self.get_cond(cond.cond2))
        op = '&&' if cond.isand else '||'
        res = binary_infix(op, left, right)
        return res

    def get_cond(self, node):
        if isinstance(node, basic_blocks.ShortCircuitBlock):
            return self._visit_condition(node.cond)
        elif isinstance(node, basic_blocks.LoopBlock):
            return self.get_cond(node.cond)
        else:
            assert (type(node) == basic_blocks.CondBlock)
            assert (len(node.ins) == 1)
            return visit_expr(node.ins[-1])

    def visit_node(self, node):
        if node in (self.if_follow[-1], self.switch_follow[-1],
                    self.loop_follow[-1], self.latch_node[-1],
                    self.try_follow[-1]):
            return
        if not node.type.is_return and node in self.visited_nodes:
            return
        self.visited_nodes.add(node)
        for var in node.var_to_declare:
            if not var.declared:
                self.add(visit_decl(var))
            var.declared = True
        node.visit(self)

    def visit_loop_node(self, loop):
        isDo = cond_expr = body = None

        follow = loop.follow['loop']
        if loop.looptype.is_pretest:
            if loop.true is follow:
                loop.neg()
                loop.true, loop.false = loop.false, loop.true
            isDo = False
            cond_expr = self.get_cond(loop)

        elif loop.looptype.is_posttest:
            isDo = True
            self.latch_node.append(loop.latch)

        elif loop.looptype.is_endless:
            isDo = False
            cond_expr = literal_bool(True)

        with self as body:
            self.loop_follow.append(follow)
            if loop.looptype.is_pretest:
                self.visit_node(loop.true)
            else:
                self.visit_node(loop.cond)
            self.loop_follow.pop()

            if loop.looptype.is_pretest:
                pass
            elif loop.looptype.is_posttest:
                self.latch_node.pop()
                cond_expr = self.get_cond(loop.latch)
            else:
                self.visit_node(loop.latch)

        assert (cond_expr is not None and isDo is not None)
        self.add(loop_stmt(isDo, cond_expr, body))
        if follow is not None:
            self.visit_node(follow)

    def visit_cond_node(self, cond):
        cond_expr = None
        scopes = []

        follow = cond.follow['if']
        if cond.false is cond.true:
            self.add(expression_stmt(self.get_cond(cond)))
            self.visit_node(cond.true)
            return

        if cond.false is self.loop_follow[-1]:
            cond.neg()
            cond.true, cond.false = cond.false, cond.true

        if self.loop_follow[-1] in (cond.true, cond.false):
            cond_expr = self.get_cond(cond)
            with self as scope:
                self.add(jump_stmt('break'))
            scopes.append(scope)

            with self as scope:
                self.visit_node(cond.false)
            scopes.append(scope)

            self.add(if_stmt(cond_expr, scopes))
        elif follow is not None:
            if cond.true in (follow, self.next_case) or \
                            cond.num > cond.true.num:
                # or cond.true.num > cond.false.num:
                cond.neg()
                cond.true, cond.false = cond.false, cond.true
            self.if_follow.append(follow)
            if cond.true:  # in self.visited_nodes:
                cond_expr = self.get_cond(cond)
                with self as scope:
                    self.visit_node(cond.true)
                scopes.append(scope)

            is_else = not (follow in (cond.true, cond.false))
            if is_else and cond.false not in self.visited_nodes:
                with self as scope:
                    self.visit_node(cond.false)
                scopes.append(scope)
            self.if_follow.pop()

            self.add(if_stmt(cond_expr, scopes))
            self.visit_node(follow)
        else:
            cond_expr = self.get_cond(cond)
            with self as scope:
                self.visit_node(cond.true)
            scopes.append(scope)

            with self as scope:
                self.visit_node(cond.false)
            scopes.append(scope)
            self.add(if_stmt(cond_expr, scopes))

    def visit_switch_node(self, switch):
        lins = switch.get_ins()
        for ins in lins[:-1]:
            self.visit_ins(ins)
        switch_ins = switch.get_ins()[-1]

        cond_expr = visit_expr(switch_ins)
        ksv_pairs = []

        follow = switch.follow['switch']
        cases = switch.cases
        self.switch_follow.append(follow)
        default = switch.default
        for i, node in enumerate(cases):
            if node in self.visited_nodes:
                continue

            cur_ks = switch.node_to_case[node][:]
            if i + 1 < len(cases):
                self.next_case = cases[i + 1]
            else:
                self.next_case = None

            if node is default:
                cur_ks.append(None)
                default = None

            with self as body:
                self.visit_node(node)
                if self.need_break:
                    self.add(jump_stmt('break'))
                else:
                    self.need_break = True
            ksv_pairs.append((cur_ks, body))

        if default not in (None, follow):
            with self as body:
                self.visit_node(default)
            ksv_pairs.append(([None], body))

        self.add(switch_stmt(cond_expr, ksv_pairs))
        self.switch_follow.pop()
        self.visit_node(follow)

    def visit_statement_node(self, stmt):
        sucs = self.graph.sucs(stmt)
        for ins in stmt.get_ins():
            self.visit_ins(ins)
        if len(sucs) == 1:
            if sucs[0] is self.loop_follow[-1]:
                self.add(jump_stmt('break'))
            elif sucs[0] is self.next_case:
                self.need_break = False
            else:
                self.visit_node(sucs[0])

    def visit_try_node(self, try_node):
        with self as tryb:
            self.try_follow.append(try_node.follow)
            self.visit_node(try_node.try_start)

        pairs = []
        for catch_node in try_node.catch:
            if catch_node.exception_ins:
                ins = catch_node.exception_ins
                assert (isinstance(ins, instruction.MoveExceptionExpression))
                var = ins.var_map[ins.ref]
                var.declared = True

                ctype = var.get_type()
                name = 'v{}'.format(var.name)
            else:
                ctype = catch_node.catch_type
                name = '_'
            catch_decl = var_decl(parse_descriptor(ctype), local(name))

            with self as body:
                self.visit_node(catch_node.catch_start)
            pairs.append((catch_decl, body))

        self.add(try_stmt(tryb, pairs))
        self.visit_node(self.try_follow.pop())

    def visit_return_node(self, ret):
        self.need_break = False
        for ins in ret.get_ins():
            self.visit_ins(ins)

    def visit_throw_node(self, throw):
        for ins in throw.get_ins():
            self.visit_ins(ins) def parse_descriptor(desc):
    dim = 0
    while desc and desc[0] == '[':
        desc = desc[1:]
        dim += 1

    if desc in TYPE_DESCRIPTOR:
        return typen('.' + TYPE_DESCRIPTOR[desc], dim)
    if desc and desc[0] == 'L' and desc[-1] == ';':
        return typen(desc[1:-1], dim)
    # invalid descriptor (probably None)
    return dummy(str(desc)) def literal_string(s):
    return literal(str(s), ('java/lang/String', 0)) def literal_hex_int(b):
    return literal(hex(b), ('.int', 0)) def dummy(*args):
    return ['Dummy', args] def build_def_use(graph, lparams):
    """
    Builds the Def-Use and Use-Def (DU/UD) chains of the variables of the
    method.
    """
    analysis = reach_def_analysis(graph, lparams)

    UD = defaultdict(list)
    for node in graph.rpo:
        for i, ins in node.get_loc_with_ins():
            for var in ins.get_used_vars():
                # var not in analysis.def_to_loc: test that the register
                # exists. It is possible that it is not the case, when a
                # variable is of a type which is stored on multiple registers
                # e.g: a 'double' stored in v3 is also present in v4, so a call
                # to foo(v3), will in fact call foo(v3, v4).
                if var not in analysis.def_to_loc:
                    continue
                ldefs = analysis.defs[node]
                prior_def = -1
                for v in ldefs.get(var, set()):
                    if prior_def < v < i:
                        prior_def = v
                if prior_def >= 0:
                    UD[var, i].append(prior_def)
                else:
                    intersect = analysis.def_to_loc[var].intersection(
                        analysis.R[node])
                    UD[var, i].extend(intersect)
    DU = defaultdict(list)
    for var_loc, defs_loc in UD.items():
        var, loc = var_loc
        for def_loc in defs_loc:
            DU[var, def_loc].append(loc)

    return UD, DU def place_declarations(graph, dvars, du, ud):
    idom = graph.immediate_dominators()
    for node in graph.post_order():
        for loc, ins in node.get_loc_with_ins():
            for var in ins.get_used_vars():
                if (not isinstance(dvars[var], Variable) or
                        isinstance(dvars[var], Param)):
                    continue
                var_defs_locs = ud[var, loc]
                def_nodes = set()
                for def_loc in var_defs_locs:
                    def_node = graph.get_node_from_loc(def_loc)
                    # TODO: place declarations in catch if needed
                    if def_node.in_catch:
                        continue
                    def_nodes.add(def_node)
                if not def_nodes:
                    continue
                common_dominator = def_nodes.pop()
                for def_node in def_nodes:
                    common_dominator = common_dom(
                        idom, common_dominator, def_node)
                if any(var in range(*common_dominator.ins_range)
                       for var in ud[var, loc]):
                    continue
                common_dominator.add_variable_declaration(dvars[var]) def dead_code_elimination(graph, du, ud):
    """
    Run a dead code elimination pass.
    Instructions are checked to be dead. If it is the case, we remove them and
    we update the DU & UD chains of its variables to check for further dead
    instructions.
    """
    for node in graph.rpo:
        for i, ins in node.get_loc_with_ins():
            reg = ins.get_lhs()
            if reg is not None:
                # If the definition is not used, we check that the instruction
                # has no side effect. If there is one and this is a call, we
                # remove only the unused defined variable. else, this is
                # something like an array access, so we do nothing.
                # Otherwise (no side effect) we can remove the instruction from
                # the node.
                if (reg, i) not in du:
                    if ins.is_call():
                        ins.remove_defined_var()
                    elif ins.has_side_effect():
                        continue
                    else:
                        # We can delete the instruction. First update the DU
                        # chain of the variables used by the instruction to
                        # `let them know` that they are not used anymore by the
                        # deleted instruction.
                        # Then remove the instruction.
                        update_chain(graph, i, du, ud)
                        graph.remove_ins(i) def register_propagation(graph, du, ud):
    """
    Propagate the temporary registers between instructions and remove them if
    necessary.
    We process the nodes of the graph in reverse post order. For each
    instruction in the node, we look at the variables that it uses. For each of
    these variables we look where it is defined and if we can replace it with
    its definition.
    We have to be careful to the side effects some instructions may have.
    To do the propagation, we use the computed DU and UD chains.
    """
    change = True
    while change:
        change = False
        for node in graph.rpo:
            for i, ins in node.get_loc_with_ins():
                logger.debug('Treating instruction %d: %s', i, ins)
                logger.debug('  Used vars: %s', ins.get_used_vars())
                for var in ins.get_used_vars():
                    # Get the list of locations this variable is defined at.
                    locs = ud[var, i]
                    logger.debug('    var %s defined in lines %s', var, locs)
                    # If the variable is uniquely defined for this instruction
                    # it may be eligible for propagation.
                    if len(locs) != 1:
                        continue

                    loc = locs[0]
                    # Methods parameters are defined with a location < 0.
                    if loc < 0:
                        continue
                    orig_ins = graph.get_ins_from_loc(loc)
                    logger.debug('     -> %s', orig_ins)
                    logger.debug('     -> DU(%s, %s) = %s', var, loc,
                                 du[var, loc])

                    # We defined some instructions as not propagable.
                    # Actually this is the case only for array creation
                    # (new foo[x])
                    if not orig_ins.is_propagable():
                        logger.debug('    %s not propagable...', orig_ins)
                        continue

                    if not orig_ins.get_rhs().is_const():
                        # We only try to propagate constants and definition
                        # points which are used at only one location.
                        if len(du[var, loc]) > 1:
                            logger.debug('       => variable has multiple uses'
                                         ' and is not const => skip')
                            continue

                        # We check that the propagation is safe for all the
                        # variables that are used in the instruction.
                        # The propagation is not safe if there is a side effect
                        # along the path from the definition of the variable
                        # to its use in the instruction, or if the variable may
                        # be redifined along this path.
                        safe = True
                        orig_ins_used_vars = orig_ins.get_used_vars()
                        logger.debug('    variables used by the original '
                                     'instruction: %s', orig_ins_used_vars)
                        for var2 in orig_ins_used_vars:
                            # loc is the location of the defined variable
                            # i is the location of the current instruction
                            if not clear_path(graph, var2, loc, i):
                                safe = False
                                break
                        if not safe:
                            logger.debug('Propagation NOT SAFE')
                            continue

                    # We also check that the instruction itself is
                    # propagable. If the instruction has a side effect it
                    # cannot be propagated if there is another side effect
                    # along the path
                    if orig_ins.has_side_effect():
                        if not clear_path(graph, None, loc, i):
                            logger.debug('        %s has side effect and the '
                                         'path is not clear !', orig_ins)
                            continue

                    logger.debug('     => Modification of the instruction!')
                    logger.debug('      - BEFORE: %s', ins)
                    ins.replace(var, orig_ins.get_rhs())
                    logger.debug('      -> AFTER: %s', ins)
                    logger.debug('\t UD(%s, %s) : %s', var, i, ud[var, i])
                    ud[var, i].remove(loc)
                    logger.debug('\t    -> %s', ud[var, i])
                    if len(ud[var, i]) == 0:
                        ud.pop((var, i))
                    for var2 in orig_ins.get_used_vars():
                        # We update the UD chain of the variables we
                        # propagate. We also have to take the
                        # definition points of all the variables used
                        # by the instruction and update the DU chain
                        # with this information.
                        old_ud = ud.get((var2, loc))
                        logger.debug('\t  ud(%s, %s) = %s', var2, loc, old_ud)
                        # If the instruction use the same variable
                        # multiple times, the second+ time the ud chain
                        # will be None because already treated.
                        if old_ud is None:
                            continue
                        ud[var2, i].extend(old_ud)
                        logger.debug('\t  - ud(%s, %s) = %s', var2, i,
                                     ud[var2, i])
                        ud.pop((var2, loc))

                        for def_loc in old_ud:
                            du[var2, def_loc].remove(loc)
                            du[var2, def_loc].append(i)

                    new_du = du[var, loc]
                    logger.debug('\t new_du(%s, %s): %s', var, loc, new_du)
                    new_du.remove(i)
                    logger.debug('\t    -> %s', new_du)
                    if not new_du:
                        logger.debug('\t  REMOVING INS %d', loc)
                        du.pop((var, loc))
                        graph.remove_ins(loc)
                        change = True def split_variables(graph, lvars, DU, UD):
    variables = group_variables(lvars, DU, UD)

    if lvars:
        nb_vars = max(lvars) + 1
    else:
        nb_vars = 0
    for var, versions in variables.items():
        nversions = len(versions)
        if nversions == 1:
            continue
        orig_var = lvars.pop(var)
        for i, (defs, uses) in enumerate(versions):
            if min(defs) < 0:  # Param
                if orig_var.this:
                    new_version = ThisParam(var, orig_var.type)
                else:
                    new_version = Param(var, orig_var.type)
                lvars[var] = new_version
            else:
                new_version = Variable(nb_vars)
                new_version.type = orig_var.type
                lvars[nb_vars] = new_version  # add new version to variables
                nb_vars += 1
            new_version.name = '%d_%d' % (var, i)

            for loc in defs:
                if loc < 0:
                    continue
                ins = graph.get_ins_from_loc(loc)
                ins.replace_lhs(new_version)
                DU[(new_version.value(), loc)] = DU.pop((var, loc))
            for loc in uses:
                ins = graph.get_ins_from_loc(loc)
                ins.replace_var(var, new_version)
                UD[(new_version.value(), loc)] = UD.pop((var, loc)) def construct(start_block, vmap, exceptions):
    """
    Constructs a CFG

    :param androguard.core.analysis.analysis.DVMBasicBlock start_block: The startpoint
    :param vmap: variable mapping
    :param exceptions: list of androguard.core.analysis.analysis.ExceptionAnalysis

    :rtype: Graph
    """
    bfs_blocks = bfs(start_block)

    graph = Graph()
    gen_ret = GenInvokeRetName()

    # Construction of a mapping of basic blocks into Nodes
    block_to_node = {}

    exceptions_start_block = []
    for exception in exceptions:
        for _, _, block in exception.exceptions:
            exceptions_start_block.append(block)

    for block in bfs_blocks:
        node = make_node(graph, block, block_to_node, vmap, gen_ret)
        graph.add_node(node)

    graph.entry = block_to_node[start_block]
    del block_to_node, bfs_blocks

    graph.compute_rpo()
    graph.number_ins()

    for node in graph.rpo:
        preds = [pred for pred in graph.all_preds(node) if pred.num < node.num]
        if preds and all(pred.in_catch for pred in preds):
            node.in_catch = True

    # FIXME: We have seen samples in the wild which have multiple exit nodes!
    #        This seems to be not necessarily a obfuscation method, but rather some
    #        speciality with certain compilers!
    # Create a list of Node which are 'return' node
    # There should be one and only one node of this type
    # If this is not the case, try to continue anyway by setting the exit node
    # to the one which has the greatest RPO number (not necessarily the case)
    lexit_nodes = [node for node in graph if node.type.is_return]

    if len(lexit_nodes) > 1:
        # Not sure that this case is possible...
        logger.error('Multiple exit nodes found !')
        graph.exit = graph.rpo[-1]
    elif len(lexit_nodes) < 1:
        # A method can have no return if it has throw statement(s) or if its
        # body is a while(1) whitout break/return.
        logger.debug('No exit node found !')
    else:
        graph.exit = lexit_nodes[0]

    return graph def simplify(graph):
    """
    Simplify the CFG by merging/deleting statement nodes when possible:
    If statement B follows statement A and if B has no other predecessor
    besides A, then we can merge A and B into a new statement node.
    We also remove nodes which do nothing except redirecting the control
    flow (nodes which only contains a goto).
    """
    redo = True
    while redo:
        redo = False
        node_map = {}
        to_update = set()
        for node in graph.nodes[:]:
            if node.type.is_stmt and node in graph:
                sucs = graph.all_sucs(node)
                if len(sucs) != 1:
                    continue
                suc = sucs[0]
                if len(node.get_ins()) == 0:
                    if any(pred.type.is_switch
                           for pred in graph.all_preds(node)):
                        continue
                    if node is suc:
                        continue
                    node_map[node] = suc

                    for pred in graph.all_preds(node):
                        pred.update_attribute_with(node_map)
                        if node not in graph.sucs(pred):
                            graph.add_catch_edge(pred, suc)
                            continue
                        graph.add_edge(pred, suc)
                    redo = True
                    if node is graph.entry:
                        graph.entry = suc
                    graph.remove_node(node)
                elif (suc.type.is_stmt and len(graph.all_preds(suc)) == 1 and
                          not (suc in graph.catch_edges) and not (
                            (node is suc) or (suc is graph.entry))):
                    ins_to_merge = suc.get_ins()
                    node.add_ins(ins_to_merge)
                    for var in suc.var_to_declare:
                        node.add_variable_declaration(var)
                    new_suc = graph.sucs(suc)[0]
                    if new_suc:
                        graph.add_edge(node, new_suc)
                    for exception_suc in graph.catch_edges.get(suc, []):
                        graph.add_catch_edge(node, exception_suc)
                    redo = True
                    graph.remove_node(suc)
            else:
                to_update.add(node)
        for node in to_update:
            node.update_attribute_with(node_map) def split_if_nodes(graph):
    """
    Split IfNodes in two nodes, the first node is the header node, the
    second one is only composed of the jump condition.
    """
    node_map = {n: n for n in graph}
    to_update = set()
    for node in graph.nodes[:]:
        if node.type.is_cond:
            if len(node.get_ins()) > 1:
                pre_ins = node.get_ins()[:-1]
                last_ins = node.get_ins()[-1]
                pre_node = StatementBlock('%s-pre' % node.name, pre_ins)
                cond_node = CondBlock('%s-cond' % node.name, [last_ins])
                node_map[node] = pre_node
                node_map[pre_node] = pre_node
                node_map[cond_node] = cond_node

                pre_node.copy_from(node)
                cond_node.copy_from(node)
                for var in node.var_to_declare:
                    pre_node.add_variable_declaration(var)
                pre_node.type.is_stmt = True
                cond_node.true = node.true
                cond_node.false = node.false

                for pred in graph.all_preds(node):
                    pred_node = node_map[pred]
                    # Verify that the link is not an exception link
                    if node not in graph.sucs(pred):
                        graph.add_catch_edge(pred_node, pre_node)
                        continue
                    if pred is node:
                        pred_node = cond_node
                    if pred.type.is_cond:  # and not (pred is node):
                        if pred.true is node:
                            pred_node.true = pre_node
                        if pred.false is node:
                            pred_node.false = pre_node
                    graph.add_edge(pred_node, pre_node)
                for suc in graph.sucs(node):
                    graph.add_edge(cond_node, node_map[suc])

                # We link all the exceptions to the pre node instead of the
                # condition node, which should not trigger any of them.
                for suc in graph.catch_edges.get(node, []):
                    graph.add_catch_edge(pre_node, node_map[suc])

                if node is graph.entry:
                    graph.entry = pre_node

                graph.add_node(pre_node)
                graph.add_node(cond_node)
                graph.add_edge(pre_node, cond_node)
                pre_node.update_attribute_with(node_map)
                cond_node.update_attribute_with(node_map)
                graph.remove_node(node)
        else:
            to_update.add(node)
    for node in to_update:
        node.update_attribute_with(node_map) class Param(Variable):
    def __init__(self, value, atype):
        super().__init__(value)
        self.declared = True
        self.type = atype
        self.this = False

    def is_const(self):
        return True

    def visit(self, visitor):
        return visitor.visit_param(self.v, data=self.type)

    def __str__(self):
        return 'PARAM_%s' % self.name class ThisParam(Param):
    def __init__(self, value, atype):
        super().__init__(value, atype)
        self.this = True
        self.super = False

    def visit(self, visitor):
        if self.super:
            return visitor.visit_super()
        return visitor.visit_this()

    def __str__(self):
        return 'THIS' def read(filename, binary=True):
    """
    Open and read a file

    :param filename: filename to open and read
    :param binary: True if the file should be read as binary
    :return: bytes if binary is True, str otherwise
    """
    with open(filename, 'rb' if binary else 'r') as f:
        return f.read()
import logging
import struct
import sys
import androguard.core.androconf as androconf
import androguard.decompiler.dad.util as util
from collections import defaultdict
from androguard.core.analysis import analysis
from androguard.core.bytecodes import apk, dvm
from androguard.decompiler.dad.control_flow import identify_structures
from androguard.decompiler.dad.dast import (
    JSONWriter,
    parse_descriptor,
    literal_string,
    literal_hex_int,
    dummy
)
from androguard.decompiler.dad.dataflow import (
    build_def_use,
    place_declarations,
    dead_code_elimination,
    register_propagation,
    split_variables
)
from androguard.decompiler.dad.graph import construct, simplify, split_if_nodes
from androguard.decompiler.dad.instruction import Param, ThisParam
from androguard.decompiler.dad.writer import Writer
from androguard.util import read
            from androguard.core import bytecode
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


logger = logging.getLogger('dad')


# No seperate DvField class currently
def get_field_ast(field):
    triple = field.get_class_name()[1:-1], field.get_name(), field.get_descriptor()

    expr = None
    if field.init_value:
        val = field.init_value.value
        expr = dummy(str(val))

        if val is not None:
            if field.get_descriptor() == 'Ljava/lang/String;':
                expr = literal_string(val)
            elif field.proto == 'B':
                expr = literal_hex_int(struct.unpack('<b', struct.pack("B", val))[0])

    return {
        'triple': triple,
        'type': parse_descriptor(field.get_descriptor()),
        'flags': util.get_access_field(field.get_access_flags()),
        'expr': expr,
    }


class DvMethod:
    """
    This is a wrapper around :class:`~androguard.core.analysis.analysis.MethodAnalysis` and
    :class:`~androguard.core.bytecodes.dvm.EncodedMethod` inside the decompiler.

    :param androguard.core.analysis.analysis.MethodAnalysis methanalysis:
    """
    def __init__(self, methanalysis):
        method = methanalysis.get_method()
        self.method = method
        self.start_block = next(methanalysis.get_basic_blocks().get(), None)
        self.cls_name = method.get_class_name()
        self.name = method.get_name()
        self.lparams = []
        self.var_to_name = defaultdict()
        self.writer = None
        self.graph = None
        self.ast = None

        self.access = util.get_access_method(method.get_access_flags())

        desc = method.get_descriptor()
        self.type = desc.split(')')[-1]
        self.params_type = util.get_params_type(desc)
        self.triple = method.get_triple()

        self.exceptions = methanalysis.exceptions.exceptions

        code = method.get_code()
        if code is None:
            logger.debug('No code : %s %s', self.name, self.cls_name)
        else:
            start = code.registers_size - code.ins_size
            if 'static' not in self.access:
                self.var_to_name[start] = ThisParam(start, self.cls_name)
                self.lparams.append(start)
                start += 1
            num_param = 0
            for ptype in self.params_type:
                param = start + num_param
                self.lparams.append(param)
                self.var_to_name[param] = Param(param, ptype)
                num_param += util.get_type_size(ptype)

        if not __debug__:
            # TODO: use tempfile to create a correct tempfile (cross platform compatible)
            bytecode.method2png('/tmp/dad/graphs/{}#{}.png'.format(self.cls_name.split('/')[-1][:-1], self.name), methanalysis)

    def process(self, doAST=False):
        """
        Processes the method and decompile the code.

        There are two modes of operation:

        1) Normal Decompilation to Java Code
        2) Decompilation into an abstract syntax tree (AST)

        The Decompilation is done twice. First, a rough decompilation is created,
        which is then optimized. Second, the optimized version is used to create the final version.

        :param doAST: generate AST instead of Java Code
        """
        logger.debug('METHOD : %s', self.name)

        # Native methods... no blocks.
        if self.start_block is None:
            logger.debug('Native Method.')
            if doAST:
                self.ast = JSONWriter(None, self).get_ast()
            else:
                self.writer = Writer(None, self)
                self.writer.write_method()
            return

        # Construct the CFG
        graph = construct(self.start_block, self.var_to_name, self.exceptions)
        self.graph = graph

        if not __debug__:
            # TODO: use tempfile to create a correct tempfile (cross platform compatible)
            util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks')


        use_defs, def_uses = build_def_use(graph, self.lparams)