private Address calculateSymbolAddress(ElfSymbol elfSymbol) {

		if (elfSymbol.getSymbolTableIndex() == 0) {
			return null; // always skip the first symbol, it is NULL
		}

		if (elfSymbol.isFile()) {
			return null; //do not create file symbols... (source file list added to program properties)
		}

		if (elfSymbol.isTLS()) {
			// TODO: Investigate support for TLS symbols
			log("Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getFormattedName());
			return null;
		}

		ElfLoadAdapter loadAdapter = elf.getLoadAdapter();

		// Allow extension to have first shot at calculating symbol address
		try {
			Address address = elf.getLoadAdapter().calculateSymbolAddress(this, elfSymbol);
			if (address != null) {
				return address;
			}
		}
		catch (NoValueException e) {
			return null;
		}

		ElfSectionHeader[] elfSections = elf.getSections();
		short sectionIndex = elfSymbol.getSectionHeaderIndex();
		Address symSectionBase = null;
		AddressSpace defaultSpace = getDefaultAddressSpace();
		AddressSpace defaultDataSpace = getDefaultDataSpace();
		AddressSpace symbolSpace = defaultSpace;
		long symOffset = elfSymbol.getValue();

		boolean isAllocatedToSection = false;
		if (sectionIndex == ElfSectionHeaderConstants.SHN_UNDEF) { // Not section relative 0x0000 (e.g., no sections defined)
			Address regAddr = findMemoryRegister(elfSymbol);
			if (regAddr != null) {
				return regAddr;
			}

			// FIXME: No sections defined or refers to external symbol
			// Uncertain what if any offset adjustments should apply, although the
			// EXTERNAL block is affected by the program image base
			symOffset = loadAdapter.getAdjustedMemoryOffset(symOffset, defaultSpace);
			symOffset += getImageBaseWordAdjustmentOffset();
		}
		else if (Short.compareUnsigned(sectionIndex, ElfSectionHeaderConstants.SHN_LORESERVE) < 0 ||
			sectionIndex == ElfSectionHeaderConstants.SHN_XINDEX) {

			isAllocatedToSection = true;
			int uSectionIndex = Short.toUnsignedInt(sectionIndex);

			if (sectionIndex == ElfSectionHeaderConstants.SHN_XINDEX) {
				uSectionIndex = elfSymbol.getExtendedSectionHeaderIndex();
				if (uSectionIndex == 0) {
					log("Failed to read extended symbol section index: " +
						elfSymbol.getFormattedName() + " - value=0x" +
						Long.toHexString(elfSymbol.getValue()));
					return null;
				}
			}

			if (uSectionIndex < elfSections.length) {

				ElfSectionHeader symSection = elf.getSections()[uSectionIndex];
				symSectionBase = findLoadAddress(symSection, 0);
				if (symSectionBase == null) {
					log("Unable to place symbol due to non-loaded section: " +
						elfSymbol.getFormattedName() + " - value=0x" +
						Long.toHexString(elfSymbol.getValue()) + ", section=" +
						symSection.getNameAsString());
					return null;
				}

				symbolSpace = symSectionBase.getAddressSpace();

				Long relOffset = loadAdapter.getSectionSymbolRelativeOffset(symSection,
					symSectionBase, elfSymbol);
				if (relOffset != null) {
					// Section relative symbol - ensure that symbol remains in
					// overlay space even if beyond bounds of associated block
					try {
						return symSectionBase.addNoWrap(
							relOffset * symSectionBase.getAddressSpace().getAddressableUnitSize());
					}
					catch (AddressOverflowException e) {
						log("Unable to place symbol within section (address overflow): " +
							elfSymbol.getFormattedName() + " - value=0x" +
							Long.toHexString(elfSymbol.getValue()) + ", section=" +
							symSection.getNameAsString());
						return null;
					}
				}
			}

			// Unable to place symbol within relocatable if section missing/stripped
			else if (elf.isRelocatable()) {
				log("No Memory for symbol: " + elfSymbol.getFormattedName() + " - 0x" +
					Long.toHexString(elfSymbol.getValue()));
				return null;
			}

			AddressSpace space = symbolSpace.getPhysicalSpace();
			symOffset = loadAdapter.getAdjustedMemoryOffset(symOffset, space);
			if (space == defaultSpace) {
				symOffset =
					elf.adjustAddressForPrelink(symOffset) + getImageBaseWordAdjustmentOffset();
			}
			else if (space == defaultDataSpace) {
				symOffset += getImageDataBase();
			}
		}
		else if (sectionIndex == ElfSectionHeaderConstants.SHN_ABS) { // Absolute value/address - 0xfff1

			// Absolute symbols will be pinned to associated address
			symbolSpace = defaultDataSpace;
			if (elfSymbol.isFunction()) {
				symbolSpace = defaultSpace;
			}
			else {
				Address regAddr = findMemoryRegister(elfSymbol);
				if (regAddr != null) {
					return regAddr;
				}
			}
		}
		else if (sectionIndex == ElfSectionHeaderConstants.SHN_COMMON) { // Common symbols - 0xfff2 (
			return Address.NO_ADDRESS; // assume unallocated/external
		}
		else { // TODO: Identify which cases if any that this is valid

			// SHN_LORESERVE 0xff00
			// SHN_LOPROC 0xff00
			// SHN_HIPROC 0xff1f
			// SHN_HIRESERVE 0xffff

			log("Unable to place symbol: " + elfSymbol.getFormattedName() + " - value=0x" +
				Long.toHexString(elfSymbol.getValue()) + ", section-index=0x" +
				Integer.toHexString(Short.toUnsignedInt(sectionIndex)));
			return null;
		}

		Address address = symbolSpace.getTruncatedAddress(symOffset, true);
		if (symbolSpace.isOverlaySpace() && address.getAddressSpace() != symbolSpace) {
			// Ensure that address remains within correct symbol space
			address = symbolSpace.getAddressInThisSpaceOnly(address.getOffset());
		}

		if (isAllocatedToSection || elfSymbol.isAbsolute()) {
			return address;
		}

		// Identify special cases which should be treated as external (return NO_ADDRESS)

		if (elfSymbol.isExternal()) {
			return Address.NO_ADDRESS;
		}
		else if (!elfSymbol.isSection() && elfSymbol.getValue() == 0) {
			return Address.NO_ADDRESS;
		}
		else if (elfSymbol.getValue() == 1) {
			// Most likely a Thumb Symbol...
			return Address.NO_ADDRESS;
		}

		return address;
	}
Calculate the load address associated with a specified elfSymbol.
@param elfSymbol ELF symbol
@return symbol address or null if symbol not supported and address not determined,
or {@link Address#NO_ADDRESS} if symbol is external and should be allocated to the EXTERNAL block.
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java