我们可以使用负地址偏移量来存储和加载堆栈中的数据,如下面的代码片段所示吗?从实际位于堆栈边界外([sp, #-16]
或[sp, #-20]
)的内存地址写入和读取数据是否安全?
谢谢!
stmdb sp, { r4 - r6 }
mov r4, #255
str r4, [sp, #-16]
mov r3, #127
str r3, [sp, #-20]
ldr r4, [sp, #-20]
sub sp, #12
ldmia sp, { r4 - r6 }
答案 0 :(得分:3)
这是ABI的问题,而不是架构或语言,因此最终取决于运营环境和ABI。
虽然你可以访问SP以下的地址,但是基本寄存器r13和负偏移的加载或存储是完全有效的指令,它只是ABI这决定了你的数据是否安全,以及这种访问是否保证不会首先出现段错误。当前使用的大多数系统可能会使用ARM EABI的某些变体,procedure call standard表示,这是#34;通用堆栈约束的一部分":
进程只能访问(用于读取或写入)由[SP,stack-base-1]分隔的整个堆栈的闭合间隔(其中SP是寄存器r13的值)。
即。虽然没有任何东西可以阻止你违反这个限制,但试试吧,所有的赌注都会被取消。
既然你提到了Android,它肯定是EABI(特别是GNU变体),那么最明显的问题就是Linux内核提供信号的方式。如果您的进程恰好在str r3, [sp, #-20]
之后发出信号,则信号处理程序可以使用进程堆栈运行,因此当(如果)正常执行恢复时,SP本身将返回到之前的相同值,谁知道ldr r4, [sp, #-20]
实际会加载什么。
请注意,some environments可能会对堆栈指针下方的内容提供一些额外的保证,如果您处于裸机场景或完全控制,那么您可以做任何您喜欢的事情,但一般来说,除非你不知道,否则假设答案是" no"。