题
目前,我正在玩弄的手臂会在Linux作为一个学习的运动。我使用的'赤裸'大会,即没有libcrt或libgcc.任何人都可以点我的信息是关于什么状态叠指针和其他登记将在本程序开始之前的第一个指令被称为?显然pc/r15点在_start,其余的出现被初始化为0,有两个例外情况;sp/r13点的一个地址远远超出我的程序,并r1点稍微高的地址。
所以为某些固体问题:
- 有什么价值在r1?
- 是的价值在sp合法堆分配的核心?
- 如果不是,什么是优选方法分配一堆;使用brk或分配一个静态的。bss部分?
任何指针,将不胜感激。
解决方案
这是我用什么来获得一个Linux/ARM程序开始与我的编译器:
/** The initial entry point.
*/
asm(
" .text\n"
" .globl _start\n"
" .align 2\n"
"_start:\n"
" sub lr, lr, lr\n" // Clear the link register.
" ldr r0, [sp]\n" // Get argc...
" add r1, sp, #4\n" // ... and argv ...
" add r2, r1, r0, LSL #2\n" // ... and compute environ.
" bl _estart\n" // Let's go!
" b .\n" // Never gets here.
" .size _start, .-_start\n"
);
正如你可以看到,我刚刚得到的argc,argv,并environ东西堆在[sp].
一点澄清:堆的指针指向一个有效的区域在该进程的存储器。r0,r1,r2,并r3第三种参数的函数。我填充他们与argc,argv,并environ,分别。
其他提示
由于这是Linux,你可以看看它是如何实施的核心。
登记似乎是设置呼叫来 start_thread
在结束 load_elf_binary
(如果您使用的是一个现代化的Linux系统,它会几乎总是使用精灵格式)。手臂,注册似乎是设定如下:
r0 = first word in the stack
r1 = second word in the stack
r2 = third word in the stack
sp = address of the stack
pc = binary entry point
cpsr = endianess, thumb mode, and address limit set as needed
显然你有一个有效的堆。我认为值 r0
-r2
是垃圾,你应该读一切从栈(你会看到为什么我觉得这个以后)。现在,让我们看看什么是在堆。什么你会读从栈是满的 create_elf_tables
.
一个有趣的事情这里要注意的是,这个功能架构无关,所以同样的事情(大部分)将在堆在每一个小精灵的基于Linux的结构。以下是关于堆叠,在为你会读:
- 这些参数(这是
argc
在main()
). - 一个指C string对每个参数,随后通过一个零(这是内容
argv
在main()
;argv
要点的第一这些指针). - 一个指C串的每个环境可变的,随后通过一个零(这是内容很少-看到
envp
第三个参数main()
;envp
要点的第一这些指针). - "辅助矢量",这是一系列对(a类型随后通过一个值),终止对零(
AT_NULL
)在第一个元素。这辅助矢量有一些有趣和有用的信息,这些信息,你可以看到的(如果使用glibc)通过运行的任何动态联的程序LD_SHOW_AUXV
环境变量设定为1
(例如LD_SHOW_AUXV=1 /bin/true
).这也是这里的东西可以改变一位根据建筑。
由于这种结构是相同的每一建筑,你可以看看例如在绘画上,第54页的 SYSV386ABI 得到一个更好的主意是如何的东西合在一起(注意,然而,辅助向量型的常量就该文件是不同Linux用,所以你应该看看Linux的标题)。
现在你可以看到为什么内容 r0
-r2
都是垃圾。第一词在栈 argc
, 第二是指向的节目名称(argv[0]
),第三个也许是零,因为你称程序没有参数(这将是 argv[1]
).我猜他们是设置这种方式为老 a.out
二进制的格式,它作为你可以看到 create_aout_tables
让 argc
, argv
, , envp
在堆(所以他们会在 r0
-r2
在以预期的一个呼叫 main()
).
最后,为什么 r0
零你,而不是一个(argc
应该是一个如果你叫的程序没有参数)?我猜深处的东西在系统调用机械复盖它与返回值的系统打电话(这将是零,因为执行成功).你可以看看 kernel_execve
(其中不使用的系统调用机械,因为它是什么内核呼吁时,它想要执行从核心模式),它刻意将复盖 r0
与返回值 do_execve
.
这里的 uClibc crt.这似乎表明所有寄存器是不确定的除了 r0
(其中包含一个功能的指针指向被注册 atexit()
)和 sp
其中包含一个有效的堆的地址。
因此,值您看看 r1
可能不是东西,你可以依靠。
一些数据放置在堆为你。
我从来没有用手臂Linux但我建议你看看源的libcrt,看看他们做什么,或使用库步入现有的可执行的。你不需要的源代码的步骤,通过大会的代码。
你需要的一切要找出应当发生在第一次执行的代码由二进制的任何可执行的。
希望这会有所帮助。
Tony