mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-24 22:32:22 +08:00
GT-3545 - GNU Demangler - Fix Parsing Issues - Checkpoint 1
All tests passing; major class model refactoring pending
This commit is contained in:
+1
-1
@@ -233,7 +233,7 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
log.appendMsg(getName(),
|
||||
"Failed to apply mangled symbol at " + address + "; name: " +
|
||||
demangled.getMangledName() + failMessage);
|
||||
demangled.getMangledString() + failMessage);
|
||||
}
|
||||
|
||||
protected String cleanSymbol(Address address, String name) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* ###
|
||||
* 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 ghidra.app.util.demangler;
|
||||
|
||||
// TODO better name
|
||||
public interface Demangled {
|
||||
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Returns the namespace containing this demangled object
|
||||
* @return the namespace containing this demangled object
|
||||
*/
|
||||
public Demangled getNamespace();
|
||||
|
||||
public void setNamespace(Demangled ns);
|
||||
|
||||
public String toNamespaceString();
|
||||
|
||||
// TODO doc difference
|
||||
public String toNamespaceName();
|
||||
|
||||
/**
|
||||
* Returns the original mangled string
|
||||
* @return the string
|
||||
*/
|
||||
public String getMangledString();
|
||||
|
||||
public void setMangledString(String mangled);
|
||||
}
|
||||
+8
-6
@@ -27,11 +27,11 @@ import util.demangler.GenericDemangledAddressTable;
|
||||
|
||||
public class DemangledAddressTable extends DemangledObject {
|
||||
|
||||
private boolean calculateLength;
|
||||
private int length;
|
||||
|
||||
public DemangledAddressTable(String name, int length) {
|
||||
public DemangledAddressTable(String name, boolean calculateLength) {
|
||||
setName(name);
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
DemangledAddressTable(GenericDemangledAddressTable generic) {
|
||||
@@ -57,7 +57,7 @@ public class DemangledAddressTable extends DemangledObject {
|
||||
buffer.append(specialPrefix);
|
||||
buffer.append(' ');
|
||||
}
|
||||
String namespaceStr = namespace.toSignature();
|
||||
String namespaceStr = namespace.toNamespaceString();
|
||||
buffer.append(namespaceStr);
|
||||
if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) {
|
||||
buffer.append(NAMESPACE_SEPARATOR);
|
||||
@@ -83,15 +83,16 @@ public class DemangledAddressTable extends DemangledObject {
|
||||
return false;
|
||||
}
|
||||
|
||||
Listing listing = program.getListing();
|
||||
if (MemoryBlock.isExternalBlockAddress(address, program)) {
|
||||
program.getListing().setComment(address, CodeUnit.EOL_COMMENT,
|
||||
listing.setComment(address, CodeUnit.EOL_COMMENT,
|
||||
"WARNING: Unable to apply demangled Address Table");
|
||||
return true; // don't complain
|
||||
}
|
||||
|
||||
if (length == -1) {
|
||||
if (calculateLength) {
|
||||
// determine length of address table
|
||||
Data d = program.getListing().getDefinedDataAt(address);
|
||||
Data d = listing.getDefinedDataAt(address);
|
||||
if (d != null && Undefined.isUndefinedArray(d.getDataType())) {
|
||||
// use length of Undefined array at start of table to indicate length
|
||||
length = d.getLength();
|
||||
@@ -102,6 +103,7 @@ public class DemangledAddressTable extends DemangledObject {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
calculateLength = false;
|
||||
}
|
||||
|
||||
if (isUndefinedInRange(program, address, address.add(length - 1))) {
|
||||
|
||||
+13
-16
@@ -22,6 +22,7 @@ import java.util.regex.Pattern;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
@@ -84,14 +85,13 @@ public class DemangledDataType extends DemangledType {
|
||||
private boolean isEnum;
|
||||
private boolean isPointer64;
|
||||
private boolean isReference;
|
||||
private boolean isSigned;//explicitly signed!
|
||||
private boolean isSigned;
|
||||
private boolean isStruct;
|
||||
private boolean isTemplate;
|
||||
private boolean isUnaligned;
|
||||
private boolean isUnion;
|
||||
private boolean isUnsigned;
|
||||
private boolean isVarArgs;
|
||||
// private boolean isVolatile;
|
||||
private int pointerLevels = 0;
|
||||
private String enumType;
|
||||
private boolean isRestrict;
|
||||
@@ -408,12 +408,12 @@ public class DemangledDataType extends DemangledType {
|
||||
* @param dataTypeManager data type manager to be searched
|
||||
* @param dtName name of data type
|
||||
* @param namespace namespace associated with dtName or null if not applicable. If specified,
|
||||
* a namespace-base category path will be given precendence.
|
||||
* a namespace-base category path will be given precedence.
|
||||
* @return data type if found, otherwise null.
|
||||
* @see DataTypeUtilities#findDataType(DataTypeManager, ghidra.program.model.symbol.Namespace, String, Class) for similar namespace
|
||||
* based search.
|
||||
*/
|
||||
static DataType findDataType(DataTypeManager dataTypeManager, DemangledType namespace,
|
||||
static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace,
|
||||
String dtName) {
|
||||
// TODO: Should be able to search archives somehow
|
||||
ArrayList<DataType> list = new ArrayList<>();
|
||||
@@ -446,11 +446,11 @@ public class DemangledDataType extends DemangledType {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isNamespaceCategoryMatch(DataType dt, DemangledType namespace) {
|
||||
private static boolean isNamespaceCategoryMatch(DataType dt, Demangled namespace) {
|
||||
if (namespace == null) {
|
||||
return true;
|
||||
}
|
||||
DemangledType ns = namespace;
|
||||
Demangled ns = namespace;
|
||||
CategoryPath categoryPath = dt.getCategoryPath();
|
||||
while (ns != null) {
|
||||
if (categoryPath.equals(CategoryPath.ROOT) ||
|
||||
@@ -463,8 +463,8 @@ public class DemangledDataType extends DemangledType {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getNamespacePath(String dtName, DemangledType namespace) {
|
||||
DemangledType ns = namespace;
|
||||
private static String getNamespacePath(String dtName, Demangled namespace) {
|
||||
Demangled ns = namespace;
|
||||
String namespacePath = "";
|
||||
while (ns != null) {
|
||||
namespacePath = "/" + ns.getName() + namespacePath;
|
||||
@@ -473,11 +473,11 @@ public class DemangledDataType extends DemangledType {
|
||||
return namespacePath;
|
||||
}
|
||||
|
||||
private static CategoryPath getDemanglerCategoryPath(String dtName, DemangledType namespace) {
|
||||
private static CategoryPath getDemanglerCategoryPath(String dtName, Demangled namespace) {
|
||||
return new CategoryPath("/Demangler" + getNamespacePath(dtName, namespace));
|
||||
}
|
||||
|
||||
static Structure createPlaceHolderStructure(String dtName, DemangledType namespace) {
|
||||
static Structure createPlaceHolderStructure(String dtName, Demangled namespace) {
|
||||
StructureDataType structDT = new StructureDataType(dtName, 0);
|
||||
structDT.setDescription("PlaceHolder Structure");
|
||||
structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace));
|
||||
@@ -561,10 +561,6 @@ public class DemangledDataType extends DemangledType {
|
||||
isVarArgs = true;
|
||||
}
|
||||
|
||||
// public void setVolatile() {
|
||||
// isVolatile = true;
|
||||
// }
|
||||
//
|
||||
public void setEnumType(String enumType) {
|
||||
this.enumType = enumType;
|
||||
}
|
||||
@@ -685,7 +681,7 @@ public class DemangledDataType extends DemangledType {
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
if (isUnion) {
|
||||
buffer.append(UNION + SPACE);
|
||||
@@ -722,7 +718,8 @@ public class DemangledDataType extends DemangledType {
|
||||
}
|
||||
|
||||
if (getNamespace() != null) {
|
||||
buffer.append(getNamespace().toNamespace());
|
||||
buffer.append(getNamespace().toNamespaceString());
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
}
|
||||
|
||||
buffer.append(getDemangledName());
|
||||
|
||||
+17
-7
@@ -159,7 +159,10 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||
return callingConvention;
|
||||
}
|
||||
|
||||
/** Special constructor where it has a templated type before the parameter list */
|
||||
/**
|
||||
* Special constructor where it has a templated type before the parameter list
|
||||
* @param type the type
|
||||
*/
|
||||
public void setTemplatedConstructorType(String type) {
|
||||
this.templatedConstructorType = type;
|
||||
}
|
||||
@@ -227,7 +230,6 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||
}
|
||||
buffer.append(
|
||||
visibility == null || "global".equals(visibility) ? "" : visibility + " ");
|
||||
// if (virtual) {
|
||||
if (isVirtual) {
|
||||
buffer.append("virtual ");
|
||||
}
|
||||
@@ -242,7 +244,8 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||
|
||||
buffer.append(callingConvention == null ? "" : callingConvention + " ");
|
||||
if (namespace != null) {
|
||||
buffer.append(namespace.toNamespace());
|
||||
buffer.append(namespace.toNamespaceString());
|
||||
buffer.append(NAMESPACE_SEPARATOR);
|
||||
}
|
||||
|
||||
buffer.append(getDemangledName());
|
||||
@@ -351,6 +354,11 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
return getName() + getParameterString();
|
||||
}
|
||||
|
||||
public String getParameterString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append('(');
|
||||
@@ -530,9 +538,11 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||
// warn that calling convention not found. Datatypes are still good,
|
||||
// the real calling convention can be figured out later
|
||||
// For example X64 can have __cdecl, __fastcall, __stdcall, that are accepted but ignored
|
||||
program.getBookmarkManager().setBookmark(func.getEntryPoint(),
|
||||
BookmarkType.ANALYSIS, "Demangler", "Warning calling convention \"" +
|
||||
callingConvention + "\" not defined in Compiler Spec (.cspec)");
|
||||
program.getBookmarkManager()
|
||||
.setBookmark(func.getEntryPoint(),
|
||||
BookmarkType.ANALYSIS, "Demangler",
|
||||
"Warning calling convention \"" +
|
||||
callingConvention + "\" not defined in Compiler Spec (.cspec)");
|
||||
}
|
||||
else {
|
||||
func.setCallingConvention(callingConvention);
|
||||
@@ -714,7 +724,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||
* @return true if it is in the std namespace
|
||||
*/
|
||||
private boolean isInStdNameSpace() {
|
||||
DemangledType ns = namespace;
|
||||
Demangled ns = namespace;
|
||||
|
||||
// if my immediate namespace is "std", then I am just a function in the std namespace.
|
||||
if (ns == null) {
|
||||
|
||||
+12
-9
@@ -198,8 +198,8 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||
}
|
||||
|
||||
public String toSignature(String name) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuffer buffer1 = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
StringBuilder buffer1 = new StringBuilder();
|
||||
String s = getConventionPointerNameString(name);
|
||||
if (s.contains(" ") || s.isEmpty()) {
|
||||
// spaces--add parens
|
||||
@@ -220,18 +220,21 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||
|
||||
if (returnType instanceof DemangledFunctionPointer) {
|
||||
buffer.append(
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionReference) {
|
||||
buffer.append(
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||
buffer.append(
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else {
|
||||
buffer.append(returnType.toSignature()).append(SPACE);
|
||||
@@ -276,7 +279,7 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void addFunctionPointerParens(StringBuffer buffer, String s) {
|
||||
private void addFunctionPointerParens(StringBuilder buffer, String s) {
|
||||
if (!displayFunctionPointerParens) {
|
||||
return;
|
||||
}
|
||||
|
||||
-5
@@ -28,11 +28,6 @@ public class DemangledFunctionType extends DemangledType {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFunction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/* ###
|
||||
* 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 ghidra.app.util.demangler;
|
||||
|
||||
public class DemangledLambda extends DemangledFunction {
|
||||
|
||||
public DemangledLambda(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
@@ -18,6 +17,7 @@ package ghidra.app.util.demangler;
|
||||
|
||||
import util.demangler.GenericDemangledMethod;
|
||||
|
||||
// TODO delete this
|
||||
public class DemangledMethod extends DemangledFunction {
|
||||
|
||||
public DemangledMethod(String name) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import util.demangler.GenericDemangledType;
|
||||
/**
|
||||
* A class to represent a demangled object.
|
||||
*/
|
||||
public abstract class DemangledObject {
|
||||
public abstract class DemangledObject implements Demangled {
|
||||
|
||||
protected static final String SPACE = " ";
|
||||
protected static final Pattern SPACE_PATTERN = Pattern.compile(SPACE);
|
||||
@@ -42,12 +42,12 @@ public abstract class DemangledObject {
|
||||
protected static final String NAMESPACE_SEPARATOR = Namespace.DELIMITER;
|
||||
protected static final String EMPTY_STRING = "";
|
||||
|
||||
protected String originalMangled;
|
||||
protected String mangled; // original mangled string
|
||||
protected String utilDemangled;
|
||||
protected String specialPrefix;
|
||||
protected String specialMidfix;
|
||||
protected String specialSuffix;
|
||||
protected DemangledType namespace;
|
||||
protected Demangled namespace;
|
||||
protected String visibility;//public, protected, etc.
|
||||
|
||||
//TODO: storageClass refers to things such as "static" but const and volatile are
|
||||
@@ -78,7 +78,7 @@ public abstract class DemangledObject {
|
||||
}
|
||||
|
||||
DemangledObject(GenericDemangledObject other) {
|
||||
originalMangled = other.getOriginalMangled();
|
||||
mangled = other.getOriginalMangled();
|
||||
specialPrefix = other.getSpecialPrefix();
|
||||
specialMidfix = other.getSpecialMidfix();
|
||||
specialSuffix = other.getSpecialSuffix();
|
||||
@@ -115,20 +115,13 @@ public abstract class DemangledObject {
|
||||
return demangledName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original mangled name
|
||||
* @return the name
|
||||
*/
|
||||
public String getMangledName() {
|
||||
return originalMangled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the demangled name of this object.
|
||||
* NOTE: unsupported symbol characters, like whitespace, will be
|
||||
* converted to an underscore.
|
||||
* @return name of this DemangledObject with unsupported characters converted to underscore
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -228,12 +221,14 @@ public abstract class DemangledObject {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the original mangled name
|
||||
* @param mangled the original mangled name
|
||||
*/
|
||||
public void setOriginalMangled(String mangled) {
|
||||
this.originalMangled = mangled;
|
||||
@Override
|
||||
public void setMangledString(String mangled) {
|
||||
this.mangled = mangled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMangledString() {
|
||||
return mangled;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,15 +247,13 @@ public abstract class DemangledObject {
|
||||
return utilDemangled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the namespace containing this demangled object.
|
||||
* @return the namespace containing this demangled object
|
||||
*/
|
||||
public DemangledType getNamespace() {
|
||||
@Override
|
||||
public Demangled getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(DemangledType namespace) {
|
||||
@Override
|
||||
public void setNamespace(Demangled namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@@ -317,6 +310,15 @@ public abstract class DemangledObject {
|
||||
*/
|
||||
public abstract String getSignature(boolean format);
|
||||
|
||||
/**
|
||||
* Returns a signature that contains only the name (and parameter list for functions)
|
||||
* @return the signature
|
||||
*/
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
return getSignature(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the signature. Calling this method will
|
||||
* override the auto-generated signature.
|
||||
@@ -331,6 +333,17 @@ public abstract class DemangledObject {
|
||||
return getSignature(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceString() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if (namespace != null) {
|
||||
buffer.append(namespace.toNamespaceString());
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
}
|
||||
buffer.append(toNamespaceName());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the symbol at address has already been demangled. While memory symbols
|
||||
* check for presence of demangledName, external symbols simply check if demangled/alternate
|
||||
@@ -364,7 +377,7 @@ public abstract class DemangledObject {
|
||||
|
||||
public boolean applyTo(Program program, Address address, DemanglerOptions options,
|
||||
TaskMonitor monitor) throws Exception {
|
||||
if (originalMangled.equals(name)) {
|
||||
if (mangled.equals(name)) {
|
||||
return false;
|
||||
}
|
||||
String comment = program.getListing().getComment(CodeUnit.PLATE_COMMENT, address);
|
||||
@@ -432,7 +445,7 @@ public abstract class DemangledObject {
|
||||
}
|
||||
|
||||
private Symbol updateExternalSymbol(Program program, Address externalAddr, String symbolName,
|
||||
DemangledType demangledNamespace) {
|
||||
Demangled demangledNamespace) {
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol s = symbolTable.getPrimarySymbol(externalAddr);
|
||||
@@ -461,9 +474,9 @@ public abstract class DemangledObject {
|
||||
* @param typeNamespace demangled namespace object
|
||||
* @return list of namespace names
|
||||
*/
|
||||
private static List<String> getNamespaceList(DemangledType typeNamespace) {
|
||||
private static List<String> getNamespaceList(Demangled typeNamespace) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
DemangledType ns = typeNamespace;
|
||||
Demangled ns = typeNamespace;
|
||||
while (ns != null) {
|
||||
list.add(0, ns.getName());
|
||||
ns = ns.getNamespace();
|
||||
@@ -478,13 +491,13 @@ public abstract class DemangledObject {
|
||||
* any symbol creation accordingly. Caller should use
|
||||
* <code>getResidualNamespacePath(DemangledType, Namespace)</code> to handle the case where
|
||||
* only a partial namespace has been returned.
|
||||
* @param program
|
||||
* @param program the program
|
||||
* @param typeNamespace demangled namespace
|
||||
* @param parentNamespace root namespace to be used (e.g., library, global, etc.)
|
||||
* @param functionPermitted if true an existing function may be used as a namespace
|
||||
* @return namespace or partial namespace if error occurs
|
||||
*/
|
||||
public static Namespace createNamespace(Program program, DemangledType typeNamespace,
|
||||
public static Namespace createNamespace(Program program, Demangled typeNamespace,
|
||||
Namespace parentNamespace, boolean functionPermitted) {
|
||||
|
||||
Namespace namespace = parentNamespace;
|
||||
@@ -592,7 +605,7 @@ public abstract class DemangledObject {
|
||||
}
|
||||
|
||||
// Store class structure in parent namespace
|
||||
DemangledType classStructureNamespace = namespace.getNamespace();
|
||||
Demangled classStructureNamespace = namespace.getNamespace();
|
||||
|
||||
Structure classStructure = (Structure) DemangledDataType.findDataType(dataTypeManager,
|
||||
classStructureNamespace, structureName);
|
||||
|
||||
@@ -106,7 +106,7 @@ public class DemangledThunk extends DemangledObject {
|
||||
function = function.getThunkedFunction(false);
|
||||
}
|
||||
|
||||
if (thunkedFunction != null && originalMangled.equals(function.getName()) &&
|
||||
if (thunkedFunction != null && mangled.equals(function.getName()) &&
|
||||
!function.isThunk()) {
|
||||
function.setThunkedFunction(thunkedFunction);
|
||||
}
|
||||
@@ -147,8 +147,9 @@ public class DemangledThunk extends DemangledObject {
|
||||
while (instr != null) {
|
||||
// This is done in a way to handle potential delay slots
|
||||
InstructionContext instructionContext = instr.getInstructionContext();
|
||||
Address fallThru = instructionContext.getAddress().add(
|
||||
instr.getPrototype().getFallThroughOffset(instructionContext));
|
||||
Address fallThru = instructionContext.getAddress()
|
||||
.add(
|
||||
instr.getPrototype().getFallThroughOffset(instructionContext));
|
||||
Address maxAddr = fallThru.previous();
|
||||
if (maxAddr.compareTo(instr.getMinAddress()) < 0) {
|
||||
// just in case we wrapped
|
||||
@@ -181,7 +182,7 @@ public class DemangledThunk extends DemangledObject {
|
||||
}
|
||||
|
||||
Symbol s = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
|
||||
thunkedFunctionObject.originalMangled, err -> Msg.warn(this, err));
|
||||
thunkedFunctionObject.mangled, err -> Msg.warn(this, err));
|
||||
|
||||
if (s == null) {
|
||||
Address thunkedAddr =
|
||||
|
||||
@@ -22,11 +22,12 @@ import ghidra.program.model.symbol.Namespace;
|
||||
import util.demangler.GenericDemangledTemplate;
|
||||
import util.demangler.GenericDemangledType;
|
||||
|
||||
public class DemangledType {
|
||||
// TODO maybe rename this to DemangledNamespace
|
||||
public class DemangledType implements Demangled {
|
||||
private String demangledName;
|
||||
private String name;
|
||||
protected String originalMangled;
|
||||
protected DemangledType namespace;
|
||||
protected String mangled; // the original mangled string
|
||||
protected Demangled namespace;
|
||||
protected DemangledTemplate template;
|
||||
private boolean isConst;
|
||||
private boolean isVolatile;
|
||||
@@ -41,7 +42,7 @@ public class DemangledType {
|
||||
* that contains a child, that contains a child and so on, representing the
|
||||
* split-up of the original namespace string.
|
||||
*/
|
||||
public static DemangledType convertToNamespace(GenericDemangledType otherNamespace) {
|
||||
public static Demangled convertToNamespace(GenericDemangledType otherNamespace) {
|
||||
if (otherNamespace == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -103,6 +104,7 @@ public class DemangledType {
|
||||
* converted to an underscore.
|
||||
* @return name of this DemangledType suitable for namespace creation.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -120,20 +122,14 @@ public class DemangledType {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the original mangled name
|
||||
* @param mangled the original mangled name
|
||||
*/
|
||||
public void setOriginalMangled(String mangled) {
|
||||
this.originalMangled = mangled;
|
||||
@Override
|
||||
public void setMangledString(String mangled) {
|
||||
this.mangled = mangled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original mangled name
|
||||
* @return the original mangled name
|
||||
*/
|
||||
public String getOriginalMangled() {
|
||||
return originalMangled;
|
||||
@Override
|
||||
public String getMangledString() {
|
||||
return mangled;
|
||||
}
|
||||
|
||||
public boolean isConst() {
|
||||
@@ -144,10 +140,6 @@ public class DemangledType {
|
||||
isConst = true;
|
||||
}
|
||||
|
||||
public boolean isFunction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isVolatile() {
|
||||
return isVolatile;
|
||||
}
|
||||
@@ -156,11 +148,13 @@ public class DemangledType {
|
||||
isVolatile = true;
|
||||
}
|
||||
|
||||
public DemangledType getNamespace() {
|
||||
@Override
|
||||
public Demangled getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(DemangledType namespace) {
|
||||
@Override
|
||||
public void setNamespace(Demangled namespace) {
|
||||
if (this == namespace) {
|
||||
throw new IllegalArgumentException("Attempt to set this.namespace == this!");
|
||||
}
|
||||
@@ -176,14 +170,21 @@ public class DemangledType {
|
||||
}
|
||||
|
||||
public String toSignature() {
|
||||
return toNamespace();
|
||||
return toNamespaceString();
|
||||
}
|
||||
|
||||
public String toNamespace() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
if (namespace != null) {
|
||||
buffer.append(namespace.toNamespace());
|
||||
@Override
|
||||
public String toNamespaceString() {
|
||||
return getName(true);
|
||||
}
|
||||
|
||||
private String getName(boolean includeNamespace) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if (includeNamespace && namespace != null) {
|
||||
buffer.append(namespace.toNamespaceString());
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
}
|
||||
|
||||
buffer.append(demangledName);
|
||||
if (template != null) {
|
||||
buffer.append(template.toTemplate());
|
||||
@@ -193,12 +194,16 @@ public class DemangledType {
|
||||
return "";
|
||||
}
|
||||
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
return getName(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toNamespace();
|
||||
return toNamespaceString();
|
||||
}
|
||||
}
|
||||
|
||||
+21
-9
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package ghidra.app.util.demangler;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.cmd.data.CreateDataCmd;
|
||||
import ghidra.app.util.PseudoDisassembler;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -70,7 +72,7 @@ public class DemangledVariable extends DemangledObject {
|
||||
|
||||
@Override
|
||||
public String getSignature(boolean format) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(specialPrefix == null ? EMPTY_STRING : specialPrefix + SPACE);
|
||||
buffer.append(
|
||||
visibility == null || "global".equals(visibility) ? EMPTY_STRING : visibility + SPACE);
|
||||
@@ -80,7 +82,7 @@ public class DemangledVariable extends DemangledObject {
|
||||
buffer.append(isVirtual ? "virtual" + SPACE : EMPTY_STRING);
|
||||
|
||||
String n = getDemangledName();
|
||||
boolean hasName = (n != null) && !n.isEmpty();
|
||||
boolean hasName = !StringUtils.isBlank(n);
|
||||
|
||||
StringBuffer datatypeBuffer = new StringBuffer();
|
||||
String spacer = EMPTY_STRING;
|
||||
@@ -139,11 +141,10 @@ public class DemangledVariable extends DemangledObject {
|
||||
datatypeBuffer.append(spacer);
|
||||
spacer = EMPTY_STRING;
|
||||
|
||||
datatypeBuffer.append(namespace.toNamespace());
|
||||
datatypeBuffer.append(namespace.toNamespaceString());
|
||||
|
||||
if (!hasName) {
|
||||
int end = buffer.length();
|
||||
datatypeBuffer.delete(end - 2, end); // strip off the last namespace characters
|
||||
if (hasName) {
|
||||
datatypeBuffer.append(NAMESPACE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,17 +159,14 @@ public class DemangledVariable extends DemangledObject {
|
||||
|
||||
if (datatype instanceof DemangledFunctionPointer) {
|
||||
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) datatype;
|
||||
//return funcPtr.toSignature(buffer.toString());
|
||||
return buffer.append(funcPtr.toSignature(datatypeBuffer.toString())).toString();
|
||||
}
|
||||
else if (datatype instanceof DemangledFunctionReference) {
|
||||
DemangledFunctionReference funcRef = (DemangledFunctionReference) datatype;
|
||||
//return funcRef.toSignature(buffer.toString());
|
||||
return buffer.append(funcRef.toSignature(datatypeBuffer.toString())).toString();
|
||||
}
|
||||
else if (datatype instanceof DemangledFunctionIndirect) {
|
||||
DemangledFunctionIndirect funcDef = (DemangledFunctionIndirect) datatype;
|
||||
//return funcDef.toSignature(buffer.toString());
|
||||
return buffer.append(funcDef.toSignature(datatypeBuffer.toString())).toString();
|
||||
}
|
||||
|
||||
@@ -177,6 +175,20 @@ public class DemangledVariable extends DemangledObject {
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
|
||||
String n = getDemangledName();
|
||||
if (!StringUtils.isBlank(n)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
if (datatype != null) {
|
||||
return datatype.toSignature();
|
||||
}
|
||||
return "<no name>"; // shouldn't happen
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAlreadyDemangled(Program program, Address address) {
|
||||
Data data = program.getListing().getDefinedDataAt(address);
|
||||
|
||||
@@ -146,13 +146,4 @@ public class DemanglerUtil {
|
||||
matcher.appendTail(buffy);
|
||||
return buffy.toString();
|
||||
}
|
||||
|
||||
public static void setNamespace(DemangledType dt, DemangledType namespace) {
|
||||
if (dt.getNamespace() == null) {
|
||||
dt.setNamespace(namespace);
|
||||
}
|
||||
else {
|
||||
setNamespace(dt.getNamespace(), namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -123,14 +123,14 @@ public class GnuDemangler implements Demangler {
|
||||
demangledObject.setSignature(demangled);
|
||||
}
|
||||
|
||||
demangledObject.setOriginalMangled(originalMangled);
|
||||
demangledObject.setMangledString(originalMangled);
|
||||
|
||||
if (isDwarf) {
|
||||
DemangledAddressTable dat = new DemangledAddressTable((String) null, 1);
|
||||
DemangledAddressTable dat = new DemangledAddressTable((String) null, false);
|
||||
dat.setSpecialPrefix("DWARF Debug ");
|
||||
dat.setName(demangledObject.getName());
|
||||
dat.setNamespace(demangledObject.getNamespace());
|
||||
dat.setOriginalMangled(originalMangled);
|
||||
dat.setMangledString(originalMangled);
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
+774
-234
File diff suppressed because it is too large
Load Diff
+136
-46
@@ -72,14 +72,6 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
System.out.println("Elapsed Time: " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
private void demangle(String mangled) throws IOException {
|
||||
String demangled = process.demangle(mangled);
|
||||
assertNotNull(demangled);
|
||||
assertNotEquals(mangled, demangled);
|
||||
//System.out.println(parser.parse(mangled, demangled));
|
||||
assertNotNull(parser.parse(mangled, demangled));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverloadedShiftOperatorParsingBug() {
|
||||
parser = new GnuDemanglerParser(null);
|
||||
@@ -101,7 +93,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
parse = parser.parse(null, "typeinfo name for Magick::Blob");
|
||||
assertTrue(parse instanceof DemangledString);
|
||||
assertEquals("Magick::Blob", ((DemangledString) parse).getString());
|
||||
assertName(parse, "typeinfo_name", "Magick", "Blob");
|
||||
assertName(parse, "typeinfo-name", "Magick", "Blob");
|
||||
|
||||
parse = parser.parse(null, "Bob::operator_new[](float, double, Bob::Fred &)");
|
||||
assertTrue(parse instanceof DemangledMethod);
|
||||
@@ -161,33 +153,6 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
"covariant return thunk [nv:0] [nv:16] to KHotKeys::WindowTrigger::copy(KHotKeys::ActionData*) const");
|
||||
assertTrue(parse instanceof DemangledThunk);
|
||||
assertName(parse, "copy", "KHotKeys", "WindowTrigger");
|
||||
|
||||
try {
|
||||
parse = parser.parse(
|
||||
"_ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j",
|
||||
"GrGLFunction<unsigned char const* (unsigned int)>::GrGLFunction<skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0>(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0)::{lambda(void const*, unsigned int)#1}::__invoke(void const*, unsigned int)");
|
||||
assertNull("Shouldn't have parsed", parser);
|
||||
}
|
||||
catch (Exception exc) {
|
||||
// should get an exception
|
||||
}
|
||||
}
|
||||
|
||||
private void assertName(DemangledObject demangledObj, String name, String... namespaces) {
|
||||
// String label = demangledObj.getName();
|
||||
// if (demangledObj instanceof DemangledString) {
|
||||
// label = ((DemangledString) demangledObj).getString();
|
||||
// }
|
||||
|
||||
assertEquals("Unexpected demangled name", name, demangledObj.getName());
|
||||
DemangledType namespace = demangledObj.getNamespace();
|
||||
for (int i = namespaces.length - 1; i >= 0; i--) {
|
||||
String n = namespaces[i];
|
||||
assertNotNull("Namespace mismatch", namespace);
|
||||
assertEquals(n, namespace.getName());
|
||||
namespace = namespace.getNamespace();
|
||||
}
|
||||
assertNull("Namespace mismatch", namespace);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -420,7 +385,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
DemangledVariable variable = (DemangledVariable) object;
|
||||
assertEquals("__gthread_active_ptr", variable.getName());
|
||||
assertEquals("__gthread_active_p()", variable.getNamespace().getName());
|
||||
assertEquals("__gthread_active_p()", variable.getNamespace().toNamespaceName());
|
||||
assertNull(variable.getDataType()); // no type information provided
|
||||
}
|
||||
|
||||
@@ -473,15 +438,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
//
|
||||
// The below demangles to DDDSaveOptionsCB(_WidgetRec*, void*, void*)::dialog [#1]
|
||||
//
|
||||
// from program ddd
|
||||
//
|
||||
String mangled = "_ZZ16DDDSaveOptionsCBP10_WidgetRecPvS1_E6dialog_0";
|
||||
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertTrue(object instanceof DemangledVariable);
|
||||
assertName(object, "dialog", "DDDSaveOptionsCB(_WidgetRec*,void*,void*)");
|
||||
assertName(object, "dialog", "DDDSaveOptionsCB(_WidgetRec *,void *,void *)");
|
||||
|
||||
assertEquals("DDDSaveOptionsCB(_WidgetRec *,void *,void *)::dialog",
|
||||
object.getSignature(false));
|
||||
@@ -737,6 +700,12 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
// Format: operator std::string() const { return "bob"; }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Mangled: _ZNK6Magick5ColorcvSsEv
|
||||
//
|
||||
// Demangled: Magick::Color::operator std::basic_string<char, std::char_traits<char>, std::allocator<char> >() const
|
||||
//
|
||||
|
||||
String mangled = "_ZNK6Magick5ColorcvSsEv";
|
||||
|
||||
@@ -955,7 +924,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
List<DemangledDataType> parameters = df.getParameters();
|
||||
assertEquals("Number of parameters", 1, parameters.size());
|
||||
assertEquals("Name of type parsed", "F", parameters.get(0).getName());
|
||||
assertEquals("Param Type Name parsed", "WTF::",
|
||||
assertEquals("Param Type Name parsed", "WTF",
|
||||
parameters.get(0).getNamespace().toString());
|
||||
assertEquals("Param Template was parsed",
|
||||
"<WTF::F<void (Core::FileClient &)> (Core::File &)>",
|
||||
@@ -991,7 +960,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
DemangledDataType demangParamDT = parameters.get(0);
|
||||
|
||||
assertEquals("Name of type parsed", "function", demangParamDT.getName());
|
||||
assertEquals("Param Type Name parsed", "boost::", demangParamDT.getNamespace().toString());
|
||||
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
||||
assertEquals("Param Template parsed", "<void ()>", demangParamDT.getTemplate().toString());
|
||||
assertTrue("Is referent", demangParamDT.isReference());
|
||||
|
||||
@@ -1023,7 +992,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
DemangledDataType demangParamDT = parameters.get(0);
|
||||
|
||||
assertEquals("Name of type parsed", "function", demangParamDT.getName());
|
||||
assertEquals("Param Type Name parsed", "boost::", demangParamDT.getNamespace().toString());
|
||||
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
||||
assertEquals("Param Template parsed", "<void (ares_options *,int *)>",
|
||||
demangParamDT.getTemplate().toString());
|
||||
assertTrue("Is referent", demangParamDT.isReference());
|
||||
@@ -1061,7 +1030,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
//
|
||||
// Mangled: _ZTCN6Crypto10HmacSha256E0_NS_3MacE
|
||||
//
|
||||
// Demangled:
|
||||
// Demangled: construction vtable for Crypto::Mac-in-Crypto::HmacSha256
|
||||
//
|
||||
|
||||
String mangled = "_ZTCN6Crypto10HmacSha256E0_NS_3MacE";
|
||||
|
||||
@@ -1081,6 +1051,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
// Mangled: _Z11testVarArgsiz
|
||||
//
|
||||
// Demangled: testVarArgs(int, ...)
|
||||
//
|
||||
|
||||
String mangled = "_Z11testVarArgsiz";
|
||||
|
||||
@@ -1134,13 +1105,110 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertNull(res);
|
||||
}
|
||||
|
||||
// @Test TODO upcoming fix for GT-3545
|
||||
@Test
|
||||
public void testStructureConstructorWithinTemplatedFunction() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: _ZZN9__gnu_cxx6__stoaIlicJiEEET0_PFT_PKT1_PPS3_DpT2_EPKcS5_PmS9_EN11_Save_errnoC2Ev
|
||||
//
|
||||
// Demangled: __gnu_cxx
|
||||
// ::
|
||||
// __stoa<long, int, char, int>(long (*)(char const*, char**, int), char const*, char const*, unsigned long*, int)
|
||||
// ::
|
||||
// _Save_errno
|
||||
// ::
|
||||
// _Save_errno()
|
||||
//
|
||||
// This is _Save_errno struct's constructor inside of the stoa templated function, in the
|
||||
// __gnu_cxx namespace.
|
||||
//
|
||||
|
||||
String mangled =
|
||||
"_ZZN9__gnu_cxx6__stoaIlicJiEEET0_PFT_PKT1_PPS3_DpT2_EPKcS5_PmS9_EN11_Save_errnoC2Ev";
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertNotNull(object);
|
||||
assertTrue("Expected a Demangled Function: " + object, object instanceof DemangledFunction);
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"undefined __gnu_cxx" +
|
||||
"::" +
|
||||
"__stoa<long,int,char,int>(long(*)(char_const*,char**,int),char_const*,char_const*,unsigned_long*,int)" +
|
||||
"::" +
|
||||
"_Save_errno::_Save_errno(void)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperatorTODO() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: _ZNK2cc14ScrollSnapTypeneERKS0_
|
||||
//
|
||||
// Demangled: cc::ScrollSnapType::operator!=(cc::ScrollSnapType const&) const
|
||||
//
|
||||
|
||||
String mangled = "_ZNK2cc14ScrollSnapTypeneERKS0_";
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertNotNull(object);
|
||||
assertTrue(object instanceof DemangledFunction);
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals("undefined cc::ScrollSnapType::operator!=(cc::ScrollSnapType const &)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionInLambdaNamespace() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: _ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j
|
||||
//
|
||||
// Demangled: GrGLFunction<unsigned char const* (unsigned int)>
|
||||
// ::
|
||||
// GrGLFunction<skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0>(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0)
|
||||
// ::
|
||||
// {lambda(void const*, unsigned int)#1}
|
||||
// ::
|
||||
// __invoke(void const*, unsigned int)
|
||||
//
|
||||
|
||||
DemangledObject object = parser.parse(
|
||||
"_ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j",
|
||||
"GrGLFunction<unsigned char const* (unsigned int)>::GrGLFunction<skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0>(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0)::{lambda(void const*, unsigned int)#1}::__invoke(void const*, unsigned int)");
|
||||
assertNotNull(object);
|
||||
assertTrue(object instanceof DemangledFunction);
|
||||
|
||||
assertName(object, "__invoke",
|
||||
"GrGLFunction<unsigned_char_const*(unsigned_int)>",
|
||||
"GrGLFunction<skia_bindings--CreateGLES2InterfaceBindings(gpu--gles2--GLES2Interface*,gpu--ContextSupport*)--$_0>(skia_bindings--CreateGLES2InterfaceBindings(gpu--gles2--GLES2Interface*,gpu--ContextSupport*)--$_0)",
|
||||
"{lambda(void_const*,unsigned_int)#1}");
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"undefined GrGLFunction<unsigned_char_const*(unsigned_int)>::GrGLFunction<skia_bindings--CreateGLES2InterfaceBindings(gpu--gles2--GLES2Interface*,gpu--ContextSupport*)--$_0>(skia_bindings--CreateGLES2InterfaceBindings(gpu--gles2--GLES2Interface*,gpu--ContextSupport*)--$_0)::{lambda(void_const*,unsigned_int)#1}::__invoke(void const *,unsigned int)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionWithLambda_WrappingAnotherFunctionCall() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: _Z11wrap_360_cdIiEDTcl8wrap_360fp_Lf42c80000EEET_
|
||||
//
|
||||
// Demangled: (wrap_360({parm#1}, (float)[42c80000])) wrap_360_cd<int>(int)
|
||||
// Demangled: decltype (wrap_360({parm#1}, (float)[42c80000])) wrap_360_cd<int>(int)
|
||||
//
|
||||
// 'wrap_360_cd<int>(int)' is a function that takes an int and then passes that int along
|
||||
// with a constant value to 'wrap_360<int>' by using a lambda function. It looks like
|
||||
// this:
|
||||
// auto wrap_360_cd<int>(int a) -> decltype(wrap_360(angle, 100.f))
|
||||
//
|
||||
// where the function is declared with this syntax:
|
||||
// auto identifier ( argument-declarations... ) -> return_type
|
||||
//
|
||||
|
||||
String mangled = "_Z11wrap_360_cdIiEDTcl8wrap_360fp_Lf42c80000EEET_";
|
||||
@@ -1150,8 +1218,30 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertNotNull(object);
|
||||
assertTrue(object instanceof DemangledFunction);
|
||||
|
||||
// TODO
|
||||
// TODO maybe put full output in setUtilDemangled()
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals("undefined wrap_360_cd<int>(int)", signature);
|
||||
}
|
||||
|
||||
private void assertName(DemangledObject demangledObj, String name, String... namespaces) {
|
||||
|
||||
assertEquals("Unexpected demangled name", name, demangledObj.getName());
|
||||
Demangled namespace = demangledObj.getNamespace();
|
||||
for (int i = namespaces.length - 1; i >= 0; i--) {
|
||||
String n = namespaces[i];
|
||||
assertNotNull("Namespace mismatch", namespace);
|
||||
assertEquals(n, namespace.toNamespaceName());
|
||||
namespace = namespace.getNamespace();
|
||||
}
|
||||
assertNull("Namespace mismatch", namespace);
|
||||
}
|
||||
|
||||
private void demangle(String mangled) throws IOException {
|
||||
String demangled = process.demangle(mangled);
|
||||
assertNotNull(demangled);
|
||||
assertNotEquals(mangled, demangled);
|
||||
assertNotNull(parser.parse(mangled, demangled));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class MDMangGhidra extends MDMang {
|
||||
qual = it.next();
|
||||
DemangledType newType = new DemangledType(qual.toString());
|
||||
if (qual.isNested()) {
|
||||
newType.setOriginalMangled(qual.getNested().getMangled());
|
||||
newType.setMangledString(qual.getNested().getMangled());
|
||||
}
|
||||
parentType.setNamespace(newType);
|
||||
parentType = newType;
|
||||
@@ -86,7 +86,7 @@ public class MDMangGhidra extends MDMang {
|
||||
MDParsableItem returnedItem = super.demangle(mangledArg, true);
|
||||
objectResult = processItem();
|
||||
if (objectResult != null) {
|
||||
objectResult.setOriginalMangled(mangledArg);
|
||||
objectResult.setMangledString(mangledArg);
|
||||
// Make our version of the demangled string available (could be large).
|
||||
objectResult.setUtilDemangled(item.toString());
|
||||
}
|
||||
@@ -805,4 +805,3 @@ public class MDMangGhidra extends MDMang {
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package mdemangler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class MDMangExtraTests extends AbstractGenericTest {
|
||||
String demangled = item.toString();
|
||||
assertEquals(wholeTruth, demangled);
|
||||
DemangledObject obj = demangler.getObject();
|
||||
String mangledFunctionNamespace = obj.getNamespace().getNamespace().getOriginalMangled();
|
||||
String mangledFunctionNamespace = obj.getNamespace().getNamespace().getMangledString();
|
||||
assertEquals(functionNamespaceMangledTruth, mangledFunctionNamespace);
|
||||
|
||||
item = demangler.demangle(mangledFunctionNamespace, true);
|
||||
|
||||
Reference in New Issue
Block a user