Pdb dumpickery

This commit is contained in:
Guus Waals 2025-05-31 00:17:41 +08:00
parent 0187b3943c
commit af2c8c1384
6 changed files with 1087 additions and 58 deletions

Binary file not shown.

View File

@ -13,7 +13,6 @@ function(setup_target TARGET DBG_MODE)
)
if(WIN32 AND R3_32BIT)
target_link_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../third_party/bink)
target_link_libraries(${TARGET} PRIVATE
binkw32
d3d8

1009
java/ghidra/PdbGen.java Normal file

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,8 @@ public class RemanConfig {
public final String rootDir;
// The output directory for the recompiled game
public final String outputDir;
// The output directory for the original game
public final String originalDir;
public final String typeBlacklistPath;
public final String categoryPathBlacklistPath;
public final String functionBlacklistPath;
@ -67,6 +69,8 @@ public class RemanConfig {
rootDir = new File(script.getSourceFile().getAbsolutePath()).getParentFile().getParentFile().getParentFile().toString();
outputDir = new File(rootDir, RECOMPILE_PREFIX).toString();
script.println("Output path: " + outputDir);
originalDir = new File(rootDir, "game").toString();
typeBlacklistPath = new File(outputDir, "type_blacklist.txt").toString();
categoryPathBlacklistPath = new File(outputDir, "type_path_blacklist.txt").toString();

View File

@ -1,19 +1,22 @@
add_subdirectory(spdlog)
if(WIN32)
add_library(binkw32 SHARED IMPORTED)
set_target_properties(binkw32 PROPERTIES
IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/bink/binkw32.lib
add_library(binkw32_imp SHARED IMPORTED)
set_target_properties(binkw32_imp PROPERTIES
IMPORTED_IMPLIB ${CMAKE_CURRENT_LIST_DIR}/bink/binkw32.lib
)
# Copy to output dir
set(BINK_DST ${CMAKE_CURRENT_BINARY_DIR}/bin/binkw32.dll)
set(BINK_DST ${CMAKE_BINARY_DIR}/bin/binkw32.dll)
add_custom_command(
OUTPUT ${BINK_DST}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/third_party/bink/binkw32.dll ${BINK_DST}
)
add_custom_target(copy_binkw32 ALL DEPENDS ${BINK_DST})
add_dependencies(binkw32 copy_binkw32)
add_dependencies(binkw32_imp copy_binkw32)
add_library(binkw32 INTERFACE)
target_link_libraries(binkw32 INTERFACE binkw32_imp)
set(SDK_LIB ${CMAKE_CURRENT_LIST_DIR}/mssdk/lib)

View File

@ -15,11 +15,44 @@ typedef struct {
// Followed by null-terminated PDB path
} RSDS_DEBUG_FORMAT;
typedef struct _IMAGE_OPTIONAL_HEADER6433 {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
ULONGLONG ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
};
class PEModifier {
private:
std::vector<BYTE> fileData;
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeaders;
IMAGE_NT_HEADERS32 *ntHeaders;
IMAGE_SECTION_HEADER *sectionHeaders;
public:
@ -41,10 +74,16 @@ public:
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return false;
ntHeaders = (IMAGE_NT_HEADERS *)(fileData.data() + dosHeader->e_lfanew);
ntHeaders = (IMAGE_NT_HEADERS32 *)(fileData.data() + dosHeader->e_lfanew);
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
return false;
// Verify it's actually a 32-bit PE
if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
printf("Error: This is not a 32-bit PE file!\n");
return false;
}
sectionHeaders =
(IMAGE_SECTION_HEADER *)((BYTE *)&ntHeaders->OptionalHeader +
ntHeaders->FileHeader.SizeOfOptionalHeader);
@ -62,7 +101,7 @@ public:
}
bool addDebugDirectory(const std::string &pdbPath) {
IMAGE_SECTION_HEADER *rsrcSection = findSection(".rsrc");
IMAGE_SECTION_HEADER *rsrcSection = findSection(".rdata");
if (!rsrcSection) {
printf("Error: .rsrc section not found!\n");
return false;
@ -71,28 +110,21 @@ public:
// Calculate debug data size
size_t pdb_path_len = pdbPath.size() + 1;
size_t debug_data_size = sizeof(RSDS_DEBUG_FORMAT) + pdb_path_len;
size_t total_needed = sizeof(IMAGE_DEBUG_DIRECTORY) + debug_data_size + 32; // + padding
// Find end of rsrc section (aligned)
DWORD sectionAlignment = ntHeaders->OptionalHeader.SectionAlignment;
DWORD fileAlignment = ntHeaders->OptionalHeader.FileAlignment;
// Calculate where to place debug data in the rsrc section
DWORD currentSectionEnd =
rsrcSection->PointerToRawData + rsrcSection->SizeOfRawData;
DWORD availableSpace =
rsrcSection->Misc.VirtualSize - rsrcSection->SizeOfRawData;
if (debug_data_size > availableSpace) {
printf("Error: Not enough space in .rsrc section! Need %zu bytes, have "
"%lu\n",
debug_data_size, availableSpace);
// Check if we have enough space at the end of rsrc section
if (total_needed > rsrcSection->SizeOfRawData) {
printf("Error: Not enough space in .rsrc section! Need %zu bytes, section is %lu bytes\n",
total_needed, rsrcSection->SizeOfRawData);
return false;
}
// Calculate RVA for debug data
DWORD debugDataRVA =
rsrcSection->VirtualAddress + rsrcSection->SizeOfRawData;
DWORD debugDataFileOffset = currentSectionEnd;
// Calculate where to place debug directory and data (at the very end of rsrc section)
DWORD debugDirFileOffset = rsrcSection->PointerToRawData + rsrcSection->SizeOfRawData - total_needed;
DWORD debugDataFileOffset = debugDirFileOffset + sizeof(IMAGE_DEBUG_DIRECTORY);
DWORD debugDirRVA = rsrcSection->VirtualAddress + rsrcSection->SizeOfRawData - total_needed;
DWORD debugDataRVA = debugDirRVA + sizeof(IMAGE_DEBUG_DIRECTORY);
// Prepare debug data
std::vector<BYTE> debugData(debug_data_size);
@ -113,19 +145,7 @@ public:
memcpy(debugData.data() + sizeof(RSDS_DEBUG_FORMAT), pdbPath.c_str(),
pdb_path_len);
// Extend file data if needed
if (debugDataFileOffset + debug_data_size > fileData.size()) {
fileData.resize(debugDataFileOffset + debug_data_size);
}
// Write debug data to rsrc section
memcpy(fileData.data() + debugDataFileOffset, debugData.data(),
debug_data_size);
// Update rsrc section size
rsrcSection->SizeOfRawData += debug_data_size;
// Create/update debug directory entry
// Create debug directory entry
IMAGE_DEBUG_DIRECTORY debugDir = {0};
debugDir.Characteristics = 0x00000000;
debugDir.TimeDateStamp = ntHeaders->FileHeader.TimeDateStamp;
@ -136,32 +156,26 @@ public:
debugDir.AddressOfRawData = debugDataRVA;
debugDir.PointerToRawData = debugDataFileOffset;
// Update debug directory in optional header
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]
.VirtualAddress = debugDataRVA;
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size =
sizeof(IMAGE_DEBUG_DIRECTORY);
// Actually, we need to place the debug directory entry somewhere too
// Let's put it right before the debug data
DWORD debugDirRVA = debugDataRVA - sizeof(IMAGE_DEBUG_DIRECTORY);
DWORD debugDirFileOffset =
debugDataFileOffset - sizeof(IMAGE_DEBUG_DIRECTORY);
// Adjust our calculations
rsrcSection->SizeOfRawData += sizeof(IMAGE_DEBUG_DIRECTORY);
// Write debug directory entry
// Overwrite the end of rsrc section with debug directory entry
memcpy(fileData.data() + debugDirFileOffset, &debugDir,
sizeof(IMAGE_DEBUG_DIRECTORY));
// Overwrite with debug data
memcpy(fileData.data() + debugDataFileOffset, debugData.data(),
debug_data_size);
// Update optional header to point to debug directory
printf("IMAGE_DIRECTORY_ENTRY_DEBUG constant value: %d\n", IMAGE_DIRECTORY_ENTRY_DEBUG);
printf("Setting debug directory at index %d\n", IMAGE_DIRECTORY_ENTRY_DEBUG);
printf("Debug directory RVA: 0x%08X\n", debugDirRVA);
printf("Debug directory size: %d\n", sizeof(IMAGE_DEBUG_DIRECTORY));
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]
.VirtualAddress = debugDirRVA;
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size =
sizeof(IMAGE_DEBUG_DIRECTORY);
printf("Debug directory added at RVA: 0x%08X\n", debugDirRVA);
printf("Debug directory added at RVA: 0x%08X (overwriting rsrc end)\n", debugDirRVA);
printf("Debug data added at RVA: 0x%08X\n", debugDataRVA);
return true;
@ -206,7 +220,7 @@ int main(int argc, char **argv) {
}
// Save modified PE
std::string outputPath = std::string(exePath) + ".debug";
std::string outputPath = std::string(exePath);
if (!pe.savePE(outputPath.c_str())) {
printf("Error: Failed to save modified PE file\n");
return 1;