sunwengang blog

developer | android display/graphics

  1. 1. native编译
    1. 1.1. 编译为obj
    2. 1.2. 静态链接
    3. 1.3. 动态链接
  2. 2. tombstone定位错误方法
    1. 2.1. signum
    2. 2.2. *sigcode
  3. 3. 参考

了解gcc将*.c/cpp编译成*.o,再将其链接为可执行程序或/lib库的过程,有助于我们将native从编译/加载/执行到崩溃一条路贯通起来。Android的Makefile只需要将source file填入LOCAL_SRC_FILES,然后include $(BUILD_SHARED_LIBRARY)$(BUILD_EXECUTABLE)就可以将*.c/cpp/s编译为动态库或可执行程序。

native编译

编译为obj

在build/core/definitions.mk有定义transform-c-or-s-to-o-no-deps和transform-cpp-to-o,分别将每个.c/s和.cpp编译成*.o,里面传了很多参数给gcc

  1. -fpic -fPIE
  • PIC是Position-Independent Code的缩写,经常被用在共享库中,这样就能将相同的库代码为每个程序映射到一个位置,不用担心覆盖掉其他程序或共享库。
  • PIE是Position-Independent-Executable的缩写,只能应用在可执行程序中。PIE和PIC很像,但做了一些调整(不用PLT,使用PC相关的重定位)。-fPIE给编译用,-pie给链接(ld)用。

例如,一个程序没有使用PIC被链接到0地址,那么系统将其加载到0地址。

  1. -fstack-protector

顾名思义就是保护堆栈,每一个函数在运行时都有自己的栈帧,如果代码没有写好,很可能将自己甚至是其他的栈帧踩坏,那如何防护呢?简单的方法就是在栈帧头部也就是在局部变量开始之前多存储一个stack_chk_guard值,用于在函数返回前取出来和_stack_chk_guard做对比,失败则调用stack_chk_fail函数,这个就是该参数完成的行为。

静态链接

build/core/combo/TARGET_linux-arm.mk里有定义transform-o-to-static-executable-inner,将*.o链接成静态可执行程序,静态可执行程序是一个完整的程序,不需要额外的共享库即可执行,比如/init,/sbin/adbd等。

链接器用的是arm-linux-androideabi-g++

动态链接

build/core/combo/TARGET_linux-arm.mk里有定义transform-o-to-executable-innertransform-o-to-shared-lib-inner,分别将*.o链接为动态可执行程序和共享库。动态可执行程序需要linker才能进一步运行的。

链接器也是用arm-linux-androideabi-g++

tombstone定位错误方法

signum

一般debuggerd关注的是SIGILL,SIGBUS,SIGABRT,SIGFPE,SIGSEGV,SIGPIPE等。而这里,估计九成都是SIGSEGV (即signal 11),段错误,和非法内存访问等价。

*sigcode

  • SEGV_MAPERR:访问一个没有映射到任何内容的地址,这种情况通常就是野指针,或者越界访问,访问空指针也是属于这类
  • SEGV_ACCERR:试图访问您无权访问的地址。说明访问出错地址,被map到地址空间来了,但是没访问权限。基本上是指针越界或野指针,比如写只读map的内存地址

例如:

1
2
3
4
5
6
7
8
9
10
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x7ecbf6a000   //SEGV_ACCERR表示试图访问您无权访问的地址
x0 0000007e44001c30 x1 0000000000000000 x2 0000000000000000 x3 0000007e44001c30
x4 0000007ecbf6a008 x5 0000007e44001c98 x6 0000000000000000 x7 0000000000000000
x8 0000000000000000 x9 0000000000000000 x10 0000000000000000 x11 0000000000000000
x12 0000000000000000 x13 0000000000000000 x14 0000000000000001 x15 0000007ecbe3f540
x16 0000007eca917290 x17 0000007ec94ea480 x18 0000007e42e9c000 x19 0000007ecbdf5400
x20 0000000000000001 x21 0000007e44001c30 x22 0000000000000001 x23 0000007e44002020
x24 0000007ecb6bf045 x25 0000007ecb6bf260 x26 0000007ecb6bf278 x27 0000007ecb6bf041
x28 0000007ecb6bf044 x29 0000007e44001bf0
sp 0000007e44001bd0 lr 0000007eca910618 pc 0000007ec94ea460

tombstone日志当中也提供了出错时寄存器地址里面的临近内存信息,信息量同样很丰富。查看0000007e44001c30附近的内存情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
memory near x0:
0000007e44001c10 0000000000030d40 00000000ffffffff @...............
0000007e44001c20 0000007e44001cf0 0000007ecb6b83f0 ...D~.....k.~...
0000007e44001c30 0000000000000000 0000000000000000 ................
0000007e44001c40 0000000000000000 0000000000000000 ................
0000007e44001c50 0000000000000000 0000000000000000 ................
0000007e44001c60 0000000000000000 0000000000000000 ................
0000007e44001c70 0000000000000000 0000000000000000 ................
0000007e44001c80 0000000000000000 0000000000000000 ................
0000007e44001c90 0000000000000000 1c86a694ed72c72c ........,.r.....
0000007e44001ca0 0000000000000001 00000000000fd000 ................
0000007e44001cb0 0000007ecb6b8170 0000007e44001d50 p.k.~...P..D~...
0000007e44001cc0 0000007e44001d50 0000007e44001dd8 P..D~......D~...
0000007e44001cd0 00000207000005ea 0000007e44001d50 ........P..D~...
0000007e44001ce0 0000007ec954e5f0 0000007e44001d50 ..T.~...P..D~...
0000007e44001cf0 0000007e44001d10 0000007ec954e618 ...D~.....T.~...
0000007e44001d00 0000007e44001d50 0000000000000000 P..D~...........

参考

本文作者 : sunwengang
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://alonealive.github.io/Blog/2020/07/28/2020/200727_android_NE_Two/

本文最后更新于 天前,文中所描述的信息可能已发生改变