Show processes, too, and write results to fixed filename on storage card.
[wincetools.git] / inspection / virtual-query-imager.py
1 import fileinput
2 import Image, ImageDraw, ImageFont, ImageOps
3
4
5 # Pagesize
6 psize = 4096
7
8 # A column is 32MB
9 p_per_col = 32*1024*1024/psize
10 # 4 GB address space.
11 slots = 2*1024*1024*1024/psize/p_per_col
12
13 slotwidth = 60
14 pheight = 1
15
16 # colors:
17
18 size = p_per_col * pheight, slotwidth * slots
19
20 im = Image.new ("RGB", size)
21
22 draw = ImageDraw.Draw(im)
23 draw.rectangle ((0,0) + im.size, fill="#ffffff")
24
25
26 def getcolor (state, prot, prot_, type):
27     if state == "free":
28         return "#cccccc"
29     if state == "reserve":
30         if type == "image":
31             return "#88ff88"
32         if type == "private":
33             return "#ff8888"
34         if type == "mapped":
35             return "#8888ff"
36         return "#ffff00"
37     if state == "commit":
38         if type == "image":
39             return "#44dd44"
40         if type == "private":
41             return "#dd4444"
42         if type == "mapped":
43             return "#4444dd"
44         return "#ffff00"
45     return "#ffff00"
46
47     # alc-base   alc-prot address    size       state    protect  type     
48     # 0x00000000 --- ---  0x00001000 0x0000f000 free     --- ---  unknown  
49     # 0x00010000 --- ---  0x00014000 0x0000a000 reserve  --- ---  image    
50     # 0x00000000 --- ---  0x0001e000 0x017a2000 free     --- ---  unknown  
51     # 0x017c0000 --- ---  0x017c0000 0x000fe000 reserve  --- ---  private  
52     # 0x017c0000 --- ---  0x018be000 0x00002000 commit   rw- ---  private  
53     # 0x018c0000 --- ---  0x018c0000 0x00002000 commit   rw- -n-  private  
54
55
56 def upperleft (col, row):
57     col = slots - col - 1
58     return (row * pheight, col * slotwidth)
59
60 def lowerright (col, row):
61     col = slots - col - 1
62     return ((row + 1) * pheight - 1, (col + 1) * slotwidth - 1)
63
64
65 def drawit_ (draw, pstart, pstop, state, prot, prot_, type):
66     col = pstart / p_per_col
67     pstart = pstart - col * p_per_col
68     # inclusive now
69     pstop = (pstop - col * p_per_col) - 1
70
71     # Same col for pstop, ensured by drawit
72     color = getcolor (state, prot, prot_, type)
73     draw.rectangle (upperleft(col, pstop) + lowerright (col, pstart),
74                     color)
75    
76
77 def drawit (draw, addr, size, state, prot, prot_, type):
78     if addr >= 2*1024*1024*1024:
79         return
80     
81     end = addr + size
82     while addr < end:
83         next = ((addr + p_per_col) / p_per_col) * p_per_col
84         if next > end:
85             next = end
86         drawit_ (draw, addr, next, state, prot, prot_, type)
87         addr = next
88
89 process = [''] * 32
90 threads = [0] * 32
91 mode = 0
92 for line in fileinput.input():
93     if mode == 0:
94         field = line.split();
95         if field[0] == "alc-base":
96             mode = 1
97             continue
98         if field[0] == "Process":
99             continue
100         # Process                               PID Base Priority # Threads Base Addr Access Key
101         # NK.EXE                            FFFF002             3         2  C2000000          1
102         # filesys.exe                       FFEEE5E             3        18   4000000          2
103         # akonadi_agent_server             6CD3C9B6             3         1   6000000          4
104         base = int(field[4], 16)
105         idx = base / (32*1024*1024) - 2;
106         if idx >= 0 and idx < 32:
107             process[idx] = field[0]
108             threads[idx] = int(field[3])
109     else:
110         if line[0] != '0':
111             continue
112         # alc-base   alc-prot address    size       state    protect  type     
113         # 0x00000000 --- ---  0x00001000 0x0000f000 free     --- ---  unknown  
114         # 0x00010000 --- ---  0x00014000 0x0000a000 reserve  --- ---  image    
115         # 0x00000000 --- ---  0x0001e000 0x017a2000 free     --- ---  unknown  
116         # 0x017c0000 --- ---  0x017c0000 0x000fe000 reserve  --- ---  private  
117         # 0x017c0000 --- ---  0x018be000 0x00002000 commit   rw- ---  private  
118         # 0x018c0000 --- ---  0x018c0000 0x00002000 commit   rw- -n-  private  
119
120         fields = line.split()
121         addr, size, state, prot, prot_, type = fields[3:]
122         addr = int(addr, 16) / 4096
123         size = int(size, 16) / 4096
124
125         drawit (draw, addr, size, state, prot, prot_, type)
126         
127
128 # Create grid.
129 for col in xrange(slots):
130     draw.line ((0, col*slotwidth) + (im.size[0], col*slotwidth), fill="#666666")
131 for col in xrange(3):
132     draw.rectangle ((0, (col+1)*(slots/4)*slotwidth - slotwidth/16)
133                     + (im.size[0], (col+1)*(slots/4)*slotwidth + slotwidth/16), fill="#666666")
134 for row in xrange(31):
135     draw.line (((row+1)*(p_per_col/32)*pheight, 0) + (((row+1)*(p_per_col/32))*pheight, im.size[1]), fill="#666666")
136
137 del draw
138
139 # Compose documented image.
140 fsize = (im.size[0] + 30 * slotwidth, im.size[1] + 6 * slotwidth)
141 ulpaste = (28*slotwidth, 3*slotwidth)
142 fim = Image.new ("RGB", fsize)
143 draw = ImageDraw.Draw(fim)
144
145 draw.rectangle ((0,0) + fim.size, fill="#ffffff")
146 draw.rectangle ((ulpaste[0]-2, ulpaste[1]-2) + (ulpaste[0] + im.size[0] + 2, ulpaste[1] + im.size[1] + 2), fill="#000000")
147 fim.paste (im, ulpaste)
148
149 fs = int (slotwidth * 2 / 3)
150 dpf = ImageFont.truetype ("datapro.ttf", int(fs * 1.5))
151 draw.text((slotwidth/2,slotwidth), "Virtual Memory Map of Windows CE", fill="#000000", font=dpf)
152
153 dpf = ImageFont.truetype ("datapro.ttf", fs)
154
155 def getrow(i):
156     return 5 + ulpaste[1] + im.size[1] - slotwidth * (i + 1)
157
158 for i in xrange(slots):
159     draw.text ((ulpaste[0] - 6 * slotwidth, getrow(i) ),
160                "0x%08x" % (i * 0x02000000), fill="#444444", font=dpf)
161
162 for row in xrange(32):
163     txt=Image.new("L", (600,60))
164     d = ImageDraw.Draw(txt)
165     d.text ((0,0), "0x%08x" % (row * 0x00100000), fill=255, font=dpf)
166     del d
167     rtxt = txt.rotate (17.5, expand=1)
168     fim.paste (ImageOps.colorize(rtxt, "#ffffff", "#444444"),
169                (ulpaste[0] + (row*(p_per_col/32)*pheight), ulpaste[1] - 4*slotwidth), rtxt)
170     del txt
171     del rtxt
172
173 #draw.text ((ulpaste[0] + 0x00011000 * p_per_col*pheight / (32*1024*1024), ulpaste[1] + 65*slotwidth),
174 #           "Code/Data", fill="#000000", font=dpf)
175 #draw.text ((ulpaste[0] + 0x018C0000 * p_per_col*pheight / (32*1024*1024), ulpaste[1] + 65*slotwidth),
176 #           "Stack/Heap", fill="#000000", font=dpf)
177
178               
179 def writerow(i, str):
180     draw.text ((10 * slotwidth, getrow(i) ), str, fill="#000000", font=dpf)
181
182 writerow (0, "Slot  0: Active Process")
183 writerow (1, "Slot  1: ROM Image")
184 for i in xrange (31):
185     writerow (2 + i, "Slot %2i: Process %i" % (i + 2, i))
186     if process[i] != "":
187         if threads[i] > 1:
188             writerow (2 + i, "                                     %s (%i threads)" % (process[i], threads[i]))
189         else:
190             writerow (2 + i, "                                     %s" % (process[i]))
191 for i in xrange (26):
192     writerow (33 + i, "Slot %2i: Shared Area" % (33 + i))
193 writerow (59, "Slot 59: Driver Stacks")
194 writerow (60, "Slot 60: Large DLLs")
195 writerow (61, "Slot 61: Large DLLs")
196 writerow (62, "Slot 62: Shared Heaps")
197 writerow (63, "Slot 63: Resource DLLs")
198
199 def writelegend(i, col, str):
200     draw.rectangle ((1 * slotwidth, getrow(63-i), 2 * slotwidth - 10, getrow(63-i - 1) - 10), fill=col)
201     draw.rectangle ((1 * slotwidth, getrow(63-i), 2 * slotwidth - 10, getrow(63-i - 1) - 10), outline="#444444")
202     draw.text ((2 * slotwidth, getrow(63-i) ), str, fill="#000000", font=dpf)
203
204 writelegend(0, "#ffffff", "unused")
205 writelegend(1, getcolor("free", 0, 0, ""), "free")
206 writelegend(2, getcolor("reserve", 0, 0, "image"), "image")
207 writelegend(3, getcolor("commit", 0, 0, "image"), "... committed")
208 writelegend(4, getcolor("reserve", 0, 0, "private"), "private")
209 writelegend(5, getcolor("commit", 0, 0, "private"), "... committed")
210 writelegend(6, getcolor("reserve", 0, 0, "mapped"), "mapped")
211 writelegend(7, getcolor("commit", 0, 0, "mapped"), "... committed")
212
213 def writeextra(i, str):
214     draw.text ((1 * slotwidth, getrow(63-i) ), str, fill="#000000", font=dpf)
215 writeextra(9, "1px = 4 KB")
216
217
218 del draw 
219 fim.save("output.png", "PNG")