mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-2334 improve support for extended ELF section indexing when number of
sections exceed SHN_LORESERVE (0xff00).
This commit is contained in:
parent
88570bf43e
commit
5908e79022
10 changed files with 228 additions and 108 deletions
|
@ -212,8 +212,8 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
|||
"Manually re-run the DWARF analyzer after adjusting the options or start it via Dwarf_ExtractorScript");
|
||||
}
|
||||
catch (DWARFException | IOException e) {
|
||||
log.appendMsg("Error during DWARFAnalyzer import");
|
||||
log.appendException(e);
|
||||
log.appendMsg("Error during DWARFAnalyzer import: " + e.getMessage());
|
||||
Msg.error(this, "Error during DWARFAnalyzer import: " + e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -141,10 +141,8 @@ public class DWARFCompilationUnit {
|
|||
debugInfoBR.setPointerIndex(debugInfoBR.length());
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new DWARFException(
|
||||
"Invalid DWARF length 0 at 0x" + Long.toHexString(startOffset));
|
||||
}
|
||||
throw new DWARFException(
|
||||
"Invalid DWARF length 0 at 0x" + Long.toHexString(startOffset));
|
||||
}
|
||||
|
||||
long endOffset = debugInfoBR.getPointerIndex() + lengthInfo.length;
|
||||
|
@ -155,7 +153,8 @@ public class DWARFCompilationUnit {
|
|||
|
||||
if (version < 2 || version > 4) {
|
||||
throw new DWARFException(
|
||||
"Only DWARF version 2, 3, or 4 information is currently supported.");
|
||||
"Only DWARF version 2, 3, or 4 information is currently supported (detected " +
|
||||
version + ").");
|
||||
}
|
||||
if (firstDIEOffset > endOffset) {
|
||||
throw new IOException("Invalid length " + (endOffset - startOffset) +
|
||||
|
|
|
@ -68,10 +68,10 @@ 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 int e_phnum; //number of enties in the program header table (may not be preserved)
|
||||
private int e_phnum; //number of enties in the program header table (may be extended and may not be preserved)
|
||||
private short e_shentsize; //size of entries 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 int e_shnum; //number of enties in the section header table (may be extended and may not be preserved)
|
||||
private int e_shstrndx; //section index of the section name string table (may be extended and may not be preserved)
|
||||
|
||||
private Structure headerStructure;
|
||||
|
||||
|
@ -88,6 +88,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
|
||||
private ElfStringTable dynamicStringTable;
|
||||
private ElfSymbolTable dynamicSymbolTable;
|
||||
private boolean hasExtendedSymbolSectionIndexTable; // if SHT_SYMTAB_SHNDX sections exist
|
||||
|
||||
private String[] dynamicLibraryNames;
|
||||
|
||||
|
@ -186,15 +187,23 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
e_shentsize = reader.readNextShort();
|
||||
e_shnum = reader.readNextUnsignedShort();
|
||||
|
||||
e_shstrndx = reader.readNextShort();
|
||||
e_shstrndx = Short.toUnsignedInt(reader.readNextShort());
|
||||
|
||||
if (e_shnum >= Short.toUnsignedInt(ElfSectionHeaderConstants.SHN_LORESERVE)) {
|
||||
if (e_shnum == 0 ||
|
||||
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
|
||||
}
|
||||
|
||||
if (e_shnum == 0) {
|
||||
e_shstrndx = 0;
|
||||
}
|
||||
else if (e_shstrndx == Short.toUnsignedInt(ElfSectionHeaderConstants.SHN_XINDEX)) {
|
||||
e_shstrndx = readExtendedSectionHeaderStringTableIndex();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ElfException(e);
|
||||
|
@ -202,35 +211,36 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
}
|
||||
|
||||
private ElfSectionHeader getSection0() throws IOException {
|
||||
if (section0 == null && e_shnum != 0) {
|
||||
long index = e_shoff;
|
||||
if (!providerContainsRegion(index, e_shentsize)) {
|
||||
if (section0 == null && e_shoff != 0) {
|
||||
if (!providerContainsRegion(e_shoff, e_shentsize)) {
|
||||
return null;
|
||||
}
|
||||
reader.setPointerIndex(index);
|
||||
reader.setPointerIndex(e_shoff);
|
||||
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.
|
||||
* Read extended program header count (e_phnum) stored in first section header (ST_NULL)
|
||||
* sh_info field value. This is done to overcome the short value limitation of the
|
||||
* e_phnum header field. 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;
|
||||
int val = s.getInfo();
|
||||
return val < 0 ? 0 : 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.
|
||||
* Read extended section header count (e_shnum) stored in first section header (ST_NULL)
|
||||
* sh_size field value. This is done to overcome the short value limitation of the
|
||||
* e_shnum header field. 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
|
||||
*/
|
||||
|
@ -243,6 +253,22 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read extended section header string table index (e_shstrndx) stored in first section header
|
||||
* (ST_NULL) sh_size field value. This is done to overcome the short value limitation of the
|
||||
* e_shstrndx header field. 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 readExtendedSectionHeaderStringTableIndex() throws IOException {
|
||||
ElfSectionHeader s = getSection0();
|
||||
if (s != null && s.getType() == ElfSectionHeaderConstants.SHT_NULL) {
|
||||
int val = s.getLink();
|
||||
return val < 0 ? 0 : val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void initElfLoadAdapter() {
|
||||
|
||||
programHeaderTypeMap = new HashMap<>();
|
||||
|
@ -733,9 +759,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
ArrayList<ElfStringTable> stringTableList = new ArrayList<>();
|
||||
for (ElfSectionHeader stringTableSectionHeader : sectionHeaders) {
|
||||
if (stringTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_STRTAB) {
|
||||
ElfStringTable stringTable = new ElfStringTable(reader, this,
|
||||
stringTableSectionHeader, stringTableSectionHeader.getOffset(),
|
||||
stringTableSectionHeader.getAddress(), stringTableSectionHeader.getSize());
|
||||
ElfStringTable stringTable = new ElfStringTable(this, stringTableSectionHeader,
|
||||
stringTableSectionHeader.getOffset(), stringTableSectionHeader.getAddress(),
|
||||
stringTableSectionHeader.getSize());
|
||||
stringTableList.add(stringTable);
|
||||
if (stringTable.getAddressOffset() == dynamicStringTableAddr) {
|
||||
dynamicStringTable = stringTable;
|
||||
|
@ -778,7 +804,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
return null;
|
||||
}
|
||||
|
||||
return new ElfStringTable(reader, this, null,
|
||||
return new ElfStringTable(this, null,
|
||||
stringTableLoadHeader.getOffset(dynamicStringTableAddr), dynamicStringTableAddr,
|
||||
stringTableSize);
|
||||
}
|
||||
|
@ -787,6 +813,54 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
}
|
||||
}
|
||||
|
||||
private int[] getExtendedSymbolSectionIndexTable(ElfSectionHeader symbolTableSectionHeader) {
|
||||
|
||||
if (!hasExtendedSymbolSectionIndexTable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find SHT_SYMTAB_SHNDX section linked to specified symbol table section
|
||||
ElfSectionHeader symbolSectionIndexHeader = null;
|
||||
for (ElfSectionHeader section : sectionHeaders) {
|
||||
if (section.getType() != ElfSectionHeaderConstants.SHT_SYMTAB_SHNDX) {
|
||||
continue;
|
||||
}
|
||||
int linkIndex = section.getLink();
|
||||
if (linkIndex <= 0 || linkIndex >= sectionHeaders.length) {
|
||||
continue;
|
||||
}
|
||||
if (sectionHeaders[linkIndex] == symbolTableSectionHeader) {
|
||||
symbolSectionIndexHeader = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (symbolSectionIndexHeader == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// determine number of 32-bit index elements for int[]
|
||||
int count = (int) (symbolSectionIndexHeader.getSize() / 4);
|
||||
int[] indexTable = new int[count];
|
||||
|
||||
long ptr = reader.getPointerIndex();
|
||||
try {
|
||||
reader.setPointerIndex(symbolSectionIndexHeader.getOffset());
|
||||
for (int i = 0; i < count; i++) {
|
||||
indexTable[i] = reader.readNextInt();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
errorConsumer.accept("Failed to read symbol section index table at 0x" +
|
||||
Long.toHexString(symbolSectionIndexHeader.getOffset()) + ": " +
|
||||
symbolSectionIndexHeader.getNameAsString());
|
||||
}
|
||||
finally {
|
||||
reader.setPointerIndex(ptr); // restore reader position
|
||||
}
|
||||
|
||||
return indexTable;
|
||||
}
|
||||
|
||||
private void parseSymbolTables() throws IOException {
|
||||
|
||||
// identify dynamic symbol table address
|
||||
|
@ -822,10 +896,15 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
boolean isDyanmic = ElfSectionHeaderConstants.dot_dynsym
|
||||
.equals(symbolTableSectionHeader.getNameAsString());
|
||||
|
||||
// get extended symbol section index table if present
|
||||
int[] symbolSectionIndexTable =
|
||||
getExtendedSymbolSectionIndexTable(symbolTableSectionHeader);
|
||||
|
||||
ElfSymbolTable symbolTable = new ElfSymbolTable(reader, this,
|
||||
symbolTableSectionHeader, symbolTableSectionHeader.getOffset(),
|
||||
symbolTableSectionHeader.getAddress(), symbolTableSectionHeader.getSize(),
|
||||
symbolTableSectionHeader.getEntrySize(), stringTable, isDyanmic);
|
||||
symbolTableSectionHeader.getEntrySize(), stringTable, symbolSectionIndexTable,
|
||||
isDyanmic);
|
||||
symbolTableList.add(symbolTable);
|
||||
if (symbolTable.getAddressOffset() == dynamicSymbolTableAddr) {
|
||||
dynamicSymbolTable = symbolTable; // remember dynamic symbol table
|
||||
|
@ -910,8 +989,12 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
symCount = reader.readInt(symbolHashTableOffset + 4); // nchain from DT_HASH
|
||||
}
|
||||
|
||||
// NOTE: When parsed from dynamic table and not found via section header parse
|
||||
// it is assumed that the extended symbol section table is not used.
|
||||
|
||||
return new ElfSymbolTable(reader, this, null, symbolTableOffset,
|
||||
tableAddr, tableEntrySize * symCount, tableEntrySize, dynamicStringTable, true);
|
||||
tableAddr, tableEntrySize * symCount, tableEntrySize, dynamicStringTable, null,
|
||||
true);
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
throw new AssertException(e);
|
||||
|
@ -997,6 +1080,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
}
|
||||
reader.setPointerIndex(index);
|
||||
sectionHeaders[i] = new ElfSectionHeader(reader, this);
|
||||
if (sectionHeaders[i].getType() == ElfSectionHeaderConstants.SHT_SYMTAB_SHNDX) {
|
||||
hasExtendedSymbolSectionIndexTable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sectionHeaders.length != 0) {
|
||||
|
@ -1388,7 +1474,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* the value SHN_UNDEF.
|
||||
* @return the section header table index of the entry associated with the section name string table
|
||||
*/
|
||||
public short e_shstrndx() {
|
||||
public int e_shstrndx() {
|
||||
return e_shstrndx;
|
||||
}
|
||||
|
||||
|
|
|
@ -333,10 +333,10 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
|
|||
}
|
||||
|
||||
ElfSectionHeader[] sections = header.getSections();
|
||||
short e_shstrndx = header.e_shstrndx();
|
||||
int e_shstrndx = header.e_shstrndx();
|
||||
name = null;
|
||||
try {
|
||||
if (sh_name >= 0 && e_shstrndx >= 0 && e_shstrndx < sections.length) {
|
||||
if (sh_name >= 0 && e_shstrndx > 0 && e_shstrndx < sections.length) {
|
||||
// read section name from string table
|
||||
long stringTableOffset = sections[e_shstrndx].getOffset();
|
||||
if (stringTableOffset >= 0) {
|
||||
|
|
|
@ -20,56 +20,32 @@ public class ElfSectionHeaderConstants {
|
|||
private ElfSectionHeaderConstants() {
|
||||
}
|
||||
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_bss = ".bss";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_comment = ".comment";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_data = ".data";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_data1 = ".data1";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_debug = ".debug";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_dynamic = ".dynamic";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_dynstr = ".dynstr";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_dynsym = ".dynsym";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_fini = ".fini";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_got = ".got";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_hash = ".hash";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_init = ".init";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_interp = ".interp";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_line = ".line";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_note = ".note";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_plt = ".plt";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_rodata = ".rodata";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_rodata1 = ".rodata1";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_shstrtab = ".shstrtab";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_strtab = ".strtab";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_symtab = ".symtab";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_text = ".text";
|
||||
// Frequently used section names
|
||||
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_bss = ".bss";
|
||||
public static final String dot_comment = ".comment";
|
||||
public static final String dot_data = ".data";
|
||||
public static final String dot_data1 = ".data1";
|
||||
public static final String dot_debug = ".debug";
|
||||
public static final String dot_dynamic = ".dynamic";
|
||||
public static final String dot_dynstr = ".dynstr";
|
||||
public static final String dot_dynsym = ".dynsym";
|
||||
public static final String dot_fini = ".fini";
|
||||
public static final String dot_got = ".got";
|
||||
public static final String dot_hash = ".hash";
|
||||
public static final String dot_init = ".init";
|
||||
public static final String dot_interp = ".interp";
|
||||
public static final String dot_line = ".line";
|
||||
public static final String dot_note = ".note";
|
||||
public static final String dot_plt = ".plt";
|
||||
public static final String dot_rodata = ".rodata";
|
||||
public static final String dot_rodata1 = ".rodata1";
|
||||
public static final String dot_shstrtab = ".shstrtab";
|
||||
public static final String dot_strtab = ".strtab";
|
||||
public static final String dot_symtab = ".symtab";
|
||||
public static final String dot_text = ".text";
|
||||
public static final String dot_tbss = ".tbss";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_tdata = ".tdata";
|
||||
/**RESERVED SECTION NAME*/
|
||||
public static final String dot_tdata1 = ".tdata1";
|
||||
|
||||
// Section Header Types
|
||||
|
@ -106,9 +82,12 @@ public class ElfSectionHeaderConstants {
|
|||
public static final int SHT_PREINIT_ARRAY = 16;
|
||||
/**Section group*/
|
||||
public static final int SHT_GROUP = 17;
|
||||
/**Extended section indeces*/
|
||||
/**Extended section index table for linked symbol table */
|
||||
public static final int SHT_SYMTAB_SHNDX = 18;
|
||||
/**Experimental support - see proposal at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg */
|
||||
/**
|
||||
* Relative relocation table section
|
||||
* (see proposal at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
|
||||
*/
|
||||
public static final int SHT_RELR = 19;
|
||||
|
||||
// OS Specific Section Types
|
||||
|
@ -192,13 +171,4 @@ public class ElfSectionHeaderConstants {
|
|||
/**upper bound on range of reserved indexes*/
|
||||
public static final short SHN_HIRESERVE = (short) 0xffff;
|
||||
|
||||
/**
|
||||
* @param symbolSectionIndex symbol section index (st_shndx)
|
||||
* @return true if specified symbol section index corresponds to a processor
|
||||
* specific value in the range SHN_LOPROC..SHN_HIPROC, else false
|
||||
*/
|
||||
public static boolean isProcessorSpecificSymbolSectionIndex(short symbolSectionIndex) {
|
||||
return (Short.compareUnsigned(symbolSectionIndex, SHN_LOPROC) >= 0) &&
|
||||
(Short.compareUnsigned(symbolSectionIndex, SHN_HIPROC) <= 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,15 +32,14 @@ public class ElfStringTable implements ElfFileSection {
|
|||
|
||||
/**
|
||||
* Construct and parse an Elf string table
|
||||
* @param reader the binary reader containing the elf string table
|
||||
* @param header elf header
|
||||
* @param stringTableSection string table section header or null if associated with a dynamic table entry
|
||||
* @param fileOffset symbol table file offset
|
||||
* @param addrOffset memory address of symbol table (should already be adjusted for prelink)
|
||||
* @param length length of symbol table in bytes of -1 if unknown
|
||||
*/
|
||||
public ElfStringTable(BinaryReader reader, ElfHeader header,
|
||||
ElfSectionHeader stringTableSection, long fileOffset, long addrOffset, long length) {
|
||||
public ElfStringTable(ElfHeader header, ElfSectionHeader stringTableSection, long fileOffset,
|
||||
long addrOffset, long length) {
|
||||
this.header = header;
|
||||
this.stringTableSection = stringTableSection;
|
||||
this.fileOffset = fileOffset;
|
||||
|
|
|
@ -469,15 +469,36 @@ public class ElfSymbol implements ByteArrayConverter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Every symbol table entry is "defined" in relation to some section;
|
||||
* this member holds the relevant section header table index.
|
||||
* NOTE: This value reflects the raw st_shndx value and not the extended section index value
|
||||
* @return the relevant section header table index
|
||||
* Get the raw section index value (<code>st_shndx</code>) for this symbol.
|
||||
* Special values (SHN_LORESERVE and higher) must be treated properly. The value SHN_XINDEX
|
||||
* indicates that the extended value must be used to obtained the actual section index
|
||||
* (see {@link #getExtendedSectionHeaderIndex()}).
|
||||
* @return the <code>st_shndx</code> section index value
|
||||
*/
|
||||
public short getSectionHeaderIndex() {
|
||||
return st_shndx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extended symbol section index value when <code>st_shndx</code>
|
||||
* ({@link #getSectionHeaderIndex()}) has a value of SHN_XINDEX. This requires a lookup
|
||||
* into a table defined by an associated SHT_SYMTAB_SHNDX section.
|
||||
* @return extended symbol section index value
|
||||
*/
|
||||
public int getExtendedSectionHeaderIndex() {
|
||||
return symbolTable.getExtendedSectionIndex(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if st_shndx is within the reserved processor-specific index range
|
||||
* @return true if specified symbol section index corresponds to a processor
|
||||
* specific value in the range SHN_LOPROC..SHN_HIPROC, else false
|
||||
*/
|
||||
public boolean hasProcessorSpecificSymbolSectionIndex() {
|
||||
return (Short.compareUnsigned(st_shndx, ElfSectionHeaderConstants.SHN_LOPROC) >= 0) &&
|
||||
(Short.compareUnsigned(st_shndx, ElfSectionHeaderConstants.SHN_HIPROC) <= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Many symbols have associated sizes. For example, a data object's size is the number of
|
||||
* bytes contained in the object. This member holds 0 if the symbol has no size or an
|
||||
|
|
|
@ -32,8 +32,8 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
||||
|
||||
private ElfStringTable stringTable;
|
||||
|
||||
private ElfSectionHeader symbolTableSection; // may be null
|
||||
private int[] symbolSectionIndexTable;
|
||||
private long fileOffset;
|
||||
private long addrOffset;
|
||||
private long length;
|
||||
|
@ -55,12 +55,16 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
* @param length length of symbol table in bytes of -1 if unknown
|
||||
* @param entrySize size of each symbol entry in bytes
|
||||
* @param stringTable associated string table
|
||||
* @param symbolSectionIndexTable extended symbol section index table (may be null, used when
|
||||
* symbol <code>st_shndx == SHN_XINDEX</code>). See
|
||||
* {@link ElfSymbol#getExtendedSectionHeaderIndex()}).
|
||||
* @param isDynamic true if symbol table is the dynamic symbol table
|
||||
* @throws IOException if an IO or parse error occurs
|
||||
*/
|
||||
public ElfSymbolTable(BinaryReader reader, ElfHeader header,
|
||||
ElfSectionHeader symbolTableSection, long fileOffset, long addrOffset, long length,
|
||||
long entrySize, ElfStringTable stringTable, boolean isDynamic) throws IOException {
|
||||
long entrySize, ElfStringTable stringTable, int[] symbolSectionIndexTable,
|
||||
boolean isDynamic) throws IOException {
|
||||
|
||||
this.symbolTableSection = symbolTableSection;
|
||||
this.fileOffset = fileOffset;
|
||||
|
@ -69,6 +73,7 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
this.entrySize = entrySize;
|
||||
this.stringTable = stringTable;
|
||||
this.is32bit = header.is32Bit();
|
||||
this.symbolSectionIndexTable = symbolSectionIndexTable;
|
||||
this.isDynamic = isDynamic;
|
||||
|
||||
long ptr = reader.getPointerIndex();
|
||||
|
@ -136,6 +141,24 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
return symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extended symbol section index value for the specified ELF symbol which originated
|
||||
* from this symbol table. This section index is provided by an associated SHT_SYMTAB_SHNDX
|
||||
* section when the symbols st_shndx == SHN_XINDEX.
|
||||
* @param sym ELF symbol from this symbol table
|
||||
* @return associated extended section index value or 0 if not defined.
|
||||
*/
|
||||
public int getExtendedSectionIndex(ElfSymbol sym) {
|
||||
if (sym.getSectionHeaderIndex() == ElfSectionHeaderConstants.SHN_XINDEX &&
|
||||
symbolSectionIndexTable != null) {
|
||||
int symbolTableIndex = sym.getSymbolTableIndex();
|
||||
if (symbolTableIndex < symbolSectionIndexTable.length) {
|
||||
return symbolSectionIndexTable[symbolTableIndex];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the specified symbol in this
|
||||
* symbol table.
|
||||
|
|
|
@ -1162,6 +1162,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
component.addOperandReference(0, sectionAddr, RefType.DATA,
|
||||
SourceType.IMPORTED);
|
||||
}
|
||||
|
||||
if (sections[i].getType() == ElfSectionHeaderConstants.SHT_SYMTAB_SHNDX) {
|
||||
markupSymbolSectionHeaderIndex(sections[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -1169,6 +1173,17 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private void markupSymbolSectionHeaderIndex(ElfSectionHeader section) {
|
||||
Address sectionAddr = findLoadAddress(section, 0);
|
||||
if (sectionAddr == null) {
|
||||
return;
|
||||
}
|
||||
// determine number of 32-bit index elements for DWORD[]
|
||||
int count = (int) (section.getSize() / 4);
|
||||
DataType dt = new ArrayDataType(DWordDataType.dataType, count, -1);
|
||||
createData(sectionAddr, dt);
|
||||
}
|
||||
|
||||
private void markupRelocationTable(Address relocTableAddr, ElfRelocationTable relocTable,
|
||||
TaskMonitor monitor) {
|
||||
try {
|
||||
|
@ -1583,7 +1598,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
boolean isAllocatedToSection = false;
|
||||
if (sectionIndex == ElfSectionHeaderConstants.SHN_UNDEF) { // Not section relative 0x0000 (e.g., no sections defined)
|
||||
|
||||
Address regAddr = findMemoryRegister(elfSymbol);
|
||||
if (regAddr != null) {
|
||||
return regAddr;
|
||||
|
@ -1595,9 +1609,22 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
symOffset = loadAdapter.getAdjustedMemoryOffset(symOffset, defaultSpace);
|
||||
symOffset += getImageBaseWordAdjustmentOffset();
|
||||
}
|
||||
else if (Short.compareUnsigned(sectionIndex, ElfSectionHeaderConstants.SHN_LORESERVE) < 0) {
|
||||
else if (Short.compareUnsigned(sectionIndex, ElfSectionHeaderConstants.SHN_LORESERVE) < 0 ||
|
||||
sectionIndex == ElfSectionHeaderConstants.SHN_XINDEX) {
|
||||
|
||||
isAllocatedToSection = true;
|
||||
int uSectionIndex = Short.toUnsignedInt(sectionIndex);
|
||||
|
||||
if (sectionIndex == ElfSectionHeaderConstants.SHN_XINDEX) {
|
||||
uSectionIndex = elfSymbol.getExtendedSectionHeaderIndex();
|
||||
if (uSectionIndex == 0) {
|
||||
log("Failed to read extended symbol section index: " +
|
||||
elfSymbol.getNameAsString() + " - value=0x" +
|
||||
Long.toHexString(elfSymbol.getValue()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uSectionIndex < elfSections.length) {
|
||||
|
||||
ElfSectionHeader symSection = elf.getSections()[uSectionIndex];
|
||||
|
@ -1641,11 +1668,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
else if (sectionIndex == ElfSectionHeaderConstants.SHN_ABS) { // Absolute value/address - 0xfff1
|
||||
|
||||
byte type = elfSymbol.getType();
|
||||
if (type == ElfSymbol.STT_FILE) {
|
||||
return null; // ignore file symbol
|
||||
}
|
||||
|
||||
// Absolute symbols will be pinned to associated address
|
||||
symbolSpace = defaultDataSpace;
|
||||
if (elfSymbol.isFunction()) {
|
||||
|
|
|
@ -336,11 +336,11 @@ public class MIPS_ElfExtension extends ElfExtension {
|
|||
public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol)
|
||||
throws NoValueException {
|
||||
|
||||
short sectionIndex = elfSymbol.getSectionHeaderIndex();
|
||||
if (!ElfSectionHeaderConstants.isProcessorSpecificSymbolSectionIndex(sectionIndex)) {
|
||||
if (!elfSymbol.hasProcessorSpecificSymbolSectionIndex()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
short sectionIndex = elfSymbol.getSectionHeaderIndex();
|
||||
if (sectionIndex == SHN_MIPS_ACOMMON || sectionIndex == SHN_MIPS_TEXT || sectionIndex == SHN_MIPS_DATA) {
|
||||
// NOTE: logic assumes no memory conflict occured during section loading
|
||||
AddressSpace defaultSpace = elfLoadHelper.getProgram().getAddressFactory().getDefaultAddressSpace();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue