android-ndk开发(6): 查看反汇编

android-ndk开发(6): 查看反汇编

2025/05/05

1. 概要

android-ndk 是基于 clang 的工具链, clang 则保持了和 gcc 的高度兼容。 在 Linux 开发机上, GCC 套件里的 objdump 提供了反汇编的功能。 实际上 android-ndk 也提供了一份 objdump, 用它可以反汇编 android 平台的二进制文件。

使用调试器带来的交互式体验, 在 android-ndk 这一交叉编译 - 连接到设备上运行和调试的场景下, 卡顿感比较明显; 相比之下, 查看反汇编代码来辅助 crash 分析, 是 android-ndk 开发过程中会使用到的一个技能。 不求精通汇编, 反正可以问 AI; 而具备查看反汇编的思维则显得更加重要。

2. 查看反汇编

2.1 查看可执行文件的反汇编

还记得上一篇我们搭建的 hello-world 工程吗?

#include <stdio.h>
int main() {
    printf("hello, world!\n");
}
#!/bin/bash
NDK=~/soft/android-ndk/r21e
HOST_TAG=darwin-x86_64
$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/clang \
    -target aarch64-linux-android21 hello.c \
    -o hello

adb push hello /data/local/tmp/hello
adb shell "cd /data/local/tmp; chmod +x ./hello; ./hello"

编译后会在当前目录得到 hello 可执行文件。 查看它的反汇编:

/<path/to>/aarch64-linux-android-objdump -d hello

例如我的路径是:

/Users/zz/soft/android-ndk/r21e/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-objdump -d hello

反汇编结果如下:

hello:     file format elf64-littleaarch64


Disassembly of section .plt:

0000000000000560 <printf@plt-0x20>:
 560:   a9bf7bf0    stp x16, x30, [sp,#-16]!
 564:   b0000010    adrp    x16, 1000 <main+0x9d8>
 568:   f947de11    ldr x17, [x16,#4024]
 56c:   913ee210    add x16, x16, #0xfb8
 570:   d61f0220    br  x17
 574:   d503201f    nop
 578:   d503201f    nop
 57c:   d503201f    nop

0000000000000580 <printf@plt>:
 580:   b0000010    adrp    x16, 1000 <main+0x9d8>
 584:   f947e211    ldr x17, [x16,#4032]
 588:   913f0210    add x16, x16, #0xfc0
 58c:   d61f0220    br  x17

0000000000000590 <__libc_init@plt>:
 590:   b0000010    adrp    x16, 1000 <main+0x9d8>
 594:   f947e611    ldr x17, [x16,#4040]
 598:   913f2210    add x16, x16, #0xfc8
 59c:   d61f0220    br  x17

00000000000005a0 <__cxa_atexit@plt>:
 5a0:   b0000010    adrp    x16, 1000 <main+0x9d8>
 5a4:   f947ea11    ldr x17, [x16,#4048]
 5a8:   913f4210    add x16, x16, #0xfd0
 5ac:   d61f0220    br  x17

Disassembly of section .text:

00000000000005b0 <_start>:
 5b0:   910003e0    mov x0, sp
 5b4:   14000001    b   5b8 <_start_main>

00000000000005b8 <_start_main>:
 5b8:   d100c3ff    sub sp, sp, #0x30
 5bc:   a9027bfd    stp x29, x30, [sp,#32]
 5c0:   b0000008    adrp    x8, 1000 <main+0x9d8>
 5c4:   f947f508    ldr x8, [x8,#4072]
 5c8:   b0000009    adrp    x9, 1000 <main+0x9d8>
 5cc:   f947fd29    ldr x9, [x9,#4088]
 5d0:   b000000a    adrp    x10, 1000 <main+0x9d8>
 5d4:   f947f94a    ldr x10, [x10,#4080]
 5d8:   9e670100    fmov    d0, x8
 5dc:   4e181d20    mov v0.d[1], x9
 5e0:   3d8003e0    str q0, [sp]
 5e4:   f9000bea    str x10, [sp,#16]
 5e8:   b0000002    adrp    x2, 1000 <main+0x9d8>
 5ec:   f947f042    ldr x2, [x2,#4064]
 5f0:   910003e3    mov x3, sp
 5f4:   aa1f03e1    mov x1, xzr
 5f8:   910083fd    add x29, sp, #0x20
 5fc:   97ffffe5    bl  590 <__libc_init@plt>

0000000000000600 <__atexit_handler_wrapper>:
 600:   b4000040    cbz x0, 608 <__atexit_handler_wrapper+0x8>
 604:   d61f0000    br  x0
 608:   d65f03c0    ret

000000000000060c <atexit>:
 60c:   90000008    adrp    x8, 0 <note_android_ident-0x218>
 610:   91180108    add x8, x8, #0x600
 614:   d0000002    adrp    x2, 2000 <__bss_start>
 618:   91000042    add x2, x2, #0x0
 61c:   aa0003e1    mov x1, x0
 620:   aa0803e0    mov x0, x8
 624:   17ffffdf    b   5a0 <__cxa_atexit@plt>

0000000000000628 <main>:
 628:   d10083ff    sub sp, sp, #0x20
 62c:   a9017bfd    stp x29, x30, [sp,#16]
 630:   910043fd    add x29, sp, #0x10
 634:   90000000    adrp    x0, 0 <note_android_ident-0x218>
 638:   91197000    add x0, x0, #0x65c
 63c:   52800008    mov w8, #0x0                    // #0
 640:   b81fc3a8    stur    w8, [x29,#-4]
 644:   97ffffcf    bl  580 <printf@plt>
 648:   b85fc3a8    ldur    w8, [x29,#-4]
 64c:   2a0803e0    mov w0, w8
 650:   a9417bfd    ldp x29, x30, [sp,#16]
 654:   910083ff    add sp, sp, #0x20
 658:   d65f03c0    ret

也可以封装为脚本: disassemble.sh:

#!/bin/bash
NDK=~/soft/android-ndk/r21e
HOST_TAG=darwin-x86_64
$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android-objdump -d hello

3.2 查看单个 .c/.cpp 文件的反汇编

对于 hello-world 工程, 可执行文件对应到唯一的源代码文件 hello.c。

对于稍微有点内容的工程, 不止一个源代码文件。 拿我本地的 ncv 工程来说, 有5个源文件:

  • color.c
  • io.c
  • main.c
  • thread.c
  • timer.c

这对应两个事情:

  • 使用 cmake 构建比较方便, 使用纯粹的命令行也行, 但是有点麻烦
  • 查看反汇编时, 分别对每个 .c 对应的 .o 反汇编, 内容比较清晰; 所有文件编译出的可执行文件 test_ncv 的反汇编, 内容太多, 看不过来

我的 CMakeLists.txt 为:

cmake_minimum_required(VERSION 3.10)
project(ncv C)
add_library(ncv STATIC color.c io.c)
add_executable(test_ncv main.c)
target_link_libraries(test_ncv PUBLIC ncv)

对应的 cmake 构建输出, build/CMakeFiles 目录下的文件:

➜  ncv git:(main) ✗ tree build/CMakeFiles
build/CMakeFiles
├── 3.31.6
│             ├── CMakeCCompiler.cmake
│             ├── CMakeDetermineCompilerABI_C.bin
│             └── CMakeSystem.cmake
├── CMakeConfigureLog.yaml
├── TargetDirectories.txt
├── cmake.check_cache
├── ncv.dir
│             ├── color.c.o
│             └── io.c.o
├── pkgRedirects
├── rules.ninja
└── test_ncv.dir
    └── main.c.o

5 directories, 10 files

我们感兴趣的 ncv.dir/color.c.oncv.dir/io.c.o. 他们是库目标 ncv 对应的源代码们, 对应的 .o 文件。

执行反汇编:

/Users/zz/soft/android-ndk/r21e/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-objdump -d build/CMakeFiles/ncv.dir/color.c.o

一些反汇编结果:

Disassembly of section .text.nv21_to_rgb_worker:

0000000000000000 <nv21_to_rgb_worker>:
   0:   a9bf4ff4    stp x20, x19, [sp,#-16]!
   4:   69402408    ldpsw   x8, x9, [x0]
   8:   6b09011f    cmp w8, w9
   c:   540014aa    b.ge    2a0 <nv21_to_rgb_worker+0x2a0>
  10:   f940040a    ldr x10, [x0,#8]
  14:   9000000b    adrp    x11, 0 <nv21_to_rgb_worker>
  18:   9000000c    adrp    x12, 0 <nv21_to_rgb_worker>
  1c:   fd400160    ldr d0, [x11]
  20:   fd400181    ldr d1, [x12]
  24:   a940314b    ldp x11, x12, [x10]
  28:   9000000d    adrp    x13, 0 <nv21_to_rgb_worker>
  2c:   9000000e    adrp    x14, 0 <nv21_to_rgb_worker>
  30:   fd4001a2    ldr d2, [x13]
  34:   fd4001c3    ldr d3, [x14]
  38:   a941396d    ldp x13, x14, [x11,#16]
  3c:   f9400990    ldr x16, [x12,#16]
  40:   69462971    ldpsw   x17, x10, [x11,#48]
  44:   b9803180    ldrsw   x0, [x12,#48]
  48:   b940056b    ldr w11, [x11,#4]
  4c:   9100050f    add x15, x8, #0x1
  50:   9b113501    madd    x1, x8, x17, x13
  54:   d37ffa2c    lsl x12, x17, #1
  58:   9b1135f1    madd    x17, x15, x17, x13
  5c:   910005cd    add x13, x14, #0x1
  60:   9b004102    madd    x2, x8, x0, x16
  64:   d37ff80e    lsl x14, x0, #1
  68:   9b0041e0    madd    x0, x15, x0, x16
  6c:   9100042f    add x15, x1, #0x1
  70:   91000630    add x16, x17, #0x1
  74:   91000851    add x17, x2, #0x2
  78:   91000800    add x0, x0, #0x2
  7c:   52801fe1    mov w1, #0xff                   // #255
  80:   7100057f    cmp w11, #0x1
  84:   5400014a    b.ge    ac <nv21_to_rgb_worker+0xac>
  88:   91000908    add x8, x8, #0x2
  8c:   8b0c01ef    add x15, x15, x12
  90:   8b0c0210    add x16, x16, x12
  94:   8b0e0231    add x17, x17, x14
  98:   eb09011f    cmp x8, x9
  9c:   8b0e0000    add x0, x0, x14
  a0:   5400100a    b.ge    2a0 <nv21_to_rgb_worker+0x2a0>
  a4:   7100057f    cmp w11, #0x1
  a8:   54ffff0b    b.lt    88 <nv21_to_rgb_worker+0x88>
  ac:   93417d02    sbfx    x2, x8, #1, #31
  b0:   9b0a3442    madd    x2, x2, x10, x13
  b4:   aa0003e3    mov x3, x0
  b8:   aa1103e4    mov x4, x17
  bc:   aa1003e5    mov x5, x16
  c0:   aa0f03e6    mov x6, x15
  c4:   2a0b03e7    mov w7, w11
  c8:   385ff053    ldurb   w19, [x2,#-1]
  cc:   3c5ff0c4    ldur    b4, [x6,#-1]
  d0:   38402454    ldrb    w20, [x2],#2
  d4:   510008e7    sub w7, w7, #0x2
  d8:   51020273    sub w19, w19, #0x80
  dc:   1e620265    scvtf   d5, w19
  e0:   7e61d884    ucvtf   d4, d4
  e4:   1e6008a7    fmul    d7, d5, d0
  e8:   1e6428e4    fadd    d4, d7, d4
  ec:   1e780093    fcvtzs  w19, d4
  f0:   7103fe7f    cmp w19, #0xff
  f4:   1a81b273    csel    w19, w19, w1, lt
  f8:   0ab37e73    bic w19, w19, w19, asr #31
  fc:   381fe093    sturb   w19, [x4,#-2]
 100:   3c5ff0c6    ldur    b6, [x6,#-1]
 104:   51020294    sub w20, w20, #0x80
 108:   1e620290    scvtf   d16, w20
 10c:   1e610a04    fmul    d4, d16, d1
 110:   7e61d8c6    ucvtf   d6, d6
 114:   1e6208a5    fmul    d5, d5, d2
 118:   1e6438c6    fsub    d6, d6, d4
 11c:   1e6538c6    fsub    d6, d6, d5
 120:   1e7800d3    fcvtzs  w19, d6
 124:   7103fe7f    cmp w19, #0xff
 128:   1a81b273    csel    w19, w19, w1, lt
 12c:   0ab37e73    bic w19, w19, w19, asr #31
 130:   381ff093    sturb   w19, [x4,#-1]
 134:   3c5ff0d1    ldur    b17, [x6,#-1]
 138:   1e630a06    fmul    d6, d16, d3
 13c:   7e61da30    ucvtf   d16, d17
 140:   1e7028d0    fadd    d16, d6, d16
 144:   1e780213    fcvtzs  w19, d16
 148:   7103fe7f    cmp w19, #0xff
 14c:   1a81b273    csel    w19, w19, w1, lt
 150:   0ab37e73    bic w19, w19, w19, asr #31
 154:   39000093    strb    w19, [x4]
 158:   3d4000d0    ldr b16, [x6]
 15c:   7e61da10    ucvtf   d16, d16
 160:   1e7028f0    fadd    d16, d7, d16
 164:   1e780213    fcvtzs  w19, d16
 168:   7103fe7f    cmp w19, #0xff
 16c:   1a81b273    csel    w19, w19, w1, lt
 170:   0ab37e73    bic w19, w19, w19, asr #31
 174:   39000493    strb    w19, [x4,#1]
 178:   3d4000d0    ldr b16, [x6]
 17c:   7e61da10    ucvtf   d16, d16
 180:   1e643a10    fsub    d16, d16, d4
 184:   1e653a10    fsub    d16, d16, d5
 188:   1e780213    fcvtzs  w19, d16
 18c:   7103fe7f    cmp w19, #0xff
 190:   1a81b273    csel    w19, w19, w1, lt
 194:   0ab37e73    bic w19, w19, w19, asr #31
 198:   39000893    strb    w19, [x4,#2]
 19c:   3d4000d0    ldr b16, [x6]
 1a0:   910008c6    add x6, x6, #0x2
 1a4:   7e61da10    ucvtf   d16, d16
 1a8:   1e7028d0    fadd    d16, d6, d16
 1ac:   1e780213    fcvtzs  w19, d16
 1b0:   7103fe7f    cmp w19, #0xff
 1b4:   1a81b273    csel    w19, w19, w1, lt
 1b8:   0ab37e73    bic w19, w19, w19, asr #31
 1bc:   39000c93    strb    w19, [x4,#3]
 1c0:   3c5ff0b0    ldur    b16, [x5,#-1]
 1c4:   91001884    add x4, x4, #0x6
 1c8:   7e61da10    ucvtf   d16, d16
 1cc:   1e7028f0    fadd    d16, d7, d16
 1d0:   1e780213    fcvtzs  w19, d16
 1d4:   7103fe7f    cmp w19, #0xff
 1d8:   1a81b273    csel    w19, w19, w1, lt
 1dc:   0ab37e73    bic w19, w19, w19, asr #31
 1e0:   381fe073    sturb   w19, [x3,#-2]
 1e4:   3c5ff0b0    ldur    b16, [x5,#-1]
 1e8:   7e61da10    ucvtf   d16, d16
 1ec:   1e643a10    fsub    d16, d16, d4
 1f0:   1e653a10    fsub    d16, d16, d5
 1f4:   1e780213    fcvtzs  w19, d16
 1f8:   7103fe7f    cmp w19, #0xff
 1fc:   1a81b273    csel    w19, w19, w1, lt
 200:   0ab37e73    bic w19, w19, w19, asr #31
 204:   381ff073    sturb   w19, [x3,#-1]
 208:   3c5ff0b0    ldur    b16, [x5,#-1]
 20c:   7e61da10    ucvtf   d16, d16
 210:   1e7028d0    fadd    d16, d6, d16
 214:   1e780213    fcvtzs  w19, d16
 218:   7103fe7f    cmp w19, #0xff
 21c:   1a81b273    csel    w19, w19, w1, lt
 220:   0ab37e73    bic w19, w19, w19, asr #31
 224:   39000073    strb    w19, [x3]
 228:   3d4000b0    ldr b16, [x5]
 22c:   7e61da10    ucvtf   d16, d16
 230:   1e7028e7    fadd    d7, d7, d16
 234:   1e7800f3    fcvtzs  w19, d7
 238:   7103fe7f    cmp w19, #0xff
 23c:   1a81b273    csel    w19, w19, w1, lt
 240:   0ab37e73    bic w19, w19, w19, asr #31
 244:   39000473    strb    w19, [x3,#1]
 248:   3d4000a7    ldr b7, [x5]
 24c:   7e61d8e7    ucvtf   d7, d7
 250:   1e6438e4    fsub    d4, d7, d4
 254:   1e653884    fsub    d4, d4, d5
 258:   1e780093    fcvtzs  w19, d4
 25c:   7103fe7f    cmp w19, #0xff
 260:   1a81b273    csel    w19, w19, w1, lt
 264:   0ab37e73    bic w19, w19, w19, asr #31
 268:   39000873    strb    w19, [x3,#2]
 26c:   3d4000a4    ldr b4, [x5]
 270:   910008a5    add x5, x5, #0x2
 274:   7e61d884    ucvtf   d4, d4
 278:   1e6428c4    fadd    d4, d6, d4
 27c:   1e780093    fcvtzs  w19, d4
 280:   7103fe7f    cmp w19, #0xff
 284:   1a81b273    csel    w19, w19, w1, lt
 288:   0ab37e73    bic w19, w19, w19, asr #31
 28c:   710000ff    cmp w7, #0x0
 290:   39000c73    strb    w19, [x3,#3]
 294:   91001863    add x3, x3, #0x6
 298:   54fff18c    b.gt    c8 <nv21_to_rgb_worker+0xc8>
 29c:   17ffff7b    b   88 <nv21_to_rgb_worker+0x88>
 2a0:   aa1f03e0    mov x0, xzr
 2a4:   a8c14ff4    ldp x20, x19, [sp],#16
 2a8:   d65f03c0    ret

Disassembly of section .text.ncv_color_cvt:

0000000000000000 <ncv_color_cvt>:
   0:   d10143ff    sub sp, sp, #0x50
   4:   f9001bf3    str x19, [sp,#48]
   8:   a9047bfd    stp x29, x30, [sp,#64]
   c:   910103fd    add x29, sp, #0x40
  10:   d53bd053    mrs x19, tpidr_el0
  14:   f9401669    ldr x9, [x19,#40]
  18:   aa0003e8    mov x8, x0
  1c:   52800020    mov w0, #0x1                    // #1
  20:   f81e83a9    stur    x9, [x29,#-24]
  24:   b4000668    cbz x8, f0 <ncv_color_cvt+0xf0>
  28:   b4000641    cbz x1, f0 <ncv_color_cvt+0xf0>
  2c:   b940010a    ldr w10, [x8]
  30:   b9400029    ldr w9, [x1]
  34:   7108055f    cmp w10, #0x201
  38:   54000321    b.ne    9c <ncv_color_cvt+0x9c>
  3c:   711c053f    cmp w9, #0x701
  40:   540002e1    b.ne    9c <ncv_color_cvt+0x9c>
  44:   b9400509    ldr w9, [x8,#4]
  48:   b940042a    ldr w10, [x1,#4]
  4c:   6b0a013f    cmp w9, w10
  50:   540004e1    b.ne    ec <ncv_color_cvt+0xec>
  54:   b9400909    ldr w9, [x8,#8]
  58:   b940082a    ldr w10, [x1,#8]
  5c:   6b0a013f    cmp w9, w10
  60:   54000461    b.ne    ec <ncv_color_cvt+0xec>
  64:   f940090a    ldr x10, [x8,#16]
  68:   b400054a    cbz x10, 110 <ncv_color_cvt+0x110>
  6c:   f940082a    ldr x10, [x1,#16]
  70:   b400050a    cbz x10, 110 <ncv_color_cvt+0x110>
  74:   90000000    adrp    x0, 0 <ncv_color_cvt>
  78:   a90187e8    stp x8, x1, [sp,#24]
  7c:   910063e8    add x8, sp, #0x18
  80:   91000000    add x0, x0, #0x0
  84:   910023e1    add x1, sp, #0x8
  88:   290127ff    stp wzr, w9, [sp,#8]
  8c:   f9000be8    str x8, [sp,#16]
  90:   94000000    bl  0 <ncv_parallel_for>
  94:   2a1f03e0    mov w0, wzr
  98:   14000016    b   f0 <ncv_color_cvt+0xf0>
  9c:   7108055f    cmp w10, #0x201
  a0:   2a1f03e0    mov w0, wzr
  a4:   54000261    b.ne    f0 <ncv_color_cvt+0xf0>
  a8:   7108053f    cmp w9, #0x201
  ac:   54000221    b.ne    f0 <ncv_color_cvt+0xf0>
  b0:   b9400509    ldr w9, [x8,#4]
  b4:   b940042a    ldr w10, [x1,#4]
  b8:   6b0a013f    cmp w9, w10
  bc:   54000181    b.ne    ec <ncv_color_cvt+0xec>
  c0:   b9400909    ldr w9, [x8,#8]
  c4:   b940082a    ldr w10, [x1,#8]
  c8:   6b0a013f    cmp w9, w10
  cc:   54000101    b.ne    ec <ncv_color_cvt+0xec>
  d0:   f9400908    ldr x8, [x8,#16]
  d4:   528000a0    mov w0, #0x5                    // #5
  d8:   b40000c8    cbz x8, f0 <ncv_color_cvt+0xf0>
  dc:   f9400828    ldr x8, [x1,#16]
  e0:   f100011f    cmp x8, #0x0
  e4:   1a9f0000    csel    w0, w0, wzr, eq
  e8:   14000002    b   f0 <ncv_color_cvt+0xf0>
  ec:   52800080    mov w0, #0x4                    // #4
  f0:   f9401668    ldr x8, [x19,#40]
  f4:   f85e83a9    ldur    x9, [x29,#-24]
  f8:   eb09011f    cmp x8, x9
  fc:   540000e1    b.ne    118 <ncv_color_cvt+0x118>
 100:   a9447bfd    ldp x29, x30, [sp,#64]
 104:   f9401bf3    ldr x19, [sp,#48]
 108:   910143ff    add sp, sp, #0x50
 10c:   d65f03c0    ret
 110:   528000a0    mov w0, #0x5                    // #5
 114:   17fffff7    b   f0 <ncv_color_cvt+0xf0>
 118:   94000000    bl  0 <__stack_chk_fail>

4. 反汇编有什么用处?

当发生 crash 时, 当程序耗时超出预期时, 都可以从汇编代码进一步分析。

举例: 对于一个C/C++函数,返回值类型不是 void; 如果缺失返回值,可能会在 Debug 模式发生 TRAP(crash,信号为TRAP), 在 Release 模式能运行而不会 Trap。 这时候可以从反汇编分析。

再举例: 对于 rgb 到 gray 的颜色空间转换, 在 Release 模式下的程序运行的很快, 在 Debug 模式下运行的稍慢, 并且如果手写了 arm neon (intrinsics)优化, 仍然和 Release 模式差不多快。 那么检查 Release 下的反汇编代码, 大概率是生成了 neon intrinsics 指令, 并且可能还把流水排布做了优化。

5. 搞一个网站查看反汇编呗!

很可惜, godbolt.org 目前还不支持 android-ndk 作为编译器。

对于 infra 比较到位的公司, 应该可以自行搭建一个在线网站来查看反汇编, 以及根据 crash 堆栈自动做分析等 (比如腾讯)。

6. 总结

给出了 android-ndk 程序查看反汇编代码的方法, 包括单个可执行文件、 基于 cmake 构建时的每个源代码文件。 简要提及了反汇编典型使用场景: crash 分析、 性能分析.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值