2
0

postw32.pp 9.6 KB

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