Merge branch 'GP-1936_ghidra1_Elf_PN_XNUM'

This commit is contained in:
ghidra1
2022-04-19 16:05:41 -04:00
7 changed files with 143 additions and 41 deletions

View File

@@ -213,7 +213,7 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
private void processProgramHeaders(ElfHeader elf, Listing listing) throws Exception {
int headerCount = elf.e_phnum();
int headerCount = elf.getProgramHeaderCount();
int size = elf.e_phentsize() * headerCount;
if (size == 0) {
return;

View File

@@ -512,4 +512,10 @@ public interface ElfConstants {
/** used by NetBSD/avr32 - AVR 32-bit */
public static final short EM_AVR32_unofficial = 0x18ad;
/**
* PN_XNUM: Used by e_phnum field to signal alternate storage of program header count
* within section[0] sh_info field.
*/
public static final short PN_XNUM = (short) 0xffff;
}

View File

@@ -60,7 +60,7 @@ public class ElfDefaultGotPltMarkup {
}
public void process(TaskMonitor monitor) throws CancelledException {
if (elf.e_shnum() == 0) {
if (elf.getSectionHeaderCount() == 0) {
processDynamicPLTGOT(ElfDynamicType.DT_PLTGOT, ElfDynamicType.DT_JMPREL, monitor);
}
else {

View File

@@ -68,9 +68,9 @@ public class ElfHeader implements StructConverter, Writeable {
private int e_flags; //processor-specific flags
private short e_ehsize; //elf header size
private short e_phentsize; //size of entries in the program header table
private short e_phnum; //number of enties in the program header table
private int e_phnum; //number of enties in the program header table (may not be preserved)
private short e_shentsize; //size of entries in the section header table
private short e_shnum; //number of enties in the section header table
private int e_shnum; //number of enties in the section header table (may not be preserved)
private short e_shstrndx; //section index of the section name string table
private Structure headerStructure;
@@ -78,6 +78,7 @@ public class ElfHeader implements StructConverter, Writeable {
private boolean parsed = false;
private boolean parsedSectionHeaders = false;
private ElfSectionHeader section0 = null;
private ElfSectionHeader[] sectionHeaders = new ElfSectionHeader[0];
private ElfProgramHeader[] programHeaders = new ElfProgramHeader[0];
private ElfStringTable[] stringTables = new ElfStringTable[0];
@@ -161,9 +162,9 @@ public class ElfHeader implements StructConverter, Writeable {
e_version = reader.readNextInt();
if (is32Bit()) {
e_entry = reader.readNextInt() & 0xffffffffL;
e_phoff = reader.readNextInt() & 0xffffffffL;
e_shoff = reader.readNextInt() & 0xffffffffL;
e_entry = reader.readNextUnsignedInt();
e_phoff = reader.readNextUnsignedInt();
e_shoff = reader.readNextUnsignedInt();
}
else if (is64Bit()) {
e_entry = reader.readNextLong();
@@ -178,23 +179,70 @@ public class ElfHeader implements StructConverter, Writeable {
e_flags = reader.readNextInt();
e_ehsize = reader.readNextShort();
e_phentsize = reader.readNextShort();
e_phnum = reader.readNextShort();
if (e_phnum < 0) {
e_phnum = 0; // protect against stripped program headers
}
e_phnum = reader.readNextUnsignedShort();
e_shentsize = reader.readNextShort();
e_shnum = reader.readNextShort();
if (e_shnum < 0) {
e_shnum = 0; // protect against stripped section headers (have seen -1)
}
e_shnum = reader.readNextUnsignedShort();
e_shstrndx = reader.readNextShort();
if (e_shnum >= Short.toUnsignedInt(ElfSectionHeaderConstants.SHN_LORESERVE)) {
e_shnum = readExtendedSectionHeaderCount(); // use extended stored section header count
}
if (e_phnum == Short.toUnsignedInt(ElfConstants.PN_XNUM)) {
e_phnum = readExtendedProgramHeaderCount(); // use extended stored program header count
}
}
catch (IOException e) {
throw new ElfException(e);
}
}
private ElfSectionHeader getSection0() throws IOException {
if (section0 == null && e_shnum != 0) {
long index = e_shoff;
if (!providerContainsRegion(index, e_shentsize)) {
return null;
}
reader.setPointerIndex(index);
section0 = new ElfSectionHeader(reader, this);
}
return section0;
}
/**
* Read extended program header count stored in first section header (ST_NULL) sh_info field value.
* Returned value is restricted to the range 0..0x7fffffff.
* @return extended program header count or 0 if not found or out of range
* @throws IOException if file IO error occurs
*/
private int readExtendedProgramHeaderCount() throws IOException {
ElfSectionHeader s = getSection0();
if (s != null && s.getType() == ElfSectionHeaderConstants.SHT_NULL) {
long val = s.getInfo();
return (val < 0 || val > Integer.MAX_VALUE) ? 0 : (int) val;
}
return 0;
}
/**
* Read extended section header count stored in first section header (ST_NULL) sh_size field value.
* Returned value is restricted to the range 0..0x7fffffff.
* @return extended section header count or 0 if not found or out of range
* @throws IOException if file IO error occurs
*/
private int readExtendedSectionHeaderCount() throws IOException {
ElfSectionHeader s = getSection0();
if (s != null && s.getType() == ElfSectionHeaderConstants.SHT_NULL) {
long val = s.getSize();
return (val < 0 || val > Integer.MAX_VALUE) ? 0 : (int) val;
}
return 0;
}
private void initElfLoadAdapter() {
programHeaderTypeMap = new HashMap<>();
@@ -951,6 +999,10 @@ public class ElfHeader implements StructConverter, Writeable {
sectionHeaders[i] = new ElfSectionHeader(reader, this);
}
if (sectionHeaders.length != 0) {
section0 = sectionHeaders[0];
}
//note: we cannot retrieve all the names
//until after we have read all the section headers.
//this is because one of the section headers
@@ -1283,11 +1335,13 @@ public class ElfHeader implements StructConverter, Writeable {
/**
* This member holds the number of entries in the program header table. Thus the product
* of e_phentsize and e_phnum gives the table's size in bytes. If a file has no program
* header table, e_phnum holds the value zero.
* of e_phentsize and unsigned e_phnum gives the table's size in bytes. If original
* e_phnum equals PNXNUM (0xffff) an attempt will be made to obtained the extended size
* from section[0].sh_info field. If a file has no program header table, e_phnum holds
* the value zero.
* @return the number of entries in the program header table
*/
public short e_phnum() {
public int getProgramHeaderCount() {
return e_phnum;
}
@@ -1311,11 +1365,11 @@ public class ElfHeader implements StructConverter, Writeable {
/**
* This member holds the number of entries in the section header table. Thus the product
* of e_shentsize and e_shnum gives the section header table's size in bytes. If a file
* of e_shentsize and unsigned e_shnum gives the section header table's size in bytes. If a file
* has no section header table, e_shnum holds the value zero.
* @return the number of entries in the section header table
*/
public short e_shnum() {
public int getSectionHeaderCount() {
return e_shnum;
}
@@ -1911,7 +1965,7 @@ public class ElfHeader implements StructConverter, Writeable {
programHeaders = tmp;
e_phnum = (short) programHeaders.length;
e_phnum = programHeaders.length;
}
@@ -1947,8 +2001,16 @@ public class ElfHeader implements StructConverter, Writeable {
raf.write(dc.getBytes(e_flags));
raf.write(dc.getBytes(e_ehsize));
raf.write(dc.getBytes(e_phentsize));
if (e_phnum >= Short.toUnsignedInt(ElfConstants.PN_XNUM)) {
throw new IOException(
"Unsupported program header count serialization: " + e_phnum);
}
raf.write(dc.getBytes(e_phnum));
raf.write(dc.getBytes(e_shentsize));
if (e_shnum >= Short.toUnsignedInt(ElfSectionHeaderConstants.SHN_LORESERVE)) {
throw new IOException(
"Unsupported section header count serialization: " + e_shnum);
}
raf.write(dc.getBytes(e_shnum));
raf.write(dc.getBytes(e_shstrndx));
}

View File

@@ -115,6 +115,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
int id = program.startTransaction("Load ELF program");
boolean success = false;
try {
monitor.setIndeterminate(true);
addProgramProperties(monitor);
@@ -135,9 +136,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
processProgramHeaders(monitor);
processSectionHeaders(monitor);
monitor.setIndeterminate(false);
resolve(monitor);
if (elf.e_shnum() == 0) {
if (elf.getSectionHeaderCount() == 0) {
// create/expand segments to their fullsize if no sections are defined
expandProgramHeaderBlocks(monitor);
}
@@ -151,6 +154,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
markupElfHeader(monitor);
markupProgramHeaders(monitor);
markupSectionHeaders(monitor);
monitor.setProgress(0);
monitor.setIndeterminate(true);
markupDynamicTable(monitor);
markupInterpreter(monitor);
@@ -222,11 +229,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// Ignore header regions which will always be allocated to blocks
int elfHeaderSize = elf.toDataType().getLength();
fileMap.paintRange(0, elfHeaderSize - 1, -4); // -4: header block
int programHeaderSize = elf.e_phentsize() * elf.e_phnum();
int programHeaderSize = elf.e_phentsize() * elf.getProgramHeaderCount();
if (programHeaderSize != 0) {
fileMap.paintRange(elf.e_phoff(), elf.e_phoff() + programHeaderSize - 1, -4); // -4: header block
}
int sectionHeaderSize = elf.e_shentsize() * elf.e_shnum();
int sectionHeaderSize = elf.e_shentsize() * elf.getSectionHeaderCount();
if (sectionHeaderSize != 0) {
fileMap.paintRange(elf.e_shoff(), elf.e_shoff() + sectionHeaderSize - 1, -4); // -4: header block
}
@@ -288,7 +295,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
private boolean isDiscardableFillerSegment(MemoryLoadable loadable, String blockName,
Address start, long fileOffset, long length) throws IOException {
if (elf.e_shnum() == 0 || elf.e_phnum() == 0) {
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)) {
@@ -735,13 +742,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
private void processRelocations(TaskMonitor monitor) throws CancelledException {
monitor.setMessage("Processing relocation tables...");
ElfRelocationTable[] relocationTables = elf.getRelocationTables();
if (relocationTables.length == 0) {
return;
}
monitor.setMessage("Processing relocation tables...");
boolean processRelocations = ElfLoaderOptionsFactory.performRelocations(options);
if (processRelocations && ElfRelocationHandlerFactory.getHandler(elf) == null) {
log("ELF relocation handler extension not found! Unable to process relocations.");
@@ -1012,12 +1020,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
private void markupProgramHeaders(TaskMonitor monitor) {
int headerCount = elf.e_phnum();
int headerCount = elf.getProgramHeaderCount();
int size = elf.e_phentsize() * headerCount;
if (size == 0) {
return;
}
monitor.setMessage("Markup Program Headers ...");
Structure phStructDt = (Structure) elf.getProgramHeaders()[0].toDataType();
phStructDt = phStructDt.clone(program.getDataTypeManager());
@@ -1047,8 +1057,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
ElfProgramHeader[] programHeaders = elf.getProgramHeaders();
monitor.setMaximum(programHeaders.length);
int vaddrFieldIndex = elf.is64Bit() ? 3 : 2; // p_vaddr structure element index
for (int i = 0; i < programHeaders.length; i++) {
monitor.checkCanceled();
monitor.incrementProgress(1);
Data d = array.getComponent(i);
d.setComment(CodeUnit.EOL_COMMENT, programHeaders[i].getComment());
if (programHeaders[i].getType() == ElfProgramHeaderConstants.PT_NULL) {
@@ -1073,16 +1087,18 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
private void markupSectionHeaders(TaskMonitor monitor) {
int headerCount = elf.e_shnum();
int headerCount = elf.getSectionHeaderCount();
int size = elf.e_shentsize() * headerCount;
if (size == 0) {
return;
}
monitor.setMessage("Markup Section Headers ...");
Structure shStructDt = (Structure) elf.getSections()[0].toDataType();
shStructDt = shStructDt.clone(program.getDataTypeManager());
Array arrayDt = new ArrayDataType(shStructDt, elf.e_shnum(), elf.e_shentsize());
Array arrayDt = new ArrayDataType(shStructDt, headerCount, elf.e_shentsize());
Address headerAddr = findLoadAddress(elf.e_shoff(), size);
@@ -1108,7 +1124,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
ElfSectionHeader[] sections = elf.getSections();
monitor.setMaximum(sections.length);
for (int i = 0; i < sections.length; i++) {
monitor.checkCanceled();
monitor.incrementProgress(1);
Data d = array.getComponent(i);
String comment = sections[i].getNameAsString();
@@ -2758,9 +2777,15 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* @throws CancelledException
*/
private void expandProgramHeaderBlocks(TaskMonitor monitor) throws CancelledException {
monitor.setMessage("Exapanding Program Segments...");
ElfProgramHeader[] elfProgramHeaders = elf.getProgramHeaders();
monitor.setMaximum(elfProgramHeaders.length);
for (int i = 0; i < elfProgramHeaders.length; ++i) {
monitor.checkCanceled();
monitor.incrementProgress(1);
ElfProgramHeader elfProgramHeader = elfProgramHeaders[i];
if (elfProgramHeaders[i].getType() == ElfProgramHeaderConstants.PT_LOAD) {
@@ -2862,9 +2887,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
private void processProgramHeaders(TaskMonitor monitor) throws CancelledException {
if (elf.isRelocatable() && elf.e_phnum() != 0) {
if (elf.isRelocatable() && elf.getProgramHeaderCount() != 0) {
log("Ignoring unexpected program headers for relocatable ELF (e_phnum=" +
elf.e_phnum() + ")");
elf.getProgramHeaderCount() + ")");
return;
}
@@ -2933,7 +2958,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
long loadSizeBytes = elfProgramHeader.getAdjustedLoadSize();
long fullSizeBytes = elfProgramHeader.getAdjustedMemorySize();
boolean maintainExecuteBit = elf.e_shnum() == 0;
boolean maintainExecuteBit = elf.getSectionHeaderCount() == 0;
if (fullSizeBytes <= 0) {
log("Skipping zero-length segment [" + segmentNumber + "," +
@@ -2949,7 +2974,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
try {
// Only allow segment fragmentation if section headers are defined
boolean isFragmentationOK = (elf.e_shnum() != 0);
boolean isFragmentationOK = (elf.getSectionHeaderCount() != 0);
String comment = getSectionComment(addr, fullSizeBytes, space.getAddressableUnitSize(),
elfProgramHeader.getDescription(), address.isLoadedMemoryAddress());
@@ -3355,8 +3380,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
x = false;
}
Msg.debug(this,
"Loading block " + name + " at " + start + " from file offset " + fileOffset);
// Msg.debug(this,
// "Loading block " + name + " at " + start + " from file offset " + fileOffset);
long endOffset = fileOffset + revisedLength - 1;
if (endOffset >= fileBytes.getSize()) {

View File

@@ -34,6 +34,8 @@ public abstract class MemorySectionResolver {
protected final Program program;
private Set<String> usedBlockNames = new HashSet<>();
private List<MemorySection> sections = new ArrayList<>(); // built-up prior to resolve
private Map<String, Integer> sectionIndexMap = new HashMap<>();
@@ -43,6 +45,9 @@ public abstract class MemorySectionResolver {
public MemorySectionResolver(Program program) {
this.program = program;
if (!program.getMemory().isEmpty()) {
throw new IllegalStateException("program memory blocks already exist - unsupported");
}
}
/**
@@ -124,16 +129,15 @@ public abstract class MemorySectionResolver {
else {
baseName = "NO-NAME";
}
Memory mem = program.getMemory();
String name = baseName;
int index = 0;
while (mem.getBlock(name) != null) {
while (usedBlockNames.contains(name)) {
name = baseName + "-" + (++index);
}
return name;
}
private String getUniqueSectionChunkName(MemorySection section, Memory memory,
private String getUniqueSectionChunkName(MemorySection section,
int preferredIndex) {
String sectionName = section.getSectionName();
int index = preferredIndex;
@@ -142,7 +146,7 @@ public abstract class MemorySectionResolver {
if (index >= 0) {
name += "." + index;
}
if (memory.getBlock(name) == null) {
if (!usedBlockNames.contains(name)) {
return name;
}
if (index <= 0) {
@@ -245,6 +249,8 @@ public abstract class MemorySectionResolver {
*/
public void resolve(TaskMonitor monitor) throws CancelledException {
monitor.setMessage("Loading memory blocks...");
if (sectionMemoryMap != null) {
throw new IllegalStateException("already resolved");
}
@@ -263,9 +269,11 @@ public abstract class MemorySectionResolver {
// process sections in reverse order - last-in takes precedence
int sectionCount = sections.size();
monitor.initialize(sectionCount);
for (int index = sectionCount - 1; index >= 0; --index) {
monitor.checkCanceled();
resolveSectionMemory(sections.get(index), fileAllocationMap, monitor);
monitor.incrementProgress(1);
}
}
@@ -352,7 +360,7 @@ public abstract class MemorySectionResolver {
continue; // skip range
}
String blockName = getUniqueSectionChunkName(section, memory, rangeIndex);
String blockName = getUniqueSectionChunkName(section, rangeIndex);
Address physicalStartAddr = section.getMinPhysicalAddress().add(sectionByteOffset);
@@ -381,6 +389,7 @@ public abstract class MemorySectionResolver {
if (block != null) {
minAddr = block.getStart();
maxAddr = block.getEnd();
usedBlockNames.add(blockName);
}
else {
// block may be null due to unexpected conflict or pruning - allow to continue

View File

@@ -273,7 +273,7 @@ public class PowerPC_ElfExtension extends ElfExtension {
RegisterValue enableVLE = new RegisterValue(vleContextReg, BigInteger.ONE);
ElfHeader elf = elfLoadHelper.getElfHeader();
if (elf.e_shnum() != 0) {
if (elf.getSectionHeaderCount() != 0) {
// Rely on section headers if present
for (ElfSectionHeader section : elf.getSections(
ElfSectionHeaderConstants.SHT_PROGBITS)) {