public static CompilerEnum getOpinion(PortableExecutable pe, ByteProvider provider,
				Program program, TaskMonitor monitor, MessageLog log) throws IOException {

			CompilerEnum offsetChoice = CompilerEnum.Unknown;
			CompilerEnum asmChoice = CompilerEnum.Unknown;
			CompilerEnum errStringChoice = CompilerEnum.Unknown;
			BinaryReader br = new BinaryReader(provider, true);

			DOSHeader dh = pe.getDOSHeader();

			// Check for Rust.  Program object is required, which may be null.
			try {
				if (program != null && RustUtilities.isRust(program,
					program.getMemory().getBlock(".rdata"), monitor)) {
					try {
						int extensionCount = RustUtilities.addExtensions(program, monitor,
							RustConstants.RUST_EXTENSIONS_WINDOWS);
						log.appendMsg("Installed " + extensionCount + " Rust cspec extensions");
					}
					catch (IOException e) {
						log.appendMsg("Rust error: " + e.getMessage());
					}
					return CompilerEnum.Rustc;
				}
			}
			catch (CancelledException e) {
				// Move on
			}

			// Check for Swift
			List<String> sectionNames =
				Arrays.stream(pe.getNTHeader().getFileHeader().getSectionHeaders())
						.map(section -> section.getName())
						.toList();
			if (SwiftUtils.isSwift(sectionNames)) {
				return CompilerEnum.Swift;
			}

			// Check for managed code (.NET)
			if (pe.getNTHeader().getOptionalHeader().isCLI()) {
				return CompilerEnum.CLI;
			}

			// Determine based on PE Header offset
			if (dh.e_lfanew() == 0x80) {
				offsetChoice = CompilerEnum.GCC_VS;
			}
			else if (dh.e_lfanew() == 0x78) {
				offsetChoice = CompilerEnum.Clang;
			}
			else if (dh.e_lfanew() >= 0x80) {

				// Check for "DanS"
				int val1 = br.readInt(0x80);
				int val2 = br.readInt(0x80 + 4);

				if (val1 != 0 && val2 != 0 && (val1 ^ val2) == 0x536e6144 /* "DanS" */) {
					// Rich Image Header is present
					return CompilerEnum.VisualStudio;
				}

				if (dh.e_lfanew() == 0x100) {
					offsetChoice = CompilerEnum.BorlandPascal; // Could also be Borland-C
				}
				else if (dh.e_lfanew() == 0x200) {
					offsetChoice = CompilerEnum.BorlandCpp;
				}
				else if (dh.e_lfanew() > 0x300) {
					return CompilerEnum.Unknown;
				}
			} // End PE header offset check

			byte[] asm = provider.readBytes(0x40, 256);
			asmChoice = CompilerEnum.Unknown;
			if (Arrays.compare(asm, 0, asm16_Borland.length, asm16_Borland, 0,
				asm16_Borland.length) == 0) {
				asmChoice = CompilerEnum.BorlandUnk;
			}
			else if (Arrays.compare(asm, 0, asm16_GCC_VS_Clang.length, asm16_GCC_VS_Clang, 0,
				asm16_GCC_VS_Clang.length) == 0) {
				asmChoice = CompilerEnum.GCC_VS_Clang;
			}

			// Check for error message
			int errStringOffset = Bytes.indexOf(asm, THIS_BYTES);
			if (errStringOffset == -1) {
				asmChoice = CompilerEnum.Unknown;
			}
			else {
				if (compareBytesToChars(asm, errStringOffset, errString_borland)) {
					if (offsetChoice == CompilerEnum.BorlandCpp ||
						offsetChoice == CompilerEnum.BorlandPascal) {
						return offsetChoice;
					}
					errStringChoice = CompilerEnum.BorlandUnk;
				}
				else if (compareBytesToChars(asm, errStringOffset, errString_GCC_VS)) {
					errStringChoice = CompilerEnum.GCC_VS;
				}
				else if (compareBytesToChars(asm, errStringOffset, errString_Clang)) {
					errStringChoice = CompilerEnum.Clang;
				}
				else {
					errStringChoice = CompilerEnum.Unknown;
				}
			}

			// Check for AddressOfStart and PointerToSymbol
			if (errStringChoice == CompilerEnum.GCC_VS && asmChoice == CompilerEnum.GCC_VS_Clang &&
				dh.e_lfanew() == 0x80) {
				// Trying to determine if we have gcc or old VS

				// Look for the "Visual Studio" library identifier
//				if (mem.findBytes(mem.getMinAddress(), "Visual Studio".getBytes(),
//						null, true, monitor) != null) {
//					return CompilerEnum.VisualStudio
//				}

				if (isGolang(pe, provider)) {
					return CompilerEnum.GOLANG;
				}

				// Now look for PointerToSymbols (0 for VS, non-zero for gcc)
				int ptrSymTable = br.readInt(dh.e_lfanew() + 12);
				if (ptrSymTable != 0) {
					return CompilerEnum.GCC;
				}
			}
			else if ((offsetChoice == CompilerEnum.Clang ||
				errStringChoice == CompilerEnum.Clang) && asmChoice == CompilerEnum.GCC_VS_Clang) {
				return CompilerEnum.Clang;
			}
			else if (errStringChoice == CompilerEnum.Unknown || asmChoice == CompilerEnum.Unknown) {
				return CompilerEnum.Unknown;
			}

			if (errStringChoice == CompilerEnum.BorlandUnk ||
				asmChoice == CompilerEnum.BorlandUnk) {
				// Pretty sure it's Borland, but didn't get 0x100 or 0x200
				return CompilerEnum.BorlandUnk;
			}

//			if ((offsetChoice == CompilerEnum.GCC_VS) || (errStringChoice == CompilerEnum.GCC_VS)) {
//				// Pretty sure it's either gcc or Visual Studio
//				compilerType = CompilerEnum.GCC_VS;
//				// TODO: nothing feeds off of this state
//			}

			// Reaching this point implies that we did not find "DanS and we didn't
			// see the Borland DOS complaint

			FileHeader fileHeader = pe.getNTHeader().getFileHeader();
			if (fileHeader.getSectionHeader("CODE") != null) {
				// NOTE: Could be Borland-C 
				return CompilerEnum.BorlandPascal;
			}

			if (fileHeader.getSectionHeader(".bss") != null) {
				return CompilerEnum.GCC;
			}

			if (fileHeader.getSectionHeader(".idata") == null) {
				// assume VS if .idata not found
				return CompilerEnum.VisualStudio;
			}

			if (fileHeader.getSectionHeader(".tls") != null) {
				// assume Borland - prefer cpp since CODE segment didn't occur
				return CompilerEnum.BorlandCpp;
			}

			return CompilerEnum.Unknown;
		}
Return true if chararray appears in full, starting at offset bytestart in bytearray

@param bytearray the array of bytes containing the potential match
@param bytestart the potential start of the match
@param chararray the array of characters to match
@return true if there is a full match
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java