use of com.ibm.j9ddr.corereaders.memory.ISymbol 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.ISymbol in project openj9 by eclipse.
the class DDRSymbolFinder method addVoidPointersAsSymbols.
private static void addVoidPointersAsSymbols(String structureName, long structureAddress, StructureReader structureReader, IProcess process) throws DataUnavailableException, CorruptDataException {
if (structureAddress == 0) {
return;
}
List<String> voidFields = getVoidPointerFieldsFromStructure(structureReader, structureName);
if (voidFields == null) {
return;
}
// Format the hex and structure name the same as the rest of DDR.
int paddingSize = process.bytesPerPointer() * 2;
String formatString = "[!%s 0x%0" + paddingSize + "X->%s]";
for (String field : voidFields) {
if (ignoredSymbols.contains(structureName + "." + field)) {
// Ignore this field, it's not a function.
continue;
}
long functionAddress = followPointerFromStructure(structureName, structureAddress, field, structureReader, process);
if (functionAddress == 0) {
// Skip null pointers.
continue;
}
// Lower case the structure name to match the rest of the DDR !<struct> commands.
String symName = String.format(formatString, structureName.toLowerCase(), structureAddress, field);
if (functionAddress == 0) {
// Null pointer, possibly unset or no longer used.
continue;
}
if (addSymbols) {
IModule module = getModuleForInstructionAddress(process, functionAddress);
if (module == null) {
continue;
}
boolean found = false;
// Don't override/duplicate symbols we've already seen.
for (ISymbol sym : module.getSymbols()) {
if (sym.getAddress() == functionAddress) {
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
logger.log(FINER, "DDRSymbolFinder: Found exact match with " + sym.toString() + " not adding.");
found = true;
break;
}
}
if (!found) {
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
logger.log(FINER, "DDRSymbolFinder: Adding new DDR symbol " + symName);
SymbolUtil.addDDRSymbolToModule(module, "[" + field + "]", symName, functionAddress);
}
}
}
}
use of com.ibm.j9ddr.corereaders.memory.ISymbol 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.ISymbol 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;
}
use of com.ibm.j9ddr.corereaders.memory.ISymbol in project openj9 by eclipse.
the class ModuleStream method readFrom.
@Override
public void readFrom(MiniDumpReader dump, IAddressSpace as, boolean is64Bit) throws IOException, CorruptDataException {
dump.seek(getLocation());
int numberOfModules = dump.readInt();
if (numberOfModules > 1024) {
throw new CorruptDataException("Improbably high number of modules found: " + numberOfModules + ", location = " + Long.toHexString(getLocation()));
}
class ModuleData {
long imageBaseAddress;
Properties properties;
int nameAddress;
}
ModuleData[] moduleData = new ModuleData[numberOfModules];
for (int i = 0; i < numberOfModules; i++) {
moduleData[i] = new ModuleData();
moduleData[i].imageBaseAddress = dump.readLong();
int imageSize = dump.readInt();
int checksum = dump.readInt();
int timeDateStamp = dump.readInt();
moduleData[i].nameAddress = dump.readInt();
moduleData[i].properties = readProperties(dump, imageSize, checksum, timeDateStamp);
}
for (ModuleData thisModule : moduleData) {
final long imageBaseAddress = thisModule.imageBaseAddress;
final String moduleName = getModuleName(dump, thisModule.nameAddress);
final Properties properties = thisModule.properties;
short magic;
try {
magic = as.getShortAt(imageBaseAddress);
if (0x5A4D != magic) {
logger.logp(Level.WARNING, "com.ibm.j9ddr.corereaders.minidump.ModuleStream", "readFrom", "Magic number was: " + Integer.toHexString(0xFFFF & magic) + " expected 0x5A4D");
}
} catch (MemoryFault e1) {
logger.logp(Level.WARNING, "com.ibm.j9ddr.corereaders.minidump.ModuleStream", "readFrom", "MemoryFault reading magic number", e1);
}
long e_lfanewAddress = imageBaseAddress + 0x3c;
// load the e_lfanew since that is the load-address-relative location of
// the PE Header
Collection<IMemoryRange> sections = new LinkedList<IMemoryRange>();
try {
long e_lfanew = 0xFFFFFFFFL & as.getIntAt(e_lfanewAddress);
// push us to the start of the PE header
long readingAddress = e_lfanew + imageBaseAddress;
List<ISymbol> symbols = null;
if (0 != e_lfanew) {
loadModuleSections(as, imageBaseAddress, readingAddress, e_lfanew, sections);
symbols = buildSymbols(dump, as, imageBaseAddress);
}
if (symbols == null) {
symbols = new LinkedList<ISymbol>();
}
// Load the list of RUNTIME_FUNCTION structures that map code
// ranges to stack unwind information.
List<RuntimeFunction> runtimeFunctionList = null;
runtimeFunctionList = buildRuntimeFunctionList(dump, as, imageBaseAddress);
IModule module;
if (runtimeFunctionList != null) {
module = new UnwindModule(as.getProcesses().iterator().next(), moduleName, symbols, sections, thisModule.imageBaseAddress, properties, runtimeFunctionList);
// Uncommend to dump unwind info as we find it. This is very verbose.
// ((UnwindModule)module).dumpUndwindInfo(System.err);
} else {
module = new Module(as.getProcesses().iterator().next(), moduleName, symbols, sections, thisModule.imageBaseAddress, properties);
}
if (moduleName.toLowerCase().endsWith(".exe")) {
dump.setExecutable(module);
} else {
dump.addLibrary(module);
}
} catch (RuntimeException e) {
// Don't want to prevent RTE's propogating
throw e;
} catch (Exception e) {
// this needs to be here in order to not fail completely whenever we
// encounter a strange record
logger.logp(Level.WARNING, "com.ibm.j9ddr.corereaders.minidump.ModuleStream", "readFrom", "Problem reading symbols", e);
}
}
}
Aggregations