mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-24 13:11:47 +00:00
Merge remote-tracking branch 'origin/GP-5101_ghizard_MDMang_vxts_with_anon_ns--SQUASHED'
This commit is contained in:
commit
404fbdb7dc
@ -66,7 +66,13 @@ public class MicrosoftDemangler implements Demangler {
|
||||
demangler.setIsFunction(mContext.shouldInterpretAsFunction());
|
||||
try {
|
||||
item = demangler.demangle();
|
||||
object = MicrosoftDemanglerUtil.convertToDemangledObject(item, mangled);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
String originalDemangled = item.toString();
|
||||
demangler.getOutputOptions().setUseEncodedAnonymousNamespace(true);
|
||||
object =
|
||||
MicrosoftDemanglerUtil.convertToDemangledObject(item, mangled, originalDemangled);
|
||||
if (object != null) {
|
||||
object.setMangledContext(context);
|
||||
}
|
||||
@ -103,7 +109,13 @@ public class MicrosoftDemangler implements Demangler {
|
||||
demangler.setIsFunction(mContext.shouldInterpretAsFunction());
|
||||
try {
|
||||
mdType = demangler.demangleType();
|
||||
dataType = MicrosoftDemanglerUtil.convertToDemangledDataType(mdType, mangled);
|
||||
if (mdType == null) {
|
||||
return null;
|
||||
}
|
||||
String originalDemangled = item.toString();
|
||||
demangler.getOutputOptions().setUseEncodedAnonymousNamespace(true);
|
||||
dataType = MicrosoftDemanglerUtil.convertToDemangledDataType(mdType, mangled,
|
||||
originalDemangled);
|
||||
if (dataType != null) {
|
||||
dataType.setMangledContext(context);
|
||||
}
|
||||
|
@ -50,22 +50,27 @@ public class MicrosoftDemanglerUtil {
|
||||
* is not appropriate for {@link MDDataType} and some other types of {@link MDParsableItem}
|
||||
* @param item the item to convert
|
||||
* @param mangled the original mangled string
|
||||
* @param originalDemangled the original demangled string
|
||||
* @return the {@link DemangledObject} result
|
||||
* @throws DemangledException up issue converting to a {@link DemangledObject}
|
||||
*/
|
||||
static DemangledObject convertToDemangledObject(MDParsableItem item, String mangled)
|
||||
static DemangledObject convertToDemangledObject(MDParsableItem item, String mangled,
|
||||
String originalDemangled)
|
||||
throws DemangledException {
|
||||
return processItem(item, mangled, item.toString());
|
||||
return processItem(item, mangled, originalDemangled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to convert an {@link MDDataType} into a {@link DemangledDataType}
|
||||
* Method to convert an {@link MDDataType} into a {@link DemangledDataType}. Demangler
|
||||
* needs to have already run to process the type before calling this method
|
||||
* @param type the type to convert
|
||||
* @param mangled the original mangled string
|
||||
* @param mangled the mangled string
|
||||
* @param originalDemangled the original demangled string
|
||||
* @return the result
|
||||
*/
|
||||
static DemangledDataType convertToDemangledDataType(MDDataType type, String mangled) {
|
||||
return processDataType(null, type, mangled, type.toString());
|
||||
static DemangledDataType convertToDemangledDataType(MDDataType type, String mangled,
|
||||
String originalDemangled) {
|
||||
return processDataType(null, type, mangled, originalDemangled);
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
@ -121,14 +126,8 @@ public class MicrosoftDemanglerUtil {
|
||||
}
|
||||
}
|
||||
else if (qual.isAnon()) {
|
||||
// Instead of using the standard qual.toString() method, which returns
|
||||
// "`anonymous namespace'" for anonymous qualifiers, we use qual.getAnonymousName()
|
||||
// which will have the underlying anonymous name of the form "A0xfedcba98" to create
|
||||
// a standardized anonymous name that is distinguishable from other anonymous names.
|
||||
// The standardized name comes from createStandardAnonymousNamespaceNode(). This
|
||||
// is especially important when there are sibling anonymous names.
|
||||
String anon = MDMangUtils.createStandardAnonymousNamespaceNode(qual.getAnonymousName());
|
||||
demangled = new DemangledNamespaceNode(mangled, qual.toString(), anon);
|
||||
String orig = qual.getAnonymousName();
|
||||
demangled = new DemangledNamespaceNode(mangled, orig, qual.toString());
|
||||
}
|
||||
else if (qual.isInterface()) {
|
||||
// TODO: need to do better; setting namespace for now
|
||||
|
@ -178,6 +178,29 @@ public class MicrosoftDemanglerExtraTest extends AbstractGenericTest {
|
||||
|
||||
//==============================================================================================
|
||||
|
||||
@Test
|
||||
public void testVxTableAnonymousNsInOwnerAndBackref() throws Exception {
|
||||
String mangled = "??_7a@?A0xfedcba98@b@@6B012@01@@";
|
||||
String mTruth =
|
||||
"const b::`anonymous namespace'::a::`vftable'{for `b::A0xfedcba98::a's `A0xfedcba98::a'}";
|
||||
String gTruth =
|
||||
"const b::_anon_FEDCBA98::a::`vftable'{for `b::_anon_FEDCBA98::a's `_anon_FEDCBA98::a'}";
|
||||
|
||||
MicrosoftDemangler demangler = new MicrosoftDemangler();
|
||||
|
||||
MicrosoftMangledContext context =
|
||||
demangler.createMangledContext(mangled, null, program32, address32);
|
||||
DemangledObject obj = demangler.demangle(context);
|
||||
|
||||
String originalDemangled = obj.getOriginalDemangled();
|
||||
assertEquals(mTruth, originalDemangled);
|
||||
|
||||
String demangled = demangler.getMdItem().toString();
|
||||
assertEquals(gTruth, demangled);
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
|
||||
@Test
|
||||
//This test checks that we can provide a mangled string for a function namespace.
|
||||
// The return String from getOriginalMangled() is not null only for this special
|
||||
|
@ -40,6 +40,8 @@ import mdemangler.template.MDTemplateArgumentsList;
|
||||
public class MDMang {
|
||||
public static final char DONE = MDCharacterIterator.DONE;
|
||||
|
||||
private MDOutputOptions outputOptions = new MDOutputOptions();
|
||||
|
||||
protected int architectureSize = 32;
|
||||
protected boolean isFunction = false;
|
||||
|
||||
@ -110,7 +112,13 @@ public class MDMang {
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Control
|
||||
// Output Options
|
||||
public MDOutputOptions getOutputOptions() {
|
||||
return outputOptions;
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Demangling options
|
||||
|
||||
/**
|
||||
* Controls whether an exception is thrown if there are remaining characters after demangling.
|
||||
|
@ -0,0 +1,51 @@
|
||||
/* ###
|
||||
* 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 mdemangler;
|
||||
|
||||
/**
|
||||
* Options for controlling demangler output. Quick stub for now. Full implementation was planned
|
||||
* for another ticket
|
||||
*/
|
||||
public class MDOutputOptions {
|
||||
|
||||
private boolean useEncodedAnonymousNamespaceNumber;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MDOutputOptions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the option for whether to use or not use the numerical encoding to craft a
|
||||
* unique anonymous namespace. The default {@code false} is to produce the normal anonymous
|
||||
* namespace string produced by Microsoft's {@code undname}
|
||||
* @param useEncodedNumber {@code true} to produce a namespace that uses the encoded number
|
||||
*/
|
||||
public void setUseEncodedAnonymousNamespace(boolean useEncodedNumber) {
|
||||
this.useEncodedAnonymousNamespaceNumber = useEncodedNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the demangler will use the encoded number in creating the
|
||||
* anonymous namespace component
|
||||
* @return {@code true} if the flag is set
|
||||
*/
|
||||
public boolean useEncodedAnonymousNamespace() {
|
||||
return useEncodedAnonymousNamespaceNumber;
|
||||
}
|
||||
|
||||
}
|
@ -30,13 +30,13 @@ public class MDBasicName extends MDParsableItem {
|
||||
MDReusableName reusableName;
|
||||
MDObjectCPP embeddedObject;
|
||||
MDQualification embeddedObjectQualification;
|
||||
String nameModifier;
|
||||
MDNameModifier nameModifier;
|
||||
|
||||
public MDBasicName(MDMang dmang) {
|
||||
super(dmang);
|
||||
}
|
||||
|
||||
public void setNameModifier(String nameModifier) {
|
||||
public void setNameModifier(MDNameModifier nameModifier) {
|
||||
this.nameModifier = nameModifier;
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ public class MDBasicName extends MDParsableItem {
|
||||
templateNameAndArguments.insert(builder);
|
||||
}
|
||||
if (nameModifier != null) {
|
||||
builder.append(nameModifier);
|
||||
builder.append(nameModifier.getModifier());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,13 @@ public class MDFragmentName extends MDParsableItem {
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
if (dmang.getOutputOptions().useEncodedAnonymousNamespace()) {
|
||||
dmang.insertString(builder, MDMangUtils.createStandardAnonymousNamespaceNode(name));
|
||||
}
|
||||
else {
|
||||
dmang.insertString(builder, name);
|
||||
}
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
|
@ -0,0 +1,29 @@
|
||||
/* ###
|
||||
* 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 mdemangler.naming;
|
||||
|
||||
/**
|
||||
* This interface is for items that provide a name modifier
|
||||
*/
|
||||
public interface MDNameModifier {
|
||||
|
||||
/**
|
||||
* Returns the modifier string for the name
|
||||
* @return the modifier
|
||||
*/
|
||||
public String getModifier();
|
||||
|
||||
}
|
@ -93,7 +93,7 @@ public class MDQualifiedBasicName extends MDParsableItem {
|
||||
return qualification;
|
||||
}
|
||||
|
||||
public void setNameModifier(String nameModifier) {
|
||||
public void setNameModifier(MDNameModifier nameModifier) {
|
||||
basicName.setNameModifier(nameModifier);
|
||||
}
|
||||
|
||||
|
@ -91,8 +91,14 @@ public class MDQualifier extends MDParsableItem {
|
||||
name.insert(builder);
|
||||
}
|
||||
else if (nameAnonymous != null) {
|
||||
if (dmang.getOutputOptions().useEncodedAnonymousNamespace()) {
|
||||
dmang.insertString(builder,
|
||||
MDMangUtils.createStandardAnonymousNamespaceNode(nameAnonymous.getName()));
|
||||
}
|
||||
else {
|
||||
dmang.insertString(builder, ANONYMOUS_NAMESPACE);
|
||||
}
|
||||
}
|
||||
else if (nameInterface != null) {
|
||||
nameInterface.insert(builder);
|
||||
}
|
||||
|
@ -148,9 +148,7 @@ public class MDObjectCPP extends MDObject {
|
||||
typeInfo.setTypeCast();
|
||||
}
|
||||
typeInfo.parse();
|
||||
if (!typeInfo.getNameModifier().isEmpty()) {
|
||||
qualifiedName.setNameModifier(typeInfo.getNameModifier());
|
||||
}
|
||||
qualifiedName.setNameModifier(typeInfo);
|
||||
if (qualifiedName.isTypeCast()) {
|
||||
applyFunctionReturnTypeToTypeCastOperatorName();
|
||||
}
|
||||
|
@ -23,11 +23,19 @@ import mdemangler.*;
|
||||
*/
|
||||
public class MDGuard extends MDTypeInfo {
|
||||
|
||||
private MDEncodedNumber guardNumber;
|
||||
|
||||
public MDGuard(MDMang dmang) {
|
||||
super(dmang);
|
||||
guardNumber = new MDEncodedNumber(dmang);
|
||||
mdtype = new MDType(dmang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
return "{" + guardNumber + "}'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
super.insert(builder);
|
||||
@ -35,9 +43,7 @@ public class MDGuard extends MDTypeInfo {
|
||||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
MDEncodedNumber guardNumber = new MDEncodedNumber(dmang);
|
||||
guardNumber.parse();
|
||||
nameModifier = "{" + guardNumber + "}'";
|
||||
super.parseInternal();
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,12 @@
|
||||
package mdemangler.typeinfo;
|
||||
|
||||
import mdemangler.*;
|
||||
import mdemangler.naming.MDNameModifier;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MDTypeInfo extends MDParsableItem {
|
||||
public class MDTypeInfo extends MDParsableItem implements MDNameModifier {
|
||||
private static final String PRIVATE = "private: ";
|
||||
private static final String PROTECTED = "protected: ";
|
||||
private static final String PUBLIC = "public: ";
|
||||
@ -61,14 +62,13 @@ public class MDTypeInfo extends MDParsableItem {
|
||||
protected MDType mdtype;
|
||||
protected boolean isTypeCast;
|
||||
|
||||
protected String nameModifier = "";
|
||||
|
||||
public MDTypeInfo(MDMang dmang) {
|
||||
super(dmang, 1);
|
||||
}
|
||||
|
||||
public String getNameModifier() {
|
||||
return nameModifier;
|
||||
@Override
|
||||
public String getModifier() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setPrivate() {
|
||||
|
@ -57,6 +57,12 @@ public class MDVCall extends MDMemberFunctionInfo {
|
||||
callIndex = new MDEncodedNumber(dmang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
// TODO: Future specialization on 16-bit or 32plus
|
||||
return getNameModifier_32PlusBitModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
// TODO: Future specialization on 16-bit or 32plus
|
||||
@ -197,8 +203,6 @@ public class MDVCall extends MDMemberFunctionInfo {
|
||||
}
|
||||
// TODO evaluate whether parseInternal() or parse.
|
||||
super.parseInternal();
|
||||
// TODO: Future specialization on 16-bit or 32plus
|
||||
nameModifier = getNameModifier_32PlusBitModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,21 +24,27 @@ import mdemangler.functiontype.MDFunctionType;
|
||||
*/
|
||||
public class MDVFAdjustor extends MDMemberFunctionInfo {
|
||||
|
||||
private MDEncodedNumber adjustment;
|
||||
|
||||
// Comment from wiki page: This kind of thunk (G,H,O,P,W,X) function is always virtual, and
|
||||
// used to represent the logical "this" adjustor property, which means an offset to the
|
||||
// true "this" value in some multiple inheritance situations.
|
||||
public MDVFAdjustor(MDMang dmang) {
|
||||
super(dmang);
|
||||
mdtype = new MDFunctionType(dmang);
|
||||
adjustment = new MDEncodedNumber(dmang);
|
||||
setVirtual();
|
||||
setThunk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
return "`adjustor{" + adjustment + "}' ";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
MDEncodedNumber adjustment = new MDEncodedNumber(dmang);
|
||||
adjustment.parse();
|
||||
nameModifier = "`adjustor{" + adjustment + "}' ";
|
||||
super.parseInternal(); // TODO evaluate whether parseInternal() or parse.
|
||||
}
|
||||
}
|
||||
|
@ -24,22 +24,31 @@ import mdemangler.functiontype.MDFunctionType;
|
||||
*/
|
||||
public class MDVtordisp extends MDMemberFunctionInfo {
|
||||
|
||||
// 20200507: Believe this to be <offset-to-vtordisp>
|
||||
private MDEncodedNumber vtorDisplacement;
|
||||
// 20200507: Believe this to be <static-offset>
|
||||
private MDEncodedNumber adjustment;
|
||||
|
||||
public MDVtordisp(MDMang dmang) {
|
||||
super(dmang);
|
||||
mdtype = new MDFunctionType(dmang);
|
||||
vtorDisplacement = new MDEncodedNumber(dmang);
|
||||
adjustment = new MDEncodedNumber(dmang);
|
||||
setVirtual();
|
||||
setThunk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
return "`vtordisp{" + vtorDisplacement + "," + adjustment + "}' ";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
// 20200507: Believe this to be <offset-to-vtordisp>
|
||||
MDEncodedNumber vtorDisplacement = new MDEncodedNumber(dmang);
|
||||
vtorDisplacement.parse();
|
||||
// 20200507: Believe this to be <static-offset>
|
||||
MDEncodedNumber adjustment = new MDEncodedNumber(dmang);
|
||||
adjustment.parse();
|
||||
nameModifier = "`vtordisp{" + vtorDisplacement + "," + adjustment + "}' ";
|
||||
super.parseInternal();
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,15 @@ import mdemangler.functiontype.MDFunctionType;
|
||||
*/
|
||||
public class MDVtordispex extends MDMemberFunctionInfo {
|
||||
|
||||
// 20200507: Believe this to be <offset-to-vptr>
|
||||
private MDEncodedNumber a = new MDEncodedNumber(dmang);
|
||||
// 20200507: Believe this to be <vbase-offset-offset>
|
||||
private MDEncodedNumber b = new MDEncodedNumber(dmang);
|
||||
// 20200507: Believe this to be <offset-to-vtordisp>
|
||||
private MDEncodedNumber c = new MDEncodedNumber(dmang);
|
||||
// 20200507: Believe this to be <static-offset>
|
||||
private MDEncodedNumber d = new MDEncodedNumber(dmang);
|
||||
|
||||
public MDVtordispex(MDMang dmang) {
|
||||
super(dmang);
|
||||
mdtype = new MDFunctionType(dmang);
|
||||
@ -31,21 +40,21 @@ public class MDVtordispex extends MDMemberFunctionInfo {
|
||||
setThunk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
return "`vtordispex{" + a + "," + b + "," + c + "," + d + "}' ";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
// 20200507: Believe this to be <offset-to-vptr>
|
||||
MDEncodedNumber a = new MDEncodedNumber(dmang);
|
||||
a.parse();
|
||||
// 20200507: Believe this to be <vbase-offset-offset>
|
||||
MDEncodedNumber b = new MDEncodedNumber(dmang);
|
||||
b.parse();
|
||||
// 20200507: Believe this to be <offset-to-vtordisp>
|
||||
MDEncodedNumber c = new MDEncodedNumber(dmang);
|
||||
c.parse();
|
||||
// 20200507: Believe this to be <static-offset>
|
||||
MDEncodedNumber d = new MDEncodedNumber(dmang);
|
||||
d.parse();
|
||||
nameModifier = "`vtordispex{" + a + "," + b + "," + c + "," + d + "}' ";
|
||||
super.parseInternal();
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,11 @@ public class MDVxTable extends MDTypeInfo {
|
||||
goodNestedTermination = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
return generateNameModifier();
|
||||
}
|
||||
|
||||
public MDCVMod getCVMod() {
|
||||
return cvmod;
|
||||
}
|
||||
@ -94,10 +99,9 @@ public class MDVxTable extends MDTypeInfo {
|
||||
dmang.increment();
|
||||
goodNestedTermination = true;
|
||||
}
|
||||
nameModifier = generateNameModifier();
|
||||
}
|
||||
|
||||
String generateNameModifier() {
|
||||
private String generateNameModifier() {
|
||||
if (!goodNestedTermination) {
|
||||
return "{for ??}";
|
||||
}
|
||||
|
@ -4664,6 +4664,25 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
// vbtable with anonymous namespace
|
||||
@Test
|
||||
public void testUnderscore7AnonNs() throws Exception {
|
||||
mangled = "??_7a@?A0xfedcba98@b@@6B@";
|
||||
msTruth = "const b::`anonymous namespace'::a::`vftable'";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
// vbtable with anonymous namespace
|
||||
@Test
|
||||
public void testUnderscore7AnonNsAndBackref() throws Exception {
|
||||
mangled = "??_7a@?A0xfedcba98@b@@6B012@01@@";
|
||||
msTruth =
|
||||
"const b::`anonymous namespace'::a::`vftable'{for `b::A0xfedcba98::a's `A0xfedcba98::a'}";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialNames_R() throws Exception {
|
||||
mangled = "??_R0X@8";
|
||||
|
@ -78,6 +78,64 @@ public class MDMangExtraTest extends AbstractGenericTest {
|
||||
assertEquals("b::a", qualifications.get(0).toString());
|
||||
}
|
||||
|
||||
// Anonymous namespace in owner and backref
|
||||
@Test
|
||||
public void testVxTableAnonymousNsInOwner() throws Exception {
|
||||
String mangled = "??_7a@?A0xfedcba98@b@@6B@";
|
||||
String truth = "const b::`anonymous namespace'::a::`vftable'";
|
||||
String truth2 = "const b::_anon_FEDCBA98::a::`vftable'";
|
||||
|
||||
MDMangGhidra demangler = new MDMangGhidra();
|
||||
demangler.setMangledSymbol(mangled);
|
||||
demangler.setErrorOnRemainingChars(true);
|
||||
demangler.setDemangleOnlyKnownPatterns(true);
|
||||
MDParsableItem item = demangler.demangle();
|
||||
|
||||
MDObjectCPP cppItem = (MDObjectCPP) item;
|
||||
MDVxTable vxTable = (MDVxTable) cppItem.getTypeInfo();
|
||||
List<MDQualification> qualifications = vxTable.getNestedQualifications();
|
||||
assertEquals(0, qualifications.size());
|
||||
|
||||
String demangled = item.toString();
|
||||
assertEquals(truth, demangled);
|
||||
|
||||
demangler.getOutputOptions().setUseEncodedAnonymousNamespace(true);
|
||||
demangled = item.toString();
|
||||
assertEquals(truth2, demangled);
|
||||
}
|
||||
|
||||
// Anonymous namespace in owner and backref
|
||||
@Test
|
||||
public void testVxTableAnonymousNsInOwnerAndBackref() throws Exception {
|
||||
String mangled = "??_7a@?A0xfedcba98@b@@6B012@01@@";
|
||||
String truth =
|
||||
"const b::`anonymous namespace'::a::`vftable'{for `b::A0xfedcba98::a's `A0xfedcba98::a'}";
|
||||
String truth2 =
|
||||
"const b::_anon_FEDCBA98::a::`vftable'{for `b::_anon_FEDCBA98::a's `_anon_FEDCBA98::a'}";
|
||||
|
||||
MDMangGhidra demangler = new MDMangGhidra();
|
||||
demangler.setMangledSymbol(mangled);
|
||||
demangler.setErrorOnRemainingChars(true);
|
||||
demangler.setDemangleOnlyKnownPatterns(true);
|
||||
MDParsableItem item = demangler.demangle();
|
||||
|
||||
MDObjectCPP cppItem = (MDObjectCPP) item;
|
||||
MDVxTable vxTable = (MDVxTable) cppItem.getTypeInfo();
|
||||
List<MDQualification> qualifications = vxTable.getNestedQualifications();
|
||||
assertEquals(2, qualifications.size());
|
||||
|
||||
String demangled = item.toString();
|
||||
assertEquals(truth, demangled);
|
||||
assertEquals("b::A0xfedcba98::a", qualifications.get(0).toString());
|
||||
assertEquals("A0xfedcba98::a", qualifications.get(1).toString());
|
||||
|
||||
demangler.getOutputOptions().setUseEncodedAnonymousNamespace(true);
|
||||
demangled = item.toString();
|
||||
assertEquals(truth2, demangled);
|
||||
assertEquals("b::_anon_FEDCBA98::a", qualifications.get(0).toString());
|
||||
assertEquals("_anon_FEDCBA98::a", qualifications.get(1).toString());
|
||||
}
|
||||
|
||||
// Need to test the demangleType() method to make sure it does the retry with LLVM mode
|
||||
@Test
|
||||
public void testDemangleTypeWithRetry() throws Exception {
|
||||
|
Loading…
Reference in New Issue
Block a user