Merge remote-tracking branch

'origin/GP-3428_ghidra1_ELFSegmentDiscardSize' into patch (Closes #5273)
This commit is contained in:
Ryan Kurtz 2023-05-12 14:20:43 -04:00
commit 5b53757dc6
4 changed files with 51 additions and 8 deletions

View file

@ -384,6 +384,16 @@
the program is run. These sections will not be stored in a special address space called
"other".</P>
</BLOCKQUOTE>
<H4>Max Zero-Segment Discard Size</H4>
<BLOCKQUOTE>
<P>When both section-headers and program-headers are present, this option controls the
maximum byte-size of a non-section-based memory block which has a zero-fill which will
be discarded. This is intended to allow section-alignment load sequences to be ignored
and discarded. A value of "0" will disable all such discards. The default value is
255-bytes.</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H3>Intel Hex Options<A name="Options_Intel_Hex"/></H3>

View file

@ -47,6 +47,14 @@ public class ElfLoaderOptionsFactory {
public static final String INCLUDE_OTHER_BLOCKS = "Import Non-Loaded Data";// as OTHER overlay blocks
static final boolean INCLUDE_OTHER_BLOCKS_DEFAULT = true;
public static final String DISCARDABLE_SEGMENT_SIZE_OPTION_NAME =
"Max Zero-Segment Discard Size";
// Maximum length of discardable segment
// If program contains section headers, any zeroed segment smaller than this size
// will be eligible for removal.
private static final int DEFAULT_DISCARDABLE_SEGMENT_SIZE = 0xff;
private ElfLoaderOptionsFactory() {
}
@ -82,6 +90,10 @@ public class ElfLoaderOptionsFactory {
options.add(new Option(INCLUDE_OTHER_BLOCKS, INCLUDE_OTHER_BLOCKS_DEFAULT, Boolean.class,
Loader.COMMAND_LINE_ARG_PREFIX + "-includeOtherBlocks"));
options.add(
new Option(DISCARDABLE_SEGMENT_SIZE_OPTION_NAME, DEFAULT_DISCARDABLE_SEGMENT_SIZE,
Integer.class, Loader.COMMAND_LINE_ARG_PREFIX + "-maxSegmentDiscardSize"));
ElfLoadAdapter extensionAdapter = ElfExtensionFactory.getLoadAdapter(elf);
if (extensionAdapter != null) {
extensionAdapter.addLoadOptions(elf, options);
@ -166,10 +178,27 @@ public class ElfLoaderOptionsFactory {
}
}
else if (name.equals(IMAGE_BASE_OPTION_NAME)) {
return validateAddressSpaceOffsetOption(option, language.getDefaultSpace());
String err = validateAddressSpaceOffsetOption(option, language.getDefaultSpace());
if (err != null) {
return err;
}
}
else if (name.equals(IMAGE_DATA_IMAGE_BASE_OPTION_NAME)) {
return validateAddressSpaceOffsetOption(option, language.getDefaultDataSpace());
String err =
validateAddressSpaceOffsetOption(option, language.getDefaultDataSpace());
if (err != null) {
return err;
}
}
else if (name.equals(DISCARDABLE_SEGMENT_SIZE_OPTION_NAME)) {
if (!Integer.class.isAssignableFrom(option.getValueClass())) {
return "Invalid type for option: " + name + " - " + option.getValueClass();
}
int val = (Integer) option.getValue();
if (val < 0 || val > DEFAULT_DISCARDABLE_SEGMENT_SIZE) {
return "Option value out-of-range: " + name + " (0.." +
DEFAULT_DISCARDABLE_SEGMENT_SIZE + ")";
}
}
}
return null;
@ -214,4 +243,9 @@ public class ElfLoaderOptionsFactory {
return OptionUtils.getOption(IMAGE_DATA_IMAGE_BASE_OPTION_NAME, options, (String) null);
}
public static int getMaxSegmentDiscardSize(List<Option> options) {
return OptionUtils.getOption(DISCARDABLE_SEGMENT_SIZE_OPTION_NAME, options,
DEFAULT_DISCARDABLE_SEGMENT_SIZE);
}
}

View file

@ -70,11 +70,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
private static final String ELF_PROGRAM_HEADERS_BLOCK_NAME = "_elfProgramHeaders";
private static final String ELF_SECTION_HEADERS_BLOCK_NAME = "_elfSectionHeaders";
// Maximum length of discardable segment
// If program contains section headers, any zeroed segment smaller than this size
// will be eligible for removal.
private static final int DISCARDABLE_SEGMENT_SIZE = 0xff;
private List<Option> options;
private Long dataImageBase; // cached data image base option or null if not applicable
private MessageLog log;
@ -326,7 +321,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
if (elf.getSectionHeaderCount() == 0 || elf.getProgramHeaderCount() == 0) {
return false; // only prune if both sections and program headers are present
}
if (length > DISCARDABLE_SEGMENT_SIZE || !blockName.startsWith(SEGMENT_NAME_PREFIX)) {
int maxSegmentDiscardSize = ElfLoaderOptionsFactory.getMaxSegmentDiscardSize(options);
if (maxSegmentDiscardSize <= 0 || length > maxSegmentDiscardSize ||
!blockName.startsWith(SEGMENT_NAME_PREFIX)) {
return false;
}

View file

@ -600,6 +600,7 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
<LI><typewriter>-loader-imagebase &lt;imagebase<sup>3</sup>&gt;</typewriter></LI>
<LI><typewriter>-loader-dataImageBase &lt;dataImageBase<sup>4</sup>&gt;</typewriter></LI>
<LI><typewriter>-loader-includeOtherBlocks &lt;true|false&gt;</typewriter></LI>
<LI><typewriter>-loader-maxSegmentDiscardSize &lt;0..255&gt; (default: 255)</typewriter></LI>
</UL>
<LI><typewriter>-loader PeLoader<typewriter></LI>
<UL>