def _loadSections(self, machO): segStruct = machO.makeStruct('16s4^2i2L') sectStruct = machO.makeStruct(Section.STRUCT_FORMAT) (segname, self.vmaddr, self._vmsize, self._fileoff, self._filesize, self.maxprot, self.initprot, nsects, _) = readStruct(machO.file, segStruct) self.segname = fromStringz(segname) machO_fileOrigin = machO._fileOrigin sectVals = peekStructs(machO.file, sectStruct, count=nsects) # get all section headers sectionsList = (Section.createSection(i) for i in sectVals ) # convert all headers into Section objects sections = DataTable('className', 'sectname', 'ftype') for s in sectionsList: if s.offset < machO_fileOrigin: s.offset += machO_fileOrigin sections.append(s, className=type(s).__name__, sectname=s.sectname, ftype=s.ftype) self.sections = sections self._hasAnalyzedSections = False self._shouldImportMappings = machO.mappings.mutable
def __analyze(self): magic_string = peekFixedLengthString(self.file, 15, position=0) (magic, archname) = magic_string.split() if magic != 'dyld_v1': raise MachOError('Invalid magic "{0}"'.format(magic_string)) self.arch = Arch(archname) if self.endian is None: self.endian = self.arch.endian if self.endian is None: raise MachOError( 'Cannot guess endian from architecture "{0}"'.format( archname)) (mappingOffset, mappingCount, imagesOffset, imagesCount, self.dyldBaseAddress) = \ peekStruct(self.file, Struct(self.endian + '4LQ'), position=16) self.mappings = MappingSet( self.__analyzeMappings(mappingOffset, mappingCount)) self.mappings.freeze() images = DataTable('!address', '!name', '!path') for image in self.__analyzeImages(imagesOffset, imagesCount): path = image.path bn = basename(path) while True: (stem, ext) = splitext(bn) if not ext: break bn = stem images.append(image, address=image.address, name=bn, path=path) self.images = images
def __analyze(self): magic_string = peekFixedLengthString(self.file, 15, position=0) (magic, archname) = magic_string.split() if magic != 'dyld_v1': raise MachOError('Invalid magic "{0}"'.format(magic_string)) self.arch = Arch(archname) if self.endian is None: self.endian = self.arch.endian if self.endian is None: raise MachOError('Cannot guess endian from architecture "{0}"'.format(archname)) (mappingOffset, mappingCount, imagesOffset, imagesCount, self.dyldBaseAddress) = \ peekStruct(self.file, Struct(self.endian + '4LQ'), position=16) self.mappings = MappingSet(self.__analyzeMappings(mappingOffset, mappingCount)) self.mappings.freeze() images = DataTable('!address', '!name', '!path') for image in self.__analyzeImages(imagesOffset, imagesCount): path = image.path bn = basename(path) while True: (stem, ext) = splitext(bn) if not ext: break bn = stem images.append(image, address=image.address, name=bn, path=path) self.images = images
def analyzeClassList(machO, addressesAndClassTuples, protocols): """Analyze a list of classes, and return a :class:`~data_table.DataTable` of :class:`~objc.class_.Class`\\s with the following column names: * ``'name'`` (unique, string, the name of the class) * ``'addr'`` (unique, integer, the VM address to the class) The parameter *addressesAndClassTuples* should be an iteratable of 2-tuples, which include the VM address of the class, and a 12-tuple representing an ``old_class`` struct. """ classes = DataTable('!name', '!addr') supers = [] for vmaddr, classTuple in addressesAndClassTuples: (cls, superPtr) = analyzeClass(machO, classTuple, protocols) supers.append(superPtr) classes.append(cls, name=cls.name, addr=vmaddr) for cls, superPtr in zip(classes, supers): if superPtr: supcls = classAt(machO, superPtr, classes) cls.superClass = classAt(machO, superPtr, classes) return classes
def readCategoryList(machO, addresses, classes, protoRefsMap): """Read categories from an iterable of *addresses*, and return a :class:`~data_table.DataTable` of :class:`~objc.category.Category`\\s with the following column names: * ``'name'`` (string, the name of the category) * ``'base'`` (string, the name of the class the category is patching) """ cats = DataTable('name', 'base') for vmaddr in addresses: cat = readCategory(machO, vmaddr, classes, protoRefsMap) cats.append(cat, name=cat.name, base=cat.class_.name) return cats
def analyzeProtocolList(machO, addressesAndProtoTuples): """Analyze a list of protocols, and return a :class:`~data_table.DataTable` of :class:`~objc.protocol.Protocol`\\s with the following column names: * ``'name'`` (string, the name of the protocol) * ``'addr'`` (unique, integer, the VM address to the protocol) The parameter *addressesAndProtoTuples* should be an iteratable of 2-tuples, which include the VM address of the protocol, and a 5-tuple representing an ``old_protocol`` struct. """ # associate each unique protocol to a list of vmaddrs. protoDict = {} protoListDict = {} for vmaddr, protoTuple in addressesAndProtoTuples: (preped, protoListPtr) = _prepareProtocol(machO, protoTuple) if preped in protoDict: protoDict[preped].append(vmaddr) else: protoDict[preped] = [vmaddr] if protoListPtr: if preped in protoListDict: protoListDict[preped].append(protoListPtr) else: protoListDict[preped] = [protoListPtr] # now do the actual analysis. protos = DataTable('name', '!addr') # there can be multiple protocols with the same name in ABI 1.0 refs = [] d = machO.derefString analyzer = methodDescriptionAnalyzer(d) for preped, vmaddrs in protoDict.items(): protoListPtrs = protoListDict[preped] if preped in protoListDict else [] (proto, protoRefs) = _analyzeProtocol(machO, d, analyzer, preped, protoListPtrs) protos.append(proto, name=proto.name) protos.associate(proto, 'addr', vmaddrs) refs.append(protoRefs) # connect the protocols. for proto, protocolRefs in zip(protos, refs): connectProtocol(proto, protocolRefs, protos) return protos
def analyzeCategoryList(machO, catTuples, classes, protocols): """Analyze a list of classes, and return a :class:`~data_table.DataTable` of :class:`~objc.class_.Class`\\s with the following column names: * ``'name'`` (string, the name of the category) * ``'base'`` (string, the name of the class the category is patching) The parameter *catTuples* should be an iteratable of 7-tuples representing the ``old_category`` structs. """ cats = DataTable('name', 'base') for catTuple in catTuples: cat = analyzeCategory(machO, catTuple, classes, protocols) cats.append(cat, name=cat.name, base=cat.class_.name) return cats
def _loadSections(self, machO): segStruct = machO.makeStruct('16s4^2i2L') sectStruct = machO.makeStruct(Section.STRUCT_FORMAT) (segname, self.vmaddr, self._vmsize, self._fileoff, self._filesize, self.maxprot, self.initprot, nsects, _) = readStruct(machO.file, segStruct) self.segname = fromStringz(segname) machO_fileOrigin = machO._fileOrigin sectVals = peekStructs(machO.file, sectStruct, count=nsects) # get all section headers sectionsList = (Section.createSection(i) for i in sectVals) # convert all headers into Section objects sections = DataTable('className', 'sectname', 'ftype') for s in sectionsList: if s.offset < machO_fileOrigin: s.offset += machO_fileOrigin sections.append(s, className=type(s).__name__, sectname=s.sectname, ftype=s.ftype) self.sections = sections self._hasAnalyzedSections = False self._shouldImportMappings = machO.mappings.mutable
def readProtocolList(machO, addresses): """Read protocols from an iterable of *addresses*, and return a :class:`~data_table.DataTable` of :class:`~objc.protocol.Protocol`\\s with the following column names: * ``'name'`` (unique, string, the name of the protocol) * ``'addr'`` (unique, integer, the VM address to the protocol) """ # read protocols from the Mach-O binary. protos = DataTable('!name', '!addr') refs = [] for vmaddr in addresses: (proto, protocolRefs) = readProtocol(machO, vmaddr) protos.append(proto, name=proto.name, addr=vmaddr) refs.append(protocolRefs) # connect the protocols. for proto, protocolRefs in zip(protos, refs): connectProtocol(proto, protocolRefs, protos) return protos
def readClassList(machO, addresses, protoRefsMap): """Read classes from an iterable of *addresses*, and return a :class:`~data_table.DataTable` of :class:`~objc.class_.Class`\\s with the following column names: * ``'name'`` (unique, string, the name of the class) * ``'addr'`` (unique, integer, the VM address to the class) """ classes = DataTable('!name', '!addr') supers = [] for vmaddr in addresses: (cls, superPtr) = readClass(machO, vmaddr, protoRefsMap) supers.append(superPtr) classes.append(cls, name=cls.name, addr=vmaddr) for cls, superPtr in zip(classes, supers): if not cls.isRoot: cls.superClass = classAt(machO, superPtr, classes) return classes