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

2004-06-21 Alain Magloire

Big Patch from Vladimir Hirsl
	This patch contains a binary parser core and UI elements to 'support' AIX
	XCOFF32 binaries.
This commit is contained in:
Alain Magloire 2004-06-21 22:08:09 +00:00
parent 43bd85438e
commit 416238652a
14 changed files with 1852 additions and 1 deletions

View file

@ -1,3 +1,9 @@
2004-06-21 Alain Magloire
Big Patch from Vladimir Hirsl
This patch contains a binary parser core and UI elements to 'support' AIX
XCOFF32 binaries.
2004-06-21 Alain Magloire
The PathEntryManager was returning the array instead

View file

@ -19,6 +19,7 @@ ElfParser.name=Elf Parser
GNUElfParser.name=GNU Elf Parser
PEWindowsParser.name=PE Windows Parser
CygwinPEParser.name=Cygwin PE Parser
XCOFF32Parser.name=AIX XCOFF32 Parser
CDTGNUCErrorParser.name=CDT GNU C/C++ Error Parser
CDTGNUAssemblerErrorParser.name=CDT GNU Assembler Error Parser

View file

@ -97,6 +97,16 @@
</run>
</cextension>
</extension>
<extension
id="XCOFF32"
name="%XCOFF32Parser.name"
point="org.eclipse.cdt.core.BinaryParser">
<cextension>
<run
class="org.eclipse.cdt.utils.xcoff.parser.XCOFF32Parser">
</run>
</cextension>
</extension>
<!-- This is for backward compatibility: an Typo was introduce in on of the realease
and "ELF" instead of "Elf" -->
<extension

View file

@ -47,6 +47,7 @@ Util.exception.arrayToSmall=Array to small
Util.exception.notPE=Not a PE format
Util.exception.notELF=Not ELF format
Util.exception.notDOSFormat=Not DOS EXE format
Util.exception.notXCOFF32=Not XCOFF32 format
Util.exception.unknownFormat=Unknow machine/format
Util.exception.nullPath=Path is null
Util.exception.noFileAssociation=No file associated with Binary

View file

@ -0,0 +1,380 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.utils.xcoff;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Vector;
import org.eclipse.cdt.core.CCorePlugin;
/**
* The <code>AR</code> class is used for parsing standard XCOFF32 archive (ar) files.
*
* Each object within the archive is represented by an ARHeader class. Each of
* of these objects can then be turned into an XCOFF32 object for performing XCOFF32
* class operations.
* @see MemberHeader
*
* @author vhirsl
*/
public class AR {
protected String filename;
protected RandomAccessFile file;
private ARHeader header;
private MemberHeader[] memberHeaders;
/**
* TODO Provide description
*
* @author vhirsl
*/
public class ARHeader {
private final static int SAIAMAG = 8;
private byte[] fl_magic = new byte[SAIAMAG];// Archive magic string
private byte[] fl_memoff = new byte[20]; // Offset to member table
private byte[] fl_gstoff = new byte[20]; // Offset to global symbol table
private byte[] fl_gst64off = new byte[20]; // Offset to global symbol table for 64-bit objects
private byte[] fl_fstmoff = new byte[20]; // Offset to first archive member
private byte[] fl_lstmoff = new byte[20]; // Offset to last archive member
private byte[] fl_freeoff = new byte[20]; // Offset to first member on free list
private long fstmoff = 0;
private long lstmoff = 0;
private long memoff = 0;
public ARHeader() throws IOException {
try {
getRandomAccessFile();
file.seek(0);
file.read(fl_magic);
if (isARHeader(fl_magic)) {
file.read(fl_memoff);
file.read(fl_gstoff);
file.read(fl_gst64off);
file.read(fl_fstmoff);
file.read(fl_lstmoff);
file.read(fl_freeoff);
fstmoff = Long.parseLong(removeBlanks(new String(fl_fstmoff)));
lstmoff = Long.parseLong(removeBlanks(new String(fl_lstmoff)));
memoff = Long.parseLong(removeBlanks(new String(fl_memoff)));
}
} catch (IOException e) {
dispose();
CCorePlugin.log(e);
}
}
/**
* @return boolean
*/
public boolean isXcoffARHeader() {
return (fstmoff != 0);
}
}
/**
* Creates a new <code>AR</code> object from the contents of
* the given file.
*
* @param filename The file to process.
* @throws IOException The file is not a valid archive.
*/
public AR(String filename) throws IOException {
this.filename = filename;
file = new RandomAccessFile(filename, "r"); //$NON-NLS-1$
header = new ARHeader();
if (!header.isXcoffARHeader()) {
file.close();
throw new IOException(CCorePlugin.getResourceString("Util.exception.invalidArchive")); //$NON-NLS-1$
}
}
public void dispose() {
try {
if (file != null) {
file.close();
file = null;
}
} catch (IOException e) {
}
}
protected void finalize() throws Throwable {
try {
dispose();
} finally {
super.finalize();
}
}
public static boolean isARHeader(byte[] ident) {
if (ident.length < 8
|| ident[0] != '<'
|| ident[1] != 'b'
|| ident[2] != 'i'
|| ident[3] != 'g'
|| ident[4] != 'a'
|| ident[5] != 'f'
|| ident[6] != '>'
|| ident[7] != '\n')
return false;
return true;
}
/**
* The <code>ARHeader</code> class is used to store the per-object file
* archive headers. It can also create an XCOFF32 object for inspecting
* the object file data.
*/
public class MemberHeader {
byte[] ar_size = new byte[20]; // File member size - decimal
byte[] ar_nxtmem = new byte[20]; // Next member offset - decimal
byte[] ar_prvmem = new byte[20]; // Previous member offset - decimal
byte[] ar_date = new byte[12]; // File member date - decimal
byte[] ar_uid = new byte[12]; // File member userid - decimal
byte[] ar_gid = new byte[12]; // File member group id - decimal
byte[] ar_mode = new byte[12]; // File member mode - octal
byte[] ar_namlen = new byte[4]; // File member name length -decimal
byte[] ar_name; // Start of member name
byte[] ar_fmag = new byte[2]; // AIAFMAG - string to end "`\n"
// converted values
long size;
long nxtmem;
long prvmem;
int namlen;
String name;
long file_offset;
/**
* Remove the padding from the archive header strings.
*/
private String removeBlanks(String str) {
while (str.charAt(str.length() - 1) == ' ')
str = str.substring(0, str.length() - 1);
return str;
}
/**
* Look up the name stored in the archive's string table based
* on the offset given.
*
* Maintains <code>file</code> file location.
*
* @param offset
* Offset into the string table for first character of the name.
* @throws IOException
* <code>offset</code> not in string table bounds.
*/
// private String nameFromStringTable(long offset) throws IOException {
// StringBuffer name = new StringBuffer(0);
// long pos = file.getFilePointer();
//
// try {
// if (strtbl_pos != -1) {
// byte temp;
// file.seek(strtbl_pos + offset);
// while ((temp = file.readByte()) != '\n')
// name.append((char) temp);
// }
// } finally {
// file.seek(pos);
// }
//
// return name.toString();
// }
/**
* Creates a new archive header object.
*
* Assumes that file is already at the correct location in the file.
*
* @throws IOException
* There was an error processing the header data from the file.
*/
public MemberHeader() throws IOException {
//
// Read in the archive header data. Fixed sizes.
//
file.read(ar_size);
file.read(ar_nxtmem);
file.read(ar_prvmem);
file.read(ar_date);
file.read(ar_uid);
file.read(ar_gid);
file.read(ar_mode);
file.read(ar_namlen);
namlen = Integer.parseInt(removeBlanks(new String(ar_namlen)));
ar_name = new byte[namlen];
file.read(ar_name);
file.read(ar_fmag);
size = Long.parseLong(removeBlanks(new String(ar_size)));
nxtmem = Long.parseLong(removeBlanks(new String(ar_nxtmem)));
prvmem = Long.parseLong(removeBlanks(new String(ar_prvmem)));
name = new String(ar_name, 0, namlen);
//
// Save this location so we can create the XCOFF32 object later.
//
file_offset = file.getFilePointer();
if ((file_offset % 2) == 1) {
++file_offset;
}
}
/** Get the name of the object file */
public String getObjectName() {
return name;
}
/** Get the size of the object file . */
public long getSize() {
return size;
}
public String getArchiveName() {
return filename;
}
/**
* Create an new XCOFF32 object for the object file.
*
* @throws IOException
* Not a valid XCOFF32 object file.
* @return A new XCOFF32 object.
* @see XCoff32#XCoff32( String, long )
*/
public XCoff32 getXCoff() throws IOException {
return new XCoff32(filename, file_offset);
}
public byte[] getObjectData() throws IOException {
byte[] temp = new byte[(int) size];
file = getRandomAccessFile();
file.seek(file_offset);
file.read(temp);
dispose();
return temp;
}
}
/** Load the headers from the file (if required). */
private void loadHeaders() throws IOException {
if (memberHeaders != null)
return;
Vector v = new Vector();
try {
//
// Check for EOF condition
//
MemberHeader aHeader;
for (long pos = header.fstmoff; pos < file.length(); pos = aHeader.nxtmem) {
file.seek(pos);
aHeader = new MemberHeader();
String name = aHeader.getObjectName();
v.add(aHeader);
if (pos == 0 || pos == header.lstmoff) { // end of double linked list
break;
}
}
} catch (IOException e) {
}
memberHeaders = (MemberHeader[]) v.toArray(new MemberHeader[0]);
}
/**
* Get an array of all the object file headers for this archive.
*
* @throws IOException
* Unable to process the archive file.
* @return An array of headers, one for each object within the archive.
* @see ARHeader
*/
public MemberHeader[] getHeaders() throws IOException {
loadHeaders();
return memberHeaders;
}
public String[] extractFiles(String outdir, String[] names) throws IOException {
Vector names_used = new Vector();
String object_name;
int count;
loadHeaders();
count = 0;
for (int i = 0; i < memberHeaders.length; i++) {
object_name = memberHeaders[i].getObjectName();
if (names != null && !stringInStrings(object_name, names))
continue;
object_name = "" + count + "_" + object_name; //$NON-NLS-1$ //$NON-NLS-2$
count++;
byte[] data = memberHeaders[i].getObjectData();
File output = new File(outdir, object_name);
names_used.add(object_name);
RandomAccessFile rfile = new RandomAccessFile(output, "rw"); //$NON-NLS-1$
rfile.write(data);
rfile.close();
}
return (String[]) names_used.toArray(new String[0]);
}
private boolean stringInStrings(String str, String[] set) {
for (int i = 0; i < set.length; i++)
if (str.compareTo(set[i]) == 0)
return true;
return false;
}
/**
* Remove the padding from the archive header strings.
*/
private String removeBlanks(String str) {
while (str.charAt(str.length() - 1) == ' ')
str = str.substring(0, str.length() - 1);
return str;
}
public String[] extractFiles(String outdir) throws IOException {
return extractFiles(outdir, null);
}
private RandomAccessFile getRandomAccessFile () throws IOException {
if (file == null) {
file = new RandomAccessFile(filename, "r"); //$NON-NLS-1$
}
return file;
}
public static void main(String[] args) {
try {
AR ar = new AR(args[0]);
ar.getHeaders();
ar.extractFiles(args[0]);
System.out.println(ar);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,828 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.utils.xcoff;
import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.utils.coff.ReadMemoryAccess;
/**
* TODO Provide description
*
* @author vhirsl
*/
public class XCoff32 {
public static final String NL = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
String filename;
FileHeader filehdr;
OptionalHeader opthdr;
RandomAccessFile rfile;
long startingOffset;
byte[] string_table;
SectionHeader[] scnhdrs;
Symbol[] symbols;
public static class FileHeader {
public final static int FILHSZ = 20;
// Consts
public final static int U802TOCMAGIC = 0x01df; // XCOFF32
public final static int U803TOCMAGIC = 0x01e7; // obsolete XCOFF64 - not used
public final static int U803XTOCMAGIC = 0x01ef; // discontinued AIX XCOFF64
public final static int U64_TOCMAGIC = 0x01f7; // XCOFF64
// Flags
public final static int F_RELFLG = 0x0001; // relocation info stripped from file
public final static int F_EXEC = 0x0002; // file is executable
// (no unresolved external references)
public final static int F_LNNO = 0x0004; // line numbers stripped from file
public final static int F_LSYMS = 0x0008; // local symbols stripped from file
public final static int F_FDPR_PROF = 0x0010; // file was profiled with fdpr command
public final static int F_FDPR_OPTI = 0x0020; // file was reordered with fdpr command
public final static int F_DSA = 0x0040; // file uses Very Large Program Support
// public final static int F_AR16WR = 0x0080; // file is 16-bit little-endian
// public final static int F_AR32WR = 0x0100; // file is 32-bit little-endian
// public final static int F_AR32W = 0x0200; // file is 32-bit big-endian
public final static int F_DYNLOAD = 0x1000; // rs/6000 aix: dynamically
// loadable w/imports & exports
public final static int F_SHROBJ = 0x2000; // rs/6000 aix: file is a shared object
public final static int F_LOADONLY = 0x4000;// rs/6000 aix: if the object file is a member of an archive;
// it can be loaded by the system loader but the member is ignored by the binder.
// Fields
public short f_magic; /* 00-01 2 bytes: magic number */
public short f_nscns; /* 02-03 2 bytes: number of sections: 2 bytes */
public int f_timdat; /* 04-07 4 bytes: time & date stamp */
public int f_symptr; /* 08-11 4 bytes: file pointer to symtab */
public int f_nsyms; /* 12-15 4 bytes: number of symtab entries */
public short f_opthdr; /* 16-17 2 bytes: sizeof(optional hdr) */
public short f_flags; /* 18-19 2 bytes: flags */
public FileHeader (RandomAccessFile file) throws IOException {
this(file, file.getFilePointer());
}
public FileHeader (RandomAccessFile file, long offset) throws IOException {
file.seek(offset);
byte[] hdr = new byte[FILHSZ];
file.readFully(hdr);
commonSetup(hdr, false);
}
public FileHeader (byte[] hdr, boolean little) throws IOException {
commonSetup(hdr, little);
}
public void commonSetup(byte[] hdr, boolean little) throws IOException {
if (hdr == null || hdr.length < FILHSZ) {
throw new EOFException(CCorePlugin.getResourceString("Util.exception.arrayToSmall")); //$NON-NLS-1$
}
if (!isXCOFF32Header(hdr)) {
throw new IOException(CCorePlugin.getResourceString("Util.exception.notXCOFF32")); //$NON-NLS-1$
}
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, little);
f_magic = memory.getShort();
f_nscns = memory.getShort();
f_timdat = memory.getInt();
f_symptr = memory.getInt();
f_nsyms = memory.getInt();
f_opthdr = memory.getShort();
f_flags = memory.getShort();
}
public boolean isStrip() {
return (f_flags & F_RELFLG) == F_RELFLG;
}
public boolean isExec() {
return (f_flags & F_EXEC) == F_EXEC;
}
public boolean isDebug() {
return !((f_flags & F_LNNO) == F_LNNO);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("FILE HEADER VALUES").append(NL); //$NON-NLS-1$
buffer.append("f_magic = ").append(f_magic).append(NL); //$NON-NLS-1$
buffer.append("f_nscns = ").append(f_nscns).append(NL); //$NON-NLS-1$
buffer.append("f_timdat = "); //$NON-NLS-1$
buffer.append(DateFormat.getDateInstance().format(new Date(f_timdat)));
buffer.append(NL);
buffer.append("f_symptr = ").append(f_symptr).append(NL); //$NON-NLS-1$
buffer.append("f_nsyms = ").append(f_nsyms).append(NL); //$NON-NLS-1$
buffer.append("f_opthdr = ").append(f_opthdr).append(NL); //$NON-NLS-1$
buffer.append("f_flags = ").append(f_flags).append(NL); //$NON-NLS-1$
return buffer.toString();
}
}
public static class OptionalHeader {
public final static int AOUTHDRSZ = 72; // First 28 bytes same as for COFF
// Fields (as in COFF)
public short magic; /* 2 bytes: type of file (0x010B) */
public short vstamp; /* 2 bytes: version stamp (1) */
public int tsize; /* 4 bytes: text size in bytes, padded to FW bdry */
public int dsize; /* 4 bytes: initialized data " " */
public int bsize; /* 4 bytes: uninitialized data " " */
public int entry; /* 4 bytes: entry pt. */
public int text_start; /* 4 bytes: base of text used for this file */
public int data_start; /* 4 bytes: base of data used for this file */
// Additional fields
public int o_toc; /* 4 bytes: Address of TOC anchor */
public short o_snentry; /* 2 bytes: Section number for entry point */
public short o_sntext; /* 2 bytes: Section number for .text */
public short o_sndata; /* 2 bytes: Section number for .data */
public short o_sntoc; /* 2 bytes: Section number for TOC */
public short o_snloader;/* 2 bytes: Section number for loader data */
public short o_snbss; /* 2 bytes: Section number for .bss */
public short o_algntext;/* 2 bytes: Maximum alignment for .text */
public short o_algndata;/* 2 bytes: Maximum alignment for .data */
public short o_modtype; /* 2 bytes: Maximum alignment for .data */
public byte o_cpuflag; /* 1 byte: Bit flags - cpu types of objects */
public byte o_cputype; /* 1 byte: Reserved for cpu type */
public int o_maxstack; /* 4 bytes: Maximum stack size allowed (bytes) */
public int o_maxdata; /* 4 bytes: Maximum data size allowed (bytes) */
public int o_debugger; /* 4 bytes: Reserved for debuggers */
// public byte o_resv2[8]; /* 8 bytes: Reserved. Field must contain 0s */
public OptionalHeader(RandomAccessFile file) throws IOException {
this(file, file.getFilePointer() + FileHeader.FILHSZ);
}
public OptionalHeader(RandomAccessFile file, long offset) throws IOException {
file.seek(offset);
byte[] hdr = new byte[AOUTHDRSZ];
file.readFully(hdr);
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, false); // big endian
// COFF common
magic = memory.getShort();
vstamp = memory.getShort();
tsize = memory.getInt();
dsize = memory.getInt();
bsize = memory.getInt();
entry = memory.getInt();
text_start = memory.getInt();
data_start = memory.getInt();
// XCOFF32 specific
o_toc = memory.getInt();
o_snentry = memory.getShort();
o_sntext = memory.getShort();
o_sndata = memory.getShort();
o_sntoc = memory.getShort();
o_snloader = memory.getShort();
o_snbss = memory.getShort();
o_algntext = memory.getShort();
o_algndata = memory.getShort();
o_modtype = memory.getShort();
o_cpuflag = memory.getByte();
o_cputype = memory.getByte();
o_maxstack = memory.getInt();
o_maxdata = memory.getInt();
o_debugger = memory.getInt();
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("OPTIONAL HEADER VALUES").append(NL); //$NON-NLS-1$
buffer.append("magic = ").append(magic).append(NL); //$NON-NLS-1$
buffer.append("vstamp = ").append(vstamp).append(NL); //$NON-NLS-1$
buffer.append("tsize = ").append(tsize).append(NL); //$NON-NLS-1$
buffer.append("dsize = ").append(dsize).append(NL); //$NON-NLS-1$
buffer.append("bsize = ").append(bsize).append(NL); //$NON-NLS-1$
buffer.append("entry = ").append(entry).append(NL); //$NON-NLS-1$
buffer.append("text_start = ").append(text_start).append(NL); //$NON-NLS-1$
buffer.append("data_start = ").append(data_start).append(NL); //$NON-NLS-1$
buffer.append("o_toc = ").append(o_toc).append(NL); //$NON-NLS-1$
buffer.append("o_snentry = ").append(o_snentry).append(NL); //$NON-NLS-1$
buffer.append("o_sntext = ").append(o_sntext).append(NL); //$NON-NLS-1$
buffer.append("o_sndata = ").append(o_sndata).append(NL); //$NON-NLS-1$
buffer.append("o_sntoc = ").append(o_sntoc).append(NL); //$NON-NLS-1$
buffer.append("o_snloader = ").append(o_snloader).append(NL); //$NON-NLS-1$
buffer.append("o_snbss = ").append(o_snbss).append(NL); //$NON-NLS-1$
buffer.append("o_algntext = ").append(o_algntext).append(NL); //$NON-NLS-1$
buffer.append("o_algndata = ").append(o_algndata).append(NL); //$NON-NLS-1$
buffer.append("o_modtype = ").append(o_modtype).append(NL); //$NON-NLS-1$
buffer.append("o_cpuflag = ").append(o_cpuflag).append(NL); //$NON-NLS-1$
buffer.append("o_cputype = ").append(o_cputype).append(NL); //$NON-NLS-1$
buffer.append("o_maxstack = ").append(o_maxstack).append(NL); //$NON-NLS-1$
buffer.append("o_maxdata = ").append(o_maxdata).append(NL); //$NON-NLS-1$
buffer.append("o_debugger = ").append(o_debugger).append(NL); //$NON-NLS-1$
return buffer.toString();
}
}
public static class SectionHeader {
public final static int SCNHSZ = 40;
/* names of "special" sections */
public final static String _TEXT = ".text"; //$NON-NLS-1$
public final static String _DATA = ".data"; //$NON-NLS-1$
public final static String _BSS = ".bss"; //$NON-NLS-1$
public final static String _PAD = ".pad"; //$NON-NLS-1$
public final static String _LOADER = ".loader"; //$NON-NLS-1$
public final static String _DEBUG = ".debug"; //$NON-NLS-1$
public final static String _TYPCHK = ".typchk"; //$NON-NLS-1$
public final static String _EXCEPT = ".except"; //$NON-NLS-1$
public final static String _OVRFLO = ".ovrflo"; //$NON-NLS-1$
public final static String _INFO = ".info"; //$NON-NLS-1$
/* s_flags "type". */
// public final static int STYP_REG = 0x0000; /* "regular": allocated, relocated,
// loaded */
// public final static int STYP_DSECT = 0x0001; /* "dummy": relocated only */
// public final static int STYP_NOLOAD = 0x0002; /* "noload": allocated, relocated,
// not loaded */
// public final static int STYP_GROUP = 0x0004; /* "grouped": formed of input
// sections */
public final static int STYP_PAD = 0x0008; /* "padding": not allocated, not
relocated, loaded */
// public final static int STYP_COPY = 0x0010; /* "copy": for decision function
// used by field update;
// not allocated, not relocated,
// loaded; reloc & lineno entries
// processed normally */
public final static int STYP_TEXT = 0x0020; /* section contains text only. */
// public final static int S_SHRSEG = 0x0020; /* In 3b Update files (output of
// ogen), sections which appear in
// SHARED segments of the Pfile
// will have the S_SHRSEG flag set
// by ogen, to inform dufr that
// updating 1 copy of the proc. will
// update all process invocations. */
public final static int STYP_DATA = 0x0040; /* section contains data only */
public final static int STYP_BSS = 0x0080; /* section contains bss only */
public final static int STYP_EXCEPT = 0x0080; /* section contains exceptions info only */
// public final static int S_NEWFCN = 0x0100; /* In a minimal file or an update
// file, a new function (as
// compared with a replaced
// function) */
public final static int STYP_INFO = 0x0200; /* comment: not allocated not
relocated, not loaded */
// public final static int STYP_OVER = 0x0400; /* overlay: relocated not allocated
// or loaded */
// public final static int STYP_LIB = 0x0800; /* for .lib: same as INFO */
public final static int STYP_LOADER = 0x1000; /* loader section:
imported symbols,
exported symbols,
relocation data,
type-check information and
shared object names */
// public final static int STYP_MERGE = 0x2000; /* merge section -- combines with
// text, data or bss sections only */
public final static int STYP_DEBUG = 0x2000; /* debug section - su
information used by the symbolic debugger */
// public final static int STYP_REVERSE_PAD = 0x4000; /* section will be padded
// with no-op instructions
// wherever padding is necessary
// and there is a word of
// contiguous bytes beginning on a
// word boundary. */
public final static int STYP_TYPCHK = 0x4000; /* type-check section - contains
parameter/argument type-check strings used by the binder */
public final static int STYP_OVRFLO = 0x8000; /* overflow section:
Specifies a relocation or line-number field overflow section.
A section header of this type contains the count of relocation
entries and line number entries for some other section.
This section header is required when either of the counts
exceeds 65,534. */
// public final static int STYP_LIT = 0x8020; /* Literal data (like STYP_TEXT) */
public byte[] s_name= new byte[8]; // 8 bytes: section name
public int s_paddr; // 4 bytes: physical address, aliased s_nlib
public int s_vaddr; // 4 bytes: virtual address
public int s_size; // 4 bytes: section size
public int s_scnptr; // 4 bytes: file ptr to raw data for section
public int s_relptr; // 4 bytes: file ptr to relocation
public int s_lnnoptr; // 4 bytes: file ptr to line numbers
public short s_nreloc; // 2 bytes: number of relocation entries
public short s_nlnno; // 2 bytes: number of line number entries
public int s_flags; // 4 bytes: flags
RandomAccessFile sfile;
public SectionHeader(RandomAccessFile file, long offset) throws IOException {
sfile = file;
file.seek(offset);
byte[] hdr = new byte[SCNHSZ];
file.readFully(hdr);
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, false);
memory.getBytes(s_name);
s_paddr = memory.getInt();
s_vaddr = memory.getInt();
s_size = memory.getInt();
s_scnptr = memory.getInt();
s_relptr = memory.getInt();
s_lnnoptr = memory.getInt();
s_nreloc = memory.getShort();
s_nlnno = memory.getShort();
s_flags = memory.getInt();
}
public byte[] getRawData() throws IOException {
byte[] data = new byte[s_size];
sfile.seek(s_scnptr);
sfile.readFully(data);
return data;
}
// public Reloc[] getRelocs() throws IOException {
// Reloc[] relocs = new Reloc[s_nreloc];
// sfile.seek(s_relptr);
// for (int i = 0; i < s_nreloc; i++) {
// relocs[i] = new Reloc(sfile);
// }
// return relocs;
// }
//
// public Lineno[] getLinenos() throws IOException {
// Lineno[] lines = new Lineno[s_nlnno];
// sfile.seek(s_lnnoptr);
// for (int i = 0; i < s_nlnno; i++) {
// lines[i] = new Lineno(sfile);
// }
// return lines;
// }
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("SECTION HEADER VALUES").append(NL); //$NON-NLS-1$
buffer.append(new String(s_name)).append(NL);
buffer.append("s_paddr = ").append(s_paddr).append(NL); //$NON-NLS-1$
buffer.append("s_vaddr = ").append(s_vaddr).append(NL); //$NON-NLS-1$
buffer.append("s_size = ").append(s_size).append(NL); //$NON-NLS-1$
buffer.append("s_scnptr = ").append(s_scnptr).append(NL); //$NON-NLS-1$
buffer.append("s_relptr = ").append(s_relptr).append(NL); //$NON-NLS-1$
buffer.append("s_lnnoptr = ").append(s_lnnoptr).append(NL); //$NON-NLS-1$
buffer.append("s_nreloc = ").append(s_nreloc).append(NL); //$NON-NLS-1$
buffer.append("s_nlnno = ").append(s_nlnno).append(NL); //$NON-NLS-1$
buffer.append("s_flags = ").append(s_flags).append(NL); //$NON-NLS-1$
/*
try {
Reloc[] rcs = getRelocs();
for (int i = 0; i < rcs.length; i++) {
buffer.append(rcs[i]);
}
} catch (IOException e) {
}
try {
Lineno[] nos = getLinenos();
for (int i = 0; i < nos.length; i++) {
buffer.append(nos[i]);
}
} catch (IOException e) {
}
*/
return buffer.toString();
}
}
public class Symbol {
public final static int SYMSZ = 18;
public final static int SYMNMLEN = 8;
/* section number, in n_scnum. */
public final static int N_DEBUG = -2;
public final static int N_ABS = -1;
public final static int N_UNDEF = 0;
/* Storage class, in n_sclass. */
public final static int C_BCOMM = 135; /* beginning of the common block */
public final static int C_BINCL = 108; /* beginning of include file */
public final static int C_BLOCK = 100; /* beginning or end of inner block */
public final static int C_BSTAT = 143; /* beginning of static block */
public final static int C_DECL = 140; /* declaration of object (type) */
public final static int C_ECOML = 136; /* local member of common block */
public final static int C_ECOMM = 127; /* end of common block */
public final static int C_EINCL = 109; /* end of include file */
public final static int C_ENTRY = 141; /* alternate entry */
public final static int C_ESTAT = 144; /* end of static block */
public final static int C_EXT = 2; /* external symbol */
public final static int C_FCN = 101; /* beginning or end of function */
public final static int C_FILE = 103; /* source file name and compiler information */
public final static int C_FUN = 142; /* function or procedure */
public final static int C_GSYM = 128; /* global variable */
public final static int C_HIDEXT = 107; /* unnamed external symbol */
public final static int C_INFO = 100; /* comment section reference */
public final static int C_LSYM = 129; /* automatic variable allocated on stack */
public final static int C_NULL = 0; /* symbol table entry marked for deletion */
public final static int C_PSYM = 130; /* argument to subroutine allocated on stack */
public final static int C_RPSYM = 132; /* argument to function or procedure stored in register */
public final static int C_RSYM = 131; /* register variable */
public final static int C_STAT = 3; /* static symbol (unknown) */
public final static int C_STSYM = 133; /* statically allocated symbol */
public final static int C_TCSYM = 134; /* reserved */
public final static int C_WEAKEXT = 111;/* weak external symbol */
/* csect storage class, in x_smlas. */
public final static int XMC_PR = 0; /* program code */
public final static int XMC_RO = 1; /* read only constant */
public final static int XMC_DB = 2; /* debug dictionary table */
public final static int XMC_TC = 3; /* general TOC entry */
public final static int XMC_UA = 4; /* unclassified */
public final static int XMC_RW = 5; /* read/write data */
public final static int XMC_GL = 6; /* global linkage */
public final static int XMC_XO = 7; /* extended operation */
public final static int XMC_SV = 8; /* 32-bit supervisor call descriptor csect */
public final static int XMC_BS = 9; /* BSS class (uninitialized static internal) */
public final static int XMC_DS = 10; /* csect containing a function descriptor */
public final static int XMC_UC = 11; /* unnamed FORTRAN common */
public final static int XMC_TI = 12; /* reserved */
public final static int XMC_TB = 13; /* reserved */
public final static int XMC_TC0 = 15; /* TOC anchor for TOC addressability */
public final static int XMC_TD = 16; /* scalar data entry in TOC */
public final static int XMC_SV64 = 17; /* 64-bit supervisor call descriptor csect */
public final static int XMC_SV3264 = 18;/* supervisor call descriptor csect for both 32-bit and 64-bit */
// fields
public byte[] _n_name = new byte[SYMNMLEN]; /* Symbol name, or pointer into
string table if symbol name
is greater than SYMNMLEN. */
public int n_value; /* long. Symbol's value: dependent on section number,
storage class and type. */
public short n_scnum; /* short, Section number. */
public short n_type; /* Unsigned short. Symbolic type. Obsolete in XCOFF */
public byte n_sclass; /* char, Storage class. */
public byte n_numaux; /* char. Nuymber of auxiliary enties. */
private byte[] aux;
public byte x_smclas; /* storage mapping class in csect auxiliary entry */
public Symbol(RandomAccessFile file) throws IOException {
this(file, file.getFilePointer());
}
public Symbol(RandomAccessFile file, long offset) throws IOException {
file.seek(offset);
byte[] bytes = new byte[SYMSZ];
file.readFully(bytes);
ReadMemoryAccess memory = new ReadMemoryAccess(bytes, false); // big endian
memory.getBytes(_n_name);
n_value = memory.getInt();
n_scnum = memory.getShort();
n_type = memory.getShort();
n_sclass = memory.getByte();
n_numaux = memory.getByte();
aux = new byte[n_numaux * SYMSZ];
file.readFully(aux);
// 11th byte in the last auxiliary entry (csect)
x_smclas = (n_numaux > 0) ? aux[aux.length - 7] : 0;
}
private boolean isLongName() {
return (_n_name[0] == 0 &&
_n_name[1] == 0 &&
_n_name[2] == 0 &&
_n_name[3] == 0);
}
private String getShortName() {
for (int i = 0; i < _n_name.length; i++) {
if (_n_name[i] == 0) {
return new String(_n_name, 0, i);
}
}
return ""; //$NON-NLS-1$
}
public String getName(byte[] table) {
if (table.length > 0 && isLongName()) {
ReadMemoryAccess memory = new ReadMemoryAccess(_n_name, false);
memory.getInt(); // pass over the first 4 bytes.
// The first for bytes of the string table represent the
// number of bytes in the string table.
int offset = memory.getInt() - 4;
if (offset >= 0) {
for (int i = offset; i < table.length; i++) {
if (table[i] == 0) {
return new String(table, offset, i - offset);
}
}
}
}
return getShortName();
}
public boolean isFunction() {
return ((n_sclass == C_EXT || n_sclass == C_HIDEXT || n_sclass == C_WEAKEXT) &&
n_scnum == opthdr.o_sntext &&
!getShortName().equals(SectionHeader._TEXT));
}
public boolean isVariable() {
return ((n_sclass == C_EXT || n_sclass == C_HIDEXT || n_sclass == C_WEAKEXT) &&
(n_scnum == opthdr.o_snbss || n_scnum == opthdr.o_sndata) &&
x_smclas != XMC_TC0 && x_smclas != XMC_TC && x_smclas != XMC_DS &&
!getShortName().equals(SectionHeader._BSS) &&
!getShortName().equals(SectionHeader._DATA));
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("SYMBOL TABLE ENTRY").append(NL); //$NON-NLS-1$
buffer.append("n_value = ").append(n_value).append(NL); //$NON-NLS-1$
buffer.append("n_scnum = ").append(n_scnum).append(NL); //$NON-NLS-1$
buffer.append("n_type = ").append(n_type).append(NL); //$NON-NLS-1$
buffer.append("n_sclass = ").append(n_sclass).append(NL); //$NON-NLS-1$
buffer.append("n_numaux = ").append(n_numaux).append(NL); //$NON-NLS-1$
return buffer.toString();
}
}
public static class Attribute {
public static final int XCOFF_TYPE_EXE = 1;
public static final int XCOFF_TYPE_SHLIB = 2;
public static final int XCOFF_TYPE_OBJ = 3;
public static final int XCOFF_TYPE_CORE = 4;
String cpu;
int type;
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 Attribute getAttributes() {
Attribute attrib = new Attribute();
// Machine type.
switch (filehdr.f_magic) {
case FileHeader.U802TOCMAGIC:
attrib.cpu = "xcoff32"; //$NON-NLS-1$
break;
case FileHeader.U64_TOCMAGIC:
attrib.cpu = "xcoff64"; //$NON-NLS-1$
break;
default:
attrib.cpu = "unknown"; //$NON-NLS-1$
break;
}
/* XCOFF characteristics, FileHeader.f_flags. */
if ((filehdr.f_flags & FileHeader.F_SHROBJ) != 0) {
attrib.type = Attribute.XCOFF_TYPE_SHLIB;
} else if ((filehdr.f_flags & FileHeader.F_EXEC) != 0) {
attrib.type = Attribute.XCOFF_TYPE_EXE;
} else {
attrib.type = Attribute.XCOFF_TYPE_OBJ;
}
// For AIX XCOFF always assume big endian unless otherwise.
attrib.isle = false;
// No debug information.
if ((filehdr.f_flags & (FileHeader.F_LNNO & FileHeader.F_LSYMS & FileHeader.F_RELFLG)) != 0) {
attrib.bDebug = false;
} else {
attrib.bDebug = true;
}
return attrib;
}
public FileHeader getFileHeader() throws IOException {
return filehdr;
}
public OptionalHeader getOptionalHeader() throws IOException {
return opthdr;
}
public SectionHeader[] getSectionHeaders() throws IOException {
if (scnhdrs == null) {
getRandomAccessFile();
scnhdrs = new SectionHeader[getFileHeader().f_nscns];
long sec = startingOffset + FileHeader.FILHSZ + getFileHeader().f_opthdr;
for (int i = 0; i < scnhdrs.length; i++, sec += SectionHeader.SCNHSZ) {
scnhdrs[i] = new SectionHeader(rfile, sec);
}
}
return scnhdrs;
}
public Symbol[] getSymbols() throws IOException {
if (symbols == null) {
long offset = startingOffset + getFileHeader().f_symptr;
getRandomAccessFile();
rfile.seek(offset);
int numSymbols = getFileHeader().f_nsyms;
ArrayList symList = new ArrayList(numSymbols);
for (int i = 0; i < numSymbols; ++i) {
Symbol v = new Symbol(rfile);
symList.add(v);
i += v.n_numaux; // account for auxiliary entries
}
symbols = (Symbol[]) symList.toArray(new Symbol[symList.size()]);
}
return symbols;
}
public byte[] getStringTable() throws IOException {
if (string_table == null) {
if (filehdr.f_nsyms > 0) {
getRandomAccessFile();
long symbolsize = Symbol.SYMSZ * getFileHeader().f_nsyms;
long offset = startingOffset+ getFileHeader().f_symptr + symbolsize;
rfile.seek(offset);
byte[] bytes = new byte[4];
rfile.readFully(bytes);
int str_len = ReadMemoryAccess.getIntBE(bytes);
if (str_len > 4 && str_len < rfile.length()) {
str_len -= 4;
string_table = new byte[str_len];
rfile.seek(offset + 4);
rfile.readFully(string_table);
} else {
string_table = new byte[0];
}
}
}
return string_table;
}
// A hollow entry, to be used with caution in controlled situations
protected XCoff32() {
}
public XCoff32(String filename) throws IOException {
this(filename, 0);
}
public XCoff32(String filename, long offset) throws IOException {
this.filename = filename;
commonSetup(new RandomAccessFile(filename, "r"), offset);
}
void commonSetup(RandomAccessFile file, long offset) throws IOException {
startingOffset = offset;
rfile = file;
try {
filehdr = new FileHeader(rfile, startingOffset);
if (filehdr.f_opthdr > 0) {
opthdr = new OptionalHeader(rfile, startingOffset + FileHeader.FILHSZ);
}
if (filehdr.f_opthdr < OptionalHeader.AOUTHDRSZ) {
// auxiliary header does not contain needed information,
// must load section headers
getSectionHeaders();
for (int i = 0; i < filehdr.f_nscns; ++i) {
if ((scnhdrs[i].s_flags & SectionHeader.STYP_TEXT) != 0) {
opthdr.o_sntext = (short)(i+1);
}
else if ((scnhdrs[i].s_flags & SectionHeader.STYP_BSS) != 0) {
opthdr.o_snbss = (short)(i+1);
}
else if ((scnhdrs[i].s_flags & SectionHeader.STYP_DATA) != 0) {
opthdr.o_sndata = (short)(i+1);
}
}
}
} finally {
dispose();
}
}
public String toString() {
StringBuffer buffer = new StringBuffer();
try {
FileHeader header = null;
header = getFileHeader();
if (header != null) {
buffer.append(header);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
OptionalHeader opt = null;
opt = getOptionalHeader();
if (opt != null) {
buffer.append(opt);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
SectionHeader[] sections = getSectionHeaders();
for (int i = 0; i < sections.length; i++) {
buffer.append(sections[i]);
}
} catch (IOException e) {
}
try {
Symbol[] table = getSymbols();
for (int i = 0; i < table.length; i++) {
buffer.append(table[i]).append("n_name = "); //$NON-NLS-1$
buffer.append(table[i].getName(getStringTable())).append(NL);
}
} catch (IOException e) {
}
// try {
// String[] strings = getStringTable(getStringTable());
// for (int i = 0; i < strings.length; i++) {
// buffer.append(strings[i]);
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
return buffer.toString();
}
public void dispose() throws IOException {
if (rfile != null) {
rfile.close();
rfile = null;
}
}
RandomAccessFile getRandomAccessFile () throws IOException {
if (rfile == null) {
rfile = new RandomAccessFile(filename, "r"); //$NON-NLS-1$
}
return rfile;
}
public static void main(String[] args) {
try {
XCoff32 xcoff = new XCoff32(args[0]);
System.out.println(xcoff);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param hints
* @return
*/
public static boolean isXCOFF32Header(byte[] hints) {
if (hints != null && hints[0] == 0x01 && (hints[1] == (byte)0xdf) ) {
return true;
}
return false;
}
/**
* @param hints
* @return
* @throws IOException
*/
public static Attribute getAttributes(byte[] hints) throws IOException {
XCoff32 emptyXCoff = new XCoff32();
emptyXCoff.filehdr = new XCoff32.FileHeader(hints, false); // big endian
Attribute attribute = emptyXCoff.getAttributes();
emptyXCoff.dispose();
return attribute;
}
/**
* @param file
* @return
* @throws IOException
*/
public static Attribute getAttributes(String file) throws IOException {
XCoff32 xcoff = new XCoff32(file);
Attribute attribute = xcoff.getAttributes();
xcoff.dispose();
return attribute;
}
}

View file

@ -0,0 +1,111 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.utils.xcoff.parser;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.utils.Addr2line;
import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.cdt.utils.CygPath;
import org.eclipse.cdt.utils.Symbol;
import org.eclipse.cdt.utils.xcoff.AR;
import org.eclipse.cdt.utils.xcoff.XCoff32;
import org.eclipse.core.runtime.IPath;
/**
* A member of an XCOFF32 archive
*
* @author vhirsl
*/
public class ARMember extends XCOFFBinaryObject {
AR.MemberHeader header;
/**
* @param parser
* @param path
*/
public ARMember(IBinaryParser parser, IPath path, AR.MemberHeader header) {
super(parser, path);
this.header = header;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
InputStream stream = null;
if (path != null && header != null) {
try {
stream = new ByteArrayInputStream(header.getObjectData());
} catch (IOException e) {
}
}
if (stream == null) {
stream = super.getContents();
}
return stream;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getShortName()
*/
public String getName() {
if (header != null) {
return header.getObjectName();
}
return ""; //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.xcoff.parser.XCOFFBinaryObject#addSymbols(org.eclipse.cdt.utils.xcoff.XCoff32.Symbol[], byte[], org.eclipse.cdt.utils.Addr2line, org.eclipse.cdt.utils.CPPFilt, org.eclipse.cdt.utils.CygPath, java.util.List)
*/
protected void addSymbols(XCoff32.Symbol[] peSyms, byte[] table, Addr2line addr2line, CPPFilt cppfilt, CygPath cygpath, List list) {
for (int i = 0; i < peSyms.length; i++) {
if (peSyms[i].isFunction() || peSyms[i].isVariable()) {
String name = peSyms[i].getName(table);
if (name == null || name.trim().length() == 0 /*||
!Character.isJavaIdentifierStart(name.charAt(0))*/) {
continue;
}
Symbol sym = new Symbol(this);
sym.type = peSyms[i].isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE;
sym.addr = peSyms[i].n_value;
sym.name = name;
if (cppfilt != null) {
try {
sym.name = cppfilt.getFunction(sym.name);
} catch (IOException e1) {
cppfilt = null;
}
}
list.add(sym);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.xcoff.parser.XCOFFBinaryObject#getXCoff32()
*/
protected XCoff32 getXCoff32() throws IOException {
if (header != null) {
return header.getXCoff();
}
throw new IOException(CCorePlugin.getResourceString("Util.exception.noFileAssociation")); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,75 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.utils.xcoff.parser;
import java.io.IOException;
import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.utils.BinaryFile;
import org.eclipse.cdt.utils.xcoff.AR;
import org.eclipse.core.runtime.IPath;
/**
* XCOFF32 binary archive
*
* @author vhirsl
*/
public class BinaryArchive extends BinaryFile implements IBinaryArchive {
private ArrayList children;
/**
* @param parser
* @param path
* @throws IOException
*/
public BinaryArchive(IBinaryParser parser, IPath path) throws IOException {
super(parser, path);
new AR(path.toOSString()).dispose(); // check file type
children = new ArrayList(5);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.ARCHIVE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryArchive#getObjects()
*/
public IBinaryObject[] getObjects() {
if (hasChanged()) {
children.clear();
AR ar = null;
try {
ar = new AR(getPath().toOSString());
AR.MemberHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
IBinaryObject bin = new ARMember(getBinaryParser(), getPath(), headers[i]);
children.add(bin);
}
} catch (IOException e) {
//e.printStackTrace();
}
if (ar != null) {
ar.dispose();
}
children.trimToSize();
}
return (IBinaryObject[]) children.toArray(new IBinaryObject[0]);
}
}

View file

@ -0,0 +1,171 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.utils.xcoff.parser;
import java.io.EOFException;
import java.io.IOException;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.utils.ToolsProvider;
import org.eclipse.cdt.utils.xcoff.AR;
import org.eclipse.cdt.utils.xcoff.XCoff32;
import org.eclipse.core.runtime.IPath;
/**
* XCOFF 32bit binary parser for AIX
*
* @author vhirsl
*/
public class XCOFF32Parser extends ToolsProvider implements IBinaryParser {
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBinary(byte[], org.eclipse.core.runtime.IPath)
*/
public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
if (path == null) {
throw new IOException(CCorePlugin.getResourceString("Util.exception.nullPath")); //$NON-NLS-1$
}
IBinaryFile binary = null;
if (isBinary(hints, path)) {
try {
XCoff32.Attribute attribute = null;
if (hints != null && hints.length > 0) {
try {
attribute = XCoff32.getAttributes(hints);
} catch (EOFException eof) {
// continue, the array was to small.
}
}
//Take a second run at it if the data array failed.
if(attribute == null) {
attribute = XCoff32.getAttributes(path.toOSString());
}
if (attribute != null) {
switch (attribute.getType()) {
case XCoff32.Attribute.XCOFF_TYPE_EXE :
binary = createBinaryExecutable(path);
break;
case XCoff32.Attribute.XCOFF_TYPE_SHLIB :
binary = createBinaryShared(path);
break;
case XCoff32.Attribute.XCOFF_TYPE_OBJ :
binary = createBinaryObject(path);
break;
case XCoff32.Attribute.XCOFF_TYPE_CORE :
binary = createBinaryCore(path);
break;
}
}
} catch (IOException e) {
binary = createBinaryArchive(path);
}
}
return binary;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
return getBinary(null, path);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getFormat()
*/
public String getFormat() {
return "XCOFF32"; //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath)
*/
public boolean isBinary(byte[] hints, IPath path) {
return XCoff32.isXCOFF32Header(hints) || AR.isARHeader(hints);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getHintBufferSize()
*/
public int getHintBufferSize() {
return 512;
}
/**
* @param path
* @return
*/
private IBinaryFile createBinaryExecutable(IPath path) {
return new XCOFFBinaryObject(this, path) {
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.EXECUTABLE;
}
};
}
/**
* @param path
* @return
*/
private IBinaryFile createBinaryShared(IPath path) {
return new XCOFFBinaryObject(this, path) {
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.SHARED;
}
};
}
/**
* @param path
* @return
*/
private IBinaryFile createBinaryObject(IPath path) {
return new XCOFFBinaryObject(this, path);
}
/**
* @param path
* @return
*/
private IBinaryFile createBinaryCore(IPath path) {
return new XCOFFBinaryObject(this, path) {
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.CORE;
}
};
}
/**
* @param path
* @return
* @throws IOException
*/
private IBinaryFile createBinaryArchive(IPath path) throws IOException {
return new BinaryArchive(this, path);
}
}

View file

@ -0,0 +1,221 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.utils.xcoff.parser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.utils.Addr2line;
import org.eclipse.cdt.utils.BinaryObjectAdapter;
import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.cdt.utils.CygPath;
import org.eclipse.cdt.utils.Objdump;
import org.eclipse.cdt.utils.Symbol;
import org.eclipse.cdt.utils.xcoff.XCoff32;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* TODO Provide description
*
* @author vhirsl
*/
public class XCOFFBinaryObject extends BinaryObjectAdapter {
BinaryObjectInfo info;
ISymbol[] symbols;
/**
* @param parser
* @param path
*/
public XCOFFBinaryObject(IBinaryParser parser, IPath path) {
super(parser, path);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbols()
*/
public ISymbol[] getSymbols() {
if (hasChanged() || symbols == null) {
try {
loadAll();
} catch (IOException e) {
symbols = NO_SYMBOLS;
}
}
return symbols;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.BinaryObjectAdapter#getBinaryObjectInfo()
*/
protected BinaryObjectInfo getBinaryObjectInfo() {
if (hasChanged() || info == null) {
try {
loadInfo();
} catch (IOException e) {
info = new BinaryObjectInfo();
}
}
return info;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.OBJECT;
}
protected XCoff32 getXCoff32() throws IOException {
return new XCoff32(getPath().toOSString());
}
protected void loadAll() throws IOException {
XCoff32 xcoff = null;
try {
xcoff = getXCoff32();
loadInfo(xcoff);
loadSymbols(xcoff);
} finally {
if (xcoff != null) {
xcoff.dispose();
}
}
}
protected void loadInfo() throws IOException {
XCoff32 xcoff = null;
try {
xcoff = getXCoff32();
loadInfo(xcoff);
} finally {
if (xcoff != null) {
xcoff.dispose();
}
}
}
protected void loadInfo(XCoff32 xcoff) throws IOException {
info = new BinaryObjectInfo();
XCoff32.Attribute attribute = xcoff.getAttributes();
info.isLittleEndian = attribute.isLittleEndian();
info.hasDebug = attribute.hasDebug();
info.cpu = attribute.getCPU();
}
protected void loadSymbols(XCoff32 xcoff) throws IOException {
ArrayList list = new ArrayList();
Addr2line addr2line = getAddr2line();
CPPFilt cppfilt = getCPPFilt();
CygPath cygpath = getCygPath();
XCoff32.Symbol[] peSyms = xcoff.getSymbols();
byte[] table = xcoff.getStringTable();
addSymbols(peSyms, table, addr2line, cppfilt, cygpath, list);
if (addr2line != null) {
addr2line.dispose();
}
if (cppfilt != null) {
cppfilt.dispose();
}
if (cygpath != null) {
cygpath.dispose();
}
symbols = (ISymbol[])list.toArray(NO_SYMBOLS);
Arrays.sort(symbols);
list.clear();
}
protected void addSymbols(XCoff32.Symbol[] peSyms, byte[] table, Addr2line addr2line, CPPFilt cppfilt, CygPath cygpath, List list) {
for (int i = 0; i < peSyms.length; i++) {
if (peSyms[i].isFunction() || peSyms[i].isVariable()) {
String name = peSyms[i].getName(table);
if (name == null || name.trim().length() == 0 /*||
!Character.isJavaIdentifierStart(name.charAt(0))*/) {
continue;
}
Symbol sym = new Symbol(this);
sym.type = peSyms[i].isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE;
sym.addr = peSyms[i].n_value;
sym.name = name;
if (cppfilt != null) {
try {
sym.name = cppfilt.getFunction(sym.name);
} catch (IOException e1) {
cppfilt = null;
}
}
sym.filename = null;
sym.startLine = 0;
sym.endLine = 0;
if (addr2line != null) {
try {
String filename = addr2line.getFileName(sym.addr);
// Addr2line returns the funny "??" when it can not find the file.
if (filename != null && filename.equals("??")) { //$NON-NLS-1$
filename = null;
}
if (filename != null) {
if (cygpath != null) {
sym.filename = new Path(cygpath.getFileName(filename));
} else {
sym.filename = new Path(filename);
}
}
sym.startLine = addr2line.getLineNumber(sym.addr);
} catch (IOException e) {
addr2line = null;
}
}
list.add(sym);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.BinaryObjectAdapter#getAddr2line()
*/
public Addr2line getAddr2line() {
XCOFF32Parser parser = (XCOFF32Parser)getBinaryParser();
return parser.getAddr2line(getPath());
}
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.BinaryObjectAdapter#getCPPFilt()
*/
public CPPFilt getCPPFilt() {
XCOFF32Parser parser = (XCOFF32Parser)getBinaryParser();
return parser.getCPPFilt();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.BinaryObjectAdapter#getObjdump()
*/
public Objdump getObjdump() {
XCOFF32Parser parser = (XCOFF32Parser)getBinaryParser();
return parser.getObjdump(getPath());
}
private CygPath getCygPath() {
return null;
}
}

View file

@ -1,3 +1,9 @@
2004-06-21 Alain Magloire
Big Patch from Vladimir Hirsl
This patch contains a binary parser core and UI elements to 'support' AIX
XCOFF32 binaries.
2004-06-21 Hoda Amer
Fix for PR 63439 : [Content Assist] When prefix is a C/C++ keyword, Content Assist does not complete templates

View file

@ -698,6 +698,11 @@
parserID="org.eclipse.cdt.core.Cygwin_PE"
id="PEBinaryParserPage">
</parserPage>
<parserPage
class="org.eclipse.cdt.ui.dialogs.GNUXCoffBinaryParserPage"
parserID="org.eclipse.cdt.core.XCOFF32"
id="XcoffBinaryParserPage">
</parserPage>
</extension>
<extension
point="org.eclipse.ui.workingSets">

View file

@ -75,7 +75,7 @@ public class GNUElfBinaryParserPage extends AbstractCOptionPage {
for (int i = 0; i < infos.length; i++) {
String id = infos[i].getAttribute("parserID"); //$NON-NLS-1$
String clazz = infos[i].getAttribute("class"); //$NON-NLS-1$
String ego = getClass().getName();
String ego = getRealBinaryParserPage().getClass().getName();
if (clazz != null && clazz.equals(ego)) {
parserID = id;
break;
@ -104,6 +104,14 @@ public class GNUElfBinaryParserPage extends AbstractCOptionPage {
}
}
/**
* If this class is inherited from then this method MUST be implemented
* in the derived class.
*/
protected Object getRealBinaryParserPage() {
return this;
}
/*
* (non-Javadoc)
*

View file

@ -0,0 +1,28 @@
/**********************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.ui.dialogs;
/**
* Reusing GNUElfBinaryParserPage.
* New class is required for the algorithm in method performApply.
* Must implement getRealBinaryParserPage method.
*
* @author vhirsl
*/
public class GNUXCoffBinaryParserPage extends GNUElfBinaryParserPage {
/* (non-Javadoc)
* @see org.eclipse.cdt.ui.dialogs.GNUElfBinaryParserPage#getRealBinaryParserPage()
*/
protected Object getRealBinaryParserPage() {
return this;
}
}