diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java
new file mode 100644
index 00000000000..37b1e21bb99
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java
@@ -0,0 +1,315 @@
+package org.eclipse.cdt.utils.coff;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Vector;
+
+/**
+ * The AR
class is used for parsing standard ELF 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 PE object for performing PE
+ * class operations.
+ * @see ARHeader
+ */
+public class PEArchive {
+
+ protected String filename;
+ protected RandomAccessFile rfile;
+ protected long strtbl_pos = -1;
+ private ARHeader[] headers;
+
+ public void dispose() {
+ try {
+ if (rfile != null) {
+ rfile.close();
+ rfile = null;
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Do not leak fds.
+ */
+ protected void finalize() throws Throwable {
+ try {
+ dispose();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * The ARHeader
class is used to store the per-object file
+ * archive headers. It can also create an PE object for inspecting
+ * the object file data.
+ */
+ public class ARHeader {
+
+ private String object_name;
+ private String modification_time;
+ private String uid;
+ private String gid;
+ private String mode;
+ private long size;
+ private long elf_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 rfile
file location.
+ *
+ * @param offset
+ * Offset into the string table for first character of the name.
+ * @throws IOException
+ * offset
not in string table bounds.
+ */
+ private String nameFromStringTable(long offset) throws IOException {
+ StringBuffer name = new StringBuffer(0);
+ long pos = rfile.getFilePointer();
+
+ try {
+ if (strtbl_pos != -1) {
+ byte temp;
+ rfile.seek(strtbl_pos + offset);
+ while ((temp = rfile.readByte()) != '\n')
+ name.append((char) temp);
+ }
+ } finally {
+ rfile.seek(pos);
+ }
+
+ return name.toString();
+ }
+
+ /**
+ * Creates a new archive header object.
+ *
+ * Assumes that rfile is already at the correct location in the file.
+ *
+ * @throws IOException
+ * There was an error processing the header data from the file.
+ */
+ public ARHeader() throws IOException {
+ byte[] object_name = new byte[16];
+ byte[] modification_time = new byte[12];
+ byte[] uid = new byte[6];
+ byte[] gid = new byte[6];
+ byte[] mode = new byte[8];
+ byte[] size = new byte[10];
+ byte[] trailer = new byte[2];
+
+ //
+ // Read in the archive header data. Fixed sizes.
+ //
+ rfile.read(object_name);
+ rfile.read(modification_time);
+ rfile.read(uid);
+ rfile.read(gid);
+ rfile.read(mode);
+ rfile.read(size);
+ rfile.read(trailer);
+
+ //
+ // Save this location so we can create the PE object later.
+ //
+ elf_offset = rfile.getFilePointer();
+
+ //
+ // Convert the raw bytes into strings and numbers.
+ //
+ this.object_name = removeBlanks(new String(object_name));
+ this.modification_time = new String(modification_time);
+ this.uid = new String(uid);
+ this.gid = new String(gid);
+ this.mode = new String(mode);
+ this.size = Long.parseLong(removeBlanks(new String(size)));
+
+ //
+ // If the name is of the format "/", get name from the
+ // string table.
+ //
+ if (strtbl_pos != -1
+ && this.object_name.length() > 1
+ && this.object_name.charAt(0) == '/') {
+ try {
+ long offset = Long.parseLong(this.object_name.substring(1));
+ this.object_name = nameFromStringTable(offset);
+ } catch (java.lang.Exception e) {
+ }
+ }
+
+ //
+ // Strip the trailing / from the object name.
+ //
+ int len = this.object_name.length();
+ if (len > 2 && this.object_name.charAt(len - 1) == '/') {
+ this.object_name = this.object_name.substring(0, len - 1);
+ }
+
+ }
+
+ /** Get the name of the object file */
+ public String getObjectName() {
+ return object_name;
+ }
+
+ /** Get the size of the object file . */
+ public long getSize() {
+ return size;
+ }
+
+ /**
+ * Create an new PE object for the object file.
+ *
+ * @throws IOException
+ * Not a valid PE object file.
+ * @return A new PE object.
+ * @see PE#PE( String, long )
+ */
+ public PE getPE() throws IOException {
+ return new PE(filename, elf_offset);
+ }
+
+ public PE getPE(boolean filter_on) throws IOException {
+ return new PE(filename, elf_offset, filter_on);
+ }
+
+ public byte[] getObjectData() throws IOException {
+ byte[] temp = new byte[(int) size];
+ rfile.seek(elf_offset);
+ rfile.read(temp);
+ return temp;
+ }
+ }
+
+ /**
+ * Creates a new AR
object from the contents of
+ * the given file.
+ *
+ * @param filename The file to process.
+ * @throws IOException The file is not a valid archive.
+ */
+ public PEArchive(String filename) throws IOException {
+ this.filename = filename;
+ rfile = new RandomAccessFile(filename, "r");
+ String hdr = rfile.readLine();
+ if (hdr == null || hdr.compareTo("!") != 0) {
+ rfile.close();
+ throw new IOException("Not a valid archive file.");
+ }
+ }
+
+ /** Load the headers from the file (if required). */
+ private void loadHeaders() throws IOException {
+ if (headers != null)
+ return;
+
+ Vector v = new Vector();
+ try {
+ //
+ // Check for EOF condition
+ //
+ while (rfile.getFilePointer() < rfile.length()) {
+ ARHeader header = new ARHeader();
+ String name = header.getObjectName();
+
+ long pos = rfile.getFilePointer();
+
+ //
+ // If the name starts with a / it is specical.
+ //
+ if (name.charAt(0) != '/')
+ v.add(header);
+
+ //
+ // If the name is "//" then this is the string table section.
+ //
+ if (name.compareTo("//") == 0)
+ strtbl_pos = pos;
+
+ //
+ // Compute the location of the next header in the archive.
+ //
+ pos += header.getSize();
+ if ((pos % 2) != 0)
+ pos++;
+
+ rfile.seek(pos);
+ }
+ } catch (IOException e) {
+ }
+ headers = (ARHeader[]) v.toArray(new ARHeader[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 ARHeader[] getHeaders() throws IOException {
+ loadHeaders();
+ return headers;
+ }
+
+ 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;
+ }
+
+ 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 < headers.length; i++) {
+ object_name = headers[i].getObjectName();
+ if (names != null && !stringInStrings(object_name, names))
+ continue;
+
+ object_name = "" + count + "_" + object_name;
+ count++;
+
+ byte[] data = headers[i].getObjectData();
+ File output = new File(outdir, object_name);
+ names_used.add(object_name);
+
+ RandomAccessFile rfile = new RandomAccessFile(output, "rw");
+ rfile.write(data);
+ rfile.close();
+ }
+
+ return (String[]) names_used.toArray(new String[0]);
+ }
+
+ public String[] extractFiles(String outdir) throws IOException {
+ return extractFiles(outdir, null);
+ }
+
+}