t_go32v2.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  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 : 'DPMI';
  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. script : script_dos;
  406. endian : endian_little;
  407. alignment :
  408. (
  409. procalign : 4;
  410. loopalign : 4;
  411. jumpalign : 0;
  412. constalignmin : 0;
  413. constalignmax : 1;
  414. varalignmin : 0;
  415. varalignmax : 1;
  416. localalignmin : 0;
  417. localalignmax : 1;
  418. paraalign : 2;
  419. recordalignmin : 0;
  420. recordalignmax : 2;
  421. maxCrecordalign : 4
  422. );
  423. size_of_pointer : 4;
  424. size_of_longint : 4;
  425. heapsize : 2048*1024;
  426. maxheapsize : 32768*1024;
  427. stacksize : 16384;
  428. DllScanSupported : false;
  429. use_bound_instruction : false;
  430. use_function_relative_addresses : true
  431. );
  432. initialization
  433. RegisterLinker(ld_i386_go32v2,TLinkerGo32v2);
  434. RegisterTarget(target_i386_go32v2_info);
  435. end.
  436. {
  437. $Log$
  438. Revision 1.11 2001-08-19 11:22:24 peter
  439. * palmos support from v10 merged
  440. Revision 1.10 2001/08/07 18:47:15 peter
  441. * merged netbsd start
  442. * profile for win32
  443. Revision 1.9 2001/07/10 21:01:35 peter
  444. * fixed crash with writing of the linker script
  445. Revision 1.8 2001/07/01 20:16:20 peter
  446. * alignmentinfo record added
  447. * -Oa argument supports more alignment settings that can be specified
  448. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  449. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  450. required alignment and the maximum usefull alignment. The final
  451. alignment will be choosen per variable size dependent on these
  452. settings
  453. Revision 1.7 2001/06/28 19:46:25 peter
  454. * added override and virtual for constructors
  455. Revision 1.6 2001/06/18 20:36:26 peter
  456. * -Ur switch (merged)
  457. * masm fixes (merged)
  458. * quoted filenames for go32v2 and win32
  459. Revision 1.5 2001/06/03 15:15:31 peter
  460. * dllprt0 stub for linux shared libs
  461. * pass -init and -fini for linux shared libs
  462. * libprefix splitted into staticlibprefix and sharedlibprefix
  463. Revision 1.4 2001/06/02 19:22:44 peter
  464. * extradefines field added
  465. Revision 1.3 2001/04/18 22:02:04 peter
  466. * registration of targets and assemblers
  467. Revision 1.2 2001/04/13 01:22:21 peter
  468. * symtable change to classes
  469. * range check generation and errors fixed, make cycle DEBUG=1 works
  470. * memory leaks fixed
  471. Revision 1.1 2001/02/26 19:43:11 peter
  472. * moved target units to subdir
  473. Revision 1.7 2001/01/27 21:29:35 florian
  474. * behavior -Oa optimized
  475. Revision 1.6 2000/12/25 00:07:30 peter
  476. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  477. tlinkedlist objects)
  478. Revision 1.5 2000/09/24 15:06:31 peter
  479. * use defines.inc
  480. Revision 1.4 2000/08/27 16:11:54 peter
  481. * moved some util functions from globals,cobjects to cutils
  482. * splitted files into finput,fmodule
  483. Revision 1.3 2000/08/16 13:06:07 florian
  484. + support of 64 bit integer constants
  485. Revision 1.2 2000/07/13 11:32:50 michael
  486. + removed logs
  487. }