1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-22 15:53:58 +02:00

Those are heavy changes concerning the Binary Parser.

The problem was that binaryParser scheme was
a perfomance problem affecting a lot of people
when projects were medium/big size.  The IBinaryParser
was extended to allow one more method isbinary()
so that will let the BinaryParser open() the file
only once instead of multiple time like it did before.
This commit is contained in:
Alain Magloire 2003-11-18 17:16:39 +00:00
parent 52ecc62130
commit 29026f5fb0
31 changed files with 707 additions and 1365 deletions

View file

@ -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-13 David Inglis 2003-11-13 David Inglis
Fixed #46431 Fixed #46431
* utils/org/eclipse/cdt/utils/spawner/EnvironmentReader.java * utils/org/eclipse/cdt/utils/spawner/EnvironmentReader.java

View file

@ -69,7 +69,7 @@ public class Archive extends Openable implements IArchive {
IBinaryObject[] objects = ar.getObjects(); IBinaryObject[] objects = ar.getObjects();
for (int i = 0; i < objects.length; i++) { for (int i = 0; i < objects.length; i++) {
final IBinaryObject obj = objects[i]; final IBinaryObject obj = objects[i];
Binary binary = new Binary(this, res.getLocation().append(obj.getName()), obj); Binary binary = new Binary(this, ar.getPath().append(obj.getName()), obj);
info.addChild(binary); info.addChild(binary);
} }
} else { } else {

View file

@ -40,6 +40,10 @@ public class Binary extends Openable implements IBinary {
binaryFile = bin; binaryFile = bin;
} }
protected IBinaryFile getBinaryFile() {
return binaryFile;
}
public boolean isSharedLib() { public boolean isSharedLib() {
return getType() == IBinaryObject.SHARED; return getType() == IBinaryObject.SHARED;
} }
@ -58,65 +62,71 @@ public class Binary extends Openable implements IBinary {
public boolean hasDebug() { public boolean hasDebug() {
if (isObject() || isExecutable() || isSharedLib()) { if (isObject() || isExecutable() || isSharedLib()) {
return ((IBinaryObject)binaryFile).hasDebug(); return ((IBinaryObject)getBinaryFile()).hasDebug();
} }
return false; return false;
} }
public String getCPU() { public String getCPU() {
if (isObject() || isExecutable() || isSharedLib() || isCore()) { if (isObject() || isExecutable() || isSharedLib() || isCore()) {
return ((IBinaryObject)binaryFile).getCPU(); return ((IBinaryObject)getBinaryFile()).getCPU();
} }
return ""; return "";
} }
public String[] getNeededSharedLibs() { public String[] getNeededSharedLibs() {
if (isExecutable() || isSharedLib()) { if (isExecutable() || isSharedLib()) {
return ((IBinaryExecutable)binaryFile).getNeededSharedLibs(); return ((IBinaryExecutable)getBinaryFile()).getNeededSharedLibs();
} }
return new String[0]; return new String[0];
} }
protected int getType() { protected int getType() {
IResource res = getResource(); if (getBinaryFile() != null && (fBinType == 0 || getModificationStamp() != fLastModification )) {
if (binaryFile != null && (fBinType == 0 || res.getModificationStamp() != fLastModification )) { fLastModification = getModificationStamp();
fLastModification = res.getModificationStamp(); fBinType = getBinaryFile().getType();
fBinType = binaryFile.getType();
} }
return fBinType; return fBinType;
} }
protected long getModificationStamp() {
IResource res = getResource();
if (res != null)
return res.getModificationStamp();
return 0;
}
public long getText() { public long getText() {
if (isObject() || isExecutable() || isSharedLib()) { if (isObject() || isExecutable() || isSharedLib()) {
return ((IBinaryObject)binaryFile).getText(); return ((IBinaryObject)getBinaryFile()).getText();
} }
return 0; return 0;
} }
public long getData() { public long getData() {
if (isObject() || isExecutable() || isSharedLib()) { if (isObject() || isExecutable() || isSharedLib()) {
return ((IBinaryObject)binaryFile).getData(); return ((IBinaryObject)getBinaryFile()).getData();
} }
return 0; return 0;
} }
public long getBSS() { public long getBSS() {
if (isObject() || isExecutable() || isSharedLib()) { if (isObject() || isExecutable() || isSharedLib()) {
return ((IBinaryObject)binaryFile).getBSS(); return ((IBinaryObject)getBinaryFile()).getBSS();
} }
return 0; return 0;
} }
public String getSoname() { public String getSoname() {
if (isSharedLib()) { if (isSharedLib()) {
return ((IBinaryShared)binaryFile).getSoName(); return ((IBinaryShared)getBinaryFile()).getSoName();
} }
return ""; return "";
} }
public boolean isLittleEndian() { public boolean isLittleEndian() {
if (isObject() || isExecutable() || isSharedLib() || isCore()) { if (isObject() || isExecutable() || isSharedLib() || isCore()) {
return ((IBinaryObject)binaryFile).isLittleEndian(); return ((IBinaryObject)getBinaryFile()).isLittleEndian();
} }
return false; return false;
} }
@ -145,7 +155,7 @@ public class Binary extends Openable implements IBinary {
boolean computeChildren(OpenableInfo info, IResource res) { boolean computeChildren(OpenableInfo info, IResource res) {
if (isObject() || isExecutable() || isSharedLib()) { if (isObject() || isExecutable() || isSharedLib()) {
Map hash = new HashMap(); Map hash = new HashMap();
ISymbol[] symbols = ((IBinaryObject)binaryFile).getSymbols(); ISymbol[] symbols = ((IBinaryObject)getBinaryFile()).getSymbols();
for (int i = 0; i < symbols.length; i++) { for (int i = 0; i < symbols.length; i++) {
switch (symbols[i].getType()) { switch (symbols[i].getType()) {
case ISymbol.FUNCTION : case ISymbol.FUNCTION :
@ -164,19 +174,18 @@ public class Binary extends Openable implements IBinary {
} }
private void addFunction(OpenableInfo info, ISymbol symbol, Map hash) { private void addFunction(OpenableInfo info, ISymbol symbol, Map hash) {
String filename = filename = symbol.getFilename(); IPath filename = filename = symbol.getFilename();
BinaryFunction function = null; BinaryFunction function = null;
// Addr2line returns the funny "??" when it can find the file. // Addr2line returns the funny "??" when it can find the file.
if (filename != null && !filename.equals("??")) { if (filename != null && !filename.equals("??")) {
BinaryModule module = null; BinaryModule module = null;
IPath path = new Path(filename); if (hash.containsKey(filename)) {
if (hash.containsKey(path)) { module = (BinaryModule)hash.get(filename);
module = (BinaryModule)hash.get(path);
} else { } else {
// A special container we do not want the file to be parse. // A special container we do not want the file to be parse.
module = new BinaryModule(this, path); module = new BinaryModule(this, filename);
hash.put(path, module); hash.put(filename, module);
info.addChild(module); info.addChild(module);
} }
function = new BinaryFunction(module, symbol.getName(), symbol.getAddress()); function = new BinaryFunction(module, symbol.getName(), symbol.getAddress());
@ -196,17 +205,16 @@ public class Binary extends Openable implements IBinary {
} }
private void addVariable(OpenableInfo info, ISymbol symbol, Map hash) { private void addVariable(OpenableInfo info, ISymbol symbol, Map hash) {
String filename = filename = symbol.getFilename(); IPath filename = filename = symbol.getFilename();
BinaryVariable variable = null; BinaryVariable variable = null;
// Addr2line returns the funny "??" when it can not find the file. // Addr2line returns the funny "??" when it can not find the file.
if (filename != null && !filename.equals("??")) { if (filename != null && !filename.equals("??")) {
BinaryModule module = null; BinaryModule module = null;
IPath path = new Path(filename); if (hash.containsKey(filename)) {
if (hash.containsKey(path)) { module = (BinaryModule)hash.get(filename);
module = (BinaryModule)hash.get(path);
} else { } else {
module = new BinaryModule(this, path); module = new BinaryModule(this, filename);
hash.put(path, module); hash.put(filename, module);
info.addChild(module); info.addChild(module);
} }
variable = new BinaryVariable(module, symbol.getName(), symbol.getAddress()); variable = new BinaryVariable(module, symbol.getName(), symbol.getAddress());

View file

@ -10,51 +10,58 @@ import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICModel; import org.eclipse.cdt.core.model.ICModel;
import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
public class BinaryRunner extends Thread { public class BinaryRunner {
ArchiveContainer clib; IProject project;
BinaryContainer cbin; Thread runner;
ICProject cproject;
CModelManager factory;
public BinaryRunner(ICProject cprj) { public BinaryRunner(IProject prj) {
super("Binary Search Thread"); project = prj;
cproject = cprj;
cbin = (BinaryContainer)cprj.getBinaryContainer();
clib = (ArchiveContainer)cprj.getArchiveContainer();
factory = CModelManager.getDefault();
start();
} }
public void start() {
runner = new Thread(new Runnable() {
public void run() { public void run() {
ICProject cproject = CModelManager.getDefault().create(project);
ArchiveContainer clib;
BinaryContainer cbin;
cbin = (BinaryContainer)cproject.getBinaryContainer();
clib = (ArchiveContainer)cproject.getArchiveContainer();
clib.removeChildren(); clib.removeChildren();
cbin.removeChildren(); cbin.removeChildren();
try { try {
cproject.getProject().accept(new Visitor(this)); cproject.getProject().accept(new Visitor(BinaryRunner.this));
} catch (CoreException e) { } catch (CoreException e) {
//e.printStackTrace(); //e.printStackTrace();
} catch (Exception e) { } catch (Exception e) {
// What is wrong ? // What is wrong ?
e.printStackTrace(); e.printStackTrace();
} }
if (!isInterrupted()) { if (!Thread.currentThread().isInterrupted()) {
fireEvents(cbin); fireEvents(cproject, cbin);
fireEvents(clib); fireEvents(cproject, clib);
} }
// Tell the listeners we are done. // Tell the listeners we are done.
synchronized(this) { synchronized(BinaryRunner.this) {
notifyAll(); BinaryRunner.this.notifyAll();
runner = null;
} }
} }
}, "Binary Search Thread");
runner.start();
}
/** /**
* wrap the wait call and the interrupteException. * wrap the wait call and the interrupteException.
*/ */
public synchronized void waitIfRunning() { public synchronized void waitIfRunning() {
while (isAlive()) { while (runner != null && runner.isAlive()) {
try { try {
wait(); wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -62,7 +69,13 @@ public class BinaryRunner extends Thread {
} }
} }
public void fireEvents(Parent container) { public void stop() {
if ( runner != null && runner.isAlive()) {
runner.interrupt();
}
}
void fireEvents(ICProject cproject, Parent container) {
// Fired the event. // Fired the event.
ICElement[] children = container.getChildren(); ICElement[] children = container.getChildren();
if (children.length > 0) { if (children.length > 0) {
@ -80,6 +93,7 @@ public class BinaryRunner extends Thread {
} }
void addChildIfBinary(IFile file) { void addChildIfBinary(IFile file) {
CModelManager factory = CModelManager.getDefault();
// Attempt to speed things up by rejecting up front // Attempt to speed things up by rejecting up front
// Things we know should not be Binary files. // Things we know should not be Binary files.
if (!factory.isTranslationUnit(file)) { if (!factory.isTranslationUnit(file)) {

View file

@ -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() { private Object[] computeNonCResources() {
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();

View file

@ -6,6 +6,7 @@ package org.eclipse.cdt.internal.core.model;
*/ */
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -98,6 +99,11 @@ public class CModelManager implements IResourceChangeListener {
*/ */
private HashMap binaryRunners = new HashMap(); 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. * The lis of the SourceMappers on projects.
*/ */
@ -188,7 +194,7 @@ public class CModelManager implements IResourceChangeListener {
case IResource.FOLDER : case IResource.FOLDER :
return create(parent, (IFolder)resource); return create(parent, (IFolder)resource);
case IResource.ROOT : case IResource.ROOT :
return create(parent, (IWorkspaceRoot)resource); return create((IWorkspaceRoot)resource);
default : default :
return null; return null;
} }
@ -345,7 +351,14 @@ public class CModelManager implements IResourceChangeListener {
public IBinaryParser getBinaryParser(IProject project) { public IBinaryParser getBinaryParser(IProject project) {
try { 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) { } catch (CoreException e) {
} }
return new NullBinaryParser(); return new NullBinaryParser();
@ -354,8 +367,22 @@ public class CModelManager implements IResourceChangeListener {
public IBinaryFile createBinaryFile(IFile file) { public IBinaryFile createBinaryFile(IFile file) {
try { try {
IBinaryParser parser = getBinaryParser(file.getProject()); 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 (IOException e) {
} catch (CoreException e) {
//e.printStackTrace();
} }
return null; return null;
} }
@ -372,6 +399,7 @@ public class CModelManager implements IResourceChangeListener {
// but it has the side of effect of removing the CProject also // but it has the side of effect of removing the CProject also
// so we have to recall create again. // so we have to recall create again.
releaseCElement(celement); releaseCElement(celement);
binaryParsersMap.remove(project);
celement = create(project); celement = create(project);
Parent parent = (Parent)celement.getParent(); Parent parent = (Parent)celement.getParent();
CElementInfo info = (CElementInfo)parent.getElementInfo(); CElementInfo info = (CElementInfo)parent.getElementInfo();
@ -504,13 +532,14 @@ public class CModelManager implements IResourceChangeListener {
return ok; return ok;
} }
public BinaryRunner getBinaryRunner(ICProject cProject) { public BinaryRunner getBinaryRunner(ICProject project) {
BinaryRunner runner = null; BinaryRunner runner = null;
synchronized(binaryRunners) { synchronized(binaryRunners) {
runner = (BinaryRunner)binaryRunners.get(cProject); runner = (BinaryRunner)binaryRunners.get(project.getProject());
if (runner == null) { if (runner == null) {
runner = new BinaryRunner(cProject); runner = new BinaryRunner(project.getProject());
binaryRunners.put(cProject, runner); binaryRunners.put(project.getProject(), runner);
runner.start();
} }
} }
return runner; return runner;
@ -729,10 +758,27 @@ public class CModelManager implements IResourceChangeListener {
} }
break; break;
case IResource.PROJECT : case IResource.PROJECT :
// TO BE COMPLETED ... if (0 != (delta.getFlags() & IResourceDelta.OPEN)) {
IProject project = (IProject) resource;
if (!project.isOpen()) {
// project closing... stop the runner.
BinaryRunner runner = (BinaryRunner)binaryRunners.get(project);
if (runner != null ) {
runner.stop();
}
} else {
if ( binaryRunners.get(project) == null ) {
// project opening... lets add the runner to the
// map but no need to start it since the deltas
// will populate containers
binaryRunners.put(project, new BinaryRunner(project));
}
}
}
break; break;
} }
} }
/** /**
* Returns the set of elements which are out of synch with their buffers. * Returns the set of elements which are out of synch with their buffers.
*/ */
@ -788,9 +834,7 @@ public class CModelManager implements IResourceChangeListener {
BinaryRunner[] runners = (BinaryRunner[])binaryRunners.values().toArray(new BinaryRunner[0]); BinaryRunner[] runners = (BinaryRunner[])binaryRunners.values().toArray(new BinaryRunner[0]);
for (int i = 0; i < runners.length; i++) { for (int i = 0; i < runners.length; i++) {
if (runners[i].isAlive()) { runners[i].stop();
runners[i].interrupt();
}
} }
} }
@ -801,5 +845,10 @@ public class CModelManager implements IResourceChangeListener {
public void deleting(IProject project){ public void deleting(IProject project){
// discard all indexing jobs for this project // discard all indexing jobs for this project
this.getIndexManager().discardJobs(project.getName()); this.getIndexManager().discardJobs(project.getName());
BinaryRunner runner = (BinaryRunner) binaryRunners.remove(project);
if (runner != null) {
runner.stop();
}
binaryParsersMap.remove(project);
} }
} }

View file

@ -28,4 +28,11 @@ public class NullBinaryParser implements IBinaryParser {
return "Null Format"; 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;
}
} }

View file

@ -1,105 +0,0 @@
package org.eclipse.cdt.internal.core.model.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.utils.elf.AR;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.PlatformObject;
/**
*/
public class ElfBinaryArchive extends PlatformObject implements IBinaryArchive {
IPath path;
ArrayList children;
long timestamp;
public ElfBinaryArchive(IPath p) throws IOException {
path = p;
new AR(path.toOSString()).dispose(); // check file type
children = new ArrayList(5);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#getObjects()
*/
public IBinaryObject[] getObjects() {
if (hasChanged()) {
children.clear();
if (path != null) {
AR ar = null;
try {
ar = new AR(path.toOSString());
AR.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
IBinaryObject bin = new ElfBinaryFile(path, headers[i]);
children.add(bin);
}
} catch (IOException e) {
//e.printStackTrace();
}
if (ar != null) {
ar.dispose();
}
}
children.trimToSize();
}
return (IBinaryObject[])children.toArray(new IBinaryObject[0]);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/
public IPath getPath() {
return path;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.ARCHIVE;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
try {
return new FileInputStream(path.toFile());
} catch (IOException e) {
}
return new ByteArrayInputStream(new byte[0]);
}
boolean hasChanged() {
long modif = path.toFile().lastModified();
boolean changed = modif != timestamp;
timestamp = modif;
return changed;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#add(IBinaryObject[])
*/
public void add(IBinaryObject[] objs) throws IOException {
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#delete(IBinaryObject[])
*/
public void delete(IBinaryObject[] objs) throws IOException {
}
}

View file

@ -1,346 +0,0 @@
package org.eclipse.cdt.internal.core.model.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.IBinaryParser.IBinaryShared;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.utils.elf.AR;
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.PlatformObject;
/**
*/
public class ElfBinaryFile extends PlatformObject implements IBinaryFile, IBinaryObject, IBinaryExecutable, IBinaryShared {
IPath path;
AR.ARHeader header;
long timestamp;
String soname;
String[] needed;
Sizes sizes;
Attribute attribute;
ArrayList symbols;
public ElfBinaryFile(IPath p) throws IOException {
this(p, null);
}
public ElfBinaryFile(IPath p, AR.ARHeader h) throws IOException {
header = h;
path = p;
loadInformation();
hasChanged();
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/
public IPath getPath() {
return path;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getBSS()
*/
public long getBSS() {
Sizes sz = getSizes();
if (sz != null) {
return sizes.bss;
}
return 0;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getCPU()
*/
public String getCPU() {
Attribute attr = getAttribute();
if (attr != null) {
return attribute.getCPU();
}
return "";
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getData()
*/
public long getData() {
Sizes sz = getSizes();
if (sz != null) {
return sizes.data;
}
return 0;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getText()
*/
public long getText() {
Sizes sz = getSizes();
if (sz != null) {
return sizes.text;
}
return 0;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryShared#getSoName()
*/
public String getSoName() {
if (hasChanged()) {
try {
loadInformation();
} catch (IOException e) {
}
}
if (soname != null) {
return soname;
}
return "";
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#hasDebug()
*/
public boolean hasDebug() {
Attribute attr = getAttribute();
if (attr != null) {
return attribute.hasDebug();
}
return false;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#isLittleEndian()
*/
public boolean isLittleEndian() {
Attribute attr = getAttribute();
if (attr != null) {
return attribute.isLittleEndian();
}
return false;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryExecutable#getNeededSharedLibs()
*/
public String[] getNeededSharedLibs() {
if (hasChanged()) {
try {
loadInformation();
} catch (IOException e) {
}
}
if (needed != null) {
return needed;
}
return new String[0];
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
int type = 0;
Attribute attr = getAttribute();
if (attr != null) {
switch (attribute.getType()) {
case Attribute.ELF_TYPE_EXE :
type = IBinaryFile.EXECUTABLE;
break;
case Attribute.ELF_TYPE_SHLIB :
type = IBinaryFile.SHARED;
break;
case Attribute.ELF_TYPE_OBJ :
type = IBinaryFile.OBJECT;
break;
case Attribute.ELF_TYPE_CORE :
type = IBinaryFile.CORE;
break;
}
}
return type;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getSymbols()
*/
public ISymbol[] getSymbols() {
if (hasChanged() || symbols == null) {
if (symbols == null) {
symbols = new ArrayList(5);
}
try {
loadInformation();
} catch (IOException e) {
}
}
return (ISymbol[]) symbols.toArray(new ISymbol[0]);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
InputStream stream = null;
// Archive ?
if (path != null && header != null) {
try {
stream = new ByteArrayInputStream(header.getObjectData());
} catch (IOException e) {
}
} else if (path != null) {
try {
stream = new FileInputStream(path.toFile());
} catch (IOException e) {
}
}
if (stream == null) {
stream = new ByteArrayInputStream(new byte[0]);
}
return stream;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName()
*/
public String getName() {
if (header != null) {
return header.getObjectName();
}
if (path != null) {
return path.lastSegment().toString();
}
return "";
}
public String toString() {
return getName();
}
protected Attribute getAttribute() {
if (hasChanged()) {
try {
loadInformation();
} catch (IOException e) {
}
}
return attribute;
}
protected Sizes getSizes() {
if (hasChanged()) {
try {
loadInformation();
} catch (IOException e) {
}
}
return sizes;
}
boolean hasChanged() {
long modification = path.toFile().lastModified();
boolean changed = modification != timestamp;
timestamp = modification;
return changed;
}
protected ElfHelper getElfHelper() throws IOException {
// Archive ?
if (header != null) {
return new ElfHelper(header.getElf());
} else if (path != null) {
return new ElfHelper(path.toOSString());
}
throw new IOException("No file assiocated with Binary");
}
protected void loadInformation() throws IOException {
ElfHelper helper = null;
try {
helper = getElfHelper();
loadInformation(helper);
} finally {
if (helper != null) {
helper.dispose();
}
}
}
private void loadInformation(ElfHelper helper) throws IOException {
loadAttributes(helper);
if (symbols != null) {
symbols.clear();
loadSymbols(helper);
symbols.trimToSize();
}
}
private void loadAttributes(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();
}
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();
addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION);
addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION);
addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE);
addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE);
symbols.trimToSize();
}
private void addSymbols(Elf.Symbol[] array, int type) {
for (int i = 0; i < array.length; i++) {
Symbol sym = new Symbol();
sym.type = type;
sym.name = array[i].toString();
sym.addr = array[i].st_value;
try {
// This can fail if we use addr2line
// but we can safely ignore the error.
if (header == null) {
sym.filename = array[i].getFilename();
sym.startLine = array[i].getFuncLineNumber();
sym.endLine = sym.startLine;
}
} catch (IOException e) {
//e.printStackTrace();
}
symbols.add(sym);
}
}
}

View file

@ -1,42 +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.internal.core.model.parser; package org.eclipse.cdt.internal.core.model.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.IOException;
import org.eclipse.cdt.core.AbstractCExtension;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/** /**
* Implementation moved to org.eclipse.cdt.utils.elf.parser.ElfParser
* But this class is still provided for backward compatibility.
*/ */
public class ElfParser extends AbstractCExtension implements IBinaryParser { public class ElfParser extends org.eclipse.cdt.utils.elf.parser.ElfParser {
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IPath)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
if (path == null ) {
path = new Path("");
}
IBinaryFile bFile;
try {
bFile = new ElfBinaryFile(path);
} catch (IOException e) {
bFile = new ElfBinaryArchive(path);
}
return bFile;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getFormat()
*/
public String getFormat() {
return "ELF";
}
} }

View file

@ -1,109 +0,0 @@
package org.eclipse.cdt.internal.core.model.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.utils.coff.PEArchive;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.PlatformObject;
/**
*/
public class PEBinaryArchive extends PlatformObject implements IBinaryArchive {
IPath path;
ArrayList children;
long timestamp;
public PEBinaryArchive(IPath p) {
path = p;
children = new ArrayList(5);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#getObjects()
*/
public IBinaryObject[] getObjects() {
if (hasChanged()) {
children.clear();
if (path != null) {
PEArchive ar = null;
try {
ar = new PEArchive(path.toOSString());
PEArchive.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
IBinaryObject bin = new PEBinaryFile(path, headers[i].getObjectName());
children.add(bin);
}
} catch (IOException e) {
//e.printStackTrace();
}
if (ar != null) {
ar.dispose();
}
}
children.trimToSize();
}
return (IBinaryObject[])children.toArray(new IBinaryObject[0]);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/
public IPath getPath() {
return path;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
return IBinaryFile.ARCHIVE;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
try {
return new FileInputStream(path.toFile());
} catch (IOException e) {
}
return new ByteArrayInputStream(new byte[0]);
}
boolean hasChanged() {
File file = path.toFile();
if (file != null && file.exists()) {
long modification = file.lastModified();
boolean changed = modification != timestamp;
timestamp = modification;
return changed;
}
return false;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#add(IBinaryObject[])
*/
public void add(IBinaryObject[] objs) throws IOException {
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#delete(IBinaryObject[])
*/
public void delete(IBinaryObject[] objs) throws IOException {
}
}

View file

@ -1,304 +0,0 @@
package org.eclipse.cdt.internal.core.model.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.IBinaryParser.IBinaryShared;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.utils.coff.Coff;
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;
import org.eclipse.core.runtime.PlatformObject;
/**
*/
public class PEBinaryFile extends PlatformObject implements IBinaryFile,
IBinaryObject, IBinaryExecutable, IBinaryShared {
IPath path;
long timestamp;
PE.Attribute attribute;
String objectName;
ArrayList symbols;
public PEBinaryFile(IPath p) throws IOException {
this(p, null);
}
public PEBinaryFile(IPath p, String o) throws IOException {
path = p;
objectName = o;
loadInformation();
hasChanged();
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
InputStream stream = null;
if (path != null && objectName != null) {
PEArchive ar = null;
try {
ar = new PEArchive(path.toOSString());
PEArchive.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
PEArchive.ARHeader hdr = headers[i];
if (objectName.equals(hdr.getObjectName())) {
stream = new ByteArrayInputStream(hdr.getObjectData());
break;
}
}
} catch (IOException e) {
} finally {
if (ar != null) {
ar.dispose();
}
}
} else if (path != null) {
try {
stream = new FileInputStream (path.toFile());
} catch (IOException e) {
}
}
if (stream == null) {
stream = new ByteArrayInputStream(new byte[0]);
}
return stream;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/
public IPath getPath() {
return path;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
*/
public int getType() {
int type = 0;
Attribute attr = getAttribute();
if (attr != null) {
switch (attribute.getType()) {
case Attribute.PE_TYPE_EXE:
type = IBinaryFile.EXECUTABLE;
break;
case Attribute.PE_TYPE_SHLIB:
type = IBinaryFile.SHARED;
break;
case Attribute.PE_TYPE_OBJ:
type = IBinaryFile.OBJECT;
break;
case Attribute.PE_TYPE_CORE:
type = IBinaryFile.CORE;
break;
}
}
return type;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getBSS()
*/
public long getBSS() {
return 0;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getCPU()
*/
public String getCPU() {
Attribute attr = getAttribute();
if (attr != null) {
return attribute.getCPU();
}
return "";
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getData()
*/
public long getData() {
return 0;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName()
*/
public String getName() {
if (objectName != null) {
return objectName;
} else if (path != null) {
return path.lastSegment().toString();
}
return "";
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getSymbols()
*/
public ISymbol[] getSymbols() {
if (hasChanged() || symbols == null) {
if (symbols == null) {
symbols = new ArrayList(5);
}
try {
loadInformation();
} catch (IOException e) {
}
}
return (ISymbol[])symbols.toArray(new ISymbol[0]);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getText()
*/
public long getText() {
return 0;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#hasDebug()
*/
public boolean hasDebug() {
Attribute attr = getAttribute();
if (attr != null) {
return attr.hasDebug();
}
return false;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#isLittleEndian()
*/
public boolean isLittleEndian() {
Attribute attr = getAttribute();
if (attr != null) {
return attr.isLittleEndian();
}
return false;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryExecutable#getNeededSharedLibs()
*/
public String[] getNeededSharedLibs() {
return new String[0];
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryShared#getSoName()
*/
public String getSoName() {
return "";
}
protected PE getPE() throws IOException {
if (path != null && objectName != null) {
PE pe = null;
PEArchive ar = null;
try {
ar = new PEArchive(path.toOSString());
PEArchive.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) {
PEArchive.ARHeader hdr = headers[i];
if (objectName.equals(hdr.getObjectName())) {
pe = hdr.getPE();
break;
}
}
} finally {
if (ar != null) {
ar.dispose();
}
}
if (pe != null) {
return pe;
}
} else if (path != null) {
return new PE(path.toOSString());
}
throw new IOException("No file assiocated with Binary");
}
protected PE.Attribute getAttribute() {
if (hasChanged()) {
try {
loadInformation();
} catch (IOException e) {
}
}
return attribute;
}
protected void loadInformation() throws IOException {
PE pe = getPE();
loadInformation(pe);
pe.dispose();
}
private void loadInformation(PE pe) throws IOException {
loadAttribute(pe);
if (symbols != null) {
symbols.clear();
loadSymbols(pe);
symbols.trimToSize();
}
}
private void loadAttribute(PE pe) throws IOException {
attribute = pe.getAttribute();
}
private void loadSymbols(PE pe) throws IOException {
Coff.Symbol[] peSyms = pe.getSymbols();
byte[] table = pe.getStringTable();
for (int i = 0; i < peSyms.length; i++) {
if (peSyms[i].isFunction() || peSyms[i].isPointer() ||peSyms[i].isArray()) {
String name = peSyms[i].getName(table);
if (name == null || name.trim().length() == 0 ||
!Character.isJavaIdentifierStart(name.charAt(0))) {
continue;
}
Symbol sym = new Symbol();
sym.filename = null;
sym.name = name;
sym.addr = peSyms[i].n_value;
sym.startLine = 0;
sym.endLine = 0;
sym.type = peSyms[i].isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE;
symbols.add(sym);
}
}
}
boolean hasChanged() {
File file = path.toFile();
if (file != null && file.exists()) {
long modification = file.lastModified();
boolean changed = modification != timestamp;
timestamp = modification;
return changed;
}
return false;
}
}

View file

@ -5,43 +5,10 @@ package org.eclipse.cdt.internal.core.model.parser;
* All Rights Reserved. * All Rights Reserved.
*/ */
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.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/** /**
* Implementation moved to org.eclipse.cdt.utils.coff.parser.PEParser
* But this class is still provided for backward compatibility.
*/ */
public class PEParser extends AbstractCExtension implements IBinaryParser { public class PEParser extends org.eclipse.cdt.utils.coff.parser.PEParser {
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getBinary(IFile)
*/
public IBinaryFile getBinary(IPath path) throws IOException {
if (path == null) {
path = new Path("");
}
try {
PE pe = new PE(path.toOSString());
pe.dispose();
return new PEBinaryFile(path);
} catch (IOException e) {
}
// Is it an Archive.
PEArchive ar = new PEArchive(path.toOSString());
ar.dispose();
return new PEBinaryArchive(path);
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser#getFormat()
*/
public String getFormat() {
return "PE";
}
} }

View file

@ -1,62 +0,0 @@
package org.eclipse.cdt.internal.core.model.parser;
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
public class Symbol implements ISymbol {
public String filename;
public int startLine;
public int endLine;
public long addr;
public String name;
public int type;
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getFilename()
*/
public String getFilename() {
return filename;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getName()
*/
public String getName() {
return name;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getType()
*/
public int getType() {
return type;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.ISymbol#getAdress()
*/
public long getAddress() {
return addr;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.ISymbol#getEndLine()
*/
public int getEndLine() {
return endLine;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.ISymbol#getStartLine()
*/
public int getStartLine() {
return startLine;
}
}

View file

@ -56,6 +56,8 @@ public interface IBinaryParser {
ISymbol[] getSymbols(); ISymbol[] getSymbols();
ISymbol getSymbol(long addr);
String getName(); String getName();
} }
@ -74,7 +76,7 @@ public interface IBinaryParser {
String getSoName(); String getSoName();
} }
interface ISymbol { interface ISymbol extends Comparable {
static final int FUNCTION = 0x01; static final int FUNCTION = 0x01;
static final int VARIABLE = 0x02; static final int VARIABLE = 0x02;
@ -82,11 +84,13 @@ public interface IBinaryParser {
long getAddress(); long getAddress();
int getStartLine(); int getStartLine();
int getEndLine(); int getEndLine();
String getFilename(); IPath getFilename();
int getType(); int getType();
} }
IBinaryFile getBinary(IPath path) throws IOException; IBinaryFile getBinary(IPath path) throws IOException;
boolean isBinary(byte[] array, IPath path);
String getFormat(); String getFormat();
} }

View file

@ -54,25 +54,29 @@ public class GCCErrorParser implements IErrorParser {
if (firstColon != -1) { if (firstColon != -1) {
try { try {
int secondColon= line.indexOf(':', firstColon + 1); int secondColon = -1;
if (secondColon != -1) {
String fileName = line.substring(0, firstColon);
String lineNumber = line.substring(firstColon + 1, secondColon);
String varName = null;
String desc = line.substring(secondColon + 1).trim();
int severity = IMarkerGenerator.SEVERITY_ERROR_RESOURCE;
int num = -1; int num = -1;
int col = -1;
while ((secondColon = line.indexOf(':', firstColon + 1)) != -1) {
String lineNumber = line.substring(firstColon + 1, secondColon);
try { try {
num = Integer.parseInt(lineNumber); num = Integer.parseInt(lineNumber);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
// Failed.
}
if (num != -1) {
break; // Find possible match.
}
firstColon = secondColon;
} }
if (num == -1) { if (secondColon != -1) {
// Bail out not recognizable format. i.e. no line numbers int col = -1;
return false;
} else { String fileName = line.substring(0, firstColon);
String varName = null;
String desc = line.substring(secondColon + 1).trim();
int severity = IMarkerGenerator.SEVERITY_ERROR_RESOURCE;
/* Then check for the column */ /* Then check for the column */
int thirdColon= line.indexOf(':', secondColon + 1); int thirdColon= line.indexOf(':', secondColon + 1);
if (thirdColon != -1) { if (thirdColon != -1) {
@ -85,7 +89,6 @@ public class GCCErrorParser implements IErrorParser {
if (col != -1) { if (col != -1) {
desc = line.substring(thirdColon + 1).trim(); desc = line.substring(thirdColon + 1).trim();
} }
}
// gnu c: filename:no: (Each undeclared identifier is reported // gnu c: filename:no: (Each undeclared identifier is reported
// only once. filename:no: for each function it appears in.) // only once. filename:no: for each function it appears in.)
@ -103,9 +106,11 @@ public class GCCErrorParser implements IErrorParser {
/* See if we can get a var name /* See if we can get a var name
* Look for: * Look for:
* 'foo' undeclared * `foo' undeclared
* 'foo' defined but not used * `foo' defined but not used
* conflicting types for 'foo' * conflicting types for `foo'
* previous declaration of `foo'
* parse error before `foo'
* *
*/ */
int s; int s;
@ -141,26 +146,43 @@ public class GCCErrorParser implements IErrorParser {
} }
} }
/*
* In file included from b.h:2,
* from a.h:3,
* from hello.c:3:
* c.h:2:15: missing ')' in macro parameter list
*
* We reconstruct the multiline gcc errors to multiple errors:
* c.h:3:15: missing ')' in macro parameter list
* b.h:2: in inclusion c.h:3:15
* a.h:3: in inclusion b.h:2
* hello.c:3: in inclusion a.h:3
*
*/
if (eoParser.getScratchBuffer().startsWith("In file included from ")) { if (eoParser.getScratchBuffer().startsWith("In file included from ")) {
if (line.startsWith("from ")) { if (line.startsWith("from ")) {
// We want the last error in the chain, so continue.
eoParser.appendToScratchBuffer(line); eoParser.appendToScratchBuffer(line);
return false; return false;
} }
String buffer = eoParser.getScratchBuffer(); String buffer = eoParser.getScratchBuffer();
eoParser.clearScratchBuffer(); eoParser.clearScratchBuffer();
int from = -1; int from = -1;
while ((from = buffer.lastIndexOf("from ")) != -1) { String inclusionError = fileName + ":" + num;
String buf = buffer.substring(from + 5); while ((from = buffer.indexOf("from ")) != -1) {
buffer = buffer.substring(0, from); int coma = buffer.indexOf(',', from);
if (buf.endsWith(",")) { String buf;
int coma = buf.lastIndexOf(','); if (coma != -1) {
StringBuffer b = new StringBuffer(buf); buf = buffer.substring(from + 5, coma) + ':';
b.setCharAt(coma, ':'); buffer = buffer.substring(coma);
b.append(' ').append(buffer).append(" from ").append(line);
buf = b.toString();
} else { } else {
buf = buf + ' ' + buffer + " from " + line; buf = buffer.substring(from + 5);
buffer = "";
} }
String t = buf;
buf += " in inclusion " + inclusionError;
inclusionError = t;
// Call the parsing process again.
processLine(buf, eoParser); processLine(buf, eoParser);
} }
} }
@ -196,6 +218,7 @@ public class GCCErrorParser implements IErrorParser {
if (file == null) { if (file == null) {
desc = desc +"[" + fileName + "]"; desc = desc +"[" + fileName + "]";
} }
eoParser.generateMarker(file, num, desc, severity, varName); eoParser.generateMarker(file, num, desc, severity, varName);
} else { } else {
if (line.startsWith("In file included from ")) { if (line.startsWith("In file included from ")) {

View file

@ -19,13 +19,17 @@ public class Addr2line {
private BufferedWriter stdin; private BufferedWriter stdin;
private String lastaddr, lastsymbol, lastline; private String lastaddr, lastsymbol, lastline;
public Addr2line(String file) throws IOException { public Addr2line(String command, String file) throws IOException {
String[] args = {"addr2line", "-C", "-f", "-e", file}; String[] args = {command, "-C", "-f", "-e", file};
addr2line = ProcessFactory.getFactory().exec(args); addr2line = ProcessFactory.getFactory().exec(args);
stdin = new BufferedWriter(new OutputStreamWriter(addr2line.getOutputStream())); stdin = new BufferedWriter(new OutputStreamWriter(addr2line.getOutputStream()));
stdout = new BufferedReader(new InputStreamReader(addr2line.getInputStream())); stdout = new BufferedReader(new InputStreamReader(addr2line.getInputStream()));
} }
public Addr2line(String file) throws IOException {
this("addr2line", file);
}
private void getOutput(String address) throws IOException { private void getOutput(String address) throws IOException {
if ( address.equals(lastaddr) == false ) { if ( address.equals(lastaddr) == false ) {
stdin.write(address + "\n"); stdin.write(address + "\n");
@ -46,14 +50,62 @@ public class Addr2line {
return lastsymbol; return lastsymbol;
} }
/**
* The format of the output:
* addr2line -C -f -e hello
* 08048442
* main
* hello.c:39
*/
public String getFileName(long address) throws IOException {
String filename = null;
String line = getLine(address);
int index1, index2;
if (line != null && (index1 = line.lastIndexOf(':')) != -1) {
// we do this because addr2line on win produces
// <cygdrive/pathtoexc/C:/pathtofile:##>
index2 = line.indexOf(':');
if (index1 == index2) {
index2 = 0;
} else {
index2--;
}
filename = line.substring(index2, index1);
}
return filename;
}
/**
* The format of the output:
* addr2line -C -f -e hello
* 08048442
* main
* hello.c:39
*/
public int getLineNumber(long address) throws IOException {
// We try to get the nearest match
// since the symbol may not exactly align with debug info.
// In C line number 0 is invalid, line starts at 1 for file, we use
// this for validation.
for (int i = 0; i <= 20; i += 4, address += i) {
String line = getLine(address);
if (line != null) {
int colon = line.lastIndexOf(':');
String number = line.substring(colon + 1);
if (!number.startsWith("0")) {
return Integer.parseInt(number);
}
}
}
return -1;
}
public void dispose() { public void dispose() {
try { try {
//stdin.write(-1);
stdout.close(); stdout.close();
stdin.close(); stdin.close();
addr2line.getErrorStream().close(); addr2line.getErrorStream().close();
} } catch (IOException e) {
catch (IOException e) {
} }
addr2line.destroy(); addr2line.destroy();
} }

View file

@ -18,14 +18,18 @@ public class CPPFilt {
private BufferedReader stdout; private BufferedReader stdout;
private BufferedWriter stdin; private BufferedWriter stdin;
public CPPFilt() throws IOException { public CPPFilt(String command) throws IOException {
String[] args = {"c++filt"}; String[] args = {command};
cppfilt = ProcessFactory.getFactory().exec(args); cppfilt = ProcessFactory.getFactory().exec(args);
//cppfilt = new Spawner(args); //cppfilt = new Spawner(args);
stdin = new BufferedWriter(new OutputStreamWriter(cppfilt.getOutputStream())); stdin = new BufferedWriter(new OutputStreamWriter(cppfilt.getOutputStream()));
stdout = new BufferedReader(new InputStreamReader(cppfilt.getInputStream())); stdout = new BufferedReader(new InputStreamReader(cppfilt.getInputStream()));
} }
public CPPFilt() throws IOException {
this("c++filt");
}
public String getFunction(String symbol) throws IOException { public String getFunction(String symbol) throws IOException {
stdin.write(symbol + "\n"); stdin.write(symbol + "\n");
stdin.flush(); stdin.flush();

View file

@ -267,7 +267,7 @@ public class Coff {
buffer.append("s_nreloc = ").append(s_nreloc).append(NL); buffer.append("s_nreloc = ").append(s_nreloc).append(NL);
buffer.append("s_nlnno = ").append(s_nlnno).append(NL); buffer.append("s_nlnno = ").append(s_nlnno).append(NL);
buffer.append("s_flags = ").append(s_flags).append(NL); buffer.append("s_flags = ").append(s_flags).append(NL);
/* ///*
try { try {
Reloc[] rcs = getRelocs(); Reloc[] rcs = getRelocs();
for (int i = 0; i < rcs.length; i++) { for (int i = 0; i < rcs.length; i++) {
@ -282,7 +282,7 @@ public class Coff {
} }
} catch (IOException e) { } catch (IOException e) {
} }
*/ //*/
return buffer.toString(); return buffer.toString();
} }
} }
@ -406,8 +406,10 @@ public class Coff {
public String getName(byte[] table) { public String getName(byte[] table) {
if (table.length > 0 && isLongName()) { if (table.length > 0 && isLongName()) {
ReadMemoryAccess memory = new ReadMemoryAccess(_n_name, true); ReadMemoryAccess memory = new ReadMemoryAccess(_n_name, true);
memory.getInt(); memory.getInt(); // pass over the first 4 bytes.
int offset = memory.getInt(); // The first for bytes of the string table represent the
// number of bytes in the string table.
int offset = memory.getInt() - 4;
if (offset > 0) { if (offset > 0) {
for (int i = offset; i < table.length; i++) { for (int i = offset; i < table.length; i++) {
if (table[i] == 0) { if (table[i] == 0) {

View file

@ -438,6 +438,20 @@ public class PE {
return attrib; 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();
pe.dispose();
return attrib;
}
public void dispose() throws IOException { public void dispose() throws IOException {
if (rfile != null) { if (rfile != null) {
rfile.close(); rfile.close();
@ -491,7 +505,6 @@ public class PE {
int size = memory.getInt(); int size = memory.getInt();
dataDirectories[i] = new ImageDataDirectory(rva, size); dataDirectories[i] = new ImageDataDirectory(rva, size);
} }
dispose();
} }
return dataDirectories; return dataDirectories;
} }
@ -507,7 +520,6 @@ public class PE {
for (int i = 0; i < scnhdrs.length; i++, offset += SectionHeader.SCNHSZ) { for (int i = 0; i < scnhdrs.length; i++, offset += SectionHeader.SCNHSZ) {
scnhdrs[i] = new SectionHeader(accessFile, offset); scnhdrs[i] = new SectionHeader(accessFile, offset);
} }
dispose();
} }
return scnhdrs; return scnhdrs;
} }
@ -519,8 +531,11 @@ public class PE {
symbolTable = new Symbol[fileHeader.f_nsyms]; symbolTable = new Symbol[fileHeader.f_nsyms];
for (int i = 0; i < symbolTable.length; i++, offset += Symbol.SYMSZ) { for (int i = 0; i < symbolTable.length; i++, offset += Symbol.SYMSZ) {
symbolTable[i] = new Symbol(accessFile, offset); symbolTable[i] = new Symbol(accessFile, offset);
NTOptionalHeader ntHeader = getNTOptionalHeader();
// FIXME: What is this again ?
if (ntHeader != null)
symbolTable[i].n_value += ntHeader.ImageBase + ntHeader.FileAlignment;
} }
dispose();
} }
return symbolTable; return symbolTable;
} }
@ -543,7 +558,6 @@ public class PE {
} else { } else {
stringTable = new byte[0]; stringTable = new byte[0];
} }
dispose();
} else { } else {
stringTable = new byte[0]; stringTable = new byte[0];
} }

View file

@ -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 <code>AR</code> object from the contents of * Creates a new <code>AR</code> object from the contents of
* the given file. * the given file.

View file

@ -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 <code>AR</code> object from the contents of * Creates a new <code>AR</code> object from the contents of
* the given file. * the given file.

View file

@ -707,6 +707,13 @@ public class Elf {
return attrib; 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() { public void dispose() {
if (addr2line != null) { if (addr2line != null) {
addr2line.dispose(); addr2line.dispose();

View file

@ -1,14 +1,23 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; 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.AR;
import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.Elf;
import org.eclipse.cdt.utils.elf.ElfHelper; import org.eclipse.cdt.utils.elf.ElfHelper;
@ -19,8 +28,8 @@ import org.eclipse.core.runtime.IPath;
public class ARMember extends BinaryObject { public class ARMember extends BinaryObject {
AR.ARHeader header; AR.ARHeader header;
public ARMember(IPath p, AR.ARHeader h) throws IOException { public ARMember(IPath p, AR.ARHeader h, IToolsProvider provider) throws IOException {
super(p); super(p, new ElfHelper(h.getElf()), provider);
header = h; header = h;
} }
@ -58,15 +67,13 @@ public class ARMember extends BinaryObject {
throw new IOException("No file assiocated with Binary"); throw new IOException("No file assiocated with Binary");
} }
protected void addSymbols(Elf.Symbol[] array, int type) { protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt, List list) {
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
Symbol sym = new Symbol(); Symbol sym = new Symbol(this);
sym.type = type; sym.type = type;
sym.name = array[i].toString(); sym.name = array[i].toString();
sym.addr = array[i].st_value; sym.addr = array[i].st_value;
addSymbol(sym); list.add(sym);
// This can fail if we use addr2line
// but we can safely ignore the error.
} }
} }

View file

@ -1,34 +1,35 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive; import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.utils.elf.AR; import org.eclipse.cdt.utils.elf.AR;
import org.eclipse.cdt.utils.elf.Elf.Attribute;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.PlatformObject;
/** /**
*/ */
public class BinaryArchive extends PlatformObject implements IBinaryArchive { public class BinaryArchive extends BinaryFile implements IBinaryArchive {
IPath path;
ArrayList children; ArrayList children;
long timestamp; long timestamp;
public BinaryArchive(IPath p) throws IOException { public BinaryArchive(IPath p) throws IOException {
path = p; super(p);
new AR(path.toOSString()).dispose(); // check file type new AR(p.toOSString()).dispose(); // check file type
children = new ArrayList(5); children = new ArrayList(5);
} }
@ -38,13 +39,12 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
public IBinaryObject[] getObjects() { public IBinaryObject[] getObjects() {
if (hasChanged()) { if (hasChanged()) {
children.clear(); children.clear();
if (path != null) {
AR ar = null; AR ar = null;
try { try {
ar = new AR(path.toOSString()); ar = new AR(getPath().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 ARMember(path, headers[i]); IBinaryObject bin = new ARMember(getPath(), headers[i], toolsProvider);
children.add(bin); children.add(bin);
} }
} catch (IOException e) { } catch (IOException e) {
@ -53,19 +53,11 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
if (ar != null) { if (ar != null) {
ar.dispose(); ar.dispose();
} }
}
children.trimToSize(); children.trimToSize();
} }
return (IBinaryObject[]) children.toArray(new IBinaryObject[0]); return (IBinaryObject[]) children.toArray(new IBinaryObject[0]);
} }
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
*/
public IPath getPath() {
return path;
}
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType() * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
*/ */
@ -73,23 +65,6 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
return IBinaryFile.ARCHIVE; return IBinaryFile.ARCHIVE;
} }
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
try {
return new FileInputStream(path.toFile());
} catch (IOException e) {
}
return new ByteArrayInputStream(new byte[0]);
}
boolean hasChanged() {
long modif = path.toFile().lastModified();
boolean changed = modif != timestamp;
timestamp = modif;
return changed;
}
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#add(IBinaryObject[]) * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#add(IBinaryObject[])
*/ */
@ -102,4 +77,11 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
public void delete(IBinaryObject[] objs) throws IOException { public void delete(IBinaryObject[] objs) throws IOException {
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.utils.elf.parser.BinaryFile#getAttribute()
*/
protected Attribute getAttribute() {
return null;
}
} }

View file

@ -1,28 +1,24 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable; import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
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.IPath;
/** /**
*/ */
public class BinaryExecutable extends BinaryObject implements IBinaryExecutable { public class BinaryExecutable extends BinaryObject implements IBinaryExecutable {
long timestamp;
String soname;
String[] needed;
Sizes sizes;
Attribute attribute;
ArrayList symbols;
public BinaryExecutable(IPath path) throws IOException { public BinaryExecutable(IPath path) throws IOException {
super(path); super(path);

View file

@ -1,34 +1,57 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.utils.*;
import org.eclipse.cdt.utils.Addr2line;
import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.cdt.utils.elf.Elf.Attribute; import org.eclipse.cdt.utils.elf.Elf.Attribute;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.PlatformObject;
/** /**
*
*/ */
public abstract class BinaryFile extends PlatformObject implements IBinaryFile { public abstract class BinaryFile extends PlatformObject implements IBinaryFile {
protected IPath path; protected IPath path;
protected IToolsProvider toolsProvider;
protected long timestamp;
public BinaryFile(IPath p) { public BinaryFile(IPath p) {
path = p; path = p;
} }
/** public void setToolsProvider(IToolsProvider p) {
* @return toolsProvider = p;
*/ }
protected abstract Attribute getAttribute();
public Addr2line getAddr2Line() {
if (toolsProvider != null)
return toolsProvider.getAddr2Line(path);
return null;
}
public CPPFilt getCPPFilt() {
if (toolsProvider != null)
return toolsProvider.getCPPFilt();
return null;
}
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile() * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
@ -59,4 +82,16 @@ public abstract class BinaryFile extends PlatformObject implements IBinaryFile {
return stream; return stream;
} }
/**
* @return
*/
protected abstract Attribute getAttribute();
protected boolean hasChanged() {
long modification = getPath().toFile().lastModified();
boolean changed = modification != timestamp;
timestamp = modification;
return changed;
}
} }

View file

@ -1,22 +1,32 @@
/* /**********************************************************************
* (c) Copyright IBM Corp. 2000, 2001. * Copyright (c) 2002,2003 QNX Software Systems and others.
* All Rights Reserved. * 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; 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.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.IBinaryParser.ISymbol; 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.Elf;
import org.eclipse.cdt.utils.elf.ElfHelper; import org.eclipse.cdt.utils.elf.ElfHelper;
import org.eclipse.cdt.utils.elf.Elf.Attribute; import org.eclipse.cdt.utils.elf.Elf.Attribute;
import org.eclipse.cdt.utils.elf.ElfHelper.Sizes; import org.eclipse.cdt.utils.elf.ElfHelper.Sizes;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/** /**
*/ */
@ -24,18 +34,35 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
protected String soname; protected String soname;
protected String[] needed; protected String[] needed;
protected int type = IBinaryFile.OBJECT; protected int type = IBinaryFile.OBJECT;
private long timestamp;
private Sizes sizes; private Sizes sizes;
private Attribute attribute; private Attribute attribute;
private ArrayList symbols; private ISymbol[] symbols;
private ISymbol[] NO_SYMBOLS = new ISymbol[0];
public BinaryObject(IPath path) throws IOException { public BinaryObject(IPath path) throws IOException {
super(path); super(path);
loadInformation(); }
public BinaryObject(IPath path, ElfHelper helper, IToolsProvider provider) throws IOException {
super(path);
setToolsProvider(provider);
loadInformation(helper);
helper.dispose();
hasChanged(); 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() * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getBSS()
*/ */
@ -112,47 +139,28 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
public void setType(int t) { public void setType(int t) {
type = t; type = t;
} }
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getSymbols() * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getSymbols()
*/ */
public ISymbol[] getSymbols() { public ISymbol[] getSymbols() {
if (hasChanged() || symbols == null) { if (hasChanged() || symbols == null) {
if (symbols == null) {
symbols = new ArrayList(5);
}
try { try {
loadInformation(); loadInformation();
} catch (IOException e) { } catch (IOException e) {
} }
} if (symbols == null) {
return (ISymbol[]) symbols.toArray(new ISymbol[0]); symbols = NO_SYMBOLS;
}
/**
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
*/
public InputStream getContents() {
InputStream stream = null;
if (path != null) {
try {
stream = new FileInputStream(path.toFile());
} catch (IOException e) {
} }
} }
if (stream == null) { return symbols;
stream = super.getContents();
}
return stream;
} }
/** /**
* @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 (path != null) { return getPath().lastSegment().toString();
return path.lastSegment().toString();
}
return "";
} }
public String toString() { public String toString() {
@ -179,18 +187,8 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
return sizes; return sizes;
} }
boolean hasChanged() {
long modification = path.toFile().lastModified();
boolean changed = modification != timestamp;
timestamp = modification;
return changed;
}
protected ElfHelper getElfHelper() throws IOException { protected ElfHelper getElfHelper() throws IOException {
if (path != null) { return new ElfHelper(getPath().toOSString());
return new ElfHelper(path.toOSString());
}
throw new IOException("No file assiocated with Binary");
} }
protected void loadInformation() throws IOException { protected void loadInformation() throws IOException {
@ -207,11 +205,7 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
private void loadInformation(ElfHelper helper) throws IOException { private void loadInformation(ElfHelper helper) throws IOException {
loadAttributes(helper); loadAttributes(helper);
if (symbols != null) {
symbols.clear();
loadSymbols(helper); loadSymbols(helper);
symbols.trimToSize();
}
} }
private void loadAttributes(ElfHelper helper) throws IOException { private void loadAttributes(ElfHelper helper) throws IOException {
@ -226,43 +220,57 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
} }
private void loadSymbols(ElfHelper helper) throws IOException { private void loadSymbols(ElfHelper helper) throws IOException {
Elf.Dynamic[] sharedlibs = helper.getNeeded(); ArrayList list = new ArrayList();
needed = new String[sharedlibs.length]; // Hack should be remove when Elf is clean
for (int i = 0; i < sharedlibs.length; i++) { helper.getElf().setCppFilter(false);
needed[i] = sharedlibs[i].toString();
}
sizes = helper.getSizes();
soname = helper.getSoname();
attribute = helper.getElf().getAttributes();
addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION); Addr2line addr2line = getAddr2Line();
addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION); CPPFilt cppfilt = getCPPFilt();
addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE);
addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE); addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, addr2line, cppfilt, list);
symbols.trimToSize(); 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();
}
if (cppfilt != null) {
cppfilt.dispose();
} }
protected void addSymbols(Elf.Symbol[] array, int type) { symbols = (ISymbol[])list.toArray(NO_SYMBOLS);
Arrays.sort(symbols);
list.clear();
}
protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt, List list) {
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
Symbol sym = new Symbol(); Symbol sym = new Symbol(this);
sym.type = type; sym.type = type;
sym.name = array[i].toString(); sym.name = array[i].toString();
sym.addr = array[i].st_value; if (cppfilt != null) {
try { try {
// This can fail if we use addr2line sym.name = cppfilt.getFunction(sym.name);
// but we can safely ignore the error. } catch (IOException e1) {
sym.filename = array[i].getFilename(); }
sym.startLine = array[i].getFuncLineNumber(); }
sym.addr = array[i].st_value;
sym.filename = null;
sym.startLine = 0;
sym.endLine = sym.startLine; sym.endLine = sym.startLine;
if (addr2line != null) {
try {
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) { } catch (IOException e) {
//e.printStackTrace();
}
addSymbol(sym);
} }
} }
list.add(sym);
protected void addSymbol(Symbol sym) { }
symbols.add(sym);
} }
} }

View file

@ -1,10 +1,15 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.IOException; import java.io.IOException;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
@ -14,7 +19,6 @@ import org.eclipse.core.runtime.IPath;
/** /**
*/ */
public class BinaryShared extends BinaryExecutable implements IBinaryShared { public class BinaryShared extends BinaryExecutable implements IBinaryShared {
String soname;
public BinaryShared(IPath path) throws IOException { public BinaryShared(IPath path) throws IOException {
super(path); super(path);

View file

@ -1,58 +1,36 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.IOException; import java.io.IOException;
import org.eclipse.cdt.core.AbstractCExtension;
import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.ICExtensionReference; import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.cdt.internal.core.model.parser.ElfBinaryArchive; import org.eclipse.cdt.utils.*;
import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.Addr2line;
import org.eclipse.cdt.utils.elf.Elf.Attribute; import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Path;
/** /**
*/ */
public class GNUElfParser extends AbstractCExtension implements IBinaryParser { public class GNUElfParser extends ElfParser implements IBinaryParser, IToolsProvider {
/** /**
* @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(IPath path) throws IOException {
if (path == null) { IBinaryFile binary = super.getBinary(path);
path = new Path(""); if (binary instanceof BinaryFile) {
} ((BinaryFile)binary).setToolsProvider(this);
IBinaryFile binary = null;
try {
Elf.Attribute attribute = Elf.getAttributes(path.toOSString());
if (attribute != null) {
switch (attribute.getType()) {
case Attribute.ELF_TYPE_EXE :
binary = new BinaryExecutable(path);
break;
case Attribute.ELF_TYPE_SHLIB :
binary = new BinaryShared(path);
break;
case Attribute.ELF_TYPE_OBJ :
binary = new BinaryObject(path);
break;
case Attribute.ELF_TYPE_CORE :
BinaryObject obj = new BinaryObject(path);
obj.setType(IBinaryFile.CORE);
binary = obj;
break;
}
}
} catch (IOException e) {
binary = new ElfBinaryArchive(path);
} }
return binary; return binary;
} }
@ -61,16 +39,49 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
* @see org.eclipse.cdt.core.model.IBinaryParser#getFormat() * @see org.eclipse.cdt.core.model.IBinaryParser#getFormat()
*/ */
public String getFormat() { public String getFormat() {
return "ELF"; return "GNU ELF";
} }
String getAddr2LinePath() { public IPath getAddr2LinePath() {
ICExtensionReference ref = getExtensionReference(); ICExtensionReference ref = getExtensionReference();
return ref.getExtensionData("addr2line"); String value = ref.getExtensionData("addr2line"); //$NON-NLS-1
if (value == null || value.length() == 0) {
value = "addr2line"; //$NON-NLS-1
}
return new Path(value);
} }
String getCPPFiltPath() { public IPath getCPPFiltPath() {
ICExtensionReference ref = getExtensionReference(); ICExtensionReference ref = getExtensionReference();
return ref.getExtensionData("c++filt"); String value = ref.getExtensionData("c++filt"); //$NON-NLS-1
if (value == null || value.length() == 0) {
value = "c++filt"; //$NON-NLS-1
} }
return new Path(value);
}
public Addr2line getAddr2Line(IPath path) {
IPath addr2LinePath = getAddr2LinePath();
Addr2line addr2line = null;
if (addr2LinePath != null && !addr2LinePath.isEmpty()) {
try {
addr2line = new Addr2line(addr2LinePath.toOSString(), path.toOSString());
} catch (IOException e1) {
}
}
return addr2line;
}
public CPPFilt getCPPFilt() {
IPath cppFiltPath = getCPPFiltPath();
CPPFilt cppfilt = null;
if (cppFiltPath != null && ! cppFiltPath.isEmpty()) {
try {
cppfilt = new CPPFilt(cppFiltPath.toOSString());
} catch (IOException e2) {
}
}
return cppfilt;
}
} }

View file

@ -1,29 +1,42 @@
/**********************************************************************
* 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.elf.parser; package org.eclipse.cdt.utils.elf.parser;
import java.io.IOException;
import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.utils.Addr2line;
import org.eclipse.core.runtime.IPath;
/* public class Symbol implements ISymbol, Comparable {
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
public class Symbol implements ISymbol { BinaryObject binary;
public String filename; public IPath filename;
public int startLine; public int startLine;
public int endLine; public int endLine;
public long addr; public long addr;
public String name; public String name;
public int type; public int type;
public Symbol(BinaryObject bin) {
binary = bin;
}
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getFilename() * @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getFilename()
*/ */
public String getFilename() { public IPath getFilename() {
return filename; return filename;
} }
/** /**
* @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getName() * @see org.eclipse.cdt.core.model.IBinaryParser.ISymbol#getName()
*/ */
@ -59,4 +72,34 @@ public class Symbol implements ISymbol {
return startLine; return startLine;
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser.ISymbol#getLineNumber(long)
*/
public int getLineNumber(long offset) {
int line = -1;
try {
Addr2line addr2line = binary.getAddr2Line();
if (addr2line != null) {
line = addr2line.getLineNumber(addr + offset);
addr2line.dispose();
}
} 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));
}
} }