#! /usr/bin/perl use strict; use warnings; use POSIX qw ( SIGCONT ); my $pid = shift; my $base = "/proc/$pid"; open(my $mem_fh, "$base/mem") || die "$base/mem: $!"; open(my $maps_fh, "$base/maps") || die "$base/maps: $!"; require 'syscall.ph'; my $result = syscall(&SYS_ptrace, 16, int($pid), 1, 0); if ($result == -1) { die "Error: $!\n"; } while (<$maps_fh>) { my ($start, $end) = map {hex($_)} /^(\w+)-(\w+)/; dump_range_seek($mem_fh, $start, $end - $start); } # wake the patient back up kill(SIGCONT(), $pid); sub dump_range_seek { my $fh = shift; my $start = shift; my $len = shift; my $seek = sysseek($fh, $start, 0); die "seek, $!" unless defined($seek); # warn "seek = $seek"; my $buf; while ($len) { my $chunk = $len > 4096 ? 4096 : $len; # warn "reading $chunk\n"; my $read = sysread($fh, $buf, $chunk); die "$!" unless defined($read); die "read 0" unless $read; $len -= $read; print $buf; } }