use of com.ibm.j9ddr.corereaders.memory.Symbol in project openj9 by eclipse.
the class ModuleStream method buildSymbols.
/**
* Looks at the module loaded at imageBase in the given dump and produces
* a symbol table for which it returns the iterator.
* @param dump
* @param builder
* @param imageBase
* @param moduleLoadAddress
* @return
* @throws CorruptCoreException
*/
private List<ISymbol> buildSymbols(MiniDumpReader dump, IAddressSpace as, long imageBase) throws CorruptDataException, CorruptCoreException {
long moduleLoadAddress = imageBase;
byte[] magic = new byte[2];
as.getBytesAt(imageBase, magic);
String magicStr = null;
try {
magicStr = new String(magic, "ASCII");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
if (!magicStr.equals("MZ")) {
throw new CorruptCoreException("Invalid image magic number: \"" + magicStr + "\" @ " + Long.toHexString(imageBase));
}
// look up the PE offset: it is base+3c
int peInt = as.getIntAt(imageBase + 0x3cL);
long peBase = (peInt & 0xFFFFFFFFL) + imageBase;
// * typedef struct _IMAGE_NT_HEADERS {
// DWORD Signature;
as.getBytesAt(peBase, magic);
try {
magicStr = new String(magic, "UTF-8");
} catch (UnsupportedEncodingException e) {
// UTF-8 will be supported.
}
if (!magicStr.equals("PE")) {
throw new CorruptCoreException("Invalid PE magic number: \"" + magicStr + "\" @ " + Long.toHexString(peBase));
}
long nextRead = peBase + 4;
// IMAGE_FILE_HEADER FileHeader;
// IMAGE_OPTIONAL_HEADER32 OptionalHeader;
// cue us up to the optional header
// typedef struct _IMAGE_FILE_HEADER {
// short machine = dump.readShort(); // WORD Machine;
nextRead += 2;
// dump.readShort(); // WORD NumberOfSections;
nextRead += 2;
// dump.readInt(); // DWORD TimeDateStamp;
nextRead += 4;
// dump.readInt(); // DWORD PointerToSymbolTable;
nextRead += 4;
// dump.readInt(); // DWORD NumberOfSymbols;
nextRead += 4;
long imageOptionalHeaderSizeAddress = nextRead;
// WORD SizeOfOptionalHeader;
short optionalHeaderSize = as.getShortAt(imageOptionalHeaderSizeAddress);
nextRead += 2;
// dump.readShort(); // WORD Characteristics;
nextRead += 2;
// cue us up to the first data directory
if (224 == optionalHeaderSize) {
// 32-bit optional header
// typedef struct _IMAGE_OPTIONAL_HEADER {
short magicShort = as.getShortAt(nextRead);
if (0x10b != magicShort) {
throw new CorruptCoreException("Invalid IMAGE_OPTIONAL_HEADER magic number: \"0x" + Integer.toHexString(0xFFFF & magicShort) + "\" @ " + Long.toHexString(nextRead));
}
// dump.readBytes(2); // WORD Magic;
nextRead += 2;
// dump.readByte(); // BYTE MajorLinkerVersion;
nextRead += 1;
// dump.readByte(); // BYTE MinorLinkerVersion;
nextRead += 1;
// dump.readInt(); // DWORD SizeOfCode;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfInitializedData;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfUninitializedData;
nextRead += 4;
// dump.readInt(); // DWORD AddressOfEntryPoint;
nextRead += 4;
// dump.readInt(); // DWORD BaseOfCode;
nextRead += 4;
// dump.readInt(); // DWORD BaseOfData;
nextRead += 4;
// dump.readInt(); // DWORD ImageBase;
nextRead += 4;
// dump.readInt(); // DWORD SectionAlignment;
nextRead += 4;
// dump.readInt(); // DWORD FileAlignment;
nextRead += 4;
// dump.readShort(); // WORD MajorOperatingSystemVersion;
nextRead += 2;
// dump.readShort(); // WORD MinorOperatingSystemVersion;
nextRead += 2;
// dump.readShort(); // WORD MajorImageVersion;
nextRead += 2;
// dump.readShort(); // WORD MinorImageVersion;
nextRead += 2;
// dump.readShort(); // WORD MajorSubsystemVersion;
nextRead += 2;
// dump.readShort(); // WORD MinorSubsystemVersion;
nextRead += 2;
// dump.readInt(); // DWORD Win32VersionValue;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfImage;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfHeaders;
nextRead += 4;
// dump.readInt(); // DWORD CheckSum;
nextRead += 4;
// dump.readShort(); // WORD Subsystem;
nextRead += 2;
// dump.readShort(); // WORD DllCharacteristics;
nextRead += 2;
// dump.readInt(); // DWORD SizeOfStackReserve;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfStackCommit;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfHeapReserve;
nextRead += 4;
// dump.readInt(); // DWORD SizeOfHeapCommit;
nextRead += 4;
// dump.readInt(); // DWORD LoaderFlags;
nextRead += 4;
// dump.readInt(); // DWORD NumberOfRvaAndSizes;
nextRead += 4;
// IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
// } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
} else if (240 == optionalHeaderSize) {
// 64-bit optional header
// typedef struct _IMAGE_OPTIONAL_HEADER64 {
short magicShort = as.getShortAt(nextRead);
if (0x20b != magicShort) {
throw new CorruptCoreException("Invalid IMAGE_OPTIONAL_HEADER64 magic number: \"0x" + Integer.toHexString(0xFFFF & magicShort) + "\" @ " + Long.toHexString(nextRead));
}
// WORD Magic;
nextRead += 2;
// BYTE MajorLinkerVersion;
nextRead += 1;
// BYTE MinorLinkerVersion;
nextRead += 1;
// DWORD SizeOfCode;
nextRead += 4;
// DWORD SizeOfInitializedData;
nextRead += 4;
// DWORD SizeOfUninitializedData;
nextRead += 4;
// DWORD AddressOfEntryPoint;
nextRead += 4;
// DWORD BaseOfCode;
nextRead += 4;
// ULONGLONG ImageBase;
nextRead += 8;
// DWORD SectionAlignment;
nextRead += 4;
// DWORD FileAlignment;
nextRead += 4;
// WORD MajorOperatingSystemVersion;
nextRead += 2;
// WORD MinorOperatingSystemVersion;
nextRead += 2;
// WORD MajorImageVersion;
nextRead += 2;
// WORD MinorImageVersion;
nextRead += 2;
// WORD MajorSubsystemVersion;
nextRead += 2;
// WORD MinorSubsystemVersion;
nextRead += 2;
// DWORD Win32VersionValue;
nextRead += 4;
// DWORD SizeOfImage;
nextRead += 4;
// DWORD SizeOfHeaders;
nextRead += 4;
// DWORD CheckSum;
nextRead += 4;
// WORD Subsystem;
nextRead += 2;
// WORD DllCharacteristics;
nextRead += 2;
// ULONGLONG SizeOfStackReserve;
nextRead += 8;
// ULONGLONG SizeOfStackCommit;
nextRead += 8;
// ULONGLONG SizeOfHeapReserve;
nextRead += 8;
// ULONGLONG SizeOfHeapCommit;
nextRead += 8;
// DWORD LoaderFlags;
nextRead += 4;
// DWORD NumberOfRvaAndSizes;
nextRead += 4;
// IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
// } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
} else {
// invalid size
throw new CorruptCoreException("Invalid IMAGE_OPTIONAL_HEADER size: \"" + optionalHeaderSize + "\" bytes @ " + Long.toHexString(imageOptionalHeaderSizeAddress));
}
// we should now be at the data directory
// typedef struct _IMAGE_DATA_DIRECTORY
// note that it is this first directory which we are interested in since
// it is the export dir
// read that pointer and size and calculate where to seek to to begin work
// again
// DWORD VirtualAddress;
int exportRVA = as.getIntAt(nextRead);
nextRead += 4;
if (0 == exportRVA) {
// this module has no exports so return empty
return Collections.emptyList();
}
// int exportSize = dump.readInt(); // DWORD Size;
nextRead += 4;
nextRead = moduleLoadAddress + (exportRVA & 0xFFFFFFFFL);
// typedef struct _IMAGE_EXPORT_DIRECTORY
// dump.readInt(); // ULONG Characteristics;
nextRead += 4;
// dump.readInt(); // ULONG TimeDateStamp;
nextRead += 4;
// dump.readShort(); // USHORT MajorVersion;
nextRead += 2;
// dump.readShort(); // USHORT MinorVersion;
nextRead += 2;
// dump.readInt(); // ULONG Name;
nextRead += 4;
// dump.readInt(); // ULONG Base;
nextRead += 4;
long numberOfFunctionsAddress = nextRead;
// ULONG NumberOfFunctions;
int numberOfFunctions = as.getIntAt(numberOfFunctionsAddress);
nextRead += 4;
// ULONG NumberOfNames;
int numberOfNames = as.getIntAt(nextRead);
nextRead += 4;
// corruption
if (numberOfFunctions < numberOfNames) {
throw new CorruptCoreException("IMAGE_EXPORT_DIRECTORY NumberOfFunctions (" + numberOfFunctions + ") < NumberOfNames (" + numberOfNames + ") @ " + Long.toHexString(numberOfFunctionsAddress));
}
// Note: despite the fact that these are pointers, they appear to be 4
// bytes in both 32-bit and 64-bit binaries
// PULONG *AddressOfFunctions;
long funcAddress = (as.getIntAt(nextRead) & 0xFFFFFFFFL);
nextRead += 4;
// PULONG *AddressOfNames;
long nameAddress = (as.getIntAt(nextRead) & 0xFFFFFFFFL);
nextRead += 4;
// PUSHORT *AddressOfNameOrdinals;
long ordinalAddress = (as.getIntAt(nextRead) & 0xFFFFFFFFL);
nextRead += 4;
int[] nameAddresses = new int[numberOfNames];
nextRead = nameAddress + moduleLoadAddress;
for (int x = 0; x < numberOfNames; x++) {
nameAddresses[x] = as.getIntAt(nextRead);
nextRead += 4;
}
// the function addresses after the first numberOfNames entries are not
// addressable as symbols so this array could be made smaller if this is
// ever found to be a problem (for the near-term, however, it seems more
// correct to read them all since they should all be addressable)
long[] addresses = new long[numberOfFunctions];
nextRead = funcAddress + moduleLoadAddress;
for (int x = 0; x < numberOfFunctions; x++) {
addresses[x] = as.getIntAt(nextRead);
nextRead += 4;
}
int[] ordinals = new int[numberOfNames];
nextRead = ordinalAddress + moduleLoadAddress;
for (int x = 0; x < numberOfNames; x++) {
ordinals[x] = (0x0000FFFF & (int) as.getShortAt(nextRead));
nextRead += 2;
}
String[] names = new String[numberOfNames];
// Support symbols over 1Kb long. (We have seen some.)
byte[] buffer = new byte[2048];
for (int x = 0; x < numberOfNames; x++) {
nextRead = (nameAddresses[x] & 0xFFFFFFFFL) + moduleLoadAddress;
Arrays.fill(buffer, (byte) 0);
int index = 0;
byte thisByte = 0;
do {
thisByte = as.getByteAt(nextRead);
nextRead += 1;
buffer[index] = thisByte;
index++;
} while ((0 != thisByte) && (index < buffer.length));
try {
names[x] = new String(buffer, 0, index - 1, "UTF-8");
} catch (UnsupportedEncodingException e) {
// UTF-8 will be supported.
}
}
List<ISymbol> symbols = new ArrayList<ISymbol>(numberOfNames);
for (int x = 0; x < numberOfNames; x++) {
int index = ordinals[x];
long relocatedFunctionAddress = addresses[index] + moduleLoadAddress;
String functionName = names[x];
ISymbol symbol = new Symbol(functionName, relocatedFunctionAddress);
symbols.add(symbol);
}
return symbols;
}
use of com.ibm.j9ddr.corereaders.memory.Symbol in project openj9 by eclipse.
the class XCOFFReader method getSymbols.
public List<? extends ISymbol> getSymbols(long relocationBase) throws IOException {
List<ISymbol> symbols = new LinkedList<ISymbol>();
long symbolTableOffset = _symbolTableOffset();
int numberOfSymbols = _numberOfSymbols();
if (0 != symbolTableOffset) {
// read the strings first
seekFileRelative(symbolTableOffset + (18 * numberOfSymbols));
int stringTableLength = _backing.readInt();
// A value of 4 is preferable."
if (4 != stringTableLength && 0 != stringTableLength) {
byte[] rawStringTable = new byte[stringTableLength - 4];
_backing.readFully(rawStringTable);
// now read the symbol table
seekFileRelative(symbolTableOffset);
byte[] symbolTableEntry = new byte[18];
int skipNext = 0;
for (int x = 0; x < numberOfSymbols; x++) {
_backing.readFully(symbolTableEntry);
if (skipNext > 0) {
skipNext--;
} else {
int stringTableOffset = 0;
String symbolName = null;
if (_is64Bit) {
stringTableOffset = ((0xFF & symbolTableEntry[8]) << 24) | ((0xFF & symbolTableEntry[9]) << 16) | ((0xFF & symbolTableEntry[10]) << 8) | ((0xFF & symbolTableEntry[11]));
} else {
if ((0 == symbolTableEntry[0]) && (0 == symbolTableEntry[1]) && (0 == symbolTableEntry[2]) && (0 == symbolTableEntry[3])) {
// string offset
stringTableOffset = ((0xFF & symbolTableEntry[4]) << 24) | ((0xFF & symbolTableEntry[5]) << 16) | ((0xFF & symbolTableEntry[6]) << 8) | ((0xFF & symbolTableEntry[7]));
} else {
// literal
symbolName = _stringFromArray(symbolTableEntry, 0);
}
}
if ((null == symbolName) && (0 == (symbolTableEntry[16] & 0x80)) && (0 != stringTableOffset) && (stringTableOffset < (stringTableLength - 4))) {
// read the string from the table
symbolName = _stringFromArray(rawStringTable, stringTableOffset - 4);
} else if ((0 == (symbolTableEntry[16] & 0x80)) && (stringTableOffset > (stringTableLength - 4))) {
// XXX: this problem is known to happen when parsing the 64-bit /usr/lib/libiconv.a file.
// Currently, the cause is unknown so this work-around is put in until we can find the real cause
symbolName = "(string out of table bounds)";
}
if (null == symbolName) {
symbolName = "";
}
long value = 0;
if (_is64Bit) {
value = ((0xFFL & symbolTableEntry[0]) << 56) | ((0xFFL & symbolTableEntry[1]) << 48) | ((0xFFL & symbolTableEntry[2]) << 40) | ((0xFFL & symbolTableEntry[3]) << 32) | ((0xFFL & symbolTableEntry[4]) << 24) | ((0xFFL & symbolTableEntry[5]) << 16) | ((0xFFL & symbolTableEntry[6]) << 8) | ((0xFFL & symbolTableEntry[7]));
} else {
value = ((0xFF & symbolTableEntry[8]) << 24) | ((0xFF & symbolTableEntry[9]) << 16) | ((0xFF & symbolTableEntry[10]) << 8) | ((0xFF & symbolTableEntry[11]));
}
symbols.add(new Symbol(symbolName, value + relocationBase));
skipNext = symbolTableEntry[17];
}
}
}
}
return symbols;
}
use of com.ibm.j9ddr.corereaders.memory.Symbol in project openj9 by eclipse.
the class ELFFileReader method readSymbolsFrom.
/**
* Given a section header table entry that points to a symbol table, construct a list
* of the symbols.
*
* The previous code here was adding the base address to everything. However,
* the symbols for the executable and system libraries are absolute addresses not
* relative so they should not have the base address added to them.
* The symbols for the j9 shared libraries though look like offsets though whether they are
* offsets from the base address or offsets from the section that contains them is
* hard to say: interpreting symbols is hard - see the System V ABI abi386-4.pdf
* One thing is pretty sure, though which is that if the symbol table value is already
* greater than the base address, it is probably already a virtual address. Do not add the base address,
* which is an improvement on the previous code.
*
* @param entry - section header table entry
* @param baseAddress - of the module
* @return list of the symbols
* @throws IOException
*/
private List<ISymbol> readSymbolsFrom(SectionHeaderEntry entry, long baseAddress) throws IOException {
List<ISymbol> symbols = new LinkedList<ISymbol>();
SectionHeaderEntry stringTable;
try {
stringTable = _sectionHeaderEntries.get((int) entry.link);
} catch (IndexOutOfBoundsException e) {
logger.log(Level.FINER, "Invalid link value " + entry.link + " when reading section header table of length " + _sectionHeaderEntries.size());
return symbols;
}
seek(stringTable.offset);
for (ELFSymbol sym : readSymbolsAt(entry)) {
if (sym.isFunction()) {
seek(stringTable.offset + sym.name);
String name = readString();
if (name != null) {
if (sym.value != 0) {
// Draw the truth table of the four cases if that is confusing.
if ((sym.value > 0 && baseAddress > 0) || (sym.value < 0 && baseAddress < 0)) {
// comparison is the natural one
if (sym.value >= baseAddress) {
symbols.add(new Symbol(name, sym.value));
} else {
symbols.add(new Symbol(name, baseAddress + sym.value));
}
} else {
if (sym.value < baseAddress) {
// reverse the comparison
symbols.add(new Symbol(name, sym.value));
} else {
symbols.add(new Symbol(name, baseAddress + sym.value));
}
}
}
} else {
logger.log(Level.FINER, "Error reading section header name. The core file is invalid and the results may unpredictable");
}
}
}
return symbols;
}
Aggregations