GP-5776 - MDMang - Improved 16-bit program demangling of vcall modifiers and based attributes

This commit is contained in:
ghizard 2025-06-26 06:01:32 -04:00
parent 7482131bcc
commit cc213cdebf
4 changed files with 278 additions and 13 deletions

View file

@ -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;

View file

@ -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}}' }'";

View file

@ -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();

View file

@ -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.