diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java index 965a05664b..aaef83bf54 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfLoadHelper.java @@ -17,6 +17,7 @@ package ghidra.app.util.bin.format.elf; import ghidra.app.util.bin.format.MemoryLoadable; import ghidra.app.util.importer.MessageLog; +import ghidra.app.util.opinion.ElfLoaderOptionsFactory; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; import ghidra.program.model.data.DataType; @@ -104,10 +105,13 @@ public interface ElfLoadHelper { Address indirectPointerAddr); /** - * Create an undefined data item to reserve the location as data, without specifying the type + * Create an undefined data item to reserve the location as data, without specifying the type. + * If {@link ElfLoaderOptionsFactory#applyUndefinedSymbolData(java.util.List)} returns false + * data will not be applied and null will be returned. + * * @param address location of undefined data to create * @param length size of the undefined data item - * @return {@link Data} which was created or null if conflict occurs + * @return {@link Data} which was created or null if conflict occurs or disabled by option */ Data createUndefinedData(Address address, int length); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java index e93a3d15fd..70b1128fd7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java @@ -34,6 +34,9 @@ public class ElfLoaderOptionsFactory { public static final String PERFORM_RELOCATIONS_NAME = "Perform Symbol Relocations"; static final boolean PERFORM_RELOCATIONS_DEFAULT = true; + public static final String APPLY_UNDEFINED_SYMBOL_DATA_NAME = "Apply Undefined Symbol Data"; + static final boolean APPLY_UNDEFINED_SYMBOL_DATA_DEFAULT = false; + // NOTE: Using too large of an image base can cause problems for relocation processing // for some language scenarios which utilize 32-bit relocations. This may be due to // an assumed virtual memory of 32-bits. @@ -41,7 +44,7 @@ public class ElfLoaderOptionsFactory { public static final String IMAGE_BASE_OPTION_NAME = "Image Base"; public static final long IMAGE_BASE_DEFAULT = 0x00010000; public static final long IMAGE64_BASE_DEFAULT = 0x00100000L; - + public static final String IMAGE_DATA_IMAGE_BASE_OPTION_NAME = "Data Image Base"; public static final String INCLUDE_OTHER_BLOCKS = "Import Non-Loaded Data";// as OTHER overlay blocks @@ -66,6 +69,10 @@ public class ElfLoaderOptionsFactory { options.add(new Option(PERFORM_RELOCATIONS_NAME, PERFORM_RELOCATIONS_DEFAULT, Boolean.class, Loader.COMMAND_LINE_ARG_PREFIX + "-applyRelocations")); + options.add( + new Option(APPLY_UNDEFINED_SYMBOL_DATA_NAME, APPLY_UNDEFINED_SYMBOL_DATA_DEFAULT, + Boolean.class, Loader.COMMAND_LINE_ARG_PREFIX + "-applyUndefinedData")); + ElfHeader elf = new ElfHeader(provider, null); long imageBase = elf.findImageBase(); @@ -78,7 +85,7 @@ public class ElfLoaderOptionsFactory { String hexValueStr = getBaseAddressOffsetString(imageBase, defaultSpace); options.add(new Option(IMAGE_BASE_OPTION_NAME, hexValueStr, String.class, Loader.COMMAND_LINE_ARG_PREFIX + "-imagebase")); - + if (includeDataImageBaseOption(elf, language)) { long minDataImageBase = getRecommendedMinimumDataImageBase(elf, language); hexValueStr = @@ -100,7 +107,7 @@ public class ElfLoaderOptionsFactory { } } - + private static boolean includeDataImageBaseOption(ElfHeader elf, Language language) { // only include option if all segments and section have a 0 address AddressSpace defaultSpace = language.getDefaultSpace(); @@ -110,18 +117,18 @@ public class ElfLoaderOptionsFactory { } return elf.isRelocatable() && elf.getImageBase() == 0; } - + private static long getRecommendedMinimumDataImageBase(ElfHeader elf, Language language) { - + String minDataOffset = language.getProperty(GhidraLanguagePropertyKeys.MINIMUM_DATA_IMAGE_BASE); if (minDataOffset != null) { return NumericUtilities.parseHexLong(minDataOffset); } - + AddressSpace defaultDataSpace = language.getDefaultDataSpace(); int unitSize = defaultDataSpace.getAddressableUnitSize(); - + // logic assumes memory mapped registers reside at low-end addresses (e.g., 0) long minOffset = 0; for (Register reg : language.getRegisters()) { @@ -152,8 +159,7 @@ public class ElfLoaderOptionsFactory { int minNibbles = Math.min(8, space.getSize() / 4); int baseOffsetStrLen = baseOffsetStr.length(); if (baseOffsetStrLen < minNibbles) { - baseOffsetStr = - StringUtilities.pad(baseOffsetStr, '0', minNibbles - baseOffsetStrLen); + baseOffsetStr = StringUtilities.pad(baseOffsetStr, '0', minNibbles - baseOffsetStrLen); } return baseOffsetStr; } @@ -162,17 +168,14 @@ public class ElfLoaderOptionsFactory { Language language; try { language = loadSpec.getLanguageCompilerSpec().getLanguage(); - } catch (LanguageNotFoundException e) { + } + catch (LanguageNotFoundException e) { throw new RuntimeException(e); } for (Option option : options) { String name = option.getName(); - if (name.equals(PERFORM_RELOCATIONS_NAME)) { - if (!Boolean.class.isAssignableFrom(option.getValueClass())) { - return "Invalid type for option: " + name + " - " + option.getValueClass(); - } - } - else if (name.equals(INCLUDE_OTHER_BLOCKS)) { + if (name.equals(PERFORM_RELOCATIONS_NAME) || name.equals(INCLUDE_OTHER_BLOCKS) || + name.equals(APPLY_UNDEFINED_SYMBOL_DATA_NAME)) { if (!Boolean.class.isAssignableFrom(option.getValueClass())) { return "Invalid type for option: " + name + " - " + option.getValueClass(); } @@ -227,6 +230,11 @@ public class ElfLoaderOptionsFactory { PERFORM_RELOCATIONS_DEFAULT); } + public static boolean applyUndefinedSymbolData(List