八月的太阳晒得黄黄的,谁说这世界不是黄金?小雀儿在树荫里打盹,孩子们在草地里打滚。八月的太阳晒得黄黄的,谁说这世界不是黄金?金黄的树林,金黄的草地,小雀们合奏着欢畅的清音:金黄的茅舍,金黄的麦屯,金黄是老农们的笑声。 ——徐志摩·八月的太阳

ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287

在生成 native 程序时,在链接阶段会传入一个链接脚本,在该脚本中指定了程序的入口函数。

可以看到,在默认的链接脚本 armelf_linux_eabi.x 中,入口函数指定为“_start”。

在 NDK 目录下搜索 ldscripts,所有的链接脚本都在该目录中。

_start 函数定义在 (libc 的 bionic 目录下) Crtbegin.c 中。

在 _start 中又调用了 __libc_init,并将 main 函数的地址作为参数传入。

再看 __libc_init 的源码 (在 libc 的 bionic 目录下的 Libc_init_static.cpp 文件中):

在 __libc_init 中先进行一些初始化工作,再调用 preinit_array、init_array,最后调用由参数 slingshot 传入的 main 函数。

上面的描述针对静态链接的程序,对于动态链接的程序还稍有不同。

对于动态链接 (在 gcc 命令行中指定 -Bdynamic),在生成的可执行文件的 .interp 中保存了程序解释器的文件路径,默认为“/system/bin/linker”。

当执行动态链接的程序时,系统会解析该 ELF 文件,并找到 .interp 中保存的程序解释器,也就是 android linker。然后先执行 linker,linker 会加载该程序的所依赖的一系列 so,并最后再调用该可执行程序。

linker 的入口函数 _start 不在 Crtbegin.c 中,而是在 linker 源码的 begin.S 文件中。

调用 __linker_init 函数完成 linker 的“自举”,并进行一些初始化工作,最后会返回原 native 程序的入口函数的地址 (从 native 程序的 ELF Header 中找到)。

mov pc, r0,跳转到 native 程序的入口函数 (_start) 去执行,接下来的执行过程与上面一样。_start 调用 __libc_init。动态链接程序的 __libc_init 定义在 Libc_init_dynamic.cpp 文件中 (静态链接程序的 __libc_init 定义在 Libc_init_static.cpp 文件中)。

看起来比静态链接程序的 __libc_init 简单点,因为一些初始化工作由 linker 完成了。

总结:静态链接与动态链接的 native 程序的入口函数都是 _start。动态链接的程序在执行 _start 之前,需要先由 linker 加载依赖库,并进行一些初始化工作。

学习资料: 《Android 软件安全与逆向分析》

更多相关文章

  1. 一起来学android开发之一——写给初学android的同学们
  2. Android10 insmod源码分析
  3. android input命令 模拟按键
  4. Android模拟器常用操作
  5. pAdTy_-5 保存数据
  6. Android判断、创建和删除快捷方式
  7. Netty 之Oio程序编写
  8. android notepad详解
  9. Android(安卓)网络管理

随机推荐

  1. 为了获取下一个10亿用户,Google的布局其实
  2. Android:规范命名,让合作更加愉快
  3. Android——内存篇:Android中5种最常见的
  4. mssql @@ERROR 使用
  5. mssql 两种数据插入方式
  6. sql 普通行列转换
  7. SQL Server的复制功能
  8. Oracle 10g各个帐号的访问权限、登录路径
  9. SQL Server 更改DB的Collation
  10. SQL Server约束增强的两点建议