1 package Linux
::Proc
::Maps
;
2 # ABSTRACT: Read and write /proc/[pid]/maps files
3 # KEYWORDS: linux proc procfs
9 our $VERSION = '0.002'; # VERSION
12 use Exporter
qw(import);
13 use namespace
::clean
-except
=> [qw(import)];
15 our @EXPORT_OK = qw(read_maps write_maps parse_maps_single_line format_maps_single_line);
19 my %args = @_ == 1 ? (pid
=> $_[0]) : @_;
21 my $file = $args{file
};
23 if (!$file and my $pid = $args{pid
}) {
24 if ($pid =~ /^\d+$/) {
25 require File
::Spec
::Functions
;
26 my $procfs = $args{mnt
} || $ENV{PERL_LINUX_PROC_MAPS_MOUNT
} ||
27 File
::Spec
::Functions
::catdir
(File
::Spec
::Functions
::rootdir
(), 'proc');
28 $file = File
::Spec
::Functions
::catfile
($procfs, $pid, 'maps');
35 $file or croak
'Filename or PID required';
36 open(my $fh, '<:encoding(UTF-8)', $file) or croak
"Open failed ($file): $!";
40 while (my $line = <$fh>) {
43 my $region = parse_maps_single_line
($line);
46 push @regions, $region;
54 my $regions = shift or croak
'Regions required';
57 ref $regions eq 'ARRAY' or croak
'Regions must be an arrayref';
61 for my $region (@$regions) {
62 $out .= format_maps_single_line
($region);
65 # maybe print out the memory regions to a filehandle
67 if (!$fh and my $file = $args{file
}) {
68 open($fh, '>:encoding(UTF-8)', $file) or croak
"Open failed ($file): $!";
70 print $fh $out if $fh;
76 sub parse_maps_single_line
{
77 my $line = shift or croak
'Line from a maps file required';
81 my ($addr1, $addr2, $read, $write, $exec, $shared, $offset, $device, $inode, $pathname) = $line =~ m
{
83 ([[:xdigit
:]]+)-([[:xdigit
:]]+)
84 \s
+ ([r-
])([w-
])([x-
])([sp
])
86 \s
+ ([[:xdigit
:]]+:[[:xdigit
:]]+)
93 no warnings
'portable'; # for hex() on 64-bit perls
96 address_start
=> hex($addr1),
97 address_end
=> hex($addr2),
99 write => 'w' eq $write,
100 execute
=> 'x' eq $exec,
101 shared
=> 's' eq $shared,
102 offset
=> hex($offset),
105 pathname
=> $pathname || '',
110 sub format_maps_single_line
{
111 my $region = shift or croak
'Region required';
113 my @args = @{$region}{qw(address_start address_end read write execute shared offset device inode)};
114 $args[2] = $args[2] ? 'r' : '-';
115 $args[3] = $args[3] ? 'w' : '-';
116 $args[4] = $args[4] ? 'x' : '-';
117 $args[5] = $args[5] ? 's' : 'p';
119 return sprintf("%-72s %s\n", sprintf("%x-%x %s%s%s%s %08x %s %d", @args), $region->{pathname
});
133 Linux::Proc::Maps - Read and write /proc/[pid]/maps files
141 use Linux::Proc::Maps qw(read_maps);
144 my $vm_regions = read_maps(pid => $$);
146 # by pid with explicit procfs mount:
147 my $vm_regions = read_maps(mnt => '/proc', pid => 123);
150 my $vm_regions = read_maps(file => '/proc/456/maps');
154 This module reads and writes F</proc/[pid]/maps> files that contain listed mapped memory regions.
160 Read and parse a maps file, returning an arrayref of regions (each represented as a hashref). See
161 L</parse_maps_single_line> to see the format of the hashrefs.
163 my $regions = read_maps(%args);
171 C<file> - Path to maps file
175 C<pid> - Process ID (one of C<file> or C<pid> is required)
179 C<mnt> - Absolute path where L<proc(5)> is mounted (optional, default: C</proc>)
185 Returns a string with the contents of a maps file from the memory regions passed.
187 my $file_content = write_maps(\@regions, %args);
189 This is the opposite of L</read_maps>.
197 C<fh> - Write maps to this open file handle (optional)
201 C<file> - Open this filepath and write maps to that file (optional)
205 =head2 parse_maps_single_line
207 Parse and return a single line from a maps file into a region represented as a hashref.
209 my $region = parse_maps_single_line($line);
213 # address perms offset dev inode pathname
214 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
219 address_start => 134512640,
220 address_end => 134569984,
228 pathname => '/usr/sbin/gpm',
231 =head2 format_maps_single_line
233 Return a single line for a maps file from a region represented as a hashref.
235 my $line = format_maps_single_line(\%region);
237 This is the opposite of L</parse_maps_single_line>.
241 L<proc(5)> describes the file format.
245 Integer overloading may occur if you try to parse memory regions from address spaces larger than
246 your current architecture (or perl) supports. This is currently not fatal, though you will get
247 warnings from perl that you probably shouldn't ignore.
251 Please report any bugs or feature requests on the bugtracker website
252 L<https://github.com/chazmcgarvey/Linux-Proc-Maps/issues>
254 When submitting a bug or request, please include a test-file or a
255 patch to an existing test-file that illustrates the bug or desired
260 Charles McGarvey <chazmcgarvey@brokenzipper.com>
262 =head1 COPYRIGHT AND LICENSE
264 This software is copyright (c) 2016 by Charles McGarvey.
266 This is free software; you can redistribute it and/or modify it under
267 the same terms as the Perl 5 programming language system itself.