1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56:01 +02:00

Parse symbols.

This commit is contained in:
Alain Magloire 2002-11-25 05:54:54 +00:00
parent 56d92428d9
commit 98fa05101a
2 changed files with 324 additions and 56 deletions

View file

@ -351,6 +351,18 @@ public class Coff {
public static class Symbol { public static class Symbol {
public final static int SYMSZ = 18; public final static int SYMSZ = 18;
public final static int SYMNMLEN = 8; public final static int SYMNMLEN = 8;
/* Derived types, in n_type. */
public final static int DT_NON = 0; /* no derived type */
public final static int DT_PTR = 1; /* pointer */
public final static int DT_FCN = 2; /* function */
public final static int DT_ARY = 3; /* array */
public final static int N_TMASK = 0x30;
public final static int N_BTSHFT = 4;
public final static int N_TSHIFT = 2;
public byte[] _n_name = new byte[SYMNMLEN]; /* Symbol name, or pointer into public byte[] _n_name = new byte[SYMNMLEN]; /* Symbol name, or pointer into
string table if symbol name string table if symbol name
is greater than SYMNMLEN. */ is greater than SYMNMLEN. */
@ -378,11 +390,51 @@ public class Coff {
n_numaux = memory.getByte(); n_numaux = memory.getByte();
} }
public String toString() { public boolean isLongName() {
StringBuffer buffer = new StringBuffer(); return (_n_name[0] == 0);
buffer.append("SYMBOL VALUES");
return buffer.toString();
} }
public String getName() {
for (int i = 0; i < _n_name.length; i++) {
if (_n_name[i] == 0) {
return new String(_n_name, 0, i);
}
}
return "";
}
public String getName(byte[] table) {
if (table.length > 0 && isLongName()) {
ReadMemoryAccess memory = new ReadMemoryAccess(_n_name, true);
memory.getInt();
int offset = memory.getInt();
if (offset > 0) {
for (int i = offset; i < table.length; i++) {
if (table[i] == 0) {
return new String(table, offset, i - offset);
}
}
}
}
return getName();
}
public boolean isPointer() {
return (n_type & N_TMASK) == (DT_PTR << N_BTSHFT);
}
public boolean isFunction() {
return (n_type & N_TMASK) == (DT_FCN << N_BTSHFT);
}
public boolean isArray() {
return (n_type & N_TMASK) == (DT_ARY << N_BTSHFT);
}
public String toString() {
return getName();
}
} }
public FileHeader getFileHeader() throws IOException { public FileHeader getFileHeader() throws IOException {
@ -467,19 +519,19 @@ public class Coff {
try { try {
Symbol[] table = getSymbols(); Symbol[] table = getSymbols();
for (int i = 0; i < table.length; i++) { for (int i = 0; i < table.length; i++) {
buffer.append(table[i]); buffer.append(table[i].getName(getStringTable())).append(NL);
} }
} catch (IOException e) { } catch (IOException e) {
} }
try { // try {
String[] strings = getStringTable(getStringTable()); // String[] strings = getStringTable(getStringTable());
for (int i = 0; i < strings.length; i++) { // for (int i = 0; i < strings.length; i++) {
buffer.append(strings[i]); // buffer.append(strings[i]);
} // }
} catch (IOException e) { // } catch (IOException e) {
e.printStackTrace(); // e.printStackTrace();
} // }
return buffer.toString(); return buffer.toString();
} }
@ -487,9 +539,9 @@ public class Coff {
List aList = new ArrayList(); List aList = new ArrayList();
int offset = 0; int offset = 0;
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
if (bytes[i] == '\0') { if (bytes[i] == 0) {
aList.add(new String(bytes, offset, (i + 1) - offset)); aList.add(new String(bytes, offset, i - offset));
offset = i; offset = i + 1;
} }
} }
return (String[])aList.toArray(new String[0]); return (String[])aList.toArray(new String[0]);

View file

@ -55,6 +55,7 @@ public class PE {
public static final String NL = System.getProperty("line.separator", "\n"); public static final String NL = System.getProperty("line.separator", "\n");
RandomAccessFile rfile; RandomAccessFile rfile;
String filename;
ExeHeader exeHeader; ExeHeader exeHeader;
DOSHeader dosHeader; DOSHeader dosHeader;
FileHeader fileHeader; FileHeader fileHeader;
@ -65,6 +66,39 @@ public class PE {
Symbol[] symbolTable; Symbol[] symbolTable;
byte[] stringTable; byte[] stringTable;
public class Attribute {
public static final int PE_TYPE_EXE = 1;
public static final int PE_TYPE_SHLIB = 2;
public static final int PE_TYPE_OBJ = 3;
public static final int PE_TYPE_CORE = 4;
String cpu;
int type;
int word;
boolean bDebug;
boolean isle;
public String getCPU() {
return cpu;
}
public int getType() {
return type;
}
public boolean hasDebug() {
return bDebug;
}
public boolean isLittleEndian() {
return isle;
}
public int getWord() {
return word;
}
}
/** /**
*/ */
public static class DOSHeader { public static class DOSHeader {
@ -239,15 +273,24 @@ public class PE {
} }
} }
public PE (String filename) throws IOException { public PE (String filename) throws IOException {
this(filename, 0);
}
public PE(String filename, long pos) throws IOException {
this(filename, pos, true);
}
public PE (String filename, long pos, boolean filter) throws IOException {
try {
rfile = new RandomAccessFile(filename, "r"); rfile = new RandomAccessFile(filename, "r");
this.filename = filename;
rfile.seek(pos);
// Object files do not have exe/dos header.
try {
exeHeader = new ExeHeader(rfile); exeHeader = new ExeHeader(rfile);
dosHeader = new DOSHeader(rfile); dosHeader = new DOSHeader(rfile);
// Jump the Coff header, and Check the sig. // Jump the Coff header, and Check the sig.
rfile.seek(dosHeader.e_lfanew); rfile.seek(dosHeader.e_lfanew);
byte[] sig = new byte[4]; byte[] sig = new byte[4];
@ -256,13 +299,158 @@ public class PE {
&& (sig[2] == '\0') && (sig[3] == '\0'))) { && (sig[2] == '\0') && (sig[3] == '\0'))) {
throw new IOException("Not a PE format"); throw new IOException("Not a PE format");
} }
} catch (IOException e) {
rfile.seek(pos);
}
fileHeader = new Coff.FileHeader(rfile, rfile.getFilePointer()); fileHeader = new Coff.FileHeader(rfile, rfile.getFilePointer());
// Check if this a valid machine.
switch (fileHeader.f_magic) {
case PEConstants.IMAGE_FILE_MACHINE_ALPHA:
case PEConstants.IMAGE_FILE_MACHINE_ARM:
case PEConstants.IMAGE_FILE_MACHINE_ALPHA64:
case PEConstants.IMAGE_FILE_MACHINE_I386:
case PEConstants.IMAGE_FILE_MACHINE_IA64:
case PEConstants.IMAGE_FILE_MACHINE_M68K:
case PEConstants.IMAGE_FILE_MACHINE_MIPS16:
case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU:
case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU16:
case PEConstants.IMAGE_FILE_MACHINE_POWERPC:
case PEConstants.IMAGE_FILE_MACHINE_R3000:
case PEConstants.IMAGE_FILE_MACHINE_R4000:
case PEConstants.IMAGE_FILE_MACHINE_R10000:
case PEConstants.IMAGE_FILE_MACHINE_SH3:
case PEConstants.IMAGE_FILE_MACHINE_SH4:
case PEConstants.IMAGE_FILE_MACHINE_THUMB:
// Ok;
break;
default:
throw new IOException("Unknow machine/format");
}
if (fileHeader.f_opthdr > 0) {
optionalHeader = new Coff.OptionalHeader(rfile, rfile.getFilePointer()); optionalHeader = new Coff.OptionalHeader(rfile, rfile.getFilePointer());
ntHeader = new NTOptionalHeader(rfile, rfile.getFilePointer()); ntHeader = new NTOptionalHeader(rfile, rfile.getFilePointer());
}
} finally {
if (rfile != null) {
rfile.close();
rfile = null;
}
}
}
public Attribute getAttribute() {
Attribute attrib = new Attribute();
FileHeader filhdr = getFileHeader();
// Machine type.
switch (filhdr.f_magic) {
case PEConstants.IMAGE_FILE_MACHINE_UNKNOWN:
attrib.cpu = "none";
break;
case PEConstants.IMAGE_FILE_MACHINE_ALPHA:
attrib.cpu = "alpha";
break;
case PEConstants.IMAGE_FILE_MACHINE_ARM:
attrib.cpu = "arm";
break;
case PEConstants.IMAGE_FILE_MACHINE_ALPHA64:
attrib.cpu = "arm64";
break;
case PEConstants.IMAGE_FILE_MACHINE_I386:
attrib.cpu = "i386";
break;
case PEConstants.IMAGE_FILE_MACHINE_IA64:
attrib.cpu = "ia64";
break;
case PEConstants.IMAGE_FILE_MACHINE_M68K:
attrib.cpu = "m68k";
break;
case PEConstants.IMAGE_FILE_MACHINE_MIPS16:
attrib.cpu = "mips16";
break;
case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU:
attrib.cpu = "mipsfpu";
break;
case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU16:
attrib.cpu = "mipsfpu16";
break;
case PEConstants.IMAGE_FILE_MACHINE_POWERPC:
attrib.cpu = "powerpc";
break;
case PEConstants.IMAGE_FILE_MACHINE_R3000:
attrib.cpu = "r3000";
break;
case PEConstants.IMAGE_FILE_MACHINE_R4000:
attrib.cpu = "r4000";
break;
case PEConstants.IMAGE_FILE_MACHINE_R10000:
attrib.cpu = "r10000";
break;
case PEConstants.IMAGE_FILE_MACHINE_SH3:
attrib.cpu = "sh3";
break;
case PEConstants.IMAGE_FILE_MACHINE_SH4:
attrib.cpu = "sh4";
break;
case PEConstants.IMAGE_FILE_MACHINE_THUMB:
attrib.cpu = "thumb";
break;
}
/* PE characteristics, FileHeader.f_flags. */
if ((filhdr.f_flags & PEConstants.IMAGE_FILE_DLL) != 0) {
attrib.type = attrib.PE_TYPE_SHLIB;
} else if ((filhdr.f_flags & PEConstants.IMAGE_FILE_EXECUTABLE_IMAGE) != 0) {
attrib.type = attrib.PE_TYPE_EXE;
} else {
attrib.type = attrib.PE_TYPE_OBJ;
}
// For PE always assume little endian unless otherwise.
attrib.isle = true;
// Little Endian.
if ((filhdr.f_flags & PEConstants.IMAGE_FILE_BYTES_REVERSED_LO) != 0) {
attrib.isle = true;
}
// Big Endian.
if ((filhdr.f_flags & PEConstants.IMAGE_FILE_BYTES_REVERSED_HI) != 0) {
attrib.isle = false;
}
// No debug information.
if ((filhdr.f_flags & PEConstants.IMAGE_FILE_DEBUG_STRIPPED) != 0) {
attrib.bDebug = false;
} else {
attrib.bDebug = true;
}
// sizeof word.
if ((filhdr.f_flags & PEConstants.IMAGE_FILE_16BIT_MACHINE) != 0) {
attrib.word = 16;
}
if ((filhdr.f_flags & PEConstants.IMAGE_FILE_32BIT_MACHINE) != 0) {
attrib.word = 32;
}
return attrib;
}
public void dispose() throws IOException {
if (rfile != null) {
rfile.close();
rfile = null;
}
}
protected void finalize() throws Throwable {
try {
dispose();
} finally {
super.finalize();
}
} }
public ExeHeader getExeHeader() { public ExeHeader getExeHeader() {
@ -287,40 +475,52 @@ public class PE {
public ImageDataDirectory[] getImageDataDirectories() throws IOException { public ImageDataDirectory[] getImageDataDirectories() throws IOException {
if (dataDirectories == null) { if (dataDirectories == null) {
long offset = dosHeader.e_lfanew + FileHeader.FILHSZ + RandomAccessFile accessFile = getRandomAccessFile();
OptionalHeader.AOUTHDRSZ + NTOptionalHeader.NTHDRSZ + 4/*NT SIG*/; long offset = 0;
rfile.seek(offset); if (dosHeader != null) {
offset = dosHeader.e_lfanew + 4/*NT SIG*/;
}
offset += FileHeader.FILHSZ + OptionalHeader.AOUTHDRSZ + NTOptionalHeader.NTHDRSZ;
accessFile.seek(offset);
dataDirectories = new ImageDataDirectory[PEConstants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; dataDirectories = new ImageDataDirectory[PEConstants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
byte[] data = new byte[dataDirectories.length * (4 + 4)]; byte[] data = new byte[dataDirectories.length * (4 + 4)];
rfile.readFully(data); accessFile.readFully(data);
ReadMemoryAccess memory = new ReadMemoryAccess(data, true); ReadMemoryAccess memory = new ReadMemoryAccess(data, true);
for (int i = 0; i < dataDirectories.length; i++) { for (int i = 0; i < dataDirectories.length; i++) {
int rva = memory.getInt(); int rva = memory.getInt();
int size = memory.getInt(); int size = memory.getInt();
dataDirectories[i] = new ImageDataDirectory(rva, size); dataDirectories[i] = new ImageDataDirectory(rva, size);
} }
dispose();
} }
return dataDirectories; return dataDirectories;
} }
public SectionHeader[] getSectionHeaders() throws IOException { public SectionHeader[] getSectionHeaders() throws IOException {
if (scnhdrs == null) { if (scnhdrs == null) {
RandomAccessFile accessFile = getRandomAccessFile();
scnhdrs = new SectionHeader[fileHeader.f_nscns]; scnhdrs = new SectionHeader[fileHeader.f_nscns];
long offset = dosHeader.e_lfanew + long offset = 0;
FileHeader.FILHSZ + fileHeader.f_opthdr + 4 /* NT SIG */; if (dosHeader != null) {
for (int i = 0; i < scnhdrs.length; i++, offset += SectionHeader.SCNHSZ) { offset = dosHeader.e_lfanew + 4 /* NT SIG */;
scnhdrs[i] = new SectionHeader(rfile, offset);
} }
offset += FileHeader.FILHSZ + fileHeader.f_opthdr;
for (int i = 0; i < scnhdrs.length; i++, offset += SectionHeader.SCNHSZ) {
scnhdrs[i] = new SectionHeader(accessFile, offset);
}
dispose();
} }
return scnhdrs; return scnhdrs;
} }
public Symbol[] getSymbols() throws IOException { public Symbol[] getSymbols() throws IOException {
if (symbolTable == null) { if (symbolTable == null) {
RandomAccessFile accessFile = getRandomAccessFile();
long offset = fileHeader.f_symptr; long offset = fileHeader.f_symptr;
symbolTable = new Symbol[fileHeader.f_nsyms]; symbolTable = new Symbol[fileHeader.f_nsyms];
for (int i = 0; i < symbolTable.length; i++, offset += Symbol.SYMSZ) { for (int i = 0; i < symbolTable.length; i++, offset += Symbol.SYMSZ) {
symbolTable[i] = new Symbol(rfile, offset); symbolTable[i] = new Symbol(accessFile, offset);
} }
dispose();
} }
return symbolTable; return symbolTable;
} }
@ -328,20 +528,22 @@ public class PE {
public byte[] getStringTable() throws IOException { public byte[] getStringTable() throws IOException {
if (stringTable == null) { if (stringTable == null) {
if (fileHeader.f_nsyms > 0) { if (fileHeader.f_nsyms > 0) {
RandomAccessFile accessFile = getRandomAccessFile();
long symbolsize = Symbol.SYMSZ * fileHeader.f_nsyms; long symbolsize = Symbol.SYMSZ * fileHeader.f_nsyms;
long offset = fileHeader.f_symptr + symbolsize; long offset = fileHeader.f_symptr + symbolsize;
rfile.seek(offset); accessFile.seek(offset);
byte[] bytes = new byte[4]; byte[] bytes = new byte[4];
rfile.readFully(bytes); accessFile.readFully(bytes);
int str_len = ReadMemoryAccess.getIntLE(bytes); int str_len = ReadMemoryAccess.getIntLE(bytes);
if (str_len > 4) { if (str_len > 4) {
str_len -= 4; str_len -= 4;
stringTable = new byte[str_len]; stringTable = new byte[str_len];
rfile.seek(offset + 4); accessFile.seek(offset + 4);
rfile.readFully(stringTable); accessFile.readFully(stringTable);
} else { } else {
stringTable = new byte[0]; stringTable = new byte[0];
} }
dispose();
} else { } else {
stringTable = new byte[0]; stringTable = new byte[0];
} }
@ -351,11 +553,19 @@ public class PE {
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
if (exeHeader != null) {
buffer.append(exeHeader); buffer.append(exeHeader);
}
if (dosHeader != null) {
buffer.append(dosHeader); buffer.append(dosHeader);
}
buffer.append(fileHeader); buffer.append(fileHeader);
if (optionalHeader != null) {
buffer.append(optionalHeader); buffer.append(optionalHeader);
}
if (ntHeader != null) {
buffer.append(ntHeader); buffer.append(ntHeader);
}
try { try {
ImageDataDirectory[] dirs = getImageDataDirectories(); ImageDataDirectory[] dirs = getImageDataDirectories();
for (int i = 0; i < dirs.length; i++) { for (int i = 0; i < dirs.length; i++) {
@ -396,6 +606,12 @@ public class PE {
return buffer.toString(); return buffer.toString();
} }
RandomAccessFile getRandomAccessFile () throws IOException {
if (rfile == null) {
rfile = new RandomAccessFile(filename, "r");
}
return rfile;
}
public static void main(String[] args) { public static void main(String[] args) {
try { try {
PE pe = new PE(args[0]); PE pe = new PE(args[0]);