6 public align(1) struct MemoryRegionInfo
{
13 public MemoryRegionInfo
[] readMemoryRegions (uint pid
, bool includeStack
=false) {
14 import std
.format
: format
;
16 static byte hexDigit (char ch
) pure nothrow @safe @nogc {
19 ch
>= '0' && ch
<= '9' ?
cast(byte)(ch
-'0') :
20 ch
>= 'A' && ch
<= 'F' ?
cast(byte)(ch
-'A'+10) :
21 ch
>= 'a' && ch
<= 'f' ?
cast(byte)(ch
-'a'+10) :
25 static uint parseHex(T
: const(char)[]) (ref T s
) {
26 while (s
.length
> 0 && s
.ptr
[0] <= ' ') s
= s
[1..$];
27 if (s
.length
== 0 ||
hexDigit(s
.ptr
[0]) < 0) throw new Exception("hex number expected");
30 auto d
= hexDigit(s
.ptr
[0]);
33 if (nr
< res
) throw new Exception("hex overflow");
40 static void consume(T
: const(char)[]) (ref T s
, char ch
) {
41 if (s
.length
== 0 && s
.ptr
[0] != ch
) throw new Exception("'"~ch
~"' expected");
45 static void skipSpaces(T
: const(char)[]) (ref T s
) {
46 if (s
.length
== 0 && s
.ptr
[0] > ' ') throw new Exception("space expected");
47 while (s
.length
> 0 && s
.ptr
[0] <= ' ') s
= s
[1..$];
50 MemoryRegionInfo
[] res
;
51 foreach (char[] ln
; VFile("/proc/%s/maps".format(pid
)).byLine
) {
59 if (start
>= end
) continue;
60 // skip regions with less than 16 bytes of data
61 if (end
-start
< 16) continue;
62 if (ln
.length
< 5) throw new Exception("invalid region description");
63 // skip non-writeable, executable and shared regions
64 if (ln
.ptr
[0] != 'r' || ln
.ptr
[1] != 'w' || ln
.ptr
[2] == 'x' || ln
.ptr
[3] != 'p') continue;
67 // if offset is not 0, it is mmaped region, skip it
68 if (parseHex(ln
) != 0) continue;
69 // if devicehi or devilelo is not 0, it is mmaped region, skip it
71 if (parseHex(ln
) != 0) continue;
73 if (parseHex(ln
) != 0) continue;
74 // if inode is not 0, it is mmaped region, skip it
76 if (parseHex(ln
) != 0) continue;
81 while (name
.length
&& name
[$-1] <= ' ') name
= name
[0..$-1];
84 // can't parse this region, skip it
88 if (name
.length
> 6 && name
[0..6] == "[stack") continue;
90 if (name
.length
> 0 && name
.ptr
[0] == '[') {
91 // specials; allow only "heap"
92 //writefln("**** %08X:%08X <%s>", start, end, name);
93 if (name
.length
< 6 || name
[0..5] != "[heap") continue;
95 //writefln("%08X:%08X <%s>", start, end, name);
96 res
~= MemoryRegionInfo(start
, end
, name
);
103 void main (string[] args) {
105 if (args.length > 1) {
106 import std.conv : to;
107 pid = to!uint(args[1]);
109 auto regs = readMemoryRegions(pid);
111 foreach (const ref reg; regs) total += reg.end-reg.start;
112 writeln(cast(double)total/1024/1024, " megabytes");