facebook / redex

A bytecode optimizer for Android apps
https://fbredex.com/
MIT License
6.03k stars 653 forks source link

Is there any advice to recover crash stack trace line number in android firebase platform after use "StripDebugInfoPass"? #818

Closed pidanxiangjiao closed 9 months ago

thezhangwei commented 9 months ago

@agampe Hey any comment on this one?

agampe commented 9 months ago

Unlikely, you should have considered the likelihood of your APK being broken before shipping an APK without debug info.

Redex is deterministic. You can try to recompile the exact source for the crashing APK, disabling the strip pass, then look at the output. If the dex bytecode is the same, you have a starting point.

If the Android version this is crashing on is new enough, in the absence of debug information the Android Runtime will print bytecode offsets. If method names are unique, or if you have multiple but only one has said offset be an instruction, then you can map back.


In general, how about you try IODI? We do not have good documentation, but there's tests that show the config, e.g., here.

When you output with IODI, debug info is indirected and shared between buckets of methods. The Play Console won't be very helpful, you will have to use the symbolicator provided with Redex to use the stack, APK and debug metadata from build time to get things like line numbers.

pidanxiangjiao commented 4 months ago

Hello there @agampe , current i use iodi2 for debug_info_kind and try to recover the stack trace with "redex/tools/python/symbolicator/symbolicator.py". i find the line number is a little bit after the right place which cause crash.

Am i config right? or iodi2 debug info could be inaccurate in some cases?

the config i use:

  "redex": {
    "passes": [
      "RegAllocPass",
      "ReduceGotosPass"
    ]
  },
    "StripDebugInfoPass": {
    "drop_all_dbg_info": false,
    "drop_local_variables": true,
    "drop_line_numbers": false,
    "drop_src_files": false,
    "use_allowlist": false,
    "cls_allowlist": [

    ],
    "drop_synth_aggressive": false,
    "drop_synth_conservative": true,
    "method_allowlist": [

    ],
    "drop_prologue_end": true,
    "drop_epilogue_begin": true,
    "drop_all_dbg_info_if_empty": true
  },
  "debug_info_kind": "iodi2",

the correct stack :

java.lang.NullPointerException: Attempt to invoke interface method 'xxx.save(java.lang.Object)' on a null object reference
at xxx.save(Utils.java:969) <-- correct place
at xxx.Utils.lambda$xxx$1(Utils.java:263) <-- correct place
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)

inaccurate stack trace i recovered is below, and i saw some weired string like "1a1c664416c38a8f31a661730f9fc0ba1e9f297230aed0cd05f2de4cd4225afa$0.run$bridge", there is no such string when i recover the stack with r8retrace from aab that is not be redexed.

java.lang.NullPointerException: Attempt to invoke interface method 'xxx.save(java.lang.Object)' on a null object reference
    at xxx.Utils.save(Utils.java:971) <-- the line num is after the right place
    at xxxx.Utils.lambda$xxx$1(Utils.java:269) <-- the line num is after the right place
    at xxx.Utils$$InternalSyntheticLambda$1$1a1c664416c38a8f31a661730f9fc0ba1e9f297230aed0cd05f2de4cd4225afa$0.run$bridge(Utils$$InternalSyntheticLambda$1$1a1c664416c38a8f31a661730f9fc0ba1e9f297230aed0cd05f2de4cd4225afa.java:56)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
    at java.lang.Thread.run(Thread.java:1012)