Android动态链接之应用程序的参数传递

来源:互联网 发布:淘宝店铺查询 编辑:程序博客网 时间:2024/06/05 16:57
    为Android手机移植了如GDB/Git/GCC等开源工具后,就可以在手机上调试二进制程序了。下面就来探究一下Linux内核在执行一个动态链接的ELF文件时,android的动态链接器是如何工作的。
    当Linux内核启动一个动态链接的ELF文件时,会加载其链接器至应用的地址空间,并跳转到链接器的入口处执行;也就是说,内核执行的是链接器的代码;而后链接器在完成其工作后会跳转到应用程序的入口。

    如下图所示,我们调试的ELF文件为hello,其链接器为dyn64,其实就是由bionic(版本为platform-22)编译得到的linker64。链接器的入口函数在bionic/linker/arch/arm64/begin.S中定义,通过objdump可以看到其代码只有三条汇编指令,首先将栈指针复制给x0寄存器,并跳转至__linker_init函数:


    在使用gdb调试时,我们使用break __linker_init给链接器加断点,然后启动之,如上图所示。通过查看__linker_init函数的代码,可以看到一个C++类,KernelArgumentBlock,其定义上方的注释给出了很有用的信息,可以了解到内核给hello传递的参数是放在栈空间上的:



    接下来,查看一下此刻的寄存器等信息,可以看到x0与sp的内容是相同的,即为栈指针;而x1至x29这29个通用寄存器的值均为零,可见Linux内核刚创建的应用程序如同初生的婴儿般纯净。同时我们也知道了x0指向的栈空间保存了内核为hello传递的参数,那么内核传递的参数在栈空间内是如何存放的呢?


    使用x指令查看内存,可以看到参数栈空间第一个长整型为0x3,那么猜测该值即为命令行的个数;依次用x/s查看其后几个长整型指向的数据,可以看到其后三个指针指向命令行字符串;在一个空指针之后,会存放包含等于符号的字符串数组,那么就可以猜测这些是hello执行的环境变量了。至此,我们可以对内核的参数传递方式有一个基本的了解,难怪某些书中会把C语言的main函数写作main(int argc, char **argv, char ** env)。

    我们可以进一步查看Linux(版本为4.13)内核的代码,可以看到在执行ELF文件时,确时会将argc存放在栈空间上;紧接着会放置命令行参数字符串指针数组,随后放置一个0(空指针);而后就是环境变量的指针数组了:



不过,在环境变量指针数据之后,还会存放一个0及elf_info等信息,而elf_info实质上是一个AUX的向量(vector),是与动态链接相关的信息,这些以后再讨论吧。



原创粉丝点击