From ad00d5734f82266e7d58624a36075da33d8e3005 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 23 Dec 2025 19:04:43 -0500 Subject: [PATCH] GP-3960: ElfLoader can now recognize Swift and golang --- .../app/util/bin/format/elf/ElfHeader.java | 2 +- .../ghidra/app/util/opinion/ElfLoader.java | 36 ++++++++++++++++--- .../ghidra/app/util/opinion/MachoLoader.java | 2 +- .../AARCH64/data/languages/AARCH64.ldefs | 1 + .../AARCH64/data/languages/AARCH64.opinion | 6 ++++ .../Processors/x86/data/languages/x86.opinion | 6 ++++ 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java index c89f5e4fd5..edb1b94bc7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java @@ -1070,7 +1070,7 @@ public class ElfHeader implements StructConverter { return offset >= 0 && (offset + length) <= provider.length(); } - protected void parseSectionHeaders() throws IOException { + public void parseSectionHeaders() throws IOException { if (reader == null) { throw new IOException("ELF binary reader is null!"); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java index 2579889e11..c282272ef6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java @@ -20,8 +20,10 @@ import java.util.*; import ghidra.app.util.Option; import ghidra.app.util.bin.ByteProvider; -import ghidra.app.util.bin.format.elf.ElfException; -import ghidra.app.util.bin.format.elf.ElfHeader; +import ghidra.app.util.bin.format.elf.*; +import ghidra.app.util.bin.format.golang.GoConstants; +import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper; +import ghidra.app.util.bin.format.swift.SwiftUtils; import ghidra.framework.model.DomainObject; import ghidra.framework.model.ProjectData; import ghidra.framework.options.Options; @@ -102,8 +104,13 @@ public class ElfLoader extends AbstractLibrarySupportLoader { try { ElfHeader elf = new ElfHeader(provider, null); - List results = - QueryOpinionService.query(getName(), elf.getMachineName(), elf.getFlags()); + Set results = new HashSet<>(); + String machine = elf.getMachineName(); + String compiler = detectCompilerName(elf); + if (compiler != null) { + results.addAll(QueryOpinionService.query(getName(), machine, compiler)); + } + results.addAll(QueryOpinionService.query(getName(), machine, elf.getFlags())); for (QueryResult result : results) { boolean add = true; // Some languages are defined with sizes smaller than 32 @@ -170,4 +177,25 @@ public class ElfLoader extends AbstractLibrarySupportLoader { public String getName() { return ELF_NAME; } + + /** + * Attempts to detect a more specific compiler from the ELF + * + * @param elf The {@link ElfHeader} + * @return The detected compiler name, or {@code null} if one couldn't be detected + * @throws IOException if an IO-related error occurred + */ + private String detectCompilerName(ElfHeader elf) throws IOException { + elf.parseSectionHeaders(); + List sectionNames = Arrays.stream(elf.getSections()) + .map(ElfSectionHeader::getNameAsString) + .toList(); + if (SwiftUtils.isSwift(sectionNames)) { + return SwiftUtils.SWIFT_COMPILER; + } + if (GoRttiMapper.hasGolangSections(sectionNames)) { + return GoConstants.GOLANG_CSPEC_NAME; + } + return null; + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java index 85e61f7c23..c0c235403f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java @@ -531,7 +531,7 @@ public class MachoLoader extends AbstractLibrarySupportLoader { * Attempts to detect a more specific compiler from the Mach-O * * @param machHeader The {@link MachHeader} - * @return The detected compiler name, or {@code null} if one could be detected + * @return The detected compiler name, or {@code null} if one couldn't be detected * @throws IOException if an IO-related error occurred */ private String detectCompilerName(MachHeader machHeader) throws IOException { diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs b/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs index 58bb44108b..633ec3d451 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs @@ -13,6 +13,7 @@ + diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64.opinion b/Ghidra/Processors/AARCH64/data/languages/AARCH64.opinion index 6d1300072f..2655181d5e 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64.opinion +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64.opinion @@ -5,6 +5,12 @@ + + + + + + diff --git a/Ghidra/Processors/x86/data/languages/x86.opinion b/Ghidra/Processors/x86/data/languages/x86.opinion index c086a56d69..4e5fc7a331 100644 --- a/Ghidra/Processors/x86/data/languages/x86.opinion +++ b/Ghidra/Processors/x86/data/languages/x86.opinion @@ -42,6 +42,12 @@ + + + + + +