Search in sources :

Example 1 with IModule

use of com.ibm.j9ddr.corereaders.memory.IModule in project openj9 by eclipse.

the class DDRSymbolFinder method getModuleForInstructionAddress.

/* Logic stolen from SymbolUtil. */
private static IModule getModuleForInstructionAddress(IProcess process, long address) throws CorruptDataException {
    Collection<? extends IModule> modules = process.getModules();
    IModule matchingModule = null;
    OUTER_LOOP: for (IModule thisModule : modules) {
        for (IMemoryRange thisRange : thisModule.getMemoryRanges()) {
            if (thisRange.contains(address)) {
                matchingModule = thisModule;
                break OUTER_LOOP;
            }
        }
    }
    return matchingModule;
}
Also used : IMemoryRange(com.ibm.j9ddr.corereaders.memory.IMemoryRange) IModule(com.ibm.j9ddr.corereaders.memory.IModule)

Example 2 with IModule

use of com.ibm.j9ddr.corereaders.memory.IModule in project openj9 by eclipse.

the class AIXDumpReader method executablePathHint.

// Passback of executable path. If we couldn't load the executable the first time, try again now.
public void executablePathHint(String path) {
    if (_executable instanceof MissingFileModule) {
        // Check the hint points at the same file name
        try {
            if (!getFileName(_executable.getName()).equals(getFileName(path))) {
                return;
            }
        } catch (CorruptDataException e1) {
            return;
        }
        // Remove placeholder memory source
        _process.removeMemorySource(_executableTextSection);
        // Remember the current placeholder in case this one fails too
        IModule currentExecutable = _executable;
        IMemorySource currentExecutableTextSection = _executableTextSection;
        ILibraryResolver resolver = LibraryResolverFactory.getResolverForCoreFile(this.coreFile);
        IProcess proc = getProcess();
        try {
            seek(_loaderOffset);
            readInt();
            // Ignore flags
            readLoaderInfoFlags();
            // Ignore dataOffset
            readAddress();
            long textVirtualAddress = readAddress();
            long textSize = readAddress();
            long dataVirtualAddress = readAddress();
            long dataSize = readAddress();
            // Disregard fileName from core
            readString();
            String fileName = path;
            String objectName = readString();
            String moduleName = fileName;
            if (0 < objectName.length()) {
                moduleName += "(" + objectName + ")";
            }
            loadModule(resolver, proc, textVirtualAddress, textSize, dataVirtualAddress, dataSize, fileName, objectName, moduleName, true);
        } catch (IOException e) {
        // TODO handle
        }
        // If the executable is still a MissingFileModule, the hint didn't work
        if (_executable instanceof MissingFileModule) {
            _process.removeMemorySource(_executableTextSection);
            _executableTextSection = currentExecutableTextSection;
            _process.addMemorySource(_executableTextSection);
            _executable = currentExecutable;
        }
    }
}
Also used : IMemorySource(com.ibm.j9ddr.corereaders.memory.IMemorySource) IModule(com.ibm.j9ddr.corereaders.memory.IModule) ILibraryResolver(com.ibm.j9ddr.corereaders.ILibraryResolver) CorruptDataException(com.ibm.j9ddr.CorruptDataException) IOException(java.io.IOException) IProcess(com.ibm.j9ddr.corereaders.memory.IProcess) MissingFileModule(com.ibm.j9ddr.corereaders.memory.MissingFileModule)

Example 3 with IModule

use of com.ibm.j9ddr.corereaders.memory.IModule in project openj9 by eclipse.

the class ELFDumpReader method createModuleFromElfReader.

/**
 * Given an ELF reader, read the symbols, memory ranges and properties from the module
 * and construct a Module object. The ELF reader may point to a segment within the core file
 * or may point to a copy of the module on disk or appended to the core file.
 *
 * @param loadedBaseAddress of the module
 * @param name of the module
 * @param elfReader to the module
 *
 * @return IModule
 * @throws IOException
 */
private IModule createModuleFromElfReader(final long loadedBaseAddress, String name, ELFFileReader inCoreReader, ELFFileReader diskReader) {
    if (name == null) {
        return null;
    }
    if (inCoreReader == null) {
        return new MissingFileModule(_process, name, Collections.<IMemoryRange>emptyList());
    }
    List<? extends ISymbol> symbols = null;
    Map<Long, String> sectionHeaderStringTable = null;
    List<SectionHeaderEntry> sectionHeaderEntries = null;
    Properties properties;
    Collection<? extends IMemorySource> declaredRanges;
    ProgramHeaderEntry ehFrameEntry = null;
    // so don't raise an error if it isn't present.
    for (ProgramHeaderEntry ph : inCoreReader.getProgramHeaderEntries()) {
        if (ph.isEhFrame()) {
            ehFrameEntry = ph;
        }
    }
    try {
        if (ehFrameEntry != null) {
            unwinder.addCallFrameInformation(loadedBaseAddress, ehFrameEntry, name);
        }
    } catch (MemoryFault mf) {
        // We get known memory faults for ld-linux-x86-64.so.2 in AMD64 dumps (at the first address it's loaded at)
        // and linux-vdso.so.1. The first of these turns up again at a location that works, the second is
        // "magic" so we don't worry about them. We want this code to be as resilient as possible.
        logger.log(Level.FINER, "MemoryFault reading GNU_EH_FRAME data for module with name " + name + " and base address " + Long.toHexString(loadedBaseAddress));
    } catch (CorruptDataException cde) {
        logger.log(Level.FINER, "CorruptDataException reading GNU_EH_FRAME data for module with name " + name + " and base address " + Long.toHexString(loadedBaseAddress));
    } catch (IOException e) {
        logger.log(Level.FINER, "IOException reading GNU_EH_FRAME data for module with name " + name + " and base address " + Long.toHexString(loadedBaseAddress));
    }
    try {
        if (diskReader != null) {
            symbols = diskReader.getSymbols(loadedBaseAddress, true);
            sectionHeaderStringTable = diskReader.getSectionHeaderStringTable();
            sectionHeaderEntries = diskReader.getSectionHeaderEntries();
        } else {
            symbols = inCoreReader.getSymbols(loadedBaseAddress, false);
            sectionHeaderStringTable = inCoreReader.getSectionHeaderStringTable();
            sectionHeaderEntries = inCoreReader.getSectionHeaderEntries();
        }
        properties = inCoreReader.getProperties();
        // Only ever get memory ranges from the data loaded into the core file!
        // But we can use the section headers and string table from the disk or zipped library
        // to navigate. (Section headers are redundant once the library is loaded so may not
        // be in memory.)
        declaredRanges = inCoreReader.getMemoryRanges(loadedBaseAddress, sectionHeaderEntries, sectionHeaderStringTable);
    } catch (IOException e) {
        logger.log(Level.FINER, "Error generating module with name " + name + " and base address " + Long.toHexString(loadedBaseAddress));
        return null;
    }
    // Of the declared memory ranges, some will already be in core (i.e. .data) others will have been declared
    // in the core, but not backed.
    List<IMemoryRange> ranges = new ArrayList<IMemoryRange>(declaredRanges.size());
    for (IMemorySource source : declaredRanges) {
        IMemorySource coreSource = _process.getRangeForAddress(source.getBaseAddress());
        /**
         * The following test skips sections that originally had an address of 0
         * the section header table.
         *
         * Explanation follows - see also the example section header table at the top
         * of SectionHeaderEntry.java
         *
         * Some of the later sections in the section header table have an address field
         * 0. That is a relative address, relative to the base address of the module.
         * They are usually the sections from .comment onwards.
         *
         * When the entry is constructed the code that creates the entry creates it with
         * address (base address of the module) + (address field in the SHT) hence those
         * that had an address of 0 will have an address == base address of the module.
         * These entries are precisely those that are often not in the core file so it is
         * not safe to create them as sections - they were there in the on-disk version of
         * the library but often not in memory. The code above that called elfReader.getMemoryRanges
         * may have been reading the version of the module from disk (which is good, it means
         * you get a good section header string table so you get good names for all the
         * sections) but not all the sections exist in memory. The danger of adding them
         * as memory ranges is that they start to overlay the segments in the core file
         * that come immediately afterwards; that is, they cause jdmpview, for example, to
         * believe that the contents of these later areas of memory are backed by the
         * contents of the library on disk when they are not.
         * See CMVC 185753
         *
         * So, don't add sections that originally had address 0.
         */
        if (source.getBaseAddress() == loadedBaseAddress) {
            // must have originally had address 0 in the section header table
            continue;
        }
        if (null != coreSource) {
            if (coreSource.isBacked()) {
            // Range already exists
            } else {
                // from the library
                if (source.getSize() > 0) {
                    _process.removeMemorySource(coreSource);
                    _process.addMemorySource(source);
                }
            }
        } else {
            if (source.getSize() > 0) {
                _process.addMemorySource(source);
            }
        }
        ranges.add(source);
    }
    return new Module(_process, name, symbols, ranges, loadedBaseAddress, properties);
}
Also used : IMemorySource(com.ibm.j9ddr.corereaders.memory.IMemorySource) ArrayList(java.util.ArrayList) CorruptDataException(com.ibm.j9ddr.CorruptDataException) IOException(java.io.IOException) Properties(java.util.Properties) MissingFileModule(com.ibm.j9ddr.corereaders.memory.MissingFileModule) IMemoryRange(com.ibm.j9ddr.corereaders.memory.IMemoryRange) MemoryFault(com.ibm.j9ddr.corereaders.memory.MemoryFault) MissingFileModule(com.ibm.j9ddr.corereaders.memory.MissingFileModule) IModule(com.ibm.j9ddr.corereaders.memory.IModule) Module(com.ibm.j9ddr.corereaders.memory.Module)

Example 4 with IModule

use of com.ibm.j9ddr.corereaders.memory.IModule in project openj9 by eclipse.

the class ELFDumpReader method readModules.

/**
 * Read all modules in the core file, where "modules" = the executable and all
 * shared libraries. Put the executable into _executable and the libraries without
 * the executable into _modules.
 * <p>
 * Find libraries by two methods: iterating through all the segments in the core
 * file looking for which are libraries and iterating through the debug information
 * within the executable. We may find the executable either on disk, within the
 * core file as one of the loaded segments, or appended to the core file by
 * library collections. Consolidate the list of libraries that we find from the
 * debug information with the list from the core file to build the best list possible.
 * <p>
 * When constructing the module objects, use the best available data. This means using
 * the section header information from the collected libraries if present since this
 * is always more reliable than that in the core file.
 *
 * @throws IOException
 */
/* In a second comment to avoid it appearing in hovertext
	 * 
	 * This method is called under at least two completely different circumstances:
	 * 
	 * Circumstance 1 - called during library collection when there are not yet any collected libraries
	 * appended to the core file. In this case all that is really wanted is a list of the 
	 * names of the libraries to guide the collection but this method does not discriminate and 
	 * constructs everything possible, reading section header tables and symbol tables and so on. 
	 * In this case the aim is to return the most complete list of modules, examining both the 
	 * modules within the core file and the list that can be found from the debug data in the 
	 * executable. 
	 *  
	 * Circumstance 2 - called when it is important to have the best possible information about
	 * each module - as for example when called from jdmpview. In this case the collected libraries 
	 * may or may not be appended to the core file but if they are then the section header information 
	 * is always better when taken from the collected library so the modules should be constructed 
	 * from the them. 
	 * 
	 * The reason it is important to keep an eye on both circumstances is that they affect one another.
	 * In circumstance 1, some of the constructed modules are of poor quality because the original library is not
	 * available. In circumstance 2, whether or not the library will be found appended to the core file
	 * depends on whether it was found and returned in circumstance 1. 
	 * 
	 * TODO refactor so that the code paths for the two circumstances are not so entwined. Separate out the 
	 * two functions of gathering the list of names of which libraries exist, needed for both circumstances, and constructing
	 * the best possible image of each library, using core and collected library, only needed for the second circumstance. 
	 * 
	 * There are three sorts of module, too. 
	 * 1. Those found only via the program header table of the core file. This includes most of the system
	 * libraries e.g. ld-linux.so.2. These only have the library name, no path, because they are found from 
	 * the SOname within the module.
	 * 2. Those found only via the debug data in the executable. This can include several of the j9 libraries.
	 * They are present within the core file but the route to the SOname is broken somehow
	 * 3. Those found both ways - most of the j9 libraries are in this case. However note that the 
	 * names will be different because the names found via the debug data are full pathnames and the 
	 * names found via the SOname is just the library name. However they can be matched up via the load
	 * address which is available on both routes. 
	 * 
	 * There are a some oddities too:
	 * 1. the executable always appears in the core file with a SOname of "lib.so"
	 * 2. The core file always contains a library called linux-gate.so which does not correspond to 
	 * a file on disk
	 * 3. Sometimes the same file - e.g. libvmi.so, and the executable itself - will be mapped into memory 
	 * twice or more at different addresses so the same name will appear more than once in the 
	 * list from the core file.
	 */
private void readModules() throws IOException {
    if (_executable == null || _executable instanceof MissingFileModule) {
        _modulesException = null;
        _modules = new LinkedList<IModule>();
        readProcessData();
        // Try to find the executable image either on disk or appended to the core file by library collection.
        // If we can we will probably also find the libraries on disk or appended to the core file and will
        // therefore get good section header tables.
        // Otherwise use the copy of the executable within the core file. It may contain some of the library info
        // so it makes a good fallback.
        LibraryDataSource executableFile = findExecutableOnDiskOrAppended();
        ELFFileReader executableELF = null;
        if (executableFile != null && executableFile.getType() != LibraryDataSource.Source.NOT_FOUND && !useLoadedLibraries) {
            try {
                executableELF = getELFReaderFromDataSource(executableFile);
            } catch (InvalidDumpFormatException e) {
            // Not an ELF file.
            }
            if (null != executableELF) {
                createAllModules(executableELF, executableFile.getName());
            }
        } else if (_executable instanceof MissingFileModule) {
            logger.log(Level.FINE, "Libraries unavailable, falling back to loaded modules within the core file.");
            executableELF = getELFReaderForExecutableWithinCoreFile();
            if (null != executableELF) {
                createAllModules(executableELF, _executablePathOverride);
            } else {
                _executable = new MissingFileModule(_process, _executableFileName, Collections.<IMemoryRange>emptyList());
            }
        } else {
            _executable = new MissingFileModule(_process, _executableFileName, Collections.<IMemoryRange>emptyList());
        }
    }
}
Also used : IModule(com.ibm.j9ddr.corereaders.memory.IModule) LibraryDataSource(com.ibm.j9ddr.corereaders.LibraryDataSource) InvalidDumpFormatException(com.ibm.j9ddr.corereaders.InvalidDumpFormatException) MissingFileModule(com.ibm.j9ddr.corereaders.memory.MissingFileModule)

Example 5 with IModule

use of com.ibm.j9ddr.corereaders.memory.IModule in project openj9 by eclipse.

the class ELFDumpReader method createAllModules.

/**
 * Gather all of the information about all of the modules in the core file and fill in the _executable and _modules
 * instance variables.
 * <p>
 *  The name and a reader for the executable need to be passed in as there is special handling for the executable: not only must it
 *  be removed from the list of libraries since it is special, but also the name is needed so that when we come across a modules
 *  with a name of "lib.so" the name of the executable can be put in instead.
 * <p>
 * Gather the full set of libraries using both the debug data in the executable and the list of segments from
 * the program header table in the core file.
 * <p>
 * When constructing the module objects, use the copies of the module from disk or appended to the core file for their
 * section info, if it is available. It is invariably better than that in the core file which may have been overwritten.
 * <p>
 * When constructing the module objects, use the name of the module from the debug data if there is a choice, since
 * the debug data always has full path names. Full path names are needed for accurate library collection.
 * <p>
 * During library collection or when using jdmpview with a core file which does not have libraries appended, the best module
 * object will be constructed using data from both sources: the full path name from the
 * debug data but the section and symbol information from what is available in the core file.
 * <p>
 * The overall logic is to gather all of the names from the debug data and to gather readers for all of the library files
 * within the core file, all indexed and sorted by virtual address, then to do a two-way merge on address and
 * create the module objects with the best data available.
 *
 * @param ELFFileReader for the executable
 * @param executable name
 * @throws IOException
 */
private void createAllModules(ELFFileReader executableELF, String executableName) throws IOException {
    /* Load modules from the core file. Modules in the core file may not have a section header table as
		 * the program header table describes what is loaded into memory. The section header table is used
		 * while loading but not once loaded. If we have a disk version of the library we can pull in the
		 * section header table from that (as well as the symbols as those sections may not be loaded either).
		 */
    List<IModule> allModules = new LinkedList<IModule>();
    long executableBaseAddress = executableELF.getBaseAddress();
    Map<Long, ELFFileReader> inCoreReaders = getElfReadersForModulesWithinCoreFile(executableELF, executableName);
    Map<Long, String> libraryNamesFromDebugData = readLibraryNamesFromDebugData(executableELF, inCoreReaders, executableELF);
    for (Map.Entry<Long, ELFFileReader> entry : inCoreReaders.entrySet()) {
        long coreFileAddress = entry.getKey();
        ELFFileReader inCoreReader = entry.getValue();
        String moduleName = inCoreReader.readSONAME(_reader);
        /* A module name of lib.so apparently really means the executable. */
        if ("lib.so".equals(moduleName)) {
            moduleName = executableName;
        }
        String debugName = libraryNamesFromDebugData.get(coreFileAddress);
        ELFFileReader readerForModuleOnDiskOrAppended = null;
        /* Is there an entry in the debug data for this module? */
        if (debugName != null) {
            moduleName = debugName;
            readerForModuleOnDiskOrAppended = getReaderForModuleOnDiskOrAppended(debugName);
        } else {
            readerForModuleOnDiskOrAppended = getReaderForModuleOnDiskOrAppended(moduleName);
        }
        /* Patch up this modules section header table with the one from the disk version before we
			 * create the module.
			 */
        if (!inCoreReader.isCompatibleWith(readerForModuleOnDiskOrAppended)) {
            // Can we use the on disk reader so we can use it to get missing data.
            readerForModuleOnDiskOrAppended = null;
        }
        IModule module = createModuleFromElfReader(coreFileAddress, moduleName, inCoreReader, readerForModuleOnDiskOrAppended);
        if (module != null) {
            allModules.add(module);
        }
    }
    // TODO - Sort modules. For the sake of tidyness.
    _modules.addAll(allModules);
    ELFFileReader readerForExectuableOnDiskOrAppended = getReaderForModuleOnDiskOrAppended(executableName);
    _executable = createModuleFromElfReader(executableBaseAddress, executableName, executableELF, readerForExectuableOnDiskOrAppended);
}
Also used : IModule(com.ibm.j9ddr.corereaders.memory.IModule) Map(java.util.Map) SortedMap(java.util.SortedMap) TreeMap(java.util.TreeMap) LinkedList(java.util.LinkedList)

Aggregations

IModule (com.ibm.j9ddr.corereaders.memory.IModule)14 CorruptDataException (com.ibm.j9ddr.CorruptDataException)6 IMemoryRange (com.ibm.j9ddr.corereaders.memory.IMemoryRange)5 LinkedList (java.util.LinkedList)5 MissingFileModule (com.ibm.j9ddr.corereaders.memory.MissingFileModule)4 IOException (java.io.IOException)4 IMemorySource (com.ibm.j9ddr.corereaders.memory.IMemorySource)3 ISymbol (com.ibm.j9ddr.corereaders.memory.ISymbol)3 Module (com.ibm.j9ddr.corereaders.memory.Module)3 ArrayList (java.util.ArrayList)3 InvalidDumpFormatException (com.ibm.j9ddr.corereaders.InvalidDumpFormatException)2 LibraryDataSource (com.ibm.j9ddr.corereaders.LibraryDataSource)2 MemoryFault (com.ibm.j9ddr.corereaders.memory.MemoryFault)2 UnwindModule (com.ibm.j9ddr.corereaders.minidump.unwind.UnwindModule)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 Properties (java.util.Properties)2 ImageModule (com.ibm.dtfj.image.ImageModule)1 DataUnavailableException (com.ibm.j9ddr.DataUnavailableException)1 CorruptCoreException (com.ibm.j9ddr.corereaders.CorruptCoreException)1 ILibraryResolver (com.ibm.j9ddr.corereaders.ILibraryResolver)1