Complete delink workflow; separate from decomp

We can now create a fresh Ghidra project, import the JSRF executable
into it, import symbols into it, delink object files from it, and then
decompile with objdiff.  Just needs some documentation.
This commit is contained in:
KeybadeBlox 2025-12-16 22:30:49 -05:00
parent 87c56f01d6
commit 1a48d4323e
17 changed files with 1178 additions and 8 deletions

69
delink/delink.sh Executable file
View file

@ -0,0 +1,69 @@
#!/bin/sh -eu
# Script to produce delinked object files in decompile/target/ directory from
# objects.csv and a Ghidra project via boricj's delinker extension
main() {
if [ $# -ne 3 ]; then usage; fi
ghidra_path=$1
project_path=$2
project_name=$3
printf '=== Delinking object files ===\n'
while IFS= read -r line; do # Read objects.csv line by line
# Split columns (col 1 in $1, col 2 in $2, etc.)
set -f; IFS_PREV=$IFS; IFS=,
set -- $line
set +f; IFS=$IFS_PREV
if [ "$2" == true ]; then # If object is marked for extraction
object_name=$1
printf '\n--- %s ---\n' "$object_name"
# Delete object name and delink toggle positional
# arguments, leaving only address ranges
shift 2
# Call Ghidra delinker script
delink "$ghidra_path" "$project_path" "$project_name" "$*" "$object_name"
fi
done < objects.csv
}
usage() {
printf '%s\n'\
'Usage: delink.sh GHIDRA_PATH PROJECT_PATH PROJECT_NAME'\
' 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'\
''\
'Populates the target/ directory with delinked object files using the address'\
'ranges given in objects.csv.' >& 2
exit 2
}
delink() {
# Invoke headless Ghidra with the delinker script to produce an object file
# $1: Ghidra installation path
# $2: Ghidra project path
# $3: Ghidra project name
# $4: Whitespace-separated address ranges to include in object
# $5: Output path (inside /target)
# Call the right script depending on whether we're on Windows
# (this seems like the most reliable method I can find for POSIX sh)
if [ -n "$WINDIR" ]; then suffix=.bat
else suffix=
fi
"$1/support/analyzeHeadless$suffix" "$2" "$3"\
-process default.xbe\
-noanalysis\
-postScript DelinkProgram.java\
/exporter 'COFF relocatable object'\
$(printf "/include-range %s " $4)\
/export "../decompile/target/$5"
}
main "$@"

42
delink/make_symboltable.sh Executable file
View file

@ -0,0 +1,42 @@
#!/bin/sh -eu
# Script to convert Ghidra symbol table CSV export data to the format used by
# the Ghidra script ImportSymbolsScript.py
main() {
if [ $# -ne 1 ]; then usage; fi
printf 'Writing symbol table to symboltable.tsv...'
>symboltable.tsv # Create/truncate output file
while IFS=, read -r name location type; do # Iterate over rows
# Determine symbol type (skip if unrecognized, e.g. header row)
if [ "$type" == '"Function"' ]; then type_out=f
elif [ "$type" == '"Data Label"' ]; then type_out=l
else continue
fi
# Strip quotes from other columns
name_out=${name#'"'} ; name_out=${name_out%'"'}
location_out=${location#'"'}; location_out=${location_out%'"'}
# Output row
printf '%s\t%s\t%s\n' "$name_out" "$location_out" "$type_out"\
>> symboltable.tsv
done < $1
printf ' done.\n'
}
usage() {
printf '%s\n'\
'Usage: make_symboltable.sh CSVFILE'\
' CSVFILE is the path of a symbol table CSV from Ghidra'\
''\
'The CSV file should have columns Name, Location, and Type. The output file'\
'will be named "symboltable.tsv".' >&2
exit 2
}
main "$@"

14
delink/objects.csv Normal file
View file

@ -0,0 +1,14 @@
Object,Delink?,.text,.text$x,D3D,DSOUND,MMATRIX,XGRPH,XPP,.rdata,.rdata$x,.data,DOLBY
Core.obj,false,0x00011000-0x00013FF0,0x00186BA0-0x00186C1F,,,,,,0x001C4390-0x001C44FF,0x001E4D20-0x001E4DAB,0x00251D40-0x00251DAB,
Jet2.obj,true,0x0006F9E0-0x0006FA6F,0x00187710-0x00187724,,,,,,,0x001E620C-0x001E622F,0x0022FCE0-0x0022FCE7,
ADX (need to decompose),false,0x0013A570-0x0014555F,?,,,,,,?,?,?,
XDK Core (need to decompose),false,0x00145560-0x0014B79F,?,,,,,,?,?,?,
Smilebit libs (need to decompose),false,0x0014B7A0-0x0017BF3F,?,,,,,,?,?,?-0x0022ED2B,
C runtime,false,0x0017BF40-0x00182B80,?,,,,,,?,?,0x0022ED2C-?,
Unknown MS math lib,false,0x00182B81-0x0018694F,?,,,,,,?,?,?,
Another (tiny) Smilebit math lib,false,0x00186950-0x00186B7F,?,,,,,,?,?,?,
Direct3D8 (need to decompose),false,,,0x0018CB40-0x0019E334,,,,,?,?,?,
DirectSound8 (need to decompose),false,,,,0x0019E340-0x001BA89B,,,,?,?,?,0x0027E080-0x00284E17
MMatrix.obj,false,,,,,0x001BA8A0-0x001BBAAF,,,,,0x00264BD8-0x00264C13,
Xgraphics (need to decompose),false,,,,,,0x001BBAC0-0x001BC7BB,,,,,
XDK Peripherals,false,,,,,,,0x001BC7C0-0x001C3F57,,,,
1 Object Delink? .text .text$x D3D DSOUND MMATRIX XGRPH XPP .rdata .rdata$x .data DOLBY
2 Core.obj false 0x00011000-0x00013FF0 0x00186BA0-0x00186C1F 0x001C4390-0x001C44FF 0x001E4D20-0x001E4DAB 0x00251D40-0x00251DAB
3 Jet2.obj true 0x0006F9E0-0x0006FA6F 0x00187710-0x00187724 0x001E620C-0x001E622F 0x0022FCE0-0x0022FCE7
4 ADX (need to decompose) false 0x0013A570-0x0014555F ? ? ? ?
5 XDK Core (need to decompose) false 0x00145560-0x0014B79F ? ? ? ?
6 Smilebit libs (need to decompose) false 0x0014B7A0-0x0017BF3F ? ? ? ?-0x0022ED2B
7 C runtime false 0x0017BF40-0x00182B80 ? ? ? 0x0022ED2C-?
8 Unknown MS math lib false 0x00182B81-0x0018694F ? ? ? ?
9 Another (tiny) Smilebit math lib false 0x00186950-0x00186B7F ? ? ? ?
10 Direct3D8 (need to decompose) false 0x0018CB40-0x0019E334 ? ? ?
11 DirectSound8 (need to decompose) false 0x0019E340-0x001BA89B ? ? ? 0x0027E080-0x00284E17
12 MMatrix.obj false 0x001BA8A0-0x001BBAAF 0x00264BD8-0x00264C13
13 Xgraphics (need to decompose) false 0x001BBAC0-0x001BC7BB
14 XDK Peripherals false 0x001BC7C0-0x001C3F57

1127
delink/symboltable.tsv Normal file

File diff suppressed because it is too large Load diff