private void analyzeFunctionStarts(Program program, MachHeader header, AddressSetView set,
			TaskMonitor monitor) throws IOException, CancelledException {
		FunctionManager functionMgr = program.getFunctionManager();
		Listing listing = program.getListing();
		PseudoDisassembler pdis = new PseudoDisassembler(program);
		Disassembler dis = Disassembler.getDisassembler(program, monitor, null);
		AutoAnalysisManager analysisMgr = AutoAnalysisManager.getAnalysisManager(program);

		// Function start values are offsets from start of text segment
		SegmentCommand textSegment = header.getSegment(SegmentNames.SEG_TEXT);
		if (textSegment == null) {
			return;
		}

		// Determine which function start addresses need a new function created on them
		AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
		Address textSegmentAddr = space.getAddress(textSegment.getVMaddress());
		List<FunctionStartsCommand> commands = header.getLoadCommands(FunctionStartsCommand.class);
		for (FunctionStartsCommand cmd : commands) {
			for (Address addr : cmd.findFunctionStartAddrs(textSegmentAddr)) {
				monitor.checkCancelled();
				if (!set.contains(textSegmentAddr)) {
					continue;
				}

				// Check for conditions to skip creating a function at the function start address
				String skipMessage = null;
				if (listing.getDataAt(addr) != null && !listing.isUndefined(addr, addr)) {
					skipMessage = "Skipped Existing Data"; // possible switch data
				}
				else if (functionMgr.getFunctionAt(addr) != null) {
					skipMessage = "Skipped Existing Function";
				}
				else if (usePseudoDisassembler) {
					try {
						final String UDF = "UDF";
						if (pdis.disassemble(addr).getMnemonicString().equalsIgnoreCase(UDF)) {
							skipMessage = "Skipped \"" + UDF + "\" Instruction";
						}
						else if (!pdis.isValidSubroutine(addr, true, false)) {
							skipMessage = "Skipped Invalid Subroutine";
						}
					}
					catch (Exception e) {
						// ignore
					}
				}
				if (skipMessage != null) {
					if (createBookmarksSkipped) {
						setBookmark(program, addr,  skipMessage);

					}
					continue;
				}

				// Disassemble at the function start address
				AddressSet disassembledSet = dis.disassemble(new AddressSet(addr), null, true);
				analysisMgr.codeDefined(disassembledSet);

				// Create function at the function start address
				CreateFunctionCmd fCommand = new CreateFunctionCmd(addr);
				if (fCommand.applyTo(program, monitor)) {
					if (createBookmarksNew) {
						setBookmark(program, addr, "New Function");

					}
				}
				else {
					// Couldn't create function
					if (createBookmarksFailed) {
						setBookmark(program, addr, "Failed Function");
					}
				}
			}
		}
	}
Finds and creates new functions using the LC_FUNCTION_STARTS load command

@param program The {@link Program}
@param header The {@link MachHeader} that contains the LC_FUNCTION_STARTS load command
@param set The set of addresses to find new functions at
@param monitor A cancellable monitor
@throws CancelledException If the user cancelled
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/MachoFunctionStartsAnalyzer.java