mfu*_*chs 0 c++ assembly android arm android-ndk
我正在反汇编本机 Android 库 (armeabi-v7a),这些库很可能是由 C++ 或 C 代码创建的,并且已被删除。目标是创建一个函数调用树以供以后分析。
我在理解反汇编输出时遇到问题。
采用以下创建的汇编器片段arm-linux-androideabi-objdump -d libledger.so > output.txt
00014988 <_ZSt10__pop_heapIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEENS0_5__ops15_Iter_less_iterEEvT_S9_S9_T0_>:
...
149e0: 4620 mov r0, r4
149e2: f030 fadd bl 44fa0 <_ZNK10__cxxabiv120__si_class_type_info11__do_upcastEPKNS_17__class_type_infoEPKvRNS1_15__upcast_resultE+0x2a7ec>
149e6: e7ff b.n 149e8 <_ZSt10__pop_heapIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEENS0_5__ops15_Iter_less_iterEEvT_S9_S9_T0_+0x60>
149e8: 4628 mov r0, r5
149ea: f030 fad9 bl 44fa0 <_ZNK10__cxxabiv120__si_class_type_info11__do_upcastEPKNS_17__class_type_infoEPKvRNS1_15__upcast_resultE+0x2a7ec>
149ee: f004 fe55 bl 1969c <__cxa_end_cleanup>
149f2: bf00 nop
149f4: b154 cbz r4, 14a0c <_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEEiNS0_5__ops15_Iter_less_iterEEvT_S9_T0_T1_+0x14>
149f6: 0005 movs r5, r0
000149f8 <_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEEiNS0_5__ops15_Iter_less_iterEEvT_S9_T0_T1_>:
149f8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
149fc: 1d07 adds r7, r0, #4
149fe: b085 sub sp, #20
14a00: 4604 mov r4, r0
14a02: 4690 mov r8, r2
14a04: 460e mov r6, r1
14a06: 1b35 subs r5, r6, r4
14a08: 2d43 cmp r5, #67 ; 0x43
14a0a: f340 8095 ble.w 14b38 <_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEEiNS0_5__ops15_Iter_less_iterEEvT_S9_T0_T1_+0x140>
14a0e: f1b8 0f00 cmp.w r8, #0
14a12: d13f bne.n 14a94 <_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEEiNS0_5__ops15_Iter_less_iterEEvT_S9_T0_T1_+0x9c>
14a14: 10ad asrs r5, r5, #2
14a16: 4b4a ldr r3, [pc, #296] ; (14b40 <_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEEiNS0_5__ops15_Iter_less_iterEEvT_S9_T0_T1_+0x148>)
14a18: 1eaf subs r7, r5, #2
14a1a: f10d 090c add.w r9, sp, #12
Run Code Online (Sandbox Code Playgroud)
此处描述的分支指令中,该系列的BL分支指令最类似于函数调用,这也在5.3 子例程调用中有所暗示。然后还有通过 的系统调用SWI。但我还是想到了一些问题:
BL跳转的指令始终指向 C 函数的开头?这意味着它们的行为类似于调用 C 函数。149e2:有一个函数调用。但我不明白这<XY+0x2a7ec>部分。这是不是意味着……
addressoff(XY) + 0x2a7ec,但不在.dynsym表中,因此没有可供反汇编程序引用的人类友好名称?XY调用它时会在其主体中产生巨大的偏移量?00014988 <...>函数。尽管我担心这只适用于动态符号表一部分的函数,这可以解释上面的巨大偏移量。149f4还有一个分支,这次是通过CBZ。这看起来也像是对不同函数的函数调用,并且再次带有偏移量。当 和00014988都是000149f8函数时,此CBZ调用将直接跳转到函数中,而不是在开头。这是什么意思?我能否确定 BL 指令跳转到的标签始终指向 C 函数的开头?这意味着它们的行为类似于调用 C 函数。
是的,大多数时候分支将到达函数的开头。
还有哪些指令用于 C 函数调用?
任何可以改变程序计数器的东西。
我已经看到BX, LDR PC,并POP指示了。
在上面的例子中,这意味着在 149e2:有一个函数调用。但我不明白这部分。这是否意味着...
被调用的函数从 addressoff(XY) + 0x2a7ec 开始,但不在 .dynsym 表中,因此没有可供反汇编程序引用的人类友好名称?
并非每个地址都与源行号对齐。偏移量是距地图文件中已知符号(通常是函数名称)的距离。
这是否意味着 XY 被调用时与它的主体有很大的偏移?
否。分支的目的地位于公共符号的偏移处。在很多情况下,很多函数不是公共的,因此它们引用映射文件中最近的公共符号。
或者两者都有可能吗?
往上看。
如何识别函数的开始?
没有一般规则。
这是一个过程:
在 149f4 处也有一个分支,这次是通过 CBZ。这看起来也像是对不同函数的函数调用,并且再次带有偏移量。当 00014988 和 000149f8 都是函数时,此 CBZ 调用将直接跳转到函数而不是在开头。这是什么意思?
这CBZ不是子例程或函数调用。这是到另一个地址的分支。预计不会有回报。
Branch and Link ( BL) 和 Branch and Exchange ( BX) 指令将LR寄存器设置为返回地址(通常是BL或之后的下一条指令BX)。为了返回,LR寄存器中的值被复制到程序计数器(PC)寄存器中,导致执行转移到LR中的地址。这是函数或子例程调用的返回。