diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugArrayType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugArrayType.java new file mode 100644 index 00000000000..06fe7a93d39 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugArrayType.java @@ -0,0 +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.debug; + + +/** + * DebugArrayType + * + */ +public class DebugArrayType extends DebugDerivedType { + + int size; + + /** + * + */ + public DebugArrayType(DebugType type, int arraySize) { + super(type); + size = arraySize; + } + + public int getSize() { + return size; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugBaseType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugBaseType.java new file mode 100644 index 00000000000..be17c017c0a --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugBaseType.java @@ -0,0 +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.debug; + + +/** + * DebugType + * + */ +public class DebugBaseType extends DebugType { + + String typeName; + int typeSize; + boolean typeUnSigned; + + public DebugBaseType(String name, int size, boolean unSigned) { + typeName = name; + typeSize = size; + typeUnSigned = unSigned; + } + + public String getTypeName() { + return typeName; + } + + public int sizeof() { + return typeSize; + } + + public boolean isUnSigned() { + return typeUnSigned; + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugCrossRefType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugCrossRefType.java new file mode 100644 index 00000000000..7890c26cbfc --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugCrossRefType.java @@ -0,0 +1,41 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugCrossRefType + * + */ +public class DebugCrossRefType extends DebugDerivedType { + + String name; + String xName; + + /** + * + */ + public DebugCrossRefType(DebugType type, String name, String xName) { + super(type); + this.name = name; + this.xName = xName; + } + + public String getName() { + return name; + } + + public String getCrossRefName() { + return xName; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugDerivedType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugDerivedType.java new file mode 100644 index 00000000000..8b169e62b88 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugDerivedType.java @@ -0,0 +1,38 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugDerivedType + * + */ +public abstract class DebugDerivedType extends DebugType { + + DebugType component; + + /** + * + */ + public DebugDerivedType(DebugType type) { + component = type; + } + + public DebugType getComponentType() { + return component; + } + + public void setComponentType(DebugType type) { + component = type; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugDump.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugDump.java new file mode 100644 index 00000000000..296803c3431 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugDump.java @@ -0,0 +1,292 @@ +/********************************************************************** + * 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.debug; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.utils.debug.stabs.Stabs; + +/** + * DebugDump + * + */ +public class DebugDump implements IDebugEntryRequestor { + + List list = new ArrayList(); + BufferedWriter bwriter; + int bracket; + int paramCount = -1; + + String currentCU; + + /** + * + */ + public DebugDump(OutputStream stream) { + bwriter = new BufferedWriter(new OutputStreamWriter(stream)); + } + + void write(String s) { + try { + bwriter.write(s, 0, s.length()); + } catch (IOException e) { + // ignore. + } + } + + void newLine() { + try { + bwriter.newLine(); + } catch (IOException e) { + // ignore + } + } + + String printTabs() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < bracket; i++) { + sb.append('\t'); + } + return sb.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterCompilationUnit(java.lang.String, long) + */ + public void enterCompilationUnit(String name, long address) { + write("/* Enter Compilation Unit " + name + " address " + Long.toHexString(address) + " */"); + newLine(); + currentCU = name; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitCompilationUnit(long) + */ + public void exitCompilationUnit(long address) { + write("/* Exit Compilation Unit "); + if (currentCU != null) { + write(currentCU + " address " + Long.toHexString(address)); + } + write(" */"); + newLine();newLine(); + try { + bwriter.flush(); + } catch (IOException e) { + } + currentCU = null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterInclude(java.lang.String) + */ + public void enterInclude(String name) { + write("#include \"" + name + "\" "); + write("/* Enter Include */"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitInclude() + */ + public void exitInclude() { + //write("/* Exit Include */"); + //newLine();newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterFunction(java.lang.String, int, boolean, long) + */ + public void enterFunction(String name, DebugType type, boolean isGlobal, long address) { + write("/* Func:" + name + " address " + Long.toHexString(address) + " */"); + newLine(); + if (!isGlobal) { + write("static "); + } + write(type.toString() + " " + name + "("); + paramCount = 0; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitFunction(long) + */ + public void exitFunction(long address) { + if (paramCount > -1) { + paramCount = -1; + write(")"); + newLine(); + write("{"); + newLine(); + bracket++; + } + for (; bracket > 0; bracket--) { + write("}"); + } + write(" /* Exit Func address " + Long.toHexString(address) + " */"); + newLine();newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterCodeBlock(long) + */ + public void enterCodeBlock(long offset) { + if (paramCount > -1) { + paramCount = -1; + write(")"); + newLine(); + } + write(printTabs() + "{ " + "/* " + offset + " */"); + newLine(); + bracket++; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitCodeBlock(long) + */ + public void exitCodeBlock(long offset) { + bracket--; + write(printTabs() + "} " + "/* " + offset + " */"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptStatement(int, long) + */ + public void acceptStatement(int line, long address) { + if (paramCount > -1) { + write(")"); + newLine(); + write("{"); + newLine(); + bracket++; + paramCount = -1; + } + write(printTabs() + "/* line " + line + " address " + address + " */"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptIntegerConst(java.lang.String, long) + */ + public void acceptIntegerConst(String name, int value) { + write("const int " + name + " = " + value + ";"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptFloatConst(java.lang.String, double) + */ + public void acceptFloatConst(String name, double value) { + write("const float " + name + " = " + value + ";"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptTypeConst(java.lang.String, + * org.eclipse.cdt.utils.debug.DebugType, int) + */ + public void acceptTypeConst(String name, DebugType type, int value) { + write("const " + type.toString() + " " + name + " = " + value + ";"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptParameter(java.lang.String, int, int, long) + */ + public void acceptParameter(String name, DebugType type, DebugParameterKind kind, long offset) { + if (paramCount > 0) { + write(", "); + } + paramCount++; + write(type.toString() + " " + name + "/* " + offset + " */"); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptVariable(java.lang.String, int, int, long) + */ + public void acceptVariable(String name, DebugType type, DebugVariableKind kind, long address) { + write(printTabs() + type.toString() + " " + name + ";" + "/* " + Long.toHexString(address) + " */"); + newLine(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptCaughtException(java.lang.String, + * org.eclipse.cdt.utils.debug.DebugType, long) + */ + public void acceptCaughtException(String name, DebugType type, long address) { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptTypeDef(java.lang.String, org.eclipse.cdt.utils.debug.DebugType) + */ + public void acceptTypeDef(String name, DebugType type) { + if (!name.equals(type.toString())) { + write("typedef " + type.toString() + " " + name + ";"); + newLine(); + } else if (type instanceof DebugBaseType){ + DebugBaseType baseType =(DebugBaseType)type; + write("/* " + name + ": " + baseType.sizeof() + " bytes */"); + newLine(); + } else { + int x = 9; + } + } + + public static void main(String[] args) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DebugDump dump = new DebugDump(System.out); + Stabs stabs = new Stabs(args[0]); + stabs.parse(dump); + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugEnumField.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugEnumField.java new file mode 100644 index 00000000000..2c5ea473cf9 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugEnumField.java @@ -0,0 +1,40 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugEnumField + * + */ +public class DebugEnumField { + + String name; + int value; + + /** + * + */ + public DebugEnumField(String name, int value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public int getValue() { + return value; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugEnumType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugEnumType.java new file mode 100644 index 00000000000..4799b4a5805 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugEnumType.java @@ -0,0 +1,40 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugEnumType + * + */ +public class DebugEnumType extends DebugType { + + DebugEnumField[] fields; + String name; + + /** + * + */ + public DebugEnumType(String name, DebugEnumField[] fields) { + this.name = name; + this.fields = fields; + } + + public DebugEnumField[] getDebugEnumFields() { + return fields; + } + + public String getName() { + return name; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugField.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugField.java new file mode 100644 index 00000000000..83e577aa353 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugField.java @@ -0,0 +1,44 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugEnumField + * + */ +public class DebugField { + + String name; + DebugType type; + int offset; + int bits; + + /** + * + */ + public DebugField(String name, DebugType type, int offset, int bits) { + this.name = name; + this.type = type; + this.offset = offset; + this.bits = bits; + } + + public String getName() { + return name; + } + + public DebugType getDebugType() { + return type; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugFunctionType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugFunctionType.java new file mode 100644 index 00000000000..d3b0942c3de --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugFunctionType.java @@ -0,0 +1,34 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugFunctionType + * + */ +public class DebugFunctionType extends DebugType { + + DebugType returnType; + + /** + * + */ + public DebugFunctionType(DebugType type) { + returnType = type; + } + + public DebugType getReturnType() { + return returnType; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugParameterKind.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugParameterKind.java new file mode 100644 index 00000000000..799e39399f0 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugParameterKind.java @@ -0,0 +1,46 @@ +/********************************************************************** + * 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.debug; + +/** + * DebugParameterKind + * + */ +public final class DebugParameterKind { + + /* What is it ?? . */ + public final static DebugParameterKind UNKNOWN = new DebugParameterKind(0); + /* parameter on the stack*/ + public final static DebugParameterKind STACK = new DebugParameterKind(1); + /* parameter in register. */ + public final static DebugParameterKind REGISTER = new DebugParameterKind(2); + /* parameter by reference. */ + public final static DebugParameterKind REFERENCE = new DebugParameterKind(3); + /* register reference parameter. */ + public final static DebugParameterKind REGISTER_REFERENCE = new DebugParameterKind(4); + + private int id; + /** + * + */ + private DebugParameterKind(int id) { + this.id = id; + } + + public boolean equals(Object obj) { + if (obj instanceof DebugParameterKind) { + DebugParameterKind kind = (DebugParameterKind)obj; + return kind.id == id; + } + return super.equals(obj); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugPointerType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugPointerType.java new file mode 100644 index 00000000000..82d2becc5e8 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugPointerType.java @@ -0,0 +1,28 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugPointerType + * + */ +public class DebugPointerType extends DebugDerivedType { + + /** + * + */ + public DebugPointerType(DebugType type) { + super(type); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugReferenceType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugReferenceType.java new file mode 100644 index 00000000000..72cfd6b2e60 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugReferenceType.java @@ -0,0 +1,28 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugReferenceType + * + */ +public class DebugReferenceType extends DebugDerivedType { + + /** + * + */ + public DebugReferenceType(DebugType type) { + super(type); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugStructType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugStructType.java new file mode 100644 index 00000000000..d23c5f4d87d --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugStructType.java @@ -0,0 +1,60 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugStructType + * + */ +public class DebugStructType extends DebugType { + + String name; + int size; + boolean isUnion; + final static DebugField[] EMPTY_FIELDS = new DebugField[0]; + DebugField[] fields; + + /** + * + */ + public DebugStructType(String name, int size, boolean union) { + this.name = name; + this.size = size; + this.isUnion = union; + fields = EMPTY_FIELDS; + } + + public int getSize() { + return size; + } + + public String getName() { + return name; + } + + public boolean isUnion() { + return isUnion; + } + + public DebugField[] getDebugFields() { + return fields; + } + + public void addField(DebugField field) { + DebugField[] fs = new DebugField[fields.length + 1]; + System.arraycopy(fields, 0, fs, 0, fields.length); + fs[fields.length] = field; + fields = fs; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugType.java new file mode 100644 index 00000000000..b25909ab986 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugType.java @@ -0,0 +1,97 @@ +/********************************************************************** + * 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.debug; + + +/** + * DebugType + * + */ +public class DebugType { + + /** + * + */ + protected DebugType() { + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + if (this instanceof DebugArrayType) { + DebugArrayType arrayType = (DebugArrayType)this; + int size = arrayType.getSize(); + DebugType type = arrayType.getComponentType(); + sb.append(type.toString()); + sb.append(" [").append(size).append(']'); + } else if (this instanceof DebugDerivedType) { + DebugDerivedType derived = (DebugDerivedType)this; + DebugType component = derived.getComponentType(); + if (component instanceof DebugStructType) { + DebugStructType structType = (DebugStructType)component; + sb.append(structType.getName()); + } else if (component != null){ + sb.append(component.toString()); + } + if (this instanceof DebugPointerType) { + sb.append(" *"); + } else if (this instanceof DebugReferenceType) { + sb.append(" &"); + } else if (this instanceof DebugCrossRefType && component == null) { + DebugCrossRefType crossRef = (DebugCrossRefType)this; + sb.append(crossRef.getCrossRefName()); + //sb.append(crossRef.getName()); + } + } else if (this instanceof DebugBaseType) { + DebugBaseType base = (DebugBaseType)this; + String typeName = base.getTypeName(); + sb.append(typeName); + } else if (this instanceof DebugFunctionType) { + DebugFunctionType function = (DebugFunctionType)this; + DebugType type = function.getReturnType(); + sb.append(type.toString()); + sb.append(" (*())"); + } else if (this instanceof DebugEnumType) { + DebugEnumType enum = (DebugEnumType)this; + DebugEnumField[] fields = enum.getDebugEnumFields(); + sb.append("enum ").append(enum.getName()).append(" {"); + for (int i = 0; i < fields.length; i++) { + if (i > 0) { + sb.append(','); + } + sb.append(' ').append(fields[i].getName()); + sb.append(" = ").append(fields[i].getValue()); + } + sb.append(" }"); + } else if (this instanceof DebugStructType) { + DebugStructType struct = (DebugStructType)this; + if (struct.isUnion()) { + sb.append("union "); + } else { + sb.append("struct "); + } + sb.append(struct.getName()).append(" {"); + DebugField[] fields = struct.getDebugFields(); + for (int i = 0; i < fields.length; i++) { + if (i > 0) { + sb.append(';'); + } + sb.append(' ').append(fields[i].getDebugType()); + sb.append(' ').append(fields[i].getName()); + } + sb.append(" }"); + } else if (this instanceof DebugUnknownType) { + DebugUnknownType unknown = (DebugUnknownType)this; + sb.append(unknown.getName()); + } + return sb.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugUnknownType.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugUnknownType.java new file mode 100644 index 00000000000..c25b88a09a7 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugUnknownType.java @@ -0,0 +1,34 @@ +/********************************************************************** + * 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.debug; + +/** + * DebugUnknownType + * + */ +public class DebugUnknownType extends DebugType { + + String name; + + /** + * + */ + public DebugUnknownType(String unknown) { + super(); + name = unknown; + } + + public String getName() { + return name; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugVariableKind.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugVariableKind.java new file mode 100644 index 00000000000..a34e629aed0 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugVariableKind.java @@ -0,0 +1,48 @@ +/********************************************************************** + * 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.debug; + +/** + * DebugVariableKind + * + */ +public final class DebugVariableKind { + + /* What is it ?? . */ + public final static DebugVariableKind UNKNOWN = new DebugVariableKind(0); + /* global variable */ + public final static DebugVariableKind GLOBAL = new DebugVariableKind(1); + /* static variable. */ + public final static DebugVariableKind STATIC = new DebugVariableKind(2); + /* local static variable. */ + public final static DebugVariableKind LOCAL_STATIC = new DebugVariableKind(3); + /* local variable. */ + public final static DebugVariableKind LOCAL = new DebugVariableKind(4); + /* variable is in register. */ + public final static DebugVariableKind REGISTER = new DebugVariableKind(5); + + private int id; + /** + * + */ + private DebugVariableKind(int id) { + this.id = id; + } + + public boolean equals(Object obj) { + if (obj instanceof DebugVariableKind) { + DebugVariableKind kind = (DebugVariableKind)obj; + return kind.id == id; + } + return super.equals(obj); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugVisibility.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugVisibility.java new file mode 100644 index 00000000000..21214a79793 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/DebugVisibility.java @@ -0,0 +1,44 @@ +/********************************************************************** + * 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.debug; + +/** + * DebugVisibility + * + */ +public final class DebugVisibility { + + /* What is it ?? . */ + public final static DebugVisibility UNKNOWN = new DebugVisibility(0); + /* public field */ + public final static DebugVisibility PUBLIC = new DebugVisibility(1); + /* protected field. */ + public final static DebugVisibility PROTECTED = new DebugVisibility(2); + /* private field. */ + public final static DebugVisibility PRIVATE = new DebugVisibility(3); + + private int id; + /** + * + */ + private DebugVisibility(int id) { + this.id = id; + } + + public boolean equals(Object obj) { + if (obj instanceof DebugVisibility) { + DebugVisibility kind = (DebugVisibility)obj; + return kind.id == id; + } + return super.equals(obj); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/IDebugEntryRequestor.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/IDebugEntryRequestor.java new file mode 100644 index 00000000000..5199ce60000 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/IDebugEntryRequestor.java @@ -0,0 +1,128 @@ +/********************************************************************** + * 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.debug; + +public interface IDebugEntryRequestor { + + /** + * Entering a compilation unit. + * @param name + * @param address start of address of the cu. + */ + void enterCompilationUnit(String name, long address); + + /** + * Exit the current compilation unit. + * @param address end of compilation unit. + */ + void exitCompilationUnit(long address); + + /** + * Entering new include file in a compilation unit. + * @param name + */ + void enterInclude(String name); + + /** + * Exit the current include file. + */ + void exitInclude(); + + /** + * Enter a function. + * @param name of the function/method + * @param type type of the return value. + * @param isGlobal return the visiblity of the function. + * @param address the start address of the function. + */ + void enterFunction(String name, DebugType type, boolean isGlobal, long address); + + /** + * Exit the current function. + * @param address the address where the function ends. + */ + void exitFunction(long address); + + /** + * Enter a code block in a function. + * @param offset address of the block starts relative to the current function. + */ + void enterCodeBlock(long offset); + + /** + * Exit of the current code block. + * @param offset the address of which the blocks ends relative to the current function. + */ + void exitCodeBlock(long offset); + + /** + * Statement in the compilation unit with a given address. + * @param line lineno of the statement relative to the current compilation unit. + * @param offset addres of the statement relative to the current function. + */ + void acceptStatement(int line, long address); + + /** + * Integer constant. + * @param name + * @param address. + */ + void acceptIntegerConst(String name, int value); + + /** + * floating point constant. + * @param name + * @param value + */ + void acceptFloatConst(String name, double value); + + /** + * Type constant: "const b = 0", b is a type enum. + * @param name + * @param type + * @param address + */ + void acceptTypeConst(String name, DebugType type, int value); + + /** + * Caught Exception. + * @param name + * @param value + */ + void acceptCaughtException(String name, DebugType type, long address); + + /** + * Accept a parameter for the current function. + * @param name of the parameter + * @param type of the parameter + * @param kind of the parameter + * @param offset address of the parameter relative to the current function. + */ + void acceptParameter(String name, DebugType type, DebugParameterKind kind, long offset); + + /** + * Record a variable. + * @param name + * @param type + * @param kind + * @param address + */ + void acceptVariable(String name, DebugType type, DebugVariableKind kind, long address); + + /** + * Type definition. + * IDebugEntryRequestor + * @param name new name + * @param type + */ + void acceptTypeDef(String name, DebugType type); + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/.Dwarf.java.swp b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/.Dwarf.java.swp new file mode 100644 index 00000000000..6d6e978ec5f Binary files /dev/null and b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/.Dwarf.java.swp differ diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java new file mode 100644 index 00000000000..27dbf989c7b --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java @@ -0,0 +1,146 @@ +/********************************************************************** + * 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.debug.dwarf; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.utils.elf.Elf; + +public class Dwarf { + + /* Section names. */ + final static String DWARF_DEBUG_INFO = ".debug_info"; + final static String DWARF_DEBUG_ABBREV = ".debug_abbrev"; + final static String DWARF_DEBUG_ARANGES = ".debug_aranges"; + final static String DWARF_DEBUG_LINE = ".debug_line"; + final static String DWARF_DEBUG_FRAME = ".debug_frame"; + final static String DWARF_EH_FRAME = ".eh_frame"; + final static String DWARF_DEBUG_LOC = ".debug_loc"; + final static String DWARF_DEBUG_PUBNAMES = ".debug_pubnames"; + final static String DWARF_DEBUG_STR = ".debug_str"; + final static String DWARF_DEBUG_FUNCNAMES = ".debug_funcnames"; + final static String DWARF_DEBUG_TYPENAMES = ".debug_typenames"; + final static String DWARF_DEBUG_VARNAMES = ".debug_varnames"; + final static String DWARF_DEBUG_WEAKNAMES = ".debug_weaknames"; + final static String DWARF_DEBUG_MACINFO = ".debug_macinfo"; + final static String[] DWARF_SCNNAMES = + { + DWARF_DEBUG_INFO, + DWARF_DEBUG_ABBREV, + DWARF_DEBUG_ARANGES, + DWARF_DEBUG_LINE, + DWARF_DEBUG_FRAME, + DWARF_EH_FRAME, + DWARF_DEBUG_LOC, + DWARF_DEBUG_PUBNAMES, + DWARF_DEBUG_STR, + DWARF_DEBUG_FUNCNAMES, + DWARF_DEBUG_TYPENAMES, + DWARF_DEBUG_VARNAMES, + DWARF_DEBUG_WEAKNAMES, + DWARF_DEBUG_MACINFO + }; + + public static class DwarfSection { + String name; + byte[] data; + public DwarfSection (String n, byte[] d) { + name = n; + data = d; + } + } + + DwarfSection[] dwarfSections; + boolean isLE; + + public Dwarf(String file) throws IOException { + Elf exe = new Elf(file); + init(exe); + exe.dispose(); + } + + public Dwarf(Elf exe) throws IOException { + init(exe); + } + + public void init(Elf exe) throws IOException { + Elf.ELFhdr header = exe.getELFhdr(); + isLE = header.e_ident[Elf.ELFhdr.EI_DATA] == Elf.ELFhdr.ELFDATA2LSB; + + Elf.Section[] sections = exe.getSections(); + List list = new ArrayList(); + for (int i = 0; i < sections.length; i++) { + String name = sections[i].toString(); + for (int j = 0; j < DWARF_SCNNAMES.length; j++) { + if (name.equals(DWARF_SCNNAMES[j])) { + list.add(new DwarfSection(name, sections[i].loadSectionData())); + } + } + } + dwarfSections = new DwarfSection[list.size()]; + list.toArray(dwarfSections); + } + + int read_4_bytes(byte[] bytes, int offset) { + if (isLE) { + return (((bytes[offset + 3] & 0xff) << 24) + ((bytes[offset + 2] & 0xff) << 16) + + ((bytes[offset + 1] & 0xff) << 8) + (bytes[offset] & 0xff)); + } + return (((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) << 16) + ((bytes[offset + 2] & 0xff) << 8) + (bytes[offset + 3] & 0xff)); + } + + short read_2_bytes(byte[] bytes, int offset) { + if (isLE) { + return (short) (((bytes[offset + 1] & 0xff) << 8) + (bytes[offset] & 0xff)); + } + return (short) (((bytes[offset] & 0xff) << 8) + (bytes[offset + 1] & 0xff)); + } + + public void parse() { + for (int i = 0; i < dwarfSections.length; i++) { + if (dwarfSections[i].name.equals(DWARF_DEBUG_INFO)) { + parse_debug_info(dwarfSections[i].data); + } + } + } + + void parse_debug_info(byte[] data) { + int offset = 0; + int nentries = data.length / 11; + for (int i = 0; i < nentries; offset += 11) { + int length = read_4_bytes(data, offset); + short version = read_2_bytes(data, offset + 4); + int abbrev_offset = read_4_bytes(data, offset + 4 + 2); + byte address_size = data[offset + 4 + 2 + 4]; + System.out.println("Length:" + length); + System.out.println("Version:" + version); + System.out.println("Abbreviation:" + abbrev_offset); + System.out.println("Address size:" + address_size); + } + } + + void parse_compilation_unit() { + + } + + public static void main(String[] args) { + try { + Dwarf dwarf = new Dwarf(args[0]); + dwarf.parse(); + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/StabConstant.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabConstant.java similarity index 98% rename from core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/StabConstant.java rename to core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabConstant.java index e78d2b9ca09..d9a44c37799 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/StabConstant.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabConstant.java @@ -9,7 +9,7 @@ * QNX Software Systems - Initial API and implementation ***********************************************************************/ -package org.eclipse.cdt.utils.stabs; +package org.eclipse.cdt.utils.debug.stabs; public final class StabConstant { diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabSym.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabSym.java new file mode 100644 index 00000000000..6a0927618ef --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabSym.java @@ -0,0 +1,53 @@ +/********************************************************************** + * 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.debug.stabs; + + +public class StabSym implements Comparable { + + public long addr; + public long size; + public int startLine; + public int endLine; + public String name; + public String type; + public String filename; + + public StabSym() { + } + + public int compareTo(Object obj) { + long thisVal = 0; + long anotherVal = 0; + if (obj instanceof StabSym) { + StabSym entry = (StabSym) obj; + thisVal = this.addr; + anotherVal = entry.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)); + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("Type:").append(type).append("\n"); + buf.append("Name: ").append(name).append("\n"); + buf.append("\taddress:").append("0x").append(Long.toHexString(addr)).append("\n"); + buf.append("\tstartLine:").append(startLine).append("\n"); + buf.append("\tendLine:").append(endLine).append("\n"); + buf.append("\tSize:").append(size).append("\n"); + return buf.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabSymsRequestor.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabSymsRequestor.java new file mode 100644 index 00000000000..eba50863459 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabSymsRequestor.java @@ -0,0 +1,205 @@ +/********************************************************************** + * 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.debug.stabs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.cdt.utils.debug.DebugParameterKind; +import org.eclipse.cdt.utils.debug.DebugType; +import org.eclipse.cdt.utils.debug.DebugVariableKind; +import org.eclipse.cdt.utils.debug.IDebugEntryRequestor; + + +/** + * StabSymsRequestor + * + */ +public class StabSymsRequestor implements IDebugEntryRequestor { + + StabSym currentCU; + StabSym currentFunction; + + List list = new ArrayList(); + + /** + * + */ + public StabSymsRequestor() { + super(); + } + + public StabSym[] getSortedEntries() { + StabSym[] syms = getEntries(); + Arrays.sort(syms); + return syms; + } + + public StabSym[] getEntries() { + StabSym[] syms = new StabSym[list.size()]; + list.toArray(syms); + return syms; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterCompilationUnit(java.lang.String, long) + */ + public void enterCompilationUnit(String name, long address) { + StabSym sym = new StabSym(); + sym.name = name; + sym.addr = address; + sym.type = "CU"; + sym.filename = name; + currentCU = sym; + list.add(sym); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitCompilationUnit(long) + */ + public void exitCompilationUnit(long address) { + if (currentCU != null) { + currentCU.size = address; + } + currentCU = null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterInclude(java.lang.String) + */ + public void enterInclude(String name) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitInclude() + */ + public void exitInclude() { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterFunction(java.lang.String, int, boolean, long) + */ + public void enterFunction(String name, DebugType type, boolean isGlobal, long address) { + StabSym sym = new StabSym(); + sym.name = name; + sym.addr = address; + sym.type = "Func"; + if (currentCU != null) { + sym.filename = currentCU.filename; + } + currentFunction = sym; + list.add(sym); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitFunction(long) + */ + public void exitFunction(long address) { + if (currentFunction != null) { + currentFunction.size = address; + } + currentFunction = null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#enterCodeBlock(long) + */ + public void enterCodeBlock(long offset) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#exitCodeBlock(long) + */ + public void exitCodeBlock(long offset) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptStatement(int, long) + */ + public void acceptStatement(int line, long address) { + StabSym sym = new StabSym(); + sym.name = ""; + sym.addr = address; + sym.startLine = line; + sym.type = "SLINE"; + if (currentFunction != null) { + if (currentFunction.startLine == 0) { + currentFunction.startLine = line; + } + currentFunction.endLine = line; + } + if (currentCU != null) { + sym.filename = currentCU.filename; + } + list.add(sym); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptIntegerConst(java.lang.String, long) + */ + public void acceptIntegerConst(String name, int value) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptFloatConst(java.lang.String, double) + */ + public void acceptFloatConst(String name, double value) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptTypeConst(java.lang.String, org.eclipse.cdt.utils.debug.DebugType, int) + */ + public void acceptTypeConst(String name, DebugType type, int value) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptParameter(java.lang.String, int, int, long) + */ + public void acceptParameter(String name, DebugType type, DebugParameterKind kind, long offset) { + StabSym sym = new StabSym(); + sym.name = name; + sym.addr = offset; + sym.type = "PARAM"; + if (currentCU != null) { + sym.filename = currentCU.filename; + } + list.add(sym); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptVariable(java.lang.String, int, int, long) + */ + public void acceptVariable(String name, DebugType type, DebugVariableKind kind, long address) { + StabSym sym = new StabSym(); + sym.name = name; + sym.addr = address; + sym.type = "VAR"; + if (currentCU != null) { + sym.filename = currentCU.filename; + } + list.add(sym); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptCaughtException(java.lang.String, org.eclipse.cdt.utils.debug.DebugType, long) + */ + public void acceptCaughtException(String name, DebugType type, long address) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.debug.IDebugEntryRequestor#acceptTypeDef(java.lang.String, org.eclipse.cdt.utils.debug.DebugType) + */ + public void acceptTypeDef(String name, DebugType type) { + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/Stabs.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/Stabs.java new file mode 100644 index 00000000000..473aa21eeff --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/Stabs.java @@ -0,0 +1,1384 @@ +/********************************************************************** + * 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.debug.stabs; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.utils.debug.DebugArrayType; +import org.eclipse.cdt.utils.debug.DebugBaseType; +import org.eclipse.cdt.utils.debug.DebugCrossRefType; +import org.eclipse.cdt.utils.debug.DebugEnumField; +import org.eclipse.cdt.utils.debug.DebugEnumType; +import org.eclipse.cdt.utils.debug.DebugField; +import org.eclipse.cdt.utils.debug.DebugFunctionType; +import org.eclipse.cdt.utils.debug.DebugParameterKind; +import org.eclipse.cdt.utils.debug.DebugPointerType; +import org.eclipse.cdt.utils.debug.DebugReferenceType; +import org.eclipse.cdt.utils.debug.DebugStructType; +import org.eclipse.cdt.utils.debug.DebugType; +import org.eclipse.cdt.utils.debug.DebugUnknownType; +import org.eclipse.cdt.utils.debug.DebugVariableKind; +import org.eclipse.cdt.utils.debug.IDebugEntryRequestor; +import org.eclipse.cdt.utils.elf.Elf; + +public class Stabs { + + final static String LLLOW = "01000000000000000000000"; + final static String LLHIGH = "0777777777777777777777"; + final static String ULLHIGH = "01777777777777777777777"; + + byte[] stabData; + byte[] stabstrData; + boolean isLe; + + StabSym[] entries; + + boolean inCompilationUnit; + boolean inFunction; + boolean inInclude; + + int bracket; + String currentFile; + + Map mapTypes = new HashMap(); + DebugType voidType = new DebugBaseType("void", 0, false); + + public Stabs(String file) throws IOException { + Elf exe = new Elf(file); + init(exe); + exe.dispose(); + } + + public Stabs(Elf exe) throws IOException { + init(exe); + } + + public Stabs(byte[] stab, byte[] stabstr, boolean le) { + init(stab, stabstr, le); + } + + public StabSym[] getEntries() throws IOException { + if (entries == null) { + parse(); + } + return entries; + } + + public StabSym getEntry(long addr) throws IOException { + if (entries == null) { + parse(); + } + int insertion = Arrays.binarySearch(entries, new Long(addr)); + if (insertion >= 0) { + return entries[insertion]; + } + if (insertion == -1) { + return null; + } + insertion = -insertion - 1; + StabSym entry = entries[insertion - 1]; + if (addr < (entry.addr + entry.size)) { + return entries[insertion - 1]; + } + return null; + } + + void init(Elf exe) throws IOException { + byte[] data = null; + byte[] stabstr = null; + Elf.Section[] sections = exe.getSections(); + for (int i = 0; i < sections.length; i++) { + String name = sections[i].toString(); + if (name.equals(".stab")) { + data = sections[i].loadSectionData(); + } else if (name.equals(".stabstr")) { + stabstr = sections[i].loadSectionData(); + } + } + Elf.ELFhdr header = exe.getELFhdr(); + boolean isLE = header.e_ident[Elf.ELFhdr.EI_DATA] == Elf.ELFhdr.ELFDATA2LSB; + if (data != null && stabstr != null) { + init(data, stabstr, isLE); + } + } + + void init(byte[] stab, byte[] stabstr, boolean le) { + stabData = stab; + stabstrData = stabstr; + isLe = le; + } + + String makeString(long offset) { + StringBuffer buf = new StringBuffer(); + for (; offset < stabstrData.length; offset++) { + byte b = stabstrData[(int) offset]; + if (b == 0) { + break; + } + buf.append((char) b); + } + return buf.toString(); + } + + int read_4_bytes(byte[] bytes, int offset) { + if (isLe) { + return ( + ((bytes[offset + 3] & 0xff) << 24) + + ((bytes[offset + 2] & 0xff) << 16) + + ((bytes[offset + 1] & 0xff) << 8) + + (bytes[offset] & 0xff)); + } + return ( + ((bytes[offset] & 0xff) << 24) + + ((bytes[offset + 1] & 0xff) << 16) + + ((bytes[offset + 2] & 0xff) << 8) + + (bytes[offset + 3] & 0xff)); + } + + short read_2_bytes(byte[] bytes, int offset) { + if (isLe) { + return (short) (((bytes[offset + 1] & 0xff) << 8) + (bytes[offset] & 0xff)); + } + return (short) (((bytes[offset] & 0xff) << 8) + (bytes[offset + 1] & 0xff)); + } + + void parse() { + StabSymsRequestor stabreq = new StabSymsRequestor(); + parse(stabreq); + entries = stabreq.getSortedEntries(); + } + + public void parse(IDebugEntryRequestor requestor) { + List list = new ArrayList(); + long nstab = stabData.length / StabConstant.SIZE; + int i, offset; + String holder = null; + long stroff = 0; + int type = 0; + int other = 0; + short desc = 0; + long value = 0; + for (bracket = i = offset = 0; i < nstab; i++, offset += StabConstant.SIZE) { + + // get the offset for the string; 4 bytes + stroff = read_4_bytes(stabData, offset); + // get the type; 1 byte; + type = 0xff & stabData[offset + 4]; + // get the other + other = 0xff & stabData[offset + 5]; + // get the desc + desc = read_2_bytes(stabData, offset + 6); + // get the value + value = read_4_bytes(stabData, offset + 8); + + String field; + if (stroff > 0) { + field = makeString(stroff); + } else { + field = new String(); + } + // Check for continuation and if any go to the next stab + // until we find a string that is not terminated with a + // continuation line '\\' + // According to the spec all the other fields are duplicated so we + // still have the data. + // From the spec continuation line on AIX is '?' + if (field.endsWith("\\") || field.endsWith("?")) { + field = field.substring(0, field.length() - 1); + if (holder == null) { + holder = field; + } else { + holder += field; + } + continue; + } else if (holder != null) { + field = holder + field; + holder = null; + } + parseStabEntry(requestor, field, type, other, desc, value); + } + // Bring closure. + if (inFunction) { + requestor.exitFunction(-1); + inFunction = false; + } + if (inInclude) { + requestor.exitInclude(); + inInclude = false; + } + if (inCompilationUnit) { + requestor.exitCompilationUnit(value); + inCompilationUnit = false; + } + } + + void parseStabEntry(IDebugEntryRequestor requestor, String field, int type, int other, short desc, long value) { + // Parse the string + switch (type) { + case StabConstant.N_GSYM : + case StabConstant.N_LSYM : + case StabConstant.N_PSYM : + //accept a new variable + parseStabString(requestor, field, value); + break; + + case StabConstant.N_SLINE : + // New statement line + requestor.acceptStatement(desc, value); + break; + + case StabConstant.N_FUN : + if (inFunction) { + requestor.exitFunction(value); + inFunction = false; + } + // Start a new Function + if (field.length() == 0) { + field = " anon "; + } + inFunction = true; + parseStabString(requestor, field, value); + break; + + case StabConstant.N_LBRAC : + if (inFunction) { + requestor.enterCodeBlock(value); + } + bracket++; + break; + + case StabConstant.N_RBRAC : + requestor.exitCodeBlock(value); + bracket--; + break; + + case StabConstant.N_BINCL : + // Start of an include file + requestor.enterInclude(field); + inInclude = true; + break; + + case StabConstant.N_EINCL : + // end of the include + requestor.exitInclude(); + inInclude = false; + break; + + case StabConstant.N_SOL : + // if we had an include it means the end. + if (inInclude) { + requestor.exitInclude(); + inInclude = false; + } + // Start of an include file + requestor.enterInclude(field); + inInclude = true; + break; + + case StabConstant.N_CATCH : + parseStabString(requestor, field, value); + break; + + case StabConstant.N_SO : + // if whitin a function + if (inFunction) { + requestor.exitFunction(-1); + inFunction = false; + } + if (inInclude) { + requestor.exitInclude(); + inInclude = false; + } + if (inCompilationUnit) { + requestor.exitCompilationUnit(value); + inCompilationUnit = false; + } + if (field != null && field.length() > 0) { + // if it ends with "/" do not call the entering yet + // we have to concatenate the next one. + if (field.endsWith("/")) { + currentFile = field; + } else { + if (currentFile != null) { + currentFile += field; + } else { + currentFile = field; + } + requestor.enterCompilationUnit(currentFile, value); + inCompilationUnit = true; + } + } + break; + } + //System.out.println(" " + i + "\t" + Stab.type2String(type) + "\t" + + // other + "\t\t" + + // desc + "\t" + Long.toHexString(value) + "\t" + + stroff + "\t\t" + // +name); + } + + void parseStabString(IDebugEntryRequestor requestor, String field, long value) { + + StringField sf = new StringField(field); + + switch (sf.getSymbolDescriptor()) { + // C++ nested symbol. + case ':' : + break; + + // Parameter pass by reference in register. + case 'a' : + { + String information = sf.getTypeInformation(); + String paramName = sf.getName(); + DebugParameterKind paramKind = DebugParameterKind.REGISTER_REFERENCE; + DebugType paramType = parseStabType("", information); + requestor.acceptParameter(paramName, paramType, paramKind, value); + } + break; + + // Sun Based variable + case 'b' : + break; + + // symbol descriptor indicates that this stab represents a + // constant. + case 'c' : + { + String name = sf.getName(); + String information = sf.getTypeInformation(); + parseStabConstant(requestor, name, information, value); + } + break; + + // Conformant array bound(Pascal). + // Nave of a caught exception GNU C++ + case 'C' : + { + String excName = sf.getName(); + String information = sf.getTypeInformation(); + DebugType excType = parseStabType("", information); + requestor.acceptCaughtException(excName, excType, value); + } + break; + + // File scope function. + case 'f' : + // Global function. + case 'F' : + { + String funcName = sf.getName(); + String funcInfo = sf.getTypeInformation(); + DebugType funcType = parseStabType("", funcInfo); + boolean funcGlobal = sf.getSymbolDescriptor() == 'F'; + requestor.enterFunction(funcName, funcType, funcGlobal, value); + } + break; + // Global variable + case 'G' : + { + String varName = sf.getName(); + String varInfo = sf.getTypeInformation(); + DebugVariableKind varKind = DebugVariableKind.GLOBAL; + DebugType varType = parseStabType("", varInfo); + requestor.acceptVariable(varName, varType, varKind, value); + } + break; + + // ??? + case 'i' : + break; + // Internal(nested) procedure. + case 'I' : + break; + // Internal/nested function. + case 'J' : + break; + // Label name + case 'L' : + break; + // Module + case 'm' : + break; + + // Argument list parameter + case 'p' : + { + String paramName = sf.getName(); + String paramInfo = sf.getTypeInformation(); + DebugParameterKind paramKind = DebugParameterKind.STACK; + DebugType paramType = parseStabType("", paramInfo); + requestor.acceptParameter(paramName, paramType, paramKind, value); + } + break; + + // Paramater in floating point register. + case 'D' : + // register parameter or prototype f function referenced by the + // file. + case 'P' : + // Register Parameter + case 'R' : + { + String paramName = sf.getName(); + String paramInfo = sf.getTypeInformation(); + DebugParameterKind paramKind = DebugParameterKind.REGISTER; + DebugType paramType = parseStabType("", paramInfo); + requestor.acceptParameter(paramName, paramType, paramKind, value); + } + break; + + // static procedure + case 'Q' : + break; + + // Floating point register variable + case 'd' : + // Never use, according to the + // Register variable + case 'r' : + { + String varName = sf.getName(); + String varInfo = sf.getTypeInformation(); + DebugVariableKind varKind = DebugVariableKind.REGISTER; + DebugType varType = parseStabType("", varInfo); + requestor.acceptVariable(varName, varType, varKind, value); + } + break; + + // File scope variable + case 'S' : + { + String varName = sf.getName(); + String varInfo = sf.getTypeInformation(); + DebugVariableKind varKind = DebugVariableKind.STATIC; + DebugType varType = parseStabType("", varInfo); + requestor.acceptVariable(varName, varType, varKind, value); + } + break; + + // Type name + case 't' : + { + String name = sf.getName(); + String infoField = sf.getTypeInformation(); + DebugType type = parseStabType(name, infoField); + requestor.acceptTypeDef(name, type); + } + break; + + // Enumeration, structure or union + case 'T' : + { + String infoField = sf.getTypeInformation(); + // According to the doc 't' can follow the 'T' + if (infoField.length() > 0 && infoField.charAt(0) == 't') { + String s = infoField.substring(1); + parseStabString(requestor, field, value); + } else { + // Just register the type. + String name = sf.getName(); + parseStabType(name, infoField); + } + } + break; + + // Parameter passed by reference. + case 'v' : + { + String paramName = sf.getName(); + String paramInfo = sf.getTypeInformation(); + DebugParameterKind paramKind = DebugParameterKind.REFERENCE; + DebugType paramType = parseStabType("", paramInfo); + requestor.acceptParameter(paramName, paramType, paramKind, value); + } + break; + + // Procedure scope static variable + case 'V' : + { + String varName = sf.getName(); + String varInfo = sf.getTypeInformation(); + DebugVariableKind varKind = DebugVariableKind.LOCAL_STATIC; + DebugType varType = parseStabType("", varInfo); + requestor.acceptVariable(varName, varType, varKind, value); + } + break; + + // Conformant array + case 'x' : + break; + + // Function return variable + case 'X' : + // local variable + case 's' : + // Variable on the stack + case '-' : + default : + { + String varName = sf.getName(); + String varInfo = sf.getTypeInformation(); + DebugVariableKind varKind = DebugVariableKind.LOCAL; + DebugType varType = parseStabType("", varInfo); + requestor.acceptVariable(varName, varType, varKind, value); + } + break; + } + } + + DebugType parseStabType(String name, String typeInformation) { + try { + Reader reader = new StringReader(typeInformation); + return parseStabType(name, reader); + } catch (IOException e) { + } + return new DebugUnknownType(name); + } + + DebugType parseStabType(String name, Reader reader) throws IOException { + return parseStabType(name, null, reader); + } + + DebugType parseStabType(String name, TypeInformation oldType, Reader reader) throws IOException { + + TypeInformation typeInfo = new TypeInformation(reader); + DebugType type = null; + switch (typeInfo.getTypeDescriptor()) { + + // Method (C++) + case '#' : + break; + + // Reference (C++) + case '&' : + { + DebugType subType = parseStabType("", reader); + type = new DebugReferenceType(subType); + } + break; + + // Member (C++) class and variable + case '@' : + break; + + // pointer type. + case '*' : + { + DebugType subType = parseStabType("", reader); + type = new DebugPointerType(subType); + } + break; + + // Builtin type define byt Sun stabs + // Pascal Type + case 'b' : + // Builtin floating type + case 'R' : + // Wide character + case 'w' : + // Builtin flaoting point type. + case 'g' : + // Complex buitin type. + case 'c' : + { + char desc = typeInfo.getTypeDescriptor(); + type = parseStabBuiltinType(name, desc, reader); + } + break; + + // Array. + case 'a' : + case 'A' : + type = parseStabArrayType(name, reader); + break; + + // Volatile-qualified type + case 'B' : + break; + + // Cobol + case 'C' : + break; + + // File type + case 'd' : + break; + + // N-dimensional dynamic array. + case 'D' : + break; + + // Enumeration type + case 'e' : + type = parseStabEnumType(name, reader); + break; + + // N-dimensional subarray + case 'E' : + break; + + // Function type + case 'f' : + { + DebugType subType = parseStabType("", reader); + type = new DebugFunctionType(subType); + } + break; + + // Pascal Function parameter + case 'F' : + break; + + // COBOL Group + case 'G' : + break; + + // Imported type + case 'i' : + break; + + // Const-qualified type + case 'k' : + break; + + // Cobol file desc. + case 'K' : + break; + + // Multiple instance type + case 'M' : + break; + + // string type: + case 'n' : + break; + + // Stringpt: + case 'N' : + break; + + // Opaque type + case 'o' : + break; + + // Procedure + case 'p' : + break; + + // Packed array + case 'P' : + break; + + // Range. example: + case 'r' : + type = parseStabRangeType(name, typeInfo.getTypeNumber(), reader); + break; + + // Structure type + case 's' : + type = parseStabStructType(name, typeInfo.getTypeNumber(), false, reader); + break; + + // Union + case 'u' : + type = parseStabStructType(name, typeInfo.getTypeNumber(), true, reader); + break; + + // Set type + case 'S' : + break; + + // variant record. + case 'v' : + break; + + // Cross-reference + case 'x' : + type = parseStabCrossRefType(name, reader); + break; + + // ??? + case 'Y' : + break; + + // gstring + case 'z' : + break; + + // Reference to a previously define type. + case '(' : + case '-' : + default : + if (typeInfo.isTypeDefinition()) { + type = parseStabType(name, typeInfo, reader); + } else { + // check for void + if (oldType != null && oldType.getTypeNumber().equals(typeInfo.getTypeNumber())) { + type = voidType; + } else { + type = getDebugType(typeInfo.getTypeNumber()); + } + } + } + + // register the type. + if (type != null && typeInfo.isTypeDefinition()) { + mapTypes.put(typeInfo.getTypeNumber(), type); + } + if (type == null) { + type = new DebugUnknownType(name); + } + return type; + } + + /** + * @param name + * @param reader + * @return + */ + DebugType parseStabCrossRefType(String name, Reader reader) throws IOException { + StringBuffer sb = new StringBuffer(); + int c = reader.read(); + if (c == 's') { + sb.append("struct "); + } else if (c == 'u') { + sb.append("union "); + } else if (c == 'e') { + sb.append("enum "); + } else { + sb.append((char) c); + } + while ((c = reader.read()) != -1) { + if (c == ':') { + break; + } + sb.append((char) c); + } + return new DebugCrossRefType(null, name, sb.toString()); + } + + /** + * @param name + * @param desc + * @param reader + * @return + */ + private DebugType parseStabBuiltinType(String name, char desc, Reader reader) throws IOException { + DebugType builtinType = null; + switch (desc) { + case 'b' : + { + // get the signed + int signed = reader.read(); + reader.mark(1); + // get the flag + int charFlag = reader.read(); + if (charFlag != 'c') { + reader.reset(); + } + int c; + StringBuffer sb = new StringBuffer(); + + // get the width + int width = 0; + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + try { + String token = sb.toString(); + width = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + + sb.setLength(0); + + // get the offset + int offset = 0; + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + try { + String token = sb.toString(); + offset = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + + sb.setLength(0); + + // get the nbits + int nbits = 0; + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + try { + String token = sb.toString(); + nbits = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + builtinType = new DebugBaseType(name, nbits / 8, signed == 'u'); + } + break; + + case 'w' : + { + builtinType = new DebugBaseType(name, 8, false); + } + break; + + case 'R' : + { + int c; + StringBuffer sb = new StringBuffer(); + + // get the fp-Type + int fpType = 0; + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + try { + String token = sb.toString(); + fpType = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + + sb.setLength(0); + + // get the bytes + int bytes = 0; + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + try { + String token = sb.toString(); + bytes = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + builtinType = new DebugBaseType(name, bytes, false); + } + break; + + case 'c' : + case 'g' : + { + DebugType type = parseStabType(name, reader); + int c = reader.read(); // semicolon + StringBuffer sb = new StringBuffer(); + int nbits = 0; + while ((c = reader.read()) != -1) { + sb.append((char) c); + } + try { + String token = sb.toString(); + nbits = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + builtinType = new DebugBaseType(name, nbits / 8, false); + } + break; + + } + return builtinType; + } + + DebugType parseStabArrayType(String name, Reader reader) throws IOException { + // Format of an array type: + // "ar;lower;upper;". + + // we only understand range for an array. + int c = reader.read(); + if (c == 'r') { + DebugType index_type = parseStabType("", reader); + + c = reader.read(); + // Check ';' + if (c != ';') { + // bad array type + return null; + } + + StringBuffer sb = new StringBuffer(); + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + // Check ';' + if (c != ';') { + // bad array type + return null; + } + + // lower index + int lower = 0; // should always be zero for C/C++ + try { + String token = sb.toString(); + lower = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + + sb.setLength(0); + + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + // Check ';' + if (c != ';') { + // bad array type + return null; + } + + int upper = 0; + // upper index + try { + String token = sb.toString(); + upper = Integer.parseInt(token); + } catch (NumberFormatException e) { + } + + // Check ';' + if (c != ';') { + // bad array type + return null; + } + + // The array_content_type + DebugType subType = parseStabType("", reader); + + return new DebugArrayType(subType, upper - lower + 1); + } + return new DebugArrayType(new DebugUnknownType(name), 0); + } + + /** + * _Bool:t(0,20)=eFalse:0,True:1,; fruit:T(1,4)=eapple:0,orange:1,; + * + * @param name + * @param attributes + * @return + */ + DebugType parseStabEnumType(String name, Reader reader) throws IOException { + List list = new ArrayList(); + String fieldName = null; + StringBuffer sb = new StringBuffer(); + int c; + while ((c = reader.read()) != -1) { + if (c == ':') { + fieldName = sb.toString(); + sb.setLength(0); + } else if (c == ',') { + if (fieldName != null && fieldName.length() > 0) { + String value = sb.toString(); + int fieldValue = 0; + try { + fieldValue = Integer.decode(value).intValue(); + } catch (NumberFormatException e) { + } + list.add(new DebugEnumField(fieldName, fieldValue)); + } + fieldName = null; + sb.setLength(0); + } else if (c == ';') { + break; + } else { + sb.append((char) c); + } + } + DebugEnumField[] fields = new DebugEnumField[list.size()]; + list.toArray(fields); + return new DebugEnumType(name, fields); + } + + /** + * For C lang -- node:T(1,5)=s12i:(0,1),0,32;j:(0,1),32,32;next:(1,6)=*(1,5),64,32;; + * + * @param name + * @param typeNumber + * @param union + * @param reader + * @return + */ + DebugType parseStabStructType(String name, TypeNumber typeNumber, boolean union, Reader reader) throws IOException { + int c; + StringBuffer sb = new StringBuffer(); + while ((c = reader.read()) != -1) { + if (!Character.isDigit((char) c)) { + reader.reset(); + break; + } + reader.mark(1); + sb.append((char) c); + } + String number = sb.toString(); + int size = 0; + try { + size = Integer.decode(number).intValue(); + } catch (NumberFormatException e) { + } + DebugStructType structType = new DebugStructType(name, size, union); + // We have to register it right away, some field may + // need the tag if they self reference via a pointer. + mapTypes.put(typeNumber, structType); + + // parse the fields. + parseStabStructField(structType, reader); + return structType; + } + + void parseStabStructField(DebugStructType structType, Reader reader) throws IOException { + // get the field name. + StringBuffer sb = new StringBuffer(); + int c; + while ((c = reader.read()) != -1) { + if (c != ':') { + sb.append((char) c); + } else { + break; + } + } + // Sanity check: We should have ':' if no bailout + if (c != ':') { + return; + } + String name = sb.toString(); + + // get the type of the field + DebugType fieldType = parseStabType("", reader); + + c = reader.read(); + // Sanity check: we should have ',' here. + if (c != ',') { + return; + } + + // the offset of the struct of the field. + sb.setLength(0); + while ((c = reader.read()) != -1 && c != ',') { + sb.append((char) c); + } + // Sanity check: we should have ',' + if (c != ',') { + return; + } + int offset = 0; + try { + offset = Integer.decode(sb.toString()).intValue(); + } catch (NumberFormatException e) { + } + + // the number of bits of the struct of the field. + sb.setLength(0); + while ((c = reader.read()) != -1 && c != ';') { + sb.append((char) c); + } + // Check we need ';' + if (c != ';') { + return; + } + int bits = 0; + try { + bits = Integer.decode(sb.toString()).intValue(); + } catch (NumberFormatException e) { + } + + // add the new field. + structType.addField(new DebugField(name, fieldType, offset, bits)); + + // absorb the trailing ';' + //reader.read(); + // continue the parsing recursively. + parseStabStructField(structType, reader); + } + + DebugType parseStabRangeType(String name, TypeNumber number, Reader reader) throws IOException { + // int:t(0,1)=r(0,1);-2147483648;2147483647; + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + DebugType rangeType = null; + + // get the index_type + TypeNumber typeNumber = new TypeNumber(reader); + + int c = reader.read(); + // Sanity we should have a semicolon + if (c != ';') { + // bad range type; + return new DebugUnknownType(name); + } + + StringBuffer sb = new StringBuffer(); + + // read the lowerBound. + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + // Sanity we should have a semicolon + if (c != ';') { + // bad range type; + return new DebugUnknownType(name); + } + + boolean overflowLowerBound = false; + String lowerBoundString = sb.toString(); + long lowerBound = 0; + try { + lowerBound = Long.decode(lowerBoundString).longValue(); + } catch (NumberFormatException e) { + overflowLowerBound = true; + } + + sb.setLength(0); + + // read the upperBound. + while ((c = reader.read()) != -1) { + if (c == ';') { + break; + } + sb.append((char) c); + } + // Sanity we should have a semicolon + if (c != ';') { + // bad range type; + return new DebugUnknownType(name); + } + + boolean overflowUpperBound = false; + long upperBound = 0; + String upperBoundString = sb.toString(); + try { + upperBound = Long.decode(upperBoundString).longValue(); + } catch (NumberFormatException e) { + overflowUpperBound = true; + } + + if (typeNumber == null) { + typeNumber = new TypeNumber(0, 0); + } + + boolean self = typeNumber.equals(number); + + // Probably trying 64 bits range like "long long" + if (overflowLowerBound || overflowUpperBound) { + + if (lowerBoundString.equals(LLLOW) && upperBoundString.equals(LLHIGH)) + rangeType = new DebugBaseType(name, 8, false); + if (!overflowLowerBound && lowerBound == 0 && upperBoundString.equals(ULLHIGH)) + rangeType = new DebugBaseType(name, 8, true); + } else { + + if (lowerBound == 0 && upperBound == -1) { + // if the lower bound is 0 and the upper bound is -1, + // it means unsigned int + if (name.equals("long long int")) { + rangeType = new DebugBaseType(name, 8, true); + } else if (name.equals("long long unsigned int")) { + rangeType = new DebugBaseType(name, 8, true); + } else { + rangeType = new DebugBaseType(name, 4, true); + } + } else if (upperBound == 0 && lowerBound > 0) { + // if The upper bound is 0 and the lower bound is positive + // it is a floating point and the lower bound is the number of bytes + rangeType = new DebugBaseType(name, (int) lowerBound, true); + } else if (lowerBound == -128 && upperBound == 127) { + // signed char; + rangeType = new DebugBaseType(name, 1, false); + } else if (self && lowerBound == 0 && upperBound == 127) { + // C/C++ specific + rangeType = new DebugBaseType(name, 1, false); + } else if (self && lowerBound == 0 && upperBound == 255) { + // unsigned char + rangeType = new DebugBaseType(name, 1, true); + } else if (lowerBound == -32768 && upperBound == 32767) { + // signed short + rangeType = new DebugBaseType(name, 2, false); + } else if (self && lowerBound == 0 && upperBound == 65535) { + // unsigned short + rangeType = new DebugBaseType(name, 2, true); + } else if (lowerBound == -2147483648 && upperBound == 2147483647) { + // int + rangeType = new DebugBaseType(name, 4, false); + } + } + return rangeType; + } + + void parseStabConstant(IDebugEntryRequestor requestor, String name, String field, long value) { + try { + parseStabConstant(requestor, name, new StringReader(field), value); + } catch (IOException e) { + // + } + } + + void parseStabConstant(IDebugEntryRequestor requestor, String name, Reader reader, long value) throws IOException { + int c = reader.read(); + if (c == '=') { + c = reader.read(); + switch (c) { + // Boolean constant. + // c=bvalue or c=bvalue + // value is a numeric value: 0 fo false and 1 for true. + // Not supported by GDB. + case 'b' : + break; + + // Character constant. + // c=cvalue + // value is the numeric value of the constant. + // Not supported by GDB. + case 'c' : + break; + + // Constant whose value van be represented as integral. + // c=e type-information, value + // type-information is the type of the constant. + // value is the numeric value of the constant. + // This is usually use for enumeration constants. + case 'e' : + { + int val = 0; + DebugType type = parseStabType("", reader); + c = reader.read(); + if (c == ',') { + StringBuffer sb = new StringBuffer(); + while ((c = reader.read()) != -1) { + sb.append((char) c); + } + try { + String s = sb.toString(); + val = Integer.decode(s).intValue(); + } catch (NumberFormatException e) { + } + } + requestor.acceptTypeConst(name, type, val); + } + break; + + // Integer constant. + // c=ivalue + // value is the numeric value; + case 'i' : + { + int val = 0; + StringBuffer sb = new StringBuffer(); + while ((c = reader.read()) != -1) { + sb.append((char) c); + } + try { + String s = sb.toString(); + val = Integer.decode(s).intValue(); + } catch (NumberFormatException e) { + } catch (IndexOutOfBoundsException e) { + } + requestor.acceptIntegerConst(name, val); + } + break; + + // Real constant. + // c=rvalue + // value is the real value, which can be INF or QNAN or SNAN + // preceded + // by a sign. + case 'r' : + { + double val = 0; + StringBuffer sb = new StringBuffer(); + while ((c = reader.read()) != -1) { + sb.append((char) c); + } + try { + String s = sb.toString(); + if (s.equals("-INF")) { + val = Double.NEGATIVE_INFINITY; + } else if (s.equals("INF")) { + val = Double.POSITIVE_INFINITY; + } else if (s.equals("QNAN")) { + val = Double.NaN; + } else if (s.equals("SNAN")) { + val = Double.NaN; + } else { + val = Double.parseDouble(s); + } + } catch (NumberFormatException e) { + } catch (IndexOutOfBoundsException e) { + } + requestor.acceptFloatConst(name, val); + } + break; + + // String constant. + // c=svalue + // value is a strinc encosed in either ' in which case ' are + // escaped or + // " in which case " are escaped. + // Not supported by GDB. + case 's' : + break; + + // Set constant. + // C/C++ does not have set + // Not supported by GDB. + case 'S' : + break; + } + } + } + + DebugType getDebugType(TypeNumber tn) { + return (DebugType) mapTypes.get(tn); + } + + public void print() { + for (int i = 0; i < entries.length; i++) { + StabSym entry = entries[i]; + System.out.println(entry); + } + } + + public static void main(String[] args) { + try { + Stabs stabs = new Stabs(args[0]); + stabs.parse(); + stabs.print(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabsAddr2line.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabsAddr2line.java new file mode 100644 index 00000000000..2704745615b --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StabsAddr2line.java @@ -0,0 +1,110 @@ +/********************************************************************** + * 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.debug.stabs; + +import java.io.IOException; + +import org.eclipse.cdt.utils.elf.Elf; + +/** + * StabsAddr2ine + * + * @author alain + */ +public class StabsAddr2line { + + Stabs stabs; + + public StabsAddr2line(String file) throws IOException { + stabs = new Stabs(file); + } + + public StabsAddr2line(Elf elf) throws IOException { + stabs = new Stabs(elf); + } + + /* + * (non-Javadoc) + * + * @see IAddr2line#dispose() + */ + public void dispose() { + } + + /* + * (non-Javadoc) + * + * @see IAddr2line#getStartLine(long) + */ + public int getStartLine(long address) throws IOException { + StabSym entry = stabs.getEntry(address); + if (entry != null) { + return entry.startLine; + } + return 0; + } + + /* + * (non-Javadoc) + * + * @see IAddr2line#getEndLine(long) + */ + public int getEndLine(long address) throws IOException { + StabSym entry = stabs.getEntry(address); + if (entry != null) { + return entry.endLine; + } + return 0; + } + + /* + * (non-Javadoc) + * + * @see IAddr2line#getFunction(long) + */ + public String getFunction(long address) throws IOException { + StabSym entry = stabs.getEntry(address); + if (entry != null) { + return entry.name; + } + return null; + } + + /* + * (non-Javadoc) + * + * @see IAddr2line#getFileName(long) + */ + public String getFileName(long address) throws IOException { + StabSym entry = stabs.getEntry(address); + if (entry != null) { + return entry.filename; + } + return null; + } + + public static void main(String[] args) { + try { + StabsAddr2line addr2line = new StabsAddr2line(args[0]); + long address = Integer.decode(args[1]).longValue(); + int startLine = addr2line.getStartLine(address); + int endLine = addr2line.getEndLine(address); + String function = addr2line.getFunction(address); + String filename = addr2line.getFileName(address); + System.out.println(Long.toHexString(address)); + System.out.println(filename + ":" + function + ":" + startLine + ":" + endLine); + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StringField.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StringField.java new file mode 100644 index 00000000000..b4a436a013b --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/StringField.java @@ -0,0 +1,102 @@ +/********************************************************************** + * 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.debug.stabs; + + +/** + * Format: string_field = name ':' symbol-descriptor type-information + */ +public class StringField { + String name; + char symbolDescriptor; + String typeInformation; + + public StringField(String s) { + parseStringField(s.toCharArray()); + } + + public String getName() { + return name; + } + + public char getSymbolDescriptor() { + return symbolDescriptor; + } + + public String getTypeInformation() { + return typeInformation; + } + + /** + * Format: string_field = name ':' symbol-descriptor type-information + */ + void parseStringField(char[] array) { + int index = 0; + + // Some String field may contain format like: + // "foo::bar::baz:t5=*6" in that case the name is "foo::bar::baz" + char prev = 0; + for (; index < array.length; index++) { + char c = array[index]; + if (c == ':' && prev != ':') { + break; + } + prev = c; + } + + if (index < array.length) { + name = new String(array, 0, index); + } else { + name = new String(array); + } + + /* FIXME: Sometimes the special C++ names start with '.'. */ + if (name.length() > 1 && name.charAt(0) == '$') { + switch (name.charAt(1)) { + case 't' : + name = "this"; + break; + case 'v' : + /* Was: name = "vptr"; */ + break; + case 'e' : + name = "eh_throw"; + break; + case '_' : + /* This was an anonymous type that was never fixed up. */ + break; + case 'X' : + /* SunPRO (3.0 at least) static variable encoding. */ + break; + default : + name = "unknown C++ encoded name"; + break; + } + } + + // get the symbol descriptor + if (index < array.length) { + index++; + if (Character.isLetter(array[index])) { + symbolDescriptor = array[index]; + index++; + } + } + + // get the type-information + if (index < array.length) { + typeInformation = new String(array, index, array.length - index); + } else { + typeInformation = new String(); + } + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/TypeInformation.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/TypeInformation.java new file mode 100644 index 00000000000..b7d78cb47d9 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/TypeInformation.java @@ -0,0 +1,75 @@ +/********************************************************************** + * 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.debug.stabs; + +import java.io.IOException; +import java.io.Reader; + + + +public class TypeInformation { + TypeNumber typeNumber; + char typeDescriptor; + boolean isTypeDefinition; + + public TypeInformation(Reader reader) { + parseTypeInformation(reader); + } + + public TypeNumber getTypeNumber() { + return typeNumber; + } + + public char getTypeDescriptor() { + return typeDescriptor; + } + + public boolean isTypeDefinition() { + return isTypeDefinition; + } + + /** + * int:t(0,1)=r(0,1);-2147483648;2147483647; + * We receieve as input: + * (0,1)=r(0,1);-2147483648;2147483647; + * typeNumber: (0,1) + * typeDescriptor: r + * attributes: (0,1);-2147483648;2147483647; + * isTypeDefinition = true; + */ + void parseTypeInformation(Reader reader) { + try { + typeNumber = new TypeNumber(reader); + reader.mark(1); + int c = reader.read(); + if (c == '=') { + isTypeDefinition = true; + reader.mark(1); + c = reader.read(); + if (isTypeDescriptor((char)c)) { + typeDescriptor = (char)c; + } else { + reader.reset(); + } + } else { + reader.reset(); + } + } catch (IOException e) { + } + } + + boolean isTypeDescriptor(char c) { + return Character.isLetter(c) || c == '=' || c == '#' || c =='*' + || c == '&' || c == '@'; + } +} + diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/TypeNumber.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/TypeNumber.java new file mode 100644 index 00000000000..469ce9fba78 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/stabs/TypeNumber.java @@ -0,0 +1,106 @@ +/********************************************************************** + * 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.debug.stabs; + +import java.io.IOException; +import java.io.Reader; + + +public class TypeNumber { + + int typeno; + int fileno; + + public TypeNumber(int f, int t) { + fileno = f; + typeno = t; + } + + public TypeNumber(Reader reader) { + parseTypeNumber(reader); + } + + public int getTypeNo() { + return typeno; + } + + public int getFileNo() { + return fileno; + } + + public boolean equals(Object obj) { + if (obj instanceof TypeNumber) { + TypeNumber tn = (TypeNumber)obj; + return tn.typeno == typeno && tn.fileno == fileno; + } + return super.equals(obj); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return fileno*10 + typeno; + } + + void parseTypeNumber(Reader reader) { + try { + int c = reader.read(); + char ch = (char)c; + if (c == -1) { + return; + } else if (ch == '(') { + StringBuffer sb = new StringBuffer(); + while ((c = reader.read()) != -1) { + ch = (char)c; + if (ch == ')') { + try { + typeno = Integer.parseInt(sb.toString()); + } catch (NumberFormatException e) { + } + break; + } else if (ch == ',') { + try { + fileno = Integer.parseInt(sb.toString()); + } catch (NumberFormatException e) { + } + sb.setLength(0); + } else if (Character.isDigit(ch)) { + sb.append(ch); + } else { + break; + } + } + } else if (Character.isDigit(ch)) { + StringBuffer sb = new StringBuffer(); + sb.append(ch); + reader.mark(1); + while ((c = reader.read()) != -1) { + ch = (char)c; + if (Character.isDigit(ch)) { + sb.append(ch); + } else { + reader.reset(); + break; + } + } + try { + typeno = Integer.parseInt(sb.toString()); + } catch (NumberFormatException e) { + } + } + } catch (IOException e) { + } + } + +} + diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/Stabs.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/Stabs.java deleted file mode 100644 index 5253ca2a27c..00000000000 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/Stabs.java +++ /dev/null @@ -1,458 +0,0 @@ -/********************************************************************** - * 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.stabs; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.cdt.utils.elf.Elf; - -public class Stabs { - - byte[] stabData; - byte[] stabstrData; - boolean isLe; - Entry[] entries; - - public class Entry implements Comparable{ - public long addr; - public long size; - public int startLine; - public String string; - - public Entry(String s) { - string = s; - } - public int compareTo(Object obj) { - long thisVal = 0; - long anotherVal = 0; - if (obj instanceof Entry) { - Entry entry = (Entry) obj; - thisVal = this.addr; - anotherVal = entry.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)); - } - - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("Name: ").append(string).append("\n"); - buf.append("\taddress:").append("0x").append(Long.toHexString(addr)).append("\n"); - buf.append("\tstartLine:").append(startLine).append("\n"); - //buf.append("\tName:").append(string).append("\n"); - return buf.toString(); - } - } - - public abstract class LocatableEntry extends Entry { - public String filename; - - public LocatableEntry(String s) { - super(s); - } - } - - public class Variable extends LocatableEntry { - public int kind; - public Function function; - - public Variable(String s) { - super(s); - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("Variable: "); - buf.append(super.toString()); - buf.append("\tkind:").append(kind).append("\n"); - buf.append("\tfilename:").append(filename).append("\n"); - return buf.toString(); - } - } - - public class Function extends LocatableEntry { - public int endLine; - public ArrayList lines; - public ArrayList variables; - - public Function(String s) { - super(s); - variables = new ArrayList(); - lines = new ArrayList(); - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("Function: "); - buf.append(super.toString()); - buf.append("\tendLine:").append(endLine).append("\n"); - buf.append("\tfilename:").append(filename).append("\n"); - buf.append("\tSource code: "); - for (int i = 0; i < lines.size(); i++) { - buf.append(" ").append(lines.get(i)); - } - buf.append("\n"); - buf.append("\tVariables\n"); - for (int i = 0; i < variables.size(); i++) { - buf.append("\t\t").append("[" + i + "]").append("\n"); - buf.append("\t\t\t").append(variables.get(i)).append("\n"); - } - return buf.toString(); - } - } - - public class Include extends Entry { - int index; - - public Include(String s) { - super(s); - } - - public String toString() { - return super.toString() + "\tindex:" + index + "\n"; - } - } - - // type-information = type-number | type-definition - // type-number = type-reference - // type-reference = number | '(' number ',' number ')' - // type-definition = type_number '=' (type-descriptor | type-reference) - public class TypeInformation { - int typeNumber; - int fileNumber; - boolean isTypeDefinition; - - public TypeInformation(String s) { - parserTypeInformation(s.toCharArray()); - } - - void parserTypeInformation(char[] array) { - } - } - - /** - * Format: string_field = name ':' symbol-descriptor type-information - */ - public class StringField { - String name; - char symbolDescriptor; - String typeInformation; - - public StringField(String s) { - parseStringField(s.toCharArray()); - } - - /** - * Format: string_field = name ':' symbol-descriptor type-information - */ - void parseStringField(char[] array) { - int index = 0; - - // Some String field may contain format like: - // "foo::bar::baz:t5=*6" in that case the name is "foo::bar::baz" - char prev = 0; - for (int i = 0; index < array.length; index++) { - char c = array[index]; - if (prev != ':') { - break; - } - prev = c; - } - - if (index < array.length) { - name = new String(array, 0, index); - } else { - name = new String(array); - } - - // get the symbol descriptor - if (index < array.length) { - index++; - symbolDescriptor = array[index]; - } - - // get the type-information - if (index < array.length) { - typeInformation = new String(array, index, array.length); - } else { - typeInformation = new String(); - } - } - } - - public String makeString(long offset) { - StringBuffer buf = new StringBuffer(); - for (; offset < stabstrData.length; offset++) { - byte b = stabstrData[(int) offset]; - if (b == 0) { - break; - } - buf.append((char) b); - } - return buf.toString(); - } - - public Stabs(byte[] stab, byte[] stabstr, boolean le) { - stabData = stab; - stabstrData = stabstr; - isLe = le; - } - - public Entry[] getEntries() throws IOException { - if (entries == null) { - parse(); - } - return entries; - } - - public Entry getEntry(long addr) throws IOException { - if (entries == null) { - parse(); - } - int insertion = Arrays.binarySearch(entries, new Long(addr)); - if (insertion >= 0) { - return entries[insertion]; - } - if (insertion == -1) { - return null; - } - insertion = -insertion - 1; - Entry entry = entries[insertion - 1]; - if (addr < (entry.addr + entry.size)) { - return entries[insertion - 1]; - } - return null; - } - - void parse() throws IOException { - - List list = new ArrayList(); - - long nstab = stabData.length / StabConstant.SIZE; - int i, offset, bracket; - int includeCount = 0; - Function currentFunction = null; - String currentFile = ""; - String holder = null; - - for (bracket = i = offset = 0; i < nstab; i++, offset += StabConstant.SIZE) { - - long stroff = 0; - int type = 0; - int other = 0; - short desc = 0; - long value = 0; - String name = new String(); - - // get the offset for the string; 4 bytes - if (isLe) { - stroff = - (((stabData[offset + 3] & 0xff) << 24) - + ((stabData[offset + 2] & 0xff) << 16) - + ((stabData[offset + 1] & 0xff) << 8) - + (stabData[offset] & 0xff)); - } else { - stroff = - (((stabData[offset] & 0xff) << 24) - + ((stabData[offset + 1] & 0xff) << 16) - + ((stabData[offset + 2] & 0xff) << 8) - + (stabData[offset + 3] & 0xff)); - } - - if (stroff > 0) { - name = makeString(stroff); - } - - // Check for continuation and if any go to the next stab - // until we find a string that is not terminated with a continuation line '\\' - // According to the spec all the other fields are duplicated so we still have the data. - // From the spec continuation line on AIX is '?' - if (name.endsWith("\\") || name.endsWith("?")) { - name = name.substring(0, name.length() - 1); - if (holder == null) { - holder = name; - } else { - holder += name; - } - continue; - } else if (holder != null) { - name = holder + name; - holder = null; - } - - /* FIXME: Sometimes the special C++ names start with '.'. */ - if (name.length() > 1 && name.charAt(0) == '$') { - switch (name.charAt(1)) { - case 't' : - name = "this"; - break; - case 'v' : - /* Was: name = "vptr"; */ - break; - case 'e' : - name = "eh_throw"; - break; - case '_' : - /* This was an anonymous type that was never fixed up. */ - break; - case 'X' : - /* SunPRO (3.0 at least) static variable encoding. */ - break; - default : - name = "unknown C++ encoded name"; - break; - } - } - - // get the type; 1 byte; - type = 0xff & stabData[offset + 4]; - - // get the other - other = 0xff & stabData[offset + 5]; - - // get the desc - if (isLe) { - desc = (short) (((stabData[offset + 7] & 0xff) << 8) + (stabData[offset + 6] & 0xff)); - } else { - desc = (short) (((stabData[offset + 6] & 0xff) << 8) + (stabData[offset + 7] & 0xff)); - } - - // get the value - if (isLe) { - value = - (((stabData[offset + 11] & 0xff) << 24) - + ((stabData[offset + 10] & 0xff) << 16) - + ((stabData[offset + 9] & 0xff) << 8) - + (stabData[offset + 8] & 0xff)); - } else { - value = - (((stabData[offset + 8] & 0xff) << 24) - + ((stabData[offset + 9] & 0xff) << 16) - + ((stabData[offset + 10] & 0xff) << 8) - + (stabData[offset + 11] & 0xff)); - } - - // Parse the string - switch (type) { - case StabConstant.N_GSYM : - case StabConstant.N_LSYM : - case StabConstant.N_PSYM : - Variable variable = new Variable(name); - variable.kind = type; - variable.addr = value; - variable.startLine = desc; - variable.function = currentFunction; - variable.filename = currentFile; - list.add(variable); - if (currentFunction != null) { - currentFunction.variables.add(variable); - } - break; - case StabConstant.N_SLINE : - if (currentFunction != null) { - if (currentFunction.startLine == 0) { - currentFunction.endLine = currentFunction.startLine = desc; - } else { - currentFunction.endLine = desc; - currentFunction.size = value; - } - currentFunction.lines.add(new Integer(desc)); - } - break; - case StabConstant.N_FUN : - if (name.length() == 0) { - name = "anon"; - } - currentFunction = null; - currentFunction = new Function(name); - currentFunction.addr = value; - currentFunction.startLine = desc; - currentFunction.filename = currentFile; - list.add(currentFunction); - break; - case StabConstant.N_LBRAC : - bracket++; - break; - case StabConstant.N_RBRAC : - bracket--; - break; - case StabConstant.N_BINCL : - Include include = new Include(name); - include.index = includeCount++; - list.add(include); - break; - case StabConstant.N_EINCL : - break; - case StabConstant.N_SO : - if (name.length() == 0) { - currentFile = name; - } else { - if (currentFile != null && currentFile.endsWith("/")) { - currentFile += name; - } else { - currentFile = name; - } - } - break; - } - //System.out.println(" " + i + "\t" + Stab.type2String(type) + "\t" + other + "\t\t" + - // desc + "\t" + Long.toHexString(value) + "\t" + + stroff + "\t\t" +name); - } - entries = new Entry[list.size()]; - list.toArray(entries); - list.clear(); - Arrays.sort(entries); - } - - public void print() { - for (int i = 0; i < entries.length; i++) { - Entry entry = entries[i]; - System.out.println(entry); - } - } - - public static void main(String[] args) { - try { - Elf.Section stab = null; - Elf.Section stabstr = null; - Elf exe = new Elf(args[0]); - Elf.Section[] sections = exe.getSections(); - for (int i = 0; i < sections.length; i++) { - String name = sections[i].toString(); - if (name.equals(".stab")) { - stab = sections[i]; - } else if (name.equals(".stabstr")) { - stabstr = sections[i]; - } - } - if (stab != null && stabstr != null) { - long nstab = stab.sh_size / StabConstant.SIZE; - System.out.println("Number of stabs" + nstab); - byte[] array = stab.loadSectionData(); - byte[] strtab = stabstr.loadSectionData(); - Stabs stabs = new Stabs(array, strtab, true); - stabs.parse(); - stabs.print(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - } -} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/StabsAddr2line.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/StabsAddr2line.java deleted file mode 100644 index f6e0050adf1..00000000000 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/stabs/StabsAddr2line.java +++ /dev/null @@ -1,127 +0,0 @@ -/********************************************************************** - * 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.stabs; - -import java.io.IOException; - -import org.eclipse.cdt.utils.elf.Elf; - -/** - * StabsAddr2ine - * - * @author alain - */ -public class StabsAddr2line { - - Stabs stabs; - - public StabsAddr2line(byte[] stab, byte[] stabstr, boolean le) throws IOException { - stabs = new Stabs(stab, stabstr, le); - } - - /* - * (non-Javadoc) - * - * @see IAddr2line#dispose() - */ - public void dispose() { - } - - /* - * (non-Javadoc) - * - * @see IAddr2line#getStartLine(long) - */ - public int getStartLine(long address) throws IOException { - Stabs.Entry entry = stabs.getEntry(address); - if (entry != null) { - return entry.startLine; - } - return 0; - } - - /* - * (non-Javadoc) - * - * @see IAddr2line#getEndLine(long) - */ - public int getEndLine(long address) throws IOException { - Stabs.Entry entry = stabs.getEntry(address); - if (entry != null) { - if (entry instanceof Stabs.Function) { - return ((Stabs.Function)entry).endLine; - } - return entry.startLine; - } - return 0; - } - - /* - * (non-Javadoc) - * - * @see IAddr2line#getFunction(long) - */ - public String getFunction(long address) throws IOException { - Stabs.Entry entry = stabs.getEntry(address); - if (entry != null) { - return entry.string; - } - return null; - } - - /* - * (non-Javadoc) - * - * @see IAddr2line#getFileName(long) - */ - public String getFileName(long address) throws IOException { - Stabs.Entry entry = stabs.getEntry(address); - if (entry instanceof Stabs.LocatableEntry) { - return ((Stabs.LocatableEntry)entry).filename; - } - return null; - } - - public static void main(String[] args) { - try { - Elf.Section stab = null; - Elf.Section stabstr = null; - Elf exe = new Elf(args[0]); - Elf.Section[] sections = exe.getSections(); - for (int i = 0; i < sections.length; i++) { - String name = sections[i].toString(); - if (name.equals(".stab")) { - stab = sections[i]; - } else if (name.equals(".stabstr")) { - stabstr = sections[i]; - } - } - if (stab != null && stabstr != null) { - long nstab = stab.sh_size / StabConstant.SIZE; - System.out.println("Number of stabs" + nstab); - byte[] array = stab.loadSectionData(); - byte[] strtab = stabstr.loadSectionData(); - StabsAddr2line addr2line = new StabsAddr2line(array, strtab, true); - long address = Integer.decode(args[1]).longValue(); - int startLine = addr2line.getStartLine(address); - int endLine = addr2line.getEndLine(address); - String function = addr2line.getFunction(address); - String filename = addr2line.getFileName(address); - System.out.println(Long.toHexString(address)); - System.out.println(filename + ":" + function + ":" + startLine + ":" + endLine); - } - } catch (IOException e) { - e.printStackTrace(); - } - - } -}