postw32.pp 9.7 KB

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