private DWARFName getDWARFName(DIEAggregate diea, DWARFName localRootDNI) {

		DWARFName parentDNI = localRootDNI;

		DIEAggregate declParent = diea.getDeclParent();
		if ((declParent != null) && declParent.getTag() != DW_TAG_compile_unit) {
			parentDNI = lookupDNIByOffset(declParent.getOffset());
			if (parentDNI == null) {
				parentDNI = getDWARFName(declParent, localRootDNI);
				if (parentDNI != null) {
					cacheDNIByOffset(declParent.getOffset(), parentDNI);
				}
			}
		}

		DWARFTag tag = diea.getTag();
		String name = getEntryName(diea);

		// Mangled names can occur in linkage attributes or in the regular name attribute.
		if (name != null && name.contains("_Z") /* mangler start seq */ && !name.startsWith(
			"_GLOBAL_") /* compiler generated, don't demangle as they tend to conflict with existing names */) {
			List<String> nestings = ensureSafeNameLengths(DWARFUtil.parseMangledNestings(name));
			if (!nestings.isEmpty()) {
				name = nestings.remove(nestings.size() - 1);
				if (parentDNI == localRootDNI && !nestings.isEmpty()) {
					parentDNI = DWARFName.fromList(localRootDNI, nestings);
				}
			}
		}

		// If namespace info got squashed due to compiler/linker flags, try to
		// dig it up from the mangled linkage info that might be present in our children.
		if (localRootDNI.equals(parentDNI)) {
			List<String> nestings = DWARFUtil.findLinkageNameInChildren(diea.getHeadFragment());
			if (!nestings.isEmpty()) {
				nestings.remove(nestings.size() - 1);
				parentDNI = DWARFName.fromList(localRootDNI, nestings);
			}
		}

		if (name == null) {
			// check to see if there is a single inbound typedef that we can steal its name.
			List<DIEAggregate> referers = getTypeReferers(diea, DW_TAG_typedef);
			if (referers.size() == 1) {
				return getDWARFName(referers.get(0), localRootDNI);
			}
		}

		if (name == null && tag.isStructureType()) {
			String fingerprint = DWARFUtil.getStructLayoutFingerprint(diea);

			// check to see if there are struct member defs that ref this anon type
			// and build a name using the field names
			List<DIEAggregate> referringMembers =
				diea.getProgram().getTypeReferers(diea, DW_TAG_member);

			String referringMemberNames = getReferringMemberFieldNames(referringMembers);
			if (!referringMemberNames.isEmpty()) {
				// this re-homes this anon struct def from the root of the compunit to the
				// structure that is using this anon struct def.
				parentDNI = getName(referringMembers.get(0).getParent());
				referringMemberNames = "_for_" + referringMemberNames;
			}
			name = "anon_" + tag.getContainerTypeName() + "_" + fingerprint + referringMemberNames;
			return parentDNI.createChild(null, name, tag.getSymbolType());
		}

		boolean isAnon = false;
		if (name == null) {
			switch (diea.getTag()) {
				case DW_TAG_base_type:
					name = getAnonBaseTypeName(diea);
					isAnon = true;
					break;
				case DW_TAG_enumeration_type:
					name = getAnonEnumName(diea);
					isAnon = true;
					break;
				case DW_TAG_subroutine_type:
					// unnamed subroutines (C func ptrs)
					// See {@link #isAnonSubroutine(DataType)}
					name = "anon_subr";
					isAnon = true;
					break;
				case DW_TAG_lexical_block: // "lexical_block_1_2_3"
					name = "lexical_block" + getLexicalBlockNameWorker(diea.getHeadFragment());
					break;
				case DW_TAG_formal_parameter:
					name = "param_%d".formatted(diea.getHeadFragment().getPositionInParent());
					isAnon = true;
					break;
				case DW_TAG_subprogram:
				case DW_TAG_inlined_subroutine:
					if (declParent != null && declParent.getTag().isStructureType() &&
						diea.getBool(DW_AT_artificial, false)) {
						name = parentDNI.getName();
					}
					else {
						name = "anon_func";
						isAnon = true;
					}
					break;
				default:
					if (declParent != null && declParent.getTag().isNameSpaceContainer()) {
						name = DWARFUtil.getAnonNameForMeFromParentContext2(diea);
					}
					break;
			}
		}

		// Name was not found
		if (isAnonDWARFName(name)) {
			name = createAnonName("anon_" + tag.getContainerTypeName(), diea);
			isAnon = true;
		}

		String origName = isAnon ? null : name;
		String workingName = ensureSafeNameLength(name);
		workingName = GoSymbolName.fixGolangSpecialSymbolnameChars(workingName);

		if (diea.getCompilationUnit().getLanguage() == DWARFSourceLanguage.DW_LANG_Rust &&
			workingName.startsWith("{impl#") && parentDNI != null) {
			// if matches a Rust {impl#NN} name, skip it and re-use the parent name
			return parentDNI;
		}

		DWARFName result = parentDNI.createChild(origName, workingName, tag.getSymbolType());
		return result;
	}
Reads and indexes available DWARF information.

@param monitor {@link TaskMonitor}
@throws IOException if error reading data
@throws DWARFException if bad or invalid DWARF information
@throws CancelledException if cancelled
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/DWARFProgram.java