2017-06-06 14 views
0

我想在64位Linux上獲取用戶堆棧信息。 我知道mm-> start_stack,它表示用戶堆棧的初始堆棧指針的位置。如何在Linux上的多線程下獲取用戶堆棧底部

但是,在像pthread這樣的多線程應用程序中,由於使用相同的struct task_struct,mm-> start_stack與所有線程的值相同。

而且,我通過使用mm-> mmap-> vm_start和mm-> mmap-> vm_end來了解內存佈局的方式,但是,我不知道這些mmap區域是否堆疊。

我使用pmap進程id和strace確認了這些內存佈局。

你能告訴我如何獲得用戶棧位置的所有線程,如mm-> 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的結果

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 
+1

'mm-> start_stack與所有線程相同,因爲使用相同的struct task_struct.' - 部分錯誤:在Linux上,每個線程使用**自己的**'task_struct'。但'mm'可能在同一進程的線程之間共享。 – Tsyvarev

+0

謝謝。你是絕對正確的... – ouiouiouioui

回答

0

你的問題沒有完全確定。從技術上講,用戶可以使用pthread創建線程,然後將新線程sp切換到另一個線程。所以由pthread_create創建的堆棧並不總是進程使用的堆棧。地獄,過程甚至可能munmap它...

你可以,但是,訪問用戶的堆棧在特定時刻(如系統調用),以下列方式:

task_pt_regs(task)->sp 

但是,一定要驗證它,因爲它可能不總是在用戶空間中。用戶可以完全控制它。

0

大多數系統都提供了pthread_getattr_np(Linux)或pthread_attr_get_np(NetBSD)或類似的方法來初始化一個正在運行的線程的pthread_attr_t結構。

完成之後,您可以使用例如pthread_attr_getstackaddrpthread_attr_getstacksize以獲得最低地址和大小。取決於堆疊增長的方向,堆疊的「底部」是前者或兩者的總和。

小警告:雖然許多系統提供此功能,但它可能或可能不適用於程序的初始/主線程。你已經找到了一種處理這個問題的Linux特定方式。

相關問題