mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-09-13 21:56:19 +00:00
GP-4178 Added ELF Import option to control undefined data creation (now off by default)
This commit is contained in:
parent
f739df7c21
commit
c5243f9a95
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<Option> options) {
|
||||
return OptionUtils.getOption(APPLY_UNDEFINED_SYMBOL_DATA_NAME, options,
|
||||
APPLY_UNDEFINED_SYMBOL_DATA_DEFAULT);
|
||||
}
|
||||
|
||||
static boolean includeOtherBlocks(List<Option> options) {
|
||||
return OptionUtils.getOption(INCLUDE_OTHER_BLOCKS, options, INCLUDE_OTHER_BLOCKS_DEFAULT);
|
||||
}
|
||||
|
@ -238,7 +246,7 @@ public class ElfLoaderOptionsFactory {
|
|||
public static String getImageBaseOption(List<Option> options) {
|
||||
return OptionUtils.getOption(IMAGE_BASE_OPTION_NAME, options, (String) null);
|
||||
}
|
||||
|
||||
|
||||
public static String getDataImageBaseOption(List<Option> options) {
|
||||
return OptionUtils.getOption(IMAGE_DATA_IMAGE_BASE_OPTION_NAME, options, (String) null);
|
||||
}
|
||||
|
|
|
@ -1361,12 +1361,22 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
|
||||
private void allocateUndefinedSymbolData(HashMap<Address, Integer> dataAllocationMap) {
|
||||
if (!ElfLoaderOptionsFactory.applyUndefinedSymbolData(options)) {
|
||||
return;
|
||||
}
|
||||
for (Address addr : dataAllocationMap.keySet()) {
|
||||
|
||||
MemoryBlock block = memory.getBlock(addr);
|
||||
if (block == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create undefined data for each data/object symbol
|
||||
Integer symbolSize = dataAllocationMap.get(addr);
|
||||
if (symbolSize != null) {
|
||||
try {
|
||||
createUndefined(addr, symbolSize);
|
||||
DataType undefined = Undefined.getUndefinedDataType(symbolSize);
|
||||
listing.createData(addr, undefined);
|
||||
}
|
||||
catch (CodeUnitInsertionException e) {
|
||||
// ignore conflicts which can be caused by other markup
|
||||
|
@ -2311,6 +2321,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
@Override
|
||||
public Data createUndefinedData(Address address, int length) {
|
||||
if (!ElfLoaderOptionsFactory.applyUndefinedSymbolData(options)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// If it is bigger than 8, just let it go through and create a single undefined
|
||||
// Otherwise this would create an array of undefined, might get in the way
|
||||
|
@ -3550,16 +3563,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
return StringUtilities.pad("" + value, ' ', 4);
|
||||
}
|
||||
|
||||
private Data createUndefined(Address addr, int size) throws CodeUnitInsertionException {
|
||||
|
||||
MemoryBlock block = memory.getBlock(addr);
|
||||
if (block == null) {
|
||||
return null;
|
||||
}
|
||||
DataType undefined = Undefined.getUndefinedDataType(size);
|
||||
return listing.createData(addr, undefined);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol createSymbol(Address addr, String name, boolean isPrimary, boolean pinAbsolute,
|
||||
Namespace namespace) throws InvalidInputException {
|
||||
|
|
|
@ -609,6 +609,7 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
|
|||
<LI><typewriter>-loader-libraryLoadDepth <depth></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryDestinationFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-applyRelocations <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-applyUndefinedData <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-imagebase <imagebase<sup>3</sup>></typewriter></LI>
|
||||
<LI><typewriter>-loader-dataImageBase <dataImageBase<sup>4</sup>></typewriter></LI>
|
||||
<LI><typewriter>-loader-includeOtherBlocks <true|false></typewriter></LI>
|
||||
|
|
Loading…
Reference in a new issue