private void parseDynamicRelocTable(ArrayList<ElfRelocationTable> relocationTableList,
			ElfDynamicType relocTableAddrType, ElfDynamicType relocEntrySizeType,
			ElfDynamicType relocTableSizeType, boolean addendTypeReloc) throws IOException {

		if (dynamicTable == null) {
			return;
		}

		try {

			// NOTE: Dynamic and Relocation tables are loaded into memory, however,
			// we construct them without loading so we must map memory addresses 
			// back to file offsets.

			long relocTableAddr =
				adjustAddressForPrelink(dynamicTable.getDynamicValue(relocTableAddrType));

			ElfSectionHeader relocTableSectionHeader =
				getSectionLoadHeaderContaining(relocTableAddr);
			if (relocTableSectionHeader != null) {
				parseSectionBasedRelocationTable(relocTableSectionHeader, relocationTableList);
				return;
			}

			ElfProgramHeader relocTableLoadHeader = getProgramLoadHeaderContaining(relocTableAddr);
			if (relocTableLoadHeader == null) {
				errorConsumer.accept("Failed to locate " + relocTableAddrType.name +
					" in memory at 0x" + Long.toHexString(relocTableAddr));
				return;
			}
			if (relocTableLoadHeader.isInvalidOffset()) {
				return;
			}

			long relocTableOffset = relocTableLoadHeader.getOffset(relocTableAddr);
			for (ElfRelocationTable relocTable : relocationTableList) {
				if (relocTable.getFileOffset() == relocTableOffset) {
					return; // skip reloc table previously parsed
				}
			}
			long tableEntrySize =
				relocEntrySizeType != null ? dynamicTable.getDynamicValue(relocEntrySizeType) : -1;
			long tableSize = dynamicTable.getDynamicValue(relocTableSizeType);

			ElfRelocationTable.TableFormat format = TableFormat.DEFAULT;
			if (relocTableAddrType == ElfDynamicType.DT_ANDROID_REL ||
				relocTableAddrType == ElfDynamicType.DT_ANDROID_RELA) {
				format = TableFormat.ANDROID;
			}
			else if (relocTableAddrType == ElfDynamicType.DT_RELR ||
				relocTableAddrType == ElfDynamicType.DT_ANDROID_RELR) {
				format = TableFormat.RELR;
			}

			ElfRelocationTable relocTable =
				new ElfRelocationTable(reader, this, null, relocTableOffset, relocTableAddr,
					tableSize, tableEntrySize, addendTypeReloc, dynamicSymbolTable, null, format);
			relocationTableList.add(relocTable);
		}
		catch (NotFoundException e) {
			// ignore - skip (required dynamic table value is missing)
		}
	}
Unadjust address offset for certain pre-linked binaries which do not adjust certain
header fields (e.g., dynamic table address entries).  This may be needed when updating
a header address field which requires pre-link adjustment.
@param address prelink-adjusted address offset
@return address with appropriate pre-link adjustment subtracted
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java