<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    so true

    心懷未來,開創未來!
    隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
    數據加載中……

    virtual addr to physical addr

    轉自: http://www.cnblogs.com/pengdonglin137/p/6802108.html
    順便提一句, 通過man 5 proc可以查看proc下各個文件的介紹情況,但由于pagemap是后加的,man里查不到目前
    利用/proc/pid/pagemap將虛擬地址轉換為物理地址
    內核文檔: Documentation/vm/pagemap.txt
    pagemap is a new (as of 2.6.25) set of interfaces in the kernel that allow
    userspace programs to examine the page tables and related information by
    reading files in /proc.
    There are four components to pagemap:
     * /proc/pid/pagemap.  This file lets a userspace process find out which
       physical frame each virtual page is mapped to.  It contains one 64-bit
       value for each virtual page, containing the following data (from
       fs/proc/task_mmu.c, above pagemap_read):
        * Bits 0-54  page frame number (PFN) if present
        * Bits 0-4   swap type if swapped
        * Bits 5-54  swap offset if swapped
        * Bit  55    pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
        * Bit  56    page exclusively mapped (since 4.2)
        * Bits 57-60 zero
        * Bit  61    page is file-page or shared-anon (since 3.5)
        * Bit  62    page swapped
        * Bit  63    page present
       Since Linux 4.0 only users with the CAP_SYS_ADMIN capability can get PFNs.
       In 4.0 and 4.1 opens by unprivileged fail with -EPERM.  Starting from
       4.2 the PFN field is zeroed if the user does not have CAP_SYS_ADMIN.
       Reason: information about PFNs helps in exploiting Rowhammer vulnerability.
       If the page is not present but in swap, then the PFN contains an
       encoding of the swap file number and the page's offset into the
       swap. Unmapped pages return a null PFN. This allows determining
       precisely which pages are mapped (or in swap) and comparing mapped
       pages between processes.
       Efficient users of this interface will use /proc/pid/maps to
       determine which areas of memory are actually mapped and llseek to
       skip over unmapped regions.
     下面是一個工具:
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 #include <assert.h>
     5 #include <errno.h>
     6 #include <stdint.h>
     7 #include <string.h>
     8 
     9 #define PAGEMAP_ENTRY 8
    10 #define GET_BIT(X,Y) (X & ((uint64_t)1<<Y)) >> Y
    11 #define GET_PFN(X) X & 0x7FFFFFFFFFFFFF
    12 
    13 const int __endian_bit = 1;
    14 #define is_bigendian() ( (*(char*)&__endian_bit) == 0 )
    15 
    16 int i, c, pid, status;
    17 unsigned long virt_addr; 
    18 uint64_t read_val, file_offset, page_size;
    19 char path_buf [0x100] = {};
    20 FILE * f;
    21 char *end;
    22 
    23 int read_pagemap(char * path_buf, unsigned long virt_addr);
    24 
    25 int main(int argc, char ** argv){
    26     if(argc!=3){
    27         printf("Argument number is not correct!\n pagemap PID VIRTUAL_ADDRESS\n");
    28         return -1;
    29     }
    30     if(!memcmp(argv[1],"self",sizeof("self"))){
    31         sprintf(path_buf, "/proc/self/pagemap");
    32         pid = -1;
    33     }
    34     else{
    35         pid = strtol(argv[1],&end, 10);
    36         if (end == argv[1] || *end != '\0' || pid<=0){ 
    37             printf("PID must be a positive number or 'self'\n");
    38             return -1;
    39         }
    40     }
    41     virt_addr = strtoll(argv[2], NULL, 16);
    42     if(pid!=-1)
    43         sprintf(path_buf, "/proc/%u/pagemap", pid);
    44 
    45     page_size = getpagesize();
    46     read_pagemap(path_buf, virt_addr);
    47     return 0;
    48 }
    49 
    50 int read_pagemap(char * path_buf, unsigned long virt_addr){
    51     printf("Big endian? %d\n", is_bigendian());
    52     f = fopen(path_buf, "rb");
    53     if(!f){
    54         printf("Error! Cannot open %s\n", path_buf);
    55         return -1;
    56     }
    57 
    58     //Shifting by virt-addr-offset number of bytes
    59     //and multiplying by the size of an address (the size of an entry in pagemap file)
    60     file_offset = virt_addr / page_size * PAGEMAP_ENTRY;
    61     printf("Vaddr: 0x%lx, Page_size: %lld, Entry_size: %d\n", virt_addr, page_size, PAGEMAP_ENTRY);
    62     printf("Reading %s at 0x%llx\n", path_buf, (unsigned long long) file_offset);
    63     status = fseek(f, file_offset, SEEK_SET);
    64     if(status){
    65         perror("Failed to do fseek!");
    66         return -1;
    67     }
    68     errno = 0;
    69     read_val = 0;
    70     unsigned char c_buf[PAGEMAP_ENTRY];
    71     for(i=0; i < PAGEMAP_ENTRY; i++){
    72         c = getc(f);
    73         if(c==EOF){
    74             printf("\nReached end of the file\n");
    75             return 0;
    76         }
    77         if(is_bigendian())
    78             c_buf[i] = c;
    79         else
    80             c_buf[PAGEMAP_ENTRY - i - 1] = c;
    81         printf("[%d]0x%x ", i, c);
    82     }
    83     for(i=0; i < PAGEMAP_ENTRY; i++){
    84         //printf("%d ",c_buf[i]);
    85         read_val = (read_val << 8) + c_buf[i];
    86     }
    87     printf("\n");
    88     printf("Result: 0x%llx\n", (unsigned long long) read_val);
    89     if(GET_BIT(read_val, 63)) {
    90         uint64_t pfn = GET_PFN(read_val);
    91         printf("PFN: 0x%llx (0x%llx)\n", pfn, pfn * page_size + virt_addr % page_size);
    92     } else
    93         printf("Page not present\n");
    94     if(GET_BIT(read_val, 62))
    95         printf("Page swapped\n");
    96     fclose(f);
    97     return 0;
    98 }
    測試:
    用Qemu+vexpress-ca9:
    內存: 1GB, 物理地址范圍: 0x60000000->0x9FFFFFFF
    通過查看/proc/pid/maps獲得進程的地址空間的內存映射情況:
     1 [root@vexpress ~]# cat /proc/746/maps 
     2 00008000-001f3000 r-xp 00000000 b3:01 62         /bin/busybox
     3 001fa000-001fc000 rw-p 001ea000 b3:01 62         /bin/busybox
     4 001fc000-00222000 rw-p 00000000 00:00 0          [heap]
     5 b6c7f000-b6c80000 rw-p 00000000 00:00 0 
     6 b6c80000-b6c8d000 r-xp 00000000 b3:01 174        /lib/libnss_files-2.18.so
     7 b6c8d000-b6c94000 ---p 0000d000 b3:01 174        /lib/libnss_files-2.18.so
     8 b6c94000-b6c95000 r--p 0000c000 b3:01 174        /lib/libnss_files-2.18.so
     9 b6c95000-b6c96000 rw-p 0000d000 b3:01 174        /lib/libnss_files-2.18.so
    10 b6c96000-b6ca1000 r-xp 00000000 b3:01 141        /lib/libnss_nis-2.18.so
    11 b6ca1000-b6ca8000 ---p 0000b000 b3:01 141        /lib/libnss_nis-2.18.so
    12 b6ca8000-b6ca9000 r--p 0000a000 b3:01 141        /lib/libnss_nis-2.18.so
    13 b6ca9000-b6caa000 rw-p 0000b000 b3:01 141        /lib/libnss_nis-2.18.so
    14 b6caa000-b6daa000 rw-p 00000000 00:00 0 
    15 b6daa000-b6dca000 r-xp 00000000 b3:01 129        /lib/ld-2.18.so
    16 b6dca000-b6dd1000 ---p 00020000 b3:01 129        /lib/ld-2.18.so
    17 b6dd1000-b6dd2000 r--p 0001f000 b3:01 129        /lib/ld-2.18.so
    18 b6dd2000-b6dd3000 rw-p 00020000 b3:01 129        /lib/ld-2.18.so
    19 b6dd3000-b6f06000 r-xp 00000000 b3:01 170        /lib/libc-2.18.so
    20 b6f06000-b6f0d000 ---p 00133000 b3:01 170        /lib/libc-2.18.so
    21 b6f0d000-b6f0f000 r--p 00132000 b3:01 170        /lib/libc-2.18.so
    22 b6f0f000-b6f10000 rw-p 00134000 b3:01 170        /lib/libc-2.18.so
    23 b6f10000-b6f13000 rw-p 00000000 00:00 0 
    24 b6f13000-b6f26000 r-xp 00000000 b3:01 177        /lib/libnsl-2.18.so
    25 b6f26000-b6f2d000 ---p 00013000 b3:01 177        /lib/libnsl-2.18.so
    26 b6f2d000-b6f2e000 r--p 00012000 b3:01 177        /lib/libnsl-2.18.so
    27 b6f2e000-b6f2f000 rw-p 00013000 b3:01 177        /lib/libnsl-2.18.so
    28 b6f2f000-b6f31000 rw-p 00000000 00:00 0 
    29 b6f31000-b6f39000 r-xp 00000000 b3:01 154        /lib/libnss_compat-2.18.so
    30 b6f39000-b6f40000 ---p 00008000 b3:01 154        /lib/libnss_compat-2.18.so
    31 b6f40000-b6f41000 r--p 00007000 b3:01 154        /lib/libnss_compat-2.18.so
    32 b6f41000-b6f42000 rw-p 00008000 b3:01 154        /lib/libnss_compat-2.18.so
    33 be958000-be979000 rw-p 00000000 00:00 0          [stack]
    34 bed04000-bed05000 r-xp 00000000 00:00 0          [sigpage]
    35 bed05000-bed06000 r--p 00000000 00:00 0          [vvar]
    36 bed06000-bed07000 r-xp 00000000 00:00 0          [vdso]
    37 ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]
    可以看看0x8000這個虛擬地址對應的物理地址:
    1 [root@vexpress ~]# ./translate 746 0x8000
    2 Big endian? 0
    3 Vaddr: 0x8000, Page_size: 4096, Entry_size: 8
    4 Reading /proc/746/pagemap at 0x40
    5 [0]0x0 [1]0xf8 [2]0x9 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa0 
    6 Result: 0xa00000000009f800
    7 PFN: 0x9f800 (0x9f800000)
    可以看到, 對應的物理頁幀是0x9F800,那么物理地址就是0x9F800000.
    下面我們再做一個實驗, 進程746的地址空間有一部分用來映射libc:
    1 b6dd3000-b6f06000 r-xp 00000000 b3:01 170        /lib/libc-2.18.so
    2 b6f06000-b6f0d000 ---p 00133000 b3:01 170        /lib/libc-2.18.so
    3 b6f0d000-b6f0f000 r--p 00132000 b3:01 170        /lib/libc-2.18.so
    4 b6f0f000-b6f10000 rw-p 00134000 b3:01 170        /lib/libc-2.18.so
    此外, 進程835也會用到libc:
    1 [root@vexpress ~]# cat /proc/835/maps 
    2 ... ...
    3 b6e0b000-b6f3e000 r-xp 00000000 b3:01 170        /lib/libc-2.18.so
    4 b6f3e000-b6f45000 ---p 00133000 b3:01 170        /lib/libc-2.18.so
    5 b6f45000-b6f47000 r--p 00132000 b3:01 170        /lib/libc-2.18.so
    6 b6f47000-b6f48000 rw-p 00134000 b3:01 170        /lib/libc-2.18.so
    7 ... ...
    可以看到, 進程746和835雖然都用了libc,但是對應的虛擬地址卻不同,前者是0xb6dd3000, 而后者是0xb6e0b000, 我們知道對于共享庫, 在內存只會存在一份代碼, 那么物理地址也就是唯一的(代碼段是唯一的,所有調用libc的進程共享,而數據段每個進程一個), 那么進程746的虛擬地址空間的0xb6dd3000(代碼段)跟進程835的虛擬地址空間的0xb6e0b000(代碼段)對應的物理地址應該是同一個, 下面驗證一下:
    進程746:
    1 [root@vexpress ~]# ./translate 746 0xb6dd3000
    2 virt_addr: 0xb6dd3000
    3 Big endian? 0
    4 Vaddr: 0xb6dd3000, Page_size: 4096, Entry_size: 8
    5 Reading /proc/746/pagemap at 0x5b6e98
    6 [0]0x68 [1]0xfa [2]0x9 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa0 
    7 Result: 0xa00000000009fa68
    8 PFN: 0x9fa68 (0x9fa68000)
    可以看到,物理地址是0x9FA68000
    進程835:
    1 [root@vexpress ~]# ./translate 835 0xb6e0b000
    2 virt_addr: 0xb6e0b000
    3 Big endian? 0
    4 Vaddr: 0xb6e0b000, Page_size: 4096, Entry_size: 8
    5 Reading /proc/835/pagemap at 0x5b7058
    6 [0]0x68 [1]0xfa [2]0x9 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa0 
    7 Result: 0xa00000000009fa68
    8 PFN: 0x9fa68 (0x9fa68000)
    可以看到, 物理地址也是0x9FA68000, 從而證明了我們的猜想。
    =========================================================================
    轉自:http://blog.sina.com.cn/s/blog_628cc2b70101c8zu.html
    pagemap是linux中一組新的接口集合,他通過讀取/proc中的文件允許用戶態的程序檢查頁表以及相關的信息。
    它主要有3個組成部分:
    (1)/proc/pid/pagemap:這個文件允許一個用戶態的進程查看到每個虛擬頁映射到的物理頁,每一個虛擬頁都包含了一個64位的值,信息如下:
    Bits 0-54: page frame number(PFN) if present
    Bits 0-4:  swap type if swapped
    Bits 5-54: swap offset if swapped
    Bits 55-60:page shift 
    Bit 61:   reserved ofr future use
    Bit 62:   page swapped
    Bit 63:   page present
        如果這個page是在swap狀態,然后PFN包含一個編碼的交換文件號碼,再將頁的offset值寫入swap中。沒有映射的頁就返回一個null PFN。這樣就可以精確判斷一個page是映射的或是swap的,并且可以比較不同進程間的映射頁。
        我們可以利用/proc/pid/maps去判斷內存中哪塊區域是被映射的,然后通過llseek就可以跳過沒有映射的區域。
    (2)/proc/kpagecount:這個文件包含一個64位值,該值表示每個page被映射的次數,通過PFN索引。
    (3)/proc/kpageflags:這個文件包含每一個page的64位的標記集,通過PFN索引。
    通過pagemap查看一個進程的內存使用情況的一般步驟如下:
    (1)讀取/proc/pid/maps文件確定內存空間的哪個部分被映射;
    (2)選擇你感興趣的maps,比如全部、一部分或者堆棧什么的;
    (3)打開/proc/pid/pagemap,定位到你準備去檢查的pages;
    (4)通過pagemap讀取每一個page的64位值;
    (5)打開/proc/kpagecount以及/proc/kpageflags。對于每一個PFN你只要去讀,定位到文件中的那個入口,然后讀取你想要的數據。

    posted on 2017-08-17 17:33 so true 閱讀(214) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久精品成人免费国产片小草| 亚洲一区综合在线播放| 亚洲乱色伦图片区小说| 青青草a免费线观a| 亚洲伦理中文字幕| 永久免费AV无码国产网站 | 天天操夜夜操免费视频| 亚洲午夜电影一区二区三区| 亚洲精品视频在线观看免费| 亚洲乱人伦精品图片| 久久久久国产精品免费免费搜索 | ssswww日本免费网站片| 亚洲天堂中文字幕在线| 中文字幕免费在线观看动作大片| 国产亚洲一区二区在线观看| 久久黄色免费网站| 亚洲免费福利视频| 日韩特黄特色大片免费视频| 四虎影视久久久免费观看| 77777亚洲午夜久久多人| 久久久久久毛片免费播放| 久久精品国产亚洲αv忘忧草 | 91网站免费观看| 亚洲国产欧美国产综合一区 | 中国极品美軳免费观看| 亚洲精品福利在线观看| 女性无套免费网站在线看| 一区二区免费国产在线观看| 中文字幕久久亚洲一区| 18禁美女黄网站色大片免费观看| 亚洲人成人伊人成综合网无码| 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 在线涩涩免费观看国产精品| 亚洲六月丁香六月婷婷蜜芽| 四虎影视在线永久免费观看| 国产亚洲免费的视频看| 成人亚洲国产va天堂| 国产成人亚洲精品狼色在线| 99久久这里只精品国产免费| 全部一级一级毛片免费看| 亚洲精品美女久久久久|