请问您能解释一下程序断点是什么以及sys_brk调用在x86-64架构上的Linux中返回的内容。我曾经认为程序的断点是程序地址空间中的最后一个有效地址。如果我想扩展它,我必须调用brk系统调用并为其提供断点的新地址。如果成功,我会回到新的断点,这可能比请求的更大,因为linux按页面运行。 但我对一些简单代码的行为感到困惑。
.equ sys_call_exit,60 #rdi - exit code
.equ sys_call_brk, 12 #rdi - long break
.section .data
msg_brk:
.ascii "Your break is here:%d\n\0"
msg_addr:
.ascii "Addr: %d\n\0"
.equ ST_BRK1,8
.equ ST_BRK2,16
.equ ST_BRK3,24
.equ OFFSET, 65528
.globl _start
.section .text
_start:
movq %rsp,%rbp
subq $32,%rsp
################Get current brk
movq $sys_call_brk,%rax
movq $0,%rdi
syscall
movq %rax,ST_BRK1(%rbp)
###############################
################Try to extend
movq ST_BRK1(%rbp),%rdi
addq $8,%rdi
movq $sys_call_brk,%rax
syscall
movq %rax,ST_BRK2(%rbp)
##############################
################Get brk after extenstion
movq $sys_call_brk,%rax
movq $0,%rdi
syscall
movq %rax,ST_BRK3(%rbp)
###############################
#####print results#############
movq ST_BRK1(%rbp),%rsi
movq $msg_brk,%rdi
call printf
movq ST_BRK2(%rbp),%rsi
movq $msg_brk,%rdi
call printf
movq ST_BRK3(%rbp),%rsi
movq $msg_brk,%rdi
call printf
#########################3
# Get the last brk point in rbx
movq ST_BRK3(%rbp),%rbx
loop:
#Print rbx
movq %rbx,%rsi
movq $msg_addr,%rdi
call printf
#movq ST_BRK3(%rbp),%rbx
movb (%rbx),%cl
incq %rbx
jmp loop
movq $0,%rdi
call exit
首先,我获得了当前的brk,然后我尝试将其扩展8个字节。然后我再次获得当前的brk。之后我尝试访问新brk上方的内存。 结果如下:
Your break is here:22466560
Your break is here:22466568
Your break is here:22466568
......
Addr: 22470380
Addr: 22470381
Addr: 22470382
Addr: 22470383
Addr: 22470384
Segmentation fault (core dumped)
正如你所看到的,首先我得到22466560作为当前的brk; 然后brk完全按照要求移动到22466568; 但linux通常按页面操作,所以我再次打电话给brk(0)查看真正的当前brk,我再次获得了22466568。 之后我试图访问22466568以上的内存。我只在22470385上得到了分段故障。所以我可以访问brk上方的3817字节(22470385 - 22466568)。
我的问题是为什么我可以访问高于brk的内存以及如何获得真正的brk点数? 感谢。