一、背景
一直以来对ndk的编译链接所依赖的文件没有完成弄明白,还有ida的导入、导出函数与dynsym section之间的关系是什么?
二、ndk编译所依赖的文件
1、我们一般在Application.mk中指定所需要的平台版本和编译后so的架构。
APP_PLATFORM := android-21
APP_ABI := armeabi-v7a
这个android-21对应什么呢?这是android ndk的根目录。
这里指定的编译so时,链接时需要的so文件,如果指定了android-21,那么链接时就到这个目录下寻找so。
2、下面看下Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lesson2
LOCAL_SRC_FILES := Lesson2.cpp MyTest.cpp module.c
LOCAL_LDLIBS := -llog -ldl -lmediandk -lGLESv2
LOCAL_CPPFLAGS += -O3
LOCAL_CFLAGS += -fvisibility=hidden
include $(BUILD_SHARED_LIBRARY)
-lmediandk在链接时会使用android-ndk-r21/platforms/android-21/arch-arm/usr/lib/libmediandk.so
-lGLESv2在链接时会使用android-ndk-r21/platforms/android-21/arch-arm/usr/lib/libGLESv2.so
3、Lesson2.cpp
#include <media/NdkMediaDrm.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
在使用函数的地方还需要包含头文件,这些头文件在哪呢?
android-ndk-r21/sysroot/usr/include
4、使用的交叉编译工具
android-ndk-r21/toolchains/llvm/prebuilt/darwin-x86_64/bin
三、ida中Exports、Imports与dynsym之间的关系
arm-linux-androideabi-readelf -s liblesson2.so
Symbol table '.dynsym' contains 61 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@LIBC (2)
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize@LIBC (2)
3: 00000000 0 FUNC GLOBAL DEFAULT UND AMediaDrm_createByUUID
4: 00000000 0 FUNC GLOBAL DEFAULT UND dladdr@LIBC (3)
5: 00000000 0 FUNC GLOBAL DEFAULT UND AMediaDrm_getPropertyByte
6: 00000000 0 FUNC GLOBAL DEFAULT UND snprintf@LIBC (2)
7: 00000000 0 FUNC GLOBAL DEFAULT UND _Znwj@LIBC_O (4)
8: 00000000 0 FUNC GLOBAL DEFAULT UND __android_log_print
9: 00000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@LIBC (2)
10: 00000000 0 OBJECT GLOBAL DEFAULT UND __stack_chk_guard@LIBC (2)
11: 00000000 0 FUNC GLOBAL DEFAULT UND __vsprintf_chk@LIBC (2)
12: 00000000 0 FUNC GLOBAL DEFAULT UND gettimeofday@LIBC (2)
13: 00000000 0 FUNC GLOBAL DEFAULT UND localtime@LIBC (2)
14: 00000000 0 FUNC GLOBAL DEFAULT UND stat@LIBC (2)
15: 00000000 0 FUNC GLOBAL DEFAULT UND strftime@LIBC (2)
16: 00000000 0 FUNC GLOBAL DEFAULT UND time@LIBC (2)
17: 00000000 0 FUNC GLOBAL DEFAULT UND vsnprintf@LIBC (2)
18: 00000000 0 OBJECT GLOBAL DEFAULT UND __sF@LIBC (2)
19: 00000000 0 FUNC GLOBAL DEFAULT UND abort@LIBC (2)
20: 00000000 0 FUNC GLOBAL DEFAULT UND fflush@LIBC (2)
21: 00000000 0 FUNC GLOBAL DEFAULT UND fprintf@LIBC (2)
22: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_memclr
23: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_memcpy
24: 00000000 0 FUNC GLOBAL DEFAULT UND __gnu_Unwind_Find_exidx
25: 00001e15 72 FUNC GLOBAL DEFAULT 13 unw_set_reg
26: 00001ed1 6 FUNC GLOBAL DEFAULT 13 unw_step
27: 00001f0d 28 FUNC GLOBAL DEFAULT 13 unw_get_proc_name
28: 00001f3b 12 FUNC GLOBAL DEFAULT 13 unw_is_signal_frame
29: 00001a75 8 FUNC GLOBAL DEFAULT 13 __aeabi_unwind_cpp_pr0
30: 00001abd 160 FUNC GLOBAL DEFAULT 13 _Unwind_RaiseException
31: 00001ed7 32 FUNC GLOBAL DEFAULT 13 unw_get_proc_info
32: 00001345 312 FUNC GLOBAL DEFAULT 13 Java_com_example_ndkrever
33: 00001aad 8 FUNC GLOBAL DEFAULT 13 __aeabi_unwind_cpp_pr1
34: 00001519 72 FUNC GLOBAL DEFAULT 13 decode_eht_entry
35: 00005004 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
36: 00001ab5 8 FUNC GLOBAL DEFAULT 13 __aeabi_unwind_cpp_pr2
37: 00001d99 72 FUNC GLOBAL DEFAULT 13 unw_init_local
38: 00005005 0 NOTYPE GLOBAL DEFAULT ABS _end
39: 00001e5d 56 FUNC GLOBAL DEFAULT 13 unw_get_fpreg
40: 0000147d 36 FUNC GLOBAL DEFAULT 13 JNI_OnLoad
41: 00005004 0 NOTYPE GLOBAL DEFAULT ABS _edata
42: 00001d15 52 FUNC GLOBAL DEFAULT 13 _Unwind_GetRegionStart
43: 00001561 616 FUNC GLOBAL DEFAULT 13 _Unwind_VRS_Interpret
44: 00001de1 52 FUNC GLOBAL DEFAULT 13 unw_get_reg
45: 00001925 336 FUNC GLOBAL DEFAULT 13 _Unwind_VRS_Pop
46: 00001875 176 FUNC GLOBAL DEFAULT 13 _Unwind_VRS_Set
47: 00001ef9 20 FUNC GLOBAL DEFAULT 13 unw_resume
48: 00001f47 6 FUNC GLOBAL DEFAULT 13 unw_save_vfp_as_X
49: 00001f35 6 FUNC GLOBAL DEFAULT 13 unw_regname
50: 00001231 80 FUNC GLOBAL DEFAULT 13 _Z4testv
51: 00001d49 12 FUNC GLOBAL DEFAULT 13 _Unwind_DeleteException
52: 00001d55 18 FUNC GLOBAL DEFAULT 13 __gnu_unwind_frame
53: 00001c75 2 FUNC GLOBAL DEFAULT 13 _Unwind_Complete
54: 00001d68 0 FUNC GLOBAL DEFAULT 13 unw_getcontext
55: 00001e95 60 FUNC GLOBAL DEFAULT 13 unw_set_fpreg
56: 00001f29 12 FUNC GLOBAL DEFAULT 13 unw_is_fpreg
57: 00001ce1 52 FUNC GLOBAL DEFAULT 13 _Unwind_GetLanguageSpecif
58: 00001c79 104 FUNC GLOBAL DEFAULT 13 _Unwind_Resume
59: 000017c9 172 FUNC GLOBAL DEFAULT 13 _Unwind_VRS_Get
60: 00005000 4 OBJECT GLOBAL DEFAULT 21 unw_local_addr_space
ida Imports
ida Exports
ida Imports对应到dynsym,就是那些Value为00000000的符号。
ida Exports对应到dynsym,就是那些Value不为00000000的符号(个别_end没有放到ida的Exports中)。
使用arm-linux-androideabi-nm -D liblesson2.so,可以更加清楚和完整的看到函数名,和dynsym是一一对应的。
U AMediaDrm_createByUUID
U AMediaDrm_getPropertyByteArray
0000147c T JNI_OnLoad
00001344 T Java_com_example_ndkreverse2_Lesson2_main
00001c74 T _Unwind_Complete
00001d48 T _Unwind_DeleteException
00001ce0 T _Unwind_GetLanguageSpecificData
00001d14 T _Unwind_GetRegionStart
00001abc T _Unwind_RaiseException
00001c78 T _Unwind_Resume
000017c8 T _Unwind_VRS_Get
00001560 T _Unwind_VRS_Interpret
00001924 T _Unwind_VRS_Pop
00001874 T _Unwind_VRS_Set
00001230 T _Z4testv
U _Znwj
U __aeabi_memclr
U __aeabi_memcpy
00001a74 T __aeabi_unwind_cpp_pr0
00001aac T __aeabi_unwind_cpp_pr1
00001ab4 T __aeabi_unwind_cpp_pr2
U __android_log_print
00005004 A __bss_start
U __cxa_atexit
U __cxa_finalize
U __gnu_Unwind_Find_exidx
00001d54 T __gnu_unwind_frame
U __sF
U __stack_chk_fail
U __stack_chk_guard
U __vsprintf_chk
00005004 A _edata
00005005 A _end
U abort
00001518 T decode_eht_entry
U dladdr
U fflush
U fprintf
U gettimeofday
U localtime
U snprintf
U stat
U strftime
U time
00001e5c T unw_get_fpreg
00001ed6 T unw_get_proc_info
00001f0c T unw_get_proc_name
00001de0 T unw_get_reg
00001d68 T unw_getcontext
00001d98 T unw_init_local
00001f28 T unw_is_fpreg
00001f3a T unw_is_signal_frame
00005000 D unw_local_addr_space
00001f34 T unw_regname
00001ef8 T unw_resume
00001f46 T unw_save_vfp_as_X
00001e94 T unw_set_fpreg
00001e14 T unw_set_reg
00001ed0 T unw_step
U vsnprintf
这里面的U对应到ida的Imports里面,其他对应到ida的Exports里面。
注意有些大型的so,使用arm-linux-androideabi-nm -D 获取的信息是有重复的。比如_edata,__bss_start是重复的。还有些函数地址有两个名字,ida会智能标记上两个名字,但在ida Exports里面只有一份,这就是为什么arm-linux-androideabi-nm -D获取的行数大于ida Exports的原因。
四、so中.rel.dyn、.rel.plt、.plt、.got表
.rel.dyn、.rel.plt
00004f68 00000216 R_ARM_JUMP_SLOT 00000000 __cxa_finalize@LIBC
00004f6c 00000116 R_ARM_JUMP_SLOT 00000000 __cxa_atexit@LIBC
00004f70 00000e16 R_ARM_JUMP_SLOT 00000000 stat@LIBC
00004f74 00000816 R_ARM_JUMP_SLOT 00000000 __android_log_print
00004f78 00000916 R_ARM_JUMP_SLOT 00000000 __stack_chk_fail@LIBC
got表
在dlopen so时,会找到android_log_print的虚拟地址,然后根据.rel.dyn、.rel.plt提示的位置,写入got表。
在程序调用android_log_print是,首先会调用.plt,在.plt中得到刚才写入了got表中android_log_print的虚拟地址。然后跳转执行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)