Android二进制工具objdump/readelf不能打印出function@plt的解决
Android二进制工具objdump/readelf不能打印出function@plt的原因和补丁. 查找原因时, google到的一点资料.
有人解决了后, Google的工程师也火急火燎地让上传补丁. :)
objdump not printing "function@plt" symbols when processing arm or mips object, but does for x86.
As one would expect of a modern toolchain targeting a shared library system, the ndk toolchain creates executables in which calls toexternal library functions are implemented with a call to a helper in the .plt section, which redirects to the address in the global offset table where the runtime linker will eventually place the address of the target function.
If I compile a simple hello-world executable with the ndk targeting both x86 and arm, then objdump the x86 version, I get something like this (trimmed a lot for brevity):
$ i686-android-linux-objdump -d obj/local/x86/hello
Disassembly of section .plt:
0804827c <puts@plt>:
804827c:ff 25 58 95 04 08 jmp *0x8049558
8048282:68 00 00 00 00 push $0x0
8048287:e9 e0 ff ff ff jmp 804826c <puts@plt-0x10>
Disassembly of section .text:
080483c0 <main>:
80483de:e8 99 fe ff ff call 804827c <puts@plt>
But, for the arm version:
$arm-linux-androideabi-objdump -d obj/local/armeabi/hello
Disassembly of section .plt:
000084f8 <.plt>:
8524:e28fc600 addip, pc, #0; 0x0
8528:e28cca02 addip, ip, #8192; 0x2000
852c:e5bcf7a4 ldrpc, [ip, #1956]!
0008590 <main>:
8590:b510 push{r4, lr}
8592:4803 ldrr0, [pc, #12](85a0 <main+0x10>)
8594:4478 addr0, pc
8596:f7ff efc6 blx8524 <_start-0x3c>
As you can see, there is no "puts@plt" synthetic symbol created, and the invocation within the program code is left as a negative address in relation to the first known symbol. Needless to say, this makes making sense of dumps very complicated - extremely so if looking at a stripped executable where the dynamic link symbols of the library functions used may be the only major clues as to what you are looking at.
So I would like to figure out why this useful feature of displaying the names of library functions called via the plt works for x86, and not for arm. I know that the necessary information to create these synthetic symbols does exist in the file, because I wrote a program which pattern matches the opcodes of the .plt, figures out the target address then searches for a dynamic symbol and at that address and prints out the corresponding stringtab name with a section suffix in
the way I assme objdump/BFD is doing for x86:
$ printplt obj/local/armeabi/hello
decoding plt...
0x0000850c: __cxa_begin_cleanup@plt
0x00008518: memcpy@plt
0x00008524: puts@plt
0x00008530: abort@plt
0x0000853c: __libc_init@plt
0x00008548: __cxa_type_match@plt
0x00008554: __gnu_Unwind_Find_exidx@plt
So my question is, why is this not working with the arm objdump? (it does not seem to work for mips either)
- Is there metadata missing from the arm object which is key to objdump / BFD deciding to try to do this?
- Is the feature just not implemented for arm?
- Is it implemented, but not available in the prebuilt toolchain due to omission of a compile-time option?
- Is it failing because the instructions used in the .plt are not of the form expected?
Unfortunately, I have not yet been able to figure out where these synthetic symbols are created in the binutils source; there's not a lot to search on since the "@plt" is presumably named from the section rather than being a static string, so it seems finding the code would require developing a degree of understanding of the codebase.
If possible, I'd like to find the area where binutils could be patched to enable this for arm, as it's a capability I would really like to have when debugging projects (and poking around on the device in general). If I can't figure out how to put it into objdump, I guess I could clean up and share my plt parsing program, but it would be a lot nicer to have the names in the disassembled output (and putting them in after the fact with sed seems a bit roundabout).
Managed to solve my problem - objdump now displays the function@pltnames is the disassembly of both the .plt and program code which calls them.
Patch follows... I suppose it's time to figure out how to use gerrit.
Which version of binutils would it be appropriate to submit against? I tried this on 2.21 but see there are lots in the git package. Or should it go upstream to someone else and only then back into android?
--- bfd/elf32-arm-orig.c2012-06-27 16:12:27.000000000 -0400
+++ bfd/elf32-arm.c2012-06-27 16:31:05.000000000 -0400
@@ -13898,6 +13898,21 @@
#define elf_backend_obj_attrs_orderelf32_arm_obj_attrs_order
#define elf_backend_obj_attrs_handle_unknown
elf32_arm_obj_attrs_handle_unknown
+/* Changes to enable decoding of function@plt symbols for android */
+#undef elf_backend_plt_sym_val
+#define elf_backend_plt_sym_valelf32_arm_android_plt_sym_val
+
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+ or (bfd_vma) -1 if it should not be included. */
+
+static bfd_vma
+elf32_arm_android_plt_sym_val (bfd_vma i, const asection *plt,
+ const arelent *rel ATTRIBUTE_UNUSED)
+{
+ return plt->vma + 4 * (
+ ARRAY_SIZE(elf32_arm_plt0_entry) +
+ ARRAY_SIZE(elf32_arm_plt_entry) * i);
+}
#include "elf32-target.h"
/* VxWorks Targets. */
Thank you for figuring out the fix! Please submit it to AOSP toolchain repo
repo init -u https://android.googlesource.com/toolchain/manifest.git
repo sync
You may google for how to submit patch to AOSP, but in short.
cd binutils
repo start yourbranchname .
Apply changes to binutils/binutils-2.19 and ideally also inbinutils/binutils-2.21
git commit -a # write commit message
repo upload . # then add reviewer
Your upload will appear inhttps://android-review.googlesource.com for review.
Looking forward to see it soon.
更多相关文章
- Android(安卓)studio 的快捷键对应 MAC 和Win版本
- Android如何用代码重复加载同一个xml
- Android数据库中查找一条数据使用的方法 query详解
- 代码论坛如何通过C的方式在android NDK下面查找本机的mac地址
- Android(安卓)Studio 使用lint工具进行代码优化
- Android(安卓)Studio集成友盟SDK出现的问题解决及原因分析
- 百度地图Android(安卓)SQLITE在本地如何实现按距离排序、范围查
- Android中不能在子线程中更新View视图的原因
- android NDK开发中,用Cygwin调试本地代码时报错“Another debug s