public void addSection(MemoryBlock block, OptionalHeader optionalHeader) {
		DataDirectory[] directories = optionalHeader.getDataDirectories();

		DataDirectory[] dataDirectories = optionalHeader.getDataDirectories();

		SecurityDataDirectory sdd = null;
		if (dataDirectories.length > OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY) {
			sdd =
				(SecurityDataDirectory) dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY];
			if (sdd != null && sdd.getSize() > 0) {
				sdd.updatePointers(PortableExecutable.computeAlignment((int) block.getSize(),
					optionalHeader.getFileAlignment()));
			}
		}

		int lastPos = computeAlignedNewPosition(optionalHeader, directories);

		SectionHeader newSection = new SectionHeader(block, optionalHeader, lastPos);

		SectionHeader[] newSectionHeaders = new SectionHeader[sectionHeaders.length + 1];
		System.arraycopy(sectionHeaders, 0, newSectionHeaders, 0, sectionHeaders.length);
		newSectionHeaders[sectionHeaders.length] = newSection;
		setSectionHeaders(newSectionHeaders);

		int firstSectionStart = sectionHeaders[0].getPointerToRawData();
		int lastSectionEnd = sectionHeaders[sectionHeaders.length - 1].getPointerToRawData() +
			sectionHeaders[sectionHeaders.length - 1].getSizeOfRawData();

		for (int i = 0; i < directories.length; i++) {
			if (directories[i] == null || directories[i].getSize() == 0 ||
				directories[i].isContainedInSection()) {
				continue;
			}
			if (directories[i].getVirtualAddress() < firstSectionStart) {
				if (i != OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT) {
					throw new RuntimeException("PE - Unexpected directory before sections: " + i);
				}
			}
			if (directories[i].getVirtualAddress() > lastSectionEnd) {
				if (i != OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY) {
					throw new RuntimeException("PE - Unexpected directory after sections: " + i);
				}
			}
		}

		int offset = 0;

		if (dataDirectories.length > OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT) {
			BoundImportDataDirectory bidd =
				(BoundImportDataDirectory) dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
			if (bidd != null && bidd.getSize() > 0) {
				bidd.updatePointers(SectionHeader.IMAGE_SIZEOF_SECTION_HEADER);
				int endptr = bidd.getVirtualAddress() + bidd.getSize() - 1;
				if (endptr >= sectionHeaders[0].getPointerToRawData()) {
					int alignedPtr = PortableExecutable.computeAlignment(endptr,
						optionalHeader.getFileAlignment());
					offset = alignedPtr - sectionHeaders[0].getPointerToRawData();
					for (SectionHeader sectionHeader : sectionHeaders) {
						sectionHeader.updatePointers(offset);
					}
					//reset the sizeOfHeaders...
					optionalHeader.setSizeOfHeaders(sectionHeaders[0].getPointerToRawData());
				}
			}
		}

		if (dataDirectories.length > OptionalHeader.IMAGE_DIRECTORY_ENTRY_DEBUG) {
			DebugDataDirectory ddd =
				(DebugDataDirectory) dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_DEBUG];
			if (ddd != null && ddd.getSize() > 0) {
				if (ddd.getVirtualAddress() > newSection.getVirtualAddress()) {
					if (sdd != null && sdd.getSize() > 0) {
						ddd.updatePointers(offset, sdd.getVirtualAddress() + sdd.getSize());
					}
					else {
						ddd.updatePointers(offset, newSection.getSizeOfRawData());
					}
				}
			}
		}

		if (block.isExecute()) {
			optionalHeader
					.setSizeOfCode(optionalHeader.getSizeOfCode() + newSection.getSizeOfRawData());
		}
		else {
			optionalHeader.setSizeOfInitializedData(
				optionalHeader.getSizeOfInitializedData() + newSection.getSizeOfRawData());
		}

		int soi = newSection.getVirtualAddress() + newSection.getSizeOfRawData();
		soi = PortableExecutable.computeAlignment(soi, optionalHeader.getSectionAlignment());
		optionalHeader.setSizeOfImage(soi);
	}
Adds a new section to this file header. Uses the given memory block
as the section template. The section will have the memory block's name, start address,
size, etc. The optional header is needed to determine the free byte position in the
file.
@param block the memory block template
@param optionalHeader the related optional header
@throws RuntimeException if the memory block is uninitialized
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java