1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-26 02:15:31 +02:00

faster IArchive

This commit is contained in:
David Inglis 2003-02-26 21:01:28 +00:00
parent 7f7de54b77
commit 6940e686c7
6 changed files with 304 additions and 356 deletions

View file

@ -1,3 +1,14 @@
2003-02-26 David Inglis
* model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java
* model/org/eclipse/cdt/internal/core/model/BinaryContainer.java
Remove warning.
* model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryArchive.java
* model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryFile.java
* utils/org/eclipse/cdt/utils/elf/AR.java
Improve IBinaryObject creation from IArchive (big speed improvment)
2003-02-24 Alain Magloire
* model/org/eclipse/cdt/internal/core/model/Marker.java:

View file

@ -15,8 +15,7 @@ import org.eclipse.core.resources.IProject;
public class ArchiveContainer extends Parent implements IArchiveContainer {
CProject cProject;
private long modificationStamp;
public ArchiveContainer (CProject cProject) {
super (cProject, null, "lib", CElement.C_CONTAINER);
this.cProject = cProject;

View file

@ -19,7 +19,6 @@ import org.eclipse.core.runtime.CoreException;
public class BinaryContainer extends Parent implements IBinaryContainer {
CProject cProject;
private long modificationStamp;
public BinaryContainer (CProject cProject) {
this (cProject, "bin");

View file

@ -45,7 +45,7 @@ public class ElfBinaryArchive extends PlatformObject implements IBinaryArchive {
ar = new AR(location.toOSString());
AR.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
IBinaryObject bin = new ElfBinaryFile(file, headers[i].getObjectName());
IBinaryObject bin = new ElfBinaryFile(file, headers[i]);
children.add(bin);
}
} catch (IOException e) {

View file

@ -4,7 +4,7 @@ package org.eclipse.cdt.internal.core.model.parser;
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@ -28,25 +28,23 @@ import org.eclipse.core.runtime.PlatformObject;
/**
*/
public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
IBinaryObject, IBinaryExecutable, IBinaryShared {
public class ElfBinaryFile extends PlatformObject implements IBinaryFile, IBinaryObject, IBinaryExecutable, IBinaryShared {
IFile file;
String objectName;
AR.ARHeader header;
long timestamp;
String soname;
String[] needed;
Sizes sizes;
Attribute attribute;
ArrayList symbols;
public ElfBinaryFile(IFile f) throws IOException {
this(f, null);
}
public ElfBinaryFile(IFile f, String n) throws IOException {
public ElfBinaryFile(IFile f, AR.ARHeader h) throws IOException {
header = h;
file = f;
objectName = n;
loadInformation();
hasChanged();
}
@ -55,7 +53,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/
public IFile getFile() {
return file;
return file;
}
/**
@ -155,7 +153,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
}
return new String[0];
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
*/
@ -164,21 +162,21 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
Attribute attr = getAttribute();
if (attr != null) {
switch (attribute.getType()) {
case Attribute.ELF_TYPE_EXE:
case Attribute.ELF_TYPE_EXE :
type = IBinaryFile.EXECUTABLE;
break;
break;
case Attribute.ELF_TYPE_SHLIB:
case Attribute.ELF_TYPE_SHLIB :
type = IBinaryFile.SHARED;
break;
break;
case Attribute.ELF_TYPE_OBJ:
case Attribute.ELF_TYPE_OBJ :
type = IBinaryFile.OBJECT;
break;
case Attribute.ELF_TYPE_CORE:
break;
case Attribute.ELF_TYPE_CORE :
type = IBinaryFile.CORE;
break;
break;
}
}
return type;
@ -197,7 +195,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
} catch (IOException e) {
}
}
return (ISymbol[])symbols.toArray(new ISymbol[0]);
return (ISymbol[]) symbols.toArray(new ISymbol[0]);
}
/**
@ -206,24 +204,10 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
public InputStream getContents() {
InputStream stream = null;
// Archive ?
if (file != null && objectName != null) {
IPath location = file.getLocation();
if (location != null) {
AR ar = null;
try {
ar = new AR(file.getLocation().toOSString());
AR.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
if (objectName.equals(headers[i].getObjectName())) {
stream = new ByteArrayInputStream(headers[i].getObjectData());
break;
}
}
} catch (IOException e) {
}
if (ar != null) {
ar.dispose();
}
if (file != null && header != null) {
try {
stream = new ByteArrayInputStream(header.getObjectData());
} catch (IOException e) {
}
} else if (file != null && file.exists()) {
try {
@ -241,8 +225,8 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName()
*/
public String getName() {
if (objectName != null) {
return objectName;
if (header != null) {
return header.getObjectName();
}
if (file != null) {
return file.getName();
@ -273,7 +257,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
}
return sizes;
}
boolean hasChanged() {
long modification = file.getModificationStamp();
boolean changed = modification != timestamp;
@ -283,30 +267,8 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
protected ElfHelper getElfHelper() throws IOException {
// Archive ?
if (file != null && objectName != null) {
IPath location = file.getLocation();
if (location != null) {
ElfHelper helper = null;
AR ar = null;
try {
ar = new AR(file.getLocation().toOSString());
AR.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
AR.ARHeader hdr = headers[i];
if (objectName.equals(hdr.getObjectName())) {
helper = new ElfHelper(hdr.getElf());
break;
}
}
} finally {
if (ar != null) {
ar.dispose();
}
}
if (helper != null) {
return helper;
}
}
if (header != null) {
return new ElfHelper(header.getElf());
} else if (file != null && file.exists()) {
IPath path = file.getLocation();
if (path == null) {
@ -331,7 +293,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
symbols.trimToSize();
}
}
private void loadAttributes(ElfHelper helper) throws IOException {
Elf.Dynamic[] sharedlibs = helper.getNeeded();
needed = new String[sharedlibs.length];
@ -368,8 +330,10 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
try {
// This can fail if we use addr2line
// but we can safely ignore the error.
sym.filename = array[i].getFilename();
sym.lineno = array[i].getFuncLineNumber();
if (header == null) {
sym.filename = array[i].getFilename();
sym.lineno = array[i].getFuncLineNumber();
}
} catch (IOException e) {
//e.printStackTrace();
}

View file

@ -10,7 +10,6 @@ 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.
*
@ -21,326 +20,302 @@ import java.util.Vector;
*/
public class AR {
protected String filename;
protected ERandomAccessFile efile;
protected long strtbl_pos = -1;
private ARHeader[] headers;
protected String filename;
protected ERandomAccessFile efile;
protected long strtbl_pos = -1;
private ARHeader[] headers;
public void dispose() {
try {
if (efile != null) {
efile.close();
efile = null;
}
} catch (IOException e) {
}
}
public void dispose() {
try
{
if (efile != null)
{
efile.close();
efile = null;
}
}
catch( IOException e )
{}
}
protected void finalize() throws Throwable {
try {
dispose();
} finally {
super.finalize();
}
}
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 Elf object for inspecting
* the object file data.
*/
public class ARHeader {
/**
* The <code>ARHeader</code> class is used to store the per-object file
* archive headers. It can also create an Elf 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;
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>efile</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 = efile.getFilePointer();
/**
* 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;
}
try {
if (strtbl_pos != -1) {
byte temp;
efile.seek(strtbl_pos + offset);
while ((temp = efile.readByte()) != '\n')
name.append((char) temp);
}
} finally {
efile.seek(pos);
}
return name.toString();
}
/**
* Look up the name stored in the archive's string table based
* on the offset given.
*
* Maintains <code>efile</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 = efile.getFilePointer();
/**
* Creates a new archive header object.
*
* Assumes that efile 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];
try
{
if( strtbl_pos != -1 )
{
byte temp;
efile.seek( strtbl_pos + offset );
while( ( temp = efile.readByte() ) != '\n' )
name.append( (char)temp );
}
}
finally
{
efile.seek( pos );
}
//
// Read in the archive header data. Fixed sizes.
//
efile.read(object_name);
efile.read(modification_time);
efile.read(uid);
efile.read(gid);
efile.read(mode);
efile.read(size);
efile.read(trailer);
return name.toString();
}
//
// Save this location so we can create the Elf object later.
//
elf_offset = efile.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)));
/**
* Creates a new archive header object.
*
* Assumes that efile 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];
//
// 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) {
}
}
//
// Read in the archive header data. Fixed sizes.
//
efile.read( object_name );
efile.read( modification_time );
efile.read( uid );
efile.read( gid );
efile.read( mode );
efile.read( size );
efile.read( trailer );
//
// 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);
}
//
// Save this location so we can create the Elf object later.
//
elf_offset = efile.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 ) ) );
/** Get the name of the object file */
public String getObjectName() {
return object_name;
}
//
// 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 )
{
}
}
/** Get the size of the object file . */
public long getSize() {
return size;
}
public String getArchiveName() {
return filename;
}
//
// 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 );
}
/**
* Create an new Elf object for the object file.
*
* @throws IOException
* Not a valid Elf object file.
* @return A new Elf object.
* @see Elf#Elf( String, long )
*/
public Elf getElf() throws IOException {
return new Elf(filename, elf_offset);
}
}
public Elf getElf(boolean filter_on) throws IOException {
return new Elf(filename, elf_offset, filter_on);
}
/** Get the name of the object file */
public String getObjectName() {
return object_name;
}
public byte[] getObjectData() throws IOException {
byte[] temp = new byte[(int) size];
if (efile != null) {
efile.seek(elf_offset);
efile.read(temp);
} else {
efile = new ERandomAccessFile(filename, "r");
efile.seek(elf_offset);
efile.read(temp);
efile.close();
efile = null;
}
return temp;
}
}
/** Get the size of the object file . */
public long getSize() {
return size;
}
/**
* 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;
efile = new ERandomAccessFile(filename, "r");
String hdr = efile.readLine();
if (hdr == null || hdr.compareTo("!<arch>") != 0) {
efile.close();
throw new IOException("Not a valid archive file.");
}
}
/**
* Create an new Elf object for the object file.
*
* @throws IOException
* Not a valid Elf object file.
* @return A new Elf object.
* @see Elf#Elf( String, long )
*/
public Elf getElf() throws IOException {
return new Elf( filename, elf_offset );
}
/** Load the headers from the file (if required). */
private void loadHeaders() throws IOException {
if (headers != null)
return;
public Elf getElf( boolean filter_on ) throws IOException {
return new Elf( filename, elf_offset, filter_on );
}
Vector v = new Vector();
try {
//
// Check for EOF condition
//
while (efile.getFilePointer() < efile.length()) {
ARHeader header = new ARHeader();
String name = header.getObjectName();
public byte[] getObjectData() throws IOException {
byte[] temp = new byte[(int)size];
efile.seek( elf_offset );
efile.read( temp );
return temp;
}
}
long pos = efile.getFilePointer();
//
// If the name starts with a / it is specical.
//
if (name.charAt(0) != '/')
v.add(header);
/**
* 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;
efile = new ERandomAccessFile( filename, "r" );
String hdr = efile.readLine();
if( hdr == null || hdr.compareTo( "!<arch>" ) != 0 ) {
efile.close();
throw new IOException( "Not a valid archive file." );
}
}
//
// 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++;
/** Load the headers from the file (if required). */
private void loadHeaders() throws IOException {
if( headers != null )
return;
efile.seek(pos);
}
} catch (IOException e) {
}
headers = (ARHeader[]) v.toArray(new ARHeader[0]);
}
Vector v = new Vector();
try
{
//
// Check for EOF condition
//
while( efile.getFilePointer() < efile.length() )
{
ARHeader header = new ARHeader();
String name = header.getObjectName();
/**
* 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;
}
long pos = efile.getFilePointer();
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;
}
//
// If the name starts with a / it is specical.
//
if( name.charAt( 0 ) != '/' )
v.add( header );
public String[] extractFiles(String outdir, String[] names) throws IOException {
Vector names_used = new Vector();
String object_name;
int count;
//
// If the name is "//" then this is the string table section.
//
if( name.compareTo( "//" ) == 0 )
strtbl_pos = pos;
loadHeaders();
count = 0;
for (int i = 0; i < headers.length; i++) {
object_name = headers[i].getObjectName();
if (names != null && !stringInStrings(object_name, names))
continue;
//
// Compute the location of the next header in the archive.
//
pos += header.getSize();
if( ( pos % 2 ) != 0 )
pos++;
object_name = "" + count + "_" + object_name;
count++;
efile.seek( pos );
}
}
catch( IOException e )
{
}
headers = (ARHeader[])v.toArray( new ARHeader[0] );
}
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();
}
/**
* 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 );
}
return (String[]) names_used.toArray(new String[0]);
}
public String[] extractFiles(String outdir) throws IOException {
return extractFiles(outdir, null);
}
}