mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 01:39:21 +02:00
GP-697_emteere delayed reading of symbol names to improve memory read performance
This commit is contained in:
parent
efa065ac4d
commit
01b6027c77
2 changed files with 122 additions and 67 deletions
|
@ -103,11 +103,24 @@ public class ElfSymbol implements ByteArrayConverter {
|
|||
|
||||
private String nameAsString;
|
||||
|
||||
/**
|
||||
* create an ElfSymbol()
|
||||
* Warning! the routine initSymbolName() must be called on the symbol later
|
||||
* to initialize the string name. This is a performance enhancement.
|
||||
*
|
||||
* @param reader to read symbol from
|
||||
* @param symbolIndex index of the symbol to read
|
||||
* @param symbolTable symbol table to associate the symbol to
|
||||
* @param stringTable string table to read symbols from
|
||||
* @param header else header
|
||||
* @return newly created ElfSymbol
|
||||
*
|
||||
* @throws IOException if an issue with reading occurs
|
||||
*/
|
||||
public static ElfSymbol createElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex,
|
||||
ElfSymbolTable symbolTable, ElfStringTable stringTable, ElfHeader header)
|
||||
throws IOException {
|
||||
ElfSymbolTable symbolTable, ElfHeader header) throws IOException {
|
||||
ElfSymbol elfSymbol = (ElfSymbol) reader.getFactory().create(ElfSymbol.class);
|
||||
elfSymbol.initElfSymbol(reader, symbolIndex, symbolTable, stringTable, header);
|
||||
elfSymbol.initElfSymbol(reader, symbolIndex, symbolTable, header);
|
||||
return elfSymbol;
|
||||
}
|
||||
|
||||
|
@ -117,49 +130,6 @@ public class ElfSymbol implements ByteArrayConverter {
|
|||
public ElfSymbol() {
|
||||
}
|
||||
|
||||
private void initElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex,
|
||||
ElfSymbolTable symbolTable, ElfStringTable stringTable, ElfHeader header)
|
||||
throws IOException {
|
||||
this.header = header;
|
||||
this.symbolTable = symbolTable;
|
||||
this.symbolTableIndex = symbolIndex;
|
||||
|
||||
if (header.is32Bit()) {
|
||||
st_name = reader.readNextInt();
|
||||
st_value = reader.readNextInt() & Conv.INT_MASK;
|
||||
st_size = reader.readNextInt() & Conv.INT_MASK;
|
||||
st_info = reader.readNextByte();
|
||||
st_other = reader.readNextByte();
|
||||
st_shndx = reader.readNextShort();
|
||||
}
|
||||
else {
|
||||
st_name = reader.readNextInt();
|
||||
st_info = reader.readNextByte();
|
||||
st_other = reader.readNextByte();
|
||||
st_shndx = reader.readNextShort();
|
||||
st_value = reader.readNextLong();
|
||||
st_size = reader.readNextLong();
|
||||
}
|
||||
|
||||
if (st_name == 0) {
|
||||
if (getType() == STT_SECTION) {
|
||||
ElfSectionHeader[] sections = header.getSections();
|
||||
if (st_shndx < 0 || st_shndx >= sections.length) {
|
||||
//invalid section reference...
|
||||
//this is a bug in objcopy, whereby sections are removed
|
||||
//but the corresponding section symbols are left behind.
|
||||
}
|
||||
else {
|
||||
ElfSectionHeader section = sections[st_shndx];
|
||||
nameAsString = section.getNameAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
nameAsString = stringTable.readString(reader, st_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new section symbol.
|
||||
* @param header the corresponding ELF header
|
||||
|
@ -209,6 +179,69 @@ public class ElfSymbol implements ByteArrayConverter {
|
|||
this.symbolTableIndex = symbolIndex;
|
||||
}
|
||||
|
||||
private void initElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex,
|
||||
ElfSymbolTable symbolTable, ElfHeader header) throws IOException {
|
||||
this.header = header;
|
||||
this.symbolTable = symbolTable;
|
||||
this.symbolTableIndex = symbolIndex;
|
||||
|
||||
if (header.is32Bit()) {
|
||||
st_name = reader.readNextInt();
|
||||
st_value = reader.readNextInt() & Conv.INT_MASK;
|
||||
st_size = reader.readNextInt() & Conv.INT_MASK;
|
||||
st_info = reader.readNextByte();
|
||||
st_other = reader.readNextByte();
|
||||
st_shndx = reader.readNextShort();
|
||||
}
|
||||
else {
|
||||
st_name = reader.readNextInt();
|
||||
st_info = reader.readNextByte();
|
||||
st_other = reader.readNextByte();
|
||||
st_shndx = reader.readNextShort();
|
||||
st_value = reader.readNextLong();
|
||||
st_size = reader.readNextLong();
|
||||
}
|
||||
|
||||
if (st_name == 0) {
|
||||
if (getType() == STT_SECTION) {
|
||||
ElfSectionHeader[] sections = header.getSections();
|
||||
if (st_shndx < 0 || st_shndx >= sections.length) {
|
||||
//invalid section reference...
|
||||
//this is a bug in objcopy, whereby sections are removed
|
||||
//but the corresponding section symbols are left behind.
|
||||
}
|
||||
else {
|
||||
ElfSectionHeader section = sections[st_shndx];
|
||||
nameAsString = section.getNameAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The string name will be initialized later
|
||||
// in a call to initSymbolName()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the string name of the symbol.
|
||||
*
|
||||
* NOTE: This routine MUST be called for each
|
||||
* ELFSymbol after the elf symbols have been created.
|
||||
*
|
||||
* This is done separately from the initial symbol entry read because
|
||||
* the string names are in a separate location. If they are read
|
||||
* at the same time the reading buffer will jump around and significantly
|
||||
* degrade reading performance.
|
||||
*
|
||||
* @param reader to read from
|
||||
* @param stringTable stringTable to initialize symbol name
|
||||
*/
|
||||
public void initSymbolName(FactoryBundledWithBinaryReader reader, ElfStringTable stringTable) {
|
||||
if (nameAsString == null) {
|
||||
nameAsString = stringTable.readString(reader, st_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the symbol table containing this symbol
|
||||
* @return symbol table
|
||||
|
@ -249,27 +282,37 @@ public class ElfSymbol implements ByteArrayConverter {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
if (this == obj) {
|
||||
return true;
|
||||
if (obj == null)
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ElfSymbol other = (ElfSymbol) obj;
|
||||
if (st_info != other.st_info)
|
||||
if (st_info != other.st_info) {
|
||||
return false;
|
||||
if (st_name != other.st_name)
|
||||
}
|
||||
if (st_name != other.st_name) {
|
||||
return false;
|
||||
if (st_other != other.st_other)
|
||||
}
|
||||
if (st_other != other.st_other) {
|
||||
return false;
|
||||
if (st_shndx != other.st_shndx)
|
||||
}
|
||||
if (st_shndx != other.st_shndx) {
|
||||
return false;
|
||||
if (st_size != other.st_size)
|
||||
}
|
||||
if (st_size != other.st_size) {
|
||||
return false;
|
||||
if (st_value != other.st_value)
|
||||
}
|
||||
if (st_value != other.st_value) {
|
||||
return false;
|
||||
if (symbolTableIndex != other.symbolTableIndex)
|
||||
}
|
||||
if (symbolTableIndex != other.symbolTableIndex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.util.bin.format.elf;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.app.util.bin.ByteArrayConverter;
|
||||
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
||||
|
@ -96,15 +97,26 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
|
||||
long entryPos = reader.getPointerIndex();
|
||||
|
||||
// load the all the symbol entries first, don't initialize the string name
|
||||
// that will be done later to help localize memory access
|
||||
for (int i = 0; i < symbolCount; i++) {
|
||||
// Reposition reader to start of symbol element since ElfSymbol object
|
||||
// may not consume all symbol element data
|
||||
reader.setPointerIndex(entryPos);
|
||||
ElfSymbol sym = ElfSymbol.createElfSymbol(reader, i, this, stringTable, header);
|
||||
ElfSymbol sym = ElfSymbol.createElfSymbol(reader, i, this, header);
|
||||
symbolList.add(sym);
|
||||
entryPos += entrySize;
|
||||
}
|
||||
|
||||
// sort the entries by the index in the string table, so don't jump around reading
|
||||
List<ElfSymbol> sortedList = symbolList.stream().sorted(
|
||||
(o1, o2) -> Integer.compare(o1.getName(), o2.getName())).collect(Collectors.toList());
|
||||
|
||||
// initialize the Symbol string names from string table
|
||||
for (ElfSymbol sym : sortedList) {
|
||||
sym.initSymbolName(reader, stringTable);
|
||||
}
|
||||
|
||||
reader.setPointerIndex(ptr);
|
||||
|
||||
symbols = new ElfSymbol[symbolList.size()];
|
||||
|
@ -163,9 +175,9 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
* @return the symbol at the specified address
|
||||
*/
|
||||
public ElfSymbol getSymbolAt(long addr) {
|
||||
for (int i = 0; i < symbols.length; i++) {
|
||||
if (symbols[i].getValue() == addr) {
|
||||
return symbols[i];
|
||||
for (ElfSymbol symbol : symbols) {
|
||||
if (symbol.getValue() == addr) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -177,9 +189,9 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
*/
|
||||
public ElfSymbol[] getGlobalSymbols() {
|
||||
List<ElfSymbol> list = new ArrayList<>();
|
||||
for (int i = 0; i < symbols.length; i++) {
|
||||
if (symbols[i].getBind() == ElfSymbol.STB_GLOBAL) {
|
||||
list.add(symbols[i]);
|
||||
for (ElfSymbol symbol : symbols) {
|
||||
if (symbol.getBind() == ElfSymbol.STB_GLOBAL) {
|
||||
list.add(symbol);
|
||||
}
|
||||
}
|
||||
ElfSymbol[] array = new ElfSymbol[list.size()];
|
||||
|
@ -193,11 +205,11 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
*/
|
||||
public String[] getSourceFiles() {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (int j = 0; j < symbols.length; j++) {
|
||||
if (symbols[j].getType() == ElfSymbol.STT_FILE) {
|
||||
String name = symbols[j].getNameAsString();
|
||||
for (ElfSymbol symbol : symbols) {
|
||||
if (symbol.getType() == ElfSymbol.STT_FILE) {
|
||||
String name = symbol.getNameAsString();
|
||||
if (name != null) {
|
||||
list.add(symbols[j].getNameAsString());
|
||||
list.add(symbol.getNameAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue