Search in sources :

Example 1 with Symbol

use of com.ibm.j9ddr.corereaders.memory.Symbol 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;
}
Also used : CorruptCoreException(com.ibm.j9ddr.corereaders.CorruptCoreException) ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) Symbol(com.ibm.j9ddr.corereaders.memory.Symbol) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Example 2 with Symbol

use of com.ibm.j9ddr.corereaders.memory.Symbol 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;
}
Also used : ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) Symbol(com.ibm.j9ddr.corereaders.memory.Symbol) LinkedList(java.util.LinkedList)

Example 3 with Symbol

use of com.ibm.j9ddr.corereaders.memory.Symbol 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;
}
Also used : ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) ISymbol(com.ibm.j9ddr.corereaders.memory.ISymbol) Symbol(com.ibm.j9ddr.corereaders.memory.Symbol) LinkedList(java.util.LinkedList)

Aggregations

ISymbol (com.ibm.j9ddr.corereaders.memory.ISymbol)3 Symbol (com.ibm.j9ddr.corereaders.memory.Symbol)3 LinkedList (java.util.LinkedList)2 CorruptCoreException (com.ibm.j9ddr.corereaders.CorruptCoreException)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 ArrayList (java.util.ArrayList)1