From 6940e686c7b274fc49f34cc2b45244125f289db0 Mon Sep 17 00:00:00 2001 From: David Inglis Date: Wed, 26 Feb 2003 21:01:28 +0000 Subject: [PATCH] faster IArchive --- core/org.eclipse.cdt.core/ChangeLog | 11 + .../internal/core/model/ArchiveContainer.java | 3 +- .../internal/core/model/BinaryContainer.java | 1 - .../core/model/parser/ElfBinaryArchive.java | 2 +- .../core/model/parser/ElfBinaryFile.java | 100 ++-- .../utils/org/eclipse/cdt/utils/elf/AR.java | 543 +++++++++--------- 6 files changed, 304 insertions(+), 356 deletions(-) diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 830d8bc0eab..4477da740c4 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -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: diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java index d2ea2187aa0..e22639f6bd2 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java @@ -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; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java index 57079d78b4b..26b57407439 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java @@ -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"); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryArchive.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryArchive.java index a0102710ff2..d6de29a0f52 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryArchive.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryArchive.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryFile.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryFile.java index 6eb06343dca..81cebdc6bf8 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryFile.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryFile.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/AR.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/AR.java index ba3292099e8..98df6c982a2 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/AR.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/AR.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.util.Vector; - /** * The AR 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 ARHeader 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 ARHeader 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 efile 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 = 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 efile 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 = 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 "/", 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 "/", 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 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 AR(String filename) throws IOException { + this.filename = filename; + efile = new ERandomAccessFile(filename, "r"); + String hdr = efile.readLine(); + if (hdr == null || hdr.compareTo("!") != 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 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 AR( String filename ) throws IOException { - this.filename = filename; - efile = new ERandomAccessFile( filename, "r" ); - String hdr = efile.readLine(); - if( hdr == null || hdr.compareTo( "!" ) != 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