private void processRelocationTableEntries(ElfRelocationTable relocationTable,
			ElfRelocationContext<?> context, AddressSpace relocationSpace, long baseWordOffset,
			TaskMonitor monitor) throws CancelledException {

		boolean processRelocations = ElfLoaderOptionsFactory.performRelocations(options);

		context.startRelocationTableProcessing(relocationTable);

		ElfSymbolTable symbolTable = relocationTable.getAssociatedSymbolTable();
		ElfRelocation[] relocs = relocationTable.getRelocations();

		boolean unableToApplyRelocs = relocationTable.isMissingRequiredSymbolTable();
		if (unableToApplyRelocs) {
			ElfSectionHeader tableSectionHeader = relocationTable.getTableSectionHeader();
			String relocTableName =
				tableSectionHeader != null ? tableSectionHeader.getNameAsString() : "dynamic";
			ElfSectionHeader sectionToBeRelocated = relocationTable.getSectionToBeRelocated();
			String relocaBaseName =
				sectionToBeRelocated != null ? sectionToBeRelocated.getNameAsString() : "PT_LOAD";
			log("Unable to apply " + relocTableName + " relocations affecting " + relocaBaseName +
				" due to missing symbol table");
		}

		boolean relrTypeUnknown = false;
		int relrRelocationType = 0;
		if (relocationTable.isRelrTable()) {
			relrRelocationType = context.getRelrRelocationType();
			if (relrRelocationType == 0) {
				relrTypeUnknown = true;
				log("Failed to process RELR relocations - extension does not define RELR type");
			}
		}

		for (ElfRelocation reloc : relocs) {

			monitor.checkCancelled();
			monitor.incrementProgress(1);

			int type = reloc.getType();
			if (type == 0 && !relocationTable.isRelrTable()) {
				continue; // ignore relocation type 0 if not a RELR table (i.e., ..._NONE)
			}

			int symbolIndex = reloc.getSymbolIndex();
			String symbolName = symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : "";
			if (symbolName != null && SymbolUtilities.containsInvalidChars(symbolName)) {
				symbolName = getEscapedSymbolName(symbolName);
			}

			Address baseAddress = relocationSpace.getTruncatedAddress(baseWordOffset, true);

			// relocation offset (r_offset) is defined to be a byte offset (assume byte size is 1)
			Address relocAddr = context.getRelocationAddress(baseAddress, reloc.getOffset());

			long[] values = new long[] { reloc.getSymbolIndex() };

			if (relrRelocationType != 0) {
				type = relrRelocationType;
				reloc.setType(relrRelocationType);
			}

			Status status = Status.SKIPPED;
			int byteLength = 0;
			try {

				if (!processRelocations) {
					continue; // skip and record relocation
				}

				if (unableToApplyRelocs) {
					status = Status.FAILURE;
					context.markRelocationError(relocAddr, type, symbolIndex, symbolName,
						"Missing symbol table");
					continue;
				}

				MemoryBlock relocBlock = memory.getBlock(relocAddr);
				if (relocBlock == null) {
					throw new MemoryAccessException("Block is non-existent");
				}
				if (!relocBlock.isInitialized()) {
					try {
						memory.convertToInitialized(relocBlock, (byte) 0);
					}
					catch (Exception e) {
						status = Status.FAILURE;
						Msg.error(this,
							"Unexpected exception while converting block to initialized for relocations",
							e);
						context.markRelocationError(relocAddr, type, symbolIndex, symbolName,
							"Uninitialized memory");
						continue;
					}
				}

				if (relrTypeUnknown) {
					status = Status.UNSUPPORTED;
					ElfRelocationHandler.bookmarkUnsupportedRelr(program, relocAddr, symbolIndex,
						symbolName);
				}
				else {
					RelocationResult result = context.processRelocation(reloc, relocAddr);
					byteLength = result.byteLength();
					status = result.status();
				}
			}
			catch (MemoryAccessException e) {
				if (type != 0) { // ignore if type 0 which is always NONE (no relocation performed)
					status = Status.FAILURE;
					log("Unable to perform relocation: Type = " + type + " (0x" +
						Long.toHexString(type) + ") at " + relocAddr + " (Symbol = " + symbolName +
						") - " + getMessage(e));
				}
			}
			finally {
				// Save relocation data - uses original FileBytes
				program.getRelocationTable()
						.add(relocAddr, status, reloc.getType(), values, byteLength, symbolName);
			}
		}

		context.endRelocationTableProcessing();
	}
Cases:
1. elf.isRelocatable()
	a) sectionToBeRelocated null (may be NULL section?)
 b) sectionToBeRelocated known - offset relative to section load address

2. !elf.isRelocatable()
 a) sectionToBeRelocated null (may be NULL section?)
 b) sectionToBeRelocated known - offset relative to image base
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java