mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-09-20 17:41:48 +00:00
GP-4703 - MDMang - retry on demangleType
This commit is contained in:
parent
0e33958c76
commit
8336bdde74
|
@ -162,22 +162,10 @@ public class MDMang {
|
|||
* @throws MDException upon parsing error
|
||||
*/
|
||||
public MDDataType demangleType(boolean errorOnRemainingChars) throws MDException {
|
||||
if (mangled == null) {
|
||||
throw new MDException("MDMang: Mangled string is null.");
|
||||
}
|
||||
initState();
|
||||
pushContext();
|
||||
if (peek() != '.') {
|
||||
throw new MDException("MDMang: Mangled string is not that of a type.");
|
||||
}
|
||||
increment();
|
||||
MDDataType mdDataType = MDDataTypeParser.parseDataType(this, false);
|
||||
MDDataType mdDataType = MDDataTypeParser.determineAndParseDataType(this, false);
|
||||
item = mdDataType;
|
||||
if (mdDataType != null) {
|
||||
mdDataType.parse();
|
||||
}
|
||||
int numCharsRemaining = getNumCharsRemaining();
|
||||
popContext();
|
||||
if (errorOnRemainingChars && (numCharsRemaining > 0)) {
|
||||
throw new MDException(
|
||||
"MDMang: characters remain after demangling: " + numCharsRemaining + ".");
|
||||
|
|
|
@ -17,6 +17,7 @@ package mdemangler.datatype;
|
|||
|
||||
import mdemangler.MDException;
|
||||
import mdemangler.MDMang;
|
||||
import mdemangler.MDMang.ProcessingMode;
|
||||
import mdemangler.datatype.complex.*;
|
||||
import mdemangler.datatype.extended.*;
|
||||
import mdemangler.datatype.modifier.*;
|
||||
|
@ -31,6 +32,52 @@ import mdemangler.object.MDObjectCPP;
|
|||
* by calling the appropriate parser at the appropriate place in the code.
|
||||
*/
|
||||
public class MDDataTypeParser {
|
||||
/**
|
||||
* This method is only to be used by MDMang itself for the highest level type parsing where
|
||||
* there is not already a multi-retry. This method checks for the '.' starting character,
|
||||
* determines the type by calling the {@link #parseDataType(MDMang, boolean)}, parses the type,
|
||||
* and does the multi-mode retry if there is an exception on the first pass as
|
||||
* MDMangObjectParser does for generic mangled objects
|
||||
* @param dmang - the MDMang driver
|
||||
* @param isHighest - boolean indicating whether something else modifies or names the data
|
||||
* type to be parsed, which impacts when certain overloaded CV modifiers can be applied.
|
||||
* @return - a type derived from MDDataType
|
||||
* @throws MDException on parsing error
|
||||
*/
|
||||
public static MDDataType determineAndParseDataType(MDMang dmang, boolean isHighest)
|
||||
throws MDException {
|
||||
|
||||
MDDataType dt = null;
|
||||
if (dmang.peek() != '.') {
|
||||
throw new MDException("MDMang: Mangled string is not that of a type.");
|
||||
}
|
||||
|
||||
dmang.setProcessingMode(ProcessingMode.DEFAULT_STANDARD);
|
||||
try {
|
||||
dmang.pushContext();
|
||||
dmang.increment(); // skip the '.'
|
||||
dt = parseDataType(dmang, isHighest);
|
||||
dt.parse();
|
||||
dmang.popContext();
|
||||
}
|
||||
catch (MDException e1) {
|
||||
dmang.resetState();
|
||||
dmang.setProcessingMode(ProcessingMode.LLVM);
|
||||
try {
|
||||
dmang.pushContext();
|
||||
dmang.increment(); // skip the '.'
|
||||
dt = parseDataType(dmang, isHighest);
|
||||
dt.parse();
|
||||
dmang.popContext();
|
||||
}
|
||||
catch (MDException e2) {
|
||||
throw new MDException(
|
||||
"Reason1: " + e1.getMessage().trim() + "; Reason2: " + e2.getMessage().trim());
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method parses all data types. Specifically, it parses void, data indirect types,
|
||||
* function indirect types, and all types parsed by parsePrimaryDataType().
|
||||
|
|
|
@ -14992,6 +14992,19 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
demangleAndTest();
|
||||
}
|
||||
|
||||
// Note the suffix seems like an already or partially demangled name. Note that name0
|
||||
// seems like a plain tag (no closing '@'), there is a regular namespace delimiter "::",
|
||||
// the suffix "3@" is almost like a backreference tag with the '@' closing the full
|
||||
// qualified name... except... we've seen numbers that are beyond the backref range as
|
||||
// here, but also have seen numbers like 18.
|
||||
@Ignore
|
||||
public void testMangledTypeWithNamespaceSuffix() throws Exception {
|
||||
mangled = ".?AT<unnamed-tag>@name0::3@";
|
||||
msTruth = "";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
//=====================
|
||||
|
||||
@Test
|
||||
|
|
|
@ -80,4 +80,18 @@ public class MDMangExtraTest extends AbstractGenericTest {
|
|||
assertEquals("k::j::i", qualifications.get(2).toString());
|
||||
}
|
||||
|
||||
// Need to test the demangleType() method to make sure it does the retry with LLVM mode
|
||||
@Test
|
||||
public void testDemangleTypeWithRetry() throws Exception {
|
||||
// Test string taken from MDMangBaseTest
|
||||
String mangled = ".?AW4name0@?name1@name2@@YAX_N@Z@";
|
||||
String truth = "enum `void __cdecl name2::name1(bool)'::name0";
|
||||
|
||||
MDMangGhidra demangler = new MDMangGhidra();
|
||||
MDParsableItem item = demangler.demangleType(mangled, true); // note demangleType()
|
||||
|
||||
String demangled = item.toString();
|
||||
assertEquals(truth, demangled);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user