diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java index 7745852af8..a1232215b8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java @@ -191,4 +191,14 @@ public class ElfSectionHeaderConstants { public static final short SHN_XINDEX = (short) 0xffff; /**upper bound on range of reserved indexes*/ public static final short SHN_HIRESERVE = (short) 0xffff; + + /** + * @param symbolSectionIndex symbol section index (st_shndx) + * @return true if specified symbol section index corresponds to a processor + * specific value in the range SHN_LOPROC..SHN_HIPROC, else false + */ + public static boolean isProcessorSpecificSymbolSectionIndex(short symbolSectionIndex) { + return symbolSectionIndex >= ElfSectionHeaderConstants.SHN_LOPROC && + symbolSectionIndex <= ElfSectionHeaderConstants.SHN_HIPROC; + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java index 1eaa428bca..1d75c2746a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java @@ -312,6 +312,22 @@ public class ElfLoadAdapter { return functionAddress; } + /** + * This method allows an extension to override the default address calculation for loading + * a symbol. This is generally only neccessary when symbol requires handling of processor-specific + * flags or section index. This method should return null when default symbol processing + * is sufficient. {@link Address#NO_ADDRESS} should be returned if the symbol is external + * and is not handled by default processing. + * @param elfLoadHelper load helper object + * @param elfSymbol elf symbol + * @return symbol memory address or null to defer to default implementation + * @throws NoValueException if error logged and address calculation failed + */ + public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol) + throws NoValueException { + return null; + } + /** * During symbol processing this method will be invoked to permit an extension to * adjust the address and/or apply context to the intended symbol location. @@ -487,4 +503,5 @@ public class ElfLoadAdapter { public Class getRelocationClass(ElfHeader elfHeader) { return null; } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 4d273f4e6d..dd30101e28 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -20,7 +20,6 @@ import java.io.InputStream; import java.math.BigInteger; import java.text.NumberFormat; import java.util.*; -import java.util.function.Consumer; import ghidra.app.cmd.label.SetLabelPrimaryCmd; import ghidra.app.util.MemoryBlockUtils; @@ -1232,7 +1231,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { monitor.checkCanceled(); try { - Address address = calculateSymbolAddress(elfSymbol, msg -> log(msg)); + Address address = calculateSymbolAddress(elfSymbol); if (address == null) { continue; } @@ -1280,11 +1279,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { /** * Calculate the load address associated with a specified elfSymbol. * @param elfSymbol ELF symbol - * @param errorConsumer error consumer * @return symbol address or null if symbol not supported and address not determined, - * or NO_ADDRESS if symbol is external and should be allocated to the EXTERNAL block. + * or {@link Address#NO_ADDRESS} if symbol is external and should be allocated to the EXTERNAL block. */ - private Address calculateSymbolAddress(ElfSymbol elfSymbol, Consumer errorConsumer) { + private Address calculateSymbolAddress(ElfSymbol elfSymbol) { if (elfSymbol.getSymbolTableIndex() == 0) { return null; // always skip the first symbol, it is NULL @@ -1296,13 +1294,23 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { if (elfSymbol.isTLS()) { // TODO: Investigate support for TLS symbols - errorConsumer.accept( - "Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getNameAsString()); + log("Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getNameAsString()); 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; @@ -1316,7 +1324,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { ElfSectionHeader symSection = elf.getSections()[sectionIndex]; symSectionBase = findLoadAddress(symSection, 0); if (symSectionBase == null) { - errorConsumer.accept("Unable to place symbol due to non-loaded section: " + + log("Unable to place symbol due to non-loaded section: " + elfSymbol.getNameAsString() + " - value=0x" + Long.toHexString(elfSymbol.getValue()) + ", section=" + symSection.getNameAsString()); @@ -1366,7 +1374,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { // SHN_COMMON 0xfff2 // SHN_HIRESERVE 0xffff - errorConsumer.accept("Unable to place symbol: " + elfSymbol.getNameAsString() + + log("Unable to place symbol: " + elfSymbol.getNameAsString() + " - value=0x" + Long.toHexString(elfSymbol.getValue()) + ", section-index=0x" + Integer.toHexString(sectionIndex & 0xffff)); return null; @@ -1389,12 +1397,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } else if (elf.isRelocatable()) { if (sectionIndex < 0 || sectionIndex >= elfSections.length) { - errorConsumer.accept("Error creating symbol: " + elfSymbol.getNameAsString() + + log("Error creating symbol: " + elfSymbol.getNameAsString() + " - 0x" + Long.toHexString(elfSymbol.getValue())); return Address.NO_ADDRESS; } else if (symSectionBase == null) { - errorConsumer.accept("No Memory for symbol: " + elfSymbol.getNameAsString() + + log("No Memory for symbol: " + elfSymbol.getNameAsString() + " - 0x" + Long.toHexString(elfSymbol.getValue())); return Address.NO_ADDRESS; } diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java index 99c1a8c366..2e33262ce0 100644 --- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java +++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java @@ -34,7 +34,7 @@ import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; public class MIPS_ElfExtension extends ElfExtension { - + private static final String MIPS_STUBS_SECTION_NAME = ".MIPS.stubs"; // GP value reflected by symbol address @@ -287,9 +287,13 @@ public class MIPS_ElfExtension extends ElfExtension { public static final byte ODK_IDENT = 10; public static final byte ODK_PAGESIZE = 11; + // MIPS-specific SHN values + public static final short SHN_MIPS_ACOMMON = (short) 0xff00; + public static final short SHN_MIPS_TEXT = (short) 0xff01; + public static final short SHN_MIPS_DATA = (short) 0xff02; + @Override public boolean canHandle(ElfHeader elf) { - // TODO: Verify 64-bit MIPS support return elf.e_machine() == ElfConstants.EM_MIPS; } @@ -328,6 +332,25 @@ public class MIPS_ElfExtension extends ElfExtension { return functionAddress; } + @Override + public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol) + throws NoValueException { + + short sectionIndex = elfSymbol.getSectionHeaderIndex(); + if (!ElfSectionHeaderConstants.isProcessorSpecificSymbolSectionIndex(sectionIndex)) { + return null; + } + + if (sectionIndex == SHN_MIPS_ACOMMON || sectionIndex == SHN_MIPS_TEXT || sectionIndex == SHN_MIPS_DATA) { + // NOTE: logic assumes no memory conflict occured during section loading + AddressSpace defaultSpace = elfLoadHelper.getProgram().getAddressFactory().getDefaultAddressSpace(); + return defaultSpace.getAddress(elfSymbol.getValue() + elfLoadHelper.getImageBaseWordAdjustmentOffset()); + } + + return null; + } + + @Override public Address evaluateElfSymbol(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol, Address address, boolean isExternal) {