private boolean relocateV2(Address pdwListBeginAddr, int entryCount, MessageLog log,
			TaskMonitor monitor) throws CancelledException {

		Listing listing = program.getListing();
		Data d = listing.getDefinedDataAt(pdwListBeginAddr);
		if (d != null && (d.isArray() || d.isStructure())) {
			return false; // silent - appears to have been previously processed
		}

		AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
		Memory memory = program.getMemory();
		DataTypeManager dtm = program.getDataTypeManager();
		RelocationTable relocationTable = program.getRelocationTable();

		// Determine number of unique IAT symbol locations referenced
		Address addr = pdwListBeginAddr;
		MemoryBufferImpl buf = new MemoryBufferImpl(memory, addr);
		HashSet<Address> uniqueIATAddressSet = new HashSet<>();
		for (int i = 0; i < entryCount; i++) {
			monitor.checkCancelled();
			Address iatSymbolAddr = getDWAddress(buf);
			if (iatSymbolAddr == null) {
				log.appendMsg("Failed to read Mingw pseudo-relocation symbol RVA at: " + addr);
				return false;
			}
			uniqueIATAddressSet.add(iatSymbolAddr);
			addr = addr.add(NEW_STYLE_ENTRY_HEADER_SIZE);
			buf.setPosition(addr);
		}

		// Allocate EXTERNAL block
		int extBlockSize = uniqueIATAddressSet.size() * pointerSize;
		Address extBlockStart;
		try {
			extBlockStart = allocateBlock(MemoryBlock.EXTERNAL_BLOCK_NAME, extBlockSize);
		}
		catch (Exception e) {
			String msg = "Failed to allocate EXTERNAL block for MinGW relocation processing";
			log.appendMsg(msg);
			Msg.error(this, msg, e);
			return false;
		}
		ExternalIATSymbolMap extIATSymbolMap = new ExternalIATSymbolMap(extBlockStart);

		// relocation result counters
		int applied = 0;
		int failed = 0;
		int unsupported = 0;

		// Process relocations
		addr = pdwListBeginAddr; // 1st dword of item is symbol address
		buf.setPosition(addr);
		for (int i = 0; i < entryCount; i++) {
			monitor.checkCancelled();

			Address iatSymbolAddr = getDWAddress(buf);

			addr = addr.add(4); // 2nd dword of item is target address
			buf.setPosition(addr);
			Address targetAddr = getDWAddress(buf);
			if (targetAddr == null) {
				log.appendMsg("Failed to read Mingw pseudo-relocation target RVA at: " + addr);
				return false;
			}

			addr = addr.add(4); // 3rd dword of item is flags (treated as bit-length)
			buf.setPosition(addr);

			String symbolName = null;
			RelocationResult result;
			try {

				// read item flags as bit-length
				int bitLength = buf.getInt(0) & 0xff;

				ExternalIATSymbol extSymbolEntry =
					extIATSymbolMap.allocateIATEntry(iatSymbolAddr, relocationTable);
				if (extSymbolEntry == null) {
					throw new UnsupportedOperationException();
				}

				symbolName = extSymbolEntry.extLoc.getOriginalImportedName();
				if (symbolName == null) {
					symbolName = extSymbolEntry.extLoc.getSymbol().getName();
				}

				// compute relocation symbol offset value
				long impValue = pointerSize == 8 ? memory.getLong(iatSymbolAddr)
						: Integer.toUnsignedLong(memory.getInt(iatSymbolAddr));
				Address pointerValue = space.getAddress(impValue);

				long qwOffset = pointerValue.subtract(iatSymbolAddr);
				long addend = 0;

				result = new RelocationResult(Status.APPLIED_OTHER, bitLength / 8); // treat flags as bit length
				switch (bitLength) {
					case 8:
						byte val8 = (byte) (memory.getByte(targetAddr) + qwOffset);
						memory.setByte(targetAddr, val8);
						++applied;
						break;
					case 16:
						short val16 = (short) (memory.getShort(targetAddr) + qwOffset);
						memory.setShort(targetAddr, val16);
						++applied;
						break;
					case 32:
						int val32 = memory.getInt(targetAddr);
						if (pointerSize == 4) {
							addend = (val32 - (int) iatSymbolAddr.getOffset());
						}
						val32 += qwOffset;
						memory.setInt(targetAddr, val32);
						++applied;
						break;
					case 64:
						long val64 = memory.getLong(targetAddr);
						if (pointerSize == 8) {
							addend = val64 - iatSymbolAddr.getOffset();
						}
						val64 += qwOffset;
						memory.setLong(targetAddr, val64);
						++applied;
						break;
					default:
						result = RelocationResult.UNSUPPORTED;
						++unsupported;
				}

				if (addend != 0) {
					ElfRelocationHandler.warnExternalOffsetRelocation(program, targetAddr,
						pointerValue, symbolName, addend, null);
					if (!memory.getBlock(targetAddr).isExecute()) {
						// assume pointer if not in execute block
						ElfRelocationHandler.applyComponentOffsetPointer(program, targetAddr,
							addend);
					}
				}
			}
			catch (MemoryAccessException | UnsupportedOperationException
					| CodeUnitInsertionException e) {
				markAsError(targetAddr, symbolName, e.getMessage(), log);
				result = RelocationResult.FAILURE;
				++failed;
			}

			relocationTable.add(targetAddr, result.status(), 0, null, result.byteLength(),
				symbolName);

			addr = addr.add(4);
			buf.setPosition(addr); // position on next element
		}

		if (failed != 0 || unsupported != 0) {
			log.appendMsg("MinGW pseudo-relocations - applied:" + applied + " failed:" + failed +
				" unsupported:" + unsupported);
		}

		Structure relocEntryStruct = new StructureDataType(V2_RELOC_ITEM_STRUCT_NAME, 0, dtm);
		relocEntryStruct.setPackingEnabled(true);
		relocEntryStruct.add(dwAddressDataType, "sym", null);
		relocEntryStruct.add(DWordDataType.dataType, "target", null); // could be offcut
		relocEntryStruct.add(DWordDataType.dataType, "flags", null);

		Array a = new ArrayDataType(relocEntryStruct, entryCount, -1, dtm);

		try {
			DataUtilities.createData(program, pdwListBeginAddr, a, -1, false,
				ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
		}
		catch (CodeUnitInsertionException e) {
			log.appendMsg("Failed to markup Mingw pseudo-relocation List at: " + pdwListBeginAddr);
		}
		return true;
	}
External Import Address List (IAT) Symbol Record
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/MingwRelocationAnalyzer.java