t_aix.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. {
  2. Copyright (c) 2011 by Jonas Maebe
  3. This unit implements support import,export,link routines
  4. for the AIX 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. unit t_aix;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. aasmdata,
  23. symsym,symdef,ppu,
  24. import,export,expunix,link;
  25. type
  26. timportlibaix=class(timportlib)
  27. procedure generatelib;override;
  28. end;
  29. texportlibaix=class(texportlibunix)
  30. procedure setfininame(list: TAsmList; const s: string); override;
  31. end;
  32. TLinkerAIX=class(texternallinker)
  33. private
  34. prtobj : string[80];
  35. assumebinutils,use_gld : boolean;
  36. Function WriteResponseFile(isdll:boolean) : Boolean;
  37. public
  38. constructor Create;override;
  39. procedure SetDefaultInfo;override;
  40. function MakeExecutable:boolean;override;
  41. function MakeSharedLibrary:boolean;override;
  42. end;
  43. implementation
  44. uses
  45. SysUtils,
  46. cutils,cfileutl,cclasses,
  47. verbose,systems,globtype,globals,
  48. symconst,script,
  49. fmodule,
  50. aasmbase,aasmtai,aasmcpu,cpubase,
  51. cgbase,cgobj,cgutils,ogbase,ncgutil,
  52. comprsrc,
  53. rescmn, i_aix
  54. ;
  55. {*****************************************************************************
  56. timportlibaix
  57. *****************************************************************************}
  58. procedure timportlibaix.generatelib;
  59. var
  60. i : longint;
  61. ImportLibrary : TImportLibrary;
  62. begin
  63. for i:=0 to current_module.ImportLibraryList.Count-1 do
  64. begin
  65. ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
  66. current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
  67. end;
  68. end;
  69. {*****************************************************************************
  70. texportlibaix
  71. *****************************************************************************}
  72. procedure texportlibaix.setfininame(list: TAsmList; const s: string);
  73. begin
  74. inherited setfininame(list,s);
  75. end;
  76. {*****************************************************************************
  77. TLinkerAIX
  78. *****************************************************************************}
  79. Constructor TLinkerAIX.Create;
  80. begin
  81. Inherited Create;
  82. if not Dontlinkstdlibpath then
  83. if not(cs_profile in current_settings.moduleswitches) then
  84. LibrarySearchPath.AddPath(sysrootpath,'/usr/lib;/usr/X11R6/lib;/opt/freeware/lib',true)
  85. else
  86. LibrarySearchPath.AddPath(sysrootpath,'/usr/lib/profiled;/usr/X11R6/lib;/opt/freeware/lib',true)
  87. end;
  88. procedure TLinkerAIX.SetDefaultInfo;
  89. begin
  90. with Info do
  91. begin
  92. { the -bpT and -bpD options set the base addresses for text and data
  93. sections. They are required because otherwise they are both 0 and hence
  94. overlap, which confuses gdb. GCC uses those same options. -btextro makes
  95. sure that the binary does not contain any relocations in the text
  96. section (otherwise you get an error at load time instead of at link time
  97. in case something is wrong) }
  98. ExeCmd[1]:='$LDBIN -bpT:0x10000000 -bpD:0x20000000 -btextro $OPT $STRIP -L. -o $EXE $CATRES' {$ifdef powerpc64}+' -b64'{$endif};
  99. DllCmd[1]:='$LDBIN -bpT:0x10000000 -bpD:0x20000000 -btextro $OPT $INITFINI $STRIP -G -L. -o $EXE $CATRES' {$ifdef powerpc64}+' -b64'{$endif};
  100. if cs_debuginfo in current_settings.moduleswitches then
  101. begin
  102. { debugging helpers }
  103. ExeCmd[1]:=ExeCmd[1]+' -lg -bexport:/usr/lib/libg.exp';
  104. DllCmd[1]:=DllCmd[1]+' -lg -bexport:/usr/lib/libg.exp';
  105. end;
  106. end;
  107. {$if defined(powerpc)}
  108. if not(cs_profile in current_settings.moduleswitches) then
  109. prtobj:=sysrootpath+'/lib/crt0.o'
  110. else
  111. prtobj:=sysrootpath+'/lib/gcrt0.o';
  112. {$elseif defined(powerpc64)}
  113. if not(cs_profile in current_settings.moduleswitches) then
  114. prtobj:=sysrootpath+'/lib/crt0_64.o'
  115. else
  116. prtobj:=sysrootpath+'/lib/gcrt0_64.o';
  117. {$else}
  118. {$error unsupported AIX architecture}
  119. {$endif}
  120. assumebinutils:=
  121. not(cs_link_native in current_settings.globalswitches) or
  122. (not(cs_link_on_target in current_settings.globalswitches) and
  123. not(source_info.system in systems_aix)) ;
  124. use_gld:=assumebinutils and (source_info.system in systems_aix)
  125. end;
  126. Function TLinkerAIX.WriteResponseFile(isdll:boolean) : Boolean;
  127. Var
  128. linkres : TLinkRes;
  129. i : longint;
  130. HPath : TCmdStrListItem;
  131. s,s1 : TCmdStr;
  132. begin
  133. result:=False;
  134. { Open link.res file }
  135. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,assumebinutils);
  136. with linkres do
  137. begin
  138. { Write path to search libraries }
  139. HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
  140. while assigned(HPath) do
  141. begin
  142. if assumebinutils then
  143. Add('SEARCH_DIR("'+HPath.Str+'")')
  144. else
  145. Add('-L'+HPath.Str);
  146. HPath:=TCmdStrListItem(HPath.Next);
  147. end;
  148. HPath:=TCmdStrListItem(LibrarySearchPath.First);
  149. while assigned(HPath) do
  150. begin
  151. if assumebinutils then
  152. Add('SEARCH_DIR("'+HPath.Str+'")')
  153. else
  154. Add('-L'+HPath.Str);
  155. HPath:=TCmdStrListItem(HPath.Next);
  156. end;
  157. if assumebinutils then
  158. StartSection('INPUT(');
  159. { add objectfiles, start with prt0 always }
  160. if assumebinutils then
  161. AddFileName(maybequoted(FindObjectFile(prtobj,'',false)))
  162. else
  163. AddFileName(FindObjectFile(prtobj,'',false));
  164. { main objectfiles }
  165. while not ObjectFiles.Empty do
  166. begin
  167. s:=ObjectFiles.GetFirst;
  168. if s<>'' then
  169. if assumebinutils then
  170. AddFileName(maybequoted(s))
  171. else
  172. AddFileName(s)
  173. end;
  174. { Write staticlibraries }
  175. if not StaticLibFiles.Empty then
  176. begin
  177. While not StaticLibFiles.Empty do
  178. begin
  179. S:=StaticLibFiles.GetFirst;
  180. if assumebinutils then
  181. AddFileName(maybequoted(s))
  182. else
  183. AddFileName(s);
  184. end;
  185. end;
  186. { Write sharedlibraries like -l<lib> }
  187. While not SharedLibFiles.Empty do
  188. begin
  189. S:=SharedLibFiles.GetFirst;
  190. i:=Pos(target_info.sharedlibext,S);
  191. if i>0 then
  192. Delete(S,i,255);
  193. Add('-l'+s);
  194. end;
  195. { when we have -static for the linker the we also need libgcc }
  196. if (cs_link_staticflag in current_settings.globalswitches) then
  197. begin
  198. Add('-lgcc');
  199. if librarysearchpath.FindFile('libgcc_eh.a',false,s1) then
  200. Add('-lgcc_eh');
  201. end;
  202. if assumebinutils then
  203. EndSection(')');
  204. { Write and Close response }
  205. writetodisk;
  206. Free;
  207. end;
  208. WriteResponseFile:=True;
  209. end;
  210. function TLinkerAIX.MakeExecutable:boolean;
  211. var
  212. linkscript: TAsmScript;
  213. binstr,
  214. cmdstr : TCmdStr;
  215. success : boolean;
  216. StripStr : string[40];
  217. begin
  218. if not(cs_link_nolink in current_settings.globalswitches) then
  219. Message1(exec_i_linking,current_module.exefilename);
  220. linkscript:=nil;
  221. { Create some replacements }
  222. StripStr:='';
  223. if (cs_link_strip in current_settings.globalswitches) and
  224. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  225. StripStr:='-s';
  226. if (cs_link_map in current_settings.globalswitches) then
  227. StripStr:='-bmap:'+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  228. { Write used files and libraries }
  229. WriteResponseFile(false);
  230. { Call linker }
  231. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  232. if assumebinutils and (source_info.system in systems_aix) then
  233. Replace(binstr,'$LDBIN','gld')
  234. else
  235. Replace(binstr,'$LDBIN','ld');
  236. binstr:=FindUtil(utilsprefix+BinStr);
  237. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  238. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  239. { the native AIX linker does not support linkres files, so we need
  240. CatFileContent(). The binutils cross-linker does support such files, so
  241. use them when cross-compiling to avoid overflowing the Windows maximum
  242. command line length
  243. }
  244. if not(cs_link_on_target in current_settings.globalswitches) and
  245. not(source_info.system in systems_aix) then
  246. Replace(cmdstr,'$CATRES',outputexedir+Info.ResName)
  247. else
  248. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  249. Replace(cmdstr,'$STRIP',StripStr);
  250. { create dynamic symbol table? }
  251. if HasExports then
  252. cmdstr:=cmdstr+' -E';
  253. { custom sysroot? (for cross-compiling -> assume gnu ld) }
  254. if sysrootpath<>'' then
  255. cmdstr:=cmdstr+' --sysroot='+sysrootpath;
  256. if not(cs_link_nolink in current_settings.globalswitches) and
  257. not(tf_no_backquote_support in source_info.flags) then
  258. begin
  259. { we have to use a script to use the IFS hack }
  260. linkscript:=GenerateScript(outputexedir+'ppaslink');
  261. linkscript.AddLinkCommand(binstr,CmdStr,'');
  262. // if (extdbgbinstr<>'') then
  263. // linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
  264. linkscript.WriteToDisk;
  265. BinStr:=linkscript.fn;
  266. if not path_absolute(BinStr) then
  267. if cs_link_on_target in current_settings.globalswitches then
  268. BinStr:='.'+target_info.dirsep+BinStr
  269. else
  270. BinStr:='.'+source_info.dirsep+BinStr;
  271. CmdStr:='';
  272. end;
  273. success:=DoExec(BinStr,cmdstr,true,true);
  274. { Remove ReponseFile }
  275. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  276. begin
  277. DeleteFile(outputexedir+Info.ResName);
  278. if assigned(linkscript) then
  279. DeleteFile(linkscript.fn);
  280. end;
  281. linkscript.free;
  282. MakeExecutable:=success; { otherwise a recursive call to link method }
  283. end;
  284. Function TLinkerAIX.MakeSharedLibrary:boolean;
  285. const
  286. {$ifdef cpu64bitaddr}
  287. libobj = 'shr_64.o';
  288. {$else}
  289. libobj = 'shr.o';
  290. {$endif}
  291. var
  292. linkscript : TAsmScript;
  293. exportedsyms: text;
  294. InitFiniStr : string[80];
  295. StripStr,
  296. binstr,
  297. cmdstr,
  298. libfn: TCmdStr;
  299. success : boolean;
  300. begin
  301. MakeSharedLibrary:=false;
  302. if not(cs_link_nolink in current_settings.globalswitches) then
  303. Message1(exec_i_linking,current_module.sharedlibfilename);
  304. { Write used files and libraries }
  305. WriteResponseFile(true);
  306. { Create some replacements }
  307. InitFiniStr:='-binitfini:'+exportlib.initname+':'+exportlib.fininame;
  308. Replace(InitFiniStr,'$','.');
  309. if cs_link_strip in current_settings.globalswitches then
  310. StripStr:='-s'
  311. else
  312. StripStr:='';
  313. { Call linker }
  314. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  315. if assumebinutils and (source_info.system in systems_aix) then
  316. Replace(binstr,'$LDBIN','gld')
  317. else
  318. Replace(binstr,'$LDBIN','ld');
  319. binstr:=FindUtil(utilsprefix+BinStr);
  320. { on AIX, shared libraries are special object files that are stored inside
  321. an archive. In that archive, the 32 bit version of the library is called
  322. shr.o and the 64 bit version shr_64.o }
  323. Replace(cmdstr,'$EXE',maybequoted(libobj));
  324. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  325. if not(cs_link_on_target in current_settings.globalswitches) and
  326. not(source_info.system in systems_aix) then
  327. Replace(cmdstr,'$CATRES',outputexedir+Info.ResName)
  328. else
  329. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  330. Replace(cmdstr,'$INITFINI',InitFiniStr);
  331. Replace(cmdstr,'$STRIP',StripStr);
  332. { exported symbols }
  333. if not texportlibunix(exportlib).exportedsymnames.empty then
  334. begin
  335. assign(exportedsyms,outputexedir+'linksyms.fpc');
  336. rewrite(exportedsyms);
  337. repeat
  338. writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
  339. until texportlibunix(exportlib).exportedsymnames.empty;
  340. close(exportedsyms);
  341. cmdstr:=cmdstr+' -bE:'+maybequoted(outputexedir)+'linksyms.fpc';
  342. end;
  343. libfn:=maybequoted(current_module.sharedlibfilename);
  344. { we have to use a script to use the IFS hack }
  345. linkscript:=GenerateScript(outputexedir+'ppaslink');
  346. linkscript.AddLinkCommand(binstr,CmdStr,'');
  347. { delete the target static library containing the dynamic object file in
  348. case it already existed }
  349. if FileExists(libfn,true) then
  350. linkscript.AddDeleteCommand(libfn);
  351. { and create the new one }
  352. linkscript.AddLinkCommand(FindUtil(utilsprefix+'ar'),' -X32_64 -q '+libfn+(' '+libobj),'');
  353. linkscript.WriteToDisk;
  354. BinStr:=linkscript.fn;
  355. if not path_absolute(BinStr) then
  356. if cs_link_on_target in current_settings.globalswitches then
  357. BinStr:='.'+target_info.dirsep+BinStr
  358. else
  359. BinStr:='.'+source_info.dirsep+BinStr;
  360. CmdStr:='';
  361. success:=DoExec(BinStr,cmdstr,true,true);
  362. { Remove ReponseFile }
  363. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  364. begin
  365. DeleteFile(libobj);
  366. DeleteFile(outputexedir+Info.ResName);
  367. DeleteFile(outputexedir+'linksyms.fpc');
  368. DeleteFile(linkscript.fn);
  369. end;
  370. linkscript.free;
  371. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  372. end;
  373. {*****************************************************************************
  374. Initialize
  375. *****************************************************************************}
  376. initialization
  377. RegisterLinker(ld_aix,TLinkerAIX);
  378. {$ifdef powerpc}
  379. RegisterImport(system_powerpc_aix,timportlibaix);
  380. RegisterExport(system_powerpc_aix,texportlibaix);
  381. RegisterTarget(system_powerpc_aix_info);
  382. {$endif powerpc}
  383. {$ifdef powerpc64}
  384. RegisterImport(system_powerpc64_aix,timportlibaix);
  385. RegisterExport(system_powerpc64_aix,texportlibaix);
  386. RegisterTarget(system_powerpc64_aix_info);
  387. {$endif powerpc64}
  388. RegisterRes(res_xcoff_info,TWinLikeResourceFile);
  389. end.