mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-810 - Gnu Demangler - Fixed some failures when parsing function member pointers and array pointers/references; Fixed the parser not handling cast operators for function pointers
This commit is contained in:
parent
6a8788acbc
commit
071eb82103
14 changed files with 898 additions and 159 deletions
|
@ -129,7 +129,7 @@ public class DemanglerCmd extends BackgroundCommand {
|
||||||
". Message: " + message);
|
". Message: " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg.error(this, getStatusMsg());
|
Msg.error(this, getStatusMsg(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getResult() {
|
public String getResult() {
|
||||||
|
|
|
@ -18,6 +18,8 @@ package ghidra.app.util.demangler;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
|
|
||||||
|
@ -40,9 +42,6 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
protected boolean isTrailingUnaligned;
|
protected boolean isTrailingUnaligned;
|
||||||
protected boolean isTrailingRestrict;
|
protected boolean isTrailingRestrict;
|
||||||
|
|
||||||
/** display parens in front of parameter list */
|
|
||||||
protected boolean displayFunctionPointerParens = true;
|
|
||||||
|
|
||||||
AbstractDemangledFunctionDefinitionDataType(String mangled, String originalDemangled) {
|
AbstractDemangledFunctionDefinitionDataType(String mangled, String originalDemangled) {
|
||||||
super(mangled, originalDemangled, DEFAULT_NAME_PREFIX + nextId());
|
super(mangled, originalDemangled, DEFAULT_NAME_PREFIX + nextId());
|
||||||
}
|
}
|
||||||
|
@ -134,10 +133,6 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
isTrailingRestrict = true;
|
isTrailingRestrict = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplayFunctionPointerParens(boolean b) {
|
|
||||||
this.displayFunctionPointerParens = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a parameters to the end of the parameter list for this demangled function
|
* Adds a parameters to the end of the parameter list for this demangled function
|
||||||
* @param parameter the new parameter to add
|
* @param parameter the new parameter to add
|
||||||
|
@ -158,13 +153,8 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
StringBuilder buffer1 = new StringBuilder();
|
StringBuilder buffer1 = new StringBuilder();
|
||||||
String s = getConventionPointerNameString(name);
|
String s = getConventionPointerNameString(name);
|
||||||
if (s.contains(" ") || s.isEmpty()) {
|
|
||||||
// spaces--add parens
|
addFunctionPointerParens(buffer1, s);
|
||||||
addFunctionPointerParens(buffer1, s);
|
|
||||||
}
|
|
||||||
else { // this allows the '__cdecl' in templates to not have parens
|
|
||||||
buffer1.append(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer1.append('(');
|
buffer1.append('(');
|
||||||
for (int i = 0; i < parameters.size(); ++i) {
|
for (int i = 0; i < parameters.size(); ++i) {
|
||||||
|
@ -234,26 +224,28 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention);
|
buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention);
|
||||||
|
|
||||||
|
StringBuilder typeBuffer = new StringBuilder();
|
||||||
int pointerLevels = getPointerLevels();
|
int pointerLevels = getPointerLevels();
|
||||||
if (pointerLevels > 0) {
|
if (pointerLevels > 0) {
|
||||||
if (callingConvention != null) {
|
|
||||||
buffer.append(SPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
addParentName(buffer);
|
addParentName(typeBuffer);
|
||||||
|
|
||||||
for (int i = 0; i < pointerLevels; ++i) {
|
for (int i = 0; i < pointerLevels; ++i) {
|
||||||
buffer.append(getTypeString());
|
typeBuffer.append(getTypeString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((modifier != null) && (modifier.length() != 0)) {
|
if (!StringUtils.isBlank(typeBuffer)) {
|
||||||
if (buffer.length() > 2) {
|
|
||||||
|
if (!StringUtils.isBlank(callingConvention)) {
|
||||||
buffer.append(SPACE);
|
buffer.append(SPACE);
|
||||||
}
|
}
|
||||||
buffer.append(modifier);
|
|
||||||
|
buffer.append(typeBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addModifier(buffer);
|
||||||
|
|
||||||
if (isConstPointer) {
|
if (isConstPointer) {
|
||||||
buffer.append(CONST);
|
buffer.append(CONST);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +258,7 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if ((buffer.length() > 2) && (buffer.charAt(buffer.length() - 1) != SPACE)) {
|
if ((buffer.length() > 0) && (buffer.charAt(buffer.length() - 1) != SPACE)) {
|
||||||
buffer.append(SPACE);
|
buffer.append(SPACE);
|
||||||
}
|
}
|
||||||
buffer.append(name);
|
buffer.append(name);
|
||||||
|
@ -275,11 +267,29 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addFunctionPointerParens(StringBuilder buffer, String s) {
|
private void addModifier(StringBuilder buffer) {
|
||||||
if (!displayFunctionPointerParens) {
|
if (StringUtils.isBlank(modifier)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Guilty knowledge: in many cases the 'modifier' is the same as the type string. Further,
|
||||||
|
// when we print signatures, we will print the type string if there are pointer levels. To
|
||||||
|
// prevent duplication, do not print the modifier when it matches the type string and we
|
||||||
|
// will be printing the type string (which is printed when there are pointer levels).
|
||||||
|
//
|
||||||
|
if (modifier.equals(getTypeString()) &&
|
||||||
|
getPointerLevels() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.length() > 2) {
|
||||||
|
buffer.append(SPACE);
|
||||||
|
}
|
||||||
|
buffer.append(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addFunctionPointerParens(StringBuilder buffer, String s) {
|
||||||
buffer.append('(').append(s).append(')');
|
buffer.append('(').append(s).append(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,15 +320,7 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
fddt.setReturnType(returnType.getDataType(dataTypeManager));
|
fddt.setReturnType(returnType.getDataType(dataTypeManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.size() != 1 ||
|
setParameters(fddt, dataTypeManager);
|
||||||
!(parameters.get(0).getDataType(dataTypeManager) instanceof VoidDataType)) {
|
|
||||||
ParameterDefinition[] params = new ParameterDefinition[parameters.size()];
|
|
||||||
for (int i = 0; i < parameters.size(); ++i) {
|
|
||||||
params[i] = new ParameterDefinitionImpl(null,
|
|
||||||
parameters.get(i).getDataType(dataTypeManager), null);
|
|
||||||
}
|
|
||||||
fddt.setArguments(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataType dt = DemangledDataType.findDataType(dataTypeManager, namespace, getName());
|
DataType dt = DemangledDataType.findDataType(dataTypeManager, namespace, getName());
|
||||||
if (dt == null || !(dt instanceof FunctionDefinitionDataType)) {
|
if (dt == null || !(dt instanceof FunctionDefinitionDataType)) {
|
||||||
|
@ -327,4 +329,27 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
|
|
||||||
return new PointerDataType(dt, dataTypeManager);
|
return new PointerDataType(dt, dataTypeManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setParameters(FunctionDefinitionDataType fddt, DataTypeManager dataTypeManager) {
|
||||||
|
if (hasSingleVoidParameter(dataTypeManager)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterDefinition[] params = new ParameterDefinition[parameters.size()];
|
||||||
|
for (int i = 0; i < parameters.size(); ++i) {
|
||||||
|
params[i] = new ParameterDefinitionImpl(null,
|
||||||
|
parameters.get(i).getDataType(dataTypeManager), null);
|
||||||
|
}
|
||||||
|
fddt.setArguments(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSingleVoidParameter(DataTypeManager dataTypeManager) {
|
||||||
|
if (parameters.size() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DemangledDataType parameter = parameters.get(0);
|
||||||
|
DataType dt = parameter.getDataType(dataTypeManager);
|
||||||
|
return dt instanceof VoidDataType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import ghidra.program.database.data.DataTypeUtilities;
|
import ghidra.program.database.data.DataTypeUtilities;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Enum;
|
import ghidra.program.model.data.Enum;
|
||||||
|
@ -404,6 +406,9 @@ public class DemangledDataType extends DemangledType {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Structure createPlaceHolderStructure(String dtName, Demangled namespace) {
|
static Structure createPlaceHolderStructure(String dtName, Demangled namespace) {
|
||||||
|
if (StringUtils.isBlank(dtName)) {
|
||||||
|
throw new IllegalArgumentException("Name cannot be blank");
|
||||||
|
}
|
||||||
StructureDataType structDT = new StructureDataType(dtName, 0);
|
StructureDataType structDT = new StructureDataType(dtName, 0);
|
||||||
structDT.setDescription("PlaceHolder Structure");
|
structDT.setDescription("PlaceHolder Structure");
|
||||||
structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace));
|
structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace));
|
||||||
|
|
|
@ -229,25 +229,8 @@ public class DemangledFunction extends DemangledObject {
|
||||||
buffer.append('<').append(templatedConstructorType).append('>');
|
buffer.append('<').append(templatedConstructorType).append('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<DemangledDataType> paramIterator = parameters.iterator();
|
addParameters(buffer, format);
|
||||||
buffer.append('(');
|
|
||||||
String pad = format ? pad(buffer.length()) : "";
|
|
||||||
if (!paramIterator.hasNext()) {
|
|
||||||
buffer.append("void");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (paramIterator.hasNext()) {
|
|
||||||
buffer.append(paramIterator.next().getSignature());
|
|
||||||
if (paramIterator.hasNext()) {
|
|
||||||
buffer.append(',');
|
|
||||||
if (format) {
|
|
||||||
buffer.append('\n');
|
|
||||||
}
|
|
||||||
buffer.append(pad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.append(')');
|
|
||||||
buffer.append(storageClass == null ? "" : " " + storageClass);
|
buffer.append(storageClass == null ? "" : " " + storageClass);
|
||||||
|
|
||||||
if (returnType instanceof DemangledFunctionPointer) {
|
if (returnType instanceof DemangledFunctionPointer) {
|
||||||
|
@ -303,6 +286,29 @@ public class DemangledFunction extends DemangledObject {
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addParameters(StringBuilder buffer, boolean format) {
|
||||||
|
Iterator<DemangledDataType> paramIterator = parameters.iterator();
|
||||||
|
buffer.append('(');
|
||||||
|
int padLength = format ? buffer.length() : 0;
|
||||||
|
String pad = StringUtils.rightPad("", padLength);
|
||||||
|
if (!paramIterator.hasNext()) {
|
||||||
|
buffer.append("void");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (paramIterator.hasNext()) {
|
||||||
|
buffer.append(paramIterator.next().getSignature());
|
||||||
|
if (paramIterator.hasNext()) {
|
||||||
|
buffer.append(',');
|
||||||
|
if (format) {
|
||||||
|
buffer.append('\n');
|
||||||
|
}
|
||||||
|
buffer.append(pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append(')');
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNamespaceName() {
|
public String getNamespaceName() {
|
||||||
return getName() + getParameterString();
|
return getName() + getParameterString();
|
||||||
|
|
|
@ -32,4 +32,10 @@ public class DemangledFunctionIndirect extends AbstractDemangledFunctionDefiniti
|
||||||
protected String getTypeString() {
|
protected String getTypeString() {
|
||||||
return EMPTY_STRING;
|
return EMPTY_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addFunctionPointerParens(StringBuilder buffer, String s) {
|
||||||
|
// do not display pointer parens
|
||||||
|
buffer.append(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,34 @@ package ghidra.app.util.demangler;
|
||||||
*/
|
*/
|
||||||
public class DemangledFunctionPointer extends AbstractDemangledFunctionDefinitionDataType {
|
public class DemangledFunctionPointer extends AbstractDemangledFunctionDefinitionDataType {
|
||||||
|
|
||||||
|
/** display parens in front of parameter list */
|
||||||
|
private boolean displayFunctionPointerSyntax = true;
|
||||||
|
|
||||||
public DemangledFunctionPointer(String mangled, String originalDemangled) {
|
public DemangledFunctionPointer(String mangled, String originalDemangled) {
|
||||||
super(mangled, originalDemangled);
|
super(mangled, originalDemangled);
|
||||||
|
incrementPointerLevels(); // a function pointer is 1 level by default
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTypeString() {
|
protected String getTypeString() {
|
||||||
return "*";
|
return "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals whether to display function pointer syntax when there is no function name, which
|
||||||
|
* is '{@code (*)}', such as found in this example '{@code void (*)()}'. the default is true
|
||||||
|
* @param b true to display nameless function pointer syntax; false to not display
|
||||||
|
*/
|
||||||
|
public void setDisplayDefaultFunctionPointerSyntax(boolean b) {
|
||||||
|
this.displayFunctionPointerSyntax = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addFunctionPointerParens(StringBuilder buffer, String s) {
|
||||||
|
if (!displayFunctionPointerSyntax) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append('(').append(s).append(')');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,9 @@ public class DemangledLambda extends DemangledFunction {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addParameters(StringBuilder buffer, boolean format) {
|
||||||
|
// no parameter display for lambdas; the name currently shows the parameters
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ public abstract class DemangledObject implements Demangled {
|
||||||
protected String basedName;
|
protected String basedName;
|
||||||
protected String memberScope;
|
protected String memberScope;
|
||||||
|
|
||||||
private String signature;
|
private String plateComment;
|
||||||
|
|
||||||
DemangledObject(String mangled, String originalDemangled) {
|
DemangledObject(String mangled, String originalDemangled) {
|
||||||
this.mangled = mangled;
|
this.mangled = mangled;
|
||||||
|
@ -248,15 +248,6 @@ public abstract class DemangledObject implements Demangled {
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getSignature(false);
|
return getSignature(false);
|
||||||
|
@ -332,19 +323,29 @@ public abstract class DemangledObject implements Demangled {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the plate comment to be used if the {@link #getOriginalDemangled()} string is not
|
||||||
|
* available
|
||||||
|
*
|
||||||
|
* @param plateComment the plate comment text
|
||||||
|
*/
|
||||||
|
public void setBackupPlateComment(String plateComment) {
|
||||||
|
this.plateComment = plateComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates descriptive text that is intended to be used as documentation. The text defaults
|
||||||
|
* to the original demangled text. If that is not available, then any text set by
|
||||||
|
* {@link #setBackupPlateComment(String)} will be used. The last choice for this text is
|
||||||
|
* the signature generated by {@link #getSignature(boolean)}.
|
||||||
|
*
|
||||||
|
* @return the text
|
||||||
|
*/
|
||||||
protected String generatePlateComment() {
|
protected String generatePlateComment() {
|
||||||
if (originalDemangled != null) {
|
if (originalDemangled != null) {
|
||||||
return originalDemangled;
|
return originalDemangled;
|
||||||
}
|
}
|
||||||
return (signature == null) ? getSignature(true) : signature;
|
return (plateComment == null) ? getSignature(true) : plateComment;
|
||||||
}
|
|
||||||
|
|
||||||
protected String pad(int len) {
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
buffer.append(' ');
|
|
||||||
}
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Symbol applyDemangledName(Address addr, boolean setPrimary,
|
protected Symbol applyDemangledName(Address addr, boolean setPrimary,
|
||||||
|
@ -461,8 +462,7 @@ public abstract class DemangledObject implements Demangled {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
Msg.error(DemangledObject.class,
|
Msg.error(DemangledObject.class, "Failed to create namespace: " + e.getMessage());
|
||||||
"Failed to create namespace: " + e.getMessage());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +479,6 @@ public abstract class DemangledObject implements Demangled {
|
||||||
NamespaceUtils.getNamespaceQualifiedName(namespace, namespaceName, false));
|
NamespaceUtils.getNamespaceQualifiedName(namespace, namespaceName, false));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.demangler;
|
package ghidra.app.util.demangler;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,6 +55,10 @@ public class DemangledType implements Demangled {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
|
if (StringUtils.isBlank(name)) {
|
||||||
|
throw new IllegalArgumentException("Name cannot be blank");
|
||||||
|
}
|
||||||
|
|
||||||
demangledName = name;
|
demangledName = name;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
|
|
|
@ -117,9 +117,6 @@ public class GnuDemangler implements Demangler {
|
||||||
dfunc.setNamespace(demangledObject.getNamespace());
|
dfunc.setNamespace(demangledObject.getNamespace());
|
||||||
demangledObject = dfunc;
|
demangledObject = dfunc;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
demangledObject.setSignature(demangled);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDwarf) {
|
if (isDwarf) {
|
||||||
DemangledAddressTable dat =
|
DemangledAddressTable dat =
|
||||||
|
|
|
@ -93,16 +93,17 @@ public class GnuDemanglerParser {
|
||||||
/*
|
/*
|
||||||
* Sample: bob(short (&)[7])
|
* Sample: bob(short (&)[7])
|
||||||
* bob(int const[8] (*) [12])
|
* bob(int const[8] (*) [12])
|
||||||
|
* _S_ref(array<float, 3ul> const (&) [64])
|
||||||
|
* _S_ptr(Foo<Bar> const* const (&) [3])
|
||||||
|
* {lambda(long&, unsigned int)#1} const (&) [4]
|
||||||
*
|
*
|
||||||
* Pattern: name[optional '*']<space>(*|&)[optional spaces][optional value]
|
* Pattern: <space>[optional const with optional '[',']', number, '*', '&' <space>]
|
||||||
|
* (*|&)[optional spaces]brackets with optional characters inside
|
||||||
*
|
*
|
||||||
* Parts:
|
* Parts:
|
||||||
* -a word (capture group 1)
|
* -optional const text (e.g., const[8]) (non-capture group)
|
||||||
* -followed by an optional pointer '*'
|
* -followed by '()' that contain a '&' or a '*' (capture group 1)
|
||||||
* -followed by a space
|
* -followed by one or more '[]' with optional interior text (capture group 2)
|
||||||
* -*optional: any other text (e.g., const[8]) (non-capture group)
|
|
||||||
* -followed by '()' that contain a '&' or a '*' (capture group 2)
|
|
||||||
* -followed by one or more '[]' with optional interior text (capture group 3)
|
|
||||||
*
|
*
|
||||||
* Group Samples:
|
* Group Samples:
|
||||||
* short (&)[7]
|
* short (&)[7]
|
||||||
|
@ -117,7 +118,8 @@ public class GnuDemanglerParser {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final Pattern ARRAY_POINTER_REFERENCE_PATTERN =
|
private static final Pattern ARRAY_POINTER_REFERENCE_PATTERN =
|
||||||
Pattern.compile("([\\w:]+)\\*?\\s(?:.*)\\(([&*])\\)\\s*((?:\\[.*?\\])+)");
|
Pattern.compile(
|
||||||
|
"\\s(?:const[\\[\\]\\d\\*&]{0,4}\\s)*\\(([&*])\\)\\s*((?:\\[.*?\\])+)");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sample: bob(short (&)[7])
|
* Sample: bob(short (&)[7])
|
||||||
|
@ -309,6 +311,16 @@ public class GnuDemanglerParser {
|
||||||
return Pattern.compile(operatorPrefix + parameters + trailing);
|
return Pattern.compile(operatorPrefix + parameters + trailing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pattern to catch literal strings of the form:
|
||||||
|
*
|
||||||
|
* -1l
|
||||||
|
* 2l
|
||||||
|
* 0u
|
||||||
|
* 4294967295u
|
||||||
|
*/
|
||||||
|
private static final Pattern LITERAL_NUMBER_PATTERN = Pattern.compile("-*\\d+[ul]{0,1}");
|
||||||
|
|
||||||
private String mangledSource;
|
private String mangledSource;
|
||||||
private String demangledSource;
|
private String demangledSource;
|
||||||
|
|
||||||
|
@ -353,6 +365,13 @@ public class GnuDemanglerParser {
|
||||||
return operatorHandler;
|
return operatorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: this really is a 'special handler' check that used to be handled above. However,
|
||||||
|
// some demangled operator strings begin with this text. If we do this check above,
|
||||||
|
// then we will not correctly handle those operators.
|
||||||
|
if (mangledSource.startsWith("_ZZ")) {
|
||||||
|
return new ItemInNamespaceHandler(demangled);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,9 +416,6 @@ public class GnuDemanglerParser {
|
||||||
return new ItemInNamespaceHandler(demangled, prefix, type);
|
return new ItemInNamespaceHandler(demangled, prefix, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mangled.startsWith("_ZZ")) {
|
|
||||||
return new ItemInNamespaceHandler(demangled);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,12 +436,15 @@ public class GnuDemanglerParser {
|
||||||
// following that text in the original string. We want the name to be the full lambda
|
// following that text in the original string. We want the name to be the full lambda
|
||||||
// text, without spaces.
|
// text, without spaces.
|
||||||
//
|
//
|
||||||
LambdaName lambdaName = getLambdaName(demangled);
|
String prefix = signatureParts.getRawParameterPrefix();
|
||||||
|
int lambdaStart = prefix.length() - LAMBDA_START.length(); // strip off '{lambda'
|
||||||
|
String lambdaText = demangled.substring(lambdaStart);
|
||||||
|
LambdaName lambdaName = getLambdaName(lambdaText);
|
||||||
String uniqueName = lambdaName.getFullText();
|
String uniqueName = lambdaName.getFullText();
|
||||||
String escapedLambda = removeBadSpaces(uniqueName);
|
String escapedLambda = removeBadSpaces(uniqueName);
|
||||||
simpleName = simpleName.replace(LAMBDA_START, escapedLambda);
|
simpleName = simpleName.replace(LAMBDA_START, escapedLambda);
|
||||||
function = new DemangledLambda(mangledSource, demangled, null);
|
function = new DemangledLambda(mangledSource, demangled, null);
|
||||||
function.setSignature(lambdaName.getFullText());
|
function.setBackupPlateComment(lambdaName.getFullText());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -437,16 +456,8 @@ public class GnuDemanglerParser {
|
||||||
function.addParameter(parameter);
|
function.addParameter(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For GNU, we cannot leave the return type as null, because the DemangleCmd will fill in
|
|
||||||
// pointer to the class to accommodate windows demangling
|
|
||||||
DemangledDataType defaultReturnType =
|
|
||||||
new DemangledDataType(mangledSource, demangled, "undefined");
|
|
||||||
function.setReturnType(defaultReturnType);
|
|
||||||
|
|
||||||
String returnType = signatureParts.getReturnType();
|
String returnType = signatureParts.getReturnType();
|
||||||
if (returnType != null) {
|
setReturnType(demangled, function, returnType);
|
||||||
setReturnType(function, returnType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (demangled.endsWith(CONST)) {
|
if (demangled.endsWith(CONST)) {
|
||||||
function.setConst(true);
|
function.setConst(true);
|
||||||
|
@ -455,27 +466,54 @@ public class GnuDemanglerParser {
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setReturnType(DemangledFunction function, String returnType) {
|
private void setReturnType(String demangled, DemangledFunction function, String returnType) {
|
||||||
|
|
||||||
if (DECLTYPE_RETURN_TYPE_PATTERN.matcher(returnType).matches()) {
|
String updatedReturnType = returnType;
|
||||||
|
if (returnType != null && DECLTYPE_RETURN_TYPE_PATTERN.matcher(returnType).matches()) {
|
||||||
// Not sure yet if there is any information we wish to recover from this pattern.
|
// Not sure yet if there is any information we wish to recover from this pattern.
|
||||||
// Sample: decltype (functionName({parm#1}, (float)[42c80000]))
|
// Sample: decltype (functionName({parm#1}, (float)[42c80000]))
|
||||||
|
updatedReturnType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedReturnType != null) {
|
||||||
|
function.setReturnType(parseReturnType(updatedReturnType));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function.setReturnType(parseReturnType(returnType));
|
// For GNU, we cannot leave the return type as null, because the DemangleCmd will fill in
|
||||||
|
// pointer to the class to accommodate windows demangling
|
||||||
|
DemangledDataType defaultReturnType =
|
||||||
|
new DemangledDataType(mangledSource, demangled, "undefined");
|
||||||
|
function.setReturnType(defaultReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LambdaName getLambdaName(String name) {
|
private LambdaName getLambdaName(String name) {
|
||||||
|
|
||||||
Matcher matcher = LAMBDA_PATTERN.matcher(name);
|
if (!name.startsWith("{")) {
|
||||||
|
// the text must start with the lambda syntax; ignore lambdas that are internal to
|
||||||
|
// the given name
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This replacement string will leave the initial 'lambda' text and replace all others
|
||||||
|
// with a placeholder value. This allows us to use a simple regex pattern when pulling
|
||||||
|
// the lambda apart. This is required to handle the case where a lambda expression
|
||||||
|
// contains a nested lambda expression.
|
||||||
|
LambdaReplacedString replacedString = new LambdaReplacedString(name);
|
||||||
|
String updatedName = replacedString.getModifiedText();
|
||||||
|
|
||||||
|
Matcher matcher = LAMBDA_PATTERN.matcher(updatedName);
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore the placeholder values to get back the original lambda text
|
||||||
String fullText = matcher.group(1);
|
String fullText = matcher.group(1);
|
||||||
|
fullText = replacedString.restoreReplacedText(fullText);
|
||||||
String params = matcher.group(2);
|
String params = matcher.group(2);
|
||||||
|
params = replacedString.restoreReplacedText(params);
|
||||||
String trailing = matcher.group(3);
|
String trailing = matcher.group(3);
|
||||||
|
trailing = replacedString.restoreReplacedText(trailing);
|
||||||
String modifiers = matcher.group(4);
|
String modifiers = matcher.group(4);
|
||||||
return new LambdaName(fullText, params, trailing, modifiers);
|
return new LambdaName(fullText, params, trailing, modifiers);
|
||||||
}
|
}
|
||||||
|
@ -513,7 +551,21 @@ public class GnuDemanglerParser {
|
||||||
DemangledObject parent = parseFunctionOrVariable(parentText);
|
DemangledObject parent = parseFunctionOrVariable(parentText);
|
||||||
String name = itemText.substring(pos + 2);
|
String name = itemText.substring(pos + 2);
|
||||||
DemangledObject item = parseFunctionOrVariable(name);
|
DemangledObject item = parseFunctionOrVariable(name);
|
||||||
item.setNamespace(parent);
|
|
||||||
|
//
|
||||||
|
// Convert the parent type to a suitable namespace. The parent type may have spaces
|
||||||
|
// in its name, which is not allowed in an applied namespace.
|
||||||
|
//
|
||||||
|
// We may eventually want to move this logic into the DemangledObject's
|
||||||
|
// createNamespace() method. This would also apply to the convertToNamespaces()
|
||||||
|
// method in this class.
|
||||||
|
//
|
||||||
|
String namespaceName = parent.getNamespaceName();
|
||||||
|
String escapedName = removeBadSpaces(namespaceName);
|
||||||
|
DemangledType type = new DemangledType(mangledSource, demangledSource, escapedName);
|
||||||
|
type.setNamespace(parent.getNamespace());
|
||||||
|
|
||||||
|
item.setNamespace(type);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,6 +582,19 @@ public class GnuDemanglerParser {
|
||||||
return condensedString.getCondensedText();
|
return condensedString.getCondensedText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String removeTrailingDereferenceCharacters(String text) {
|
||||||
|
|
||||||
|
int i = text.length() - 1;
|
||||||
|
for (; i >= 0; i--) {
|
||||||
|
char c = text.charAt(i);
|
||||||
|
if (c == '*' || c == '&') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return text.substring(0, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method separates the parameters as strings.
|
* This method separates the parameters as strings.
|
||||||
* This is more complicated then one might initially think.
|
* This is more complicated then one might initially think.
|
||||||
|
@ -670,6 +735,12 @@ public class GnuDemanglerParser {
|
||||||
return dt;
|
return dt;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this handles the case where the demangled template has an empty argument
|
||||||
|
if ("".equals(parameter.trim())) {
|
||||||
|
return new DemangledDataType(mangledSource, demangledSource, "missing_argument");
|
||||||
|
}
|
||||||
|
|
||||||
return parseDataType(parameter);
|
return parseDataType(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,10 +753,16 @@ public class GnuDemanglerParser {
|
||||||
DemangledDataType dt = createTypeInNamespace(fullDatatype);
|
DemangledDataType dt = createTypeInNamespace(fullDatatype);
|
||||||
String datatype = dt.getDemangledName();
|
String datatype = dt.getDemangledName();
|
||||||
|
|
||||||
if ("*".equals(datatype)) {
|
if (isMemberPointerOrReference(fullDatatype, datatype)) {
|
||||||
return createMemberPointer(fullDatatype);
|
return createMemberPointer(fullDatatype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: we should only encounter literals as template arguments. Function parameters
|
||||||
|
// and return types should never be literals.
|
||||||
|
if (isLiteral(fullDatatype)) {
|
||||||
|
return createLiteral(fullDatatype);
|
||||||
|
}
|
||||||
|
|
||||||
boolean finishedName = false;
|
boolean finishedName = false;
|
||||||
for (int i = 0; i < datatype.length(); ++i) {
|
for (int i = 0; i < datatype.length(); ++i) {
|
||||||
char ch = datatype.charAt(i);
|
char ch = datatype.charAt(i);
|
||||||
|
@ -734,23 +811,37 @@ public class GnuDemanglerParser {
|
||||||
|
|
||||||
LambdaName lambdaName = getLambdaName(datatype);
|
LambdaName lambdaName = getLambdaName(datatype);
|
||||||
|
|
||||||
// check for array case
|
//
|
||||||
Matcher arrayMatcher = ARRAY_POINTER_REFERENCE_PATTERN.matcher(datatype);
|
// Check for array case
|
||||||
if (arrayMatcher.matches()) {
|
//
|
||||||
Demangled namespace = dt.getNamespace();
|
// remove the templates to allow us to use a simpler regex when checking for arrays
|
||||||
String name = arrayMatcher.group(1);// group 0 is the entire string
|
DemangledDataType newDt = tryToParseArrayPointerOrReference(dt, datatype);
|
||||||
dt = parseArrayPointerOrReference(datatype, name, arrayMatcher);
|
if (newDt != null) {
|
||||||
dt.setNamespace(namespace);
|
dt = newDt;
|
||||||
i = arrayMatcher.end();
|
i = datatype.length();
|
||||||
}
|
}
|
||||||
|
// lambda case, maybe an array
|
||||||
else if (lambdaName != null) {
|
else if (lambdaName != null) {
|
||||||
String fullText = lambdaName.getFullText();
|
|
||||||
dt.setName(fullText);
|
DemangledDataType lambdaArrayDt =
|
||||||
int offset = fullText.indexOf('(');
|
tryToParseLambdaArrayPointerOrReference(lambdaName, dt, datatype);
|
||||||
int remaining = fullText.length() - offset;
|
if (lambdaArrayDt != null) {
|
||||||
i = i + remaining; // end of lambda's closing '}'
|
dt = lambdaArrayDt;
|
||||||
i = i - 1; // back up one space to catch optional templates on next loop pass
|
i = datatype.length();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// try a non-array lambda
|
||||||
|
String fullText = lambdaName.getFullText();
|
||||||
|
dt.setName(fullText);
|
||||||
|
int offset = fullText.indexOf('(');
|
||||||
|
// to to the end of the lambda, which is its length, minus our position
|
||||||
|
// inside the lambda
|
||||||
|
int remaining = fullText.length() - offset;
|
||||||
|
i = i + remaining; // end of lambda's closing '}'
|
||||||
|
i = i - 1; // back up one space to catch optional templates on next loop pass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// function pointer case
|
||||||
else {
|
else {
|
||||||
// e.g., unsigned long (*)(long const &)
|
// e.g., unsigned long (*)(long const &)
|
||||||
boolean hasPointerParens = hasConsecutiveSetsOfParens(datatype.substring(i));
|
boolean hasPointerParens = hasConsecutiveSetsOfParens(datatype.substring(i));
|
||||||
|
@ -856,6 +947,81 @@ public class GnuDemanglerParser {
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DemangledDataType createLiteral(String datatype) {
|
||||||
|
|
||||||
|
// literal cases handled: -1, -1l, -1ul
|
||||||
|
char lastChar = datatype.charAt(datatype.length() - 1);
|
||||||
|
if (lastChar == 'l') {
|
||||||
|
return new DemangledDataType(mangledSource, demangledSource, "long");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DemangledDataType(mangledSource, demangledSource, "int");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLiteral(String fullDatatype) {
|
||||||
|
Matcher m = LITERAL_NUMBER_PATTERN.matcher(fullDatatype);
|
||||||
|
return m.matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DemangledDataType tryToParseLambdaArrayPointerOrReference(LambdaName lambdaName,
|
||||||
|
DemangledDataType dt, String datatype) {
|
||||||
|
|
||||||
|
// remove the lambda text to allow us to use a simpler regex when checking for arrays
|
||||||
|
String fullText = lambdaName.getFullText();
|
||||||
|
ReplacedString lambdaString = new CustomReplacedString(datatype, fullText);
|
||||||
|
String noLambdaString = lambdaString.getModifiedText();
|
||||||
|
|
||||||
|
Matcher matcher = ARRAY_POINTER_REFERENCE_PATTERN.matcher(noLambdaString);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = matcher.start(0);
|
||||||
|
String leading = noLambdaString.substring(0, start);
|
||||||
|
leading = removeTrailingDereferenceCharacters(leading);
|
||||||
|
|
||||||
|
Demangled namespace = dt.getNamespace();
|
||||||
|
String name = leading;
|
||||||
|
DemangledDataType newDt = parseArrayPointerOrReference(datatype, name, lambdaString,
|
||||||
|
matcher);
|
||||||
|
newDt.setNamespace(namespace);
|
||||||
|
return newDt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DemangledDataType tryToParseArrayPointerOrReference(DemangledDataType dt,
|
||||||
|
String datatype) {
|
||||||
|
|
||||||
|
ReplacedString templatedString = new TemplatedString(datatype);
|
||||||
|
String untemplatedDatatype = templatedString.getModifiedText();
|
||||||
|
|
||||||
|
Matcher matcher = ARRAY_POINTER_REFERENCE_PATTERN.matcher(untemplatedDatatype);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = matcher.start(0);
|
||||||
|
String leading = untemplatedDatatype.substring(0, start);
|
||||||
|
leading = removeTrailingDereferenceCharacters(leading);
|
||||||
|
|
||||||
|
Demangled namespace = dt.getNamespace();
|
||||||
|
String name = leading;
|
||||||
|
DemangledDataType newDt = parseArrayPointerOrReference(datatype, name, templatedString,
|
||||||
|
matcher);
|
||||||
|
newDt.setNamespace(namespace);
|
||||||
|
return newDt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMemberPointerOrReference(String fullDataType, String datatype) {
|
||||||
|
|
||||||
|
String test = datatype;
|
||||||
|
test = test.replaceAll("const|\\*|&|\\s", "");
|
||||||
|
if (!test.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullDataType.endsWith(Namespace.DELIMITER + datatype);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasConsecutiveSetsOfParens(String text) {
|
private boolean hasConsecutiveSetsOfParens(String text) {
|
||||||
int end = findBalancedEnd(text, 0, '(', ')');
|
int end = findBalancedEnd(text, 0, '(', ')');
|
||||||
if (end < -1) {
|
if (end < -1) {
|
||||||
|
@ -869,9 +1035,12 @@ public class GnuDemanglerParser {
|
||||||
private DemangledDataType createMemberPointer(String datatype) {
|
private DemangledDataType createMemberPointer(String datatype) {
|
||||||
// this is temp code we expect to update as more samples arrive
|
// this is temp code we expect to update as more samples arrive
|
||||||
|
|
||||||
// example: NS1::Type1 NS1::ParenType::*
|
//
|
||||||
int trimLength = 3; // '::*'
|
// Examples:
|
||||||
String typeWithoutPointer = datatype.substring(0, datatype.length() - trimLength);
|
// Type NS1::Type1 NS1::ParenType::*
|
||||||
|
// Type NS1::Type1 NS1::ParenType::* const&
|
||||||
|
int namespaceEnd = datatype.lastIndexOf(Namespace.DELIMITER);
|
||||||
|
String typeWithoutPointer = datatype.substring(0, namespaceEnd);
|
||||||
int space = typeWithoutPointer.indexOf(' ');
|
int space = typeWithoutPointer.indexOf(' ');
|
||||||
DemangledDataType dt;
|
DemangledDataType dt;
|
||||||
if (space != -1) {
|
if (space != -1) {
|
||||||
|
@ -906,6 +1075,7 @@ public class GnuDemanglerParser {
|
||||||
Character.isDigit(ch) ||
|
Character.isDigit(ch) ||
|
||||||
ch == ':' ||
|
ch == ':' ||
|
||||||
ch == '_' ||
|
ch == '_' ||
|
||||||
|
ch == '{' ||
|
||||||
ch == '$';
|
ch == '$';
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
@ -1114,12 +1284,16 @@ public class GnuDemanglerParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemangledDataType parseArrayPointerOrReference(String datatype, String name,
|
private DemangledDataType parseArrayPointerOrReference(String datatype, String name,
|
||||||
Matcher matcher) {
|
ReplacedString replacedString, Matcher matcher) {
|
||||||
|
|
||||||
// int (*)[8]
|
// int (*)[8]
|
||||||
// char (&)[7]
|
// char (&)[7]
|
||||||
|
// Foo<Bar> const* const (&) [3]
|
||||||
|
|
||||||
DemangledDataType dt = new DemangledDataType(mangledSource, demangledSource, name);
|
String realName = replacedString.restoreReplacedText(name);
|
||||||
String type = matcher.group(2);
|
|
||||||
|
DemangledDataType dt = new DemangledDataType(mangledSource, demangledSource, realName);
|
||||||
|
String type = matcher.group(1);
|
||||||
if (type.equals("*")) {
|
if (type.equals("*")) {
|
||||||
dt.incrementPointerLevels();
|
dt.incrementPointerLevels();
|
||||||
}
|
}
|
||||||
|
@ -1130,9 +1304,29 @@ public class GnuDemanglerParser {
|
||||||
throw new DemanglerParseException("Unexpected charater inside of parens: " + type);
|
throw new DemanglerParseException("Unexpected charater inside of parens: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
String arraySubscripts = matcher.group(3);
|
//
|
||||||
int n = StringUtilities.countOccurrences(arraySubscripts, '[');
|
// Grab the middle text, for example, inside:
|
||||||
dt.setArray(n);
|
//
|
||||||
|
// Foo<Bar> const* const (&) [3]
|
||||||
|
//
|
||||||
|
// we would like to grab 'const* const(&)' and similar text such as 'const* const*'
|
||||||
|
//
|
||||||
|
String safeDatatype = replacedString.getModifiedText();
|
||||||
|
int midTextStart = safeDatatype.indexOf(name) + name.length();
|
||||||
|
int midTextEnd = matcher.start(1) - 1; // -1 for opening '('
|
||||||
|
String midText = safeDatatype.substring(midTextStart, midTextEnd);
|
||||||
|
if (midText.contains(CONST)) {
|
||||||
|
dt.setConst();
|
||||||
|
}
|
||||||
|
|
||||||
|
int pointers = StringUtils.countMatches(midText, '*');
|
||||||
|
for (int i = 0; i < pointers; i++) {
|
||||||
|
dt.incrementPointerLevels();
|
||||||
|
}
|
||||||
|
|
||||||
|
String arraySubscripts = matcher.group(2);
|
||||||
|
int arrays = StringUtilities.countOccurrences(arraySubscripts, '[');
|
||||||
|
dt.setArray(arrays);
|
||||||
|
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
@ -1141,14 +1335,14 @@ public class GnuDemanglerParser {
|
||||||
//unsigned long (*)(long const &)
|
//unsigned long (*)(long const &)
|
||||||
|
|
||||||
int parenStart = functionString.indexOf('(');
|
int parenStart = functionString.indexOf('(');
|
||||||
int parenEnd = functionString.indexOf(')');
|
int parenEnd = findBalancedEnd(functionString, parenStart, '(', ')');
|
||||||
|
|
||||||
String returnType = functionString.substring(0, parenStart).trim();
|
String returnType = functionString.substring(0, parenStart).trim();
|
||||||
|
|
||||||
int paramStart = functionString.indexOf('(', parenEnd + 1);
|
int paramStart = functionString.indexOf('(', parenEnd + 1);
|
||||||
int paramEnd = functionString.lastIndexOf(')');
|
int paramEnd = functionString.lastIndexOf(')');
|
||||||
String parameters = functionString.substring(paramStart + 1, paramEnd);
|
String parameters = functionString.substring(paramStart + 1, paramEnd);
|
||||||
return createFunctionPointer(parameters, returnType);
|
DemangledFunctionPointer dfp = createFunctionPointer(parameters, returnType);
|
||||||
|
return dfp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemangledFunctionPointer parseFunction(String functionString, int offset) {
|
private DemangledFunctionPointer parseFunction(String functionString, int offset) {
|
||||||
|
@ -1156,7 +1350,6 @@ public class GnuDemanglerParser {
|
||||||
|
|
||||||
int parenStart = functionString.indexOf('(', offset);
|
int parenStart = functionString.indexOf('(', offset);
|
||||||
int parenEnd = findBalancedEnd(functionString, parenStart, '(', ')');
|
int parenEnd = findBalancedEnd(functionString, parenStart, '(', ')');
|
||||||
//int parenEnd = functionString.indexOf(')', parenStart + 1);
|
|
||||||
|
|
||||||
String returnType = functionString.substring(0, parenStart).trim();
|
String returnType = functionString.substring(0, parenStart).trim();
|
||||||
|
|
||||||
|
@ -1164,7 +1357,9 @@ public class GnuDemanglerParser {
|
||||||
int paramEnd = parenEnd;
|
int paramEnd = parenEnd;
|
||||||
String parameters = functionString.substring(paramStart + 1, paramEnd);
|
String parameters = functionString.substring(paramStart + 1, paramEnd);
|
||||||
DemangledFunctionPointer dfp = createFunctionPointer(parameters, returnType);
|
DemangledFunctionPointer dfp = createFunctionPointer(parameters, returnType);
|
||||||
dfp.setDisplayFunctionPointerParens(false);
|
|
||||||
|
// disable the function pointer display so this type reads like a function
|
||||||
|
dfp.setDisplayDefaultFunctionPointerSyntax(false);
|
||||||
return dfp;
|
return dfp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,7 +1519,6 @@ public class GnuDemanglerParser {
|
||||||
DemangledObject doBuild(Demangled demangledObject) {
|
DemangledObject doBuild(Demangled demangledObject) {
|
||||||
|
|
||||||
DemangledFunction function = (DemangledFunction) demangledObject;
|
DemangledFunction function = (DemangledFunction) demangledObject;
|
||||||
function.setSignature(type);
|
|
||||||
function.setCallingConvention(CompilerSpec.CALLING_CONVENTION_thiscall);
|
function.setCallingConvention(CompilerSpec.CALLING_CONVENTION_thiscall);
|
||||||
|
|
||||||
DemangledThunk thunk = new DemangledThunk(mangledSource, demangledSource, function);
|
DemangledThunk thunk = new DemangledThunk(mangledSource, demangledSource, function);
|
||||||
|
@ -1545,9 +1739,14 @@ public class GnuDemanglerParser {
|
||||||
// Ghidra does not allow spaces in the name or extra parens. So, make a name that is
|
// Ghidra does not allow spaces in the name or extra parens. So, make a name that is
|
||||||
// as clear as possible in describing the construct.
|
// as clear as possible in describing the construct.
|
||||||
//
|
//
|
||||||
|
if (shortReturnTypeName.contains("(")) {
|
||||||
|
// assume function pointer
|
||||||
|
shortReturnTypeName = "function.pointer";
|
||||||
|
}
|
||||||
|
|
||||||
method.setName("operator.cast.to." + shortReturnTypeName);
|
method.setName("operator.cast.to." + shortReturnTypeName);
|
||||||
|
|
||||||
method.setSignature(fullName + " " + fullReturnType);
|
method.setBackupPlateComment(fullName + " " + fullReturnType + "()");
|
||||||
method.setOverloadedOperator(true);
|
method.setOverloadedOperator(true);
|
||||||
|
|
||||||
return method;
|
return method;
|
||||||
|
@ -1604,10 +1803,9 @@ public class GnuDemanglerParser {
|
||||||
if (arrayBrackets != null) {
|
if (arrayBrackets != null) {
|
||||||
name += "[]";
|
name += "[]";
|
||||||
}
|
}
|
||||||
|
|
||||||
function.setName("operator." + name);
|
function.setName("operator." + name);
|
||||||
|
function.setBackupPlateComment(operatorText + " " + operatorName);
|
||||||
function.setSignature(operatorText + " " + operatorName);
|
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1628,6 +1826,7 @@ public class GnuDemanglerParser {
|
||||||
paramEnd = -1;
|
paramEnd = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
paramStart = findParameterStart(text, paramEnd);
|
paramStart = findParameterStart(text, paramEnd);
|
||||||
int templateEnd = findTemplateEnd(text, 0);
|
int templateEnd = findTemplateEnd(text, 0);
|
||||||
int templateStart = -1;
|
int templateStart = -1;
|
||||||
|
@ -1727,6 +1926,7 @@ public class GnuDemanglerParser {
|
||||||
|
|
||||||
private String returnType;
|
private String returnType;
|
||||||
private String name;
|
private String name;
|
||||||
|
private String rawParameterPrefix;
|
||||||
|
|
||||||
private List<DemangledDataType> parameters;
|
private List<DemangledDataType> parameters;
|
||||||
|
|
||||||
|
@ -1746,9 +1946,9 @@ public class GnuDemanglerParser {
|
||||||
|
|
||||||
// 'prefix' is the text before the parameters
|
// 'prefix' is the text before the parameters
|
||||||
int prefixEndPos = paramStart;
|
int prefixEndPos = paramStart;
|
||||||
String rawPrefix = signatureString.substring(0, prefixEndPos).trim();
|
rawParameterPrefix = signatureString.substring(0, prefixEndPos).trim();
|
||||||
|
|
||||||
CondensedString prefixString = new CondensedString(rawPrefix);
|
CondensedString prefixString = new CondensedString(rawParameterPrefix);
|
||||||
String prefix = prefixString.getCondensedText();
|
String prefix = prefixString.getCondensedText();
|
||||||
int nameStart = Math.max(0, prefix.lastIndexOf(' '));
|
int nameStart = Math.max(0, prefix.lastIndexOf(' '));
|
||||||
name = prefix.substring(nameStart, prefix.length()).trim();
|
name = prefix.substring(nameStart, prefix.length()).trim();
|
||||||
|
@ -1767,6 +1967,11 @@ public class GnuDemanglerParser {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is the original demangled text up to, but excluding, the parameters
|
||||||
|
String getRawParameterPrefix() {
|
||||||
|
return rawParameterPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isValidFunction() {
|
boolean isValidFunction() {
|
||||||
return isFunction;
|
return isFunction;
|
||||||
}
|
}
|
||||||
|
@ -1880,4 +2085,149 @@ public class GnuDemanglerParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that allows us to pass around string content that has had some of its text
|
||||||
|
* replaced with temporary values. Clients can also use this class to get back the original
|
||||||
|
* text.
|
||||||
|
*/
|
||||||
|
private abstract class ReplacedString {
|
||||||
|
|
||||||
|
static final String PLACEHOLDER = "REPLACEDSTRINGTEMPNAMEPLACEHOLDERVALUE";
|
||||||
|
|
||||||
|
@SuppressWarnings("unused") // used by toString()
|
||||||
|
private String sourceText;
|
||||||
|
|
||||||
|
ReplacedString(String sourceText) {
|
||||||
|
this.sourceText = sourceText;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract String restoreReplacedText(String modifiedText);
|
||||||
|
|
||||||
|
abstract String getModifiedText();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Json.toString(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A string that clients can use to replace specific text patterns
|
||||||
|
*/
|
||||||
|
private class CustomReplacedString extends ReplacedString {
|
||||||
|
|
||||||
|
private String placeholderText = getClass().getSimpleName().toUpperCase() + PLACEHOLDER;
|
||||||
|
private String replacedText;
|
||||||
|
private String modifiedText;
|
||||||
|
|
||||||
|
CustomReplacedString(String input, String textToReplace) {
|
||||||
|
super(input);
|
||||||
|
this.replacedText = textToReplace;
|
||||||
|
this.modifiedText = input.replace(textToReplace, placeholderText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String restoreReplacedText(String mutatedText) {
|
||||||
|
return mutatedText.replace(placeholderText, replacedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getModifiedText() {
|
||||||
|
return modifiedText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class to replace templates with a temporary placeholder value
|
||||||
|
*/
|
||||||
|
private class TemplatedString extends ReplacedString {
|
||||||
|
|
||||||
|
private String placeholderText = getClass().getSimpleName().toUpperCase() + PLACEHOLDER;
|
||||||
|
|
||||||
|
private String replacedText;
|
||||||
|
private String modifiedText;
|
||||||
|
|
||||||
|
TemplatedString(String input) {
|
||||||
|
super(input);
|
||||||
|
replaceTemplates(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replaceTemplates(String string) {
|
||||||
|
StringBuilder buffy = new StringBuilder();
|
||||||
|
StringBuilder templateBuffer = new StringBuilder();
|
||||||
|
int depth = 0;
|
||||||
|
for (int i = 0; i < string.length(); i++) {
|
||||||
|
char c = string.charAt(i);
|
||||||
|
if (c == '<') {
|
||||||
|
if (depth == 0) {
|
||||||
|
buffy.append(placeholderText);
|
||||||
|
}
|
||||||
|
|
||||||
|
templateBuffer.append(c);
|
||||||
|
depth++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (c == '>') {
|
||||||
|
templateBuffer.append(c);
|
||||||
|
depth--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth == 0) {
|
||||||
|
buffy.append(c);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
templateBuffer.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiedText = buffy.toString();
|
||||||
|
replacedText = templateBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String restoreReplacedText(String s) {
|
||||||
|
return s.replace(placeholderText, replacedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getModifiedText() {
|
||||||
|
return modifiedText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class to replace the text 'lambda' with a temporary placeholder value
|
||||||
|
*/
|
||||||
|
private class LambdaReplacedString extends ReplacedString {
|
||||||
|
|
||||||
|
private String placeholderText = getClass().getSimpleName().toUpperCase() + PLACEHOLDER;
|
||||||
|
private String modifiedText;
|
||||||
|
|
||||||
|
LambdaReplacedString(String input) {
|
||||||
|
super(input);
|
||||||
|
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
Pattern p = Pattern.compile(LAMBDA);
|
||||||
|
Matcher matcher = p.matcher(input);
|
||||||
|
matcher.find(); // keep the first match
|
||||||
|
while (matcher.find()) {
|
||||||
|
matcher.appendReplacement(buffer, placeholderText);
|
||||||
|
}
|
||||||
|
matcher.appendTail(buffer);
|
||||||
|
modifiedText = buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String restoreReplacedText(String s) {
|
||||||
|
return s.replaceAll(placeholderText, LAMBDA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getModifiedText() {
|
||||||
|
return modifiedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,12 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
// bob(int const[8] (*) [12])
|
// bob(int const[8] (*) [12])
|
||||||
|
|
||||||
|
//
|
||||||
|
// Note: it is not clear whether the this demangled string is valid modern demangler output.
|
||||||
|
// We are creating a constant array pointer from this construct, but is this what
|
||||||
|
// we should be creating?
|
||||||
|
//
|
||||||
|
|
||||||
String demangled = "bob(int const[8] (*) [12])";
|
String demangled = "bob(int const[8] (*) [12])";
|
||||||
DemangledObject object = parser.parse("fake", demangled);
|
DemangledObject object = parser.parse("fake", demangled);
|
||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
|
@ -52,7 +58,27 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
DemangledDataType p1 = parameters.get(0);
|
DemangledDataType p1 = parameters.get(0);
|
||||||
assertEquals("bob(int const[8] (*) [12])", p1.getOriginalDemangled());
|
assertEquals("bob(int const[8] (*) [12])", p1.getOriginalDemangled());
|
||||||
assertEquals("undefined bob(int *[])", object.getSignature(false));
|
assertEquals("undefined bob(int const *[])", object.getSignature(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_ArrayPointerReferencePattern_ConstPointerToArrayReference()
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
// _S_ptr(entt::sparse_set<EntityId> const * &[])
|
||||||
|
|
||||||
|
String mangled =
|
||||||
|
"_ZNSt14__array_traitsIPKN4entt10sparse_setI8EntityIdEELm3EE6_S_ptrERA3_KS5_";
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"undefined std::__array_traits<entt::sparse_set<EntityId>const*,3ul>::_S_ptr(entt::sparse_set<EntityId> const * &[])",
|
||||||
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -122,14 +148,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined XpsMap<long,CORBA_TypeCode*>::XpsMap(" +
|
"undefined XpsMap<long,CORBA_TypeCode*>::XpsMap(" +
|
||||||
"unsigned long ()(long const &),unsigned long,unsigned long,float)",
|
"unsigned long (*)(long const &),unsigned long,unsigned long,float)",
|
||||||
object.getSignature(false));
|
object.getSignature(false));
|
||||||
|
|
||||||
DemangledFunction method = (DemangledFunction) object;
|
DemangledFunction method = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledDataType> parameters = method.getParameters();
|
||||||
assertEquals(4, parameters.size());
|
assertEquals(4, parameters.size());
|
||||||
assertEquals("unsigned long ()(long const &)", parameters.get(0).getSignature());
|
assertEquals("unsigned long (*)(long const &)", parameters.get(0).getSignature());
|
||||||
assertEquals("unsigned long", parameters.get(1).getSignature());
|
assertEquals("unsigned long", parameters.get(1).getSignature());
|
||||||
assertEquals("unsigned long", parameters.get(2).getSignature());
|
assertEquals("unsigned long", parameters.get(2).getSignature());
|
||||||
assertEquals("float", parameters.get(3).getSignature());
|
assertEquals("float", parameters.get(3).getSignature());
|
||||||
|
@ -182,7 +208,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
"__gnu_cxx::__normal_iterator<std::pair<unsigned long,PcodeOp *> *,std::vector<std::pair<unsigned long,PcodeOp *>,std::allocator<std::pair<unsigned long,PcodeOp *>>>>",
|
"__gnu_cxx::__normal_iterator<std::pair<unsigned long,PcodeOp *> *,std::vector<std::pair<unsigned long,PcodeOp *>,std::allocator<std::pair<unsigned long,PcodeOp *>>>>",
|
||||||
parameters.get(1).toString());
|
parameters.get(1).toString());
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"bool ()(std::pair<unsigned long,PcodeOp *> const &,std::pair<unsigned long,PcodeOp *> const &)",
|
"bool (*)(std::pair<unsigned long,PcodeOp *> const &,std::pair<unsigned long,PcodeOp *> const &)",
|
||||||
parameters.get(2).toString());
|
parameters.get(2).toString());
|
||||||
|
|
||||||
assertType(parameters.get(2), DemangledFunctionPointer.class);
|
assertType(parameters.get(2), DemangledFunctionPointer.class);
|
||||||
|
@ -334,6 +360,64 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
object.getSignature(false));
|
object.getSignature(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_DefaultArg() throws Exception {
|
||||||
|
|
||||||
|
//
|
||||||
|
// The demangled string contains this string: {default arg#1}
|
||||||
|
//
|
||||||
|
String mangled =
|
||||||
|
"_ZZN12PackManifest18CapabilityRegistry18registerCapabilityEN3gsl17basic_string_spanIKcLln1EEEbSt8functionIFbRS_R10PackReportbEEEd_NKUlS6_S8_bE_clES6_S8_b";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"PackManifest::CapabilityRegistry::registerCapability(gsl::basic_string_span<char_const,-1l>,bool,std::function<bool(PackManifest&,PackReport&,bool)>)::{default arg#1}::{lambda(PackManifest&,PackReport&,bool)#1}::operator()(PackManifest &,PackReport &,bool)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_UnnamedType() throws Exception {
|
||||||
|
|
||||||
|
//
|
||||||
|
// The demangled string contains this string: {unnamed_type#1}
|
||||||
|
//
|
||||||
|
String mangled =
|
||||||
|
"_ZN14GoalDefinitionUt_aSERKS0_";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"undefined GoalDefinition::{unnamed_type#1}::operator=({unnamed const &)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_DecltypeAuto() throws Exception {
|
||||||
|
|
||||||
|
String mangled =
|
||||||
|
"_Z9enum_castIN17FurnaceBlockActorUt_EEDcT_";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals("decltype (auto)", signature);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMethod() throws Exception {
|
public void testMethod() throws Exception {
|
||||||
String mangled = "_ZN3Foo7getBoolEf";
|
String mangled = "_ZN3Foo7getBoolEf";
|
||||||
|
@ -416,9 +500,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledObject object = parser.parse(mangled, demangled);
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
assertType(object, DemangledVariable.class);
|
assertType(object, DemangledVariable.class);
|
||||||
assertName(object, "dotdot", "KSimpleFileFilter", "passesFilter(KFileItem const *)");
|
assertName(object, "dotdot", "KSimpleFileFilter", "passesFilter(KFileItem_const*)");
|
||||||
|
|
||||||
assertEquals("KSimpleFileFilter::passesFilter(KFileItem const *)::dotdot",
|
assertEquals("KSimpleFileFilter::passesFilter(KFileItem_const*)::dotdot",
|
||||||
object.getSignature(false));
|
object.getSignature(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,9 +696,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledObject object = parser.parse(mangled, demangled);
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
assertType(object, DemangledVariable.class);
|
assertType(object, DemangledVariable.class);
|
||||||
assertName(object, "dialog", "DDDSaveOptionsCB(_WidgetRec *,void *,void *)");
|
assertName(object, "dialog", "DDDSaveOptionsCB(_WidgetRec*,void*,void*)");
|
||||||
|
|
||||||
assertEquals("DDDSaveOptionsCB(_WidgetRec *,void *,void *)::dialog",
|
assertEquals("DDDSaveOptionsCB(_WidgetRec*,void*,void*)::dialog",
|
||||||
object.getSignature(false));
|
object.getSignature(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,8 +766,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
assertName(object, "graphNew", "Layout");
|
assertName(object, "graphNew", "Layout");
|
||||||
|
|
||||||
// note: the two pointers were condensed to one (I think this is correct, but not sure)
|
assertEquals("undefined Layout::graphNew(_GRAPH * *[],char *)", object.getSignature(false));
|
||||||
assertEquals("undefined Layout::graphNew(_GRAPH *[],char *)", object.getSignature(false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -913,7 +996,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertEquals("operator<<", name);
|
assertEquals("operator<<", name);
|
||||||
assertName(object, "operator<<", "std", "basic_ostream<char,std::char_traits<char>>");
|
assertName(object, "operator<<", "std", "basic_ostream<char,std::char_traits<char>>");
|
||||||
assertEquals("undefined std::basic_ostream<char,std::char_traits<char>>" + "::operator<<(" +
|
assertEquals("undefined std::basic_ostream<char,std::char_traits<char>>" + "::operator<<(" +
|
||||||
"std::basic_ostream<char,std::char_traits<char>> & ()(std::basic_ostream<char,std::char_traits<char>> &))",
|
"std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))",
|
||||||
object.getSignature());
|
object.getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,6 +1062,128 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertEquals("Magick::Image &", parameters.get(0).getSignature());
|
assertEquals("Magick::Image &", parameters.get(0).getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPointerToArray_WithLambda() throws Exception {
|
||||||
|
|
||||||
|
String mangled =
|
||||||
|
"_ZNSt14__array_traitsIN12LayerDetails15RandomProviderTIZNKS0_9LayerBase10initRandomEllEUlRljE_EELm4EE6_S_refERA4_KS5_m";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"undefined std::__array_traits<LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>,4ul>::_S_ref(LayerDetails::LayerBase::initRandom(long,long) const::{lambda(long&, unsigned int)#1} const &[],unsigned long)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOperator_WithTemplatesMissingATemplateArgument() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Note: the empty template type: '<, std...'
|
||||||
|
<, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>
|
||||||
|
|
||||||
|
|
||||||
|
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::_Bind<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (EduAppConfigs::*(EduAppConfigs const*))() const>::operator()<, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >()
|
||||||
|
|
||||||
|
*/
|
||||||
|
String mangled =
|
||||||
|
"_ZNSt5_BindIFM13EduAppConfigsKFNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvEPKS0_EEclIJES6_EET0_DpOT_";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>> std::_Bind<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>(EduAppConfigs::*(EduAppConfigs_const*))()const>::operator()<missing_argument,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>(void)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParamegterWithTemplateValue_DataTypeLiteral_int() throws Exception {
|
||||||
|
|
||||||
|
String mangled = "_Z13reverse_rangeIjLin1EE5RangeIiXT0_EET_";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals("Range<int,int> reverse_range<unsigned_int,-1>(unsigned int)", signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParamegterWithTemplateValue_DataTypeLiteral_long() throws Exception {
|
||||||
|
|
||||||
|
String mangled =
|
||||||
|
"_ZN3gsl9to_stringIKcLln1EEENSt7__cxx1112basic_stringINSt12remove_constIT_E4typeESt11char_traitsIS7_ESaIS7_EEENS_17basic_string_spanIS5_XT0_EEE";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"std::__cxx11::basic_string<std::remove_const<char_const>::type,std::char_traits<std::remove_const<char_const>::type>,std::allocator<std::remove_const<char_const>::type>> gsl::to_string<char_const,-1l>(gsl::basic_string_span<char const,long>)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLambdaWithLambdaParameters() throws Exception {
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
lambda contents - lambdas in templates and as a parameter
|
||||||
|
|
||||||
|
bool (***
|
||||||
|
const* std::
|
||||||
|
__addressof<
|
||||||
|
Bedrock::
|
||||||
|
Threading::
|
||||||
|
TLSDetail::
|
||||||
|
DefaultConstructor<bool (**)(AssertHandlerContext const&), void>::
|
||||||
|
create()::
|
||||||
|
{lambda(bool (*** const)(AssertHandlerContext const&))#1}
|
||||||
|
>
|
||||||
|
(
|
||||||
|
Bedrock::
|
||||||
|
Threading::
|
||||||
|
TLSDetail::
|
||||||
|
DefaultConstructor<bool (**)(AssertHandlerContext const&), void>::
|
||||||
|
create()::
|
||||||
|
{lambda(bool (*** const&)(AssertHandlerContext const&))#1}
|
||||||
|
)
|
||||||
|
)(AssertHandlerContext const&)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
String mangled =
|
||||||
|
"_ZSt11__addressofIKZN7Bedrock9Threading9TLSDetail18DefaultConstructorIPPFbRK20AssertHandlerContextEvE6createEvEUlPS9_E_EPT_RSE_";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"undefined Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const*std::__addressof<Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const)(AssertHandlerContext_const&))#1}>(Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const&)(AssertHandlerContext_const&))#1}))(AssertHandlerContext_const&))#1}",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOperatorCastTo() throws Exception {
|
public void testOperatorCastTo() throws Exception {
|
||||||
//
|
//
|
||||||
|
@ -998,6 +1203,53 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertEquals("bool std::integral_constant::operator.cast.to.bool(void)", signature);
|
assertEquals("bool std::integral_constant::operator.cast.to.bool(void)", signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOperatorCastTo_FunctionPointer() throws Exception {
|
||||||
|
|
||||||
|
String mangled =
|
||||||
|
"_ZZNK4entt14basic_registryI8EntityIdE6assureI32FilteredTransformationAttributesI26PreHillsEdgeTransformationEEERKNS2_12pool_handlerIT_EEvENKUlRNS_10sparse_setIS1_EERS2_S1_E_cvPFvSE_SF_S1_EEv";
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Full demangled:
|
||||||
|
|
||||||
|
Operator Text
|
||||||
|
|
||||||
|
entt::
|
||||||
|
basic_registry<EntityId>::
|
||||||
|
assure<FilteredTransformationAttributes<PreHillsEdgeTransformation> >() const::
|
||||||
|
{lambda(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)#1}::
|
||||||
|
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)() const
|
||||||
|
|
||||||
|
Operartor Without Namespace
|
||||||
|
|
||||||
|
operator void (*)(entt::sparse_set<EntityId>&, entt::basic_registry<EntityId>&, EntityId)()
|
||||||
|
|
||||||
|
Simplified Cast Operator Construct
|
||||||
|
|
||||||
|
operator void (*)(A,B,C)()
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
String expected =
|
||||||
|
"void (* " +
|
||||||
|
"entt::" +
|
||||||
|
"basic_registry::" +
|
||||||
|
"assure() const::" +
|
||||||
|
"{lambda(entt::sparse_set&,entt::basic_registry&,EntityId)#1}::" +
|
||||||
|
"operator.cast.to.function.pointer(void)" +
|
||||||
|
")(entt::sparse_set<EntityId> &,entt::basic_registry<EntityId> &,EntityId)";
|
||||||
|
//@formatter:on
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(expected, signature);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConversionOperator() throws Exception {
|
public void testConversionOperator() throws Exception {
|
||||||
|
|
||||||
|
@ -1226,7 +1478,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertName(object, "FTransferGvmlData", "Dr", "ClipboardHelper");
|
assertName(object, "FTransferGvmlData", "Dr", "ClipboardHelper");
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined Dr::ClipboardHelper::FTransferGvmlData(Art::Transaction &,Ofc::TReferringPtr<Dr::DrawingE2o> const &,bool,Ofc::TCntPtr<IDataObject>,Dr::IClientDataCreator &,Ofc::TVector<Ofc::TWeakPtr<Dr::DrawingElement>,0u,4294967295u> &,Art::Rect64 &)",
|
"undefined Dr::ClipboardHelper::FTransferGvmlData(Art::Transaction &,Ofc::TReferringPtr<Dr::DrawingE2o> const &,bool,Ofc::TCntPtr<IDataObject>,Dr::IClientDataCreator &,Ofc::TVector<Ofc::TWeakPtr<Dr::DrawingElement>,int,int> &,Art::Rect64 &)",
|
||||||
object.getSignature(false));
|
object.getSignature(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,7 +1801,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1} brigand::for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,2l>>>(WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,0l>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,1l>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,2l>> &&)",
|
"WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1} brigand::for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,2l>>>(WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,long>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,long>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,long>> &&)",
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,7 +1839,46 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined WebCore::FontSelectionAlgorithm::filterCapability(bool *,WebCore::FontSelectionAlgorithm::DistanceResult ()(WebCore::FontSelectionCapabilities) const,WebCore::FontSelectionCapabilities::FontSelectionRange *)",
|
"undefined WebCore::FontSelectionAlgorithm::filterCapability(bool *,WebCore::FontSelectionAlgorithm::DistanceResult (*)(WebCore::FontSelectionCapabilities) const,WebCore::FontSelectionCapabilities::FontSelectionRange *)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFunctionParameterWithMemberPointer_ToFloat() throws Exception {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test to ensure proper handling of 'float AvoidBlockGoal::Definition::* const&'
|
||||||
|
// which is a const reference to a floating point member of the class
|
||||||
|
// AvoidBlockGoal::Definition
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Demangled:
|
||||||
|
|
||||||
|
auto && JsonUtil::
|
||||||
|
addMember<std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,AvoidBlockGoal::Definition,float>
|
||||||
|
(
|
||||||
|
|
||||||
|
std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,
|
||||||
|
float AvoidBlockGoal::Definition::*,
|
||||||
|
char const *,
|
||||||
|
float AvoidBlockGoal::Definition::* const&
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
*/
|
||||||
|
String mangled =
|
||||||
|
"_ZN8JsonUtil9addMemberISt10shared_ptrINS_20JsonSchemaObjectNodeINS_10EmptyClassEN14AvoidBlockGoal10DefinitionEEEES5_fEEODaT_MT0_T1_PKcRKSC_";
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"auto && JsonUtil::addMember<std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,AvoidBlockGoal::Definition,float>(std::shared_ptr<JsonUtil::JsonSchemaObjectNode<JsonUtil::EmptyClass,AvoidBlockGoal::Definition>>,AvoidBlockGoal::Definition::float *,char const *,AvoidBlockGoal::Definition::float *)",
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,7 +1909,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined WebCore::TextCodecICU::registerCodecs(void ()(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
"undefined WebCore::TextCodecICU::registerCodecs(void (*)(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1676,6 +1967,23 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOperator_ArrayReference() throws Exception {
|
||||||
|
String mangled =
|
||||||
|
"_ZN12LayerDetails15RandomProviderTIZNKS_9LayerBase10initRandomEllEUlRljE_EclIiLm2EEET_RAT0__KS6_";
|
||||||
|
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals(
|
||||||
|
"int LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>::operator()<int,2ul>(LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>::operator() const &[])",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLambdaWithTemplates() throws Exception {
|
public void testLambdaWithTemplates() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -476,6 +476,15 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
||||||
demangleAndTest();
|
demangleAndTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFunctionPointer_NamedFunctionPointerWithAnonymousFunctionPointerParameter()
|
||||||
|
throws Exception {
|
||||||
|
mangled = "?fun@@3P6KXP6KXH@Z@ZA";
|
||||||
|
msTruth = "void (* fun)(void (*)(int))";
|
||||||
|
mdTruth = msTruth;
|
||||||
|
demangleAndTest();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFunctionPointer_EMod_invalid() throws Exception {
|
public void testFunctionPointer_EMod_invalid() throws Exception {
|
||||||
mangled = "?fn@@3PE6AHH@ZA";
|
mangled = "?fn@@3PE6AHH@ZA";
|
||||||
|
|
|
@ -2312,7 +2312,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||||
SourceType originalSource = namespaceSymbol.getSource();
|
SourceType originalSource = namespaceSymbol.getSource();
|
||||||
|
|
||||||
// no duplicate check, since this class name will be set to that of the existing namespace
|
// no duplicate check, since this class name will be set to that of the existing namespace
|
||||||
String tempName = name + System.nanoTime();
|
String tempName = "_temp_" + System.nanoTime();
|
||||||
SymbolDB classSymbol =
|
SymbolDB classSymbol =
|
||||||
doCreateSpecialSymbol(Address.NO_ADDRESS, tempName, namespace.getParentNamespace(),
|
doCreateSpecialSymbol(Address.NO_ADDRESS, tempName, namespace.getParentNamespace(),
|
||||||
SymbolType.CLASS, -1, -1, null, originalSource, false /*check for duplicate */);
|
SymbolType.CLASS, -1, -1, null, originalSource, false /*check for duplicate */);
|
||||||
|
@ -2334,7 +2334,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||||
return classNamespace;
|
return classNamespace;
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
|
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
|
||||||
throw new AssertException("Unexpected exception creating class from namespace", e);
|
throw new AssertException("Unexpected exception creating class from namespace: " +
|
||||||
|
e.getMessage(), e);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
lock.release();
|
lock.release();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue