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;
}
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;
}
}
}
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);
}
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());
}
}
}
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);
}
Aggregations