├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── generate_readme.py ├── modules ├── __init__.py ├── classlist_parser.py ├── demangler.py ├── node.py ├── old.py └── printer.py └── plugin.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Kevin Watson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS Tools (v0.1) 2 | Author: **Kevin Watson** 3 | 4 | _A collection of helper functions for reversing iOS Mach-O files_ 5 | 6 | ## Description: 7 | 8 | This plugin is currently a partially completed mess. Needed to make the first commit at some point. 9 | 10 | Can automatically parse class structures and rename function symbols to use their method names. 11 | Using the Objective-C runtime implementation at https://opensource.apple.com/source/objc4/objc4-709/ as a reference. 12 | 13 | Can demangle imported Swift symbols and comment their occurences in a function. 14 | Using the Swift demangler implementation at https://github.com/apple/swift/ as a reference. 15 | 16 | 17 | 18 | ## Minimum Version 19 | 20 | This plugin requires the following minimum version of Binary Ninja: 21 | 22 | * release - 1.0.776 23 | 24 | 25 | ## Required Dependencies 26 | 27 | The following dependencies are required for this plugin: 28 | 29 | * pip - enum34 30 | 31 | 32 | ## License 33 | 34 | This plugin is released under a [MIT](LICENSE) license. 35 | 36 | 37 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | import logging, os 2 | 3 | from binaryninja.plugin import PluginCommand 4 | from binaryninja.log import log_error 5 | from binaryninja.lowlevelil import LowLevelILOperation 6 | from binaryninja.enums import SymbolType 7 | 8 | from modules import classlist_parser 9 | from modules import demangler 10 | 11 | def define_classes(bv): 12 | if bv.view_type != 'Mach-O': 13 | log_error('BinaryView.view_type must be "Mach-O"') 14 | return 15 | 16 | supported_platforms = ['mac-armv7'] 17 | if bv.platform.name not in supported_platforms: 18 | log_error("{} platform is not supported. Supported platforms are {}".format(bv.platform.name, supported_platforms)) 19 | return 20 | 21 | if not bv.get_section_by_name("__objc_classlist"): 22 | log_error("Could not find an __objc_classlist section") 23 | return 24 | 25 | classlist_parser.define_types(bv) 26 | classlist_parser.define_objc_classlist(bv) 27 | 28 | def demangleImportsInFunction(bv, f): 29 | LOG_FILE='/Users/Kevin/debug-log.txt' 30 | os.remove(LOG_FILE) 31 | logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG) 32 | logging.debug('Calling demangleSymbolAsNode()...') 33 | skipped = [] 34 | successful = [] 35 | for block in f.low_level_il: 36 | #for block in bv.get_function_at(here).low_level_il: 37 | for instruction in block: 38 | if not instruction.prefix_operands[0].operation == LowLevelILOperation.LLIL_CALL: 39 | continue 40 | if not instruction.prefix_operands[1].operation == LowLevelILOperation.LLIL_CONST_PTR: 41 | print('WARNING: unfamiliar call operand in {}'.format(instruction)) 42 | continue 43 | if not isinstance(instruction.prefix_operands[2], (int, long)): 44 | print('WARNING: unfamiliar call operand in {}'.format(instruction)) 45 | continue 46 | symbol = bv.get_symbol_at(instruction.prefix_operands[2]) 47 | if symbol and symbol.type == SymbolType.ImportedFunctionSymbol: 48 | #print(symbol.name) 49 | #demangler.demangleImport(bv, instruction.prefix_operands[2]) 50 | #demangler.demangleImport(bv, symbol.name) 51 | name = symbol.name 52 | if name[:2] == '__': 53 | name = name[1:] 54 | try: 55 | result = demangler.demangleSymbolAsNode(bv, name) 56 | if not result: 57 | skipped.append(symbol.name) 58 | print('SKIPPING: {}'.format(symbol.name)) 59 | continue 60 | successful.append(symbol.name) 61 | print(result) 62 | #print(demangler.getNodeTreeAsString(result)) 63 | except Exception as e: 64 | logging.exception(e) 65 | 66 | print(len(skipped)) 67 | print(skipped) 68 | print(len(successful)) 69 | print(successful) 70 | 71 | PluginCommand.register("Define Objective-C classes", "Parses the objc_classlist section to define Objective C and Swift classes", define_classes) 72 | PluginCommand.register_for_address("Demangle Swift symbol", "Demangles the Swift symbol name at the given address", demangler.demangleAddress) 73 | PluginCommand.register_for_function("Demangle imported Swift symbols", "Demangles the imported Swift symbol names in the given function", demangleImportsInFunction) 74 | -------------------------------------------------------------------------------- /generate_readme.py: -------------------------------------------------------------------------------- 1 | ''' Python script to generate a stub README.md files from a plugin.json file ''' 2 | import json 3 | import argparse 4 | import os 5 | import sys 6 | 7 | parser = argparse.ArgumentParser(description = 'Generate README.md (and optional LICENSE) from plugin.json metadata') 8 | parser.add_argument('filename', type = argparse.FileType('r'), help = 'path to the plugin.json file') 9 | parser.add_argument("-f", "--force", help = 'will automatically overwrite existing files', action='store_true') 10 | 11 | args = parser.parse_args() 12 | 13 | plugin = json.load(args.filename)['plugin'] 14 | 15 | outputfile = os.path.join(os.path.dirname(args.filename.name), 'README.md') 16 | licensefile = os.path.join(os.path.dirname(args.filename.name), 'LICENSE') 17 | 18 | if not args.force and (os.path.isfile(outputfile) or os.path.isfile(licensefile)): 19 | print("Cowardly refusing to overwrite an existing license or readme.") 20 | sys.exit(0) 21 | 22 | if 'license' in plugin and 'name' in plugin['license'] and 'text' in plugin['license']: 23 | name = plugin['license']['name'] 24 | text = plugin['license']['text'] 25 | license = '''## License 26 | 27 | This plugin is released under a [{name}](LICENSE) license. 28 | 29 | '''.format(name=plugin['license']['name']) 30 | print("Creating {licensefile}".format(licensefile=licensefile)) 31 | open(licensefile,'w').write(plugin['license']['text']) 32 | 33 | elif ('license' in plugin and 'name' in plugin['license']): 34 | name = plugin['license']['name'] 35 | license = '''## License 36 | 37 | This plugin is released under a {name}] license. 38 | 39 | '''.format(name=plugin['license']['name']) 40 | else: 41 | license = '' 42 | 43 | if 'minimumBinaryNinjaVersion' in plugin: 44 | minimum = '## Minimum Version\n\nThis plugin requires the following minimum version of Binary Ninja:\n\n' 45 | for chan in plugin['minimumBinaryNinjaVersion']: 46 | version = plugin['minimumBinaryNinjaVersion'][chan] 47 | minimum += " * {chan} - {version}\n".format(chan = chan, version = version) 48 | minimum += '\n' 49 | else: 50 | minimum = '' 51 | 52 | if 'dependencies' in plugin: 53 | dependencies = '## Required Dependencies\n\nThe following dependencies are required for this plugin:\n\n' 54 | for dependency in plugin['dependencies']: 55 | dependencylist = ', '.join(plugin['dependencies'][dependency]) 56 | dependencies += " * {dependency} - {dependencylist}\n".format(dependency = dependency, dependencylist = dependencylist) 57 | dependencies += '\n' 58 | else: 59 | dependencies = '' 60 | 61 | template = '''# {PluginName} (v{version}) 62 | Author: **{author}** 63 | 64 | _{description}_ 65 | 66 | ## Description: 67 | 68 | {longdescription} 69 | 70 | {minimum} 71 | {dependencies} 72 | {license} 73 | '''.format(PluginName = plugin['name'], version = plugin['version'], 74 | author = plugin['author'], description = plugin['description'], 75 | longdescription = plugin['longdescription'], license = license, 76 | dependencies = dependencies, minimum = minimum) 77 | 78 | print("Writing {outputfile}".format(outputfile=outputfile)) 79 | open(outputfile, 'w').write(template) 80 | -------------------------------------------------------------------------------- /modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/watsonkp/binaryninja-ios-tools/ee4082fb2cdcf972051bfd94beccb7144e6e6211/modules/__init__.py -------------------------------------------------------------------------------- /modules/classlist_parser.py: -------------------------------------------------------------------------------- 1 | from binaryninja import * 2 | 3 | from demangler import demangleString 4 | 5 | def define_types(bv): 6 | t, name = bv.parse_type_string("struct {void *isa; void *superclass; void *cache; void *vtable; void *data;} objc_class") 7 | bv.define_user_type(name, t) 8 | 9 | t, name = bv.parse_type_string("struct { uint32_t flags; uint32_t instanceStart; uint32_t instanceSize; const uint8_t * ivarLayout; const char * name; void * baseMethodList; void * baseProtocols; void * ivars; const uint8_t * weakIvarLayout; void *baseProperties; } class_ro_t") 10 | bv.define_user_type(name, t) 11 | 12 | t, name = bv.parse_type_string("struct {char *name; const char *types; void *imp;} method_t") 13 | bv.define_user_type(name, t) 14 | t, name = bv.parse_type_string("struct {uint32_t entsizeAndFlags; uint32_t count; method_t first;} method_list_t") 15 | bv.define_user_type(name, t) 16 | 17 | def define_objc_class_ptr(bv, br, addr): 18 | objc_class_ptr, _ = bv.parse_type_string("objc_class *foo") 19 | bv.define_user_data_var(addr, objc_class_ptr) 20 | ptr = br.read32() 21 | offset = br.offset 22 | define_objc_class(bv, br, ptr) 23 | br.seek(offset) 24 | 25 | def define_objc_class(bv, br, objc_class_ptr): 26 | objc_class = bv.get_type_by_name("objc_class") 27 | for member in objc_class.structure.members: 28 | if member.name == "data": 29 | data_offset = member.offset 30 | break 31 | 32 | bv.define_user_data_var(objc_class_ptr, objc_class) 33 | 34 | br.seek(objc_class_ptr + data_offset) 35 | objc_class_data = br.read32() 36 | if objc_class_data & 0x1: 37 | class_ro_t_ptr = objc_class_data & ~0x1 38 | else: 39 | class_ro_t_ptr = objc_class_data 40 | 41 | define_class_ro_t(bv, br, class_ro_t_ptr) 42 | 43 | def define_class_ro_t(bv, br, class_ro_t_ptr): 44 | class_ro_t = bv.get_type_by_name("class_ro_t") 45 | bv.define_user_data_var(class_ro_t_ptr, class_ro_t) 46 | 47 | for member in class_ro_t.structure.members: 48 | if member.name == "baseMethodList": 49 | method_list_offset = member.offset 50 | continue 51 | if member.name == "name": 52 | name_offset = member.offset 53 | 54 | br.seek(class_ro_t_ptr + name_offset) 55 | name_ptr = br.read32() 56 | name = get_string_data_at(bv, br, name_ptr) 57 | demangled = demangleString(name) 58 | if demangled: 59 | name = demangled 60 | bv.define_user_symbol(types.Symbol(enums.SymbolType.DataSymbol, class_ro_t_ptr, name)) 61 | 62 | br.seek(class_ro_t_ptr + method_list_offset) 63 | base_method_list = br.read32() 64 | if base_method_list == 0: 65 | return 66 | define_method_list_t(bv, br, name, base_method_list) 67 | 68 | def define_method_list_t(bv, br, class_name, method_list_t_ptr): 69 | method_list_t = bv.get_type_by_name("method_list_t") 70 | bv.define_user_data_var(method_list_t_ptr, method_list_t) 71 | 72 | for member in method_list_t.structure.members: 73 | if member.name == "first": 74 | first_offset = member.offset 75 | continue 76 | if member.name == "count": 77 | count_offset = member.offset 78 | continue 79 | 80 | first = method_list_t_ptr + first_offset 81 | br.seek(method_list_t_ptr + count_offset) 82 | count = br.read32() 83 | method_t_size = bv.get_type_by_name("method_t").structure.width 84 | define_method_t(bv, br, class_name, first, first=True) 85 | for i in range(1, count): 86 | define_method_t(bv, br, class_name, first + i * method_t_size) 87 | 88 | def define_method_t(bv, br, class_name, method_t_ptr, first=False): 89 | method_t = bv.get_type_by_name("method_t") 90 | if not first: 91 | bv.define_user_data_var(method_t_ptr, method_t) 92 | 93 | for member in method_t.structure.members: 94 | if member.name == "name": 95 | name_offset = member.offset 96 | continue 97 | if member.name == "imp": 98 | imp_offset = member.offset 99 | continue 100 | br.seek(method_t_ptr + name_offset) 101 | name_ptr = br.read32() 102 | name = get_string_data_at(bv, br, name_ptr) 103 | br.seek(method_t_ptr + imp_offset) 104 | imp_ptr = br.read32() 105 | bv.get_function_at(imp_ptr).name = class_name + "." + name 106 | 107 | def define_objc_classlist(bv): 108 | br = BinaryReader(bv) 109 | objc_classlist = bv.get_section_by_name("__objc_classlist") 110 | br.seek(objc_classlist.start) 111 | for addr in range(objc_classlist.start, objc_classlist.start + objc_classlist.length, 4): 112 | define_objc_class_ptr(bv, br, addr) 113 | 114 | def get_string_data_at(bv, br, addr): 115 | s = bv.get_strings(addr, 1)[0] 116 | br.seek(s.start) 117 | s_data = br.read(s.length) 118 | return s_data 119 | -------------------------------------------------------------------------------- /modules/demangler.py: -------------------------------------------------------------------------------- 1 | import string 2 | from enum import Enum 3 | from binaryninja import types 4 | 5 | from node import Node, Kind 6 | from old import demangleOldSymbolAsNode 7 | 8 | # Using the enum34 package on the recommendation of https://stackoverflow.com/a/1695250/689100 9 | # In the Binary Ninja console 10 | # from setuptools.command import easy_install 11 | # easy_install.main(["-U", "enum34"]) 12 | # Needed to grant user write permissions on C:\Program Files\Vector35\BinaryNinja\plugins\Lib\site-packages 13 | 14 | 15 | Type_Printing = Enum('Type_Printing', 'NO_TYPE') 16 | 17 | def getManglingPrefixLength(mangled_name): 18 | if mangled_name[:3] == '_T0': 19 | return 3 20 | offset = 1 if mangled_name[0] == '_' else 0 21 | if mangled_name[offset:offset+2] == '$S': 22 | return offset + 2 23 | return 0 24 | 25 | def isMangledName(mangled_name): 26 | return getManglingPrefixLength(mangled_name) != 0 27 | 28 | def isSwiftSymbol(mangled_name): 29 | if mangled_name[:2] == '_T': 30 | return True 31 | return getManglingPrefixLength(mangled_name) != 0 32 | 33 | 34 | def demangleSymbolAsNode(bv, s): 35 | # TODO: hook into the existing stuff and test 36 | if isMangledName(s): 37 | mangled = Mangled(s) 38 | mangled.demangleSymbol() 39 | return 40 | return demangleOldSymbolAsNode(s) 41 | 42 | def getNodeTreeAsString(tree): 43 | printNode(tree) 44 | 45 | 46 | # TODO: use this as Node.__str__, maybe? 47 | def printNode(node, as_prefix_context=False): 48 | if node.kind == Kind.GLOBAL: 49 | return printChildren(node) 50 | elif node.kind == Kind.TYPE_MANGLING: 51 | return printNode(node.children[0]) 52 | elif node.kind == Kind.TYPE: 53 | return printNode(node.children[0]) 54 | elif node.kind == Kind.CLASS: 55 | return printEntity(node, as_prefix_context, Type_Printing.NO_TYPE, True) 56 | elif node.kind == Kind.MODULE: 57 | return node.text 58 | elif node.kind == Kind.IDENTIFIER: 59 | return node.text 60 | else: 61 | print("Unrecognized kind: {}".format(node.kind)) 62 | return None 63 | 64 | def printChildren(node): 65 | s = "" 66 | for child in node.children: 67 | s += printNode(child) 68 | return s 69 | 70 | def printEntity(entity, as_prefix_context, type_printing, has_name, extra_name="", extra_index=-1): 71 | s = "" 72 | context = entity.children[0] 73 | s += printNode(context, True) 74 | s += "." 75 | if has_name: 76 | s += printNode(entity.children[1]) 77 | return s 78 | 79 | class NodeStack(): 80 | def __init__(self): 81 | self.stack = [] 82 | 83 | def popNode(self): 84 | if len(self.stack) == 0: 85 | return Node() 86 | node = self.stack.pop() 87 | return node 88 | 89 | def pushNode(self, node): 90 | self.stack.append(node) 91 | 92 | class Mangled(): 93 | def __init__(self, mangled_name): 94 | self.name = mangled_name 95 | self.position = 0 96 | self.tree = None 97 | self.stack = NodeStack() 98 | 99 | def demangleSymbol(self): 100 | if self.name[:3] == "_Tt": 101 | self.position = 3 102 | # TODO: return the node, don't use a member 103 | print(self.demangleObjCTypeName()) 104 | return 105 | print("Don't know how to demangle {}".format(self.name)) 106 | 107 | def demangleObjCTypeName(self): 108 | t = Node(Kind.TYPE) 109 | self.tree = Node(Kind.GLOBAL).addChild(Node(Kind.TYPE_MANGLING).addChild(t)) 110 | if self.name[self.position] == 'C': 111 | self.position += 1 112 | nominal = Node(Kind.CLASS) 113 | t.addChild(nominal) 114 | elif self.name[self.position] == 'P': 115 | self.position += 1 116 | print('Is a protocol') 117 | else: 118 | return None 119 | 120 | if self.name[self.position] == 's': 121 | nominal.addChild(Node(Kind.MODULE, 'Swift')) 122 | else: 123 | module = self.demangleIdentifier() 124 | if not module: 125 | return None 126 | module.kind = Kind.MODULE 127 | nominal.addChild(module) 128 | 129 | identifier = self.demangleIdentifier() 130 | if not identifier: 131 | return None 132 | nominal.addChild(identifier) 133 | 134 | return self.tree 135 | 136 | def demangleIdentifier(self): 137 | has_word_substrings = False 138 | is_punycoded = False 139 | if self.name[self.position] not in string.digits: 140 | return None 141 | if self.name[self.position] == '0': 142 | self.position += 1 143 | if self.name[self.position] == '0': 144 | self.position += 1 145 | is_punycoded = True 146 | else: 147 | has_word_substrings = True 148 | 149 | while has_word_substrings: 150 | print("ERROR: It has word substrings, which haven't been implemented") 151 | return None 152 | 153 | num_chars = self.demangleNatural() 154 | if num_chars <= 0: 155 | return None 156 | if is_punycoded: 157 | print("ERROR: {} is punycoded, which hasn't been implemented".format(self.name)) 158 | return None 159 | if self.position + num_chars > len(self.name): 160 | return None 161 | if is_punycoded: 162 | print("ERROR: {} is punycoded, which hasn't been implemented".format(self.name)) 163 | return None 164 | else: 165 | identifier = self.name[self.position:self.position + num_chars] 166 | self.position += num_chars 167 | 168 | if len(identifier) == 0: 169 | return None 170 | 171 | identifier_node = Node(Kind.IDENTIFIER, text=identifier) 172 | 173 | return identifier_node 174 | 175 | def demangleNatural(self): 176 | length = 0 177 | for c in self.name[self.position:]: 178 | if c not in string.digits: 179 | break 180 | length += 1 181 | num_chars = int(self.name[self.position:self.position + length]) 182 | self.position += length 183 | return num_chars 184 | 185 | def demangleAddress(bv, address): 186 | symbol = bv.get_symbol_at(address) 187 | if not symbol: 188 | print('No symbol found at 0x{:x}'.format(address)) 189 | return 190 | demangled = demangleString(symbol.name) 191 | if not demangled: 192 | return 193 | # If multiple symbols for the same address are defined, only the most recent symbol will ever be used. 194 | # per https://api.binary.ninja/binaryninja.binaryview-module.html 195 | bv.define_user_symbol(types.Symbol(symbol.type, symbol.address, demangled)) 196 | 197 | def demangleString(s): 198 | if s[:2] == '__': 199 | s = s[1:] 200 | if not isSwiftSymbol(s): 201 | print('{} is not a Swift symbol'.format(s)) 202 | return None 203 | mangled = Mangled(s) 204 | mangled.demangleSymbol() 205 | demangled = printNode(mangled.tree) 206 | if not demangled: 207 | print('Failed to demangle {}'.format(s)) 208 | return None 209 | return demangled 210 | 211 | def demangleImport(bv, s): 212 | if s[:2] == '__': 213 | s = s[1:] 214 | if not isSwiftSymbol(s): 215 | print('{} is not a Swift symbol'.format(s)) 216 | return None 217 | mangled = Mangled(s) 218 | #mangled.demangleSymbol() 219 | mangled.demangleType() 220 | -------------------------------------------------------------------------------- /modules/node.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | Kind = Enum('Kind', 'ALLOCATOR ARGUMENT_TUPLE ASSOCIATED_TYPE_METADATA_ACCESSOR ASSOCIATED_TYPE_WITNESS_TABLE_ACCESSOR BOUND_GENERIC_CLASS BOUND_GENERIC_ENUM BOUND_GENERIC_STRUCTURE CLASS CONSTRUCTOR DEALLOCATOR DEFAULT_ARGUMENT_INITIALIZER DEPENDENT_ASSOCIATED_TYPE_REF DEPENDENT_GENERIC_CONFORMANCE_REQUIREMENT DEPENDENT_GENERIC_LAYOUT_REQUIREMENT DEPENDENT_GENERIC_PARAM_COUNT DEPENDENT_GENERIC_PARAM_TYPE DEPENDENT_GENERIC_SAME_TYPE_REQUIREMENT DEPENDENT_GENERIC_TYPE DEPENDENT_GENERIC_SIGNATURE DEPENDENT_MEMBER_TYPE DEPENDENT_PSEUDOGENERIC_SIGNATURE DESCTRUCTOR DID_SET DIRECT_METHOD_REFERENCE_ATTRIBUTE DYNAMIC_ATTRIBUTE ENUM EXPLICIT_CLOSURE EXTENSION FIELD_OFFSET FULL_TYPE_METADATA FUNCTION FUNCTION_SIGNATURE_SPECIALIZATION FUNCTION_SIGNATURE_SPECIALIZATION_PARAM FUNCTION_SIGNATURE_SPECIALIZATION_PARAM_KIND FUNCTION_TYPE GENERIC_PROTOCOL_WITNESS_TABLE GENERIC_PROTOCOL_WITNESS_TABLE_INSTANTIATION_FUNCTION GENERIC_TYPE_METADATA_PATTERN GENERIC_SPECIALIZATION GENERIC_SPECIALIZATION_NOT_RE_ABSTRACTED GENERIC_SPECIALIZATION_PARAM GETTER GLOBAL GLOBAL_GETTER IDENTIFIER IMPLICIT_CLOSURE IN_OUT INDEX INITIALIZER IVAR_DESTROYER IVAR_INITIALIZER LAZY_PROTOCOL_WITNESS_TABLE_ACCESSOR LOCAL_DECL_NAME MATERIALIZE_FOR_SET METACLASS MODULE NATIVE_OWNING_MUTABLE_ADDRESSOR NATIVE_PINNING_MUTABLE_ADDRESSOR NOMINAL_TYPE_DESCRIPTOR NON_OBJC_ATTRIBUTE NUMBER OBJC_ATTRIBUTE OWNING_MUTABLE_ADDRESSSOR PRIVATE_DECL_NAME PROTOCOL PROTOCOL_CONFORMANCE PROTOCOL_DESCRIPTOR PROTOCOL_LIST PROTOCOL_WITNESS PROTOCOL_WITNESS_TABLE PROTOCOL_WITNESS_TABLE_ACCESSOR SETTER SPECIALIZATION_IS_FRAGILE SPECIALIZATION_PASS_ID STATIC STRUCTURE SUBSCRIPT REABSTRACTION_THUNK REABSTRACTION_THUNK_HELPER RETURN_TYPE SUFFIX THROWS_ANNOTATION TUPLE TUPLE_ELEMENT TUPLE_ELEMENT_NAME TYPE TYPE_LIST TYPE_MANGLING TYPE_METADATA TYPE_METADATA_ACCESS_FUNCTION TYPE_METADATA_LAZY_CACHE UNCURRIED_FUNCTION_TYPE UNSAFE_MUTABLE_ADDRESSOR VALUE_WITNESS_TABLE VARIABLE VARIADIC_MARKER VTABLE_ATTRIBUTE WILL_SET') 4 | 5 | class Node(): 6 | def __init__(self, kind, text="", index=-1): 7 | self.kind = kind 8 | self.children = [] 9 | self.text = text 10 | if index >= 0: 11 | self.index = index 12 | 13 | def __repr__(self): 14 | return self.__str__() 15 | 16 | def __str__(self): 17 | if self.text != "": 18 | if len(self.children) == 0: 19 | return "{{{}({})}}".format(self.kind, self.text, self.children) 20 | return "{{{}({}) children: {}}}".format(self.kind, self.text, self.children) 21 | return "{{{} children: {}}}".format(self.kind, self.children) 22 | 23 | def getNumChildren(self): 24 | return len(self.children) 25 | 26 | def getChild(self, n): 27 | return self.children[n] 28 | 29 | def addChild(self, child): 30 | self.children.append(child) 31 | return self 32 | 33 | def reverseChildren(self, starting_at=0): 34 | self.children = self.children[:starting_at] + self.children[starting_at:][::-1] 35 | -------------------------------------------------------------------------------- /modules/old.py: -------------------------------------------------------------------------------- 1 | import string 2 | from enum import Enum 3 | 4 | from node import Node, Kind 5 | 6 | from printer import archetypeName 7 | 8 | MANGLING_MODULE_OBJC = '__ObjC' 9 | MANGLING_MODULE_C = '__C' 10 | STDLIB_NAME = 'Swift' 11 | 12 | IsVariadic = Enum('IsVariadic', 'YES NO') 13 | 14 | # typedef uint64_t IndexType 15 | 16 | class FunctionSigSpecializationParamKind(): 17 | CONSTANT_PROP_FUNCTION = 0 18 | CONSTANT_PROP_GLOBAL = 1 19 | CONSTANT_PROP_INTEGER = 2 20 | CONSTANT_PROP_FLOAT = 3 21 | CONSTANT_PROP_STRING = 4 22 | CLOSURE_PROP = 5 23 | BOX_TO_VALUE = 6 24 | BOX_TO_STACK = 7 25 | DEAD = 1 << 6 26 | OWNED_TO_GUARANTEED = 1 << 7 27 | SROA = 1 << 8 28 | 29 | class NameSource(): 30 | def __init__(self, text): 31 | self.text = text 32 | 33 | def hasAtLeast(self, n): 34 | return n <= len(self.text) 35 | 36 | def isEmpty(self): 37 | return len(self.text) == 0 38 | 39 | def __bool__(self): 40 | return not self.isEmpty() 41 | 42 | def peek(self): 43 | return self.text[0] 44 | 45 | def next(self): 46 | c = self.peek() 47 | self.advanceOffset(1) 48 | return c 49 | 50 | def nextIf(self, s): 51 | if len(self.text) < len(s) or self.text[:len(s)] != s: 52 | return False 53 | self.advanceOffset(len(s)) 54 | return True 55 | 56 | def slice(self, n): 57 | return self.text[:n] 58 | 59 | def advanceOffset(self, len): 60 | self.text = self.text[len:] 61 | 62 | def getString(self): 63 | result = self.text 64 | self.advanceOffset(len(result)) 65 | return result 66 | 67 | class OldDemangler(): 68 | def __init__(self, mangled_name): 69 | self.substitutions = [] 70 | self.mangled = NameSource(mangled_name) 71 | 72 | def demangleTopLevel(self): 73 | print('demangleTopLevel({})'.format(self.mangled.text)) 74 | if not self.mangled.nextIf('_T'): 75 | return None 76 | 77 | top_level = Node(Kind.GLOBAL) 78 | 79 | # Specialization prefixes 80 | if self.mangled.nextIf('TS'): 81 | node = self.demangleSpecializedAttribute() 82 | if not node: 83 | return None 84 | top_level.addChild(node) 85 | self.substitutions = [] 86 | 87 | while self.mangled.nextIf('_TTS'): 88 | node = self.demangleSpecializedAttribute() 89 | if not node: 90 | return None 91 | top_level.addChild(node) 92 | self.substitutions = [] 93 | 94 | if not self.mangled.nextIf('_T'): 95 | return None 96 | elif self.mangled.nextIf('To'): 97 | top_level.addChild(Node(Kind.OBJC_ATTRIBUTE)) 98 | elif self.mangled.nextIf('TO'): 99 | top_level.addChild(Node(Kind.NON_OBJC_ATTRIBUTE)) 100 | elif self.mangled.nextIf('TD'): 101 | top_level.addChild(Node(Kind.DYNAMIC_ATTRIBUTE)) 102 | elif self.mangled.nextIf('Td'): 103 | top_level.addChild(Node(Kind.DIRECT_METHOD_REFERENCE_ATTRIBUTE)) 104 | elif self.mangled.nextIf('TV'): 105 | top_level.addChild(Node(Kind.VTABLE_ATTRIBUTE)) 106 | 107 | node = self.demangleGlobal() 108 | if not node: 109 | return None 110 | top_level.addChild(node) 111 | 112 | if not self.mangled.isEmpty(): 113 | top_level.addChild(Node(Kind.SUFFIX, text=self.mangled.getString())) 114 | 115 | return top_level 116 | 117 | def demangleNatural(self, num): 118 | print('demangleNatural({})'.format(self.mangled.text)) 119 | if not self.mangled: 120 | return False, num 121 | 122 | if not self.mangled.peek() in string.digits: 123 | return False, num 124 | s = "" 125 | while True: 126 | if not self.mangled: 127 | return True, int(s) 128 | c = self.mangled.peek() 129 | if not c in string.digits: 130 | return True, int(s) 131 | else: 132 | s += self.mangled.next() 133 | 134 | def demangleGlobal(self): 135 | print('demangleGlobal({})'.format(self.mangled.text)) 136 | if not self.mangled: 137 | return None 138 | 139 | # Type metadata 140 | if self.mangled.nextIf('M'): 141 | if self.mangled.nextIf('P'): 142 | pattern = Node(Kind.GENERIC_TYPE_METADATA_PATTERN) 143 | node = self.demangleType() 144 | if not node: 145 | return None 146 | pattern.addChild(node) 147 | return pattern 148 | if self.mangled.nextIf('a'): 149 | accessor = Node(Kind.TYPE_METADATA_ACCESS_FUNCTION) 150 | node = self.demangleType() 151 | if not node: 152 | return None 153 | accessor.addChild(node) 154 | return accessor 155 | if self.mangled.nextIf('L'): 156 | cache = Node(Kind.TYPE_METADATA_LAZY_CACHE) 157 | node = self.demangleType() 158 | if not node: 159 | return None 160 | cache.addChild(node) 161 | return cache 162 | if self.mangled.nextIf('m'): 163 | metaclass = Node(Kind.METACLASS) 164 | node = self.demangleType() 165 | if not node: 166 | return None 167 | metaclass.addChild(node) 168 | return metaclass 169 | if self.mangled.nextIf('n'): 170 | nominal_type = Node(Kind.NOMINAL_TYPE_DESCRIPTOR) 171 | node = self.demangleType() 172 | if not node: 173 | return None 174 | nominal_type.addChild(node) 175 | return nominal_type 176 | if self.mangled.nextIf('f'): 177 | metadata = Node(Kind.FULL_TYPE_METADATA) 178 | node = self.demangleType() 179 | if not node: 180 | return None 181 | metadata.addChild(node) 182 | return metadata 183 | if self.mangled.nextIf('p'): 184 | metadata = Node(Kind.PROTOCOL_DESCRIPTOR) 185 | node = self.demangleType() 186 | if not node: 187 | return None 188 | metadata.addChild(node) 189 | return metadata 190 | metadata = Node(Kind.TYPE_METADATA) 191 | node = self.demangleType() 192 | if not node: 193 | return None 194 | metadata.addChild(node) 195 | return metadata 196 | 197 | # Partial application thunks 198 | if self.mangled.nextIf('PA'): 199 | print('TODO: implement partial application thunks') 200 | return None 201 | 202 | # Top-level types 203 | if self.mangled.nextIf('t'): 204 | print('TODO: implement top level types for consumers') 205 | return None 206 | 207 | # Value witnesses 208 | if self.mangled.nextIf('w'): 209 | print('TODO: implement value witnesses') 210 | return None 211 | 212 | # Offsets, value witness tables, and protocol witnesses 213 | if self.mangled.nextIf('W'): 214 | if self.mangled.nextIf('V'): 215 | witness_table = Node(Kind.VALUE_WITNESS_TABLE) 216 | node = self.demangleType() 217 | if not node: 218 | return None 219 | witness_table.addChild(node) 220 | return witness_table 221 | if self.mangled.nextIf('v'): 222 | field_offset = Node(Kind.FIELD_OFFSET) 223 | kind = self.demangleDirectness() 224 | if not kind: 225 | return None 226 | field_offset.addChild(Node(kind)) 227 | print('WARNING: weird parsing is happending with a demangleDirectness() call') 228 | # TODO: seems to take the Directness enum as an index, which is weird 229 | #field_offset.addChild(Node(kind, index=kind)) 230 | node = self.demangleEntity() 231 | if not node: 232 | return None 233 | field_offset.addChild(node) 234 | return field_offset 235 | if self.mangled.nextIf('P'): 236 | witness_table = Node(Kind.PROTOCOL_WITNESS_TABLE) 237 | node = self.demangleProtocolConformance() 238 | if not node: 239 | return None 240 | witness_table.addChild(node) 241 | return witness_table 242 | if self.mangled.nextIf('G'): 243 | witness_table = Node(Kind.GENERIC_PROTOCOL_WITNESS_TABLE) 244 | node = self.demangleProtocolConformance() 245 | if not node: 246 | return None 247 | witness_table.addChild(node) 248 | return witness_table 249 | if self.mangled.nextIf('I'): 250 | witness_table = Node(Kind.GENERIC_PROTOCOL_WITNESS_TABLE_INSTANTIATION_FUNCTION) 251 | node = self.demangleProtocolConformance() 252 | if not node: 253 | return None 254 | witness_table.addChild(node) 255 | return witness_table 256 | if self.mangled.nextIf('l'): 257 | accessor = Node(Kind.LAZY_PROTOCOL_WITNESS_TABLE_ACCESSOR) 258 | node = self.demangleType() 259 | if not node: 260 | return None 261 | accessor.addChild(node) 262 | node = self.demangleProtocolConformance() 263 | if not node: 264 | return None 265 | accessor.addChild(node) 266 | return accessor 267 | if self.mangled.nextIf('L'): 268 | accessor = Node(Kind.LAZY_PROTOCOL_WITNESS_TABLE_CACHE_VARIABLE) 269 | node = self.demangleType() 270 | if not node: 271 | return None 272 | accessor.addChild(node) 273 | node = self.demangleProtocolConformance() 274 | if not node: 275 | return None 276 | accessor.addChild(node) 277 | return accessor 278 | if self.mangled.nextIf('a'): 279 | table_template = Node(Kind.PROTOCOL_WITNESS_TABLE_ACCESSOR) 280 | node = self.demangleProtocolConformance() 281 | if not node: 282 | return None 283 | table_template.addChild(node) 284 | return table_template 285 | if self.mangled.nextIf('t'): 286 | accessor = Node(Kind.ASSOCIATED_TYPE_METADATA_ACCESSOR) 287 | node = self.demangleProtocolConformance() 288 | if not node: 289 | return None 290 | accessor.addChild(node) 291 | node = self.demangleDeclName() 292 | if not node: 293 | return None 294 | accessor.addChild(node) 295 | return accessor 296 | if self.mangled.nextIf('T'): 297 | accessor = Node(Kind.ASSOCIATED_TYPE_WITNESS_TABLE_ACCESSOR) 298 | node = self.demangleProtocolConformance() 299 | if not node: 300 | return None 301 | accessor.addChild(node) 302 | node = self.demangleDeclName() 303 | if not node: 304 | return None 305 | accessor.addChild(node) 306 | node = self.demangleProtocolName() 307 | if not node: 308 | return None 309 | accessor.addChild(node) 310 | return accessor 311 | return None 312 | 313 | # Other thunks 314 | if self.mangled.nextIf('T'): 315 | if self.mangled.nextIf('R'): 316 | thunk = Node(Kind.REABSTRACTION_THUNK_HELPER) 317 | success, thunk = self.demangleReabstractSignature(thunk) 318 | if not success: 319 | return None 320 | return thunk 321 | if self.mangled.nextIf('r'): 322 | thunk = Node(Kind.REABSTRACTION_THUNK) 323 | success, thunk = self.demangleReabstractSignature(thunk) 324 | if not success: 325 | return None 326 | return thunk 327 | if self.mangled.nextIf('W'): 328 | thunk = Node(Kind.PROTOCOL_WITNESS) 329 | node = self.demangleProtocolConformance() 330 | if not node: 331 | return None 332 | thunk.addChild(node) 333 | node = self.demangleEntity() 334 | if not node: 335 | return None 336 | thunk.addChild(node) 337 | return thunk 338 | return None 339 | 340 | return self.demangleEntity() 341 | 342 | def demangleGenericSpecialization(self, specialization): 343 | print('demangleGenericSpecialization({})'.format(self.mangled.text)) 344 | while not self.mangled.nextIf('_'): 345 | param = Node(Kind.GENERIC_SPECIALIZATION_PARAM) 346 | node = self.demangleType() 347 | if not node: 348 | return None 349 | param.addChild(node) 350 | 351 | while not self.mangled.nextIf('_'): 352 | node = self.demangleProtocolConformance() 353 | if not node: 354 | return None 355 | param.addChild(node) 356 | specialization.addChild(param) 357 | 358 | return specialization 359 | 360 | def demangleFunctionSignatureSpecialization(self, specialization): 361 | print('demangleFunctionSignatureSpecialization({})'.format(self.mangled.text)) 362 | param_count = 0 363 | while not self.mangled.nextIf('_'): 364 | param = Node(Kind.FUNCTION_SIGNATURE_SPECIALIZATION_PARAM, index=param_count) 365 | if self.mangled.nextIf('n_'): 366 | pass 367 | elif self.mangled.nextIf('cp'): 368 | if not self.demangleFuncSigSpecializationConstantProp(param): 369 | return None 370 | elif self.mangled.nextIf('cl'): 371 | if not self.demangleFuncSigSpecializationClosureProp(param): 372 | return None 373 | elif self.mangled.nextIf('i_'): 374 | result = Node(Kind.FUNCTION_SIGNATURE_SPECIALIZATION_PARAM_KIND, index=FunctionSigSpecializationParamKind.BOX_TO_VALUE) 375 | if not result: 376 | return None 377 | param.addChild(result) 378 | elif self.mangled.nextIf('k_'): 379 | result = Node(Kind.FUNCTION_SIGNATURE_SPECIALIZATION_PARAM_KIND, index=FunctionSigSpecializationParamKind.BOX_TO_STACK) 380 | if not result: 381 | return None 382 | param.addChild(result) 383 | else: 384 | value = 0 385 | if self.mangled.nextIf('d'): 386 | value = value | FunctionSigSpecializationParamKind.DEAD 387 | if self.mangled.nextIf('g'): 388 | value = value | FunctionSigSpecializationParamKind.OWNED_TO_GUARANTEED 389 | if self.mangled.nextIf('s'): 390 | value = value | FunctionSigSpecializationParamKind.SROA 391 | if not self.mangled.nextIf('_'): 392 | return None 393 | if not value: 394 | return None 395 | 396 | result = Node(Kind.FUNCTION_SIGNATURE_SPECIALIZATION_PARAM_KIND, index=value) 397 | if not result: 398 | return None 399 | param.addChild(result) 400 | 401 | specialization.addChild(param) 402 | param_count += 1 403 | 404 | return specialization 405 | 406 | def demangleProtocolConformance(self): 407 | print('demangleProtocolConformance({})'.format(self.mangled.text)) 408 | t = self.demangleType() 409 | if not t: 410 | return None 411 | protocol = self.demangleProtocolName() 412 | if not protocol: 413 | return None 414 | context = self.demangleContext() 415 | if not context: 416 | return None 417 | proto_conformance = Node(Kind.PROTOCOL_CONFORMANCE) 418 | proto_conformance.addChild(t) 419 | proto_conformance.addChild(protocol) 420 | proto_conformance.addChild(context) 421 | return proto_conformance 422 | 423 | def demangleEntity(self): 424 | print('demangleEntity({})'.format(self.mangled.text)) 425 | is_static = self.mangled.nextIf('Z') 426 | 427 | if self.mangled.nextIf('F'): 428 | entity_basic_kind = Node(Kind.FUNCTION) 429 | elif self.mangled.nextIf('v'): 430 | entity_basic_kind = Node(Kind.VARIABLE) 431 | elif self.mangled.nextIf('I'): 432 | entity_basic_kind = Node(Kind.INITIALIZER) 433 | elif self.mangled.nextIf('i'): 434 | entity_basic_kind = Node(Kind.SUBSCRIPT) 435 | else: 436 | return self.demangleNominalType() 437 | 438 | context = self.demangleContext() 439 | if not context: 440 | return None 441 | 442 | has_type = True 443 | name = "" 444 | if self.mangled.nextIf('D'): 445 | entity_kind = Node(Kind.DEALLOCATOR) 446 | has_type = False 447 | elif self.mangled.nextIf('d'): 448 | entity_kind = Node(Kind.DESCTRUCTOR) 449 | has_type = False 450 | elif self.mangled.nextIf('e'): 451 | entity_kind = Node(Kind.IVAR_INITIALIZER) 452 | has_type = False 453 | elif self.mangled.nextIf('E'): 454 | entity_kind = Node(Kind.IVAR_DESTROYER) 455 | has_type = False 456 | elif self.mangled.nextIf('C'): 457 | entity_kind = Node(Kind.ALLOCATOR) 458 | elif self.mangled.nextIf('c'): 459 | entity_kind = Node(Kind.CONSTRUCTOR) 460 | elif self.mangled.nextIf('a'): 461 | if self.mangled.nextIf('O'): 462 | entity_kind = Node(Kind.OWNING_MUTABLE_ADDRESSSOR) 463 | elif self.mangled.nextIf('o'): 464 | entity_kind = Node(Kind.NATIVE_OWNING_MUTABLE_ADDRESSOR) 465 | elif self.mangled.nextIf('p'): 466 | entity_kind = Node(Kind.NATIVE_PINNING_MUTABLE_ADDRESSOR) 467 | elif self.mangled.nextIf('u'): 468 | entity_kind = Node(Kind.UNSAFE_MUTABLE_ADDRESSOR) 469 | else: 470 | print('demangleEntity() couldn\'t handle addressor with suffix={}'.format(self.mangled.text)) 471 | return None 472 | name = self.demangleDeclName() 473 | if not name: 474 | return None 475 | elif self.mangled.nextIf('g'): 476 | entity_kind = Node(Kind.GETTER) 477 | name = self.demangleDeclName() 478 | if not name: 479 | return None 480 | elif self.mangled.nextIf('G'): 481 | entity_kind = Node(Kind.GLOBAL_GETTER) 482 | name = self.demangleDeclName() 483 | if not name: 484 | return None 485 | elif self.mangled.nextIf('s'): 486 | entity_kind = Node(Kind.SETTER) 487 | name = self.demangleDeclName() 488 | if not name: 489 | return None 490 | elif self.mangled.nextIf('m'): 491 | entity_kind = Node(Kind.MATERIALIZE_FOR_SET) 492 | name = self.demangleDeclName() 493 | if not name: 494 | return None 495 | elif self.mangled.nextIf('w'): 496 | entity_kind = Node(Kind.WILL_SET) 497 | name = self.demangleDeclName() 498 | if not name: 499 | return None 500 | elif self.mangled.nextIf('W'): 501 | entity_kind = Node(Kind.DID_SET) 502 | name = self.demangleDeclName() 503 | if not name: 504 | return None 505 | elif self.mangled.nextIf('U'): 506 | entity_kind = Node(Kind.EXPLICIT_CLOSURE) 507 | name = self.demangleDeclName() 508 | if not name: 509 | return None 510 | elif self.mangled.nextIf('u'): 511 | entity_kind = Node(Kind.IMPLICIT_CLOSURE) 512 | name = self.demangleDeclName() 513 | if not name: 514 | return None 515 | elif entity_basic_kind == Kind.INITIALIZER: 516 | if self.mangled.nextIf('A'): 517 | entity_kind = Node(Kind.DEFAULT_ARGUMENT_INITIALIZER) 518 | name = self.demangleIndexAsNode() 519 | if not name: 520 | return None 521 | elif self.mangled.nextIf('i'): 522 | entity_kind = Node(Kind.INITIALIZER) 523 | else: 524 | print('demangleEntity() couldn\'t handle initializer with suffix={}'.format(self.mangled.text)) 525 | return None 526 | has_type = False 527 | else: 528 | entity_kind = entity_basic_kind 529 | name = self.demangleDeclName() 530 | if not name: 531 | return None 532 | 533 | entity = Node(entity_kind) 534 | entity.addChild(context) 535 | if name: 536 | entity.addChild(name) 537 | if has_type: 538 | t = self.demangleType() 539 | if not t: 540 | return None 541 | entity.addChild(t) 542 | if is_static: 543 | static_node = Node(Kind.STATIC) 544 | static_node.addChild(entity) 545 | return static_node 546 | 547 | return entity 548 | 549 | def demangleNominalType(self): 550 | print('demangleNominalType({})'.format(self.mangled.text)) 551 | if self.mangled.nextIf('S'): 552 | return self.demangleSubstitutionIndex() 553 | if self.mangled.nextIf('V'): 554 | return self.demangleDeclarationName(Kind.STRUCTURE) 555 | if self.mangled.nextIf('O'): 556 | return self.demangleDeclarationName(Kind.ENUM) 557 | if self.mangled.nextIf('C'): 558 | return self.demangleDeclarationName(Kind.CLASS) 559 | if self.mangled.nextIf('P'): 560 | return self.demangleDeclarationName(Kind.PROTOCOL) 561 | return None 562 | 563 | def demangleBoundGenericArgs(self, nominal_type): 564 | print('demangleBoundGenericArgs({})'.format(self.mangled.text)) 565 | if nominal_type.getNumChildren() == 0: 566 | return None 567 | 568 | parent_or_module = nominal_type.getChild(0) 569 | 570 | if (parent_or_module.kind != Kind.MODULE) and (parent_or_module.kind != Kind.FUNCTION) and (parent_or_module.kind != Kind.EXTENSION): 571 | parent_or_module = self.demangleBoundGenericArgs(parent_or_module) 572 | 573 | result = Node(nominal_type.kind) 574 | result.addChild(parent_or_module) 575 | result.addChild(nominal_type.getChild(1)) 576 | nominal_type = result 577 | 578 | args = Node(Kind.TYPE_LIST) 579 | while not self.mangled.nextIf('_'): 580 | t = self.demangleType() 581 | if not t: 582 | return None 583 | args.addChild(t) 584 | if self.mangled.isEmpty(): 585 | return None 586 | 587 | if args.getNumChildren() == 0: 588 | return nominal_type 589 | 590 | unbound_type = Node(Kind.TYPE) 591 | unbound_type.addChild(nominal_type) 592 | 593 | if nominal_type.kind == Kind.CLASS: 594 | kind = Kind.BOUND_GENERIC_CLASS 595 | elif nominal_type.kind == Kind.STRUCTURE: 596 | kind = Kind.BOUND_GENERIC_STRUCTURE 597 | elif nominal_type.kind == Kind.ENUM: 598 | kind = Kind.BOUND_GENERIC_ENUM 599 | else: 600 | return None 601 | 602 | result = Node(kind) 603 | result.addChild(unbound_type) 604 | result.addChild(args) 605 | return result 606 | 607 | def demangleSpecializedAttribute(self): 608 | print('demangleSpecializedAttribute({})'.format(self.mangled.text)) 609 | is_not_re_abstracted = False 610 | if self.mangled.nextIf('g') or (self.mangled.peek() == 'r'): 611 | is_not_re_abstracted = self.mangled.nextIf('r') 612 | kind = Kind.GENERIC_SPECIALIZATION_NOT_RE_ABSTRACTED if is_not_re_abstracted else Kind.GENERIC_SPECIALIZATION 613 | spec = Node(kind) 614 | 615 | if self.mangled.nextIf('q'): 616 | spec.addChild(Node(Kind.SPECIALIZATION_IS_FRAGILE)) 617 | 618 | spec.addChild(Node(Kind.SPECIALIZATION_PASS_ID, index=int(self.mangled.next))) 619 | 620 | return self.demangleGenericSpecialization(spec) 621 | 622 | if self.mangled.nextIf('f'): 623 | spec = Node(Kind.FUNCTION_SIGNATURE_SPECIALIZATION) 624 | 625 | if self.mangled.nextIf('q'): 626 | spec.addChild(Node(Kind.SPECIALIZATION_IS_FRAGILE)) 627 | 628 | spec.addChild(Node(Kind.SPECIALIZATION_PASS_ID, index=int(self.mangled.next()))) 629 | 630 | return self.demangleFunctionSignatureSpecialization(spec) 631 | 632 | return None 633 | 634 | def demangleDeclName(self): 635 | print('demangleDeclName({})'.format(self.mangled.text)) 636 | if self.mangled.nextIf('L'): 637 | discriminator = self.demangleIndexAsNode() 638 | if not discriminator: 639 | return None 640 | name = self.demangleIdentifier() 641 | if not name: 642 | return None 643 | 644 | local_name = Node(Kind.LOCAL_DECL_NAME) 645 | local_name.addChild(disciminator) 646 | local_name.addChild(name) 647 | return local_name 648 | elif self.mangled.nextIf('P'): 649 | discriminator = self.demangleIdentifier() 650 | if not discriminator: 651 | return None 652 | 653 | name = self.demangleIdentifier() 654 | if not name: 655 | return None 656 | 657 | private_name = Node(Kind.PRIVATE_DECL_NAME) 658 | private_name.addChild(discriminator) 659 | private_name.addChild(name) 660 | return private_name 661 | 662 | return self.demangleIdentifier() 663 | 664 | def demangleIdentifier(self, kind=None): 665 | print('demangleIdentifier({})'.format(self.mangled.text)) 666 | if not self.mangled: 667 | return None 668 | 669 | is_puny_coded = self.mangled.nextIf('X') 670 | # TODO: WTF? 671 | 672 | is_operator = False 673 | if self.mangled.nextIf('o'): 674 | is_operator = True 675 | # TODO: not sure about this 676 | if kind: 677 | return None 678 | 679 | op_mode = self.mangled.next() 680 | if op_mode == 'p': 681 | kind = Node(Kind.PREFIX_OPERATOR) 682 | elif op_mode == 'P': 683 | kind = Node(Kind.POSTFIX_OPERATOR) 684 | elif op_mode == 'i': 685 | kind = Node(Kind.INFIX_OPERATOR) 686 | else: 687 | return None 688 | 689 | if not kind: 690 | kind = Kind.IDENTIFIER 691 | 692 | length = 0 693 | success, length = self.demangleNatural(length) 694 | if not success: 695 | return None 696 | if not self.mangled.hasAtLeast(length): 697 | return None 698 | 699 | identifier = self.mangled.slice(length) 700 | self.mangled.advanceOffset(length) 701 | 702 | #identifier = decode(identifier) 703 | if len(identifier) == 0: 704 | return None 705 | 706 | if is_operator: 707 | print('TODO: decode operator names for {}'.format(identifier)) 708 | return None 709 | 710 | return Node(kind, identifier) 711 | 712 | def demangleIndex(self, natural): 713 | print('demangleIndex({})'.format(self.mangled.text)) 714 | #natural = 0 715 | if self.mangled.nextIf('_'): 716 | natural = 0 717 | return True, natural 718 | 719 | success, natural = self.demangleNatural(natural) 720 | print('success={} natural={}'.format(success, natural)) 721 | if success: 722 | if not self.mangled.nextIf('_'): 723 | return False, natural 724 | natural += 1 725 | return True, natural 726 | return False, natural 727 | 728 | def demangleIndexAsNode(self, kind=Node(Kind.NUMBER)): 729 | print('demangleIndexAsNode({})'.format(self.mangled.text)) 730 | success, index = self.demangleIndex(0) 731 | if not success: 732 | return None 733 | return Node(kind, index=index) 734 | 735 | def createSwiftType(self, type_kind, name): 736 | print('createSwiftType({})'.format(name)) 737 | t = Node(type_kind) 738 | t.addChild(Node(Kind.MODULE, text=STDLIB_NAME)) 739 | t.addChild(Node(Kind.IDENTIFIER, text=name)) 740 | return t 741 | 742 | def demangleSubstitutionIndex(self): 743 | print('demangleSubstitutionIndex({})'.format(self.mangled.text)) 744 | if not self.mangled: 745 | return None 746 | if self.mangled.nextIf('o'): 747 | return Node(Kind.MODULE, text=MANGLING_MODULE_OBJC) 748 | if self.mangled.nextIf('C'): 749 | return Node(Kind.MODULE, text=MANGLING_MODULE_C) 750 | if self.mangled.nextIf('a'): 751 | return self.createSwiftType(Kind.STRUCTURE, 'Array') 752 | if self.mangled.nextIf('b'): 753 | return self.createSwiftType(Kind.STRUCTURE, 'Bool') 754 | if self.mangled.nextIf('c'): 755 | return self.createSwiftType(Kind.STRUCTURE, 'UnicodeScalar') 756 | if self.mangled.nextIf('d'): 757 | return self.createSwiftType(Kind.STRUCTURE, 'Double') 758 | if self.mangled.nextIf('f'): 759 | return self.createSwiftType(Kind.STRUCTURE, 'Float') 760 | if self.mangled.nextIf('i'): 761 | return self.createSwiftType(Kind.STRUCTURE, 'Int') 762 | if self.mangled.nextIf('V'): 763 | return self.createSwiftType(Kind.STRUCTURE, 'UnsafeRawPointer') 764 | if self.mangled.nextIf('v'): 765 | return self.createSwiftType(Kind.STRUCTURE, 'UnsafeMutableRawPointer') 766 | if self.mangled.nextIf('P'): 767 | return self.createSwiftType(Kind.STRUCTURE, 'UnsafePointer') 768 | if self.mangled.nextIf('p'): 769 | return self.createSwiftType(Kind.STRUCTURE, 'UnsafeMutablePointer') 770 | if self.mangled.nextIf('q'): 771 | return self.createSwiftType(Kind.ENUM, 'Optional') 772 | if self.mangled.nextIf('Q'): 773 | return self.createSwiftType(Kind.ENUM, 'ImplicitlyUnwrappedOptional') 774 | if self.mangled.nextIf('R'): 775 | return self.createSwiftType(Kind.STRUCTURE, 'UnsafeBufferPointer') 776 | if self.mangled.nextIf('r'): 777 | return self.createSwiftType(Kind.STRUCTURE, 'UnsafeMutableBufferPointer') 778 | if self.mangled.nextIf('S'): 779 | return self.createSwiftType(Kind.STRUCTURE, 'String') 780 | if self.mangled.nextIf('u'): 781 | return self.createSwiftType(Kind.STRUCTURE, 'UInt') 782 | 783 | print('demangleSubstitutionIndex made it past createSwiftType()') 784 | print('substitutions={}'.format(self.substitutions)) 785 | success, index_sub = self.demangleIndex(0) 786 | print('success={} index_sub={}'.format(success, index_sub)) 787 | if not success: 788 | return None 789 | if index_sub >= len(self.substitutions): 790 | return None 791 | return self.substitutions[index_sub] 792 | 793 | def demangleDeclarationName(self, kind): 794 | print('demangleDeclarationName({})'.format(self.mangled.text)) 795 | context = self.demangleContext() 796 | if not context: 797 | return None 798 | 799 | name = self.demangleDeclName() 800 | if not name: 801 | return None 802 | 803 | decl = Node(kind) 804 | decl.addChild(context) 805 | decl.addChild(name) 806 | self.substitutions.append(decl) 807 | return decl 808 | 809 | def demangleProtocolName(self): 810 | print('demangleProtocolName({})'.format(self.mangled.text)) 811 | proto = self.demangleProtocolNameImpl() 812 | if not proto: 813 | return None 814 | 815 | t = Node(Kind.TYPE) 816 | t.addChild(proto) 817 | return t 818 | 819 | def demangleProtocolNameGivenContext(self, context): 820 | print('demangleProtocolNameGivenContext({})'.format(self.mangled.text)) 821 | name = self.demangleDeclName() 822 | if not name: 823 | return None 824 | 825 | proto = Node(Kind.PROTOCOL) 826 | proto.addChild(context) 827 | proto.addChild(name) 828 | self.substitutions.append(proto) 829 | return proto 830 | 831 | def demangleProtocolNameImpl(self): 832 | print('demangleProtocolNameImpl({})'.format(self.mangled.text)) 833 | if self.mangled.nextIf('S'): 834 | sub = self.demangleSubstitutionIndex() 835 | if not sub: 836 | return None 837 | if sub.kind == Kind.PROTOCOL: 838 | return sub 839 | if sub.kind != Kind.MODULE: 840 | return None 841 | return self.demangleProtocolNameGivenContext(sub) 842 | 843 | if self.mangled.nextIf('s'): 844 | stdlib = Node(Kind.MODULE, text=STDLIB_NAME) 845 | return self.demangleProtocolNameGivenContext(stdlib) 846 | 847 | return self.demangleDeclaratioinName(Kind.PROTOCOL) 848 | 849 | def demangleModule(self): 850 | print('demangleModule({})'.format(self.mangled.text)) 851 | if self.mangled.nextIf('s'): 852 | return Node(Kind.MODULE, text=STDLIB_NAME) 853 | if self.mangled.nextIf('S'): 854 | module = self.demangleSubstitutionIndex() 855 | if not module: 856 | return None 857 | if module.kind != Kind.MODULE: 858 | return None 859 | return module 860 | 861 | module = self.demangleIdentifier(Kind.MODULE) 862 | if not module: 863 | return None 864 | self.substitutions.append(module) 865 | return module 866 | 867 | def demangleBoundGenericType(self): 868 | print('demangleBoundGenericType({})'.format(self.mangled.text)) 869 | nominal_type = self.demangleNominalType() 870 | if not nominal_type: 871 | return None 872 | return self.demangleBoundGenericArgs(nominal_type) 873 | 874 | def demangleContext(self): 875 | print('demangleContext({})'.format(self.mangled.text)) 876 | if not self.mangled: 877 | return None 878 | if self.mangled.nextIf('E'): 879 | ext = Node(Kind.EXTENSION) 880 | def_module = self.demangleModule() 881 | if not def_module: 882 | return None 883 | t = self.demangleContext() 884 | if not t: 885 | return None 886 | ext.addChild(def_module) 887 | ext.addChild(t) 888 | return ext 889 | 890 | if self.mangled.nextIf('e'): 891 | ext = Node(Kind.EXTENSION) 892 | def_module = self.demangleModule() 893 | if not def_module: 894 | return None 895 | sig = self.demangleGenericSignature() 896 | if not sig: 897 | return None 898 | t = self.demangleContext() 899 | if not t: 900 | return None 901 | ext.addChild(def_module) 902 | ext.addChild(t) 903 | ext.addChild(sig) 904 | return ext 905 | 906 | if self.mangled.nextIf('S'): 907 | return self.demangleSubstitutionIndex() 908 | if self.mangled.nextIf('s'): 909 | return Node(Kind.MODULE, text=STDLIB_NAME) 910 | if self.mangled.nextIf('G'): 911 | print('TODO: implement demangleBoundGenericType()') 912 | return None 913 | #return self.demangleBoundGenericType() 914 | if isStartOfEntity(self.mangled.peek()): 915 | return self.demangleEntity() 916 | return self.demangleModule() 917 | 918 | def demangleProtocolList(self): 919 | print('demangleProtocolList({})'.format(self.mangled.text)) 920 | proto_list = Node(Kind.PROTOCOL_LIST) 921 | type_list = Node(Kind.TYPE_LIST) 922 | proto_list.addChild(type_list) 923 | while not self.mangled.nextIf('_'): 924 | proto = self.demangleProtocolName() 925 | if not proto: 926 | return None 927 | type_list.addChild(proto) 928 | return proto_list 929 | 930 | def demangleTuple(self, is_v): 931 | print('demangleTuple({})'.format(self.mangled.text)) 932 | tuple = Node(Kind.TUPLE) 933 | elt = None 934 | while not self.mangled.nextIf('_'): 935 | if not self.mangled: 936 | return None 937 | elt = Node(Kind.TUPLE_ELEMENT) 938 | 939 | if isStartOfIdentifier(self.mangled.peek()): 940 | label = self.demangleIdentifier(Kind.TUPLE_ELEMENT_NAME) 941 | if not label: 942 | return None 943 | elt.addChild(label) 944 | 945 | t = self.demangleType() 946 | if not t: 947 | return None 948 | elt.addChild(t) 949 | tuple.addChild(elt) 950 | 951 | if is_v == IsVariadic.YES and elt: 952 | elt.reverseChildren() 953 | marker = Node(Kind.VARIADIC_MARKER) 954 | elt.addChild(marker) 955 | elt.reverseChildren() 956 | return tuple 957 | 958 | def postProcessReturnTypeNode(self, out_args): 959 | out_node = Node(Kind.RETURN_TYPE) 960 | out_node.addChild(out_args) 961 | return out_node 962 | 963 | def demangleType(self): 964 | print('demangleType({})'.format(self.mangled.text)) 965 | t = self.demangleTypeImpl() 966 | if not t: 967 | return None 968 | node_type = Node(Kind.TYPE) 969 | node_type.addChild(t) 970 | return node_type 971 | 972 | def demangleFunctionType(self, kind): 973 | print('demangleFunctionType({})'.format(self.mangled.text)) 974 | throws = False 975 | if self.mangled and self.mangled.nextIf('z'): 976 | throws = True 977 | in_args = self.demangleType() 978 | print('in_args={}'.format(in_args)) 979 | if not in_args: 980 | return None 981 | out_args = self.demangleType() 982 | print('out_args={}'.format(out_args)) 983 | if not out_args: 984 | return None 985 | block = Node(kind) 986 | 987 | if throws: 988 | block.addChild(Node(Kind.THROWS_ANNOTATION)) 989 | 990 | in_node = Node(Kind.ARGUMENT_TUPLE) 991 | block.addChild(in_node) 992 | in_node.addChild(in_args) 993 | block.addChild(self.postProcessReturnTypeNode(out_args)) 994 | return block 995 | 996 | def demangleTypeImpl(self): 997 | print('demangleTypeImpl({})'.format(self.mangled.text)) 998 | if not self.mangled: 999 | return None 1000 | 1001 | c = self.mangled.next() 1002 | if c == 'B': 1003 | if not self.mangled: 1004 | return None 1005 | c = self.mangled.next() 1006 | if c == 'b': 1007 | return Node(Kind.BUILTIN_TYPE_NAME, text="Builtin.BridgeObject") 1008 | 1009 | if c == 'B': 1010 | return Node(Kind.BUILTIN_TYPE_NAME, text="Builtin.UnsafeValueBuffer") 1011 | 1012 | if c == 'f': 1013 | print('TODO: implement demangleBuiltinSize(size)') 1014 | return None 1015 | 1016 | if c == 'i': 1017 | print('TODO: implement demangleBuiltinSize(size)') 1018 | return None 1019 | 1020 | if c == 'v': 1021 | elts = 0 1022 | success, elts = self.demangleNatural(elts) 1023 | if sucess: 1024 | if not self.mangled.nextIf('B'): 1025 | return None 1026 | if self.mangled.nextIf('i'): 1027 | print('TODO: implement demangleBuiltinSize(size)') 1028 | return None 1029 | if self.mangled.nextIf('f'): 1030 | print('TODO: implement demangleBuiltinSize(size)') 1031 | return None 1032 | if self.mangled.nextIf('p'): 1033 | print('TODO: implement DemanglerPrinter()') 1034 | return None 1035 | if c == 'O': 1036 | return Node(Kind.BUILTIN_TYPE_NAME, text='Builtin.UnknownObject') 1037 | if c == 'o': 1038 | return Node(Kind.BUILTIN_TYPE_NAME, text='Builtin.NativeObject') 1039 | if c == 'p': 1040 | return Node(Kind.BUILTIN_TYPE_NAME, text='Builtin.RawPointer') 1041 | if c == 'w': 1042 | return Node(Kind.BUILTIN_TYPE_NAME, text='Builtin.Word') 1043 | return None 1044 | 1045 | if c == 'a': 1046 | return self.demangleDeclarationname(Kind.TYPE_ALIAS) 1047 | if c == 'b': 1048 | return self.demangleDeclarationname(Kind.ObjCBlock) 1049 | if c == 'c': 1050 | return self.demangleDeclarationname(Kind.CFunctionPointer) 1051 | if c == 'D': 1052 | t = self.demangleType() 1053 | if not t: 1054 | return None 1055 | dynamic_self = Node(Kind.DYNAMIC_SELF) 1056 | dynamic_self.addChild(t) 1057 | return dynamic_self 1058 | if c == 'E': 1059 | if not self.mangled.nextIf('R'): 1060 | return None 1061 | if not self.mangled.nextIf('R'): 1062 | return None 1063 | # TODO: std::string() is unusual 1064 | return Node(Kind.ERROR_TYPE, text="") 1065 | if c == 'F': 1066 | return self.demangleFunctionType(Kind.FUNCTION_TYPE) 1067 | if c == 'f': 1068 | return self.demangleFunctionType(Kind.UNCURRIED_FUNCTION_TYPE) 1069 | if c == 'G': 1070 | return self.demangleBoundGenericType() 1071 | if c == 'X': 1072 | print('TODO: implement X case') 1073 | return None 1074 | if c == 'K': 1075 | return self.demangleFunctionType(Kind.AUTO_CLOSURE_TYPE) 1076 | if c == 'M': 1077 | t = self.demangleType() 1078 | if not t: 1079 | return None 1080 | metatype = Node(Kind.METATYPE) 1081 | metatype.addChild(t) 1082 | return metatype 1083 | if c == 'X': 1084 | print('TODO: implement demangleMetatypeRepresentation') 1085 | return None 1086 | if c == 'P': 1087 | if self.mangled.nextIf('M'): 1088 | t = self.demangleType() 1089 | if not t: 1090 | return None 1091 | metatype = Node(Kind.EXISTENTIAL_METATYPE) 1092 | metatype.addChild(t) 1093 | return metatype 1094 | return self.demangleProtocolList() 1095 | if c == 'X': 1096 | print('TODO: implement demangleMetatypeRepresentation') 1097 | return None 1098 | if c == 'Q': 1099 | print('TODO: implement demangleArchetypeType') 1100 | return None 1101 | #return self.demangleArchetypeType() 1102 | if c == 'q': 1103 | print('TODO: implement demangleDependentType') 1104 | return None 1105 | if c == 'x': 1106 | return self.getDependentGenericParamType(0, 0) 1107 | if c == 'w': 1108 | return self.demangleAssociatedTypeSimple() 1109 | if c == 'W': 1110 | return self.demangleAssociatedTypeCompound() 1111 | if c == 'R': 1112 | inout = Node(Kind.IN_OUT) 1113 | t = self.demangleTypeImpl() 1114 | if not t: 1115 | return None 1116 | inout.addChild(t) 1117 | return inout 1118 | if c == 'S': 1119 | return self.demangleSubstitutionIndex() 1120 | if c == 'T': 1121 | return self.demangleTuple(IsVariadic.NO) 1122 | if c == 't': 1123 | return self.demangleTuple(IsVariadic.YES) 1124 | if c == 'u': 1125 | sig = self.demangleGenericSignature() 1126 | if not sig: 1127 | return None 1128 | sub = self.demangleType() 1129 | if not sub: 1130 | return None 1131 | dependent_generic_type = Node(Kind.DEPENDENT_GENERIC_TYPE) 1132 | dependent_generic_type.addChild(sig) 1133 | dependent_generic_type.addChild(sub) 1134 | return dependent_generic_type 1135 | if c == 'X': 1136 | if self.mangled.nextIf('f'): 1137 | return self.demangleFunctionType(Kind.THIN_FUNCTION_TYPE) 1138 | if self.magled.nextIf('o'): 1139 | t = self.demangleType() 1140 | if not t: 1141 | return None 1142 | unowned = Node(Kind.UNOWNED) 1143 | unowned.addChild(t) 1144 | return unowned 1145 | if self.mangled.nextIf('u'): 1146 | t = self.demangleType() 1147 | if not t: 1148 | return None 1149 | unowned = Node(Kind.UNMANAGED) 1150 | unowned.addChild(t) 1151 | return unowned 1152 | if self.mangled.nextIf('w'): 1153 | t = self.demangleType() 1154 | if not t: 1155 | return None 1156 | weak = Node(Kind.WEAK) 1157 | weak.addChild(t) 1158 | return weak 1159 | if self.mangled.nextIf('F'): 1160 | return self.demangleImplFunctionType() 1161 | 1162 | return None 1163 | if isStartOfNominalType(c): 1164 | return self.demangleDeclarationName(nominalTypeMarkerToNodeKind(c)) 1165 | return None 1166 | 1167 | def demangleReabstractSignature(self, signature): 1168 | print('demangleReabstractSignature({})'.format(self.mangled.text)) 1169 | if self.mangled.nextIf('G'): 1170 | generics = self.demangleGenericSignature() 1171 | if not generics: 1172 | return False, signature 1173 | signature.addChild(generics) 1174 | 1175 | src_type = self.demangleType() 1176 | if not src_type: 1177 | return False, signature 1178 | signature.addChild(src_type) 1179 | 1180 | dest_type = self.demangleType() 1181 | if not dest_type: 1182 | return False, signature 1183 | signature.addChild(dest_type) 1184 | 1185 | return True, signature 1186 | 1187 | def getDependentGenericParamType(self, depth, index): 1188 | print('getDependentGenericParamType({})'.format(self.mangled.text)) 1189 | print_name = archetypeName(index, depth) 1190 | param_ty = Node(Kind.DEPENDENT_GENERIC_PARAM_TYPE, print_name) 1191 | param_ty.addChild(Node(Kind.INDEX, index=depth)) 1192 | param_ty.addChild(Node(Kind.INDEX, index=index)) 1193 | return param_ty 1194 | 1195 | def demangleGenericParamIndex(self): 1196 | print('demangleGenericParamIndex({})'.format(self.mangled.text)) 1197 | depth = 0 1198 | index = 0 1199 | if self.mangled.nextIf('d'): 1200 | success, depth = self.demangleIndex(depth) 1201 | if not success: 1202 | return None 1203 | depth += 1 1204 | success, index = self.demangleIndex(index) 1205 | if not success: 1206 | return None 1207 | elif self.mangled.nextIf('x'): 1208 | depth = 0 1209 | index = 0 1210 | else: 1211 | success, index = self.demangleIndex(index) 1212 | if not success: 1213 | return None 1214 | depth = 0 1215 | index += 1 1216 | return self.getDependentGenericParamType(depth, index) 1217 | 1218 | def demangleDependentMemberTypeName(self, base): 1219 | print('demangleDependentMemberTypeName({})'.format(self.mangled.text)) 1220 | if base.kind != Kind.TYPE: 1221 | print('ERROR: demangleDependentMemberTypeName(base) base should be a type') 1222 | return None 1223 | 1224 | assoc_ty = None 1225 | if self.mangled.nextIf('S'): 1226 | assoc_ty = self.demangleSubstitutionIndex() 1227 | if not assoc_ty: 1228 | return None 1229 | if assoc_ty.kind != Kind.DEPENDENT_ASSOCIATED_TYPE_REF: 1230 | return None 1231 | else: 1232 | protocol = None 1233 | if self.mangled.nextIf('P'): 1234 | protocol = self.demangleProtocolName() 1235 | if not protocol: 1236 | return None 1237 | 1238 | assoc_ty = self.demangleIdentifier(Kind.DEPENDENT_ASSOCIATED_TYPE_REF) 1239 | if not assoc_ty: 1240 | return None 1241 | if protocol: 1242 | assoc_ty.addChild(protocol) 1243 | 1244 | self.substitutions.append(assoc_ty) 1245 | 1246 | dep_ty = Node(Kind.DEPENDENT_MEMBER_TYPE) 1247 | dep_ty.addChild(base) 1248 | dep_ty.addChild(assoc_ty) 1249 | return dep_ty 1250 | 1251 | def demangleAssociatedTypeSimple(self): 1252 | print('demangleAssociatedTypeSimple({})'.format(self.mangled.text)) 1253 | base = self.demangleGenericParamIndex() 1254 | if not base: 1255 | return None 1256 | 1257 | node_type = Node(Kind.TYPE) 1258 | node_type.addChild(base) 1259 | return self.demangleDependentMemberTypeName(node_type) 1260 | 1261 | def demangleAssociatedTypeCompound(self): 1262 | print('demangleAssociatedTypeCompound({})'.format(self.mangled.text)) 1263 | base = self.demangleGenericParamIndex() 1264 | if not base: 1265 | return None 1266 | 1267 | while not self.mangled.nextIf('_'): 1268 | node_type = Node(Kind.TYPE) 1269 | node_type.addChild(base) 1270 | 1271 | base = self.demangleDependentMemberTypeName(node_type) 1272 | if not base: 1273 | return None 1274 | 1275 | return base 1276 | 1277 | def demangleConstrainedTypeImpl(self): 1278 | print('demangleConstrainedTypeImpl({})'.format(self.mangled.text)) 1279 | if self.mangled.nextIf('w'): 1280 | return self.demangleAssociatedTypeSimple() 1281 | if self.mangled.nextIf('W'): 1282 | return self.demangleAssociatedTypeCompound() 1283 | return self.demangleGenericParamIndex() 1284 | 1285 | def demangleConstrainedType(self): 1286 | print('demangleConstrainedType({})'.format(self.mangled.text)) 1287 | t = self.demangleConstrainedTypeImpl() 1288 | if not t: 1289 | return None 1290 | 1291 | node_type = Node(Kind.TYPE) 1292 | node_type.addChild(t) 1293 | return node_type 1294 | 1295 | def demangleGenericSignature(self, is_pseudogeneric = False): 1296 | print('demangleGenericSignature({})'.format(self.mangled.text)) 1297 | kind = Kind.DEPENDENT_PSEUDOGENERIC_SIGNATURE if is_pseudogeneric else Kind.DEPENDENT_GENERIC_SIGNATURE 1298 | sig = Node(kind) 1299 | 1300 | count = (1<<64) - 1 1301 | 1302 | addCount = lambda node, n: node.addChild(Node(Kind.DEPENDENT_GENERIC_PARAM_COUNT, index=n)) 1303 | 1304 | while (self.mangled.peek() != 'R') and (self.mangled.peek() != 'r'): 1305 | if self.mangled.nextIf('z'): 1306 | count = 0 1307 | addCount(sig, count) 1308 | continue 1309 | success, count = self.demangleIndex(count) 1310 | if success: 1311 | count += 1 1312 | else: 1313 | return None 1314 | addCount(sig, count) 1315 | 1316 | if count == ((1<<64) - 1): 1317 | count = 1 1318 | addCount(sig, count) 1319 | 1320 | if self.mangled.nextIf('r'): 1321 | return sig 1322 | 1323 | if not self.mangled.nextIf('R'): 1324 | return None 1325 | 1326 | while not self.mangled.nextIf('r'): 1327 | reqt = self.demangleGenericRequirement() 1328 | if not reqt: 1329 | return None 1330 | sig.addChild(reqt) 1331 | 1332 | return sig 1333 | 1334 | def demangleGenericRequirement(self): 1335 | print('demangleGenericRequirement({})'.format(self.mangled.text)) 1336 | constrained_type = self.demangleConstrainedType() 1337 | if not constrained_type: 1338 | return None 1339 | if self.mangled.nextIf('z'): 1340 | second = self.demangleType() 1341 | if not second: 1342 | return None 1343 | reqt = Node(Kind.DEPENDENT_GENERIC_SAME_TYPE_REQUIREMENT) 1344 | reqt.addChild(constrained_type) 1345 | reqt.addChild(second) 1346 | return reqt 1347 | 1348 | if self.mangled.nextIf('l'): 1349 | size = -1 1350 | aligment = -1 1351 | if self.mangled.nextIf('U'): 1352 | kind = Kind.IDENTIFIER 1353 | name = 'U' 1354 | elif self.mangled.nextIf('R'): 1355 | kind = Kind.IDENTIFIER 1356 | name = 'R' 1357 | elif self.mangled.nextIf('N'): 1358 | kind = Kind.IDENTIFIER 1359 | name = 'N' 1360 | elif self.mangled.nextIf('T'): 1361 | kind = Kind.IDENTIFIER 1362 | name = 'T' 1363 | elif self.mangled.nextIf('E'): 1364 | kind = Kind.IDENTIFIER 1365 | success, size = self.demangleNatural(size) 1366 | if not success: 1367 | return None 1368 | if not self.mangled.nextIf('_'): 1369 | return None 1370 | success, alignment = self.demangleNatural(alignment) 1371 | if not success: 1372 | return None 1373 | name = 'E' 1374 | elif self.mangled.nextIf('e'): 1375 | kind = Node(Kind.IDENTIFIER) 1376 | success, size = self.demangleNatural(size) 1377 | if not success: 1378 | return None 1379 | name = 'e' 1380 | elif self.mangled.nextIf('M'): 1381 | kind = Node(Kind.IDENTIFIER) 1382 | success, size = self.demangleNatural(size) 1383 | if not success: 1384 | return None 1385 | if not self.mangled.nextIf('_'): 1386 | return None 1387 | success, alignment = self.demangleNatural(alignment) 1388 | if not success: 1389 | return None 1390 | name = 'M' 1391 | elif self.mangled.nextIf('m'): 1392 | kind = Node(Kind.IDENTIFIER) 1393 | success, size = self.demangleNatural(size) 1394 | if not success: 1395 | return None 1396 | name = 'm' 1397 | else: 1398 | return None 1399 | 1400 | second = Node(kind, text=name) 1401 | if not second: 1402 | return None 1403 | reqt = Node(Kind.DEPENDENT_GENERIC_LAYOUT_REQUIREMENT) 1404 | reqt.addChild(constrained_type) 1405 | reqt.addChild(second) 1406 | if size != -1: 1407 | reqt.addChild(Node(Kind.NUMBER, index=size)) 1408 | if alignment != -1: 1409 | reqt.addChild(Node(Kind.NUMBER, index=alignment)) 1410 | return reqt 1411 | 1412 | if not self.mangled: 1413 | return None 1414 | 1415 | constraint = None 1416 | next = self.mangled.peek() 1417 | 1418 | if next == 'C': 1419 | constraint = self.demangleType() 1420 | if not constraint: 1421 | return None 1422 | elif next == 'S': 1423 | type_name = None 1424 | self.mangled.next() 1425 | sub = self.demangleSubstitutionIndex() 1426 | if not sub: 1427 | return None 1428 | if (sub.kind == Kind.PROTOCOL) or (sub.kind == Kind.CLASS): 1429 | type_name = sub 1430 | elif sub.kind == Kind.MODULE: 1431 | type_name = self.demangleProtocolNameGiveContext() 1432 | if not type_name: 1433 | return None 1434 | else: 1435 | return None 1436 | constraint = Node(Kind.TYPE) 1437 | constraint.addChild(type_name) 1438 | else: 1439 | constraint = self.demangleProtocolName() 1440 | if not constraint: 1441 | return None 1442 | reqt = Node(Kind.DEPENDENT_GENERIC_CONFORMANCE_REQUIREMENT) 1443 | reqt.addChild(constrained_type) 1444 | reqt.addChild(constraint) 1445 | return reqt 1446 | 1447 | def isStartOfIdentifier(c): 1448 | if c in string.digits: 1449 | return True 1450 | return c == 'o' 1451 | 1452 | def isStartOfNominalType(c): 1453 | if c in 'CVO': 1454 | return True 1455 | return False 1456 | 1457 | def isStartOfEntity(c): 1458 | if c in 'FIvPsZ': 1459 | return True 1460 | return isStartOfNominalType(c) 1461 | 1462 | def nominalTypeMarkerToNodeKind(c): 1463 | if c == 'C': 1464 | return Kind.CLASS 1465 | if c == 'V': 1466 | return Kind.STRUCTURE 1467 | if c == 'O': 1468 | return Kind.ENUM 1469 | return Kind.IDENTIFIER 1470 | 1471 | def demangleOldSymbolAsNode(s): 1472 | demangler = OldDemangler(s) 1473 | return demangler.demangleTopLevel() 1474 | -------------------------------------------------------------------------------- /modules/printer.py: -------------------------------------------------------------------------------- 1 | def archetypeName(index, depth): 2 | name = chr(ord('A') + (index % 26)) 3 | index /= 26 4 | while index: 5 | name += chr(ord('A') + (index % 26)) 6 | index /= 26 7 | if depth != 0: 8 | name += str(depth) 9 | return name 10 | -------------------------------------------------------------------------------- /plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": { 3 | "name": "iOS Tools", 4 | "type": ["core", "ui", "architecture", "binaryview"], 5 | "api": "python2", 6 | "description": "A collection of helper functions for reversing iOS Mach-O files", 7 | "longdescription": "This plugin is currently a partially completed mess. Needed to make the first commit at some point.\n\nCan automatically parse class structures and rename function symbols to use their method names.\nUsing the Objective-C runtime implementation at https://opensource.apple.com/source/objc4/objc4-709/ as a reference.\n\nCan demangle imported Swift symbols and comment their occurences in a function.\nUsing the Swift demangler implementation at https://github.com/apple/swift/ as a reference.\n\n", 8 | "license": { 9 | "name": "MIT", 10 | "text": "Copyright (c) 2017 Kevin Watson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." 11 | }, 12 | "dependencies": { 13 | "pip": ["enum34"] 14 | }, 15 | "version": "0.1", 16 | "author": "Kevin Watson", 17 | "minimumBinaryNinjaVersion": { 18 | "release": "1.0.776" 19 | } 20 | } 21 | } 22 | --------------------------------------------------------------------------------