204cfe23f2b33f36432010bebebeb2ca96967915
[reactos.git] / sdk / tools / gen_baseaddress.py
1 '''
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)
6 '''
7
8 # FIXME: user32 always at 0x77a20000
9
10 import os
11 import struct
12 import sys
13 try:
14 import pefile
15 except ImportError:
16 print '# Please install pefile from pip or https://github.com/erocarrera/pefile'
17 print '# Using fallback'
18 print
19
20 DLL_EXTENSIONS = (
21 '.dll'
22 )
23
24 OTHER_EXTENSIONS = (
25 '.acm', '.ax', '.cpl', '.drv', '.ocx'
26 )
27
28 PRIORITIES = (
29 'ntdll.dll',
30 'kernel32.dll',
31 'msvcrt.dll',
32 'advapi32.dll',
33 'gdi32.dll',
34 'user32.dll',
35 'dhcpcsvc.dll',
36 'dnsapi.dll',
37 'icmp.dll',
38 'iphlpapi.dll',
39 'ws2_32.dll',
40 'ws2help.dll',
41 'shlwapi.dll',
42 'rpcrt4.dll',
43 'comctl32.dll',
44 'ole32.dll',
45 'winspool.drv',
46 'winmm.dll',
47 'comdlg32.dll',
48 'shell32.dll',
49 'lz32.dll',
50 'version.dll',
51 'oleaut32.dll',
52 'setupapi.dll',
53 'mpr.dll',
54 'crypt32.dll',
55 'wininet.dll',
56 'urlmon.dll',
57 'psapi.dll',
58 'imm32.dll',
59 'msvfw32.dll',
60 'dbghelp.dll',
61 'devmgr.dll',
62 'msacm32.dll',
63 'netapi32.dll',
64 'powrprof.dll',
65 'secur32.dll',
66 'wintrust.dll',
67 'avicap32.dll',
68 'cabinet.dll',
69 'dsound.dll',
70 'glu32.dll',
71 'opengl32.dll',
72 'riched20.dll',
73 'smdll.dll',
74 'userenv.dll',
75 'uxtheme.dll',
76 'cryptui.dll',
77 'csrsrv.dll',
78 'basesrv.dll',
79 'winsrv.dll',
80 'dplayx.dll',
81 'gdiplus.dll',
82 'msimg32.dll',
83 'mswsock.dll',
84 'oledlg.dll',
85 'rasapi32.dll',
86 'rsaenh.dll',
87 'samlib.dll',
88 'sensapi.dll',
89 'sfc_os.dll',
90 'snmpapi.dll',
91 'spoolss.dll',
92 'usp10.dll',
93 )
94
95 EXCLUDE = (
96 'bmfd.dll',
97 'bootvid.dll',
98 'freeldr_pe.dll',
99 'ftfd.dll',
100 'fusion.dll',
101 'hal.dll',
102 'halaacpi.dll',
103 'halacpi.dll',
104 'halapic.dll',
105 'kbda1.dll',
106 'kbda2.dll',
107 'kbda3.dll',
108 'kbdal.dll',
109 'kbdarme.dll',
110 'kbdarmw.dll',
111 'kbdaze.dll',
112 'kbdazel.dll',
113 'kbdbe.dll',
114 'kbdbga.dll',
115 'kbdbgm.dll',
116 'kbdbgt.dll',
117 'kbdblr.dll',
118 'kbdbr.dll',
119 'kbdbur.dll',
120 'kbdcan.dll',
121 'kbdcr.dll',
122 'kbdcz.dll',
123 'kbdcz1.dll',
124 'kbdda.dll',
125 'kbddv.dll',
126 'kbdes.dll',
127 'kbdest.dll',
128 'kbdfc.dll',
129 'kbdfi.dll',
130 'kbdfr.dll',
131 'kbdgeo.dll',
132 'kbdgerg.dll',
133 'kbdgneo.dll',
134 'kbdgr.dll',
135 'kbdgrist.dll',
136 'kbdhe.dll',
137 'kbdheb.dll',
138 'kbdhu.dll',
139 'kbdic.dll',
140 'kbdinasa.dll',
141 'kbdinben.dll',
142 'kbdindev.dll',
143 'kbdinguj.dll',
144 'kbdinmal.dll',
145 'kbdir.dll',
146 'kbdit.dll',
147 'kbdja.dll',
148 'kbdkaz.dll',
149 'kbdko.dll',
150 'kbdla.dll',
151 'kbdlt1.dll',
152 'kbdlv.dll',
153 'kbdmac.dll',
154 'kbdne.dll',
155 'kbdno.dll',
156 'kbdpl.dll',
157 'kbdpl1.dll',
158 'kbdpo.dll',
159 'kbdro.dll',
160 'kbdru.dll',
161 'kbdru1.dll',
162 'kbdsg.dll',
163 'kbdsk.dll',
164 'kbdsk1.dll',
165 'kbdsw.dll',
166 'kbdtat.dll',
167 'kbdth0.dll',
168 'kbdth1.dll',
169 'kbdth2.dll',
170 'kbdth3.dll',
171 'kbdtuf.dll',
172 'kbdtuq.dll',
173 'kbduk.dll',
174 'kbdur.dll',
175 'kbdurs.dll',
176 'kbdus.dll',
177 'kbdusa.dll',
178 'kbdusl.dll',
179 'kbdusr.dll',
180 'kbdusx.dll',
181 'kbduzb.dll',
182 'kbdvntc.dll',
183 'kbdycc.dll',
184 'kbdycl.dll',
185 'kdcom.dll',
186 'kdvbox.dll',
187 'setupldr_pe.dll',
188 'vgaddi.dll',
189 'dllexport_test_dll1.dll',
190 'dllexport_test_dll2.dll',
191 'dllimport_test.dll',
192 'MyEventProvider.dll',
193 'w32kdll_2k3sp2.dll',
194 'w32kdll_ros.dll',
195 'w32kdll_xpsp2.dll',
196 )
197
198
199 def size_of_image_fallback(filename):
200 with open(filename, 'rb') as fin:
201 if fin.read(2) != 'MZ':
202 print filename, 'No dos header found!'
203 return 0
204 fin.seek(0x3C)
205 e_lfanew = struct.unpack('i', fin.read(4))[0]
206 fin.seek(e_lfanew)
207 if fin.read(4) != 'PE\0\0':
208 print filename, 'No PE header found!'
209 return 0
210 fin.seek(e_lfanew + 0x18)
211 pe_magic = struct.unpack('h', fin.read(2))[0]
212 if pe_magic != 0x10b:
213 print filename, 'is not a 32 bit exe!'
214 return 0
215 fin.seek(e_lfanew + 0x50)
216 pe_size_of_image = struct.unpack('i', fin.read(4))[0]
217 return pe_size_of_image
218
219 def size_of_image(filename):
220 if 'pefile' in globals():
221 return pefile.PE(filename, fast_load=True).OPTIONAL_HEADER.SizeOfImage
222 return size_of_image_fallback(filename)
223
224 def onefile(current_address, filename, size):
225 name, ext = os.path.splitext(filename)
226 postfix = ''
227 if ext in('.acm', '.drv') and filename != 'winspool.drv':
228 name = filename
229 if current_address == 0:
230 current_address = 0x7c920000
231 postfix = ' # should be above 0x%08x' % current_address
232 else:
233 current_address = (current_address - size - 0x2000 - 0xffff) & 0xffff0000
234 print 'set(baseaddress_%-30s 0x%08x)%s' % (name, current_address, postfix)
235 return current_address
236
237 def run_dir(target):
238 print '# Generated from', target
239 print '# Generated by sdk/tools/gen_baseaddress.py'
240 found_dlls = {}
241 found_files = {}
242 for root, _, files in os.walk(target):
243 for dll in [filename for filename in files if filename.endswith(DLL_EXTENSIONS)]:
244 if not dll in EXCLUDE and not dll.startswith('api-ms-win-'):
245 found_dlls[dll] = size_of_image(os.path.join(root, dll))
246 extrafiles = [filename for filename in files if filename.endswith(OTHER_EXTENSIONS)]
247 for extrafile in extrafiles:
248 if not extrafile in EXCLUDE:
249 found_files[extrafile] = size_of_image(os.path.join(root, extrafile))
250
251 current_address = 0
252 for curr in PRIORITIES:
253 if curr in found_dlls:
254 current_address = onefile(current_address, curr, found_dlls[curr])
255 del found_dlls[curr]
256 elif curr in found_files:
257 current_address = onefile(current_address, curr, found_files[curr])
258 del found_files[curr]
259 else:
260 print '# Did not find', curr, '!'
261
262 print '# Extra dlls'
263 for curr in sorted(found_dlls):
264 current_address = onefile(current_address, curr, found_dlls[curr])
265 print '# Extra files'
266 for curr in sorted(found_files):
267 current_address = onefile(current_address, curr, found_files[curr])
268
269 def main(dirs):
270 if len(dirs) < 1:
271 trydir = os.getcwd()
272 print '# No path specified, trying', trydir
273 dirs = [trydir]
274 for onedir in dirs:
275 run_dir(onedir)
276
277 if __name__ == '__main__':
278 main(sys.argv[1:])