t_go32v2.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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. ScriptRes.Add('SECTIONS');
  141. ScriptRes.Add('{');
  142. ScriptRes.Add(' .text 0x1000+SIZEOF_HEADERS : {');
  143. ScriptRes.Add(' . = ALIGN(16);');
  144. { add objectfiles, start with prt0 always }
  145. ScriptRes.Add(' '+GetShortName(FindObjectFile('prt0',''))+'(.text)');
  146. while not ObjectFiles.Empty do
  147. begin
  148. s:=ObjectFiles.GetFirst;
  149. if s<>'' then
  150. begin
  151. ScriptRes.Add(' . = ALIGN(16);');
  152. ScriptRes.Add(' '+GetShortName(s)+'(.text)');
  153. end;
  154. end;
  155. ScriptRes.Add(' *(.text)');
  156. ScriptRes.Add(' etext = . ; _etext = .;');
  157. ScriptRes.Add(' . = ALIGN(0x200);');
  158. ScriptRes.Add(' }');
  159. ScriptRes.Add(' .data ALIGN(0x200) : {');
  160. ScriptRes.Add(' djgpp_first_ctor = . ;');
  161. ScriptRes.Add(' *(.ctor)');
  162. ScriptRes.Add(' djgpp_last_ctor = . ;');
  163. ScriptRes.Add(' djgpp_first_dtor = . ;');
  164. ScriptRes.Add(' *(.dtor)');
  165. ScriptRes.Add(' djgpp_last_dtor = . ;');
  166. ScriptRes.Add(' *(.data)');
  167. ScriptRes.Add(' *(.gcc_exc)');
  168. ScriptRes.Add(' ___EH_FRAME_BEGIN__ = . ;');
  169. ScriptRes.Add(' *(.eh_fram)');
  170. ScriptRes.Add(' ___EH_FRAME_END__ = . ;');
  171. ScriptRes.Add(' LONG(0)');
  172. ScriptRes.Add(' edata = . ; _edata = .;');
  173. ScriptRes.Add(' . = ALIGN(0x200);');
  174. ScriptRes.Add(' }');
  175. ScriptRes.Add(' .bss SIZEOF(.data) + ADDR(.data) :');
  176. ScriptRes.Add(' {');
  177. ScriptRes.Add(' _object.2 = . ;');
  178. ScriptRes.Add(' . += 24 ;');
  179. ScriptRes.Add(' *(.bss)');
  180. ScriptRes.Add(' *(COMMON)');
  181. ScriptRes.Add(' end = . ; _end = .;');
  182. ScriptRes.Add(' . = ALIGN(0x200);');
  183. ScriptRes.Add(' }');
  184. ScriptRes.Add(' }');
  185. { Write path to search libraries }
  186. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  187. while assigned(HPath) do
  188. begin
  189. ScriptRes.Add('SEARCH_DIR("'+GetShortName(HPath.Str)+'")');
  190. HPath:=TStringListItem(HPath.Next);
  191. end;
  192. HPath:=TStringListItem(LibrarySearchPath.First);
  193. while assigned(HPath) do
  194. begin
  195. ScriptRes.Add('SEARCH_DIR("'+GetShortName(HPath.Str)+'")');
  196. HPath:=TStringListItem(HPath.Next);
  197. end;
  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.9 2001-07-10 21:01:35 peter
  438. * fixed crash with writing of the linker script
  439. Revision 1.8 2001/07/01 20:16:20 peter
  440. * alignmentinfo record added
  441. * -Oa argument supports more alignment settings that can be specified
  442. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  443. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  444. required alignment and the maximum usefull alignment. The final
  445. alignment will be choosen per variable size dependent on these
  446. settings
  447. Revision 1.7 2001/06/28 19:46:25 peter
  448. * added override and virtual for constructors
  449. Revision 1.6 2001/06/18 20:36:26 peter
  450. * -Ur switch (merged)
  451. * masm fixes (merged)
  452. * quoted filenames for go32v2 and win32
  453. Revision 1.5 2001/06/03 15:15:31 peter
  454. * dllprt0 stub for linux shared libs
  455. * pass -init and -fini for linux shared libs
  456. * libprefix splitted into staticlibprefix and sharedlibprefix
  457. Revision 1.4 2001/06/02 19:22:44 peter
  458. * extradefines field added
  459. Revision 1.3 2001/04/18 22:02:04 peter
  460. * registration of targets and assemblers
  461. Revision 1.2 2001/04/13 01:22:21 peter
  462. * symtable change to classes
  463. * range check generation and errors fixed, make cycle DEBUG=1 works
  464. * memory leaks fixed
  465. Revision 1.1 2001/02/26 19:43:11 peter
  466. * moved target units to subdir
  467. Revision 1.7 2001/01/27 21:29:35 florian
  468. * behavior -Oa optimized
  469. Revision 1.6 2000/12/25 00:07:30 peter
  470. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  471. tlinkedlist objects)
  472. Revision 1.5 2000/09/24 15:06:31 peter
  473. * use defines.inc
  474. Revision 1.4 2000/08/27 16:11:54 peter
  475. * moved some util functions from globals,cobjects to cutils
  476. * splitted files into finput,fmodule
  477. Revision 1.3 2000/08/16 13:06:07 florian
  478. + support of 64 bit integer constants
  479. Revision 1.2 2000/07/13 11:32:50 michael
  480. + removed logs
  481. }