Membuang memori proses linux ke file

Jawaban:

46

Saya tidak yakin bagaimana Anda membuang semua memori ke file tanpa melakukan ini berulang kali (jika ada yang tahu cara otomatis untuk mendapatkan gdb untuk melakukan ini tolong beri tahu saya), tetapi yang berikut ini berfungsi untuk satu batch memori dengan asumsi Anda tahu pid:

$ cat /proc/[pid]/maps

Ini akan dalam format (contoh):

00400000-00421000 r-xp 00000000 08:01 592398                             /usr/libexec/dovecot/pop3-login
00621000-00622000 rw-p 00021000 08:01 592398                             /usr/libexec/dovecot/pop3-login
00622000-0066a000 rw-p 00622000 00:00 0                                  [heap]
3e73200000-3e7321c000 r-xp 00000000 08:01 229378                         /lib64/ld-2.5.so
3e7341b000-3e7341c000 r--p 0001b000 08:01 229378                         /lib64/ld-2.5.so

Pilih satu batch memori (jadi misalnya 00621000-00622000) kemudian gunakan gdb sebagai root untuk melampirkan ke proses dan membuang memori itu:

$ gdb --pid [pid]
(gdb) dump memory /root/output 0x00621000 0x00622000

Kemudian menganalisis / root / output dengan perintah string, semakin sedikit Anda ingin Putty seluruh layar Anda.

James L
sumber
1
Apakah ada cara untuk melakukan ini hanya dalam bash / sh tanpa gdb?
Programming4life
3
@ Programming4life gcore (1)
julian
51

Saya telah membuat skrip yang menyelesaikan tugas ini.

Idenya berasal dari jawaban James Lawrie dan posting ini: http://www.linuxforums.org/forum/programming-scripting/52375-reading-memory-other-processes.html#post287195

#!/bin/bash

grep rw-p /proc/$1/maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
| while read start stop; do \
    gdb --batch --pid $1 -ex \
        "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
done

letakkan ini dalam file (mis. "dump-all-memory-of-pid.sh") dan membuatnya dapat dieksekusi

pemakaian: ./dump-all-memory-of-pid.sh [pid]

Output dicetak ke file dengan nama: pid-startaddress-stopaddress.dump

Ketergantungan: gdb

A. Nilsson
sumber
2
Luar biasa! Hanya menggunakannya untuk menemukan skrip mana yang dijalankan instance misterius bash.
Tobia
Mengapa Anda hanya mengambil dan membuang rentang dengan rw-pizin?
mxmlnkn
@mxmlnkn Itu data ( rw-p), rentang lain untuk kode ( r-xp). Jika Anda ingin dump keduanya, maka maju dan tukar grepmisalnya cat.
A. Nilsson
39

mencoba

    gcore $pid

di mana $pidjumlah aktual pid; untuk info lebih lanjut lihat:info gcore

mungkin memerlukan beberapa waktu agar dump terjadi, dan beberapa memori mungkin tidak dapat dibaca, tetapi cukup bagus ... perlu diketahui juga bahwa itu dapat membuat file besar, saya baru saja membuat file 2GB seperti itu ..

Aquarius Power
sumber
1
Apakah gcoremembuang file jarang?
CMCDragonkai
3

man proc mengatakan:

/ proc / [pid] / mem File ini dapat digunakan untuk mengakses halaman memori proses melalui open (2), read (2), dan lseek (2).

Mungkin itu bisa membantu Anda

Dom
sumber
1
Itu tidak cukup, membaca proses lain membutuhkan kombinasi / proc / <pid> / {mem, * maps}, ptrace, dan beberapa penanganan sinyal untuk menghindari menggantungnya proses target.
Tobu
@Tobu Memang . Saya menulis naskah bukti konsep .
Gilles 'SANGAT berhenti menjadi jahat'
3

Saya membuat program saya sendiri untuk membuang seluruh memori proses juga, itu dalam C sehingga dapat dikompilasi silang ke Android, yang saya butuhkan.

Anda juga dapat menentukan alamat IP dan port tcp. Kode sumber di sini .

Tal Aloni
sumber
2

Solusi bash murni:

procdump () 
{ 
    cat /proc/$1/maps | grep "rw-p" | awk '{print $1}' | ( IFS="-"
    while read a b; do
        count=$(( bd-ad ))
        ad=$(printf "%llu" "0x$a")
        bd=$(printf "%llu" "0x$b")
        dd if=/proc/$1/mem bs=1 skip=$ad count=$count of=$1_mem_$a.bin
    done )
}

Penggunaan: PID procdump

untuk dump bersih:

procdump () 
{ 
    cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
    while read a b; do
        ad=$(printf "%llu" "0x$a")
        bd=$(printf "%llu" "0x$b")
        dd if=/proc/$1/mem bs=1 skip=$ad count=$(( bd-ad )) of=$1_mem_$a.bin
    done )
}
Zibri
sumber
Jadi, dari apa yang saya pahami, ide di balik dump cleaner adalah bahwa hanya file dalam memori yang memiliki ukuran yang melekat pada wilayah memori berbeda dengan memori aplikasi aktual, yang memiliki ukuran 0 (karena ukuran sebenarnya ukuran yang digunakan tidak diketahui oleh OS).
mxmlnkn
Satu masalah yang saya miliki dengan skrip ini adalah bahwa blocksize dari 1 mengarah ke bandwidth yang sangat lambat ~ 30kB / s dibandingkan dengan menggunakan blocksize yang sama dengan ukuran halaman (4096 untuk saya) yang saya dapatkan ~ 100MB / s! Lihat di sini . getconf PAGESIZEdigunakan untuk mendapatkan ukuran halaman dan kemudian alamat dan jumlah dibagi dengan itu.
mxmlnkn
0

Jika Anda ingin membuang segmen memori terpisah dari proses yang berjalan tanpa membuat file inti besar (katakanlah dengan gcore), Anda dapat menggunakan alat kecil dari sini . Ada juga satu liner di README jika Anda ingin membuang semua segmen yang dapat dibaca ke dalam file terpisah.

Nopius
sumber