1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-29 03:45:35 +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 2003-02-24 Alain Magloire
* model/org/eclipse/cdt/internal/core/model/Marker.java: * model/org/eclipse/cdt/internal/core/model/Marker.java:

View file

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

View file

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

View file

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

View file

@ -28,11 +28,9 @@ import org.eclipse.core.runtime.PlatformObject;
/** /**
*/ */
public class ElfBinaryFile extends PlatformObject implements IBinaryFile, public class ElfBinaryFile extends PlatformObject implements IBinaryFile, IBinaryObject, IBinaryExecutable, IBinaryShared {
IBinaryObject, IBinaryExecutable, IBinaryShared {
IFile file; IFile file;
String objectName; AR.ARHeader header;
long timestamp; long timestamp;
String soname; String soname;
String[] needed; String[] needed;
@ -44,9 +42,9 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
this(f, null); this(f, null);
} }
public ElfBinaryFile(IFile f, String n) throws IOException { public ElfBinaryFile(IFile f, AR.ARHeader h) throws IOException {
header = h;
file = f; file = f;
objectName = n;
loadInformation(); loadInformation();
hasChanged(); hasChanged();
} }
@ -55,7 +53,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile() * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/ */
public IFile getFile() { public IFile getFile() {
return file; return file;
} }
/** /**
@ -164,21 +162,21 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
Attribute attr = getAttribute(); Attribute attr = getAttribute();
if (attr != null) { if (attr != null) {
switch (attribute.getType()) { switch (attribute.getType()) {
case Attribute.ELF_TYPE_EXE: case Attribute.ELF_TYPE_EXE :
type = IBinaryFile.EXECUTABLE; type = IBinaryFile.EXECUTABLE;
break; break;
case Attribute.ELF_TYPE_SHLIB: case Attribute.ELF_TYPE_SHLIB :
type = IBinaryFile.SHARED; type = IBinaryFile.SHARED;
break; break;
case Attribute.ELF_TYPE_OBJ: case Attribute.ELF_TYPE_OBJ :
type = IBinaryFile.OBJECT; type = IBinaryFile.OBJECT;
break; break;
case Attribute.ELF_TYPE_CORE: case Attribute.ELF_TYPE_CORE :
type = IBinaryFile.CORE; type = IBinaryFile.CORE;
break; break;
} }
} }
return type; return type;
@ -197,7 +195,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
} catch (IOException e) { } 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() { public InputStream getContents() {
InputStream stream = null; InputStream stream = null;
// Archive ? // Archive ?
if (file != null && objectName != null) { if (file != null && header != null) {
IPath location = file.getLocation(); try {
if (location != null) { stream = new ByteArrayInputStream(header.getObjectData());
AR ar = null; } catch (IOException e) {
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();
}
} }
} else if (file != null && file.exists()) { } else if (file != null && file.exists()) {
try { try {
@ -241,8 +225,8 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName() * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName()
*/ */
public String getName() { public String getName() {
if (objectName != null) { if (header != null) {
return objectName; return header.getObjectName();
} }
if (file != null) { if (file != null) {
return file.getName(); return file.getName();
@ -283,30 +267,8 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
protected ElfHelper getElfHelper() throws IOException { protected ElfHelper getElfHelper() throws IOException {
// Archive ? // Archive ?
if (file != null && objectName != null) { if (header != null) {
IPath location = file.getLocation(); return new ElfHelper(header.getElf());
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;
}
}
} else if (file != null && file.exists()) { } else if (file != null && file.exists()) {
IPath path = file.getLocation(); IPath path = file.getLocation();
if (path == null) { if (path == null) {
@ -368,8 +330,10 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
try { try {
// This can fail if we use addr2line // This can fail if we use addr2line
// but we can safely ignore the error. // but we can safely ignore the error.
sym.filename = array[i].getFilename(); if (header == null) {
sym.lineno = array[i].getFuncLineNumber(); sym.filename = array[i].getFilename();
sym.lineno = array[i].getFuncLineNumber();
}
} catch (IOException e) { } catch (IOException e) {
//e.printStackTrace(); //e.printStackTrace();
} }

View file

@ -10,7 +10,6 @@ import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.util.Vector; import java.util.Vector;
/** /**
* The <code>AR</code> class is used for parsing standard ELF archive (ar) files. * 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 { public class AR {
protected String filename; protected String filename;
protected ERandomAccessFile efile; protected ERandomAccessFile efile;
protected long strtbl_pos = -1; protected long strtbl_pos = -1;
private ARHeader[] headers; private ARHeader[] headers;
public void dispose() {
try {
if (efile != null) {
efile.close();
efile = null;
}
} catch (IOException e) {
}
}
public void dispose() { protected void finalize() throws Throwable {
try try {
{ dispose();
if (efile != null) } finally {
{ super.finalize();
efile.close(); }
efile = null; }
}
}
catch( IOException e )
{}
}
protected void finalize() throws Throwable { /**
try * The <code>ARHeader</code> class is used to store the per-object file
{ * archive headers. It can also create an Elf object for inspecting
dispose(); * the object file data.
} */
finally public class ARHeader {
{
super.finalize();
}
}
/** private String object_name;
* The <code>ARHeader</code> class is used to store the per-object file private String modification_time;
* archive headers. It can also create an Elf object for inspecting private String uid;
* the object file data. private String gid;
*/ private String mode;
public class ARHeader { private long size;
private long elf_offset;
private String object_name; /**
private String modification_time; * Remove the padding from the archive header strings.
private String uid; */
private String gid; private String removeBlanks(String str) {
private String mode; while (str.charAt(str.length() - 1) == ' ')
private long size; str = str.substring(0, str.length() - 1);
private long elf_offset; 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();
/** try {
* Remove the padding from the archive header strings. if (strtbl_pos != -1) {
*/ byte temp;
private String removeBlanks( String str ) { efile.seek(strtbl_pos + offset);
while( str.charAt( str.length() - 1 ) == ' ' ) while ((temp = efile.readByte()) != '\n')
str = str.substring( 0, str.length() - 1 ); name.append((char) temp);
return str; }
} } finally {
efile.seek(pos);
}
return name.toString();
}
/** /**
* Look up the name stored in the archive's string table based * Creates a new archive header object.
* on the offset given. *
* * Assumes that efile is already at the correct location in the file.
* Maintains <code>efile</code> file location. *
* * @throws IOException
* @param offset * There was an error processing the header data from the file.
* Offset into the string table for first character of the name. */
* @throws IOException public ARHeader() throws IOException {
* <code>offset</code> not in string table bounds. byte[] object_name = new byte[16];
*/ byte[] modification_time = new byte[12];
private String nameFromStringTable( long offset ) throws IOException { byte[] uid = new byte[6];
StringBuffer name = new StringBuffer( 0 ); byte[] gid = new byte[6];
long pos = efile.getFilePointer(); byte[] mode = new byte[8];
byte[] size = new byte[10];
byte[] trailer = new byte[2];
try //
{ // Read in the archive header data. Fixed sizes.
if( strtbl_pos != -1 ) //
{ efile.read(object_name);
byte temp; efile.read(modification_time);
efile.seek( strtbl_pos + offset ); efile.read(uid);
while( ( temp = efile.readByte() ) != '\n' ) efile.read(gid);
name.append( (char)temp ); efile.read(mode);
} efile.read(size);
} efile.read(trailer);
finally
{
efile.seek( pos );
}
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. // If the name is of the format "/<number>", get name from the
* // string table.
* Assumes that efile is already at the correct location in the file. //
* if (strtbl_pos != -1 && this.object_name.length() > 1 && this.object_name.charAt(0) == '/') {
* @throws IOException try {
* There was an error processing the header data from the file. long offset = Long.parseLong(this.object_name.substring(1));
*/ this.object_name = nameFromStringTable(offset);
public ARHeader() throws IOException { } catch (java.lang.Exception e) {
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. // Strip the trailing / from the object name.
// //
efile.read( object_name ); int len = this.object_name.length();
efile.read( modification_time ); if (len > 2 && this.object_name.charAt(len - 1) == '/') {
efile.read( uid ); this.object_name = this.object_name.substring(0, len - 1);
efile.read( gid ); }
efile.read( mode );
efile.read( size );
efile.read( trailer );
// }
// Save this location so we can create the Elf object later.
//
elf_offset = efile.getFilePointer();
// /** Get the name of the object file */
// Convert the raw bytes into strings and numbers. public String getObjectName() {
// return object_name;
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 size of the object file . */
// If the name is of the format "/<number>", get name from the public long getSize() {
// string table. return size;
// }
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 )
{
}
}
// public String getArchiveName() {
// Strip the trailing / from the object name. return filename;
// }
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);
}
/** Get the name of the object file */ public Elf getElf(boolean filter_on) throws IOException {
public String getObjectName() { return new Elf(filename, elf_offset, filter_on);
return object_name; }
}
/** Get the size of the object file . */ public byte[] getObjectData() throws IOException {
public long getSize() { byte[] temp = new byte[(int) size];
return 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;
}
}
/** /**
* Create an new Elf object for the object file. * Creates a new <code>AR</code> object from the contents of
* * the given file.
* @throws IOException *
* Not a valid Elf object file. * @param filename The file to process.
* @return A new Elf object. * @throws IOException The file is not a valid archive.
* @see Elf#Elf( String, long ) */
*/ public AR(String filename) throws IOException {
public Elf getElf() throws IOException { this.filename = filename;
return new Elf( filename, elf_offset ); 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.");
}
}
public Elf getElf( boolean filter_on ) throws IOException { /** Load the headers from the file (if required). */
return new Elf( filename, elf_offset, filter_on ); private void loadHeaders() throws IOException {
} if (headers != null)
return;
public byte[] getObjectData() throws IOException { Vector v = new Vector();
byte[] temp = new byte[(int)size]; try {
efile.seek( elf_offset ); //
efile.read( temp ); // Check for EOF condition
return temp; //
} while (efile.getFilePointer() < efile.length()) {
} ARHeader header = new ARHeader();
String name = header.getObjectName();
long pos = efile.getFilePointer();
/** //
* Creates a new <code>AR</code> object from the contents of // If the name starts with a / it is specical.
* the given file. //
* if (name.charAt(0) != '/')
* @param filename The file to process. v.add(header);
* @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;
/** Load the headers from the file (if required). */ //
private void loadHeaders() throws IOException { // Compute the location of the next header in the archive.
if( headers != null ) //
return; pos += header.getSize();
if ((pos % 2) != 0)
pos++;
Vector v = new Vector(); efile.seek(pos);
try }
{ } catch (IOException e) {
// }
// Check for EOF condition headers = (ARHeader[]) v.toArray(new ARHeader[0]);
// }
while( efile.getFilePointer() < efile.length() )
{
ARHeader header = new ARHeader();
String name = header.getObjectName();
long pos = efile.getFilePointer(); /**
* 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) {
// If the name starts with a / it is specical. for (int i = 0; i < set.length; i++)
// if (str.compareTo(set[i]) == 0)
if( name.charAt( 0 ) != '/' ) return true;
v.add( header ); return false;
}
// public String[] extractFiles(String outdir, String[] names) throws IOException {
// If the name is "//" then this is the string table section. Vector names_used = new Vector();
// String object_name;
if( name.compareTo( "//" ) == 0 ) int count;
strtbl_pos = pos;
loadHeaders();
// count = 0;
// Compute the location of the next header in the archive. for (int i = 0; i < headers.length; i++) {
// object_name = headers[i].getObjectName();
pos += header.getSize(); if (names != null && !stringInStrings(object_name, names))
if( ( pos % 2 ) != 0 ) continue;
pos++;
efile.seek( pos ); object_name = "" + count + "_" + object_name;
} count++;
}
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");
* Get an array of all the object file headers for this archive. rfile.write(data);
* rfile.close();
* @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;
}
return (String[]) names_used.toArray(new String[0]);
}
private boolean stringInStrings( String str, String[] set ) { public String[] extractFiles(String outdir) throws IOException {
for( int i=0; i<set.length; i++ ) return extractFiles(outdir, null);
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 );
}
} }