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 { protected void parseInternal() throws MDException {
parsed = true; parsed = true;
// TODO: Provide mechanism to turn on/off (move this boolean into MDMang?) // 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) { if (boolean32BitSymbols) {
switch (dmang.getAndIncrement()) { switch (dmang.getAndIncrement()) {
case '0': // UINFO: void case '0': // UINFO: void
@ -124,7 +125,7 @@ public class MDBasedAttribute extends MDParsableItem {
bn.parse(); bn.parse();
StringBuilder bnBuilder = new StringBuilder(); StringBuilder bnBuilder = new StringBuilder();
bn.insert(bnBuilder); bn.insert(bnBuilder);
dmang.appendString(bnBuilder, "\""); dmang.appendString(bnBuilder, "\")");
dmang.insertString(bnBuilder, "__segmname(\""); dmang.insertString(bnBuilder, "__segmname(\"");
basedName = bnBuilder.toString(); basedName = bnBuilder.toString();
break; break;

View file

@ -59,19 +59,21 @@ public class MDVCall extends MDMemberFunctionInfo {
@Override @Override
public String getModifier() { public String getModifier() {
// TODO: Future specialization on 16-bit or 32plus if (dmang.getArchitectureSize() == 16) {
return getNameModifier_16BitModel();
}
return getNameModifier_32PlusBitModel(); return getNameModifier_32PlusBitModel();
} }
@Override @Override
public void insert(StringBuilder builder) { public void insert(StringBuilder builder) {
// TODO: Future specialization on 16-bit or 32plus
// dmang.appendString(builder, getNameModifier_32PlusBitModel());
super.insert(builder); super.insert(builder);
} }
public String getNameModifier_16BitModel() { 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) { if (myThisModel == ThisModel.NEAR) {
modifier += NEAR_STRING; modifier += NEAR_STRING;
} }
@ -93,7 +95,10 @@ public class MDVCall extends MDMemberFunctionInfo {
modifier += FAR_STRING; modifier += FAR_STRING;
} }
else { else {
modifier += basedType; // TODO based value. String baseStr = basedType.toString();
if (!baseStr.isEmpty()) {
modifier += baseStr + " ";
}
} }
modifier += "vfptr}}' }'"; modifier += "vfptr}}' }'";
return modifier; return modifier;
@ -170,6 +175,7 @@ public class MDVCall extends MDMemberFunctionInfo {
myThisModel = ThisModel.NEAR; myThisModel = ThisModel.NEAR;
myCallModel = CallModel.NEAR; myCallModel = CallModel.NEAR;
myVfptrModel = VfptrModel.BASED; myVfptrModel = VfptrModel.BASED;
basedType = new MDBasedAttribute(dmang);
basedType.parse(); // TODO: check this basedType.parse(); // TODO: check this
// nameModifier += "__near this, __near call, " + basedType + " // nameModifier += "__near this, __near call, " + basedType + "
// vfptr}}' }'"; // vfptr}}' }'";
@ -178,6 +184,7 @@ public class MDVCall extends MDMemberFunctionInfo {
myThisModel = ThisModel.NEAR; myThisModel = ThisModel.NEAR;
myCallModel = CallModel.FAR; myCallModel = CallModel.FAR;
myVfptrModel = VfptrModel.BASED; myVfptrModel = VfptrModel.BASED;
basedType = new MDBasedAttribute(dmang);
basedType.parse(); // TODO: check this basedType.parse(); // TODO: check this
// nameModifier += "__near this, __far call, " + basedType + " // nameModifier += "__near this, __far call, " + basedType + "
// vfptr}}' }'"; // vfptr}}' }'";
@ -186,6 +193,7 @@ public class MDVCall extends MDMemberFunctionInfo {
myThisModel = ThisModel.FAR; myThisModel = ThisModel.FAR;
myCallModel = CallModel.NEAR; myCallModel = CallModel.NEAR;
myVfptrModel = VfptrModel.BASED; myVfptrModel = VfptrModel.BASED;
basedType = new MDBasedAttribute(dmang);
basedType.parse(); // TODO: check this basedType.parse(); // TODO: check this
// nameModifier += "__far this, __near call, " + basedType + " // nameModifier += "__far this, __near call, " + basedType + "
// vfptr}}' }'"; // vfptr}}' }'";
@ -194,6 +202,7 @@ public class MDVCall extends MDMemberFunctionInfo {
myThisModel = ThisModel.FAR; myThisModel = ThisModel.FAR;
myCallModel = CallModel.FAR; myCallModel = CallModel.FAR;
myVfptrModel = VfptrModel.BASED; myVfptrModel = VfptrModel.BASED;
basedType = new MDBasedAttribute(dmang);
basedType.parse(); // TODO: check this basedType.parse(); // TODO: check this
// nameModifier += "__far this, __far call, " + basedType + " // nameModifier += "__far this, __far call, " + basedType + "
// vfptr}}' }'"; // vfptr}}' }'";

View file

@ -45,6 +45,7 @@ public class MDBaseTestConfiguration {
protected String mangled; protected String mangled;
protected MDParsableItem demangItem; protected MDParsableItem demangItem;
protected boolean isFunction = false; protected boolean isFunction = false;
protected int archSize = 64;
protected String demangled; protected String demangled;
protected String truth; protected String truth;
@ -66,6 +67,10 @@ public class MDBaseTestConfiguration {
isFunction = isFunctionArg; isFunction = isFunctionArg;
} }
public void setArchitectureSize(int size) {
archSize = size;
}
/** /**
* Runs through the process of creating a demangler, demangling a symbol string, * Runs through the process of creating a demangler, demangling a symbol string,
* testing the output, and performing other ancillary outputs and tests. * testing the output, and performing other ancillary outputs and tests.
@ -91,6 +96,8 @@ public class MDBaseTestConfiguration {
} }
mdm.setIsFunction(isFunction); mdm.setIsFunction(isFunction);
mdm.setArchitectureSize(archSize);
// Meant to be overridden, as needed by extended classes // Meant to be overridden, as needed by extended classes
demangItem = doDemangleSymbol(mdm, mangled); demangItem = doDemangleSymbol(mdm, mangled);
demangled = (demangItem == null) ? "" : demangItem.toString(); demangled = (demangItem == null) ? "" : demangItem.toString();

View file

@ -194,8 +194,15 @@ public class MDMangBaseTest extends AbstractGenericTest {
ms2013Truth); ms2013Truth);
} }
private void demangleAndTestFunction() throws Exception { private void demangleAndTestFunction32Bit() throws Exception {
testConfiguration.setIsFunction(true); 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, testConfiguration.demangleAndTest(testName, mangled, mdTruth, msTruth, ghTruth,
ms2013Truth); ms2013Truth);
} }
@ -15362,7 +15369,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
mangled = "_name"; mangled = "_name";
mdTruth = "name"; mdTruth = "name";
msTruth = ""; msTruth = "";
demangleAndTestFunction(); demangleAndTestFunction32Bit();
} }
@Test @Test
@ -15378,7 +15385,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
mangled = "_name@12"; mangled = "_name@12";
mdTruth = "__stdcall name,12"; mdTruth = "__stdcall name,12";
msTruth = ""; msTruth = "";
demangleAndTestFunction(); demangleAndTestFunction32Bit();
} }
@Test @Test
@ -15394,7 +15401,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
mangled = "@name@12"; mangled = "@name@12";
mdTruth = "__fastcall name,12"; mdTruth = "__fastcall name,12";
msTruth = ""; msTruth = "";
demangleAndTestFunction(); demangleAndTestFunction32Bit();
} }
@Test @Test
@ -15410,7 +15417,7 @@ public class MDMangBaseTest extends AbstractGenericTest {
mangled = "name@@12"; mangled = "name@@12";
mdTruth = "__vectorcall name,12"; mdTruth = "__vectorcall name,12";
msTruth = ""; msTruth = "";
demangleAndTestFunction(); demangleAndTestFunction32Bit();
} }
@Test @Test
@ -15421,6 +15428,247 @@ public class MDMangBaseTest extends AbstractGenericTest {
demangleAndTest(); 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. //TODO: ignore for now.