postw32.pp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Pavel Ozerski
  4. This program implements support post processing
  5. for the (i386) Win32 target
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. program post_process_win32_executable;
  20. uses
  21. globtype,globals,strings;
  22. const
  23. execinfo_f_cant_open_executable='Cannot open file ';
  24. execinfo_x_codesize='Code size: ';
  25. execinfo_x_initdatasize='Size of Initialized Data: ';
  26. execinfo_x_uninitdatasize='Size of Uninitialized Data: ';
  27. execinfo_f_cant_process_executable='Cannot process file ';
  28. execinfo_x_stackreserve='Size of Stack Reserve: ';
  29. execinfo_x_stackcommit='Size of Stack Commit: ';
  30. var
  31. verbose:longbool;
  32. ii,jj:longint;
  33. code:integer;
  34. DllVersion : sTring;
  35. Dllmajor,Dllminor : word;
  36. procedure Message1(const info,fn:string);
  37. var
  38. e:longbool;
  39. begin
  40. e:=pos('Cannot',info)=1;
  41. if verbose or e then
  42. writeln(info,fn);
  43. if e then
  44. halt(1);
  45. end;
  46. function postprocessexecutable(const fn : string;isdll:boolean):boolean;
  47. type
  48. tdosheader = packed record
  49. e_magic : word;
  50. e_cblp : word;
  51. e_cp : word;
  52. e_crlc : word;
  53. e_cparhdr : word;
  54. e_minalloc : word;
  55. e_maxalloc : word;
  56. e_ss : word;
  57. e_sp : word;
  58. e_csum : word;
  59. e_ip : word;
  60. e_cs : word;
  61. e_lfarlc : word;
  62. e_ovno : word;
  63. e_res : array[0..3] of word;
  64. e_oemid : word;
  65. e_oeminfo : word;
  66. e_res2 : array[0..9] of word;
  67. e_lfanew : longint;
  68. end;
  69. tpeheader = packed record
  70. PEMagic : array[0..3] of char;
  71. Machine : word;
  72. NumberOfSections : word;
  73. TimeDateStamp : longint;
  74. PointerToSymbolTable : longint;
  75. NumberOfSymbols : longint;
  76. SizeOfOptionalHeader : word;
  77. Characteristics : word;
  78. Magic : word;
  79. MajorLinkerVersion : byte;
  80. MinorLinkerVersion : byte;
  81. SizeOfCode : longint;
  82. SizeOfInitializedData : longint;
  83. SizeOfUninitializedData : longint;
  84. AddressOfEntryPoint : longint;
  85. BaseOfCode : longint;
  86. BaseOfData : longint;
  87. ImageBase : longint;
  88. SectionAlignment : longint;
  89. FileAlignment : longint;
  90. MajorOperatingSystemVersion : word;
  91. MinorOperatingSystemVersion : word;
  92. MajorImageVersion : word;
  93. MinorImageVersion : word;
  94. MajorSubsystemVersion : word;
  95. MinorSubsystemVersion : word;
  96. Reserved1 : longint;
  97. SizeOfImage : longint;
  98. SizeOfHeaders : longint;
  99. CheckSum : longint;
  100. Subsystem : word;
  101. DllCharacteristics : word;
  102. SizeOfStackReserve : longint;
  103. SizeOfStackCommit : longint;
  104. SizeOfHeapReserve : longint;
  105. SizeOfHeapCommit : longint;
  106. LoaderFlags : longint;
  107. NumberOfRvaAndSizes : longint;
  108. DataDirectory : array[1..$80] of byte;
  109. end;
  110. tcoffsechdr=packed record
  111. name : array[0..7] of char;
  112. vsize : longint;
  113. rvaofs : longint;
  114. datalen : longint;
  115. datapos : longint;
  116. relocpos : longint;
  117. lineno1 : longint;
  118. nrelocs : word;
  119. lineno2 : word;
  120. flags : longint;
  121. end;
  122. psecfill=^tsecfill;
  123. tsecfill=record
  124. fillpos,
  125. fillsize : longint;
  126. next : psecfill;
  127. end;
  128. var
  129. f : file;
  130. dosheader : tdosheader;
  131. peheader : tpeheader;
  132. firstsecpos,
  133. maxfillsize,
  134. l,peheaderpos : longint;
  135. coffsec : tcoffsechdr;
  136. secroot,hsecroot : psecfill;
  137. zerobuf : pointer;
  138. begin
  139. postprocessexecutable:=false;
  140. { open file }
  141. assign(f,fn);
  142. {$I-}
  143. reset(f,1);
  144. if ioresult<>0 then
  145. Message1(execinfo_f_cant_open_executable,fn);
  146. { read headers }
  147. blockread(f,dosheader,sizeof(tdosheader));
  148. peheaderpos:=dosheader.e_lfanew;
  149. seek(f,peheaderpos);
  150. blockread(f,peheader,sizeof(tpeheader));
  151. { write info }
  152. Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
  153. Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
  154. Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
  155. { change stack size (PM) }
  156. { I am not sure that the default value is adequate !! }
  157. peheader.SizeOfStackReserve:=stacksize;
  158. { change the header }
  159. { sub system }
  160. { gui=2 }
  161. { cui=3 }
  162. if apptype=at_gui then
  163. peheader.Subsystem:=2
  164. else if apptype=at_cui then
  165. peheader.Subsystem:=3;
  166. if dllversion<>'' then
  167. begin
  168. peheader.MajorImageVersion:=dllmajor;
  169. peheader.MinorImageVersion:=dllminor;
  170. end;
  171. { reset timestamp }
  172. peheader.TimeDateStamp:=0;
  173. { write header back }
  174. seek(f,peheaderpos);
  175. blockwrite(f,peheader,sizeof(tpeheader));
  176. if ioresult<>0 then
  177. Message1(execinfo_f_cant_process_executable,fn);
  178. seek(f,peheaderpos);
  179. blockread(f,peheader,sizeof(tpeheader));
  180. { write the value after the change }
  181. Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
  182. Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
  183. { read section info }
  184. maxfillsize:=0;
  185. firstsecpos:=0;
  186. secroot:=nil;
  187. for l:=1to peheader.NumberOfSections do
  188. begin
  189. blockread(f,coffsec,sizeof(tcoffsechdr));
  190. if coffsec.datapos>0 then
  191. begin
  192. if secroot=nil then
  193. firstsecpos:=coffsec.datapos;
  194. new(hsecroot);
  195. hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
  196. hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
  197. hsecroot^.next:=secroot;
  198. secroot:=hsecroot;
  199. if secroot^.fillsize>maxfillsize then
  200. maxfillsize:=secroot^.fillsize;
  201. end;
  202. end;
  203. if firstsecpos>0 then
  204. begin
  205. l:=firstsecpos-filepos(f);
  206. if l>maxfillsize then
  207. maxfillsize:=l;
  208. end
  209. else
  210. l:=0;
  211. { get zero buffer }
  212. getmem(zerobuf,maxfillsize);
  213. fillchar(zerobuf^,maxfillsize,0);
  214. { zero from sectioninfo until first section }
  215. blockwrite(f,zerobuf^,l);
  216. { zero section alignments }
  217. while assigned(secroot) do
  218. begin
  219. seek(f,secroot^.fillpos);
  220. blockwrite(f,zerobuf^,secroot^.fillsize);
  221. hsecroot:=secroot;
  222. secroot:=secroot^.next;
  223. dispose(hsecroot);
  224. end;
  225. freemem(zerobuf,maxfillsize);
  226. close(f);
  227. {$I+}
  228. if ioresult<>0 then;
  229. postprocessexecutable:=true;
  230. end;
  231. var
  232. fn,s:string;
  233. function GetSwitchValue(const key,shortkey,default:string;const PossibleValues:array of pchar):string;
  234. var
  235. i,j,k:longint;
  236. x:double;
  237. s1,s2:string;
  238. code:integer;
  239. procedure Error;
  240. begin
  241. writeln('Error: unrecognized option ',paramstr(i),' ',s1);
  242. halt(1);
  243. end;
  244. begin
  245. for i:=1 to paramcount do
  246. if(paramstr(i)=key)or(paramstr(i)=shortkey)then
  247. begin
  248. s1:=paramstr(succ(i));
  249. for j:=0 to high(PossibleValues)do
  250. begin
  251. s2:=strpas(PossibleValues[j]);
  252. if(length(s2)>1)and(s2[1]='*')then
  253. case s2[2]of
  254. 'i':
  255. begin
  256. val(s1,k,code);
  257. if code<>0 then
  258. error;
  259. GetSwitchValue:=s1;
  260. exit;
  261. end;
  262. 'r':
  263. begin
  264. val(s1,x,code);
  265. if code<>0 then
  266. error;
  267. GetSwitchValue:=s1;
  268. exit;
  269. end;
  270. 's':
  271. begin
  272. GetSwitchValue:=s1;
  273. exit;
  274. end;
  275. end
  276. else if s1=s2 then
  277. begin
  278. GetSwitchValue:=s1;
  279. exit;
  280. end;
  281. end;
  282. error;
  283. end;
  284. GetSwitchValue:=default;
  285. end;
  286. procedure help_info;
  287. begin
  288. fn:=paramstr(0);
  289. for jj:=length(fn)downto 1 do
  290. if fn[jj] in [':','\','/']then
  291. begin
  292. fn:=copy(fn,succ(jj),255);
  293. break;
  294. end;
  295. writeln('Usage: ',fn,' [options]');
  296. writeln('Options:');
  297. writeln('-i | --input <file> - set input file;');
  298. writeln('-m | --subsystem <console | gui> - set Win32 subsystem;');
  299. writeln('-s | --stack <size> - set stack size;');
  300. writeln('-V | --version <n.n> - set image version;');
  301. writeln('-v | --verbose - show info while processing;');
  302. writeln('-h | --help | -? - show this screen');
  303. halt;
  304. end;
  305. begin
  306. aktglobalswitches:=[];
  307. verbose:=false;
  308. if paramcount=0 then
  309. help_info;
  310. for ii:=1 to paramcount do
  311. if(paramstr(ii)='-h')or(paramstr(ii)='--help')or(paramstr(ii)='-?')then
  312. help_info
  313. else if(paramstr(ii)='-v')or(paramstr(ii)='--verbose')then
  314. begin
  315. verbose:=true;
  316. break;
  317. end;
  318. fn:=GetSwitchValue('--input','-i','',['*s']);
  319. val(GetSwitchValue('--stack','-s','33554432',['*i']),stacksize,code);
  320. {value from
  321. systems.pas
  322. for Win32 target}
  323. s:=GetSwitchValue('--subsystem','-m','console',['gui','console']);
  324. if s='gui' then
  325. apptype:=at_GUI
  326. else
  327. apptype:=at_cui;
  328. dllversion:=GetSwitchValue('--version','-V','1.0',['*r']);
  329. ii:=pos('.',dllversion);
  330. if ii=0 then
  331. begin
  332. ii:=succ(length(dllversion));
  333. dllversion:=dllversion+'.0';
  334. end
  335. else if ii=1 then
  336. begin
  337. ii:=2;
  338. dllversion:='0.'+dllversion;
  339. end;
  340. val(copy(dllversion,1,pred(ii)),dllmajor,code);
  341. val(copy(dllversion,succ(ii),length(dllversion)),dllminor,code);
  342. if verbose then
  343. writeln('Image Version: ',dllmajor,'.',dllminor);
  344. PostProcessExecutable(fn,false);
  345. end.
  346. {
  347. $Log$
  348. Revision 1.1 2000-04-14 11:10:46 pierre
  349. renamed to fit in 8.3 limitation
  350. }