Volcar la memoria de un proceso de Linux a un archivo

Respuestas:

46

No estoy seguro de cómo volcar toda la memoria en un archivo sin hacer esto repetidamente (si alguien conoce una forma automatizada de hacer que gdb haga esto, hágamelo saber), pero lo siguiente funciona para cualquier lote de memoria, suponiendo que sepa el pid:

$ cat /proc/[pid]/maps

Esto estará en el formato (ejemplo):

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

Elija un lote de memoria (por ejemplo, 00621000-00622000), luego use gdb como raíz para adjuntar al proceso y volcar esa memoria:

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

Luego analice / root / output con el comando de cadenas, menos quiere el PuTTY en toda su pantalla.

James L
fuente
1
¿Hay alguna manera de hacer esto en bash / sh sin gdb?
Programming4life
3
@ Programming4life gcore (1)
julian
51

Hice un script que realiza esta tarea.

La idea proviene de la respuesta de James Lawrie y esta publicación: 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

poner esto en un archivo (por ejemplo, "dump-all-memory-of-pid.sh") y hacerlo ejecutable

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

La salida se imprime en archivos con los nombres: pid-startaddress-stopaddress.dump

Dependencias: gdb

A. Nilsson
fuente
2
¡Increíble! Solo lo usé para descubrir qué script estaba ejecutando una misteriosa instancia de bash.
Tobia
¿Por qué solo estás buscando y volcando rangos con rw-ppermisos?
mxmlnkn
@mxmlnkn Eso es data ( rw-p), los otros rangos son para código ( r-xp). Si desea un volcado de ambos, entonces continúe e intercambie greppor ej cat.
A. Nilsson
39

tratar

    gcore $pid

donde $pides el número real del pid; para más información ver:info gcore

puede tomar algún tiempo para que ocurra el volcado, y algo de memoria puede no ser legible, pero es lo suficientemente bueno ... tenga en cuenta también que puede crear archivos grandes, acabo de crear un archivo de 2GB de esa manera ...

Poder de acuario
fuente
1
¿Se está gcorevolcando un archivo escaso?
CMCDragonkai
3

man proc dice:

/ proc / [pid] / mem Este archivo se puede utilizar para acceder a las páginas de la memoria de un proceso a través de open (2), read (2) y lseek (2).

Puede que esto te ayude

Dom
fuente
1
Eso no es suficiente, leer otro proceso necesita una combinación de / proc / <pid> / {mem, * maps}, ptrace y algo de manejo de la señal para evitar colgar el proceso de destino.
Tobu
@Tobu De hecho . Escribí un guión de prueba de concepto .
Gilles 'SO- deja de ser malvado'
3

Hice mi propio programa para volcar toda la memoria del proceso también, está en C para que pueda compilarse en Android, que es lo que necesitaba.

También puede especificar la dirección IP y el puerto tcp. Código fuente aquí .

Tal Aloni
fuente
2

Solución pura de bash:

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 )
}

Uso: PID procdump

para un vertedero más limpio:

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
fuente
Entonces, por lo que entiendo, la idea detrás del volcado del limpiador es que solo los archivos en memoria tienen un tamaño adjunto a la región de memoria en contraste con la memoria de la aplicación real, que tiene un tamaño 0 (ya que el tamaño realmente utilizado es desconocido por el OS).
mxmlnkn
Un problema que tengo con este script es que el tamaño de bloque de 1 conduce a un ancho de banda de inaceptablemente lento ~ 30kB / s en comparación con el uso de un tamaño de bloque igual al tamaño de página (4096 para mí) para el que obtengo ~ 100MB / s. Ver aquí . getconf PAGESIZEse usa para obtener el tamaño de página y luego las direcciones y los recuentos se dividen por él.
mxmlnkn
0

Si desea volcar un segmento de memoria separado del proceso en ejecución sin crear un archivo central enorme (digamos con gcore), puede usar una pequeña herramienta desde aquí . También hay una línea en README si desea volcar todos los segmentos legibles en archivos separados.

Nopio
fuente