11

I created a release build of my app with react-native 0.61.2 and enabled Hermes. In my Crashlytics I receive information about crashes along with stacktraces. Perviously I used to apply apktool to extract index.android.bundle from my apk, and it contained js code where I was able to find the issue by stacktrace.

But now using Hermes index.android.bundle seems to contain bytecode rather than js and I wasted a day trying to disassemble it. The last thing I tried was hbcdump tool mentioned in https://github.com/facebook/hermes/blob/master/doc/BuildingAndRunning.md, but all I get is "Error: fail to deserializing bytecode: Wrong bytecode version. Expected 73 but got 62"

What should I do to disassemble index.android.bundle created with Hermes? Any help is highly appreciated!

Ksenia
  • 351
  • 5
  • 10
  • You can disassemble your file by checking out the v0.2.1 release tag, but it will not do you any good. The output is bytecode assembly code, not JavaScript. What is the stack trace data you have? – that other guy Jan 07 '20 at 02:57

1 Answers1

4

Edit: As of Hermes v0.5.0, there's also a hermes-engine-cli NPM that contains a bytecode disassembler. It is only compatible with the corresponding hermes-engine version (i.e. hermes-engine-cli@0.5.0 works with hermes-engine@0.5.0).

It's still primarily useful for compiler developers, and not for debugging app crashes.


Hermes tools are not backwards compatible, so you need to check out the correct version first. For bytecode version 62, you can checkout the the v0.2.1 release with git checkout v0.2.1. For arbitrary bytecode versions, git log -p include/hermes/BCGen/HBC/BytecodeFileFormat.h will show which commits updated the format to which versions.

Once built, you can use hbcdump myfile.hbc followed by disassemble at the prompt to show a disabled version of the file.

Be aware that hbcdump is intended for developing/debugging compilers, in the same vein as javap -c and objdump -d. Here's the kind of output you can expect:

Function<fizzbuzz>1(1 params, 22 registers, 0 symbols):
Offset in debug table: src 0xd, vars 0x0
fizzbuzz.js[1:21]
    LoadConstZero     r11
    LoadConstUInt8    r10, 15
    LoadConstUInt8    r9, 3
    LoadConstString   r8, "Fizzbuzz"
    LoadConstString   r7, "Fizz"
    LoadConstString   r6, "Buzz"
    GetGlobalObject   r5
    LoadConstUndefined r0
    LoadConstUInt8    r4, 1
    LoadConstUInt8    r3, 100
    LoadConstUInt8    r2, 5
    LoadConstZero     r1
L2:
fizzbuzz.js[1:21]
    Mod               r12, r1, r10
    Mov               r13, r8
    JStrictEqual      L1, r12, r11
    Mod               r12, r1, r9
    Mov               r13, r7
    JStrictEqual      L1, r12, r11
    Mod               r12, r1, r2
    Mov               r13, r6
    JStrictEqual      L1, r12, r11
    AddEmptyString    r13, r1
L1:
fizzbuzz.js[8:5]
    TryGetById        r12, r5, 1, "print"
    Call2             r12, r12, r0, r13
    AddN              r1, r1, r4
    JLessN            L2, r1, r3
    Ret               r0
that other guy
  • 116,971
  • 11
  • 170
  • 194
  • 1
    @ksenia, is it resolved? i am also facing the same issue. – nitwatar Apr 27 '20 at 10:22
  • What is the output? Everybody says it's bytecode, but what does that mean? Is it java bytecode or some custom bytecode that only runs in the Hermes vm? How can I decompile it to something more readable? –  Jun 25 '21 at 10:26
  • It is a custom Hermes bytecode that only runs in the Hermes vm (this is normal for JSVMs: V8 and JSC also has their own custom internal bytecode). There are currently no tools that attempt to reconstruct human readable JS from Hermes bytecode. – that other guy Jun 25 '21 at 16:04