public List<Address> processChainedFixups(List<String> libraryPaths) throws Exception {
		monitor.setMessage("Fixing up chained pointers...");

		SymbolTable symbolTable = program.getSymbolTable();
		Address imagebase = getMachoBaseAddress();
		List<DyldFixup> fixups = new ArrayList<>();

		// First look for a DyldChainedFixupsCommand
		List<DyldChainedFixupsCommand> loadCommands =
			machoHeader.getLoadCommands(DyldChainedFixupsCommand.class);
		if (!loadCommands.isEmpty()) {
			BinaryReader memReader = new BinaryReader(new MemoryByteProvider(memory, imagebase),
				!memory.isBigEndian());
			for (DyldChainedFixupsCommand loadCommand : loadCommands) {
				monitor.checkCancelled();
				fixups.addAll(loadCommand.getChainedFixups(memReader, imagebase.getOffset(),
					symbolTable, log, monitor));
			}
		}
		else {
			// Didn't find a DyldChainedFixupsCommand, so look for the sections with fixup info
			Section chainStartsSection =
				machoHeader.getSection(SegmentNames.SEG_TEXT, SectionNames.CHAIN_STARTS);
			Section threadStartsSection =
				machoHeader.getSection(SegmentNames.SEG_TEXT, SectionNames.THREAD_STARTS);

			if (chainStartsSection != null && chainStartsSection.getAddress() != 0 &&
				chainStartsSection.getSize() != 0) {
				reader.setPointerIndex(chainStartsSection.getOffset());
				DyldChainedStartsOffsets chainedStartsOffsets =
					new DyldChainedStartsOffsets(reader);
				for (int offset : chainedStartsOffsets.getChainStartOffsets()) {
					monitor.checkCancelled();
					fixups.addAll(DyldChainedFixups.getChainedFixups(reader, null,
						chainedStartsOffsets.getPointerFormat(), offset, 0, 0,
						imagebase.getOffset(), symbolTable, log, monitor));
				}
			}
			else if (threadStartsSection != null && threadStartsSection.getAddress() != 0 &&
				threadStartsSection.getSize() != 0) {
				Address threadSectionStart = space.getAddress(threadStartsSection.getAddress());
				Address threadSectionEnd =
					threadSectionStart.add(threadStartsSection.getSize() - 1);
				long nextOffSize = (memory.getInt(threadSectionStart) & 1) * 4 + 4;
				Address chainHead = threadSectionStart.add(4);
				while (chainHead.compareTo(threadSectionEnd) < 0 && !monitor.isCancelled()) {
					int headStartOffset = memory.getInt(chainHead);
					if (headStartOffset == 0xFFFFFFFF || headStartOffset == 0) {
						break;
					}
					long chainStart = Integer.toUnsignedLong(headStartOffset);
					fixups.addAll(DyldChainedFixups.processPointerChain(reader, chainStart,
						nextOffSize, imagebase.getOffset(), log, monitor));
					chainHead = chainHead.add(4);
				}
			}
		}

		return DyldChainedFixups.fixupChainedPointers(fixups, program, imagebase, libraryPaths,
			log, monitor);
	}
Attempts to discover and set the entry point.
<p>
A program may declare multiple entry points to, for example, confuse static analysis tools.
We will sort the discovered entry points by priorities assigned to each type of load
command, and only use the one with the highest priority.

@param source A name that represents where the memory blocks came from.
@throws Exception If there was a problem discovering or setting the entry point.
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java