GT-3545 - GNU Demangler - Fix Parsing Issues - Checkpoint 2

Deleted old Generic* demangler classes; all tests passing
This commit is contained in:
dragonmacher
2020-02-25 15:21:22 -05:00
parent 7d09241ef6
commit ed80be21c3
31 changed files with 8 additions and 2682 deletions
-1
View File
@@ -24,7 +24,6 @@ dependencies {
compile project(':Graph')
compile project(':SoftwareModeling')
compile project(':DB')
compile project(':Demangler')
compile project(':Help')
compileOnly "junit:junit:4.12"
@@ -23,7 +23,6 @@ import ghidra.program.model.mem.*;
import ghidra.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
import util.demangler.GenericDemangledAddressTable;
public class DemangledAddressTable extends DemangledObject {
@@ -34,12 +33,6 @@ public class DemangledAddressTable extends DemangledObject {
setName(name);
}
DemangledAddressTable(GenericDemangledAddressTable generic) {
super(generic);
length = generic.getLength();
}
/**
* Returns the length of the address table.
* -1 indicates the length is unknown.
@@ -23,7 +23,6 @@ import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum;
import ghidra.program.model.symbol.Namespace;
import util.demangler.*;
/**
* A class to represent a demangled data type.
@@ -108,51 +107,6 @@ public class DemangledDataType extends DemangledType {
super(name);
}
DemangledDataType(GenericDemangledDataType source) {
super(source);
if (source.isArray()) {
// TODO GenericDemangledDataType should go away; if so, we don't need to worry
// about array dimension impedance
arrayDimensions = 1;
}
isClass = source.isClass();
isComplex = source.isComplex();
isEnum = source.isEnum();
isPointer64 = source.isPointer64();
isReference = source.isReference();
isSigned = source.isSigned();
isStruct = source.isStruct();
isTemplate = source.isTemplate();
isUnaligned = source.isUnaligned();
isUnion = source.isUnion();
isUnsigned = source.isUnsigned();
isVarArgs = source.isVarArgs();
// isVolatile = source.isVolatile();
pointerLevels = source.getPointerLevels();
//enumType = source.getEnumType();
isRestrict = source.isRestrict();
basedName = source.getBasedName();
memberScope = source.getMemberScope();
isCoclass = source.isCoclass();
isCointerface = source.isCointerface();
GenericDemangledType otherNamespace = source.getNamespace();
if (otherNamespace != null) {
namespace = DemangledType.convertToNamespace(source.getNamespace());
}
GenericDemangledTemplate otherTemplate = source.getTemplate();
if (otherTemplate != null) {
template = new DemangledTemplate(otherTemplate);
}
if (source.isConst()) {
setConst();
}
}
public DemangledDataType copy() {
DemangledDataType copy = new DemangledDataType(getName());
copy(this, copy);
@@ -172,9 +126,7 @@ public class DemangledDataType extends DemangledType {
destination.isUnion = source.isUnion;
destination.isUnsigned = source.isUnsigned;
destination.isVarArgs = source.isVarArgs;
// destination.isVolatile = source.isVolatile;
destination.pointerLevels = source.pointerLevels;
//destination.enumType = source.enumType;
destination.isUnaligned = source.isUnaligned();
destination.isRestrict = source.isRestrict();
@@ -31,7 +31,6 @@ import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.task.TaskMonitor;
import util.demangler.*;
/**
* A class to represent a demangled function.
@@ -72,28 +71,6 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
setName(name);
}
DemangledFunction(GenericDemangledFunction other) {
super(other);
GenericDemangledDataType otherReturnType = other.getReturnType();
if (otherReturnType != null) {
returnType = (DemangledDataType) DemangledObjectFactory.convert(otherReturnType);
}
callingConvention = other.getCallingConvention();
thisPassedOnStack = other.isPassedOnStack();
GenericDemangledTemplate otherTemplate = other.getTemplate();
if (otherTemplate != null) {
template = new DemangledTemplate(otherTemplate);
}
isOverloadedOperator = other.isOverloadedOperator();
List<GenericDemangledDataType> otherParams = other.getParameters();
for (GenericDemangledDataType parameter : otherParams) {
parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter));
}
}
/**
* Sets the function return type.
* @param returnType the function return type
@@ -19,8 +19,6 @@ import java.util.ArrayList;
import java.util.List;
import ghidra.program.model.data.*;
import util.demangler.GenericDemangledDataType;
import util.demangler.GenericDemangledFunctionPointer;
/**
* A class to represent a demangled function pointer.
@@ -56,23 +54,6 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
return ID++;
}
DemangledFunctionPointer(GenericDemangledFunctionPointer generic) {
super(generic);
ID = generic.getID();
returnType = (DemangledDataType) DemangledObjectFactory.convert(generic.getReturnType());
callingConvention = generic.getCallingConvention();
isConstPointer = generic.isConstPointer();
parentName = generic.getParentName();
isTrailingPointer64 = generic.isTrailingPointer64();
List<GenericDemangledDataType> genericParameters = generic.getParameters();
for (GenericDemangledDataType parameter : genericParameters) {
parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter));
}
}
/**
* Returns the return type.
* @return the return type
@@ -15,17 +15,10 @@
*/
package ghidra.app.util.demangler;
import util.demangler.GenericDemangledMethod;
// TODO delete this
public class DemangledMethod extends DemangledFunction {
public DemangledMethod(String name) {
super(name);
}
DemangledMethod(GenericDemangledMethod generic) {
super(generic);
}
}
@@ -28,8 +28,6 @@ import ghidra.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
import util.demangler.GenericDemangledObject;
import util.demangler.GenericDemangledType;
/**
* A class to represent a demangled object.
@@ -77,33 +75,6 @@ public abstract class DemangledObject implements Demangled {
// default
}
DemangledObject(GenericDemangledObject other) {
mangled = other.getOriginalMangled();
specialPrefix = other.getSpecialPrefix();
specialMidfix = other.getSpecialMidfix();
specialSuffix = other.getSpecialSuffix();
GenericDemangledType otherNamespace = other.getNamespace();
if (otherNamespace != null) {
namespace = DemangledType.convertToNamespace(otherNamespace);
}
visibility = other.getVisibility();
storageClass = other.getStorageClass();
setName(other.getName());
isConst = other.isConst();
isVolatile = other.isVolatile();
isPointer64 = other.isPointer64();
isStatic = other.isStatic();
isVirtual = other.isVirtual();
isThunk = other.isThunk();
isUnaligned = other.isUnaligned();
isRestrict = other.isRestrict();
basedName = other.getBasedName();
memberScope = other.getMemberScope();
}
/**
* Returns the unmodified demangled name of this object.
* This name may contain whitespace and other characters not
@@ -1,57 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.demangler;
import util.demangler.*;
public class DemangledObjectFactory {
private DemangledObjectFactory() {
// factory
}
public static DemangledObject convert(GenericDemangledObject generic) throws DemangledException {
if (generic instanceof GenericDemangledVariable) {
return new DemangledVariable((GenericDemangledVariable) generic);
}
else if (generic instanceof GenericDemangledString) {
return new DemangledString((GenericDemangledString) generic);
}
else if (generic instanceof GenericDemangledMethod) {
return new DemangledMethod((GenericDemangledMethod) generic);
}
else if (generic instanceof GenericDemangledFunction) {
return new DemangledFunction((GenericDemangledFunction) generic);
}
else if (generic instanceof GenericDemangledAddressTable) {
return new DemangledAddressTable((GenericDemangledAddressTable) generic);
}
throw new DemangledException("Unknown GenericDemangledObject: " + generic.getClass());
}
public static DemangledType convert(GenericDemangledType generic) {
if (generic instanceof GenericDemangledFunctionPointer) {
return new DemangledFunctionPointer((GenericDemangledFunctionPointer) generic);
}
else if (generic instanceof GenericDemangledDataType) {
return new DemangledDataType((GenericDemangledDataType) generic);
}
return new DemangledType(generic);
}
}
@@ -22,7 +22,6 @@ import ghidra.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.StringUtilities;
import ghidra.util.task.TaskMonitor;
import util.demangler.GenericDemangledString;
public class DemangledString extends DemangledObject {
private String string;
@@ -45,17 +44,6 @@ public class DemangledString extends DemangledObject {
this.unicode = unicode;
}
/**
* Construct demangled string from a GenericDemangledString
* @param generic generic demangled string
*/
DemangledString(GenericDemangledString generic) {
super(generic);
string = generic.getString();
length = generic.getLength();
unicode = generic.isUnicode();
}
@Override
public String getSignature(boolean format) {
StringBuffer buffer = new StringBuffer();
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,28 +15,15 @@
*/
package ghidra.app.util.demangler;
import ghidra.program.model.data.DataType;
import ghidra.util.Msg;
import java.util.ArrayList;
import java.util.List;
import util.demangler.GenericDemangledDataType;
import util.demangler.GenericDemangledTemplate;
import ghidra.program.model.data.DataType;
import ghidra.util.Msg;
public class DemangledTemplate implements ParameterReceiver {
private List<DemangledDataType> parameters = new ArrayList<DemangledDataType>();
public DemangledTemplate() {
}
DemangledTemplate(GenericDemangledTemplate template) {
List<GenericDemangledDataType> genericParameters = template.getParameters();
for (GenericDemangledDataType parameter : genericParameters) {
parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter));
}
}
@Override
public void addParameter(DemangledDataType parameter) {
parameters.add(parameter);
@@ -15,12 +15,7 @@
*/
package ghidra.app.util.demangler;
import java.util.List;
import ghidra.app.util.SymbolPath;
import ghidra.program.model.symbol.Namespace;
import util.demangler.GenericDemangledTemplate;
import util.demangler.GenericDemangledType;
// TODO maybe rename this to DemangledNamespace
public class DemangledType implements Demangled {
@@ -32,61 +27,10 @@ public class DemangledType implements Demangled {
private boolean isConst;
private boolean isVolatile;
/**
* Takes a {@link DemangledType} with a name that contains namespace elements
* (such as Foo::Bar) and breaks it into a hierarchy of types where each type
* represents one item in the list of namespace elements.
*
* @param otherNamespace the type to convert
* @return the original type if the name does not represent a namespace; a new type
* that contains a child, that contains a child and so on, representing the
* split-up of the original namespace string.
*/
public static Demangled convertToNamespace(GenericDemangledType otherNamespace) {
if (otherNamespace == null) {
return null;
}
DemangledType newNamespace = new DemangledType(otherNamespace);
String demangledName = newNamespace.getName();
SymbolPath symbolPath = new SymbolPath(demangledName);
if (symbolPath.getParent() == null) {
return newNamespace;
}
List<String> names = symbolPath.asList();
DemangledType lastParent = new DemangledType(names.get(0));
for (int i = 1; i < names.size(); i++) {
DemangledType child = new DemangledType(names.get(i));
child.setNamespace(lastParent);
lastParent = child;
}
return lastParent;
}
public DemangledType(String name) {
setName(name);
}
DemangledType(GenericDemangledType toCopy) {
GenericDemangledType otherNamespace = toCopy.getNamespace();
if (otherNamespace != null) {
namespace = convertToNamespace(otherNamespace);
}
setName(toCopy.getName());
GenericDemangledTemplate otherTemplate = toCopy.getTemplate();
if (otherTemplate != null) {
template = new DemangledTemplate(otherTemplate);
}
isConst = toCopy.isConst();
isVolatile = toCopy.isVolatile();
}
/**
* Returns the unmodified demangled name of this object.
* This name may contain whitespace and other characters not
@@ -29,8 +29,6 @@ import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.task.TaskMonitor;
import util.demangler.GenericDemangledDataType;
import util.demangler.GenericDemangledVariable;
/**
* An interface to represent a demangled global variable.
@@ -42,15 +40,6 @@ public class DemangledVariable extends DemangledObject {
setName(name);
}
DemangledVariable(GenericDemangledVariable other) {
super(other);
GenericDemangledDataType otherDatatype = other.getDataType();
if (otherDatatype != null) {
datatype = (DemangledDataType) DemangledObjectFactory.convert(otherDatatype);
}
}
public void setDatatype(DemangledDataType datatype) {
this.datatype = datatype;
}
@@ -21,7 +21,6 @@ import ghidra.app.util.opinion.PeLoader;
import ghidra.program.model.listing.Program;
import mdemangler.MDException;
import mdemangler.MDMangGhidra;
import util.demangler.GenericDemangledException;
/**
* A class for demangling debug symbols created using Microsoft Visual Studio.
@@ -46,7 +45,7 @@ public class MicrosoftDemangler implements Demangler {
DemangledObject demangled = demangleMS(mangled, demangleOnlyKnownPatterns);
return demangled;
}
catch (GenericDemangledException e) {
catch (DemangledException e) {
throw new DemangledException(true);
}
}
@@ -59,15 +58,15 @@ public class MicrosoftDemangler implements Demangler {
DemangledObject demangled = demangleMS(mangled, options.demangleOnlyKnownPatterns());
return demangled;
}
catch (GenericDemangledException e) {
catch (DemangledException e) {
throw new DemangledException(true);
}
}
private DemangledObject demangleMS(String mangled, boolean demangleOnlyKnownPatterns)
throws GenericDemangledException {
throws DemangledException {
if (mangled == null || mangled.length() == 0) {
throw new GenericDemangledException(true);
throw new DemangledException(true);
}
MDMangGhidra demangler = new MDMangGhidra();
@@ -77,8 +76,8 @@ public class MicrosoftDemangler implements Demangler {
return object;
}
catch (MDException e) {
GenericDemangledException gde =
new GenericDemangledException("Unable to demangle symbol: " + mangled);
DemangledException gde =
new DemangledException("Unable to demangle symbol: " + mangled);
gde.initCause(e);
throw gde;
}
-12
View File
@@ -1,12 +0,0 @@
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Framework Demangler'
dependencies {
compile project(':Utility')
}
@@ -1,3 +0,0 @@
##VERSION: 2.0
Module.manifest||GHIDRA||reviewed||END|
build.gradle||GHIDRA||||END|
@@ -1,249 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
/**
* A class for bidirectional iteration over a string.
*
* Iterators maintain a current character index, whose valid range is from
* 0 to string.length()-1.
*
* The current index can be retrieved by calling getIndex() and set directly
* by calling setIndex().
*
* The methods previous() and next() are used for iteration. They return DONE if
* they would move outside the range from 0 to string.length()-1.
*/
public class CharacterIterator {
/**
* Constant that is returned when the iterator has reached either the end
* or the beginning of the text. The value is '\\uFFFF', the "not a
* character" value which should not occur in any valid Unicode string.
*/
public static final char DONE = '\uFFFF';
private String string;
private int index;
/**
* Constructs a new character iterator using str.
* @param str the string to iterate
*/
public CharacterIterator(String str) {
this.string = str;
}
/**
* Returns the underlying string.
* @return the underlying string
*/
public String getString() {
return string;
}
/**
* Returns the current index.
* @return the current index.
*/
public int getIndex() {
return index;
}
/**
* Returns the length of the iterator.
* @return the length of the iterator
*/
public int getLength() {
return string.length();
}
/**
* Sets the position to the specified position in the text.
* @param index the position within the text.
* @throws IllegalArgumentException if index is not in range from 0 to string.length()-1
*/
public void setIndex(int index) {
if (index < 0 || index > string.length() - 1) {
throw new IllegalArgumentException();
}
this.index = index;
}
/**
* Returns true if there are more characters to read
* @return true if there are more characters to read
*/
public boolean hasNext() {
return index < string.length() - 1;
}
/**
* Returns the next character without incrementing the current index.
* @return the next character without incrementing the current index
*/
public char peek() {
try {
return string.charAt(index);
}
catch (IndexOutOfBoundsException e) {
return DONE;
}
}
/**
* Peeks at the character current index + lookAhead.
* Returns DONE if the computed position is out of range.
* @param lookAhead number of characters to look ahead
* @return the character at index+lookAhead
*/
public char peek(int lookAhead) {
try {
return string.charAt(index + lookAhead);
}
catch (IndexOutOfBoundsException e) {
return DONE;
}
}
/**
* Increments the current index by one and returns the character
* at the new index. If the resulting index is greater or equal
* to the end index, the current index is reset to the end index and
* a value of DONE is returned.
* @return the character at the new position or DONE
*/
public char next() {
try {
return string.charAt(++index);
}
catch (IndexOutOfBoundsException e) {
index = string.length();
return DONE;
}
}
/**
* Returns the character at the current index and then increments the index by one.
* If the resulting index is greater or equal
* to the end index, the current index is reset to the end index and
* a value of DONE is returned.
* @return the character at the new position or DONE
*/
public char getAndIncrement() {
try {
return string.charAt(index++);
}
catch (IndexOutOfBoundsException e) {
index = string.length();
return DONE;
}
}
/**
* Decrements the current index by one and returns the character
* at the new index. If the current index is 0, the index
* remains at 0 and a value of DONE is returned.
* @return the character at the new position or DONE
*/
public char previous() {
try {
return string.charAt(--index);
}
catch (IndexOutOfBoundsException e) {
index = 0;
return DONE;
}
}
/**
* Returns the next ascii string of the specified length starting
* at the current index.
* @param len the length of the string to read
* @return the next ascii string
*/
public String nextString(int len) {
String s = string.substring(index, index + len);
index = index + len;
return s;
}
/**
* Returns the next integer. The radix must be 10 (decimal).
* For example, given "...12fred..". If current index is pointing
* to the '1', then this value will return 12.
* @return the next base-10 integer.
*/
public int nextInteger() {
int origIndex = index;
while (Character.isDigit(peek())) {
getAndIncrement();
}
if (origIndex == index) {
return string.charAt(index) - '0';
}
String s = string.substring(origIndex, index);
try {
return Integer.parseInt(s);
}
catch (NumberFormatException e) {
index = origIndex;
throw e;
}
}
/**
* Looks for the next occurrence of 'c' starting
* at the current index. Returns the character
* position in the underlying string or -1 if 'c'
* is not found.
*/
public int find(char c) {
for (int i = index; i < string.length(); ++i) {
if (string.charAt(i) == c) {
return i;
}
}
return -1;
}
@Override
public String toString() {
return "currnt = " + peek() + "; next = " + peek(1);
}
public String getContext() {
StringBuilder buffy = new StringBuilder();
int amount = 5;
int start = index - amount;
start = Math.max(start, 0);
for (int i = start; i < index; i++) {
buffy.append(string.charAt(i));
}
buffy.append('[').append(string.charAt(index)).append(']');
int end = index + amount + 1;
end = Math.min(end, string.length());
for (int i = index + 1; i < end; i++) {
buffy.append(string.charAt(i));
}
buffy.append(" @ ").append(index);
return buffy.toString();
}
}
@@ -1,57 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
public class GenericDemangledAddressTable extends GenericDemangledObject {
private int length;
public GenericDemangledAddressTable(String name, int length) {
this.name = name;
this.length = length;
}
/**
* Returns the length of the address table.
* -1 indicates the length is unknown.
* @return the length of the address table
*/
public int getLength() {
return length;
}
@Override
public String getSignature(boolean format) {
StringBuffer buffer = new StringBuffer();
if (specialPrefix != null) {
buffer.append(specialPrefix);
buffer.append(' ');
}
if (namespace != null) {
String namespaceStr = namespace.toSignature();
buffer.append(namespaceStr);
if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) {
buffer.append(NAMESPACE_SEPARATOR);
}
}
buffer.append(name);
return buffer.toString();
}
}
@@ -1,191 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
import java.util.regex.Matcher;
public class GenericDemangledArray extends GenericDemangledDataType {
private String dataType;
public GenericDemangledArray(String name) {
super(name);
setArray();
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public String getDataType() {
return dataType;
}
@Override
public void copyInto(GenericDemangledVariable destination) {
super.copyInto(destination);
if (dataType != null) {
GenericDemangledDataType dt = new GenericDemangledDataType(dataType);
destination.setDatatype(dt);
}
}
/**
* Note: this code is a modified form of what was in the parent class, specifically to
* handle arrays. Also, feel free to jigger this around, as long as the tests pass, we are
* probably OK. There is probably a lot of code in this method that is not needed.
*/
@Override
public String toSignature() {
StringBuffer buffer = new StringBuffer();
if (isUnion) {
buffer.append(UNION).append(SPACE);
}
if (isStruct) {
buffer.append(STRUCT).append(SPACE);
}
if (isEnum) {
buffer.append(ENUM).append(SPACE);
}
if (isClass) {
buffer.append(CLASS).append(SPACE);
}
if (isComplex) {
buffer.append(COMPLEX).append(SPACE);
}
if (isVolatile) {
buffer.append(VOLATILE).append(SPACE);
}
if (isSigned) {
buffer.append(SIGNED).append(SPACE);
}
if (isUnsigned) {
buffer.append(UNSIGNED).append(SPACE);
}
String space = "";
if (dataType != null) {
buffer.append(space).append(dataType);
space = String.valueOf(SPACE);
}
if (isConst()) {
buffer.append(space).append(CONST);
space = String.valueOf(SPACE);
}
if (getNamespace() != null) {
buffer.append(getNamespace().toNamespace());
}
if (getName() != null) {
buffer.append(getName());
space = String.valueOf(SPACE);
}
if (getTemplate() != null) {
buffer.append(getTemplate().toTemplate());
space = String.valueOf(SPACE);
}
if (isUnaligned) {
buffer.append(space).append(UNALIGNED);
space = String.valueOf(SPACE);
}
if (isFar) {
buffer.append(space).append(FAR);
space = String.valueOf(SPACE);
}
if (isRestrict) {
buffer.append(space).append(RESTRICT);
space = String.valueOf(SPACE);
}
handlePointer(buffer, space);
if (isReference) {
// ugly, but MS does this
boolean hasPointers = pointerLevels >= 1;
if (isConst() && hasPointers) {
buffer.append(space).append(CONST);
space = String.valueOf(SPACE);
}
buffer.append(space).append(REF_NOTATION);
space = String.valueOf(SPACE);
}
handleTrailingPointer(buffer, space);
if (isArray) {
Matcher matcher = ARRAY_SUBSCRIPT_PATTERN.matcher(getName());
if (!matcher.find()) {
// only put subscript on if the name doesn't have it
buffer.append(ARR_NOTATION);
}
}
return buffer.toString();
}
private void handlePointer(StringBuffer buffer, String space) {
String myName = getName();
if (myName.contains("*")) {
return; // don't add pointer notation if it is already in the name
}
boolean hasPointers = pointerLevels >= 1;
if (hasPointers) {
buffer.append(space + PTR_NOTATION);
space = String.valueOf(SPACE);
}
}
private void handleTrailingPointer(StringBuffer buffer, String space) {
// not sure if we need this here
// String myName = getName();
// if (myName.contains("*")) {
// return; // don't add pointer notation if it is already in the name
// }
if (isPointer64) {
buffer.append(space).append(PTR64);
space = String.valueOf(SPACE);
}
for (int i = 1; i < pointerLevels; i++) {
// ugly, but MS does this
if (isConst()) {
buffer.append(space).append(CONST);
space = String.valueOf(SPACE);
}
buffer.append(space).append(PTR_NOTATION);
space = String.valueOf(SPACE);
// ugly, but MS does this
if (isPointer64) {
buffer.append(space).append(PTR64);
space = String.valueOf(SPACE);
}
}
}
}
@@ -1,59 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
public final class GenericDemangledConstants {
public final static String VISIBILITY_public = "public";
public final static String VISIBILITY_protected = "protected";
public final static String VISIBILITY_private = "private";
public final static String VISIBILITY_static = "static";
public final static String VISIBILITY_global = "global";
public final static String VISIBILITY_virtual = "virtual";
public final static String[] VISIBILITY_ARR = { VISIBILITY_public, VISIBILITY_protected,
VISIBILITY_private, VISIBILITY_static, VISIBILITY_global, VISIBILITY_virtual, };
public final static boolean isVisibility(String visibility) {
return contains(VISIBILITY_ARR, visibility);
}
/////////////////////////////////////////////////////
public final static String STORAGE_CLASS_const = "const";
public final static String STORAGE_CLASS_volatile = "volatile";
public final static String STORAGE_CLASS_far = "far";
public final static String STORAGE_CLASS_restrict = "restrict";
public final static String[] STORAGE_CLASS_ARR = { STORAGE_CLASS_const, STORAGE_CLASS_volatile,
STORAGE_CLASS_far, STORAGE_CLASS_restrict, };
public final static boolean isStorageClass(String storageClass) {
return contains(STORAGE_CLASS_ARR, storageClass);
}
/////////////////////////////////////////////////////
private final static boolean contains(String[] array, String target) {
for (String element : array) {
if (element.equals(target)) {
return true;
}
}
return false;
}
}
@@ -1,64 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
/**
* A class to handle exceptions that occur demangling.
*/
public class GenericDemangledException extends Exception {
private boolean invalidMangledName;
/**
* Use this constructor to indicate a demangler exception
* due to an exception thrown during the demangling process.
* @param cause the exception thrown during the demangling process
*/
public GenericDemangledException(Exception cause) {
super(cause);
}
/**
* Use this constructor to indicate a demangler exception
* due to some general invalid or unsupported mangled string
* characteristic. For example, unrecognized datatype.
* @param message the invalid or unsupported mangled message
*/
public GenericDemangledException(String message) {
super(message);
}
/**
* Use this constructor to indicate the demangler failed
* because the string to demangle does not appear to represent
* a valid mangled name.
* @param invalidMangledName true to indicate the string to
* demangle does not appear to represent a valid mangled name
*/
public GenericDemangledException(boolean invalidMangledName) {
this.invalidMangledName = invalidMangledName;
}
/**
* Returns true if the string to demangle does not appear to represent
* a valid mangled name
* @return true if the string to demangle does not appear to represent
* a valid mangled name
*/
public boolean isInvalidMangledName() {
return invalidMangledName;
}
}
@@ -1,241 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
import java.util.*;
/**
* A class to represent a demangled function.
*/
public class GenericDemangledFunction extends GenericDemangledObject implements ParameterReceiver {
protected GenericDemangledDataType returnType;
protected String callingConvention;// __cdecl, __thiscall, etc.
protected boolean thisPassedOnStack = true;
protected List<GenericDemangledDataType> parameterList =
new ArrayList<GenericDemangledDataType>();
protected GenericDemangledTemplate template;
protected boolean isOverloadedOperator = false;
private boolean virtual = false;
/** Special constructor where it has a templated type before the parameter list */
private String templatedConstructorType;
/**
* Constructs a new demangled function.
* @param name the name of the function
*/
public GenericDemangledFunction(String name) throws GenericDemangledException {
if (name == null) {
throw new GenericDemangledException(
"Function name cannot be null; failed to parse mangled name properly");
}
this.name = name;
}
/**
* Sets the function return type.
* @param returnType the function return type
*/
public void setReturnType(GenericDemangledDataType returnType) {
this.returnType = returnType;
}
/**
* Sets the function calling convention. For example, "__cdecl".
* @param callingConvention the function calling convention
*/
public void setCallingConvention(String callingConvention) {
this.callingConvention = callingConvention;
}
/**
* 'this' is passed on the stack or false if in a register
*
*/
public void setThisPassedOnStack(boolean thisPassedOnStack) {
this.thisPassedOnStack = thisPassedOnStack;
}
public boolean isPassedOnStack() {
return thisPassedOnStack;
}
public void setTemplate(GenericDemangledTemplate template) {
this.template = template;
}
public GenericDemangledTemplate getTemplate() {
return template;
}
public void setVirtual() {
this.virtual = true;
}
public boolean isVirtual() {
return virtual;
}
/**
* Sets whether this demangled function represents
* an overloaded operator. For example, "operator+()".
* @param isOverloadedOperator true if overloaded operator
*/
public void setOverloadedOperator(boolean isOverloadedOperator) {
this.isOverloadedOperator = isOverloadedOperator;
}
public boolean isOverloadedOperator() {
return isOverloadedOperator;
}
/**
* @see ghidra.app.util.demangler.ParameterReceiver
*/
@Override
public void addParameter(GenericDemangledDataType parameter) {
parameterList.add(parameter);
}
/**
* @see ghidra.app.util.demangler.ParameterReceiver
*/
@Override
public List<GenericDemangledDataType> getParameters() {
return new ArrayList<GenericDemangledDataType>(parameterList);
}
/**
* Returns the return type or null, if unspecified.
* @return the return type or null, if unspecified
*/
public GenericDemangledDataType getReturnType() {
return returnType;
}
/**
* Returns the calling convention or null, if unspecified.
* @return the calling convention or null, if unspecified
*/
public String getCallingConvention() {
return callingConvention;
}
/** Special constructor where it has a templated type before the parameter list */
public void setTemplatedConstructorType(String type) {
this.templatedConstructorType = type;
}
@Override
public String getSignature(boolean format) {
StringBuffer buffer = new StringBuffer();
if (!(returnType instanceof GenericDemangledFunctionPointer)) {
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
buffer.append(visibility == null || "global".equals(visibility) ? "" : visibility + " ");
if (isStatic()) {
buffer.append("static ");
}
if (virtual) {
buffer.append("virtual ");
}
buffer.append(returnType == null ? "" : returnType.toSignature() + " ");
}
buffer.append(callingConvention == null ? "" : callingConvention + " ");
if (namespace != null) {
buffer.append(namespace.toNamespace());
}
buffer.append(name);
if (template != null) {
buffer.append(template.toTemplate());
}
if (specialMidfix != null) {
buffer.append('[').append(specialMidfix).append(']');
}
// check for special case of 'conversion operator' where we only want to display '()' and
// not (void)
if (name.endsWith("()")) {
if (name.equals("operator")) {
buffer.append("()");
}
}
else {
if (templatedConstructorType != null) {
buffer.append('<').append(templatedConstructorType).append('>');
}
Iterator<GenericDemangledDataType> paramIterator = parameterList.iterator();
buffer.append('(');
String pad = format ? pad(buffer.length()) : "";
if (!paramIterator.hasNext()) {
buffer.append("void");
}
while (paramIterator.hasNext()) {
buffer.append(paramIterator.next().toSignature());
if (paramIterator.hasNext()) {
buffer.append(',');
if (format) {
buffer.append('\n');
}
buffer.append(pad);
}
}
buffer.append(')');
buffer.append(storageClass == null ? "" : " " + storageClass);
}
if (returnType instanceof GenericDemangledFunctionPointer) {
GenericDemangledFunctionPointer funcPtr = (GenericDemangledFunctionPointer) returnType;
String partialSig = funcPtr.toSignature(buffer.toString());
buffer = new StringBuffer();
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
buffer.append(visibility == null || "global".equals(visibility) ? "" : visibility + " ");
if (virtual) {
buffer.append("virtual ");
}
buffer.append(partialSig);
}
else {
if (specialSuffix != null) {
buffer.append(specialSuffix);
}
}
return buffer.toString();
}
public String getParameterString() {
StringBuffer buffer = new StringBuffer();
buffer.append('(');
Iterator<GenericDemangledDataType> dditer = parameterList.iterator();
while (dditer.hasNext()) {
buffer.append(dditer.next().toSignature());
if (dditer.hasNext()) {
buffer.append(',');
}
}
buffer.append(')');
return buffer.toString();
}
}
@@ -1,273 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
import java.util.ArrayList;
import java.util.List;
/**
* A class to represent a demangled function pointer.
*/
public class GenericDemangledFunctionPointer extends GenericDemangledDataType
implements ParameterReceiver {
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
private static final String EMPTY_STRING = "";
private static final Object NAMESPACE_DELIMITER = "::";
private static int ID = 0;
private GenericDemangledDataType returnType;
protected String callingConvention;// __cdecl, __thiscall, etc.
private List<GenericDemangledDataType> parameters = new ArrayList<>();
private boolean isConstPointer;
private String parentName;
private boolean isTrailingPointer64;
/**
* Constructs a new demangled function pointer.
*/
public GenericDemangledFunctionPointer() {
super(DEFAULT_NAME_PREFIX + nextID());
}
/**
* Returns the return type.
* @return the return type
*/
public GenericDemangledDataType getReturnType() {
return returnType;
}
/**
* Sets the return type.
* @param returnType the return type
*/
public void setReturnType(GenericDemangledDataType returnType) {
this.returnType = returnType;
}
/**
* Returns the calling convention or null, if unspecified.
* @return the calling convention or null, if unspecified
*/
public String getCallingConvention() {
return callingConvention;
}
/**
* Sets the function calling convention. For example, "__cdecl".
* @param callingConvention the function calling convention
*/
public void setCallingConvention(String callingConvention) {
this.callingConvention = callingConvention;
}
/**
* Adds a parameters to the end of the parameter list for
* this demangled function.
* @param parameter the new parameter to add
*/
@Override
public void addParameter(GenericDemangledDataType parameter) {
parameters.add(parameter);
}
/**
* Returns a list of the parameters for this demangled functions.
* @return a list of the parameters for this demangled functions
*/
@Override
public List<GenericDemangledDataType> getParameters() {
return new ArrayList<>(parameters);
}
@Override
public GenericDemangledDataType copy() {
GenericDemangledFunctionPointer copy = new GenericDemangledFunctionPointer();
copyInto(copy);
return copy;
}
@Override
public void copyInto(GenericDemangledDataType destination) {
super.copyInto(destination);
GenericDemangledFunctionPointer source = this;
if (destination instanceof GenericDemangledFunctionPointer) {
GenericDemangledFunctionPointer copySource = source;
GenericDemangledFunctionPointer copyDestination =
(GenericDemangledFunctionPointer) destination;
if (copySource.returnType != null) {
copyDestination.returnType = copySource.returnType.copy();
}
for (GenericDemangledDataType parameter : copySource.parameters) {
copyDestination.parameters.add(parameter.copy());
}
copyDestination.callingConvention = copySource.callingConvention;
copyDestination.isConstPointer |= copySource.isConstPointer;
}
}
@Override
public String toSignature() {
return toSignature(null);
}
public String toSignature(String name) {
StringBuffer buffer = new StringBuffer();
if (returnType != null) {
buffer.append(returnType.toSignature()).append(SPACE);
}
String s = getConventionPointerNameString(name);
if (s.contains(" ") || s.isEmpty()) {
// spaces--add parens
buffer.append('(').append(s).append(')');
}
else {// this allows the '__cdecl' in templates to not have parens
buffer.append(s);
}
buffer.append('(');
for (int i = 0; i < parameters.size(); ++i) {
buffer.append(parameters.get(i).toSignature());
if (i < parameters.size() - 1) {
buffer.append(',');
}
}
buffer.append(')');
if (isConst()) {
if (buffer.length() > 2) {
buffer.append(SPACE);
}
buffer.append(CONST);
}
if (isVolatile()) {
if (buffer.length() > 2) {
buffer.append(SPACE);
}
buffer.append(VOLATILE);
}
if (isTrailingPointer64) {
if (buffer.length() > 2) {
buffer.append(SPACE);
}
buffer.append(PTR64);
}
return buffer.toString();
}
private String getConventionPointerNameString(String name) {
StringBuilder buffer = new StringBuilder();
buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention);
int pointerLevels = getPointerLevels();
if (pointerLevels > 0) {
if (callingConvention != null) {
buffer.append(SPACE);
}
addParentName(buffer);
for (int i = 0; i < pointerLevels; ++i) {
buffer.append('*');
}
}
if (isConstPointer) {
buffer.append(CONST);
}
if (isPointer64()) {
if (buffer.length() > 2) {
buffer.append(SPACE);
}
buffer.append(PTR64);
}
if (name != null) {
if (buffer.length() > 2) {
buffer.append(SPACE);
}
buffer.append(name);
}
return buffer.toString();
}
private void addParentName(StringBuilder buffer) {
if (parentName == null) {
return;
}
if (parentName.startsWith(DEFAULT_NAME_PREFIX)) {
return;
}
if (buffer.length() > 2) {
char lastChar = buffer.charAt(buffer.length() - 1);
if (SPACE != lastChar) {
buffer.append(SPACE);
}
}
buffer.append(parentName).append(NAMESPACE_DELIMITER);
}
public void setConstPointer() {
isConstPointer = true;
}
public boolean isConstPointer() {
return isConstPointer;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
public String getParentName() {
return parentName;
}
public void setTrailingPointer64() {
this.isTrailingPointer64 = true;// TODO get real construct name for this method/field
}
public boolean isTrailingPointer64() {
return isTrailingPointer64;
}
public void clearPointer64() {
this.isPointer64 = false;
}
private synchronized static int nextID() {
return ID++;
}
public int getID() {
return ID;
}
}
@@ -1,23 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
public class GenericDemangledMethod extends GenericDemangledFunction {
public GenericDemangledMethod(String name) throws GenericDemangledException {
super(name);
}
}
@@ -1,263 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
/**
* A class to represent a demangled object.
*/
public abstract class GenericDemangledObject {
protected static final String NAMESPACE_SEPARATOR = "::";
protected static final String AT = "@";
protected static final String EMPTY_STRING = "";
protected static final String SPACE = " ";
protected String originalMangled;
protected String specialPrefix;
protected String specialMidfix;
protected String specialSuffix;
protected GenericDemangledType namespace;
protected String visibility;//public, protected, etc.
protected String storageClass;//const, volatile, etc
protected String name;
protected boolean isConst;
protected boolean isVolatile;
protected boolean isStatic;
protected boolean isVirtual;
protected boolean isThunk;
protected boolean isPointer64;
// temp
protected boolean isStruct;
protected boolean isUnsigned;
protected boolean isUnaligned;
protected boolean isRestrict;
protected String basedName;
protected String memberScope;
private String signature;
/**
* Returns the name of the demangled object.
* @return the name of the demangled object
*/
public String getName() {
return name;
}
public boolean isConst() {
return isConst;
}
public void setConst(boolean isConst) {
this.isConst = isConst;
}
public boolean isVolatile() {
return isVolatile;
}
public void setVolatile(boolean isVolatile) {
this.isVolatile = isVolatile;
}
public boolean isStatic() {
return isStatic;
}
public void setStatic(boolean isStatic) {
this.isStatic = isStatic;
}
public boolean isVirtual() {
return isVirtual;
}
public void setVirtual(boolean isVirtual) {
this.isVirtual = isVirtual;
}
public boolean isThunk() {
return isThunk;
}
public void setThunk(boolean isThunk) {
this.isThunk = isThunk;
}
public boolean isPointer64() {
return isPointer64;
}
public void setPointer64(boolean isPointer64) {
this.isPointer64 = isPointer64;
}
public void setUnsigned() {
isUnsigned = true;
}
public void setStruct() {
isStruct = true;
}
public void setUnaligned() {
isUnaligned = true;
}
public boolean isUnaligned() {
return isUnaligned;
}
public void setRestrict() {
isRestrict = true;
}
public boolean isRestrict() {
return isRestrict;
}
public String getBasedName() {
return basedName;
}
public void setBasedName(String basedName) {
this.basedName = basedName;
}
public String getMemberScope() {
return memberScope;
}
public void setMemberScope(String memberScope) {
this.memberScope = memberScope;
}
/**
* Sets the name of the demangled object
* @param name the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Sets the original mangled name
* @param mangled the original mangled name
*/
public void setOriginalMangled(String mangled) {
this.originalMangled = mangled;
}
public String getOriginalMangled() {
return originalMangled;
}
/**
* Returns the namespace containing this demangled object.
* @return the namespace containing this demangled object
*/
public GenericDemangledType getNamespace() {
return namespace;
}
/**
*
* @param namespace
*/
public void setNamespace(GenericDemangledType namespace) {
this.namespace = namespace;
}
public String getVisibility() {
return visibility;
}
public void setVisibilty(String visibility) {
this.visibility = visibility;
}
public String getStorageClass() {
return storageClass;
}
public void setStorageClass(String storageClass) {
this.storageClass = storageClass;
}
public String getSpecialPrefix() {
return specialPrefix;
}
public void setSpecialPrefix(String special) {
this.specialPrefix = special;
}
public String getSpecialMidfix() {
return specialMidfix;
}
public void setSpecialMidfix(String chargeType) {
this.specialMidfix = chargeType;
}
public String getSpecialSuffix() {
return specialSuffix;
}
public void setSpecialSuffix(String specialSuffix) {
this.specialSuffix = specialSuffix;
}
/**
* Returns a complete signature for the demangled symbol.
* <br>For example:
* {@code "unsigned long foo"
* "unsigned char * ClassA::getFoo(float, short *)"
* "void * getBar(int **, MyStruct &)"}
* <br><b>Note: based on the underlying mangling scheme, the
* return type may or may not be specified in the signature.</b>
* @param format true if signature should be pretty printed
* @return a complete signature for the demangled symbol
*/
public abstract String getSignature(boolean format);
/**
* Sets the signature. Calling this method will
* override the auto-generated signature.
* @param signature the signature
*/
public void setSignature(String signature) {
this.signature = signature;
}
@Override
public String toString() {
return getSignature(false);
}
protected String generatePlateComment() {
return (signature == null) ? getSignature(true) : signature;
}
protected String pad(int len) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < len; i++) {
buffer.append(' ');
}
return buffer.toString();
}
}
@@ -1,66 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
public class GenericDemangledString extends GenericDemangledObject {
private String string;
private int length;
private boolean unicode;
public GenericDemangledString(String string, int length, boolean unicode) {
this.string = string;
this.length = length;
this.unicode = unicode;
}
@Override
public String getSignature(boolean format) {
StringBuffer buffer = new StringBuffer();
if (specialPrefix != null) {
buffer.append(specialPrefix + " for ");
}
buffer.append(string);
if (specialSuffix != null) {
buffer.append(" " + specialSuffix);
}
return buffer.toString();
}
/**
* Returns the demangled string.
* @return the demangled string
*/
public String getString() {
return string;
}
/**
* Returns the length in bytes of the demangled string.
* @return the length in bytes of the demangled string
*/
public int getLength() {
return length;
}
/**
* Returns true if the demangled string is unicode.
* @return true if the demangled string is unicode
*/
public boolean isUnicode() {
return unicode;
}
}
@@ -1,55 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
import java.util.ArrayList;
import java.util.List;
public class GenericDemangledTemplate implements ParameterReceiver {
private List<GenericDemangledDataType> parameters = new ArrayList<GenericDemangledDataType>();
public GenericDemangledTemplate() {
}
@Override
public void addParameter(GenericDemangledDataType parameter) {
parameters.add(parameter);
}
@Override
public List<GenericDemangledDataType> getParameters() {
return new ArrayList<GenericDemangledDataType>(parameters);
}
public String toTemplate() {
StringBuffer buffer = new StringBuffer();
buffer.append('<');
for (int i = 0; i < parameters.size(); ++i) {
buffer.append(parameters.get(i).toSignature());
if (i < parameters.size() - 1) {
buffer.append(',');
}
}
buffer.append('>');
return buffer.toString();
}
@Override
public String toString() {
return toTemplate();
}
}
@@ -1,101 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
public class GenericDemangledType {
private GenericDemangledType namespace;
private String name;
private GenericDemangledTemplate template;
private boolean isConst;
private boolean isVolatile;
public GenericDemangledType(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isConst() {
return isConst;
}
public void setConst() {
isConst = true;
}
public boolean isVolatile() {
return isVolatile;
}
public void setVolatile() {
isVolatile = true;
}
public GenericDemangledType getNamespace() {
return namespace;
}
public void setNamespace(GenericDemangledType namespace) {
if (this == namespace) {
throw new IllegalArgumentException("Attempt to set this.namespace == this!");
}
this.namespace = namespace;
}
public GenericDemangledTemplate getTemplate() {
return template;
}
public void setTemplate(GenericDemangledTemplate template) {
this.template = template;
}
public String toSignature() {
StringBuffer buffer = new StringBuffer();
if (namespace != null) {
buffer.append(namespace.toNamespace());
}
buffer.append(name);
if (template != null) {
buffer.append(template.toTemplate());
}
return buffer.toString();
}
public String toNamespace() {
StringBuffer buffer = new StringBuffer();
if (namespace != null) {
buffer.append(namespace.toNamespace());
}
buffer.append(name);
if (template != null) {
buffer.append(template.toTemplate());
}
buffer.append("::");
return buffer.toString();
}
@Override
public String toString() {
return toSignature();
}
}
@@ -1,116 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
/**
* An interface to represent a demangled global variable.
*/
public class GenericDemangledVariable extends GenericDemangledObject {
private GenericDemangledDataType datatype;
public GenericDemangledVariable(String name) {
this.name = name;
}
public void setDatatype(GenericDemangledDataType datatype) {
this.datatype = datatype;
}
/**
* Returns the data type of this variable.
* @return the data type of this variable
*/
public GenericDemangledDataType getDataType() {
return datatype;
}
@Override
public String getSignature(boolean format) {
StringBuffer buffer = new StringBuffer();
buffer.append(visibility == null || "global".equals(visibility) ? EMPTY_STRING
: visibility + SPACE);
if (isStatic()) {
buffer.append("static ");
}
String spacer = EMPTY_STRING;
if (isUnsigned) {
buffer.append("unsigned");
spacer = SPACE;
}
if (isStruct) {
buffer.append("struct");
spacer = SPACE;
}
if (specialPrefix != null) {
buffer.append(specialPrefix);
spacer = SPACE;
}
boolean hasName = (name != null) && !name.isEmpty();
if (!(datatype instanceof GenericDemangledFunctionPointer)) {
if (datatype != null) {
buffer.append(spacer);
buffer.append(datatype.toSignature());
spacer = SPACE;
}
}
// e.g., 'const' - this appears after the data type in MS land
if (storageClass != null) {
buffer.append(spacer).append(storageClass);
spacer = SPACE;
}
if (namespace != null) {
buffer.append(spacer);
spacer = EMPTY_STRING;
buffer.append(namespace.toNamespace());
if (!hasName) {
int end = buffer.length();
buffer.delete(end - 2, end); // strip off the last namespace characters
}
}
if (hasName) {
buffer.append(spacer);
spacer = EMPTY_STRING;
buffer.append(name);
}
buffer.append(specialMidfix == null ? EMPTY_STRING : specialMidfix + SPACE);
buffer.append(specialSuffix == null ? EMPTY_STRING : SPACE + specialSuffix);
if (datatype instanceof GenericDemangledFunctionPointer) {
GenericDemangledFunctionPointer funcPtr = (GenericDemangledFunctionPointer) datatype;
return funcPtr.toSignature(buffer.toString());
}
if (isConst()) {
buffer.append(" const");
}
return buffer.toString().trim();
}
}
@@ -1,37 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util.demangler;
import java.util.List;
/**
* A generic interface to represent
* object that support parameters.
*/
public interface ParameterReceiver {
/**
* Adds the specified parameter to this object.
* @param parameter the parameter to add
*/
public void addParameter(GenericDemangledDataType parameter);
/**
* Returns the parameters added to this object.
* @return the parameters added to this object
*/
public List<GenericDemangledDataType> getParameters();
}