diff --git a/decompile/Makefile b/decompile/Makefile index 9ec36f4..95a0617 100644 --- a/decompile/Makefile +++ b/decompile/Makefile @@ -3,7 +3,7 @@ all: src/JSRF/Jet2.obj # Simple inference rule for producing object files .SUFFIXES: .cpp .obj .cpp.obj: - CL.EXE /nologo /Wall /W4 /Ogityb0 /GfX /Fo$@ /c $< + CL.EXE /nologo /Wall /TP /W3 /Ogityb0 /MT /Gf /GX /Fo$@ /c $< # Header files used for each object src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/Std.hpp src/XDK/D3D.hpp\ diff --git a/decompile/objdiff.json b/decompile/objdiff.json index b1ccc19..49e6c44 100644 --- a/decompile/objdiff.json +++ b/decompile/objdiff.json @@ -14,11 +14,11 @@ "source_path": "src/JSRF/Jet2.cpp" }, "symbol_mappings": { - "?main_funcinfo@@3UFuncInfo@@A": "$T754", - "?main_handler@@YAXPAUEHExceptionRecord@@PAKPAXPAU_xDISPATCHER_CONTEXT@@@Z": "$L758", - "?main_handler_unwind1@@YAXXZ": "$L750", - "?main_unwindmap@@3PAUUnwindMapEntry@@A": "$T760", - "[.rdata-0]": "[.xdata$x-0]" + "[.rdata-0]": "[.xdata$x-0]", + "_main_funcinfo": "$T754", + "_main_handler": "$L758", + "_main_handler_unwind1": "$L750", + "_main_unwindmap": "$T760" } }, { @@ -28,6 +28,94 @@ "metadata": { "complete": false, "source_path": "src/JSRF/Core.cpp" + }, + "symbol_mappings": { + "DrawTree::DrawTree": "??0DrawTree@@QAE@PAUGameObj@@W4GameObjIndex@@W4GameObjFlags@@@Z", + "DrawTree::`scalar_deleting_destructor'": "??_GDrawTree@@UAEPAXI@Z", + "DrawTree::copySomeVectors": "?copySomeVectors@DrawTree@@QAEXXZ", + "DrawTree::~DrawTree": "??1DrawTree@@UAE@XZ", + "Game::Game": "??0Game@@QAE@PAII@Z", + "Game::`scalar_deleting_destructor'": "??_GGame@@UAEPAXI@Z", + "Game::addToDrawList": "?addToDrawList@Game@@QAEXPAUGameObj@@@Z", + "Game::allocObjIndex": "?allocObjIndex@Game@@QAEHW4GameObjIndex@@0@Z", + "Game::appendToDrawPriorityList": "?appendToDrawPriorityList@Game@@QAEXPAUGameObj@@@Z", + "Game::clearDrawPriorityList": "?clearDrawPriorityList@Game@@QAEXXZ", + "Game::clearScreen": "?clearScreen@Game@@QAEXXZ", + "Game::draw": "?draw@Game@@QAEXXZ", + "Game::drawList": "?drawList@Game@@QAEXW4GameObjFlags@@H@Z", + "Game::drawList_": "?drawList_@Game@@QAEXW4GameObjFlags@@HH0I00@Z", + "Game::drawObj": "?drawObj@Game@@QAEXPAUGameObj@@H@Z", + "Game::drawObjs": "?drawObjs@Game@@QAEXXZ", + "Game::drawTree1": "?drawTree1@Game@@QAEXPAUGameObj@@@Z", + "Game::enableDrawChildren": "?enableDrawChildren@Game@@QAEXXZ", + "Game::enableSkipDraw": "?enableSkipDraw@Game@@QAEXXZ", + "Game::enableSomeExtraDrawListCode": "?enableSomeExtraDrawListCode@Game@@QAEXXZ", + "Game::exec": "?exec@Game@@QAEXXZ", + "Game::fatal": "?fatal@Game@@QAEXXZ", + "Game::frame": "?frame@Game@@QAEXXZ", + "Game::getDrawPriorityListHead": "?getDrawPriorityListHead@Game@@QAEPAUGameObj@@XZ", + "Game::getGlobal": "?getGlobal@Game@@QAEIW4GlobalIndex@@@Z", + "Game::getObj": "?getObj@Game@@QAEPAUGameObj@@W4GameObjIndex@@@Z", + "Game::initRootExecObj": "?initRootExecObj@Game@@QAEXXZ", + "Game::mainLoop": "?mainLoop@Game@@QAEHXZ", + "Game::objIndexAvail": "?objIndexAvail@Game@@QAEHW4GameObjIndex@@@Z", + "Game::removeFromDrawList": "?removeFromDrawList@Game@@QAEXPAUGameObj@@@Z", + "Game::setCoveredPauseNextFrame": "?setCoveredPauseNextFrame@Game@@QAEXH@Z", + "Game::setDrawMode": "?setDrawMode@Game@@QAEXW4DrawMode@@@Z", + "Game::setEventNextFrame": "?setEventNextFrame@Game@@QAEXH@Z", + "Game::setFallbackBgColour": "?setFallbackBgColour@Game@@QAEXKH@Z", + "Game::setFreezeCamNextFrame": "?setFreezeCamNextFrame@Game@@QAEXH@Z", + "Game::setGlobal": "?setGlobal@Game@@QAEXW4GlobalIndex@@I@Z", + "Game::setLogosStarted": "?setLogosStarted@Game@@QAEXH@Z", + "Game::setObj": "?setObj@Game@@QAEXW4GameObjIndex@@PAUGameObj@@@Z", + "Game::setUncoveredPauseNextFrame": "?setUncoveredPauseNextFrame@Game@@QAEXH@Z", + "Game::sortDrawPriorityList": "?sortDrawPriorityList@Game@@QAEXXZ", + "Game::sortDrawPriorityListSingleLevel": "?sortDrawPriorityListSingleLevel@Game@@QAEXD@Z", + "Game::swapObjs": "?swapObjs@Game@@QAEXW4GameObjIndex@@0@Z", + "Game::unsetObj": "?unsetObj@Game@@QAEXW4GameObjIndex@@@Z", + "Game::~Game": "??1Game@@UAE@XZ", + "GameObj::GameObj": "??0GameObj@@QAE@PAU0@W4GameObjIndex@@W4GameObjFlags@@@Z", + "GameObj::`scalar_deleting_destructor'": "??_GGameObj@@UAEPAXI@Z", + "GameObj::`vftable'": "??_7GameObj@@6B@", + "GameObj::addToSiblings": "?addToSiblings@GameObj@@QAEXPAU1@0@Z", + "GameObj::destructChildren": "?destructChildren@GameObj@@QAEXPAU1@@Z", + "GameObj::drawListCoveredPause": "?drawListCoveredPause@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z", + "GameObj::drawListDefault": "?drawListDefault@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z", + "GameObj::drawListEvent": "?drawListEvent@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z", + "GameObj::drawListFreezeCam": "?drawListFreezeCam@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z", + "GameObj::drawListUncoveredPause": "?drawListUncoveredPause@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z", + "GameObj::drawTreeCoveredPause1": "?drawTreeCoveredPause1@GameObj@@QAEXXZ", + "GameObj::drawTreeCoveredPause2": "?drawTreeCoveredPause2@GameObj@@QAEXXZ", + "GameObj::drawTreeDefault1": "?drawTreeDefault1@GameObj@@QAEXXZ", + "GameObj::drawTreeDefault2": "?drawTreeDefault2@GameObj@@QAEXXZ", + "GameObj::drawTreeEvent1": "?drawTreeEvent1@GameObj@@QAEXXZ", + "GameObj::drawTreeEvent2": "?drawTreeEvent2@GameObj@@QAEXXZ", + "GameObj::drawTreeFreezeCam1": "?drawTreeFreezeCam1@GameObj@@QAEXXZ", + "GameObj::drawTreeFreezeCam2": "?drawTreeFreezeCam2@GameObj@@QAEXXZ", + "GameObj::drawTreeUncoveredPause1": "?drawTreeUncoveredPause1@GameObj@@QAEXXZ", + "GameObj::drawTreeUncoveredPause2": "?drawTreeUncoveredPause2@GameObj@@QAEXXZ", + "GameObj::getParent": "?getParent@GameObj@@QAEPAU1@XZ", + "GameObj::nopDraw": "?drawDefault@GameObj@@UAEXH@Z", + "GameObj::nopExec": "?execDefault@GameObj@@UAEXXZ", + "GameObj::recursiveExecCoveredPause": "?recursiveExecCoveredPause@GameObj@@QAEXXZ", + "GameObj::recursiveExecDefault": "?recursiveExecDefault@GameObj@@QAEXXZ", + "GameObj::recursiveExecEvent": "?recursiveExecEvent@GameObj@@QAEXXZ", + "GameObj::recursiveExecFreezeCam": "?recursiveExecFreezeCam@GameObj@@QAEXXZ", + "GameObj::recursiveExecUncoveredPause": "?recursiveExecUncoveredPause@GameObj@@QAEXXZ", + "GameObj::recursivePostExecCoveredPause": "?recursivePostExecCoveredPause@GameObj@@QAEXXZ", + "GameObj::recursivePostExecDefault": "?recursivePostExecDefault@GameObj@@QAEXXZ", + "GameObj::recursivePostExecEvent": "?recursivePostExecEvent@GameObj@@QAEXXZ", + "GameObj::recursivePostExecFreezeCam": "?recursivePostExecFreezeCam@GameObj@@QAEXXZ", + "GameObj::recursivePostExecUncoveredPause": "?recursivePostExecUncoveredPause@GameObj@@QAEXXZ", + "GameObj::removeChildrenFromObjList": "?removeChildrenFromObjList@GameObj@@QAEXPAU1@@Z", + "GameObj::removeFromObjList": "?removeFromObjList@GameObj@@QAEXPAU1@@Z", + "GameObj::setParent": "?setParent@GameObj@@QAEXPAU1@@Z", + "GameObj::~GameObj": "??1GameObj@@UAE@XZ", + "PlayerObj::PlayerObj": "??0PlayerObj@@QAE@PAUGameObj@@W4GameObjIndex@@W4GameObjFlags@@@Z", + "RootExecObj::RootExecObj": "??0RootExecObj@@QAE@PAUGameObj@@W4GameObjIndex@@W4GameObjFlags@@@Z", + "RootExecObj::`scalar_deleting_destructor'": "??_GRootExecObj@@UAEPAXI@Z", + "RootExecObj::~RootExecObj": "??1RootExecObj@@UAE@XZ", + "removeFromObjListByIndex": "?removeFromObjListByIndex@@YAXW4GameObjIndex@@@Z" } }, { @@ -39,9 +127,75 @@ "source_path": "src/JSRF/GameData.cpp" }, "symbol_mappings": { - "?finalizeGameData@@YAXXZ": "_$E2", - "?initGameData@@YGXXZ": "_$E1" + "GameData::GameData": "??0GameData@@QAE@XZ", + "GameData::`scalar_deleting_destructor'": "??_GGameData@@UAEPAXI@Z", + "GameData::addHighScore": "?addHighScore@GameData@@QAEXIW4TestRunType@@PAUTestRunScore@@@Z", + "GameData::characterUnlocked": "?characterUnlocked@GameData@@QAEHI@Z", + "GameData::checkFlagCondition": "?checkFlagCondition@GameData@@QAEHI@Z", + "GameData::checkFlagConditionUnpacked": "?checkFlagConditionUnpacked@GameData@@QAEHW4FlagList@@I@Z", + "GameData::checkFlagConditions": "?checkFlagConditions@GameData@@QAEHPAII@Z", + "GameData::clearHeldSouls": "?clearHeldSouls@GameData@@QAEXXZ", + "GameData::clearStateFlags": "?clearStateFlags@GameData@@QAEXTFlagListOrPtr@@@Z", + "GameData::countMiscObjectives": "?countMiscObjectives@GameData@@QAEIXZ", + "GameData::decrypt": "?decrypt@GameData@@QAEHPAD@Z", + "GameData::encrypt": "?encrypt@GameData@@QAEXPAD@Z", + "GameData::eventSeen": "?eventSeen@GameData@@QAEHI@Z", + "GameData::getCustomTagSelected": "?getCustomTagSelected@GameData@@QAEHIW4TagSize@@H@Z", + "GameData::getGarageMusic": "?getGarageMusic@GameData@@QAEIXZ", + "GameData::getHeldSoulsInStage": "?getHeldSoulsInStage@GameData@@QAEII@Z", + "GameData::getHighScore": "?getHighScore@GameData@@QAEHIW4TestRunType@@IPAUTestRunScore@@@Z", + "GameData::getMiscObjective": "?getMiscObjective@GameData@@QAEHI@Z", + "GameData::getRumbleEnabled": "?getRumbleEnabled@GameData@@QAEHXZ", + "GameData::getSaveDataSize": "?getSaveDataSize@GameData@@QAEIXZ", + "GameData::getSaveDescription": "?getSaveDescription@GameData@@QAEXPAUSaveDescription@@@Z", + "GameData::getSelectedTag": "?getSelectedTag@GameData@@QAEIIW4TagSize@@H@Z", + "GameData::getSoulCollectedBySize": "?getSoulCollectedBySize@GameData@@QAEHW4TagSize@@I@Z", + "GameData::getSoulCount": "?getSoulCount@GameData@@QAEIXZ", + "GameData::getSoulHeld": "?getSoulHeld@GameData@@QAEHI@Z", + "GameData::getSoulSpawned": "?getSoulSpawned@GameData@@QAEHI@Z", + "GameData::getSpawnPosIndex": "?getSpawnPosIndex@GameData@@QAEIXZ", + "GameData::getTagState": "?getTagState@GameData@@QAEHIIH@Z", + "GameData::getTimer": "?getTimer@GameData@@QAEIW4Timer@@@Z", + "GameData::getTotalSoulsInStage": "?getTotalSoulsInStage@GameData@@QAEII@Z", + "GameData::getVolumeSettings": "?getVolumeSettings@GameData@@QAEXPAM0@Z", + "GameData::incrementChapter": "?incrementChapter@GameData@@QAEXXZ", + "GameData::incrementPlaytime": "?incrementPlaytime@GameData@@QAEXXZ", + "GameData::incrementTimer": "?incrementTimer@GameData@@QAEXW4Timer@@@Z", + "GameData::lockCharacter": "?lockCharacter@GameData@@QAEXI@Z", + "GameData::resetExceptSettings": "?resetExceptSettings@GameData@@QAEXXZ", + "GameData::resetExceptSettingsAndHighScores": "?resetExceptSettingsAndHighScores@GameData@@QAEXXZ", + "GameData::resetExceptSettingsAndSouls": "?resetExceptSettingsAndSouls@GameData@@QAEXXZ", + "GameData::resetSelectedTags": "?resetSelectedTags@GameData@@QAEXXZ", + "GameData::resetTimer": "?resetTimer@GameData@@QAEXW4Timer@@@Z", + "GameData::restoreHeldSouls": "?restoreHeldSouls@GameData@@QAEXXZ", + "GameData::setCustomTagSelected": "?setCustomTagSelected@GameData@@QAEXIW4TagSize@@HH@Z", + "GameData::setEventSeen": "?setEventSeen@GameData@@QAEXI@Z", + "GameData::setGarageMusic": "?setGarageMusic@GameData@@QAEXI@Z", + "GameData::setMiscObjective": "?setMiscObjective@GameData@@QAEXI@Z", + "GameData::setMissionDigits34": "?setMissionDigits34@GameData@@QAEXI@Z", + "GameData::setRumbleEnabled": "?setRumbleEnabled@GameData@@QAEXH@Z", + "GameData::setSelectedTag": "?setSelectedTag@GameData@@QAEXIW4TagSize@@IH@Z", + "GameData::setSoulCollected": "?setSoulCollected@GameData@@QAEXI@Z", + "GameData::setSoulSpawned": "?setSoulSpawned@GameData@@QAEXI@Z", + "GameData::setSpawnPosIndex": "?setSpawnPosIndex@GameData@@QAEXI@Z", + "GameData::setTagCovered": "?setTagCovered@GameData@@QAEXIIHI@Z", + "GameData::setTagState": "?setTagState@GameData@@QAEXIIHI@Z", + "GameData::setTimer": "?setTimer@GameData@@QAEXW4Timer@@I@Z", + "GameData::setUnusedBitfield": "?setUnusedBitfield@GameData@@QAEXI@Z", + "GameData::setUnusedPerStageBitmask": "?setUnusedPerStageBitmask@GameData@@QAEXII@Z", + "GameData::setVolumeSettings": "?setVolumeSettings@GameData@@QAEXMM@Z", + "GameData::soulSpawnedUncollected": "?soulSpawnedUncollected@GameData@@QAEHI@Z", + "GameData::stash": "?stash@GameData@@QAEXXZ", + "GameData::stashRestore": "?stashRestore@GameData@@QAEXXZ", + "GameData::stashRestoreExceptHighScores": "?stashRestoreExceptHighScores@GameData@@QAEXXZ", + "GameData::stashRestoreExceptSpecialFlags": "?stashRestoreExceptSpecialFlags@GameData@@QAEXXZ", + "GameData::unlockCharacter": "?unlockCharacter@GameData@@QAEXI@Z", + "GameData::writeStateFlag": "?writeStateFlag@GameData@@QAEXI@Z", + "GameData::writeStateFlagUnpacked": "?writeStateFlagUnpacked@GameData@@QAEXW4FlagList@@II@Z", + "GameData::writeStateFlags": "?writeStateFlags@GameData@@QAEXPAII@Z", + "finalizeGameData": "_$E2", + "initGameData": "_$E1" } } ] -} +} \ No newline at end of file diff --git a/decompile/src/JSRF/Core.cpp b/decompile/src/JSRF/Core.cpp index 6c0ca96..3a5415c 100644 --- a/decompile/src/JSRF/Core.cpp +++ b/decompile/src/JSRF/Core.cpp @@ -196,7 +196,7 @@ void GameObj::removeChildrenFromObjList(GameObj * firstChild) { // Address: 0x00011C80 // Matching: yes -void GameObj::drawDefault(unsigned unknown) {} +void GameObj::drawDefault(int unknown) {} // Address: 0x00011C90 // Matching: yes @@ -212,7 +212,7 @@ void GameObj::execEvent() {} void GameObj::postExecEvent() {} // Eliminated by link time code generation (aliased with 0x00011C80) -void GameObj::drawEvent(unsigned unknown) {} +void GameObj::drawEvent(int unknown) {} // Eliminated by link time code generation (aliased with 0x00011C90) void GameObj::execCoveredPause() {} @@ -221,7 +221,7 @@ void GameObj::execCoveredPause() {} void GameObj::postExecCoveredPause() {} // Eliminated by link time code generation (aliased with 0x00011C80) -void GameObj::drawCoveredPause(unsigned unknown) {} +void GameObj::drawCoveredPause(int unknown) {} // Eliminated by link time code generation (aliased with 0x00011C90) void GameObj::execFreezeCam() {} @@ -230,7 +230,7 @@ void GameObj::execFreezeCam() {} void GameObj::postExecFreezeCam() {} // Eliminated by link time code generation (aliased with 0x00011C80) -void GameObj::drawFreezeCam(unsigned unknown) {} +void GameObj::drawFreezeCam(int unknown) {} // Eliminated by link time code generation (aliased with 0x00011C90) void GameObj::execUncoveredPause() {} @@ -239,7 +239,7 @@ void GameObj::execUncoveredPause() {} void GameObj::postExecUncoveredPause() {} // Eliminated by link time code generation (aliased with 0x00011C80) -void GameObj::drawUncoveredPause(unsigned unknown) {} +void GameObj::drawUncoveredPause(int unknown) {} // Address: 0x00011CA0 // Matching: no @@ -336,7 +336,7 @@ void Game::exec() { // Address: 0x00012580 // Matching: no -void Game::drawObj(GameObj * obj, unsigned unknown) { +void Game::drawObj(GameObj * obj, int unknown) { } // Address: 0x000125E0 @@ -510,7 +510,7 @@ void Game::appendToDrawPriorityList(GameObj * obj) { // Address: 0x00012A20 // Matching: no -void Game::sortDrawPriorityListSingleLevel(unsigned char sortKeyBitOffset) { +void Game::sortDrawPriorityListSingleLevel(char sortKeyBitOffset) { for ( unsigned i = 0; i < sizeof this->drawPriorityListsByKeyHeads/sizeof *this->drawPriorityListsByKeyHeads; diff --git a/decompile/src/JSRF/Core.hpp b/decompile/src/JSRF/Core.hpp index 7d4f490..b876b63 100644 --- a/decompile/src/JSRF/Core.hpp +++ b/decompile/src/JSRF/Core.hpp @@ -146,23 +146,23 @@ struct GameObj { // frame. virtual void execDefault(); virtual void postExecDefault(); - virtual void drawDefault(unsigned); + virtual void drawDefault(int); virtual void execEvent(); virtual void postExecEvent(); - virtual void drawEvent(unsigned); + virtual void drawEvent(int); virtual void execCoveredPause(); virtual void postExecCoveredPause(); - virtual void drawCoveredPause(unsigned); + virtual void drawCoveredPause(int); virtual void execFreezeCam(); virtual void postExecFreezeCam(); - virtual void drawFreezeCam(unsigned); + virtual void drawFreezeCam(int); virtual void execUncoveredPause(); virtual void postExecUncoveredPause(); - virtual void drawUncoveredPause(unsigned); + virtual void drawUncoveredPause(int); void recursivePostExecDefault(); void recursivePostExecEvent(); @@ -297,7 +297,7 @@ struct Game { Game(unsigned *, unsigned); virtual ~Game(); void exec(); - void drawObj(GameObj * obj, unsigned); + void drawObj(GameObj * obj, int); void drawList_( GameObjFlags flagFilterAny1, int drawArg1, @@ -339,7 +339,7 @@ struct Game { void clearDrawPriorityList(); GameObj * getDrawPriorityListHead(); void appendToDrawPriorityList(GameObj * obj); - void sortDrawPriorityListSingleLevel(unsigned char sortKeyBitOffset); + void sortDrawPriorityListSingleLevel(char sortKeyBitOffset); void setFallbackBgColour(D3DCOLOR colour, BOOL useFallback); void initRootExecObj(); diff --git a/ghidra/delink.sh b/ghidra/delink.sh index f374643..9b14b9b 100755 --- a/ghidra/delink.sh +++ b/ghidra/delink.sh @@ -3,21 +3,11 @@ # objects.csv and a Ghidra project via boricj's delinker extension main() { - if \ - [ $# -eq 0 ] &&\ - [ -n "${GHIDRA_HOME-}" ] &&\ - [ -n "${JSRFDECOMP_PROJECTPATH-}" ] &&\ - [ -n "${JSRFDECOMP_PROJECTNAME-}" ] - then - ghidra_path=$GHIDRA_HOME - project_path=$JSRFDECOMP_PROJECTPATH - project_name=$JSRFDECOMP_PROJECTNAME - elif [ $# -eq 3 ]; then - ghidra_path=$1 - project_path=$2 - project_name=$3 - else usage - fi + if [ $# -ne 3 ]; then usage; fi + + ghidra_path=$1 + project_path=$2 + project_name=$3 printf '=== Delinking object files into ../decompile/target/ ===\n' @@ -49,9 +39,6 @@ usage() { ' GHIDRA_PATH is the path to your Ghidra installation'\ ' PROJECT_PATH is the path to your JSRF Ghidra project'\ ' PROJECT_NAME is the name of your JSRF Ghidra project'\ - 'Alternatively, the environment variables $GHIDRA_HOME, $JSRFDECOMP_PROJECTPATH,'\ - 'and $JSRFDECOMP_PROJECTNAME can be set, and the script can be called with no'\ - 'arguments.'\ ''\ 'Populates the target/ directory with delinked object files using the address'\ 'ranges given in objects.csv.' >& 2 diff --git a/ghidra/ghidra_scripts/MSVC7Mangle.java b/ghidra/ghidra_scripts/MSVC7Mangle.java index 13e45b2..4657ef4 100644 --- a/ghidra/ghidra_scripts/MSVC7Mangle.java +++ b/ghidra/ghidra_scripts/MSVC7Mangle.java @@ -107,10 +107,7 @@ public class MSVC7Mangle extends GhidraScript{ final Reference[] refs = ins.getReferencesFrom(); for (int i = 0; i < refs.length; i++) { final Symbol symbol = getSymbolAt(refs[i].getToAddress()); - if ( // Guard against spurious references to nonexisting things - symbol != null && - symbol.getObject() != null - ) mangle(symbol); + if (symbol != null) mangle(symbol); } } } @@ -119,17 +116,13 @@ public class MSVC7Mangle extends GhidraScript{ private void mangle(final Symbol s) throws Exception { /* Set the given symbol's name to its mangled version */ - // Skip if already mangled; skip jump tables - final String name = s.getName(true); - if ( - name.charAt(0) == '?' || - name.startsWith("switchD_") - ) return; + // Skip if already mangled + if (s.getName().charAt(0) == '?') return; // Get mangled name final String mangled = switch (s.getObject()) { case Function f -> mangleFn (f); - case Data d -> mangleData(d, name); + case Data d -> mangleData(d, s.getName(true)); default -> null; }; @@ -152,21 +145,17 @@ public class MSVC7Mangle extends GhidraScript{ private String mangleFn(final Function f) throws Exception { /* Generate a mangled name for a function */ - final String nameRaw = f.getName(true); - - // Special case for main() - if (nameRaw.equals("main")) return "_main"; - - // Special symbols like intrinsics aren't mangled - if (nameRaw.startsWith("__")) return nameRaw; + // Special cases for main() + if (f.getName(true).equals("main" )) return "_main"; + if (f.getName(true).equals("___CxxFrameHandler")) return "___CxxFrameHandler"; final ArrayList dict = new ArrayList<>(); - final List nameParts = Arrays.asList(nameRaw.split("::")); + final List nameParts = Arrays.asList(f.getName(true).split("::")); Collections.reverse(nameParts); final boolean isMethod = f.getCallingConventionName().equals("__thiscall") && nameParts.size() >= 2; - final String name = mangleIdentifier(nameRaw, isMethod, f.getReturnType(), dict); + final String name = mangleIdentifier(f.getName(true), isMethod, f.getReturnType(), dict); // Special methods with unique formats if (isMethod) { @@ -174,16 +163,14 @@ public class MSVC7Mangle extends GhidraScript{ final String clsName = nameParts.get(1); if (unqualified.equals( clsName)) { // Constructor - return "?" + name + "QAE@" + - mangleArgs(f.getSignature(true), dict, nameRaw + "()") + - "Z"; + return "?" + name + "QAE@" + mangleArgs(f.getSignature(true), dict) + "Z"; } else if (unqualified.equals("~" + clsName)) { // Destructor return "?" + name + (isVirtual(f) ? "UAE" : "QAE") + "@XZ"; } } return "?" + name + mangleFnAttrs(f, nameParts) + - mangleFnType(f.getSignature(true), dict, nameRaw + "()"); + mangleFnType(f.getSignature(true), dict); } private static String mangleIdentifier( @@ -285,9 +272,7 @@ public class MSVC7Mangle extends GhidraScript{ final List dict ) { /* Produce a backreference string if x is found in dict */ - if (x instanceof String s && s.startsWith("?")) - return Optional.empty(); // No matching special names - else switch (Integer.valueOf(dict.indexOf(x))) { + switch (Integer.valueOf(dict.indexOf(x))) { case -1: dict.add(x); return Optional.empty(); @@ -318,15 +303,12 @@ public class MSVC7Mangle extends GhidraScript{ final Function func = getFunctionContaining(refs[i].getFromAddress()); if (data != null) { - final Symbol s = getSymbolAt(data.getRoot() - .getAddress()); - if (s != null) { - final String name = s.getName(false); - if ( - name.equals("`vftable'") || - name.startsWith("??_7") - ) return true; - } + final String name = getSymbolAt(data.getRoot() + .getAddress()).getName(false); + if ( + name.equals("`vftable'") || + name.startsWith("??_7") + ) return true; } else if (func != null) { final String name = func.getName(false); if ( @@ -352,13 +334,12 @@ public class MSVC7Mangle extends GhidraScript{ private static String mangleFnType( final FunctionSignature f, - final List dict, - final String loc + final List dict ) throws Exception { /* Mangle everything in f but its name and visibility/linkage */ - return mangleCallC(f) + - mangleType(f.getReturnType(), dict, loc) + - mangleArgs(f, dict, loc) + "Z"; + + return mangleCallC(f) + mangleType(f.getReturnType(), dict) + + mangleArgs(f, dict) + "Z"; } private static String mangleCallC(final FunctionSignature f) throws Exception { @@ -377,16 +358,15 @@ public class MSVC7Mangle extends GhidraScript{ private static String mangleType( final DataType t, - final List dict, - final String loc + final List dict ) throws Exception { /* Mangle a data type in a function name All types are assumed to have no CV qualifiers. */ if (t == null) throw new Exception ( - "A data type at " + loc + " was reported as null. " + - "Ensure that all data types in the code/data to " + - "mangle have been defined." + "A data type was reported as null. Ensure that all " + + "data types in the code/data to mangle have been " + + "defined." ); return switch(t) { @@ -404,7 +384,7 @@ public class MSVC7Mangle extends GhidraScript{ case LongDoubleDataType _ -> "O"; case Pointer p -> "P" + (p.getDataType() instanceof FunctionSignature ? "6" : "A") + - mangleType(p.getDataType(), dict, loc); + mangleType(p.getDataType(), dict); case Union u -> "T" + mangleIdentifier(u.getName(), false, null, dict); case Structure s -> "U" + mangleIdentifier(s.getName(), false, null, dict); case Enum e -> "W4" + mangleIdentifier(e.getName(), false, null, dict); @@ -413,12 +393,12 @@ public class MSVC7Mangle extends GhidraScript{ case UnsignedLongLongDataType _ -> "_K"; case BooleanDataType _ -> "_N"; case WideCharDataType _ -> "_W"; - case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict, loc); - case FunctionSignature f -> mangleFnType(f, dict, "function typedef \"" + f.getName() + "\""); - case TypeDef d -> mangleType(d.getBaseDataType(), dict, "typedef \"" + d.getName() + "\""); - case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined."); - case Undefined _ -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined."); - default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\" at " + loc); + case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict); + case FunctionSignature f -> mangleFnType(f, dict); + case TypeDef d -> mangleType(d.getBaseDataType(), dict); + case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined."); + case Undefined _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined."); + default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\""); }; } @@ -466,8 +446,7 @@ public class MSVC7Mangle extends GhidraScript{ private static String mangleArgs( final FunctionSignature f, - final List dict, - final String loc + final List dict ) throws Exception { /* Mangle the arguments for a function */ final DataType[] args = Arrays.stream(f.getArguments()) @@ -490,15 +469,10 @@ public class MSVC7Mangle extends GhidraScript{ // It turns out that academic-sounding stuff everyone // freaks out at is actually useful (and Optional still // helped us out here) - String mangledArgs = ""; - for (int i = 0; i < args.length; i++) { - final String mangledArg = mangleType(args[i], dict, loc); - - mangledArgs += mangledArg.length() == 1 ? - mangledArg : - backref(args[i], argDict).orElse(mangledArg); - } - return mangledArgs + (f.hasVarArgs() ? "Z" : "@"); + String mangled = ""; + for (int i = 0; i < args.length; i++) + mangled += backref(args[i], argDict).orElse(mangleType(args[i], dict)); + return mangled + (f.hasVarArgs() ? "Z" : "@"); } } @@ -521,8 +495,7 @@ public class MSVC7Mangle extends GhidraScript{ // vtable if (ident.startsWith("?_7")) return "?" + ident + "6B@"; - return "?" + ident + "3" + - mangleType(d.getDataType(), dict, "0x" + d.getAddress().toString()) + + return "?" + ident + "3" + mangleType(d.getDataType(), dict) + "A"; }