/*
* 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);
}
}