linux32/steamclient.so is the 32-bit build games load via ~/.steam/sdk32. tools/decompile_batch.sh batches many binaries per Ghidra JVM for the Steam runtimes, mirroring their paths under decomp/runtime/. Co-Authored-By: Claude Opus 5.5 <[email protected]>
50 lines
2.1 KiB
Bash
Executable File
50 lines
2.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Batch-decompile many binaries listed in a file (paths under client/), several
|
|
# per Ghidra JVM and several JVMs in parallel. Output mirrors the path under
|
|
# client/, e.g. client/runtime/x/lib/libc.so.6 -> decomp/runtime/x/lib/libc.so.6/.
|
|
# Ghidra databases are not kept (-readOnly), and binaries whose output already
|
|
# exists are skipped, so re-running resumes. Chunks that die (e.g. OOM) are
|
|
# retried one binary per JVM at the end.
|
|
# Usage: tools/decompile_batch.sh <list-file>
|
|
# Knobs: CHUNK (binaries per JVM, 40), PARALLEL (JVMs at once, 4), plus the
|
|
# per-JVM WORKERS / GHIDRA_HEADLESS_MAXMEM / MEMLIMIT from ghidra-env.sh.
|
|
set -uo pipefail
|
|
source "$(dirname "$0")/ghidra-env.sh"
|
|
LIST="$1"
|
|
CHUNK="${CHUNK:-40}" PARALLEL="${PARALLEL:-4}"
|
|
TAG="$(basename "$LIST" .txt)"
|
|
WORK="$ROOT/decomp/logs/batch_$TAG"
|
|
mkdir -p "$WORK"
|
|
|
|
pending() {
|
|
while read -r bin; do
|
|
[ -n "$bin" ] && [ ! -f "$ROOT/decomp/${bin#client/}/functions.tsv" ] && echo "$bin"
|
|
done < "$LIST"
|
|
}
|
|
|
|
run_chunk() { # $1 = chunk file
|
|
local name; name="batch_${TAG}_$(basename "$1")"
|
|
mapfile -t bins < "$1"
|
|
run_headless "$ROOT/ghidra_projects" "$name" \
|
|
-import "${bins[@]/#/$ROOT/}" -readOnly -deleteProject \
|
|
-scriptPath "$ROOT/tools/ghidra" \
|
|
-preScript SetAnalysisOptions.java "${ANALYSIS_OPTS:-GCC Exception Handlers=false}" \
|
|
-postScript RecoverClassesFromRTTIScript.java \
|
|
-postScript RecoverNamesFromStrings.java \
|
|
-postScript ExportDecompiled.java "$ROOT/decomp" "$ROOT/client" \
|
|
-analysisTimeoutPerFile 86400 \
|
|
-log "$WORK/$(basename "$1").log" > "$WORK/$(basename "$1").out" 2>&1
|
|
echo "$(basename "$1") rc=$? $(date +%T)" >> "$WORK/chunks.log"
|
|
}
|
|
export -f run_chunk run_headless
|
|
export ROOT GHIDRA WORK TAG MEMLIMIT
|
|
|
|
for pass in batch single; do
|
|
rm -f "$WORK"/list_*
|
|
[ "$pass" = single ] && CHUNK=1 PARALLEL=1
|
|
pending | split -l "$CHUNK" -d -a 5 - "$WORK/list_${pass}_"
|
|
ls "$WORK"/list_* >/dev/null 2>&1 || break
|
|
ls "$WORK"/list_* | xargs -P "$PARALLEL" -I{} bash -c 'run_chunk "$1"' _ {}
|
|
done
|
|
echo "$TAG: $(pending | wc -l) binaries still without output" | tee -a "$WORK/chunks.log"
|