Search in sources :

Example 1 with RuntimeFunction

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;
}
Also used : CorruptCoreException(com.ibm.j9ddr.corereaders.CorruptCoreException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) RuntimeFunction(com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction) LinkedList(java.util.LinkedList)

Example 2 with RuntimeFunction

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));
    }
}
Also used : IOSStackFrame(com.ibm.j9ddr.corereaders.osthread.IOSStackFrame) OSStackFrame(com.ibm.j9ddr.corereaders.osthread.OSStackFrame) UnwindInfo(com.ibm.j9ddr.corereaders.minidump.unwind.UnwindInfo) UnwindModule(com.ibm.j9ddr.corereaders.minidump.unwind.UnwindModule) RuntimeFunction(com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction)

Example 3 with RuntimeFunction

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);
        }
    }
}
Also used : IModule(com.ibm.j9ddr.corereaders.memory.IModule) ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) CorruptDataException(com.ibm.j9ddr.CorruptDataException) Properties(java.util.Properties) LinkedList(java.util.LinkedList) IOException(java.io.IOException) CorruptDataException(com.ibm.j9ddr.CorruptDataException) CorruptCoreException(com.ibm.j9ddr.corereaders.CorruptCoreException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IMemoryRange(com.ibm.j9ddr.corereaders.memory.IMemoryRange) MemoryFault(com.ibm.j9ddr.corereaders.memory.MemoryFault) UnwindModule(com.ibm.j9ddr.corereaders.minidump.unwind.UnwindModule) IModule(com.ibm.j9ddr.corereaders.memory.IModule) Module(com.ibm.j9ddr.corereaders.memory.Module) UnwindModule(com.ibm.j9ddr.corereaders.minidump.unwind.UnwindModule) RuntimeFunction(com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction)

Aggregations

RuntimeFunction (com.ibm.j9ddr.corereaders.minidump.unwind.RuntimeFunction)3 CorruptCoreException (com.ibm.j9ddr.corereaders.CorruptCoreException)2 UnwindModule (com.ibm.j9ddr.corereaders.minidump.unwind.UnwindModule)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 LinkedList (java.util.LinkedList)2 CorruptDataException (com.ibm.j9ddr.CorruptDataException)1 IMemoryRange (com.ibm.j9ddr.corereaders.memory.IMemoryRange)1 IModule (com.ibm.j9ddr.corereaders.memory.IModule)1 ISymbol (com.ibm.j9ddr.corereaders.memory.ISymbol)1 MemoryFault (com.ibm.j9ddr.corereaders.memory.MemoryFault)1 Module (com.ibm.j9ddr.corereaders.memory.Module)1 UnwindInfo (com.ibm.j9ddr.corereaders.minidump.unwind.UnwindInfo)1 IOSStackFrame (com.ibm.j9ddr.corereaders.osthread.IOSStackFrame)1 OSStackFrame (com.ibm.j9ddr.corereaders.osthread.OSStackFrame)1 IOException (java.io.IOException)1 Properties (java.util.Properties)1