mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-31 21:05:37 +02:00
New file
This commit is contained in:
parent
98fa05101a
commit
af142b433e
1 changed files with 315 additions and 0 deletions
|
@ -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 <code>AR</code> 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 <code>ARHeader</code> 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 <code>rfile</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 = 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 "/<number>", 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 <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 PEArchive(String filename) throws IOException {
|
||||
this.filename = filename;
|
||||
rfile = new RandomAccessFile(filename, "r");
|
||||
String hdr = rfile.readLine();
|
||||
if (hdr == null || hdr.compareTo("!<arch>") != 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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue