2 PROJECT: ReactOS baseaddress updater
3 LICENSE: MIT (https://spdx.org/licenses/MIT)
4 PURPOSE: Update baseaddresses of all modules
5 COPYRIGHT: Copyright 2017,2018 Mark Jansen (mark.jansen@reactos.org)
7 from __future__
import print_function
, absolute_import
, division
15 print('# Please install pefile from pip or https://github.com/erocarrera/pefile')
16 print('# Using fallback')
20 '.dll', '.acm', '.ax', '.cpl', '.drv', '.ocx'
184 'dllexport_test_dll1.dll',
185 'dllexport_test_dll2.dll',
186 'dllimport_test.dll',
187 'MyEventProvider.dll',
188 'w32kdll_2k3sp2.dll',
194 def size_of_image_fallback(filename
):
195 with
open(filename
, 'rb') as fin
:
196 if fin
.read(2) != 'MZ':
197 print(filename
, 'No dos header found!')
200 e_lfanew
= struct
.unpack('i', fin
.read(4))[0]
202 if fin
.read(4) != 'PE\0\0':
203 print(filename
, 'No PE header found!')
205 fin
.seek(e_lfanew
+ 0x18)
206 pe_magic
= struct
.unpack('h', fin
.read(2))[0]
207 if pe_magic
!= 0x10b:
208 print(filename
, 'is not a 32 bit exe!')
210 fin
.seek(e_lfanew
+ 0x50)
211 pe_size_of_image
= struct
.unpack('i', fin
.read(4))[0]
212 return pe_size_of_image
214 def size_of_image(filename
):
215 if 'pefile' in globals():
216 return pefile
.PE(filename
, fast_load
=True).OPTIONAL_HEADER
.SizeOfImage
217 return size_of_image_fallback(filename
)
220 class Module(object):
221 def __init__(self
, name
, address
, size
):
223 self
.address
= address
225 self
._reserved
= address
!= 0
227 def gen_baseaddress(self
):
228 name
, ext
= os
.path
.splitext(self
._name
)
230 if ext
in('.acm', '.drv') and self
._name
!= 'winspool.drv':
233 postfix
= ' # should be above 0x%08x' % self
.address
235 postfix
= ' # reserved'
236 print('set(baseaddress_%-30s 0x%08x)%s' % (name
, self
.address
, postfix
))
239 return self
.address
+ self
.size
242 return '%s (0x%08x - 0x%08x)' % (self
._name
, self
.address
, self
.end())
244 class MemoryLayout(object):
245 def __init__(self
, startaddress
):
249 self
.initial
= startaddress
251 self
.module_padding
= 0x2000
253 def add_reserved(self
, name
, address
):
254 self
.reserved
[name
] = (address
, 0)
256 def add(self
, filename
, name
):
257 size
= size_of_image(filename
)
259 if name
in self
.found
:
260 return # Assume duplicate files (rshell, ...) are 1:1 copies
261 if name
in self
.reserved
:
262 addr
= self
.reserved
[name
][0]
263 self
.reserved
[name
] = (addr
, size
)
264 self
.found
[name
] = Module(name
, addr
, size
)
266 def _next_address(self
, size
):
268 addr
= (self
.start_at
- size
- self
.module_padding
- 0xffff) & 0xffff0000
271 addr
= self
.start_at
= self
.initial
274 def next_address(self
, size
):
276 current_start
= self
._next
_address
(size
)
277 current_end
= current_start
+ size
+ self
.module_padding
278 # Is there overlap with reserved modules?
279 for key
, reserved
in self
.reserved
.items():
280 res_start
= reserved
[0]
281 res_end
= res_start
+ reserved
[1] + self
.module_padding
282 if (res_start
<= current_start
<= res_end
) or \
283 (res_start
<= current_end
<= res_end
) or \
284 (current_start
< res_start
and current_end
> res_end
):
285 # We passed this reserved item, we can remove it now
286 self
.start_at
= min(res_start
, current_start
)
287 del self
.reserved
[key
]
290 # No overlap with a reserved module?
294 def update(self
, priorities
):
295 # sort addresses, should only contain reserved modules at this point!
296 for key
, reserved
in self
.reserved
.items():
297 assert reserved
[1] != 0, key
298 for curr
in priorities
:
299 if not curr
in self
.found
:
300 print('# Did not find', curr
, '!')
302 obj
= self
.found
[curr
]
305 obj
.address
= self
.next_address(obj
.size
)
306 self
.addresses
.append(obj
)
307 # We handled all known modules now, run over the rest we found
308 for key
in sorted(self
.found
):
309 obj
= self
.found
[key
]
310 obj
.address
= self
.next_address(obj
.size
)
311 self
.addresses
.append(obj
)
313 def gen_baseaddress(self
):
314 for obj
in self
.addresses
:
315 obj
.gen_baseaddress()
318 print('# Generated from', target
)
319 print('# Generated by sdk/tools/gen_baseaddress.py')
320 layout
= MemoryLayout(0x7c920000)
321 layout
.add_reserved('user32.dll', 0x77a20000)
322 for root
, _
, files
in os
.walk(target
):
323 for dll
in [filename
for filename
in files
if filename
.endswith(ALL_EXTENSIONS
)]:
324 if not dll
in EXCLUDE
and not dll
.startswith('api-ms-win-'):
325 layout
.add(os
.path
.join(root
, dll
), dll
)
326 layout
.update(PRIORITIES
)
327 layout
.gen_baseaddress()
332 print('# No path specified, trying', trydir
)
337 if __name__
== '__main__':