2013-06-10 10 views
8

Sto cercando di decifrare come usare/proc/pid/pagemap per ottenere l'indirizzo fisico di un determinato set di pagine. Supponiamo dal/proc/pid/maps, ottengo l'indirizzo virtuale afa2d000-afa42000 che corrisponde all'heap. La mia domanda è come utilizzare queste informazioni per attraversare il file di pagemap e trovare i frame di pagina fisici corrispondono all'indirizzo afa2d000-afa42000.Come decodificare le voci/proc/pid/pagemap in Linux?

La voce/proc/pid/pagemap è in formato binario. C'è qualche strumento per aiutare l'analisi di questo file?

risposta

2

Prova questa http://www.eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/ Si può analizzare il PageMap per voi, per esempio, se l'indirizzo virtuale siete interessati è nel mucchio che è 0x055468: = 0004c000-0005a000 rw-p 00000000 00:00 0 [ mucchio] : 86000000000FD6D6 : 0.600.000 miliardi
: 0.600.000 miliardi
: 86000000000FE921
: 86000000000FE922
: 0.600.000 miliardi
: 86000000000FD5AD
0.123.516,41 mila: 86000000000FD6D4
: 86000000000FD5F8
: 86000000000FD5FA => 9

Supponiamo che la dimensione della pagina di 4KB e (0x055468 - 0x4c000) mod 4K = 9, Così il numero di frame di pagina della pagina è la pagina 9 telai ==>: 86000000000FD5FA Quindi la PFN fisico è 0xFD5FA000 (prendere l'ultima 55 bit e tempi di dimensione della pagina) più l'offset: (0x055468 - 0x4c000 - 9 * 4K) = 0x468 ==> l'addr fisico è 0xFD5FA000 + 0x468 = 0xFD5FA468

+0

La pagina analyse.cpp è stata compilata correttamente, a parte la mancanza #include Viene visualizzato questo errore del compilatore: 'page-analyze.cpp: nella funzione 'void make_short_name (char *, const char *)': page-analyze.cpp: 135: 35: errore: assegnazione della posizione di sola lettura '* strchr (b, 93)' make: ** * [page-analyze] Errore 1' – JohnnyFromBF

+0

Mi dispiace, link a parte, la risposta dovrebbe avere un senso, ma l'IMO è scritto molto male. Formattazione richiesta, la fonte dei dati non è chiara/dimostrata ... anche che "mod" deve essere "div" – nhed

1

documentazione del kernel di Linux

Linux kernel doc descrive il formato: https://github.com/torvalds/linux/blob/v4.9/Documentation/vm/pagemap.txt

* 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 

C funzione parser

GitHub upstream.

#define _XOPEN_SOURCE 700 
#include <fcntl.h> /* open */ 
#include <stdint.h> /* uint64_t */ 
#include <stdlib.h> /* size_t */ 
#include <unistd.h> /* pread, sysconf */ 

typedef struct { 
    uint64_t pfn : 54; 
    unsigned int soft_dirty : 1; 
    unsigned int file_page : 1; 
    unsigned int swapped : 1; 
    unsigned int present : 1; 
} PagemapEntry; 

/* Parse the pagemap entry for the given virtual address. 
* 
* @param[out] entry  the parsed entry 
* @param[in] pagemap_fd file descriptor to an open /proc/pid/pagemap file 
* @param[in] vaddr  virtual address to get entry for 
* @return 0 for success, 1 for failure 
*/ 
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) 
{ 
    size_t nread; 
    ssize_t ret; 
    uint64_t data; 

    nread = 0; 
    while (nread < sizeof(data)) { 
     ret = pread(pagemap_fd, &data, sizeof(data), 
       (vaddr/sysconf(_SC_PAGE_SIZE)) * sizeof(data) + nread); 
     nread += ret; 
     if (ret <= 0) { 
      return 1; 
     } 
    } 
    entry->pfn = data & (((uint64_t)1 << 54) - 1); 
    entry->soft_dirty = (data >> 54) & 1; 
    entry->file_page = (data >> 61) & 1; 
    entry->swapped = (data >> 62) & 1; 
    entry->present = (data >> 63) & 1; 
    return 0; 
} 

Esempio programmi eseguibili che lo utilizzano:

0

In caso gente vuole per fare questo da Rust, ho aggiunto un'implementazione Rust in modo da poter facilmente navigare /proc/$pid/maps e /proc/$pid/pagemap: https://crates.io/crates/vm-info

Problemi correlati