public static OmfFileHeader parse(AbstractOmfRecordFactory factory, TaskMonitor monitor,
			MessageLog log) throws IOException, OmfException {
		OmfRecord record = factory.readNextRecord();
		if (!(record instanceof OmfFileHeader header)) {
			throw new OmfException("Object file does not start with proper header");
		}
		if (!record.validCheckSum()) {
			logRecord("Invalid checksum", record, log);
		}
		header.records.add(header);
		OmfData lastDataBlock = null;

		while (true) {
			record = factory.readNextRecord();
			if (!record.validCheckSum()) {
				logRecord("Invalid checksum", record, log);
			}
			header.records.add(record);

			if (monitor.isCancelled()) {
				break;
			}
			if (record instanceof OmfModuleEnd) {
				break;
			}

			if (record instanceof OmfCommentRecord comment) {
				byte commentClass = comment.getCommentClass();
				if (commentClass == OmfCommentRecord.COMMENT_CLASS_TRANSLATOR) {
					header.translator = comment.getValue();
				}
				else if (commentClass == OmfCommentRecord.COMMENT_CLASS_LIBMOD) {
					header.libModuleName = comment.getValue();
				}
			}
			else if (record instanceof OmfComdefRecord comdef) {
				header.evaluateComdef(comdef);
				header.externsymbols.add(comdef);
			}
			else if (record instanceof OmfComdatExternalSymbol comdat) {
				comdat.loadNames(header.nameList);
				header.externsymbols.add(comdat);
			}
			else if (record instanceof OmfExternalSymbol external) {
				header.externsymbols.add(external);
			}
			else if (record instanceof OmfSymbolRecord symbol) {
				if (symbol.isStatic()) {
					header.localSymbols.add(symbol);
				}
				else {
					header.publicSymbols.add(symbol);
				}
			}
			else if (record instanceof OmfNamesRecord names) {
				names.appendNames(header.nameList); // Keep names, otherwise don't save record
			}
			else if (record instanceof OmfSegmentHeader seghead) {
				header.segments.add(seghead);
			}
			else if (record instanceof OmfGroupRecord group) {
				header.groups.add(group);
			}
			else if (record instanceof OmfFixupRecord fixuprec) {
				fixuprec.setDataBlock(lastDataBlock);
				header.fixup.add(fixuprec);
			}
			else if (record instanceof OmfEnumeratedData enumheader) {
				header.addEnumeratedBlock(enumheader);
				lastDataBlock = enumheader;
			}
			else if (record instanceof OmfIteratedData iterheader) {
				if (iterheader.getSegmentIndex() <= 0 ||
					iterheader.getSegmentIndex() > header.segments.size()) {
					throw new OmfException("Bad segment index on LIDATA");
				}
				OmfSegmentHeader segheader2 = header.segments.get(iterheader.getSegmentIndex() - 1);
				segheader2.addIteratedData(iterheader);
				lastDataBlock = iterheader;
			}
			else if (record instanceof OmfUnsupportedRecord) {
				// TODO: Should we always set lastDataBlock to null?
				if (record.getRecordType() == OmfRecordTypes.COMDAT) {
					lastDataBlock = null;
				}
				logRecord("Unsupported OMF record", record, log);
			}
			else if (record instanceof OmfObsoleteRecord) {
				logRecord("Obsolete OMF record", record, log);
			}
			else if (record instanceof OmfUnknownRecord) {
				logRecord("Unknown OMF record", record, log);
			}
		}
		return header;
	}
Parse the entire object file

@param factory the {@link AbstractOmfRecordFactory}
@param monitor is checked for cancel button
@param log the log
@return the header record as root of object
@throws IOException for problems reading data
@throws OmfException for malformed records
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfFileHeader.java