t_go32v2.pas 14 KB

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