diff --git a/src/main/java/net/fornwall/jelf/ElfFile.java b/src/main/java/net/fornwall/jelf/ElfFile.java index 1123252..7b5c23d 100644 --- a/src/main/java/net/fornwall/jelf/ElfFile.java +++ b/src/main/java/net/fornwall/jelf/ElfFile.java @@ -137,43 +137,40 @@ public ElfStringTable getSectionNameStringTable() throws ElfException, IOExcepti /** Returns the string table associated with this ELF file. */ public ElfStringTable getStringTable() throws ElfException, IOException { - return findStringTableWithName(ElfSection.STRING_TABLE_NAME); + return findStringTableWithName(ElfSection.NAME_STRTAB); } /** * Returns the dynamic symbol table associated with this ELF file, or null if one does not exist. */ public ElfStringTable getDynamicStringTable() throws ElfException, IOException { - return findStringTableWithName(ElfSection.DYNAMIC_STRING_TABLE_NAME); + return findStringTableWithName(ElfSection.NAME_DYNSTR); } private ElfStringTable findStringTableWithName(String tableName) throws ElfException, IOException { // Loop through the section header and look for a section // header with the name "tableName". We can ignore entry 0 // since it is defined as being undefined. - for (int i = 1; i < num_sh; i++) { - ElfSection sh = getSection(i); - if (tableName.equals(sh.getName())) return sh.getStringTable(); - } - return null; + ElfSection section = firstSectionByName(tableName); + return section == null ? null : section.getStringTable(); } /** The {@link ElfSection#SHT_SYMTAB} section (of which there may be only one), if any. */ - public ElfSection getSymbolTableSection() throws ElfException, IOException { - return (symbolTableSection != null) ? symbolTableSection : (symbolTableSection = getSymbolTableSection(ElfSection.SHT_SYMTAB)); + public ElfSection firstSectionByType() throws ElfException, IOException { + return (symbolTableSection != null) ? symbolTableSection : (symbolTableSection = firstSectionByType(ElfSection.SHT_SYMTAB)); } /** The {@link ElfSection#SHT_DYNSYM} section (of which there may be only one), if any. */ public ElfSection getDynamicSymbolTableSection() throws ElfException, IOException { - return (dynamicSymbolTableSection != null) ? dynamicSymbolTableSection : (dynamicSymbolTableSection = getSymbolTableSection(ElfSection.SHT_DYNSYM)); + return (dynamicSymbolTableSection != null) ? dynamicSymbolTableSection : (dynamicSymbolTableSection = firstSectionByType(ElfSection.SHT_DYNSYM)); } /** The {@link ElfSection#SHT_DYNAMIC} section (of which there may be only one). Named ".dynamic". */ public ElfSection getDynamicLinkSection() throws IOException { - return (dynamicLinkSection != null) ? dynamicLinkSection : (dynamicLinkSection = getSymbolTableSection(ElfSection.SHT_DYNAMIC)); + return (dynamicLinkSection != null) ? dynamicLinkSection : (dynamicLinkSection = firstSectionByType(ElfSection.SHT_DYNAMIC)); } - private ElfSection getSymbolTableSection(int type) throws ElfException, IOException { + public ElfSection firstSectionByType(int type) throws ElfException, IOException { for (int i = 1; i < num_sh; i++) { ElfSection sh = getSection(i); if (sh.type == type) return sh; @@ -181,6 +178,14 @@ private ElfSection getSymbolTableSection(int type) throws ElfException, IOExcept return null; } + public ElfSection firstSectionByName(String sectionName) throws ElfException, IOException { + for (int i = 1; i < num_sh; i++) { + ElfSection sh = getSection(i); + if (sectionName.equals(sh.getName())) return sh; + } + return null; + } + /** Returns the elf symbol with the specified name or null if one is not found. */ public ElfSymbol getELFSymbol(String symbolName) throws ElfException, IOException { if (symbolName == null) return null; @@ -200,7 +205,7 @@ public ElfSymbol getELFSymbol(String symbolName) throws ElfException, IOExceptio } // Check symbol table for symbol name. - sh = getSymbolTableSection(); + sh = firstSectionByType(); if (sh != null) { int numSymbols = sh.getNumberOfSymbols(); for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { @@ -229,19 +234,19 @@ public ElfSymbol getELFSymbol(long address) throws ElfException, IOException { int numSymbols = sh.getNumberOfSymbols(); for (int i = 0; i < numSymbols; i++) { symbol = sh.getELFSymbol(i); - value = symbol.value; - if (address >= value && address < value + symbol.size) return symbol; + value = symbol.st_value; + if (address >= value && address < value + symbol.st_size) return symbol; } } // Check symbol table for symbol name. - sh = getSymbolTableSection(); + sh = firstSectionByType(); if (sh != null) { int numSymbols = sh.getNumberOfSymbols(); for (int i = 0; i < numSymbols; i++) { symbol = sh.getELFSymbol(i); - value = symbol.value; - if (address >= value && address < value + symbol.size) return symbol; + value = symbol.st_value; + if (address >= value && address < value + symbol.st_size) return symbol; } } return null; diff --git a/src/main/java/net/fornwall/jelf/ElfSection.java b/src/main/java/net/fornwall/jelf/ElfSection.java index cb5540a..5d4f146 100644 --- a/src/main/java/net/fornwall/jelf/ElfSection.java +++ b/src/main/java/net/fornwall/jelf/ElfSection.java @@ -4,19 +4,19 @@ /** * Class corresponding to the Elf32_Shdr/Elf64_Shdr struct. - * + * *
* An object file's section header table lets one locate all the file's sections. The section header table is an array * of Elf32_Shdr or Elf64_Shdr structures. A section header table index is a subscript into this array. The ELF header's * {@link ElfFile#sh_offset e_shoff member} gives the byte offset from the beginning of the file to the section header * table with each section header entry being {@link ElfFile#sh_entry_size e_shentsize} bytes big. - * + * *
* {@link ElfFile#num_sh e_shnum} normally tells how many entries the section header table contains, but if the number * of sections is greater than or equal to SHN_LORESERVE (0xff00), e_shnum has the value SHN_UNDEF (0) and the actual * number of section header table entries is contained in the sh_size field of the section header at index 0 (otherwise, * the sh_size member of the initial entry contains 0). - * + * *
* Some section header table indexes are reserved in contexts where index size is restricted, for example, the st_shndx * member of a symbol table entry and the e_shnum and e_shstrndx members of the ELF header. In such contexts, the @@ -91,10 +91,21 @@ public final class ElfSection { /** Flag informing that all the bits in the mask are reserved for processor specific semantics. */ public static final int FLAG_MASK = 0xf0000000; - /** Section header name identifying the section as a string table. */ - public static final String STRING_TABLE_NAME = ".strtab"; - /** Section header name identifying the section as a dynamic string table. */ - public static final String DYNAMIC_STRING_TABLE_NAME = ".dynstr"; + /** + * Name for the section containing the string table. + *
+ * This section contains a string table which contains names for symbol structures + * by being indexed by the {@link ElfSymbol#st_name} field. + */ + public static final String NAME_STRTAB = ".strtab"; + /** + * Name for the section containing the dynamic string table. + */ + public static final String NAME_DYNSTR = ".dynstr"; + /** + * Name for the section containing read-only initialized data. + */ + public static final String NAME_RODATA = ".rodata"; /** Index into the section header string table which gives the name of the section. */ public final int name_ndx; // Elf32_Word or Elf64_Word - 4 bytes in both. diff --git a/src/main/java/net/fornwall/jelf/ElfSymbol.java b/src/main/java/net/fornwall/jelf/ElfSymbol.java index a8f8e8a..637afc3 100644 --- a/src/main/java/net/fornwall/jelf/ElfSymbol.java +++ b/src/main/java/net/fornwall/jelf/ElfSymbol.java @@ -3,7 +3,29 @@ import java.io.IOException; /** - * Class corresponding to the Elf32_Sym/Elf64_Sym struct. + * An entry in the symbol table, which holds information needed to locate and relocate a program's symbolic definitions and references. + *
+ * In the elf.h header file the struct definitions are: + * + *
+ * typedef struct { + * uint32_t st_name; + * Elf32_Addr st_value; + * uint32_t st_size; + * unsigned char st_info; + * unsigned char st_other; + * uint16_t st_shndx; + * } Elf32_Sym; + * + * typedef struct { + * uint32_t st_name; + * unsigned char st_info; + * unsigned char st_other; + * uint16_t st_shndx; + * Elf64_Addr st_value; + * uint64_t st_size; + * } Elf64_Sym; + **/ public final class ElfSymbol { @@ -49,22 +71,22 @@ public final class ElfSymbol { * Index into the symbol string table that holds the character representation of the symbols. 0 means the symbol has * no character name. */ - private final int name_ndx; // Elf32_Word - /** Value of the associated symbol. This may be a relativa address for .so or absolute address for other ELFs. */ - public final long value; // Elf32_Addr + public final int st_name; // Elf32_Word + /** Value of the associated symbol. This may be a relative address for .so or absolute address for other ELFs. */ + public final long st_value; // Elf32_Addr /** Size of the symbol. 0 if the symbol has no size or the size is unknown. */ - public final long size; // Elf32_Word + public final long st_size; // Elf32_Word /** Specifies the symbol type and binding attributes. */ - private final short info; // unsigned char + public final short st_info; // unsigned char /** Currently holds the value of 0 and has no meaning. */ - public final short other; // unsigned char + public final short st_other; // unsigned char /** * Index to the associated section header. This value will need to be read as an unsigned short if we compare it to * ELFSectionHeader.NDX_LORESERVE and ELFSectionHeader.NDX_HIRESERVE. */ - public final short section_header_ndx; // Elf32_Half + public final short st_shndx; // Elf32_Half - private final int section_type; + public final int section_type; /** Offset from the beginning of the file to this symbol. */ public final long offset; @@ -76,19 +98,19 @@ public final class ElfSymbol { parser.seek(offset); this.offset = offset; if (parser.elfFile.objectSize == ElfFile.CLASS_32) { - name_ndx = parser.readInt(); - value = parser.readInt(); - size = parser.readInt(); - info = parser.readUnsignedByte(); - other = parser.readUnsignedByte(); - section_header_ndx = parser.readShort(); + st_name = parser.readInt(); + st_value = parser.readInt(); + st_size = parser.readInt(); + st_info = parser.readUnsignedByte(); + st_other = parser.readUnsignedByte(); + st_shndx = parser.readShort(); } else { - name_ndx = parser.readInt(); - info = parser.readUnsignedByte(); - other = parser.readUnsignedByte(); - section_header_ndx = parser.readShort(); - value = parser.readLong(); - size = parser.readLong(); + st_name = parser.readInt(); + st_info = parser.readUnsignedByte(); + st_other = parser.readUnsignedByte(); + st_shndx = parser.readShort(); + st_value = parser.readLong(); + st_size = parser.readLong(); } this.section_type = section_type; @@ -115,25 +137,25 @@ public final class ElfSymbol { /** Returns the binding for this symbol. */ public int getBinding() { - return info >> 4; + return st_info >> 4; } /** Returns the symbol type. */ public int getType() { - return info & 0x0F; + return st_info & 0x0F; } /** Returns the name of the symbol or null if the symbol has no name. */ public String getName() throws ElfException, IOException { // Check to make sure this symbol has a name. - if (name_ndx == 0) return null; + if (st_name == 0) return null; // Retrieve the name of the symbol from the correct string table. String symbol_name = null; if (section_type == ElfSection.SHT_SYMTAB) { - symbol_name = elfHeader.getStringTable().get(name_ndx); + symbol_name = elfHeader.getStringTable().get(st_name); } else if (section_type == ElfSection.SHT_DYNSYM) { - symbol_name = elfHeader.getDynamicStringTable().get(name_ndx); + symbol_name = elfHeader.getDynamicStringTable().get(st_name); } return symbol_name; } @@ -169,7 +191,7 @@ public String toString() { } try { - return "ElfSymbol[name=" + getName() + ", type=" + typeString + ", size=" + size + "]"; + return "ElfSymbol[name=" + getName() + ", type=" + typeString + ", size=" + st_size + "]"; } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/test/java/net/fornwall/jelf/BasicTest.java b/src/test/java/net/fornwall/jelf/BasicTest.java index a59f7ef..16fdc50 100644 --- a/src/test/java/net/fornwall/jelf/BasicTest.java +++ b/src/test/java/net/fornwall/jelf/BasicTest.java @@ -124,6 +124,10 @@ public void testLinxAmd64BinDash() throws ElfException, FileNotFoundException, I Assert.assertEquals(Collections.singletonList("libc.so.6"), ds.getNeededLibraries()); Assert.assertEquals("/lib64/ld-linux-x86-64.so.2", file.getInterpreter()); + + ElfSection rodata = file.firstSectionByName(ElfSection.NAME_RODATA); + Assert.assertNotNull(rodata); + Assert.assertEquals(ElfSection.SHT_PROGBITS, rodata.type); } }