Dump de memoria de otro proceso
Astor Giacomo
agiacom en optonline.net
Mie Ago 24 02:41:01 CLT 2005
On Tuesday 23 August 2005 05:29 pm, Bernardo Suarez wrote:
[Mis disculpas de antemano si mensajes como este no son bienvenidos en
esta lista. En ese caso no repetire la ofensa!]
[...]
> Por lo tanto me ayudaría mucho alguna utilidad que me permita hacer un
> dump hexadecimal de la memoria usada por otro proceso. Como no he
> podido detectar que parte del programa se come la memoria, quizas sea
> una buena pista saber con que la estoy llenando... Alguien
> tiene/conoce/sabe como hacer algo así?
Perl es conocido por ser extremadamente ineficiente en lo que a uso de memoria
se refiere.
Puedes tratar con lo de mas abajo. Aunque escrito a la rapida y, por eso,
bastante rustico, hace lo que necesitas (o pareces necesitar).
$ gcc -o memdump memdump.c
$ cat /proc/$$/maps
[...]
049bc000-049be000 rw-p 049bc000 00:00 0
08047000-080d8000 r-xp 00000000 03:41 145525 /bin/bash
080d8000-080de000 rw-p 00090000 03:41 145525 /bin/bash
080de000-080e3000 rw-p 080de000 00:00 0
09bea000-09c2c000 rw-p 09bea000 00:00 0 <-- el "heap"
b7de1000-b7de3000 rw-p b7de1000 00:00 0
[...]
$ ./memdump $$ 0x09bea000
[...]
Ojo que al terminar `memdump' con ^C o con "q" en less(1)
tienes que continuar manualmente el otro proceso (con
kill -CONT $pid). Arreglar eso es tarea para el lector :-)
Ocioso a las 2:20am,
-ag
---
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#define SYSERR(x,t) \
if ((x) < 0) { perror(t); pexit(1); }
pid_t mem_pid = 0;
void pexit(int x)
{
if (mem_pid) ptrace(PTRACE_DETACH, mem_pid, 0, 0);
exit(x);
}
void memdump(int f, off_t offset, int bin)
{
unsigned char data[16];
int sofar = 0, n, k;
SYSERR(lseek(f, offset, SEEK_SET), "lseek");
while ((n = read(f, data, sizeof(data))) > 0) {
const unsigned char *p;
if (bin) {
write(1, data, n);
continue;
}
printf("%08lx - ", offset + sofar);
for (p = data; p < &data[n]; p++)
printf("%02x ", *p);
printf("| ");
for (p = data; p < &data[n]; p++)
printf("%c", isprint(*p) ? *p : '.');
putchar('\n');
sofar += n;
}
}
int main(int argc, char **argv)
{
int r, status, fd, bin;
pid_t pid;
off_t off;
char buf[32];
if (argc < 3) {
printf("Usage: %s PID ADDRESS\n", argv[0]);
exit(1);
}
pid = atoi(argv[1]);
off = (off_t)strtol(argv[2], 0, 0);
bin = argv[3] ? atoi(argv[3]) : 0;
snprintf(buf, sizeof(buf), "/proc/%u/mem", pid);
SYSERR(fd = open(buf, O_RDONLY), buf);
SYSERR(r = ptrace(PTRACE_ATTACH, pid, 0, 0), "ptrace");
while ((r = waitpid(pid, &status, WUNTRACED)) < 0 && errno == EINTR)
;
mem_pid = pid;
SYSERR(r, "waitpid");
if (!WIFSTOPPED(status)) {
fprintf(stderr, "Child not stopped!?\n");
exit(1);
}
memdump(fd, off, bin);
close(fd);
pexit(0);
}
Más información sobre la lista de distribución Linux