diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index d683c8947ba..4d1e5027d33 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,31 @@ +2003-11-18 Alain Magloire + + Attempt to address performance problems from the binary parser + on big projects. The problem is that files are open multiple + times to detect if they are binaries or archives. We can + not really rely on the filename or extension. A new method + as been added to the IBinaryParser interface, isBinary() + taken an intial byte[]. + + * model/org/eclipse/cdt/internal/core/model/Binary.java + * model/org/eclipse/cdt/internal/core/model/CModelManager.java + * model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java + * src/org/eclipse/cdt/core/CCorePlugin.java + * src/org/eclipse/cdt/core/IBinaryParser.java + * utils/org/eclipse/cdt/utils/coff/PE.java + * utils/org/eclipse/cdt/utils/coff/PEArchive.java + * utils/org/eclipse/cdt/utils/coff/parser/ARMember.java + * utils/org/eclipse/cdt/utils/coff/parser/BinaryArchive.java + * utils/org/eclipse/cdt/utils/coff/parser/BinaryObject.java + * utils/org/eclipse/cdt/utils/coff/parser/PEParser.java + * utils/org/eclipse/cdt/utils/coff/parser/Symbol.java + * utils/org/eclipse/cdt/utils/elf/AR.java + * utils/org/eclipse/cdt/utils/elf/parser/ARMember.java + * utils/org/eclipse/cdt/utils/elf/parser/BinaryArchive.java + * utils/org/eclipse/cdt/utils/elf/parser/BinaryObject.java + * utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java + * utils/org/eclipse/cdt/utils/elf/parser/Symbol.java + 2003-11-17 Doug Schaefer Nothing just testing the commit logs diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java index 37ecafe5e44..0b99b357bb6 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java @@ -174,19 +174,18 @@ public class Binary extends Openable implements IBinary { } private void addFunction(OpenableInfo info, ISymbol symbol, Map hash) { - String filename = filename = symbol.getFilename(); + IPath filename = filename = symbol.getFilename(); BinaryFunction function = null; // Addr2line returns the funny "??" when it can find the file. if (filename != null && !filename.equals("??")) { BinaryModule module = null; - IPath path = new Path(filename); - if (hash.containsKey(path)) { - module = (BinaryModule)hash.get(path); + if (hash.containsKey(filename)) { + module = (BinaryModule)hash.get(filename); } else { // A special container we do not want the file to be parse. - module = new BinaryModule(this, path); - hash.put(path, module); + module = new BinaryModule(this, filename); + hash.put(filename, module); info.addChild(module); } function = new BinaryFunction(module, symbol.getName(), symbol.getAddress()); @@ -206,17 +205,16 @@ public class Binary extends Openable implements IBinary { } private void addVariable(OpenableInfo info, ISymbol symbol, Map hash) { - String filename = filename = symbol.getFilename(); + IPath filename = filename = symbol.getFilename(); BinaryVariable variable = null; // Addr2line returns the funny "??" when it can not find the file. if (filename != null && !filename.equals("??")) { BinaryModule module = null; - IPath path = new Path(filename); - if (hash.containsKey(path)) { - module = (BinaryModule)hash.get(path); + if (hash.containsKey(filename)) { + module = (BinaryModule)hash.get(filename); } else { - module = new BinaryModule(this, path); - hash.put(path, module); + module = new BinaryModule(this, filename); + hash.put(filename, module); info.addChild(module); } variable = new BinaryVariable(module, symbol.getName(), symbol.getAddress()); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelInfo.java index 8b54b5d6581..f2cac585ec8 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelInfo.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelInfo.java @@ -21,7 +21,7 @@ public class CModelInfo extends CContainerInfo { } /** - * Compute the non-java resources contained in this java project. + * Compute the non-C resources contained in this C project. */ private Object[] computeNonCResources() { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index ec5aa277b44..1b20fe0c268 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -6,6 +6,7 @@ package org.eclipse.cdt.internal.core.model; */ import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -97,6 +98,11 @@ public class CModelManager implements IResourceChangeListener { * The list of started BinaryRunners on projects. */ private HashMap binaryRunners = new HashMap(); + + /** + * Map of the binary parser for each project. + */ + private HashMap binaryParsersMap = new HashMap(); /** * The lis of the SourceMappers on projects. @@ -345,7 +351,14 @@ public class CModelManager implements IResourceChangeListener { public IBinaryParser getBinaryParser(IProject project) { try { - return CCorePlugin.getDefault().getBinaryParser(project); + IBinaryParser parser = (IBinaryParser)binaryParsersMap.get(project); + if (parser == null) { + parser = CCorePlugin.getDefault().getBinaryParser(project); + } + if (parser != null) { + binaryParsersMap.put(project, parser); + return parser; + } } catch (CoreException e) { } return new NullBinaryParser(); @@ -354,8 +367,22 @@ public class CModelManager implements IResourceChangeListener { public IBinaryFile createBinaryFile(IFile file) { try { IBinaryParser parser = getBinaryParser(file.getProject()); - return parser.getBinary(file.getLocation()); + InputStream is = file.getContents(); + byte[] bytes = new byte[128]; + int count = is.read(bytes); + is.close(); + if (count > 0 && count < bytes.length) { + byte[] array = new byte[count]; + System.arraycopy(bytes, 0, array, 0, count); + bytes = array; + } + IPath location = file.getLocation(); + if (parser.isBinary(bytes, location)) { + return parser.getBinary(location); + } } catch (IOException e) { + } catch (CoreException e) { + //e.printStackTrace(); } return null; } @@ -372,6 +399,7 @@ public class CModelManager implements IResourceChangeListener { // but it has the side of effect of removing the CProject also // so we have to recall create again. releaseCElement(celement); + binaryParsersMap.remove(project); celement = create(project); Parent parent = (Parent)celement.getParent(); CElementInfo info = (CElementInfo)parent.getElementInfo(); @@ -750,6 +778,7 @@ public class CModelManager implements IResourceChangeListener { break; } } + /** * Returns the set of elements which are out of synch with their buffers. */ @@ -820,5 +849,6 @@ public class CModelManager implements IResourceChangeListener { if (runner != null) { runner.stop(); } + binaryParsersMap.remove(project); } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java index 148604d8a86..cf4c4586f09 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/NullBinaryParser.java @@ -28,4 +28,11 @@ public class NullBinaryParser implements IBinaryParser { return "Null Format"; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath) + */ + public boolean isBinary(byte[] array, IPath path) { + return false; + } + } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index a9ed936d214..ee5e8c52939 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -471,7 +471,7 @@ public class CCorePlugin extends Plugin { if (project != null) { try { ICDescriptor cdesc = (ICDescriptor) getCProjectDescription(project); - ICExtensionReference[] cextensions = cdesc.get(BINARY_PARSER_UNIQ_ID); + ICExtensionReference[] cextensions = cdesc.get(BINARY_PARSER_UNIQ_ID, true); if (cextensions.length > 0) parser = (IBinaryParser) cextensions[0].createExtension(); } catch (CoreException e) { diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IBinaryParser.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IBinaryParser.java index 04abf78a16f..3f7e3a78898 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IBinaryParser.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IBinaryParser.java @@ -55,7 +55,9 @@ public interface IBinaryParser { boolean isLittleEndian(); ISymbol[] getSymbols(); - + + ISymbol getSymbol(long addr); + String getName(); } @@ -74,7 +76,7 @@ public interface IBinaryParser { String getSoName(); } - interface ISymbol { + interface ISymbol extends Comparable { static final int FUNCTION = 0x01; static final int VARIABLE = 0x02; @@ -82,11 +84,13 @@ public interface IBinaryParser { long getAddress(); int getStartLine(); int getEndLine(); - String getFilename(); + IPath getFilename(); int getType(); } IBinaryFile getBinary(IPath path) throws IOException; + + boolean isBinary(byte[] array, IPath path); String getFormat(); } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java index ba7d1949452..d95e27ab4f0 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java @@ -438,6 +438,12 @@ public class PE { return attrib; } + public static boolean isExeHeader(byte[] e_signature) { + if (e_signature.length < 2 || e_signature[0] != 'M' || e_signature[1] != 'Z') + return false; + return true; + } + public static Attribute getAttributes(String file) throws IOException { PE pe = new PE(file); Attribute attrib = pe.getAttribute(); diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java index 37b1e21bb99..35cb63c392f 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEArchive.java @@ -200,6 +200,19 @@ public class PEArchive { } } + public static boolean isARHeader(byte[] ident) { + if (ident.length < 7 + || ident[0] != '!' + || ident[1] != '<' + || ident[2] != 'a' + || ident[3] != 'r' + || ident[4] != 'c' + || ident[5] != 'h' + || ident[6] != '>') + return false; + return true; + } + /** * Creates a new AR object from the contents of * the given file. diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/ARMember.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/ARMember.java index d213ecab810..73ec760ad76 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/ARMember.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/ARMember.java @@ -13,11 +13,13 @@ package org.eclipse.cdt.utils.coff.parser; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.List; import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.utils.Addr2line; import org.eclipse.cdt.utils.CPPFilt; import org.eclipse.cdt.utils.CygPath; +import org.eclipse.cdt.utils.ICygwinToolsProvider; import org.eclipse.cdt.utils.coff.Coff; import org.eclipse.cdt.utils.coff.PE; import org.eclipse.cdt.utils.coff.PEArchive; @@ -28,8 +30,8 @@ import org.eclipse.core.runtime.IPath; public class ARMember extends BinaryObject { PEArchive.ARHeader header; - public ARMember(IPath p, PEArchive.ARHeader h) throws IOException { - super(p, h.getPE()); + public ARMember(IPath p, PEArchive.ARHeader h, ICygwinToolsProvider provider) throws IOException { + super(p, h.getPE(), provider); header = h; } @@ -67,7 +69,7 @@ public class ARMember extends BinaryObject { throw new IOException("No file assiocated with Binary"); } - protected void addSymbols(Coff.Symbol[] peSyms, byte[] table, Addr2line addr2line, CPPFilt cppfilt, CygPath cypath) { + protected void addSymbols(Coff.Symbol[] peSyms, byte[] table, Addr2line addr2line, CPPFilt cppfilt, CygPath cypath, List list) { for (int i = 0; i < peSyms.length; i++) { if (peSyms[i].isFunction() || peSyms[i].isPointer() ||peSyms[i].isArray()) { String name = peSyms[i].getName(table); @@ -80,7 +82,7 @@ public class ARMember extends BinaryObject { sym.name = name; sym.addr = peSyms[i].n_value; - addSymbol(sym); + list.add(sym); } } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryArchive.java index a29aeaf8be9..d32d6e22dfb 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryArchive.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryArchive.java @@ -38,7 +38,7 @@ public class BinaryArchive extends BinaryFile implements IBinaryArchive { ar = new PEArchive(getPath().toOSString()); PEArchive.ARHeader[] headers = ar.getHeaders(); for (int i = 0; i < headers.length; i++) { - IBinaryObject bin = new ARMember(path, headers[i]); + IBinaryObject bin = new ARMember(path, headers[i], toolsProvider); children.add(bin); } } catch (IOException e) { diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryObject.java index f71ef98628e..1ea7e6d2b93 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryObject.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/BinaryObject.java @@ -1,11 +1,19 @@ +/********************************************************************** + * Copyright (c) 2002,2003 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation +***********************************************************************/ package org.eclipse.cdt.utils.coff.parser; -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; @@ -13,27 +21,29 @@ import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.utils.Addr2line; import org.eclipse.cdt.utils.CPPFilt; import org.eclipse.cdt.utils.CygPath; +import org.eclipse.cdt.utils.ICygwinToolsProvider; import org.eclipse.cdt.utils.coff.Coff; import org.eclipse.cdt.utils.coff.PE; import org.eclipse.cdt.utils.coff.PE.Attribute; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; /** */ public class BinaryObject extends BinaryFile implements IBinaryObject { PE.Attribute attribute; - ArrayList symbols; + ISymbol[] symbols; int type = IBinaryFile.OBJECT; - + private ISymbol[] NO_SYMBOLS = new ISymbol[0]; + public BinaryObject(IPath p) throws IOException { super(p); - loadInformation(); - hasChanged(); } - public BinaryObject(IPath p, PE pe) throws IOException { + public BinaryObject(IPath p, PE pe, ICygwinToolsProvider provider) throws IOException { super(p); + setToolsProvider(provider); loadInformation(pe); pe.dispose(); hasChanged(); @@ -43,6 +53,18 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { type = t; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbol(long) + */ + public ISymbol getSymbol(long addr) { + ISymbol[] syms = getSymbols(); + int i = Arrays.binarySearch(syms, new Long(addr)); + if (i < 0 || i >= syms.length) { + return null; + } + return syms[i]; + } + /** * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType() */ @@ -87,15 +109,15 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { */ public ISymbol[] getSymbols() { if (hasChanged() || symbols == null) { - if (symbols == null) { - symbols = new ArrayList(5); - } try { loadInformation(); } catch (IOException e) { } + if (symbols == null) { + symbols = NO_SYMBOLS; + } } - return (ISymbol[])symbols.toArray(new ISymbol[0]); + return symbols; } /** @@ -163,11 +185,7 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { private void loadInformation(PE pe) throws IOException { loadAttribute(pe); - if (symbols != null) { - symbols.clear(); - loadSymbols(pe); - symbols.trimToSize(); - } + loadSymbols(pe); } private void loadAttribute(PE pe) throws IOException { @@ -175,13 +193,14 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { } private void loadSymbols(PE pe) throws IOException { + ArrayList list = new ArrayList(); Addr2line addr2line = getAddr2Line(); CPPFilt cppfilt = getCPPFilt(); CygPath cygpath = getCygPath(); Coff.Symbol[] peSyms = pe.getSymbols(); byte[] table = pe.getStringTable(); - addSymbols(peSyms, table, addr2line, cppfilt, cygpath); + addSymbols(peSyms, table, addr2line, cppfilt, cygpath, list); if (addr2line != null) { addr2line.dispose(); @@ -192,10 +211,13 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { if (cygpath != null) { cygpath.dispose(); } - symbols.trimToSize(); + + symbols = (ISymbol[])list.toArray(NO_SYMBOLS); + Arrays.sort(symbols); + list.clear(); } - protected void addSymbols(Coff.Symbol[] peSyms, byte[] table, Addr2line addr2line, CPPFilt cppfilt, CygPath cygpath) { + protected void addSymbols(Coff.Symbol[] peSyms, byte[] table, Addr2line addr2line, CPPFilt cppfilt, CygPath cygpath, List list) { for (int i = 0; i < peSyms.length; i++) { if (peSyms[i].isFunction() || peSyms[i].isPointer() ||peSyms[i].isArray()) { String name = peSyms[i].getName(table); @@ -220,20 +242,21 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { sym.endLine = 0; if (addr2line != null) { try { - sym.filename = addr2line.getFileName(sym.addr); - if (cygpath != null) - sym.filename = cygpath.getFileName(sym.filename); + String filename = addr2line.getFileName(sym.addr); + if (filename != null) { + if (cygpath != null) { + sym.filename = new Path(cygpath.getFileName(filename)); + } else { + sym.filename = new Path(filename); + } + } sym.startLine = addr2line.getLineNumber(sym.addr); } catch (IOException e) { } } - addSymbol(sym); + list.add(sym); } } } - protected void addSymbol(Symbol sym) { - symbols.add(sym); - } - } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java index 4b7eeeafb22..1043a4a21e9 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java @@ -16,6 +16,7 @@ import java.io.IOException; import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.utils.coff.PE; +import org.eclipse.cdt.utils.coff.PEArchive; import org.eclipse.cdt.utils.coff.PE.Attribute; import org.eclipse.core.runtime.IPath; @@ -70,4 +71,11 @@ public class PEParser extends AbstractCExtension implements IBinaryParser { return "PE"; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath) + */ + public boolean isBinary(byte[] array, IPath path) { + return PE.isExeHeader(array) || PEArchive.isARHeader(array); + } + } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/Symbol.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/Symbol.java index 14b84430b29..e0535a68416 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/Symbol.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/Symbol.java @@ -14,12 +14,13 @@ import java.io.IOException; import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.utils.Addr2line; +import org.eclipse.core.runtime.IPath; public class Symbol implements ISymbol { BinaryObject binary; - public String filename; + public IPath filename; public int startLine; public int endLine; public long addr; @@ -32,7 +33,7 @@ public class Symbol implements ISymbol { /** * @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getFilename() */ - public String getFilename() { + public IPath getFilename() { return filename; } @@ -88,4 +89,22 @@ public class Symbol implements ISymbol { return line; } + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object obj) { + long thisVal = 0; + long anotherVal = 0; + if (obj instanceof Symbol) { + Symbol sym = (Symbol) obj; + thisVal = this.addr; + anotherVal = sym.addr; + } else if (obj instanceof Long) { + Long val = (Long) obj; + anotherVal = val.longValue(); + thisVal = (long) this.addr; + } + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } + } 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 98df6c982a2..fcb9e7d6e9d 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 @@ -207,6 +207,19 @@ public class AR { } } + public static boolean isARHeader(byte[] ident) { + if (ident.length < 7 + || ident[0] != '!' + || ident[1] != '<' + || ident[2] != 'a' + || ident[3] != 'r' + || ident[4] != 'c' + || ident[5] != 'h' + || ident[6] != '>') + return false; + return true; + } + /** * Creates a new AR object from the contents of * the given file. diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java index 1ef4640e788..76285236294 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java @@ -707,6 +707,13 @@ public class Elf { return attrib; } + public static boolean isElfHeader(byte[] e_ident) { + if (e_ident.length < 4 || e_ident[ELFhdr.EI_MAG0] != 0x7f || e_ident[ELFhdr.EI_MAG1] != 'E' || + e_ident[ELFhdr.EI_MAG2] != 'L' || e_ident[ELFhdr.EI_MAG3] != 'F') + return false; + return true; + } + public void dispose() { if (addr2line != null) { addr2line.dispose(); diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ARMember.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ARMember.java index 417c369625c..a9162ef000f 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ARMember.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ARMember.java @@ -13,9 +13,11 @@ package org.eclipse.cdt.utils.elf.parser; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.List; import org.eclipse.cdt.utils.Addr2line; import org.eclipse.cdt.utils.CPPFilt; +import org.eclipse.cdt.utils.IToolsProvider; import org.eclipse.cdt.utils.elf.AR; import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.ElfHelper; @@ -26,8 +28,8 @@ import org.eclipse.core.runtime.IPath; public class ARMember extends BinaryObject { AR.ARHeader header; - public ARMember(IPath p, AR.ARHeader h) throws IOException { - super(p, new ElfHelper(h.getElf())); + public ARMember(IPath p, AR.ARHeader h, IToolsProvider provider) throws IOException { + super(p, new ElfHelper(h.getElf()), provider); header = h; } @@ -65,13 +67,13 @@ public class ARMember extends BinaryObject { throw new IOException("No file assiocated with Binary"); } - protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt) { + protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt, List list) { for (int i = 0; i < array.length; i++) { Symbol sym = new Symbol(this); sym.type = type; sym.name = array[i].toString(); sym.addr = array[i].st_value; - addSymbol(sym); + list.add(sym); } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryArchive.java index ba4a8b78fa5..d91f4190974 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryArchive.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryArchive.java @@ -44,7 +44,7 @@ public class BinaryArchive extends BinaryFile implements IBinaryArchive { ar = new AR(getPath().toOSString()); AR.ARHeader[] headers = ar.getHeaders(); for (int i = 0; i < headers.length; i++) { - IBinaryObject bin = new ARMember(getPath(), headers[i]); + IBinaryObject bin = new ARMember(getPath(), headers[i], toolsProvider); children.add(bin); } } catch (IOException e) { diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryObject.java index fdf3d56a95a..d454d9c6e15 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryObject.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/BinaryObject.java @@ -12,17 +12,21 @@ package org.eclipse.cdt.utils.elf.parser; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.utils.Addr2line; import org.eclipse.cdt.utils.CPPFilt; +import org.eclipse.cdt.utils.IToolsProvider; import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.ElfHelper; import org.eclipse.cdt.utils.elf.Elf.Attribute; import org.eclipse.cdt.utils.elf.ElfHelper.Sizes; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; /** */ @@ -32,21 +36,33 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { protected int type = IBinaryFile.OBJECT; private Sizes sizes; private Attribute attribute; - private ArrayList symbols; + private ISymbol[] symbols; + private ISymbol[] NO_SYMBOLS = new ISymbol[0]; public BinaryObject(IPath path) throws IOException { super(path); - loadInformation(); - hasChanged(); } - public BinaryObject(IPath path, ElfHelper helper) throws IOException { + public BinaryObject(IPath path, ElfHelper helper, IToolsProvider provider) throws IOException { super(path); + setToolsProvider(provider); loadInformation(helper); helper.dispose(); hasChanged(); } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbol(long) + */ + public ISymbol getSymbol(long addr) { + ISymbol[] syms = getSymbols(); + int i = Arrays.binarySearch(syms, new Long(addr)); + if (i < 0 || i >= syms.length) { + return null; + } + return syms[i]; + } + /** * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getBSS() */ @@ -129,15 +145,15 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { */ public ISymbol[] getSymbols() { if (hasChanged() || symbols == null) { - if (symbols == null) { - symbols = new ArrayList(5); - } try { loadInformation(); } catch (IOException e) { } + if (symbols == null) { + symbols = NO_SYMBOLS; + } } - return (ISymbol[]) symbols.toArray(new ISymbol[0]); + return symbols; } /** @@ -189,11 +205,7 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { private void loadInformation(ElfHelper helper) throws IOException { loadAttributes(helper); - if (symbols != null) { - symbols.clear(); - loadSymbols(helper); - symbols.trimToSize(); - } + loadSymbols(helper); } private void loadAttributes(ElfHelper helper) throws IOException { @@ -208,25 +220,18 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { } private void loadSymbols(ElfHelper helper) throws IOException { - Elf.Dynamic[] sharedlibs = helper.getNeeded(); - needed = new String[sharedlibs.length]; - for (int i = 0; i < sharedlibs.length; i++) { - needed[i] = sharedlibs[i].toString(); - } - sizes = helper.getSizes(); - soname = helper.getSoname(); - attribute = helper.getElf().getAttributes(); + ArrayList list = new ArrayList(); // Hack should be remove when Elf is clean helper.getElf().setCppFilter(false); Addr2line addr2line = getAddr2Line(); CPPFilt cppfilt = getCPPFilt(); - addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, addr2line, cppfilt); - addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, addr2line, cppfilt); - addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, addr2line, cppfilt); - addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE, addr2line, cppfilt); - symbols.trimToSize(); + addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, addr2line, cppfilt, list); + addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, addr2line, cppfilt, list); + addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, addr2line, cppfilt, list); + addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE, addr2line, cppfilt, list); + list.trimToSize(); if (addr2line != null) { addr2line.dispose(); @@ -234,9 +239,13 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { if (cppfilt != null) { cppfilt.dispose(); } + + symbols = (ISymbol[])list.toArray(NO_SYMBOLS); + Arrays.sort(symbols); + list.clear(); } - protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt) { + protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt, List list) { for (int i = 0; i < array.length; i++) { Symbol sym = new Symbol(this); sym.type = type; @@ -253,18 +262,15 @@ public class BinaryObject extends BinaryFile implements IBinaryObject { sym.endLine = sym.startLine; if (addr2line != null) { try { - sym.filename = addr2line.getFileName(sym.addr); + String filename = addr2line.getFileName(sym.addr); + sym.filename = (filename != null) ? new Path(filename) : null; sym.startLine = addr2line.getLineNumber(sym.addr); sym.endLine = addr2line.getLineNumber(sym.addr + array[i].st_size - 1); } catch (IOException e) { } } - addSymbol(sym); + list.add(sym); } } - protected void addSymbol(Symbol sym) { - symbols.add(sym); - } - } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java index 348ff6d22cf..b3c4679ab65 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java @@ -14,6 +14,7 @@ import java.io.IOException; import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.utils.elf.AR; import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.Elf.Attribute; import org.eclipse.core.runtime.IPath; @@ -67,4 +68,11 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser { return "ELF"; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath) + */ + public boolean isBinary(byte[] array, IPath path) { + return Elf.isElfHeader(array) || AR.isARHeader(array); + } + } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/Symbol.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/Symbol.java index 263b0d1d98f..f05e274ab4e 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/Symbol.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/Symbol.java @@ -14,12 +14,13 @@ import java.io.IOException; import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.utils.Addr2line; +import org.eclipse.core.runtime.IPath; -public class Symbol implements ISymbol { +public class Symbol implements ISymbol, Comparable { BinaryObject binary; - public String filename; + public IPath filename; public int startLine; public int endLine; public long addr; @@ -27,16 +28,15 @@ public class Symbol implements ISymbol { public int type; public Symbol(BinaryObject bin) { - binary = bin; + binary = bin; } /** * @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getFilename() */ - public String getFilename() { + public IPath getFilename() { return filename; } - /** * @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getName() */ @@ -83,9 +83,23 @@ public class Symbol implements ISymbol { line = addr2line.getLineNumber(addr + offset); addr2line.dispose(); } - } catch (IOException e) { + } catch (IOException e) { } return line; } + public int compareTo(Object obj) { + long thisVal = 0; + long anotherVal = 0; + if (obj instanceof Symbol) { + Symbol sym = (Symbol) obj; + thisVal = this.addr; + anotherVal = sym.addr; + } else if (obj instanceof Long) { + Long val = (Long) obj; + anotherVal = val.longValue(); + thisVal = (long) this.addr; + } + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } }