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
|
2003-10-01 Bogdan Gheorghe
|
||||||
|
|
||||||
Changed DeltaProcessor.updateDependencies to use the CModelManager
|
Changed DeltaProcessor.updateDependencies to use the CModelManager
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
</run>
|
</run>
|
||||||
</cextension>
|
</cextension>
|
||||||
</extension>
|
</extension>
|
||||||
<!-- extension
|
<extension
|
||||||
id="GNU_ELF"
|
id="GNU_ELF"
|
||||||
name="GNU Elf Parser"
|
name="GNU Elf Parser"
|
||||||
point="org.eclipse.cdt.core.BinaryParser">
|
point="org.eclipse.cdt.core.BinaryParser">
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
class="org.eclipse.cdt.utils.elf.parser.GNUElfParser">
|
class="org.eclipse.cdt.utils.elf.parser.GNUElfParser">
|
||||||
</run>
|
</run>
|
||||||
</cextension>
|
</cextension>
|
||||||
</extension -->
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
id="PE"
|
id="PE"
|
||||||
name="PE Windows Parser"
|
name="PE Windows Parser"
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -15,20 +15,19 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +40,10 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
||||||
if (path != null) {
|
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]);
|
||||||
children.add(bin);
|
children.add(bin);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -59,13 +58,6 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
||||||
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()
|
||||||
*/
|
*/
|
||||||
|
@ -78,14 +70,14 @@ public class BinaryArchive extends PlatformObject implements IBinaryArchive {
|
||||||
*/
|
*/
|
||||||
public InputStream getContents() {
|
public InputStream getContents() {
|
||||||
try {
|
try {
|
||||||
return new FileInputStream(path.toFile());
|
return new FileInputStream(getPath().toFile());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
return new ByteArrayInputStream(new byte[0]);
|
return new ByteArrayInputStream(new byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasChanged() {
|
boolean hasChanged() {
|
||||||
long modif = path.toFile().lastModified();
|
long modif = getPath().toFile().lastModified();
|
||||||
boolean changed = modif != timestamp;
|
boolean changed = modif != timestamp;
|
||||||
timestamp = modif;
|
timestamp = modif;
|
||||||
return changed;
|
return changed;
|
||||||
|
@ -102,4 +94,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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,34 @@ 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 IPath addr2linePath;
|
||||||
|
protected IPath cppfiltPath;
|
||||||
|
|
||||||
public BinaryFile(IPath p) {
|
public BinaryFile(IPath p) {
|
||||||
path = 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
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,6 +12,8 @@ import java.util.ArrayList;
|
||||||
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.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;
|
||||||
|
@ -234,25 +236,84 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
|
||||||
sizes = helper.getSizes();
|
sizes = helper.getSizes();
|
||||||
soname = helper.getSoname();
|
soname = helper.getSoname();
|
||||||
attribute = helper.getElf().getAttributes();
|
attribute = helper.getElf().getAttributes();
|
||||||
|
// Hack should be remove when Elf is clean
|
||||||
|
helper.getElf().setCppFilter(false);
|
||||||
|
|
||||||
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);
|
||||||
|
addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, addr2line, cppfilt);
|
||||||
|
addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, addr2line, cppfilt);
|
||||||
|
addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE, addr2line, cppfilt);
|
||||||
symbols.trimToSize();
|
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++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
Symbol sym = new Symbol();
|
Symbol sym = new Symbol();
|
||||||
sym.type = type;
|
sym.type = type;
|
||||||
sym.name = array[i].toString();
|
sym.name = array[i].toString();
|
||||||
|
if (cppfilt != null) {
|
||||||
|
try {
|
||||||
|
sym.name = cppfilt.getFunction(sym.name);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
sym.addr = array[i].st_value;
|
sym.addr = array[i].st_value;
|
||||||
try {
|
try {
|
||||||
// This can fail if we use addr2line
|
// This can fail if we use addr2line
|
||||||
// but we can safely ignore the error.
|
// but we can safely ignore the error.
|
||||||
sym.filename = array[i].getFilename();
|
long value = sym.addr;
|
||||||
sym.startLine = array[i].getFuncLineNumber();
|
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;
|
sym.endLine = sym.startLine;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
|
@ -265,4 +326,24 @@ public class BinaryObject extends BinaryFile implements IBinaryObject {
|
||||||
symbols.add(sym);
|
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.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.elf.Elf;
|
import org.eclipse.cdt.utils.elf.Elf;
|
||||||
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;
|
||||||
|
@ -25,9 +24,10 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
|
||||||
*/
|
*/
|
||||||
public IBinaryFile getBinary(IPath path) throws IOException {
|
public IBinaryFile getBinary(IPath path) throws IOException {
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
path = new Path("");
|
throw new IOException("path is null");
|
||||||
}
|
}
|
||||||
IBinaryFile binary = null;
|
|
||||||
|
BinaryFile binary = null;
|
||||||
try {
|
try {
|
||||||
Elf.Attribute attribute = Elf.getAttributes(path.toOSString());
|
Elf.Attribute attribute = Elf.getAttributes(path.toOSString());
|
||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
|
@ -52,8 +52,10 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
binary = new ElfBinaryArchive(path);
|
binary = new BinaryArchive(path);
|
||||||
}
|
}
|
||||||
|
binary.setAddr2LinePath(getAddr2LinePath());
|
||||||
|
binary.setCPPFiltPath(getCPPFiltPath());
|
||||||
return binary;
|
return binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +66,21 @@ public class GNUElfParser extends AbstractCExtension implements IBinaryParser {
|
||||||
return "ELF";
|
return "ELF";
|
||||||
}
|
}
|
||||||
|
|
||||||
String getAddr2LinePath() {
|
public IPath getAddr2LinePath() {
|
||||||
ICExtensionReference ref = getExtensionReference();
|
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();
|
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