1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-29 11:55:40 +02:00

Improve performance of the IBinaryParser

by providing a new API
IBinaryParser.getBinary(byte[] hints, IPath path)
This commit is contained in:
Alain Magloire 2004-02-27 16:22:58 +00:00
parent d6a96dd12e
commit e138c8bc09
13 changed files with 136 additions and 63 deletions

View file

@ -1,3 +1,26 @@
2004-02-27 Alain Magloire
Performance improvement in the IBinaryParser and
changes in the API according to the specs.
Now we have:
IBinaryParser.getBinary(byte[] hints, IPath path);
This is important when having multiple parsers on
the same project. We provide a bucket/hints for the parser
to guess the type of file and reduce the number of open()s.
* model/org/eclipse/cdt/internal/core/model/CModelManager.java
* model/org/eclipse/cdt/internal/core/model/CProject.java
* model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java
* src/org/eclipse/cdt/core/IBinaryParser.java
* utils/org/eclipse/cdt/utils/coff/Coff.java
* utils/org/eclipse/cdt/utils/coff/PE.java
* utils/org/eclipse/cdt/utils/coff/PEArchive.java
* utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser.java
* utils/org/eclipse/cdt/utils/coff/PEParser.java
* utils/org/eclipse/cdt/utils/elf/Elf.java
* utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java
* utils/org/eclipse/cdt/utils/elf/parser/GNUElfParser.java
2004-02-26 Andrew Niefer 2004-02-26 Andrew Niefer
Mark strings that don't need to be externalized for translation Mark strings that don't need to be externalized for translation

View file

@ -400,7 +400,7 @@ public class CModelManager implements IResourceChangeListener {
try { try {
IBinaryParser parser = getBinaryParser(file.getProject()); IBinaryParser parser = getBinaryParser(file.getProject());
InputStream is = file.getContents(); InputStream is = file.getContents();
byte[] bytes = new byte[128]; byte[] bytes = new byte[parser.getHintBufferSize()];
int count = is.read(bytes); int count = is.read(bytes);
is.close(); is.close();
if (count > 0 && count < bytes.length) { if (count > 0 && count < bytes.length) {
@ -409,9 +409,7 @@ public class CModelManager implements IResourceChangeListener {
bytes = array; bytes = array;
} }
IPath location = file.getLocation(); IPath location = file.getLocation();
if (parser.isBinary(bytes, location)) { return parser.getBinary(bytes, location);
return parser.getBinary(location);
}
} catch (IOException e) { } catch (IOException e) {
} catch (CoreException e) { } catch (CoreException e) {
//e.printStackTrace(); //e.printStackTrace();

View file

@ -121,7 +121,7 @@ public class CProject extends CContainer implements ICProject {
if (binParser != null) { if (binParser != null) {
IBinaryFile bin; IBinaryFile bin;
try { try {
bin = binParser.getBinary(entry.getPath()); bin = binParser.getBinary(null, entry.getPath());
if (bin.getType() == IBinaryFile.ARCHIVE) { if (bin.getType() == IBinaryFile.ARCHIVE) {
lib = new LibraryReferenceArchive(cproject, entry, (IBinaryArchive)bin); lib = new LibraryReferenceArchive(cproject, entry, (IBinaryArchive)bin);
} else { } else {

View file

@ -17,7 +17,7 @@ public class NullBinaryParser implements IBinaryParser {
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath) * @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath)
*/ */
public IBinaryFile getBinary(IPath path) throws IOException { public IBinaryFile getBinary(byte[] data, IPath path) throws IOException {
throw new IOException(CCorePlugin.getResourceString("CoreModel.NullBinaryParser.Not_binary_file")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("CoreModel.NullBinaryParser.Not_binary_file")); //$NON-NLS-1$
} }
@ -35,4 +35,11 @@ public class NullBinaryParser implements IBinaryParser {
return false; return false;
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBufferSize()
*/
public int getHintBufferSize() {
return 0;
}
} }

View file

@ -90,9 +90,33 @@ public interface IBinaryParser {
int getLineNumber(long offset); int getLineNumber(long offset);
} }
IBinaryFile getBinary(IPath path) throws IOException; /**
* Creates an IBinaryFile.
* @param hints - array byte that can be use to recognise the file.
* Can be null or empty array when no hints are passed.
* @param path
* @return
* @throws IOException
*/
IBinaryFile getBinary(byte[] hints, IPath path) throws IOException;
boolean isBinary(byte[] array, IPath path); /**
* Returns the name of the Format.
* @return
*/
String getFormat(); String getFormat();
/**
* True if the resource is a binary.
* @param hints
* @param path
* @return
*/
boolean isBinary(byte[] hints, IPath path);
/**
* Get a hint of the needed buffer size to recognise the file.
* @return
*/
int getHintBufferSize();
} }

View file

@ -4,6 +4,7 @@
*/ */
package org.eclipse.cdt.utils.coff; package org.eclipse.cdt.utils.coff;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.text.DateFormat; import java.text.DateFormat;
@ -54,7 +55,18 @@ public class Coff {
file.seek(offset); file.seek(offset);
byte[] hdr = new byte[FILHSZ]; byte[] hdr = new byte[FILHSZ];
file.readFully(hdr); file.readFully(hdr);
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); commonSetup(hdr, true);
}
public FileHeader (byte[] hdr, boolean little) throws EOFException {
commonSetup(hdr, little);
}
public void commonSetup(byte[] hdr, boolean little) throws EOFException {
if (hdr == null || hdr.length < FILHSZ) {
throw new EOFException("array to small"); //$NON-NLS-1
}
ReadMemoryAccess memory = new ReadMemoryAccess(hdr, little);
f_magic = memory.getUnsignedShort(); f_magic = memory.getUnsignedShort();
f_nscns = memory.getUnsignedShort(); f_nscns = memory.getUnsignedShort();
f_timdat = memory.getInt(); f_timdat = memory.getInt();

View file

@ -66,7 +66,7 @@ public class PE {
Symbol[] symbolTable; Symbol[] symbolTable;
byte[] stringTable; byte[] stringTable;
public class Attribute { public static class Attribute {
public static final int PE_TYPE_EXE = 1; public static final int PE_TYPE_EXE = 1;
public static final int PE_TYPE_SHLIB = 2; public static final int PE_TYPE_SHLIB = 2;
public static final int PE_TYPE_OBJ = 3; public static final int PE_TYPE_OBJ = 3;
@ -342,10 +342,8 @@ public class PE {
} }
} }
public Attribute getAttribute() { public static Attribute getAttributes(FileHeader filhdr) {
Attribute attrib = new Attribute(); Attribute attrib = new Attribute();
FileHeader filhdr = getFileHeader();
// Machine type. // Machine type.
switch (filhdr.f_magic) { switch (filhdr.f_magic) {
case PEConstants.IMAGE_FILE_MACHINE_UNKNOWN: case PEConstants.IMAGE_FILE_MACHINE_UNKNOWN:
@ -439,12 +437,25 @@ public class PE {
} }
public static boolean isExeHeader(byte[] e_signature) { public static boolean isExeHeader(byte[] e_signature) {
if (e_signature.length < 2 || e_signature[0] != 'M' || e_signature[1] != 'Z') if (e_signature == null || e_signature.length < 2 || e_signature[0] != 'M' || e_signature[1] != 'Z')
return false; return false;
return true; return true;
} }
public static Attribute getAttributes(String file) throws IOException { public Attribute getAttribute() throws IOException {
return getAttributes(getFileHeader());
}
public static Attribute getAttribute(byte[] data) throws IOException {
if (isExeHeader(data)) {
Coff.FileHeader filehdr;
filehdr = new Coff.FileHeader(data, true);
return getAttributes(filehdr);
}
throw new IOException("not a PE format");
}
public static Attribute getAttribute(String file) throws IOException {
PE pe = new PE(file); PE pe = new PE(file);
Attribute attrib = pe.getAttribute(); Attribute attrib = pe.getAttribute();
pe.dispose(); pe.dispose();

View file

@ -201,7 +201,7 @@ public class PEArchive {
} }
public static boolean isARHeader(byte[] ident) { public static boolean isARHeader(byte[] ident) {
if (ident.length < 7 if (ident == null || ident.length < 7
|| ident[0] != '!' || ident[0] != '!'
|| ident[1] != '<' || ident[1] != '<'
|| ident[2] != 'a' || ident[2] != 'a'

View file

@ -28,8 +28,8 @@ public class CygwinPEParser extends PEParser implements IBinaryParser, ICygwinTo
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath) * @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath)
*/ */
public IBinaryFile getBinary(IPath path) throws IOException { public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
IBinaryFile binary = super.getBinary(path); IBinaryFile binary = super.getBinary(hints, path);
if (binary instanceof BinaryFile) { if (binary instanceof BinaryFile) {
((BinaryFile)binary).setToolsProvider(this); ((BinaryFile)binary).setToolsProvider(this);
} }

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.utils.coff.parser; package org.eclipse.cdt.utils.coff.parser;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.AbstractCExtension;
@ -28,14 +29,26 @@ public class PEParser extends AbstractCExtension implements IBinaryParser {
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IFile) * @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IFile)
*/ */
public IBinaryFile getBinary(IPath path) throws IOException { public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
if (path == null) { if (path == null) {
throw new IOException("path is null"); throw new IOException("path is null");
} }
BinaryFile binary = null; BinaryFile binary = null;
try { try {
PE.Attribute attribute = PE.getAttributes(path.toOSString()); PE.Attribute attribute = null;
if (hints != null && hints.length > 0) {
try {
attribute = PE.getAttribute(hints);
} catch (EOFException e) {
// continue to try
}
}
// the hints may have to small, keep on trying.
if (attribute == null) {
attribute = PE.getAttribute(path.toOSString());
}
if (attribute != null) { if (attribute != null) {
switch (attribute.getType()) { switch (attribute.getType()) {
case Attribute.PE_TYPE_EXE : case Attribute.PE_TYPE_EXE :
@ -105,4 +118,11 @@ public class PEParser extends AbstractCExtension implements IBinaryParser {
return isBin; return isBin;
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getHintBufferSize()
*/
public int getHintBufferSize() {
return 128;
}
} }

View file

@ -5,6 +5,7 @@ package org.eclipse.cdt.utils.elf;
* All Rights Reserved. * All Rights Reserved.
*/ */
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -143,7 +144,7 @@ public class Elf {
protected ELFhdr(byte [] bytes) throws IOException { protected ELFhdr(byte [] bytes) throws IOException {
if(bytes.length <= e_ident.length) { if(bytes.length <= e_ident.length) {
throw new IOException("Not ELF format"); throw new EOFException("Not ELF format");
} }
System.arraycopy(bytes, 0, e_ident, 0, e_ident.length); System.arraycopy(bytes, 0, e_ident, 0, e_ident.length);
if ( e_ident[ELFhdr.EI_MAG0] != 0x7f || e_ident[ELFhdr.EI_MAG1] != 'E' || if ( e_ident[ELFhdr.EI_MAG0] != 0x7f || e_ident[ELFhdr.EI_MAG1] != 'E' ||

View file

@ -10,6 +10,7 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.utils.elf.parser; package org.eclipse.cdt.utils.elf.parser;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.AbstractCExtension;
@ -22,11 +23,8 @@ import org.eclipse.core.runtime.IPath;
/** /**
*/ */
public class ElfParser extends AbstractCExtension implements IBinaryParser { public class ElfParser extends AbstractCExtension implements IBinaryParser {
byte [] fCachedByteArray;
IPath fCachedPathEntry; public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
boolean fCachedIsAR;
public IBinaryFile getBinary(IPath path) throws IOException {
if (path == null) { if (path == null) {
throw new IOException("path is null"); throw new IOException("path is null");
} }
@ -34,25 +32,15 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser {
BinaryFile binary = null; BinaryFile binary = null;
try { try {
Elf.Attribute attribute = null; Elf.Attribute attribute = null;
if (hints != null && hints.length > 0) {
//Try our luck with the cached entry first, then clear it
if(fCachedPathEntry != null && fCachedPathEntry.equals(path)) {
try { try {
//Don't bother with ELF stuff if this is an archive attribute = Elf.getAttributes(hints);
if(fCachedIsAR) { } catch (EOFException eof) {
return new BinaryArchive(path); // continue, the array was to small.
}
//Well, if it wasn't an archive, go for broke
attribute = Elf.getAttributes(fCachedByteArray);
} catch(Exception ex) {
attribute = null;
} finally {
fCachedPathEntry = null;
fCachedByteArray = null;
} }
} }
//Take a second run at it if the cache failed. //Take a second run at it if the data array failed.
if(attribute == null) { if(attribute == null) {
attribute = Elf.getAttributes(path.toOSString()); attribute = Elf.getAttributes(path.toOSString());
} }
@ -95,24 +83,13 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser {
* @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath) * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath)
*/ */
public boolean isBinary(byte[] array, IPath path) { public boolean isBinary(byte[] array, IPath path) {
boolean isBinaryReturnValue = false; return Elf.isElfHeader(array) || AR.isARHeader(array);
if(Elf.isElfHeader(array)) {
isBinaryReturnValue = true;
fCachedIsAR = false;
} else if(AR.isARHeader(array)) {
isBinaryReturnValue = true;
fCachedIsAR = true;
}
//If it is a binary, then cache the array in anticipation that we will be asked to do something with it
if(isBinaryReturnValue && array.length > 0) {
fCachedPathEntry = path;
fCachedByteArray = new byte[array.length];
System.arraycopy(array, 0, fCachedByteArray, 0, array.length);
}
return isBinaryReturnValue;
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBufferSize()
*/
public int getHintBufferSize() {
return 128;
}
} }

View file

@ -28,8 +28,8 @@ public class GNUElfParser extends ElfParser implements IBinaryParser, IToolsProv
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath) * @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath)
*/ */
public IBinaryFile getBinary(IPath path) throws IOException { public IBinaryFile getBinary(byte[] data, IPath path) throws IOException {
IBinaryFile binary = super.getBinary(path); IBinaryFile binary = super.getBinary(data, path);
if (binary instanceof BinaryFile) { if (binary instanceof BinaryFile) {
((BinaryFile)binary).setToolsProvider(this); ((BinaryFile)binary).setToolsProvider(this);
} }