t_go32v2.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements support import,export,link routines
  5. for the (i386) Go32v2 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. unit t_go32v2;
  20. {$i defines.inc}
  21. interface
  22. implementation
  23. uses
  24. link,
  25. cutils,cclasses,
  26. globtype,globals,systems,verbose,script,fmodule;
  27. type
  28. tlinkergo32v2=class(tlinker)
  29. private
  30. Function WriteResponseFile(isdll:boolean) : Boolean;
  31. Function WriteScript(isdll:boolean) : Boolean;
  32. public
  33. constructor Create;override;
  34. procedure SetDefaultInfo;override;
  35. function MakeExecutable:boolean;override;
  36. end;
  37. {****************************************************************************
  38. TLinkerGo32v2
  39. ****************************************************************************}
  40. Constructor TLinkerGo32v2.Create;
  41. begin
  42. Inherited Create;
  43. { allow duplicated libs (PM) }
  44. SharedLibFiles.doubles:=true;
  45. StaticLibFiles.doubles:=true;
  46. end;
  47. procedure TLinkerGo32v2.SetDefaultInfo;
  48. begin
  49. with Info do
  50. begin
  51. ExeCmd[1]:='ld $SCRIPT $OPT $STRIP -o $EXE';
  52. end;
  53. end;
  54. Function TLinkerGo32v2.WriteResponseFile(isdll:boolean) : Boolean;
  55. Var
  56. linkres : TLinkRes;
  57. i : longint;
  58. HPath : TStringListItem;
  59. s : string;
  60. linklibc : boolean;
  61. begin
  62. WriteResponseFile:=False;
  63. { Open link.res file }
  64. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  65. { Write path to search libraries }
  66. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  67. while assigned(HPath) do
  68. begin
  69. LinkRes.Add('-L'+GetShortName(HPath.Str));
  70. HPath:=TStringListItem(HPath.Next);
  71. end;
  72. HPath:=TStringListItem(LibrarySearchPath.First);
  73. while assigned(HPath) do
  74. begin
  75. LinkRes.Add('-L'+GetShortName(HPath.Str));
  76. HPath:=TStringListItem(HPath.Next);
  77. end;
  78. { add objectfiles, start with prt0 always }
  79. LinkRes.AddFileName(GetShortName(FindObjectFile('prt0','')));
  80. while not ObjectFiles.Empty do
  81. begin
  82. s:=ObjectFiles.GetFirst;
  83. if s<>'' then
  84. LinkRes.AddFileName(GetShortName(s));
  85. end;
  86. { Write staticlibraries }
  87. if not StaticLibFiles.Empty then
  88. begin
  89. LinkRes.Add('-(');
  90. While not StaticLibFiles.Empty do
  91. begin
  92. S:=StaticLibFiles.GetFirst;
  93. LinkRes.AddFileName(GetShortName(s))
  94. end;
  95. LinkRes.Add('-)');
  96. end;
  97. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  98. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  99. linklibc:=false;
  100. While not SharedLibFiles.Empty do
  101. begin
  102. S:=SharedLibFiles.GetFirst;
  103. if s<>'c' then
  104. begin
  105. i:=Pos(target_info.sharedlibext,S);
  106. if i>0 then
  107. Delete(S,i,255);
  108. LinkRes.Add('-l'+s);
  109. end
  110. else
  111. begin
  112. LinkRes.Add('-l'+s);
  113. linklibc:=true;
  114. end;
  115. end;
  116. { be sure that libc&libgcc is the last lib }
  117. if linklibc then
  118. begin
  119. LinkRes.Add('-lc');
  120. LinkRes.Add('-lgcc');
  121. end;
  122. { Write and Close response }
  123. linkres.writetodisk;
  124. LinkRes.Free;
  125. WriteResponseFile:=True;
  126. end;
  127. Function TLinkerGo32v2.WriteScript(isdll:boolean) : Boolean;
  128. Var
  129. scriptres : TLinkRes;
  130. i : longint;
  131. HPath : TStringListItem;
  132. s : string;
  133. linklibc : boolean;
  134. begin
  135. WriteScript:=False;
  136. { Open link.res file }
  137. ScriptRes:=TLinkRes.Create(outputexedir+Info.ResName);
  138. ScriptRes.Add('OUTPUT_FORMAT("coff-go32-exe")');
  139. ScriptRes.Add('ENTRY(start)');
  140. { Write path to search libraries }
  141. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  142. while assigned(HPath) do
  143. begin
  144. LinkRes.Add('SEARCH_PATH("'+GetShortName(HPath.Str)+'")');
  145. HPath:=TStringListItem(HPath.Next);
  146. end;
  147. HPath:=TStringListItem(LibrarySearchPath.First);
  148. while assigned(HPath) do
  149. begin
  150. LinkRes.Add('SEARCH_PATH("'+GetShortName(HPath.Str)+'")');
  151. HPath:=TStringListItem(HPath.Next);
  152. end;
  153. ScriptRes.Add('SECTIONS');
  154. ScriptRes.Add('{');
  155. ScriptRes.Add(' .text 0x1000+SIZEOF_HEADERS : {');
  156. ScriptRes.Add(' . = ALIGN(16);');
  157. { add objectfiles, start with prt0 always }
  158. ScriptRes.Add(' '+GetShortName(FindObjectFile('prt0',''))+'(.text)');
  159. while not ObjectFiles.Empty do
  160. begin
  161. s:=ObjectFiles.GetFirst;
  162. if s<>'' then
  163. begin
  164. ScriptRes.Add(' . = ALIGN(16);');
  165. ScriptRes.Add(' '+GetShortName(s)+'(.text)');
  166. end;
  167. end;
  168. ScriptRes.Add(' *(.text)');
  169. ScriptRes.Add(' etext = . ; _etext = .;');
  170. ScriptRes.Add(' . = ALIGN(0x200);');
  171. ScriptRes.Add(' }');
  172. ScriptRes.Add(' .data ALIGN(0x200) : {');
  173. ScriptRes.Add(' djgpp_first_ctor = . ;');
  174. ScriptRes.Add(' *(.ctor)');
  175. ScriptRes.Add(' djgpp_last_ctor = . ;');
  176. ScriptRes.Add(' djgpp_first_dtor = . ;');
  177. ScriptRes.Add(' *(.dtor)');
  178. ScriptRes.Add(' djgpp_last_dtor = . ;');
  179. ScriptRes.Add(' *(.data)');
  180. ScriptRes.Add(' *(.gcc_exc)');
  181. ScriptRes.Add(' ___EH_FRAME_BEGIN__ = . ;');
  182. ScriptRes.Add(' *(.eh_fram)');
  183. ScriptRes.Add(' ___EH_FRAME_END__ = . ;');
  184. ScriptRes.Add(' LONG(0)');
  185. ScriptRes.Add(' edata = . ; _edata = .;');
  186. ScriptRes.Add(' . = ALIGN(0x200);');
  187. ScriptRes.Add(' }');
  188. ScriptRes.Add(' .bss SIZEOF(.data) + ADDR(.data) :');
  189. ScriptRes.Add(' {');
  190. ScriptRes.Add(' _object.2 = . ;');
  191. ScriptRes.Add(' . += 24 ;');
  192. ScriptRes.Add(' *(.bss)');
  193. ScriptRes.Add(' *(COMMON)');
  194. ScriptRes.Add(' end = . ; _end = .;');
  195. ScriptRes.Add(' . = ALIGN(0x200);');
  196. ScriptRes.Add(' }');
  197. ScriptRes.Add(' }');
  198. { Write staticlibraries }
  199. if not StaticLibFiles.Empty then
  200. begin
  201. ScriptRes.Add('-(');
  202. While not StaticLibFiles.Empty do
  203. begin
  204. S:=StaticLibFiles.GetFirst;
  205. ScriptRes.AddFileName(GetShortName(s))
  206. end;
  207. ScriptRes.Add('-)');
  208. end;
  209. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  210. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  211. linklibc:=false;
  212. While not SharedLibFiles.Empty do
  213. begin
  214. S:=SharedLibFiles.GetFirst;
  215. if s<>'c' then
  216. begin
  217. i:=Pos(target_info.sharedlibext,S);
  218. if i>0 then
  219. Delete(S,i,255);
  220. ScriptRes.Add('-l'+s);
  221. end
  222. else
  223. begin
  224. ScriptRes.Add('-l'+s);
  225. linklibc:=true;
  226. end;
  227. end;
  228. { be sure that libc&libgcc is the last lib }
  229. if linklibc then
  230. begin
  231. ScriptRes.Add('-lc');
  232. ScriptRes.Add('-lgcc');
  233. end;
  234. { Write and Close response }
  235. ScriptRes.WriteToDisk;
  236. ScriptRes.Free;
  237. WriteScript:=True;
  238. end;
  239. function TLinkerGo32v2.MakeExecutable:boolean;
  240. var
  241. binstr,
  242. cmdstr : string;
  243. success : boolean;
  244. StripStr : string[40];
  245. begin
  246. if not(cs_link_extern in aktglobalswitches) then
  247. Message1(exec_i_linking,current_module.exefilename^);
  248. { Create some replacements }
  249. StripStr:='';
  250. if (cs_link_strip in aktglobalswitches) then
  251. StripStr:='-s';
  252. { Write used files and libraries and our own ld script }
  253. WriteScript(false);
  254. { Call linker }
  255. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  256. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
  257. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  258. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  259. Replace(cmdstr,'$STRIP',StripStr);
  260. Replace(cmdstr,'$SCRIPT','--script='+maybequoted(outputexedir+Info.ResName));
  261. success:=DoExec(FindUtil(BinStr),cmdstr,true,false);
  262. { Remove ReponseFile }
  263. if (success) and not(cs_link_extern in aktglobalswitches) then
  264. RemoveFile(outputexedir+Info.ResName);
  265. MakeExecutable:=success; { otherwise a recursive call to link method }
  266. end;
  267. {$ifdef notnecessary}
  268. procedure tlinkergo32v2.postprocessexecutable(const n : string);
  269. type
  270. tcoffheader=packed record
  271. mach : word;
  272. nsects : word;
  273. time : longint;
  274. sympos : longint;
  275. syms : longint;
  276. opthdr : word;
  277. flag : word;
  278. end;
  279. tcoffsechdr=packed record
  280. name : array[0..7] of char;
  281. vsize : longint;
  282. rvaofs : longint;
  283. datalen : longint;
  284. datapos : longint;
  285. relocpos : longint;
  286. lineno1 : longint;
  287. nrelocs : word;
  288. lineno2 : word;
  289. flags : longint;
  290. end;
  291. psecfill=^tsecfill;
  292. tsecfill=record
  293. fillpos,
  294. fillsize : longint;
  295. next : psecfill;
  296. end;
  297. var
  298. f : file;
  299. coffheader : tcoffheader;
  300. firstsecpos,
  301. maxfillsize,
  302. l : longint;
  303. coffsec : tcoffsechdr;
  304. secroot,hsecroot : psecfill;
  305. zerobuf : pointer;
  306. begin
  307. { when -s is used quit, because there is no .exe }
  308. if cs_link_extern in aktglobalswitches then
  309. exit;
  310. { open file }
  311. assign(f,n);
  312. {$I-}
  313. reset(f,1);
  314. if ioresult<>0 then
  315. Message1(execinfo_f_cant_open_executable,n);
  316. { read headers }
  317. seek(f,2048);
  318. blockread(f,coffheader,sizeof(tcoffheader));
  319. { read section info }
  320. maxfillsize:=0;
  321. firstsecpos:=0;
  322. secroot:=nil;
  323. for l:=1to coffheader.nSects do
  324. begin
  325. blockread(f,coffsec,sizeof(tcoffsechdr));
  326. if coffsec.datapos>0 then
  327. begin
  328. if secroot=nil then
  329. firstsecpos:=coffsec.datapos;
  330. new(hsecroot);
  331. hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
  332. hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
  333. hsecroot^.next:=secroot;
  334. secroot:=hsecroot;
  335. if secroot^.fillsize>maxfillsize then
  336. maxfillsize:=secroot^.fillsize;
  337. end;
  338. end;
  339. if firstsecpos>0 then
  340. begin
  341. l:=firstsecpos-filepos(f);
  342. if l>maxfillsize then
  343. maxfillsize:=l;
  344. end
  345. else
  346. l:=0;
  347. { get zero buffer }
  348. getmem(zerobuf,maxfillsize);
  349. fillchar(zerobuf^,maxfillsize,0);
  350. { zero from sectioninfo until first section }
  351. blockwrite(f,zerobuf^,l);
  352. { zero section alignments }
  353. while assigned(secroot) do
  354. begin
  355. seek(f,secroot^.fillpos);
  356. blockwrite(f,zerobuf^,secroot^.fillsize);
  357. hsecroot:=secroot;
  358. secroot:=secroot^.next;
  359. dispose(hsecroot);
  360. end;
  361. freemem(zerobuf,maxfillsize);
  362. close(f);
  363. {$I+}
  364. i:=ioresult;
  365. postprocessexecutable:=true;
  366. end;
  367. {$endif}
  368. {*****************************************************************************
  369. Initialize
  370. *****************************************************************************}
  371. const
  372. target_i386_go32v2_info : ttargetinfo =
  373. (
  374. target : target_i386_GO32V2;
  375. name : 'GO32 V2 DOS extender';
  376. shortname : 'Go32v2';
  377. flags : [];
  378. cpu : i386;
  379. unit_env : 'GO32V2UNITS';
  380. extradefines : '';
  381. sharedlibext : '.dll';
  382. staticlibext : '.a';
  383. sourceext : '.pp';
  384. pasext : '.pas';
  385. exeext : '.exe';
  386. defext : '.def';
  387. scriptext : '.bat';
  388. smartext : '.sl';
  389. unitext : '.ppu';
  390. unitlibext : '.ppl';
  391. asmext : '.s';
  392. objext : '.o';
  393. resext : '.res';
  394. resobjext : '.or';
  395. staticlibprefix : '';
  396. sharedlibprefix : '';
  397. Cprefix : '_';
  398. newline : #13#10;
  399. assem : as_i386_coff;
  400. assemextern : as_i386_as;
  401. link : ld_i386_go32v2;
  402. linkextern : ld_i386_go32v2;
  403. ar : ar_gnu_ar;
  404. res : res_none;
  405. endian : endian_little;
  406. alignment :
  407. (
  408. procalign : 4;
  409. loopalign : 4;
  410. jumpalign : 0;
  411. constalignmin : 0;
  412. constalignmax : 1;
  413. varalignmin : 0;
  414. varalignmax : 1;
  415. localalignmin : 0;
  416. localalignmax : 1;
  417. paraalign : 2;
  418. recordalignmin : 0;
  419. recordalignmax : 2;
  420. maxCrecordalign : 4
  421. );
  422. size_of_pointer : 4;
  423. size_of_longint : 4;
  424. heapsize : 2048*1024;
  425. maxheapsize : 32768*1024;
  426. stacksize : 16384;
  427. DllScanSupported : false;
  428. use_bound_instruction : false;
  429. use_function_relative_addresses : true
  430. );
  431. initialization
  432. RegisterLinker(ld_i386_go32v2,TLinkerGo32v2);
  433. RegisterTarget(target_i386_go32v2_info);
  434. end.
  435. {
  436. $Log$
  437. Revision 1.8 2001-07-01 20:16:20 peter
  438. * alignmentinfo record added
  439. * -Oa argument supports more alignment settings that can be specified
  440. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  441. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  442. required alignment and the maximum usefull alignment. The final
  443. alignment will be choosen per variable size dependent on these
  444. settings
  445. Revision 1.7 2001/06/28 19:46:25 peter
  446. * added override and virtual for constructors
  447. Revision 1.6 2001/06/18 20:36:26 peter
  448. * -Ur switch (merged)
  449. * masm fixes (merged)
  450. * quoted filenames for go32v2 and win32
  451. Revision 1.5 2001/06/03 15:15:31 peter
  452. * dllprt0 stub for linux shared libs
  453. * pass -init and -fini for linux shared libs
  454. * libprefix splitted into staticlibprefix and sharedlibprefix
  455. Revision 1.4 2001/06/02 19:22:44 peter
  456. * extradefines field added
  457. Revision 1.3 2001/04/18 22:02:04 peter
  458. * registration of targets and assemblers
  459. Revision 1.2 2001/04/13 01:22:21 peter
  460. * symtable change to classes
  461. * range check generation and errors fixed, make cycle DEBUG=1 works
  462. * memory leaks fixed
  463. Revision 1.1 2001/02/26 19:43:11 peter
  464. * moved target units to subdir
  465. Revision 1.7 2001/01/27 21:29:35 florian
  466. * behavior -Oa optimized
  467. Revision 1.6 2000/12/25 00:07:30 peter
  468. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  469. tlinkedlist objects)
  470. Revision 1.5 2000/09/24 15:06:31 peter
  471. * use defines.inc
  472. Revision 1.4 2000/08/27 16:11:54 peter
  473. * moved some util functions from globals,cobjects to cutils
  474. * splitted files into finput,fmodule
  475. Revision 1.3 2000/08/16 13:06:07 florian
  476. + support of 64 bit integer constants
  477. Revision 1.2 2000/07/13 11:32:50 michael
  478. + removed logs
  479. }