use of com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction in project openj9 by eclipse.
the class ModuleStream method buildRuntimeFunctionList.
/* Gather the runtime function list from the loaded dll/exe.
* Possibly this should be done in the unwind package but it's
* similar to the symbol gathering above so it makes sense to
* have it here.
*/
private List<RuntimeFunction> buildRuntimeFunctionList(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 CorruptCoreException("Unable to decode magic number");
}
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;
if (224 == optionalHeaderSize) {
// 32 bit processes don't need unwind information.
return null;
// cue us up to the data directories
} 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));
}
// The exception data is index 3 in the directories.
int IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3;
for (int i = 0; i < IMAGE_DIRECTORY_ENTRY_EXCEPTION; i++) {
nextRead += 4;
nextRead += 4;
}
// DWORD VirtualAddress;
int exceptionRVA = as.getIntAt(nextRead);
// DWORD VirtualAddress;
int exceptionSize = as.getIntAt(nextRead);
// Now walk the table of IMAGE_RUNTIME_FUNCTION_ENTRY's, each is 3 DWORDS so 3*4 12 bytes long.
int entryCount = exceptionSize / 12;
nextRead = moduleLoadAddress + (exceptionRVA & 0xFFFFFFFFL);
// In the dll's entryCount is exceptionSize / sizeOf(IMAGE_RUNTIME_FUNCTION_ENTRY's)
// In the core files that doesn't appear to be true. Though they look like they are
// null terminated.
List<RuntimeFunction> rfList = new LinkedList<RuntimeFunction>();
for (int i = 0; i < entryCount; i++) {
// Create an entry in our list for each one of these.
int start = as.getIntAt(nextRead);
nextRead += 4;
if (start == 0) {
// Null entries appear to end the exception data.
break;
}
int end = as.getIntAt(nextRead);
nextRead += 4;
int unwindAddress = as.getIntAt(nextRead);
nextRead += 4;
RuntimeFunction rf = new RuntimeFunction(start, end, unwindAddress);
rfList.add(rf);
}
return rfList;
}
use of com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction in project openj9 by eclipse.
the class BaseWindowsOSThread method walkStack64.
/* Walking 64 bit stacks is not like 32 bit stacks.
* We have to apply the unwind info contained in the dll's.
*
* This is documented here:
* http://msdn.microsoft.com/en-us/library/8ydc79k6%28v=vs.110%29.aspx
*/
private void walkStack64() throws CorruptDataException {
// Get the module for the current instruction pointer.
long ip = getInstructionPointer();
long rsp = getStackPointer();
while (ip != 0x0) {
// Create a stack frame from that base pointer and instruction pointer.
// On x86-64 the there is no base pointer.
stackFrames.add(new OSStackFrame(rsp, ip));
// Get the unwind info in the right module, for the current instruction pointer. (Step 1)
UnwindModule module = getModuleForInstructionAddress(ip);
RuntimeFunction rf = null;
if (module != null) {
rf = module.getUnwindDataForAddress(ip - module.getLoadAddress());
} else {
break;
}
if (rf == null) {
// functions. (Windows 7 does.)
break;
} else {
// System.err.println("Found unwind data: " + rf + " for " + SymbolUtil.getProcedureNameForAddress(process, ip));
UnwindInfo info = new UnwindInfo(process.getAddressSpace(), module, rf.getUnwindInfoAddress());
// Uncomment to dump unwind information as we apply it.
// System.err.println("Applying UNWIND_INFO: " + info);
// Apply the unwind info to the stack and get the new
// base pointer and stack pointer.
rsp = info.apply(rsp);
// Get the instruction/base pointer for the next frame.
ip = process.getPointerAt(rsp);
// New stack pointer is the slot after that. (I think)
rsp += 8;
}
// System.err.println(String.format("Next rsp = 0x%08x", rsp));
// System.err.println(String.format("Next ip = 0x%08x", ip));
}
}
use of com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction 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