mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Enable the GNU Elf Parser.
This commit is contained in:
parent
4882849b8c
commit
994d18c7ab
8 changed files with 174 additions and 45 deletions
|
@ -1,3 +1,15 @@
|
|||
2003-10-06 Alain Magloire
|
||||
|
||||
Implementation of the GNU Elf parser, where you can
|
||||
change the path of the external commands: addr2line and cppfilt.
|
||||
|
||||
* plugin.xml: Enable the GNU Elf Parser.
|
||||
* utils/org/eclipse/cdt/utils/elf/BinaryFile.java
|
||||
* utils/org/eclipse/cdt/utils/elf/BinaryObject.java
|
||||
* utils/org/eclipse/cdt/utils/elf/BinaryArchive.java
|
||||
* utils/org/eclipse/cdt/utils/Addr2line.java
|
||||
* utils/org/eclipse/cdt/utils/elf/CPPFilt.java
|
||||
|
||||
2003-10-01 Bogdan Gheorghe
|
||||
|
||||
Changed DeltaProcessor.updateDependencies to use the CModelManager
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
</run>
|
||||
</cextension>
|
||||
</extension>
|
||||
<!-- extension
|
||||
<extension
|
||||
id="GNU_ELF"
|
||||
name="GNU Elf Parser"
|
||||
point="org.eclipse.cdt.core.BinaryParser">
|
||||
|
@ -71,7 +71,7 @@
|
|||
class="org.eclipse.cdt.utils.elf.parser.GNUElfParser">
|
||||
</run>
|
||||
</cextension>
|
||||
</extension -->
|
||||
</extension>
|
||||
<extension
|
||||
id="PE"
|
||||
name="PE Windows Parser"
|
||||
|
|
|
@ -18,21 +18,25 @@ public class Addr2line {
|
|||
private BufferedReader stdout;
|
||||
private BufferedWriter stdin;
|
||||
private String lastaddr, lastsymbol, lastline;
|
||||
|
||||
public Addr2line(String file) throws IOException {
|
||||
String[] args = {"addr2line", "-C", "-f", "-e", file};
|
||||
|
||||
public Addr2line(String command, String file) throws IOException {
|
||||
String[] args = {command, "-C", "-f", "-e", file};
|
||||
addr2line = ProcessFactory.getFactory().exec(args);
|
||||
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 {
|
||||
if ( address.equals(lastaddr) == false ) {
|
||||
stdin.write(address + "\n");
|
||||
stdin.flush();
|
||||
lastsymbol = stdout.readLine();
|
||||
lastline = stdout.readLine();
|
||||
lastaddr = address;
|
||||
stdin.write(address + "\n");
|
||||
stdin.flush();
|
||||
lastsymbol = stdout.readLine();
|
||||
lastline = stdout.readLine();
|
||||
lastaddr = address;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,15 +17,19 @@ public class CPPFilt {
|
|||
private Process cppfilt;
|
||||
private BufferedReader stdout;
|
||||
private BufferedWriter stdin;
|
||||
|
||||
public CPPFilt() throws IOException {
|
||||
String[] args = {"c++filt"};
|
||||
|
||||
public CPPFilt(String command) throws IOException {
|
||||
String[] args = {command};
|
||||
cppfilt = ProcessFactory.getFactory().exec(args);
|
||||
//cppfilt = new Spawner(args);
|
||||
stdin = new BufferedWriter(new OutputStreamWriter(cppfilt.getOutputStream()));
|
||||
stdout = new BufferedReader(new InputStreamReader(cppfilt.getInputStream()));
|
||||
}
|
||||
|
||||
public CPPFilt() throws IOException {
|
||||
this("c++filt");
|
||||
}
|
||||
|
||||
public String getFunction(String symbol) throws IOException {
|
||||
stdin.write(symbol + "\n");
|
||||
stdin.flush();
|
||||
|
|
|
@ -15,20 +15,19 @@ 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.cdt.utils.elf.Elf.Attribute;
|
||||
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;
|
||||
long timestamp;
|
||||
|
||||
public BinaryArchive(IPath p) throws IOException {
|
||||
path = p;
|
||||
new AR(path.toOSString()).dispose(); // check file type
|
||||
super(p);
|
||||
new AR(p.toOSString()).dispose(); // check file type
|
||||
children = new ArrayList(5);
|
||||
}
|
||||
|
||||
|
@ -41,10 +40,10 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
|||
if (path != null) {
|
||||
AR ar = null;
|
||||
try {
|
||||
ar = new AR(path.toOSString());
|
||||
ar = new AR(getPath().toOSString());
|
||||
AR.ARHeader[] headers = ar.getHeaders();
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
IBinaryObject bin = new ARMember(path, headers[i]);
|
||||
IBinaryObject bin = new ARMember(getPath(), headers[i]);
|
||||
children.add(bin);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -59,13 +58,6 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
|||
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()
|
||||
*/
|
||||
|
@ -78,14 +70,14 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
|||
*/
|
||||
public InputStream getContents() {
|
||||
try {
|
||||
return new FileInputStream(path.toFile());
|
||||
return new FileInputStream(getPath().toFile());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
|
||||
boolean hasChanged() {
|
||||
long modif = path.toFile().lastModified();
|
||||
long modif = getPath().toFile().lastModified();
|
||||
boolean changed = modif != timestamp;
|
||||
timestamp = modif;
|
||||
return changed;
|
||||
|
@ -102,4 +94,11 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
|||
public void delete(IBinaryObject[] objs) throws IOException {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.utils.elf.parser.BinaryFile#getAttribute()
|
||||
*/
|
||||
protected Attribute getAttribute() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,15 +16,34 @@ import org.eclipse.core.runtime.IPath;
|
|||
import org.eclipse.core.runtime.PlatformObject;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public abstract class BinaryFile extends PlatformObject implements IBinaryFile {
|
||||
|
||||
protected IPath path;
|
||||
protected IPath addr2linePath;
|
||||
protected IPath cppfiltPath;
|
||||
|
||||
public BinaryFile(IPath p) {
|
||||
path = p;
|
||||
}
|
||||
|
||||
public void setAddr2LinePath(IPath p) {
|
||||
addr2linePath = p;
|
||||
}
|
||||
|
||||
public IPath getAddr2LinePath() {
|
||||
return addr2linePath;
|
||||
}
|
||||
|
||||
public void setCPPFiltPath(IPath p) {
|
||||
cppfiltPath = p;
|
||||
}
|
||||
|
||||
public IPath getCPPFiltPath() {
|
||||
return cppfiltPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
|
|
|
@ -12,6 +12,8 @@ import java.util.ArrayList;
|
|||
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.elf.Elf;
|
||||
import org.eclipse.cdt.utils.elf.ElfHelper;
|
||||
import org.eclipse.cdt.utils.elf.Elf.Attribute;
|
||||
|
@ -234,25 +236,84 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
|
|||
sizes = helper.getSizes();
|
||||
soname = helper.getSoname();
|
||||
attribute = helper.getElf().getAttributes();
|
||||
// Hack should be remove when Elf is clean
|
||||
helper.getElf().setCppFilter(false);
|
||||
|
||||
addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION);
|
||||
addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION);
|
||||
addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE);
|
||||
addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE);
|
||||
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();
|
||||
|
||||
if (addr2line != null) {
|
||||
addr2line.dispose();
|
||||
}
|
||||
if (cppfilt != null) {
|
||||
cppfilt.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected void addSymbols(Elf.Symbol[] array, int type) {
|
||||
protected void addSymbols(Elf.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
Symbol sym = new Symbol();
|
||||
sym.type = type;
|
||||
sym.name = array[i].toString();
|
||||
if (cppfilt != null) {
|
||||
try {
|
||||
sym.name = cppfilt.getFunction(sym.name);
|
||||
} catch (IOException e1) {
|
||||
}
|
||||
}
|
||||
sym.addr = array[i].st_value;
|
||||
try {
|
||||
// This can fail if we use addr2line
|
||||
// but we can safely ignore the error.
|
||||
sym.filename = array[i].getFilename();
|
||||
sym.startLine = array[i].getFuncLineNumber();
|
||||
long value = sym.addr;
|
||||
int lineno = -1;
|
||||
String filename = null;
|
||||
if (addr2line != null) {
|
||||
// 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.
|
||||
String line = null;
|
||||
for (int j = 0; j <= 20; j += 4, value += j) {
|
||||
line = addr2line.getLine(value);
|
||||
if (line != null) {
|
||||
int colon = line.lastIndexOf(':');
|
||||
if (colon != -1) {
|
||||
String number = line.substring(colon + 1);
|
||||
if (!number.startsWith("0")) {
|
||||
break; // potential candidate bail out
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
try {
|
||||
lineno = Integer.parseInt(line.substring(index1 + 1));
|
||||
lineno = (lineno == 0) ? -1 : lineno;
|
||||
} catch(Exception e) {
|
||||
lineno = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
sym.filename = filename;
|
||||
sym.startLine = lineno;
|
||||
sym.endLine = sym.startLine;
|
||||
} catch (IOException e) {
|
||||
//e.printStackTrace();
|
||||
|
@ -265,4 +326,24 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
|
|||
symbols.add(sym);
|
||||
}
|
||||
|
||||
protected Addr2line getAddr2Line() {
|
||||
IPath addr2LinePath = getAddr2LinePath();
|
||||
Addr2line addr2line = null;
|
||||
try {
|
||||
addr2line = new Addr2line(addr2LinePath.toOSString(), getPath().toOSString());
|
||||
} catch (IOException e1) {
|
||||
}
|
||||
return addr2line;
|
||||
}
|
||||
|
||||
protected CPPFilt getCPPFilt() {
|
||||
IPath cppFiltPath = getCPPFiltPath();
|
||||
CPPFilt cppfilt = null;
|
||||
try {
|
||||
cppfilt = new CPPFilt(cppFiltPath.toOSString());
|
||||
} catch (IOException e2) {
|
||||
}
|
||||
return cppfilt;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.io.IOException;
|
|||
import org.eclipse.cdt.core.AbstractCExtension;
|
||||
import org.eclipse.cdt.core.IBinaryParser;
|
||||
import org.eclipse.cdt.core.ICExtensionReference;
|
||||
import org.eclipse.cdt.internal.core.model.parser.ElfBinaryArchive;
|
||||
import org.eclipse.cdt.utils.elf.Elf;
|
||||
import org.eclipse.cdt.utils.elf.Elf.Attribute;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
@ -25,9 +24,10 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
|
|||
*/
|
||||
public IBinaryFile getBinary(IPath path) throws IOException {
|
||||
if (path == null) {
|
||||
path = new Path("");
|
||||
throw new IOException("path is null");
|
||||
}
|
||||
IBinaryFile binary = null;
|
||||
|
||||
BinaryFile binary = null;
|
||||
try {
|
||||
Elf.Attribute attribute = Elf.getAttributes(path.toOSString());
|
||||
if (attribute != null) {
|
||||
|
@ -52,8 +52,10 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
|
|||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
binary = new ElfBinaryArchive(path);
|
||||
binary = new BinaryArchive(path);
|
||||
}
|
||||
binary.setAddr2LinePath(getAddr2LinePath());
|
||||
binary.setCPPFiltPath(getCPPFiltPath());
|
||||
return binary;
|
||||
}
|
||||
|
||||
|
@ -64,13 +66,21 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
|
|||
return "ELF";
|
||||
}
|
||||
|
||||
String getAddr2LinePath() {
|
||||
public IPath getAddr2LinePath() {
|
||||
ICExtensionReference ref = getExtensionReference();
|
||||
return ref.getExtensionData("addr2line");
|
||||
String value = ref.getExtensionData("addr2line");
|
||||
if (value == null || value.length() == 0) {
|
||||
value = "addr2line";
|
||||
}
|
||||
return new Path(value);
|
||||
}
|
||||
|
||||
String getCPPFiltPath() {
|
||||
public IPath getCPPFiltPath() {
|
||||
ICExtensionReference ref = getExtensionReference();
|
||||
return ref.getExtensionData("c++filt");
|
||||
String value = ref.getExtensionData("c++filt");
|
||||
if (value == null || value.length() == 0) {
|
||||
value = "c++filt";
|
||||
}
|
||||
return new Path(value);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue