public void processDataDirectories(MessageLog log, TaskMonitor monitor) {
		reader.setPointerIndex(startOfDataDirs);

		dataDirectory = new DataDirectory[numberOfRvaAndSizes];
		if (numberOfRvaAndSizes == 0) {
			return;
		}

		int ndata = 0;
		monitor.setMessage("Parsing exports...");
		try {
			dataDirectory[ndata] = new ExportDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(ExportDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing imports...");
		try {
			dataDirectory[ndata] = new ImportDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(ImportDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing resources...");
		try {
			dataDirectory[ndata] = new ResourceDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(ResourceDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing exceptions...");
		try {
			dataDirectory[ndata] = new ExceptionDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(ExceptionDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing security...");
		try {
			dataDirectory[ndata] = new SecurityDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(SecurityDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing relocations...");
		try {
			dataDirectory[ndata] = new BaseRelocationDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(BaseRelocationDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing debug information...");
		try {
			dataDirectory[ndata] = new DebugDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(DebugDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing architecture...");
		try {
			dataDirectory[ndata] = new ArchitectureDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(ArchitectureDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing global pointer...");
		try {
			dataDirectory[ndata] = new GlobalPointerDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(GlobalPointerDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing TLS data...");
		try {
			dataDirectory[ndata] = new TLSDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(GlobalPointerDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing load config data...");
		try {
			dataDirectory[ndata] = new LoadConfigDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(LoadConfigDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing bound imports...");
		try {
			dataDirectory[ndata] = new BoundImportDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(BoundImportDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing import address table...");
		try {
			dataDirectory[ndata] = new ImportAddressTableDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(ImportAddressTableDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing delay imports...");
		try {
			dataDirectory[ndata] = new DelayImportDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(DelayImportDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		monitor.setMessage("Parsing COM descriptors...");
		try {
			dataDirectory[ndata] = new COMDescriptorDataDirectory(ntHeader, reader);
		}
		catch (RuntimeException re) {
			if (PortableExecutable.DEBUG) {
				throw re;
			}
		}
		catch (IOException e) {
			log.appendMsg(COMDescriptorDataDirectory.class.getSimpleName(), e.getMessage());
		}
		if (++ndata == numberOfRvaAndSizes) {
			return;
		}

		dataDirectory[ndata] = null;
	}
This methods tells this optional header to process its data directories.

@param log The log
@param monitor The monitor
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/OptionalHeader.java