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