mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-5776 - MDMang - Improved 16-bit program demangling of vcall modifiers and based attributes
This commit is contained in:
parent
7482131bcc
commit
cc213cdebf
4 changed files with 278 additions and 13 deletions
|
@ -37,7 +37,7 @@ import mdemangler.naming.MDQualifiedName;
|
|||
// that String at the appropriate time in the processing of
|
||||
// outputting a demangled String. So, we first, purposefully
|
||||
// insert this null character, and later look for it in order
|
||||
// to properly truncate the substring in question, in order to
|
||||
// to properly truncate the substring in question, in order to
|
||||
// mimic what we believe is happening in Microsoft demangler
|
||||
// code.... but this is true only if we care to mimic Microsoft
|
||||
// code, which we do and do not want to do, depending on which
|
||||
|
@ -69,7 +69,8 @@ public class MDBasedAttribute extends MDParsableItem {
|
|||
protected void parseInternal() throws MDException {
|
||||
parsed = true;
|
||||
// TODO: Provide mechanism to turn on/off (move this boolean into MDMang?)
|
||||
boolean boolean32BitSymbols = true;
|
||||
// Guessing that this is correct. We do not yet have real demangled output to test against
|
||||
boolean boolean32BitSymbols = dmang.getArchitectureSize() != 16;
|
||||
if (boolean32BitSymbols) {
|
||||
switch (dmang.getAndIncrement()) {
|
||||
case '0': // UINFO: void
|
||||
|
@ -124,7 +125,7 @@ public class MDBasedAttribute extends MDParsableItem {
|
|||
bn.parse();
|
||||
StringBuilder bnBuilder = new StringBuilder();
|
||||
bn.insert(bnBuilder);
|
||||
dmang.appendString(bnBuilder, "\"");
|
||||
dmang.appendString(bnBuilder, "\")");
|
||||
dmang.insertString(bnBuilder, "__segmname(\"");
|
||||
basedName = bnBuilder.toString();
|
||||
break;
|
||||
|
|
|
@ -59,19 +59,21 @@ public class MDVCall extends MDMemberFunctionInfo {
|
|||
|
||||
@Override
|
||||
public String getModifier() {
|
||||
// TODO: Future specialization on 16-bit or 32plus
|
||||
if (dmang.getArchitectureSize() == 16) {
|
||||
return getNameModifier_16BitModel();
|
||||
}
|
||||
return getNameModifier_32PlusBitModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(StringBuilder builder) {
|
||||
// TODO: Future specialization on 16-bit or 32plus
|
||||
// dmang.appendString(builder, getNameModifier_32PlusBitModel());
|
||||
super.insert(builder);
|
||||
}
|
||||
|
||||
public String getNameModifier_16BitModel() {
|
||||
String modifier = "{" + callIndex + ",";
|
||||
// 20250625: added brace after comma to somewhat match the 32-bit+ model, though both
|
||||
// still have a mismatched number of braces.
|
||||
String modifier = "{" + callIndex + ",{";
|
||||
if (myThisModel == ThisModel.NEAR) {
|
||||
modifier += NEAR_STRING;
|
||||
}
|
||||
|
@ -93,7 +95,10 @@ public class MDVCall extends MDMemberFunctionInfo {
|
|||
modifier += FAR_STRING;
|
||||
}
|
||||
else {
|
||||
modifier += basedType; // TODO based value.
|
||||
String baseStr = basedType.toString();
|
||||
if (!baseStr.isEmpty()) {
|
||||
modifier += baseStr + " ";
|
||||
}
|
||||
}
|
||||
modifier += "vfptr}}' }'";
|
||||
return modifier;
|
||||
|
@ -170,6 +175,7 @@ public class MDVCall extends MDMemberFunctionInfo {
|
|||
myThisModel = ThisModel.NEAR;
|
||||
myCallModel = CallModel.NEAR;
|
||||
myVfptrModel = VfptrModel.BASED;
|
||||
basedType = new MDBasedAttribute(dmang);
|
||||
basedType.parse(); // TODO: check this
|
||||
// nameModifier += "__near this, __near call, " + basedType + "
|
||||
// vfptr}}' }'";
|
||||
|
@ -178,6 +184,7 @@ public class MDVCall extends MDMemberFunctionInfo {
|
|||
myThisModel = ThisModel.NEAR;
|
||||
myCallModel = CallModel.FAR;
|
||||
myVfptrModel = VfptrModel.BASED;
|
||||
basedType = new MDBasedAttribute(dmang);
|
||||
basedType.parse(); // TODO: check this
|
||||
// nameModifier += "__near this, __far call, " + basedType + "
|
||||
// vfptr}}' }'";
|
||||
|
@ -186,6 +193,7 @@ public class MDVCall extends MDMemberFunctionInfo {
|
|||
myThisModel = ThisModel.FAR;
|
||||
myCallModel = CallModel.NEAR;
|
||||
myVfptrModel = VfptrModel.BASED;
|
||||
basedType = new MDBasedAttribute(dmang);
|
||||
basedType.parse(); // TODO: check this
|
||||
// nameModifier += "__far this, __near call, " + basedType + "
|
||||
// vfptr}}' }'";
|
||||
|
@ -194,6 +202,7 @@ public class MDVCall extends MDMemberFunctionInfo {
|
|||
myThisModel = ThisModel.FAR;
|
||||
myCallModel = CallModel.FAR;
|
||||
myVfptrModel = VfptrModel.BASED;
|
||||
basedType = new MDBasedAttribute(dmang);
|
||||
basedType.parse(); // TODO: check this
|
||||
// nameModifier += "__far this, __far call, " + basedType + "
|
||||
// vfptr}}' }'";
|
||||
|
|
|
@ -45,6 +45,7 @@ public class MDBaseTestConfiguration {
|
|||
protected String mangled;
|
||||
protected MDParsableItem demangItem;
|
||||
protected boolean isFunction = false;
|
||||
protected int archSize = 64;
|
||||
|
||||
protected String demangled;
|
||||
protected String truth;
|
||||
|
@ -66,6 +67,10 @@ public class MDBaseTestConfiguration {
|
|||
isFunction = isFunctionArg;
|
||||
}
|
||||
|
||||
public void setArchitectureSize(int size) {
|
||||
archSize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs through the process of creating a demangler, demangling a symbol string,
|
||||
* testing the output, and performing other ancillary outputs and tests.
|
||||
|
@ -91,6 +96,8 @@ public class MDBaseTestConfiguration {
|
|||
}
|
||||
|
||||
mdm.setIsFunction(isFunction);
|
||||
mdm.setArchitectureSize(archSize);
|
||||
|
||||
// Meant to be overridden, as needed by extended classes
|
||||
demangItem = doDemangleSymbol(mdm, mangled);
|
||||
demangled = (demangItem == null) ? "" : demangItem.toString();
|
||||
|
|
|
@ -194,8 +194,15 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
ms2013Truth);
|
||||
}
|
||||
|
||||
private void demangleAndTestFunction() throws Exception {
|
||||
private void demangleAndTestFunction32Bit() throws Exception {
|
||||
testConfiguration.setIsFunction(true);
|
||||
testConfiguration.setArchitectureSize(32);
|
||||
testConfiguration.demangleAndTest(testName, mangled, mdTruth, msTruth, ghTruth,
|
||||
ms2013Truth);
|
||||
}
|
||||
|
||||
private void demangleAndTest16Bit() throws Exception {
|
||||
testConfiguration.setArchitectureSize(16);
|
||||
testConfiguration.demangleAndTest(testName, mangled, mdTruth, msTruth, ghTruth,
|
||||
ms2013Truth);
|
||||
}
|
||||
|
@ -15362,7 +15369,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
mangled = "_name";
|
||||
mdTruth = "name";
|
||||
msTruth = "";
|
||||
demangleAndTestFunction();
|
||||
demangleAndTestFunction32Bit();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -15378,7 +15385,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
mangled = "_name@12";
|
||||
mdTruth = "__stdcall name,12";
|
||||
msTruth = "";
|
||||
demangleAndTestFunction();
|
||||
demangleAndTestFunction32Bit();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -15394,7 +15401,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
mangled = "@name@12";
|
||||
mdTruth = "__fastcall name,12";
|
||||
msTruth = "";
|
||||
demangleAndTestFunction();
|
||||
demangleAndTestFunction32Bit();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -15410,7 +15417,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
mangled = "name@@12";
|
||||
mdTruth = "__vectorcall name,12";
|
||||
msTruth = "";
|
||||
demangleAndTestFunction();
|
||||
demangleAndTestFunction32Bit();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -15421,6 +15428,247 @@ public class MDMangBaseTest extends AbstractGenericTest {
|
|||
demangleAndTest();
|
||||
}
|
||||
|
||||
//=====================
|
||||
/*
|
||||
* Following are tests involving functions and function pointers for functions that take and
|
||||
* return function pointers
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testFunctionWithFunctionPointers1() throws Exception {
|
||||
mangled = "?fxa@@3PAP6AP6AHH@ZP6ADD@Z@ZA";
|
||||
msTruth = "int (__cdecl*(__cdecl** fxa)(char (__cdecl*)(char)))(int)";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionWithFunctionPointers2() throws Exception {
|
||||
mangled = "?f2@@YAP6AP6AHH@ZP6ADD@Z@ZAAP6AP6AHH@Z0@Z@Z";
|
||||
msTruth =
|
||||
"int (__cdecl*(__cdecl*__cdecl f2(int (__cdecl*(__cdecl*&)(char (__cdecl*)(char)))(int)))(char (__cdecl*)(char)))(int)";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
//=====================
|
||||
/*
|
||||
* Follow are hand-crafted vcall modifiers with 16-bit architecture.
|
||||
* These use the architectures size for parsing both the vcall modifier as well as the
|
||||
* __based() attributes for those that use a based attribute
|
||||
*/
|
||||
|
||||
// hand-crafted... this test is a 32-bit counterpoint test for the 16-bit test after it
|
||||
@Test
|
||||
public void testVCallA32() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@AA";
|
||||
msTruth = "[thunk]: __cdecl name0::`vcall'{392,{flat}}' }'";
|
||||
mdTruth = msTruth;
|
||||
demangleAndTest();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallA16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@AA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__near this, __near call, __near vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCallB16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@BA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__near this, __far call, __near vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallC16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@CA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __near call, __near vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallD16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@DA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __near vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallE16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@EA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__near this, __near call, __far vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallF16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@FA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__near this, __far call, __far vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallG16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@GA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __near call, __far vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallH16() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@HA";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __far vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallI016() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@I0A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__near this, __near call, __based(void) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallJ016() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@J0A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__near this, __far call, __based(void) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallK016() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@K0A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __near call, __based(void) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL016() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L0A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(void) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL116() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L1A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(__self) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL216() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L2A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(NYI:__near*) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL316() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L3A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(NYI:__far*) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL416() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L4A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(NYI:__huge*) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL516() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L5A";
|
||||
// This expected result is even more questionable... need real output for based 5 code with
|
||||
// 16-bit model
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL616() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L6A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(NYI:__segment) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL716() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L7name1@A";
|
||||
// Need special attention to mangled and demangled for this hand-crafted test
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(__segmname(\"name1\")) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
// hand-crafted
|
||||
@Test
|
||||
public void testVCallL816() throws Exception {
|
||||
mangled = "??_9name0@@$BBII@L8A";
|
||||
mdTruth =
|
||||
"[thunk]: __cdecl name0::`vcall'{392,{__far this, __far call, __based(NYI:<segment-address-of-variable>) vfptr}}' }'";
|
||||
msTruth = mdTruth; // TODO: Need a 16-bit machine to determine actual mdTruth
|
||||
demangleAndTest16Bit();
|
||||
}
|
||||
|
||||
//=====================
|
||||
|
||||
//TODO: ignore for now.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue