我想找到用戶空間進程中定義的變量的物理地址?有沒有辦法使用root權限來完成它?如何在Linux中從用戶空間找到變量的物理地址?
回答
首先,你爲什麼要這樣做?現代VM系統的目的是將應用程序員從物理內存佈局的複雜性中移除。給他們分配自己的統一地址空間,讓他們的生活變得輕鬆自在。
如果您確實想這樣做,您幾乎肯定需要使用內核模塊。以正常方式獲取變量的虛擬地址,使用它來索引進程頁表並讀取您找到的值(幀的物理地址)。然後添加頁面偏移量以獲取完整的物理地址。請注意,在啓用分頁功能時,您將無法使用此地址。
(如果你運氣好,你可能能夠得到從/ proc文件系統中的VM區域的幀地址,因而難道不要求寫一個內核模塊。)
(編輯:如果通過「物理地址「,你的意思是」RAM模塊存儲在哪個級別「,那麼下面的答案是不合適的。)
你不需要root權限就可以做到這一點。你需要的是一個調試器。在這裏,我們走(在x86_64上使用Linux系統):
首先我們需要一個小程序來玩。這個訪問一個全局變量並連續打印兩次。它有兩個全局變量,我們稍後在內存中找到它們。
#include <stdio.h> int a, b = 0; int main(void) { printf("a: "); if (fscanf("%d", &a) < 1) return 0; printf("a = %d\n", myglobal); printf("b: "); if (fscanf("%d", &b) < 1) return 0; printf("a = %d, b = %d\n", a, b); return 0; }
第1步:編譯程序,並從中去除所有調試信息,所以我們沒有得到我們不會在真實的生活狀況得到了調試任何提示。
$ gcc -s -W -Wall -Os -o ab ab.c
步驟2:運行程序並輸入兩個數字中的一個。
$ ./ab a: 123 a = 123 b: _
第3步:找到過程。
$ ps aux | grep ab roland 21601 0.0 0.0 3648 456 pts/11 S+ 15:17 0:00 ./ab roland 21665 0.0 0.0 5132 672 pts/12 S+ 15:18 0:00 grep ab
步驟4:將調試器連接到進程(21601)。
$ gdb ... (gdb) attach 21601 ... (gdb) where #0 0x00007fdecfdd2970 in read() from /lib/libc.so.6 #1 0x00007fdecfd80b40 in _IO_file_underflow() from /lib/libc.so.6 #2 0x00007fdecfd8230e in _IO_default_uflow() from /lib/libc.so.6 #3 0x00007fdecfd66903 in _IO_vfscanf() from /lib/libc.so.6 #4 0x00007fdecfd7245c in scanf() from /lib/libc.so.6 #5 0x0000000000400570 in ??() #6 0x00007fdecfd2f1a6 in __libc_start_main() from /lib/libc.so.6 #7 0x0000000000400459 in ??() #8 0x00007fffd827da48 in ??() #9 0x000000000000001c in ??() #10 0x0000000000000001 in ??() #11 0x00007fffd827f9a2 in ??() #12 0x0000000000000000 in ??()
有趣的幀編號爲5,因爲它是一些代碼調用main
功能和scanf
功能的,所以它必須是我們main
功能。繼續調試會話:
(gdb) frame 5 ... (gdb) disassemble $pc $pc+50 ... 0x0000000000400570 : test %eax,%eax 0x0000000000400572 : jle 0x40058c <[email protected]+372> 0x0000000000400574 : mov 0x2003fe(%rip),%edx # 0x600978 <[email protected]+2098528> 0x000000000040057a : mov 0x2003fc(%rip),%esi # 0x60097c <[email protected]+2098532> 0x0000000000400580 : mov $0x40068f,%edi 0x0000000000400585 : xor %eax,%eax 0x0000000000400587 : callq 0x4003f8 <[email protected]> ...
現在我們知道該函數printf
將得到三個參數,和兩個有相互只有四個字節的路程。這是一個好兆頭,這兩個是我們的變量a
和b
。所以a
的地址是0x600978或0x60097c。讓我們來看看通過嘗試:
(gdb) x/w 0x60097c 0x60097c <[email protected]+2098532>: 0x0000007b (gdb) x/w 0x600978 0x600978 <[email protected]+2098528>: 0x00000000
所以a
,即在第一次閱讀的變量,在地址0x60097c(因爲0X0000007B是123的十六進制表示,這是我們進入),並b
是0x600978。
仍然在調試器中,我們現在可以修改變量a
,然後繼續執行程序。
(gdb) set *(int *)0x60097c = 1234567 (gdb) continue
返回在要求我們的程序輸入兩個數字:
$ ./ab a: 123 a = 123 b: 5 a = 1234567, b = 5 $
這爲您提供虛擬地址,而不是物理地址。 – 2010-05-29 11:58:21
之前由於部分答案,正常的程序應該不需要擔心物理地址,因此,在虛擬地址空間中運行所有的便利。此外,並非每個虛擬地址都有物理地址,可能屬於映射文件或交換頁面。但是,有時甚至在用戶區看到這種映射可能會很有趣。
爲此,Linux內核通過/proc
中的一組文件公開其映射到userland的映射。該文檔可以找到here。簡短的摘要:
/proc/$pid/maps
提供的附加信息一起的虛擬地址,諸如用於映射文件對應的文件的映射的列表。/proc/$pid/pagemap
提供了有關每個映射頁面的更多信息,包括物理地址(如果存在)。
This website提供了一個C程序,該程序使用此接口轉儲所有正在運行的進程的映射並解釋它的作用。
測試的最小示例:https://stackoverflow.com/questions/17021214/how-to-decode-proc-pid-pagemap-entries-in-linux/45126141#45126141 – 2017-07-16 13:03:57
#include "stdio.h"
#include "unistd.h"
#include "inttypes.h"
uintptr_t vtop(uintptr_t vaddr) {
FILE *pagemap;
intptr_t paddr = 0;
int offset = (vaddr/sysconf(_SC_PAGESIZE)) * sizeof(uint64_t);
uint64_t e;
// https://www.kernel.org/doc/Documentation/vm/pagemap.txt
if ((pagemap = fopen("/proc/self/pagemap", "r"))) {
if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) {
if (fread(&e, sizeof(uint64_t), 1, pagemap)) {
if (e & (1ULL << 63)) { // page present ?
paddr = e & ((1ULL << 54) - 1); // pfn mask
paddr = paddr * sysconf(_SC_PAGESIZE);
// add offset within page
paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1));
}
}
}
fclose(pagemap);
}
return paddr;
}
- 1. 有沒有辦法從用戶空間找到全局變量的物理地址
- 2. 訪問寄存器從用戶空間的物理地址
- 3. linux內核和用戶地址空間
- 4. PAE(物理地址擴展)如何啓用大於4GB的地址空間?
- 5. 我如何在虛擬和物理地址中找到位?
- 6. 如何在C中的Linux上訪問物理地址?
- 7. 如何找出linux下的空閒物理內存量(c)
- 8. 從內核空間傳遞地址到用戶空間
- 9. 在linux內核中虛擬到物理地址的轉換
- 10. 將物理地址映射到虛擬地址linux
- 11. linux命令獲取可用的最大連續物理地址空間
- 12. 虛擬地址空間大小vs物理地址空間大小
- 13. Linux中用戶空間地址的嵌套頁面錯誤
- 14. 如何在內存hexdump中找到變量的地址?
- 15. 在8086微處理器中找到物理地址
- 16. 內存映射IO - 誰將地址映射到物理地址空間?
- 17. 4GB(VM)地址空間如何使用,而交換臺從/到用戶空間到內核空間
- 18. 如何查找變量的地址?
- 19. 物理地址到IP地址
- 20. 邏輯地址(virtaul地址空間)而不是物理地址空間的原因
- 21. 從用戶級空間訪問內核空間中的變量
- 22. 在linux的sk_buff中,skb-> data是物理地址還是虛擬地址?
- 23. JAVA中的物理地址
- 24. 如何使用物理地址
- 25. 如何在Linux中獲取文件中某個位置的物理地址
- 26. 如何使用C#獲取IP地址的物理(MAC)地址?
- 27. 用戶空間中用於Linux中mmap'ed物理內存的memcpy性能不佳
- 28. 如何將elf中的地址轉換爲物理地址
- 29. 如何從ftp地址找到網址
- 30. 如何在flex中找到用戶的IP地址?
大概用/ dev/mem? – user2284570 2014-07-19 08:59:10
一些相關的信息在http://stackoverflow.com/questions/5748492/is-there-any-api-for-determining-the-physical-address-from-virtual-address-in-li – 2015-11-04 02:12:59