private void evaluateElfSymbol(ElfSymbol elfSymbol, Address address, boolean isFakeExternal)
			throws InvalidInputException {

		// allow extension to either modify symbol address or fully handle it
		if (address.isMemoryAddress()) {
			address =
				elf.getLoadAdapter().evaluateElfSymbol(this, elfSymbol, address, isFakeExternal);
		}
		if (address != null) {

			// Remember where in memory Elf symbols have been mapped
			setElfSymbolAddress(elfSymbol, address);

			if (elfSymbol.isSection()) {
				// Do not add section symbols to program symbol table
				return;
			}

			String name = elfSymbol.getNameAsString();
			if (StringUtils.isBlank(name)) {
				return;
			}

			if (address.isConstantAddress()) {
				// Do not add constant symbols to program symbol table
				// define as equate instead
				try {
					program.getEquateTable().createEquate(name, address.getOffset());
				}
				catch (DuplicateNameException | InvalidInputException e) {
					// ignore
				}
				return;
			}

			try {
				boolean isPrimary = (elfSymbol.getType() == ElfSymbol.STT_FUNC) ||
					(elfSymbol.getType() == ElfSymbol.STT_OBJECT) || (elfSymbol.getSize() != 0);
				// don't displace existing primary unless symbol is a function or object symbol
				if (name.contains("@")) {
					isPrimary = false; // do not make version symbol primary
				}
				else if (!isPrimary && (elfSymbol.isGlobal() || elfSymbol.isWeak())) {
					Symbol existingSym = program.getSymbolTable().getPrimarySymbol(address);
					isPrimary = (existingSym == null);
				}

				if (SymbolUtilities.containsInvalidChars(name)) {
					String escapedName = getEscapedSymbolName(name);
					log("Unsupported symbol name has been escaped: \"" + escapedName + "\"");
					name = escapedName;
				}

				createSymbol(address, name, isPrimary, elfSymbol.isAbsolute(), null);

				// NOTE: treat weak symbols as global so that other programs may link to them.
				// In the future, we may want additional symbol flags to denote the distinction
				if ((elfSymbol.isGlobal() || elfSymbol.isWeak()) && !isFakeExternal) {
					program.getSymbolTable().addExternalEntryPoint(address);
				}

				if (elfSymbol.getType() == ElfSymbol.STT_FUNC) {
					Function existingFunction = program.getFunctionManager().getFunctionAt(address);
					if (existingFunction == null) {
						Function f = createOneByteFunction(null, address, false);
						if (f != null) {
							if (isFakeExternal && !f.isThunk()) {
								ExternalLocation extLoc = program.getExternalManager()
										.addExtFunction(Library.UNKNOWN, name, null,
											SourceType.IMPORTED);
								f.setThunkedFunction(extLoc.getFunction());
								// revert thunk function symbol to default source
								Symbol s = f.getSymbol();
								if (s.getSource() != SourceType.DEFAULT) {
									program.getSymbolTable().removeSymbolSpecial(f.getSymbol());
								}
							}
						}
					}
				}
			}
			catch (DuplicateNameException e) {
				throw new RuntimeException("Unexpected Exception", e);
			}
		}
	}
Find a specific named symbol within the fake EXTERNAL block.
NOTE: It is assumed that ELF will never produced duplicate names.
@param name symbol name
@param extMin EXTERNAL block minimum address
@param extMax EXTERNAL block maximum address
@return matching symbol or null if not found
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java