/* * SymbolEntry.java - This file is part of the Jakstab project. * Copyright 2007-2015 Johannes Kinder <jk@jakstab.org> * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, see <http://www.gnu.org/licenses/>. */ package org.jakstab.loader.pe; import java.io.IOException; import java.util.Map; import org.jakstab.util.BinaryInputBuffer; import org.jakstab.util.Logger; /** * @author Johannes Kinder */ @SuppressWarnings("unused") class SymbolEntry { private static final Logger logger = Logger.getLogger(SymbolEntry.class); // Storage classes used by MS compilers private static final int IMAGE_SYM_CLASS_EXTERNAL = 2; private static final int IMAGE_SYM_CLASS_STATIC = 3; private static final int IMAGE_SYM_CLASS_LABEL = 6; private static final int IMAGE_SYM_CLASS_FUNCTION = 101; private static final int IMAGE_SYM_CLASS_FILE = 103; private final String Name; private final long Value; private final int SectionNumber; private final int Type; private final int StorageClass; private final int NumberOfAuxSymbols; public SymbolEntry(BinaryInputBuffer inBuf, Map<Integer, String> stringTable) throws IOException { // Parse name byte[] nameArray = new byte[8]; inBuf.read(nameArray); // If first 4 bytes are 0, the next 4 are an offset into the string table if ((nameArray[0] == 0) && (nameArray[1] == 0) && (nameArray[2] == 0) && (nameArray[3] == 0)) { int stringOffset = ((nameArray[7] & 0xFF) << 24) | ((nameArray[6] & 0xFF) << 16) | ((nameArray[5] & 0xFF) << 8) | (nameArray[4] & 0xFF); String nameString = stringTable.get(stringOffset); if (nameString != null) { Name = nameString; } else { logger.warn("No name in string table for symbol at specified offset " + stringOffset); Name = "Anonymous(" + stringOffset + ")"; } } else { StringBuilder nBuilder = new StringBuilder(); for (int i=0;i<8;i++){ if ((nameArray[i]&0xFF)>32 && (nameArray[i]&0xFF)<128) nBuilder.append((char)(nameArray[i]&0xFF)); } Name = nBuilder.toString(); } Value = inBuf.readDWORD(); int section = inBuf.readWORD(); if (section >= 32768) SectionNumber = section - 65536; else SectionNumber = section; Type = inBuf.readWORD(); StorageClass = inBuf.readBYTE(); NumberOfAuxSymbols = inBuf.readBYTE(); } public String getName() { return Name; } public long getValue() { return Value; } public int getNumberOfAuxSymbols() { return NumberOfAuxSymbols; } public int getStorageClass() { return StorageClass; } /** * Does the symbol refer to a global variable or external function? * * @return true if the symbol is a global variable or external * function, false otherwise. */ public boolean isExternal() { return StorageClass == IMAGE_SYM_CLASS_EXTERNAL; } /** * Does the symbol refer to a static value, i.e. a string literal or * a jump table? * @return true, if the value field refers to the offset of the value relative * to it's section start, false if it is something else. */ public boolean isStatic() { return StorageClass == IMAGE_SYM_CLASS_STATIC; } /** * Does the symbol refer to a jump label? If true, the value field contains * the offset of the jump target relative to the section. * @return true if the symbol points to a jump label, false otherwise. */ public boolean isLabel() { return StorageClass == IMAGE_SYM_CLASS_LABEL; } public int getSectionNumber() { return SectionNumber; } @Override public String toString() { return "Name: " + Name + " Storage class: " + StorageClass + " Section number: " + SectionNumber + " Value: " + Long.toHexString(Value); } }