def readCategory(machO, vmaddr, classes, protoRefsMap): """Read a ``category_t`` at *vmaddr*, and returns a tuple of :class:`~objc.category.Category`, and the :class:`~objc.class_.Class` or :class:`~objc.class_.RemoteClass` it is patching.""" # typedef struct category_t { # const char *name; # struct class_t *cls; # struct method_list_t *instanceMethods; # struct method_list_t *classMethods; # struct protocol_list_t *protocols; # struct objc_property_list *instanceProperties; # } category_t; pos = machO.fromVM(vmaddr) + machO.origin (namePtr, clsPtr, instMethodsPtr, classMethodsPtr, protosPtr, propsPtr) = peekStruct(machO.file, machO.makeStruct('6^'), position=pos) name = machO.derefString(namePtr) if not clsPtr: clsPtr = vmaddr + machO.pointerWidth cls = classAt(machO, clsPtr, classes) cat = Category(name, cls) cat.addClassMethods(readMethodListAt(machO, classMethodsPtr, optional=False)) cat.addMethods(readMethodListAt(machO, instMethodsPtr, optional=False)) cat.addProperties(readPropertyListAt(machO, propsPtr)) protocolRefs = _readProtocolRefListAt(machO, protosPtr) connectProtocol(cat, protocolRefs, protoRefsMap) return cat
def analyzeCategory(machO, catTuple, classes, protoRefsMap): """Analyze an ``old_category`` structure, and returns the :class:`~objc.category.Category`""" # struct old_category { # char *category_name; # char *class_name; # struct old_method_list *instance_methods; # struct old_method_list *class_methods; # struct old_protocol_list *protocols; # uint32_t size; # struct objc_property_list *instance_properties; # }; (namePtr, clsNamePtr, methodListsPtr, clsMethodListsPtr, protoListPtr, _, propListsPtr) = catTuple ds = machO.derefString name = ds(namePtr) clsName = ds(clsNamePtr) cls = classes.any('name', clsName) if not cls: newSymbol = machO.symbols.any1('addr', clsNamePtr) cls = RemoteClass(newSymbol) cat = Category(name, cls) cat.addMethods(readMethodList(machO, methodListsPtr)) cat.addClassMethods(readMethodList(machO, clsMethodListsPtr)) if protoListPtr: protoAddrs = list(_readProtocolRefListsAt(machO, [protoListPtr])) connectProtocol(cat, protoAddrs, protoRefsMap) cls.addProperties(readPropertyList(machO, propListsPtr)) return cat