mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/GP-1725_ghizard_Add_second_pass_MDMang_processing_for_nonstandard_mangled_forms--SQUASHED'
This commit is contained in:
commit
e59d58e7fe
15 changed files with 312 additions and 41 deletions
|
@ -100,7 +100,8 @@ public class MDEncodedNumber extends MDParsableItem {
|
|||
}
|
||||
}
|
||||
else {
|
||||
throw new MDException("Illegal character in MDEncodedNumber: " + dmang.peek());
|
||||
throw new MDException("Illegal character at index " + dmang.getIndex() +
|
||||
" in MDEncodedNumber: " + dmang.peek());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,30 @@ public class MDMang {
|
|||
|
||||
protected List<MDContext> contextStack = new ArrayList<>();
|
||||
|
||||
public enum ProcessingMode {
|
||||
DEFAULT_STANDARD, LLVM
|
||||
}
|
||||
|
||||
private ProcessingMode processingMode = ProcessingMode.DEFAULT_STANDARD;
|
||||
|
||||
public void setProcessingMode(ProcessingMode processingMode) {
|
||||
this.processingMode = processingMode;
|
||||
}
|
||||
|
||||
public ProcessingMode getProcessingMode() {
|
||||
return processingMode;
|
||||
}
|
||||
|
||||
public boolean isProcessingModeActive(ProcessingMode mode) {
|
||||
switch (mode) {
|
||||
case LLVM:
|
||||
return processingMode == mode && (getIndex() == 0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return processingMode == mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Demangles the string passed in.
|
||||
*
|
||||
|
@ -69,14 +93,15 @@ public class MDMang {
|
|||
* @param errorOnRemainingChars
|
||||
* boolean flag indicating whether remaining characters causes an
|
||||
* error.
|
||||
* @return item detected and parsed
|
||||
* @throws MDException upon error parsing item
|
||||
*/
|
||||
public MDParsableItem demangle(boolean errorOnRemainingChars) throws MDException {
|
||||
if (mangled == null) {
|
||||
throw new MDException("MDMang: Mangled string is null.");
|
||||
}
|
||||
pushContext();
|
||||
item = MDMangObjectParser.parse(this);
|
||||
item.parse();
|
||||
item = MDMangObjectParser.determineItemAndParse(this);
|
||||
if (item instanceof MDObjectCPP) {
|
||||
// MDMANG SPECIALIZATION USED.
|
||||
item = getEmbeddedObject((MDObjectCPP) item);
|
||||
|
@ -163,13 +188,21 @@ public class MDMang {
|
|||
|
||||
/**
|
||||
* Returns the current index.
|
||||
*
|
||||
* @return the current index.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return iter.getIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current index.
|
||||
* @param index the position to set.
|
||||
* @throws IllegalArgumentException if index is not in range from 0 to string.length()-1
|
||||
*/
|
||||
public void setIndex(int index) {
|
||||
iter.setIndex(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next character without incrementing the current index.
|
||||
*
|
||||
|
|
|
@ -64,11 +64,7 @@ public class MDMangGenericize extends MDMang {
|
|||
throw new MDException("MDMang: Mangled string is null.");
|
||||
}
|
||||
pushContext();
|
||||
item = MDMangObjectParser.parse(this);
|
||||
if (item != null) {
|
||||
item.parse();
|
||||
}
|
||||
int numCharsRemaining = getNumCharsRemaining();
|
||||
item = MDMangObjectParser.determineItemAndParse(this);
|
||||
appendRemainder();
|
||||
popContext();
|
||||
// if (errorOnRemainingChars && (numCharsRemaining > 0)) {
|
||||
|
@ -108,7 +104,7 @@ public class MDMangGenericize extends MDMang {
|
|||
* genericizedString. Suggested use is to use peek() and next() when not
|
||||
* wanting to add the character, but to use getAndIncrement() when wanting
|
||||
* to add the character.
|
||||
*
|
||||
*
|
||||
* @return the character at the new position or DONE
|
||||
*/
|
||||
@Override
|
||||
|
@ -121,7 +117,7 @@ public class MDMangGenericize extends MDMang {
|
|||
* by one. If the resulting index is greater or equal to the end index, the
|
||||
* current index is reset to the end index and a value of DONE is returned.
|
||||
* Also adds the character to the genericizedString.
|
||||
*
|
||||
*
|
||||
* @return the character at the new position or DONE
|
||||
*/
|
||||
@Override
|
||||
|
@ -145,7 +141,7 @@ public class MDMangGenericize extends MDMang {
|
|||
* Increments the index by count. Does no testing for whether the index
|
||||
* surpasses the length of the string. Also does internal processing
|
||||
* for creating a genericized String.
|
||||
*
|
||||
*
|
||||
* @param count
|
||||
* number of characters to move ahead
|
||||
*/
|
||||
|
|
|
@ -17,6 +17,7 @@ package mdemangler.naming;
|
|||
|
||||
import ghidra.util.Msg;
|
||||
import mdemangler.*;
|
||||
import mdemangler.MDMang.ProcessingMode;
|
||||
import mdemangler.object.MDObjectCPP;
|
||||
import mdemangler.template.MDTemplateNameAndArguments;
|
||||
|
||||
|
@ -172,7 +173,11 @@ public class MDBasicName extends MDParsableItem {
|
|||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
// First pass can only have name fragment of special name
|
||||
if (dmang.peek() == '?') {
|
||||
if (dmang.isProcessingModeActive(ProcessingMode.LLVM)) {
|
||||
specialName = new MDSpecialName(dmang, 0);
|
||||
specialName.parse();
|
||||
}
|
||||
else if (dmang.peek() == '?') {
|
||||
if (dmang.peek(1) == '$') {
|
||||
templateNameAndArguments = new MDTemplateNameAndArguments(dmang);
|
||||
templateNameAndArguments.parse();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package mdemangler.naming;
|
||||
|
||||
import mdemangler.*;
|
||||
import mdemangler.MDMang.ProcessingMode;
|
||||
import mdemangler.datatype.MDDataTypeParser;
|
||||
import mdemangler.object.MDObjectCPP;
|
||||
|
||||
|
@ -117,6 +118,15 @@ public class MDSpecialName extends MDParsableItem {
|
|||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
if (dmang.isProcessingModeActive(ProcessingMode.LLVM)) {
|
||||
parseLLVM();
|
||||
}
|
||||
else {
|
||||
parseDefaultStandard();
|
||||
}
|
||||
}
|
||||
|
||||
protected void parseDefaultStandard() throws MDException {
|
||||
isQualified = true;
|
||||
switch (dmang.getAndIncrement()) {
|
||||
case '0':
|
||||
|
@ -650,7 +660,7 @@ public class MDSpecialName extends MDParsableItem {
|
|||
dmang.parseInfoPop();
|
||||
break;
|
||||
case 'J':
|
||||
dmang.parseInfoPush(3, "thread guard");
|
||||
dmang.parseInfoPush(3, "local static thread guard");
|
||||
name = "`local static thread guard'";
|
||||
dmang.parseInfoPop();
|
||||
break;
|
||||
|
@ -688,6 +698,69 @@ public class MDSpecialName extends MDParsableItem {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Seemingly LLVM-specific. Breaks the "norm" of MSFT model we have been following.
|
||||
// The output format is our creation (trying to follow MSFT convention).
|
||||
// The "?$" prefix on these are templates in MSFT's reserved space and could collide
|
||||
// the a template symbol under the MSFT scheme. Maybe LLVM will eventually fix these???
|
||||
// I could be wrong in that MSFT also honors this scheme, but it seems whacked in that it
|
||||
// doesn't conform to the rest of their scheme.
|
||||
// Following the model of MSFT Guard output strings even though the mangled form does not
|
||||
// follow MSFT's scheme. Change is that we are not outputting the extraneous tick as is seen
|
||||
// in the middle of `local static guard'{2}', but we are still increasing the string value
|
||||
// that is in braces by one from the coded value. Thus, we are outputting
|
||||
// `thread safe static guard{1}' for "?$TSS0@". We can reconsider this later.
|
||||
public void parseLLVM() throws MDException {
|
||||
if (dmang.positionStartsWith("?$TSS")) {
|
||||
dmang.parseInfoPush(0, "thread safe static guard");
|
||||
dmang.increment("?$TSS".length());
|
||||
String guardNumberString = getNumberString();
|
||||
dmang.parseInfoPop();
|
||||
name = "`thread safe static guard{" + guardNumberString + "}'";
|
||||
}
|
||||
else if (dmang.positionStartsWith("?$S1@")) {
|
||||
// The '1' in "?$S1" is currently hard-coded in the LLVM code, but I believe we
|
||||
// should still enclose it in braces... subject to change.
|
||||
dmang.parseInfoPush(0, "nonvisible static guard");
|
||||
dmang.increment("?$S1@".length());
|
||||
name = "`nonvisible static guard{1}'";
|
||||
dmang.parseInfoPop();
|
||||
}
|
||||
else if (dmang.positionStartsWith("?$RT")) {
|
||||
dmang.parseInfoPush(0, "reference temporary");
|
||||
dmang.increment("?$RT".length());
|
||||
String manglingNumberString = getNumberString();
|
||||
dmang.parseInfoPop();
|
||||
name = "`reference temporary{" + manglingNumberString + "}'";
|
||||
}
|
||||
else {
|
||||
throw new MDException("Could not match NonStandard Special Name");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Number (it is output as Number << '@' where Number is an unsigned int, so we are
|
||||
* capturing it as a string of digits, terminated with an '@' character.
|
||||
* Built for what seems to be LLVM-specific mangling. Does not follow MSFT model.
|
||||
* @return a the Number represented by a String (decimal).
|
||||
* @throws MDException Upon invalid character sequence or out of characters.
|
||||
*/
|
||||
private String getNumberString() throws MDException {
|
||||
char ch;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
dmang.parseInfoPush(0, "Number");
|
||||
while ((ch = dmang.peek()) != '@') {
|
||||
if (!Character.isDigit(ch)) { // includes end of string (MDMang.DONE)
|
||||
throw new MDException("Illegal character in Number: " + ch);
|
||||
}
|
||||
builder.append(ch);
|
||||
dmang.next();
|
||||
}
|
||||
dmang.next(); // '@'
|
||||
dmang.parseInfoPop();
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package mdemangler.object;
|
||||
|
||||
import mdemangler.*;
|
||||
import mdemangler.MDMang.ProcessingMode;
|
||||
import mdemangler.datatype.MDDataTypeParser;
|
||||
import mdemangler.template.MDTemplateNameAndArguments;
|
||||
|
||||
|
@ -25,8 +26,50 @@ import mdemangler.template.MDTemplateNameAndArguments;
|
|||
*/
|
||||
public class MDMangObjectParser {
|
||||
|
||||
public static MDParsableItem parse(MDMang dmang) throws MDException {
|
||||
public static MDParsableItem determineItemAndParse(MDMang dmang) throws MDException {
|
||||
boolean retry = false;
|
||||
MDException firstException = null;
|
||||
MDParsableItem myItem = null;
|
||||
int index = dmang.getIndex();
|
||||
try {
|
||||
myItem = parseDefaultStandard(dmang);
|
||||
if (myItem != null) {
|
||||
myItem.parse();
|
||||
}
|
||||
else {
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
catch (MDException e) {
|
||||
retry = true;
|
||||
myItem = null;
|
||||
firstException = e;
|
||||
}
|
||||
if (!retry) {
|
||||
return myItem;
|
||||
}
|
||||
try {
|
||||
dmang.setIndex(index);
|
||||
myItem = parseLlvm(dmang);
|
||||
if (myItem != null) {
|
||||
myItem.parse();
|
||||
}
|
||||
}
|
||||
catch (MDException e) {
|
||||
if (firstException != null) {
|
||||
throw firstException;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
if (myItem == null && firstException != null) {
|
||||
throw firstException;
|
||||
}
|
||||
return myItem;
|
||||
}
|
||||
|
||||
public static MDParsableItem parseDefaultStandard(MDMang dmang) throws MDException {
|
||||
MDParsableItem item;
|
||||
dmang.setProcessingMode(ProcessingMode.DEFAULT_STANDARD);
|
||||
if (dmang.peek() == '?') {
|
||||
if (dmang.peek(1) == '@') {
|
||||
item = new MDObjectCodeView(dmang);
|
||||
|
@ -52,6 +95,17 @@ public class MDMangObjectParser {
|
|||
return item;
|
||||
}
|
||||
|
||||
public static MDParsableItem parseLlvm(MDMang dmang) {
|
||||
// Might eliminate next test if we create other "non-standard" processing
|
||||
// that does not begin with "?$".
|
||||
if (dmang.peek() != '?' && dmang.peek(1) != '$') {
|
||||
return null;
|
||||
}
|
||||
dmang.setProcessingMode(ProcessingMode.LLVM);
|
||||
MDObjectCPP item = new MDObjectCPP(dmang);
|
||||
return item;
|
||||
}
|
||||
|
||||
// Thus far, we have seen (created from forward code example):
|
||||
// __mep => [MEP], which is presumably "Managed Entry Point"
|
||||
// __t2m => [T2M], which is presumably "Transition to Managed (code)"
|
||||
|
@ -96,7 +150,7 @@ public class MDMangObjectParser {
|
|||
* @throws MDException Upon <b><code>MDMang</code></b> parsing issues that cause us to fail
|
||||
* processing.
|
||||
*/
|
||||
public static MDParsableItem parseObjectReserved(MDMang dmang) throws MDException {
|
||||
public static MDParsableItem parseObjectReserved(MDMang dmang) {
|
||||
MDParsableItem item;
|
||||
if (dmang.positionStartsWith("__TI")) {
|
||||
dmang.increment("__TI".length());
|
||||
|
|
|
@ -17,6 +17,7 @@ package mdemangler.object;
|
|||
|
||||
import ghidra.util.Msg;
|
||||
import mdemangler.*;
|
||||
import mdemangler.MDMang.ProcessingMode;
|
||||
import mdemangler.functiontype.MDFunctionType;
|
||||
import mdemangler.naming.*;
|
||||
import mdemangler.typeinfo.MDTypeInfo;
|
||||
|
@ -119,7 +120,13 @@ public class MDObjectCPP extends MDObject {
|
|||
if (dmang.peek() != '?') {
|
||||
throw new MDException("Invalid ObjectCPP");
|
||||
}
|
||||
dmang.increment();
|
||||
if (!dmang.isProcessingModeActive(ProcessingMode.LLVM)) {
|
||||
// If not LLVM mode, then the '?' seen above is valid as being part of this MDObjectCPP
|
||||
// parsing, so we should consume it. If, on the other hand, we are in LLVM mode, then
|
||||
// this '?' is currently part of the possible nonstandard mangling forms that are
|
||||
// output by LLVM mangling and they are consumed there.
|
||||
dmang.increment();
|
||||
}
|
||||
if ((dmang.peek(0) == '?') && (dmang.peek(1) == '?')) { //??? prefix
|
||||
embeddedObjectFlag = true;
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ public class MDObjectCatch extends MDObjectReserved {
|
|||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
internalItem = MDMangObjectParser.parse(dmang);
|
||||
internalItem.parse();
|
||||
internalItem = MDMangObjectParser.determineItemAndParse(dmang);
|
||||
dmang.increment(); // '$'
|
||||
//We are assuming that we can have more than one digit.
|
||||
//TODO: forward programming to test beyond one digit.
|
||||
|
|
|
@ -37,14 +37,12 @@ public class MDObjectUnwindFunclet extends MDObjectReserved {
|
|||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
super.insert(builder);
|
||||
dmang.appendString(builder,
|
||||
"[UnwindFunclet," + digits + "]{" + internalItem + "}");
|
||||
dmang.appendString(builder, "[UnwindFunclet," + digits + "]{" + internalItem + "}");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
internalItem = MDMangObjectParser.parse(dmang);
|
||||
internalItem.parse();
|
||||
internalItem = MDMangObjectParser.determineItemAndParse(dmang);
|
||||
dmang.increment(); // '$'
|
||||
//Here, we have seen $9 and $10 (two digits for $10).
|
||||
//TODO: forward programming to test beyond one digit.
|
||||
|
|
|
@ -43,8 +43,16 @@ public class MDTypeInfo extends MDParsableItem {
|
|||
_NOT_SPECIFIED, _STATIC, _VIRTUAL
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum representing pointer format.
|
||||
*/
|
||||
enum PointerFormat {
|
||||
_NOT_SPECIFIED, _NEAR, _FAR //HUGE not present in mangling.
|
||||
}
|
||||
|
||||
private StorageClass storage = StorageClass._NOT_SPECIFIED;
|
||||
private AccessSpecifier access = AccessSpecifier._NOT_SPECIFIED;
|
||||
private PointerFormat pointerFormat = PointerFormat._NOT_SPECIFIED;
|
||||
private boolean isThunk = false;
|
||||
private boolean isMember = true;
|
||||
private boolean isExternC = false;
|
||||
|
@ -103,6 +111,18 @@ public class MDTypeInfo extends MDParsableItem {
|
|||
return (storage == StorageClass._VIRTUAL);
|
||||
}
|
||||
|
||||
public void setPointerFormat(PointerFormat pointerFormat) {
|
||||
this.pointerFormat = pointerFormat;
|
||||
}
|
||||
|
||||
public boolean isNear() {
|
||||
return (pointerFormat == PointerFormat._NEAR);
|
||||
}
|
||||
|
||||
public boolean isFar() {
|
||||
return (pointerFormat == PointerFormat._FAR);
|
||||
}
|
||||
|
||||
public void setThunk() {
|
||||
isThunk = true;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package mdemangler.typeinfo;
|
|||
import mdemangler.MDException;
|
||||
import mdemangler.MDMang;
|
||||
import mdemangler.datatype.modifier.MDBasedAttribute;
|
||||
import mdemangler.typeinfo.MDTypeInfo.PointerFormat;
|
||||
|
||||
/**
|
||||
* This class parses the mangled string at the current offset to determine and
|
||||
|
@ -143,11 +144,13 @@ public class MDTypeInfoParser {
|
|||
// hasArgs = false; //no reason to have set true
|
||||
// dmang.parseInfoPop();
|
||||
break;
|
||||
case 'A':
|
||||
case 'A': // A, B, I, J, Q, R: These might be "this adjustment" with no adjustment
|
||||
case 'B':
|
||||
dmang.increment();
|
||||
typeInfo = new MDMemberFunctionInfo(dmang);
|
||||
typeInfo.setPrivate();
|
||||
typeInfo.setPointerFormat(
|
||||
(code % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case 'C':
|
||||
case 'D':
|
||||
|
@ -168,12 +171,16 @@ public class MDTypeInfoParser {
|
|||
dmang.increment();
|
||||
typeInfo = new MDVFAdjustor(dmang);
|
||||
typeInfo.setPrivate();
|
||||
typeInfo.setPointerFormat(
|
||||
(code % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case 'I':
|
||||
case 'I': // A, B, I, J, Q, R: These might be "this adjustment" with no adjustment
|
||||
case 'J':
|
||||
dmang.increment();
|
||||
typeInfo = new MDMemberFunctionInfo(dmang);
|
||||
typeInfo.setProtected();
|
||||
typeInfo.setPointerFormat(
|
||||
(code % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case 'K':
|
||||
case 'L':
|
||||
|
@ -194,12 +201,16 @@ public class MDTypeInfoParser {
|
|||
dmang.increment();
|
||||
typeInfo = new MDVFAdjustor(dmang);
|
||||
typeInfo.setProtected();
|
||||
typeInfo.setPointerFormat(
|
||||
(code % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case 'Q':
|
||||
case 'Q': // A, B, I, J, Q, R: These might be "this adjustment" with no adjustment
|
||||
case 'R':
|
||||
dmang.increment();
|
||||
typeInfo = new MDMemberFunctionInfo(dmang);
|
||||
typeInfo.setPublic();
|
||||
typeInfo.setPointerFormat(
|
||||
(code % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case 'S':
|
||||
case 'T':
|
||||
|
@ -220,6 +231,8 @@ public class MDTypeInfoParser {
|
|||
dmang.increment();
|
||||
typeInfo = new MDVFAdjustor(dmang);
|
||||
typeInfo.setPublic();
|
||||
typeInfo.setPointerFormat(
|
||||
(code % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
|
@ -269,16 +282,22 @@ public class MDTypeInfoParser {
|
|||
case '1':
|
||||
typeInfo = new MDVtordisp(dmang);
|
||||
typeInfo.setPrivate();
|
||||
typeInfo.setPointerFormat(
|
||||
(ch % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case '2':
|
||||
case '3':
|
||||
typeInfo = new MDVtordisp(dmang);
|
||||
typeInfo.setProtected();
|
||||
typeInfo.setPointerFormat(
|
||||
(ch % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case '4':
|
||||
case '5':
|
||||
typeInfo = new MDVtordisp(dmang);
|
||||
typeInfo.setPublic();
|
||||
typeInfo.setPointerFormat(
|
||||
(ch % 2 == 0) ? PointerFormat._NEAR : PointerFormat._NEAR);
|
||||
break;
|
||||
case '$':
|
||||
char ch2 = dmang.getAndIncrement();
|
||||
|
|
|
@ -33,8 +33,10 @@ public class MDVtordisp extends MDMemberFunctionInfo {
|
|||
|
||||
@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 + "}' ";
|
||||
|
|
|
@ -33,16 +33,16 @@ public class MDVtordispex extends MDMemberFunctionInfo {
|
|||
|
||||
@Override
|
||||
protected void parseInternal() throws MDException {
|
||||
// TODO: what is this? Possibly the displacement?
|
||||
// 20200507: Believe this to be <offset-to-vptr>
|
||||
MDEncodedNumber a = new MDEncodedNumber(dmang);
|
||||
a.parse();
|
||||
// TODO: what is this? Possibly the adjustment?
|
||||
// 20200507: Believe this to be <vbase-offset-offset>
|
||||
MDEncodedNumber b = new MDEncodedNumber(dmang);
|
||||
b.parse();
|
||||
// TODO: what is this?
|
||||
// 20200507: Believe this to be <offset-to-vtordisp>
|
||||
MDEncodedNumber c = new MDEncodedNumber(dmang);
|
||||
c.parse();
|
||||
// TODO: what is this?
|
||||
// 20200507: Believe this to be <static-offset>
|
||||
MDEncodedNumber d = new MDEncodedNumber(dmang);
|
||||
d.parse();
|
||||
nameModifier = "`vtordispex{" + a + "," + b + "," + c + "," + d + "}' ";
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* 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.
|
||||
|
@ -198,6 +198,7 @@ public class MDBaseTestConfiguration {
|
|||
demangled = demangItem.toString();
|
||||
}
|
||||
catch (MDException e) {
|
||||
Msg.info(this, "Could not demangle: " + mangled, e);
|
||||
demangItem = null;
|
||||
demangled = "";
|
||||
}
|
||||
|
|
|
@ -14487,24 +14487,87 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
demangleAndTest();
|
||||
}
|
||||
|
||||
//TODO: considering for Issue 1162
|
||||
@Ignore
|
||||
// real symbol (Issue #1162)
|
||||
// Following the model of MSFT Guard output strings even though the mangled form does not
|
||||
// follow MSFT's scheme. Change is that we are not outputting the extraneous tick as is seen
|
||||
// in the middle of `local static guard'{2}', and we are not increasing the string value
|
||||
// that is in braces by one from the coded "GuardNum" value. Thus, we are outputting
|
||||
// `thread safe static guard{0}' for "?$TSS0@". We can reconsider this later.
|
||||
@Test
|
||||
public void testThreadSafeStaticGuard_1() throws Exception {
|
||||
mangled =
|
||||
"?$TSS0@?1??GetCategoryMap@CDynamicRegistrationInfoSource@XPerfAddIn@@SAPEBU_ATL_CATMAP_ENTRY@ATL@@XZ@4HA";
|
||||
// mangled =
|
||||
// "?xTSS0@?1??GetCategoryMap@CDynamicRegistrationInfoSource@XPerfAddIn@@SAPEBU_ATL_CATMAP_ENTRY@ATL@@XZ@4HA";
|
||||
//TODO: investigate and consider what we should have as outputs.
|
||||
msTruth = "";
|
||||
mdTruth =
|
||||
"int `public: static struct ATL::_ATL_CATMAP_ENTRY const * __ptr64 __cdecl XPerfAddIn::CDynamicRegistrationInfoSource::GetCategoryMap(void)'::`2'::`thread safe local static guard'";
|
||||
"int `public: static struct ATL::_ATL_CATMAP_ENTRY const * __ptr64 __cdecl XPerfAddIn::CDynamicRegistrationInfoSource::GetCategoryMap(void)'::`2'::`thread safe static guard{0}'";
|
||||
//TODO: Create MDMangVS2015 Specialization for this problem and then remove "mstruth = mdtruth"
|
||||
msTruth = mdTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleMainTemplateAsCounterpointToThreadSafeStaticGuard() throws Exception {
|
||||
mangled = "?$TSS0@HH"; // Begins with same pattern as ThreadSafeStaticGuard
|
||||
msTruth = "TSS0<int,int>";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
// Manufactured by modifying "??_B?1??name0@name1@name2@@KAHPEBGAEAG@Z@51" which is a
|
||||
// `local static guard'{2}'. We eliminated the closing 51 that makes it an MDGuard typeinfo
|
||||
// with value of 2 (1+1). We are also eliminating the extraneous middle closing tick (single
|
||||
// quote) that MSFT has in their output. We are not incrementing the value of ManglingNumber
|
||||
// that we are putting in braces (unlike other MSFT guard numbers). Thus, we will output
|
||||
// `nonvisible static guard{1}' for "?$S1@". We can reconsider this later. We also tacked
|
||||
// on the "4HA" as is done for the `thread safe static guard' so that it is an "int".
|
||||
// TODO: Watch for real symbol of this type "?$S1@".
|
||||
@Test
|
||||
public void testNonvisibleStaticGuard() throws Exception {
|
||||
mangled = "?$S1@?1??name0@name1@name2@@KAHPEBGAEAG@Z@4HA";
|
||||
mdTruth =
|
||||
"int `protected: static int __cdecl name2::name1::name0(unsigned short const * __ptr64,unsigned short & __ptr64)'::`2'::`nonvisible static guard{1}'";
|
||||
//TODO: Create MDMangVS2015 Specialization for this problem and then remove "mstruth = mdtruth"
|
||||
msTruth = mdTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleMainTemplateAsCounterpointToNonvisibleStaticGuard() throws Exception {
|
||||
mangled = "?$S1@HH"; // Begins with same pattern as ThreadSafeStaticGuard
|
||||
msTruth = "S1<int,int>";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
// Manufactured by modifying "??_B?1??name0@name1@name2@@KAHPEBGAEAG@Z@51" which is a
|
||||
// `local static guard'{2}'. We eliminated the closing 51 that makes it an MDGuard typeinfo
|
||||
// with value of 2 (1+1). We are also eliminating the extraneous middle closing tick (single
|
||||
// quote) that MSFT has in their output. We are not incrementing the value of "number"
|
||||
// that we are putting in braces (unlike other MSFT guard numbers). Thus, we will output
|
||||
// `reference temporary{1}'" for the "?$RT1@". We can reconsider this later. We also tacked
|
||||
// on the "4HA" as is done for the `thread safe static guard' so that it is an "int".
|
||||
// TODO: Watch for real symbol of this type "?$RTnum@".
|
||||
@Test
|
||||
public void testReferenceTemporary() throws Exception {
|
||||
mangled = "?$RT1@?1??name0@name1@name2@@KAHPEBGAEAG@Z@4HA";
|
||||
mdTruth =
|
||||
"int `protected: static int __cdecl name2::name1::name0(unsigned short const * __ptr64,unsigned short & __ptr64)'::`2'::`reference temporary{1}'";
|
||||
//TODO: Create MDMangVS2015 Specialization for this problem and then remove "mstruth = mdtruth"
|
||||
msTruth = mdTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleMainTemplateAsCounterpointToReferenceTemporary() throws Exception {
|
||||
mangled = "?$RT1@HH"; // Begins with same pattern as ThreadSafeStaticGuard
|
||||
msTruth = "RT1<int,int>";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
//Issue 1344: Long symbols get MD5-hashed.
|
||||
// We have made up the output format. Nothing is sacrosanct about this output.
|
||||
@Test
|
||||
public void testHashedSymbolComponentsLongerThan5096_1() throws Exception {
|
||||
public void testHashedSymbolComponentsLongerThan4096_1() throws Exception {
|
||||
mangled = "??@f4873c94f485cd6716c2319fc51ac714@";
|
||||
msTruth = "";
|
||||
mdTruth = "`f4873c94f485cd6716c2319fc51ac714'";
|
||||
|
@ -14514,7 +14577,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
//Issue 1344: Long symbols get MD5-hashed.
|
||||
// We have made up the output format. Nothing is sacrosanct about this output.
|
||||
@Test
|
||||
public void testHashedSymbolComponentsLongerThan5096_2() throws Exception {
|
||||
public void testHashedSymbolComponentsLongerThan4096_2() throws Exception {
|
||||
mangled = "?catch$0@?0???@f4873c94f485cd6716c2319fc51ac714@@4HA";
|
||||
msTruth = "";
|
||||
mdTruth = "int ``f4873c94f485cd6716c2319fc51ac714''::`1'::catch$0";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue