我想在64位Linux上获取用户堆栈信息。 我知道mm-> start_stack指示用户堆栈的初始堆栈指针的位置。
但是,在像pthread这样的多线程应用程序中,mm-> start_stack与所有线程的值相同,因为使用了相同的struct task_struct。
而且,我通过使用mm-&gt; mmap-&gt; vm_start和mm-&gt; mmap-&gt; vm_end知道内存布局的方式但是,我不知道这些mmap区域是否是堆栈。< / p>
我用pmap进程id和strace确认了这些内存布局。
你能告诉我如何获得用户堆栈位置所有线程,如mm-&gt; start_stack?。
sudo pmap 24074
24074: ./a.out
0000000000400000 4K r-x-- a.out
0000000000600000 4K r---- a.out
0000000000601000 4K rw--- a.out
0000000000602000 132K rw--- [ anon ]
00007ffff5fee000 4K ----- [ anon ]
00007ffff5fef000 8192K rw--- [ anon ] <==== Thread Stack
00007ffff67ef000 4K ----- [ anon ]
00007ffff67f0000 8192K rw--- [ anon ] <==== Thread Stack
00007ffff6ff0000 4K ----- [ anon ]
00007ffff6ff1000 8192K rw--- [ anon ] <==== Thread Stack
00007ffff77f1000 1792K r-x-- libc-2.23.so
00007ffff79b1000 2044K ----- libc-2.23.so
00007ffff7bb0000 16K r---- libc-2.23.so
00007ffff7bb4000 8K rw--- libc-2.23.so
00007ffff7bb6000 16K rw--- [ anon ]
00007ffff7bba000 96K r-x-- libpthread-2.23.so
00007ffff7bd2000 2044K ----- libpthread-2.23.so
00007ffff7dd1000 4K r---- libpthread-2.23.so
00007ffff7dd2000 4K rw--- libpthread-2.23.so
00007ffff7dd3000 16K rw--- [ anon ]
00007ffff7dd7000 152K r-x-- ld-2.23.so
00007ffff7fda000 12K rw--- [ anon ]
00007ffff7ff6000 8K rw--- [ anon ]
00007ffff7ff8000 8K r---- [ anon ]
00007ffff7ffa000 8K r-x-- [ anon ]
00007ffff7ffc000 4K r---- ld-2.23.so
00007ffff7ffd000 4K rw--- ld-2.23.so
00007ffff7ffe000 4K rw--- [ anon ]
00007ffffffde000 132K rw--- [ stack ]
ffffffffff600000 4K r-x-- [ anon ]
total 31108K
strace results
clone(child_stack=0x7ffff77efff0,flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7ffff77f09d0, tls=0x7ffff77f0700, child_tidptr=0x7ffff77f09d0) = 24075
clone(pid: 24074 child_stack=0x7ffff6feeff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7ffff6fef9d0, tls=0x7ffff6fef700, child_tidptr=0x7ffff6fef9d0) = 24076
clone(child_stack=0x7ffff67edff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7ffff67ee9d0, tls=0x7ffff67ee700, child_tidptr=0x7ffff67ee9d0) = 24077
答案 0 :(得分:0)
你的问题没有完全明确。从技术上讲,用户可以使用pthread
创建一个线程,然后将新线程sp
切换到另一个线程。因此,pthread_create
创建的堆栈并不总是进程使用的堆栈。地狱,这个过程甚至可能munmap
......
但是,您可以通过以下方式在特定时刻(例如系统调用)访问用户的堆栈:
task_pt_regs(task)->sp
但是,请务必对其进行验证,因为它可能并不总是在用户空间中。用户可以完全控制它。
答案 1 :(得分:0)
大多数系统提供pthread_getattr_np
(Linux)或pthread_attr_get_np
(NetBSD)或类似的方法来从正在运行的线程初始化pthread_attr_t
结构。
完成后,您可以使用例如pthread_attr_getstackaddr
和pthread_attr_getstacksize
获取最低地址和大小。堆栈的“底部”是前者或两者的总和,具体取决于堆栈增长的方向。
小警告:虽然许多系统提供此功能,但它可能适用于程序的初始/主线程,也可能不适用。您已经找到了一种特定于Linux的方法来解决这个问题。