ApplicationExitInfo.getTraceInputStream() is often null for REASON_CRASH; install an early uncaught-exception handler and attach that local log on the recovery gate. Co-authored-by: Cursor <cursoragent@cursor.com>
102 lines
3.9 KiB
Bash
Executable file
102 lines
3.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
SRC_GATE="${ROOT_DIR}/sources/java/com/mycompany/app/web/CrashExitGate.java"
|
|
SRC_ACTIVITY="${ROOT_DIR}/sources/java/com/mycompany/app/web/CrashRecoveryActivity.java"
|
|
SRC_PROVIDER="${ROOT_DIR}/sources/java/com/mycompany/app/web/CrashGateInitProvider.java"
|
|
OUT_SMALI="${ROOT_DIR}/app/smali_classes3/com/mycompany/app/web"
|
|
TOOLS="${ROOT_DIR}/tools"
|
|
ANDROID_HOME="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-${HOME}/android-sdk}}"
|
|
ANDROID_JAR="$(ls -1 "${ANDROID_HOME}/platforms"/android-*/android.jar 2>/dev/null | sort -V | tail -1)"
|
|
D8="$(find "${ANDROID_HOME}/build-tools" -name d8 -type f 2>/dev/null | sort -V | tail -1)"
|
|
APK="$(ls -1 "${ROOT_DIR}/dist"/soul-browser-*-merged-unsigned.apk 2>/dev/null | sort | tail -1 || true)"
|
|
if [[ -z "${APK}" || ! -f "${APK}" ]]; then
|
|
APK="$(ls -1 "${ROOT_DIR}/../soul-browser/dist"/soul-browser-*-merged-unsigned.apk 2>/dev/null | sort | tail -1 || true)"
|
|
fi
|
|
DEX_TOOLS_ZIP="${TOOLS}/dex-tools-v2.4.zip"
|
|
DEX_TOOLS_DIR="${TOOLS}/dex-tools-v2.4"
|
|
|
|
mkdir -p "${TOOLS}" "${OUT_SMALI}"
|
|
|
|
if [[ ! -f "${ANDROID_JAR}" ]]; then
|
|
echo "error: android.jar not found" >&2
|
|
exit 1
|
|
fi
|
|
if [[ -z "${D8}" ]]; then
|
|
echo "error: d8 not found" >&2
|
|
exit 1
|
|
fi
|
|
if [[ -z "${APK}" || ! -f "${APK}" ]]; then
|
|
echo "error: merged unsigned APK not found; run ./scripts/build.sh first" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "${DEX_TOOLS_DIR}/d2j-dex2jar.sh" ]]; then
|
|
if [[ ! -f "${DEX_TOOLS_ZIP}" ]]; then
|
|
echo "Downloading dex-tools v2.4..."
|
|
curl -fsSL -o "${DEX_TOOLS_ZIP}" \
|
|
"https://github.com/pxb1988/dex2jar/releases/download/v2.4/dex-tools-v2.4.zip"
|
|
fi
|
|
unzip -qo "${DEX_TOOLS_ZIP}" -d "${TOOLS}"
|
|
fi
|
|
D2J="${DEX_TOOLS_DIR}/d2j-dex2jar.sh"
|
|
chmod +x "${DEX_TOOLS_DIR}/"*.sh "${DEX_TOOLS_DIR}/d2j_invoke.sh"
|
|
|
|
STAGE="$(mktemp -d)"
|
|
cleanup() { rm -rf "${STAGE}"; }
|
|
trap cleanup EXIT
|
|
|
|
echo "Building classpath from APK dex files..."
|
|
CP="${ANDROID_JAR}"
|
|
for dex in classes.dex classes2.dex classes3.dex classes4.dex; do
|
|
unzip -p "${APK}" "${dex}" > "${STAGE}/${dex}" 2>/dev/null || true
|
|
if [[ -s "${STAGE}/${dex}" ]]; then
|
|
jar="${STAGE}/${dex%.dex}.jar"
|
|
bash "${D2J}" --force "${STAGE}/${dex}" -o "${jar}" >/dev/null
|
|
CP="${CP}:${jar}"
|
|
fi
|
|
done
|
|
|
|
echo "Compiling crash recovery sources..."
|
|
javac --release 11 -classpath "${CP}" -d "${STAGE}/classes" "${SRC_GATE}" "${SRC_ACTIVITY}" "${SRC_PROVIDER}"
|
|
|
|
echo "Dexing compiled classes..."
|
|
mkdir -p "${STAGE}/out"
|
|
mapfile -t CLASS_FILES < <(find "${STAGE}/classes" -name '*.class' -type f)
|
|
("${D8}" --release --lib "${ANDROID_JAR}" --output "${STAGE}/out" "${CLASS_FILES[@]}")
|
|
|
|
echo "Disassembling to smali..."
|
|
bash "${DEX_TOOLS_DIR}/d2j-baksmali.sh" -f -o "${STAGE}/smali" "${STAGE}/out/classes.dex"
|
|
|
|
# d2j-baksmali sometimes emits const/high16 with the high 16 bits only.
|
|
STAGE_SMALI="${STAGE}/smali" python3 - <<'PY'
|
|
import os, pathlib, re
|
|
root = pathlib.Path(os.environ["STAGE_SMALI"])
|
|
pat = re.compile(r"^(?P<pre>\s*const/high16\s+[vp]\d+,\s*)(?P<lit>-?\d+)\s*$")
|
|
for path in root.rglob("*.smali"):
|
|
text = path.read_text()
|
|
out = []
|
|
changed = False
|
|
for line in text.splitlines(True):
|
|
m = pat.match(line.rstrip("\n"))
|
|
if m:
|
|
lit = int(m.group("lit"))
|
|
if lit & 0xFFFF:
|
|
lit = (lit << 16) & 0xFFFFFFFF
|
|
if lit >= 0x80000000:
|
|
lit -= 0x100000000
|
|
line = f"{m.group('pre')}{lit}\n"
|
|
changed = True
|
|
out.append(line)
|
|
if changed:
|
|
path.write_text("".join(out))
|
|
PY
|
|
|
|
find "${STAGE}/smali" -name '*.smali' -print0 | xargs -0 sed -i \
|
|
-e 's/\\u002d\$\$Nest\$/\-$$Nest$/g'
|
|
|
|
cp -a "${STAGE}/smali/com/mycompany/app/web/CrashExitGate"* "${OUT_SMALI}/"
|
|
cp -a "${STAGE}/smali/com/mycompany/app/web/CrashRecoveryActivity"* "${OUT_SMALI}/"
|
|
cp -a "${STAGE}/smali/com/mycompany/app/web/CrashGateInitProvider"* "${OUT_SMALI}/"
|
|
echo "Wrote smali under ${OUT_SMALI}"
|