private void processDylibs(SplitDyldCache splitDyldCache, DyldCacheHeader dyldCacheHeader,
			ByteProvider bp, boolean localSymbolsPresent) throws Exception {
		// Create an "info" object for each DyldCache DYLIB, which will make processing them 
		// easier.  Save off the "libobjc" DYLIB for additional processing later.
		monitor.setMessage("Parsing DYLIB's...");
		DyldCacheMachoInfo libobjcInfo = null;
		TreeSet<DyldCacheMachoInfo> infoSet =
			new TreeSet<>((a, b) -> a.headerAddr.compareTo(b.headerAddr));
		List<DyldCacheImage> mappedImages = dyldCacheHeader.getMappedImages();
		monitor.initialize(mappedImages.size());
		for (DyldCacheImage mappedImage : mappedImages) {
			monitor.checkCancelled();
			monitor.incrementProgress(1);
			DyldCacheMachoInfo info = new DyldCacheMachoInfo(splitDyldCache, bp,
				mappedImage.getAddress() - dyldCacheHeader.getBaseAddress(),
				space.getAddress(mappedImage.getAddress()), mappedImage.getPath());
			infoSet.add(info);
			if (libobjcInfo == null && info.name.contains("libobjc.")) {
				libobjcInfo = info;
			}
		}
		
		// Markup DyldCache DYLIB headers 
		monitor.setMessage("Marking up DYLIB headers...");
		monitor.initialize(infoSet.size());
		for (DyldCacheMachoInfo info : infoSet) {
			monitor.checkCancelled();
			monitor.incrementProgress(1);
			info.markupHeaders();
		}

		// Add DyldCache Mach-O's to program tree
		monitor.setMessage("Adding DYLIB's to program tree...");
		monitor.initialize(infoSet.size());
		for (DyldCacheMachoInfo info : infoSet) {
			monitor.checkCancelled();
			monitor.incrementProgress(1);
			info.addToProgramTree();
		}

		// Process DyldCache DYLIB memory blocks
		if (options.processDylibMemory()) {
			monitor.setMessage("Processing DYLIB memory blocks...");
			monitor.initialize(infoSet.size());
			for (DyldCacheMachoInfo info : infoSet) {
				monitor.checkCancelled();
				monitor.incrementProgress(1);
				info.processMemoryBlocks();
			}

		}

		// Markup DyldCache DYLIB load command data
		if (options.markupDylibLoadCommandData()) {
			monitor.setMessage("Marking up DYLIB load command data...");
			monitor.initialize(infoSet.size());
			for (DyldCacheMachoInfo info : infoSet) {
				monitor.checkCancelled();
				monitor.incrementProgress(1);
				info.markupLoadCommandData();
			}
		}

		// Create DYLIB symbols 
		if (options.processDylibSymbols()) {
			monitor.setMessage("Creating DYLIB symbols...");
			monitor.initialize(infoSet.size());
			for (DyldCacheMachoInfo info : infoSet) {
				info.createSymbols(false);
				monitor.checkCancelled();
				monitor.incrementProgress(1);
			}
		}

		// Create DYLIB Exports
		if (options.processDylibExports()) {
			monitor.setMessage("Creating DYLIB exports...");
			monitor.initialize(infoSet.size());
			for (DyldCacheMachoInfo info : infoSet) {
				info.createExports();
				monitor.checkCancelled();
				monitor.incrementProgress(1);
			}
		}

		// Process and markup the libobjc DYLIB
		if (options.processLibobjc()) {
			monitor.setMessage("Processing libobjc...");
			DyldCacheMachoInfo libObjcInfo =
				infoSet.stream().filter(e -> e.name.contains("libobjc.")).findAny().orElse(null);
			if (libObjcInfo != null) {
				LibObjcDylib libObjcDylib =
					new LibObjcDylib(libObjcInfo.header, program, space, log, monitor);
				libObjcDylib.markup();
			}
		}
	}
Processes the DYLD Cache's DYLIB files.  This will mark up the DYLIB files, added them to the
program tree, and make memory blocks for them.

@param dyldCacheHeader The {@link DyldCacheHeader}
@param bp The corresponding {@link ByteProvider}
@param localSymbolsPresent True if DYLD local symbols are present; otherwise, false
@throws Exception if there was a problem processing the DYLIB files
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DyldCacheProgramBuilder.java