diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java index c17d0a2373..6607334388 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java @@ -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; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java index 3b7c2858cb..f0d0ee8b70 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java @@ -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) + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java index 3506725254..2c8a689364 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java @@ -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 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; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java index eaf0104300..572db5afcf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java @@ -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) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java index 8e6339af80..5929bcaa82 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java @@ -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); - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java index 7c72600010..e31676d8c2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java @@ -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; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java index 767fa9ebde..e73e5707d6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java @@ -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 (st_shndx) 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 st_shndx section index value */ public short getSectionHeaderIndex() { return st_shndx; } + /** + * Get the extended symbol section index value when st_shndx + * ({@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 diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java index a17a70a2cd..197bd93970 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java @@ -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 st_shndx == SHN_XINDEX). 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. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 07e11f1a18..69d86e5bb6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -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()) { diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java index 0301de5ab1..1c0091872f 100644 --- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java +++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java @@ -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();