link.pas 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman
  3. This unit handles the linker and binder calls for programs and
  4. libraries
  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 link;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. sysutils,
  23. cclasses,
  24. systems,
  25. fmodule,
  26. globtype,
  27. ogbase;
  28. Type
  29. TLinkerInfo=record
  30. ExeCmd,
  31. DllCmd,
  32. ExtDbgCmd : array[1..3] of string;
  33. ResName : string[100];
  34. ScriptName : string[100];
  35. ExtraOptions : TCmdStr;
  36. DynamicLinker : string[100];
  37. end;
  38. TLinker = class(TAbstractLinker)
  39. public
  40. HasResources,
  41. HasExports : boolean;
  42. SysInitUnit : string[20];
  43. ObjectFiles,
  44. SharedLibFiles,
  45. StaticLibFiles,
  46. FrameworkFiles : TCmdStrList;
  47. Constructor Create;virtual;
  48. Destructor Destroy;override;
  49. procedure AddModuleFiles(hp:tmodule);
  50. Procedure AddObject(const S,unitpath : TCmdStr;isunit:boolean);
  51. Procedure AddStaticLibrary(const S : TCmdStr);
  52. Procedure AddSharedLibrary(S : TCmdStr);
  53. Procedure AddStaticCLibrary(const S : TCmdStr);
  54. Procedure AddSharedCLibrary(S : TCmdStr);
  55. Procedure AddFramework(S : TCmdStr);
  56. procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);virtual;
  57. Procedure InitSysInitUnitName;virtual;
  58. Function MakeExecutable:boolean;virtual;
  59. Function MakeSharedLibrary:boolean;virtual;
  60. Function MakeStaticLibrary:boolean;virtual;
  61. procedure ExpandAndApplyOrder(var Src:TCmdStrList);
  62. procedure LoadPredefinedLibraryOrder;virtual;
  63. function ReOrderEntries : boolean;
  64. end;
  65. TExternalLinker = class(TLinker)
  66. public
  67. Info : TLinkerInfo;
  68. Constructor Create;override;
  69. Destructor Destroy;override;
  70. Function FindUtil(const s:TCmdStr):TCmdStr;
  71. Function DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
  72. procedure SetDefaultInfo;virtual;
  73. Function MakeStaticLibrary:boolean;override;
  74. end;
  75. TBooleanArray = array [1..1024] of boolean;
  76. PBooleanArray = ^TBooleanArray;
  77. TInternalLinker = class(TLinker)
  78. private
  79. FCExeOutput : TExeOutputClass;
  80. FCObjInput : TObjInputClass;
  81. { Libraries }
  82. FStaticLibraryList : TFPHashObjectList;
  83. FImportLibraryList : TFPHashObjectList;
  84. procedure Load_ReadObject(const para:TCmdStr);
  85. procedure Load_ReadStaticLibrary(const para:TCmdStr);
  86. procedure ParseScript_Handle;
  87. procedure ParseScript_PostCheck;
  88. procedure ParseScript_Load;
  89. function ParsePara(const para : string) : string;
  90. procedure ParseScript_Order;
  91. procedure ParseScript_MemPos;
  92. procedure ParseScript_DataPos;
  93. procedure PrintLinkerScript;
  94. function RunLinkScript(const outputname:TCmdStr):boolean;
  95. protected
  96. linkscript : TCmdStrList;
  97. ScriptCount : longint;
  98. IsHandled : PBooleanArray;
  99. property CObjInput:TObjInputClass read FCObjInput write FCObjInput;
  100. property CExeOutput:TExeOutputClass read FCExeOutput write FCExeOutput;
  101. property StaticLibraryList:TFPHashObjectList read FStaticLibraryList;
  102. property ImportLibraryList:TFPHashObjectList read FImportLibraryList;
  103. procedure DefaultLinkScript;virtual;abstract;
  104. public
  105. IsSharedLibrary : boolean;
  106. UseStabs : boolean;
  107. Constructor Create;override;
  108. Destructor Destroy;override;
  109. Function MakeExecutable:boolean;override;
  110. Function MakeSharedLibrary:boolean;override;
  111. procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);override;
  112. end;
  113. var
  114. Linker : TLinker;
  115. function FindObjectFile(s : TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
  116. function FindLibraryFile(s:TCmdStr;const prefix,ext:TCmdStr;var foundfile : TCmdStr) : boolean;
  117. function FindDLL(const s:TCmdStr;var founddll:TCmdStr):boolean;
  118. procedure InitLinker;
  119. procedure DoneLinker;
  120. Implementation
  121. uses
  122. cutils,cfileutl,cstreams,
  123. script,globals,verbose,comphook,ppu,fpccrc,
  124. aasmbase,aasmtai,aasmdata,aasmcpu,
  125. owbase,owar,ogmap;
  126. type
  127. TLinkerClass = class of Tlinker;
  128. {*****************************************************************************
  129. Helpers
  130. *****************************************************************************}
  131. function GetFileCRC(const fn:string):cardinal;
  132. var
  133. fs : TCStream;
  134. bufcount,
  135. bufsize : Integer;
  136. buf : pbyte;
  137. begin
  138. result:=0;
  139. bufsize:=64*1024;
  140. fs:=CFileStreamClass.Create(fn,fmOpenRead or fmShareDenyNone);
  141. if CStreamError<>0 then
  142. begin
  143. fs.Free;
  144. Comment(V_Error,'Can''t open file: '+fn);
  145. exit;
  146. end;
  147. getmem(buf,bufsize);
  148. repeat
  149. bufcount:=fs.Read(buf^,bufsize);
  150. result:=UpdateCrc32(result,buf^,bufcount);
  151. until bufcount<bufsize;
  152. freemem(buf);
  153. fs.Free;
  154. end;
  155. { searches an object file }
  156. function FindObjectFile(s:TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
  157. var
  158. found : boolean;
  159. foundfile : TCmdStr;
  160. begin
  161. findobjectfile:='';
  162. if s='' then
  163. exit;
  164. {When linking on target, the units has not been assembled yet,
  165. so there is no object files to look for at
  166. the host. Look for the corresponding assembler file instead,
  167. because it will be assembled to object file on the target.}
  168. if isunit and (cs_link_on_target in current_settings.globalswitches) then
  169. s:=ChangeFileExt(s,target_info.asmext);
  170. { when it does not belong to the unit then check if
  171. the specified file exists without searching any paths }
  172. if not isunit then
  173. begin
  174. if FileExists(FixFileName(s),false) then
  175. begin
  176. foundfile:=ScriptFixFileName(s);
  177. found:=true;
  178. end;
  179. end;
  180. if pos('.',s)=0 then
  181. s:=s+target_info.objext;
  182. { find object file
  183. 1. output unit path
  184. 2. output exe path
  185. 3. specified unit path (if specified)
  186. 4. cwd
  187. 5. unit search path
  188. 6. local object path
  189. 7. global object path
  190. 8. exepath (not when linking on target)
  191. for all finds don't use the directory caching }
  192. found:=false;
  193. if isunit and (OutputUnitDir<>'') then
  194. found:=FindFile(s,OutPutUnitDir,false,foundfile)
  195. else
  196. if OutputExeDir<>'' then
  197. found:=FindFile(s,OutPutExeDir,false,foundfile);
  198. if (not found) and (unitpath<>'') then
  199. found:=FindFile(s,unitpath,false,foundfile);
  200. if (not found) then
  201. found:=FindFile(s, CurDirRelPath(source_info),false,foundfile);
  202. if (not found) then
  203. found:=UnitSearchPath.FindFile(s,false,foundfile);
  204. if (not found) then
  205. found:=current_module.localobjectsearchpath.FindFile(s,false,foundfile);
  206. if (not found) then
  207. found:=objectsearchpath.FindFile(s,false,foundfile);
  208. if not(cs_link_on_target in current_settings.globalswitches) and (not found) then
  209. found:=FindFile(s,exepath,false,foundfile);
  210. if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
  211. Message1(exec_w_objfile_not_found,s);
  212. {Restore file extension}
  213. if isunit and (cs_link_on_target in current_settings.globalswitches) then
  214. foundfile:= ChangeFileExt(foundfile,target_info.objext);
  215. findobjectfile:=ScriptFixFileName(foundfile);
  216. end;
  217. { searches a (windows) DLL file }
  218. function FindDLL(const s:TCmdStr;var founddll:TCmdStr):boolean;
  219. var
  220. sysdir : TCmdStr;
  221. Found : boolean;
  222. begin
  223. Found:=false;
  224. { Look for DLL in:
  225. 1. Current dir
  226. 2. Library Path
  227. 3. windir,windir/system,windir/system32 }
  228. Found:=FindFile(s,'.'+source_info.DirSep,false,founddll);
  229. if (not found) then
  230. Found:=librarysearchpath.FindFile(s,false,founddll);
  231. { when cross compiling, it is pretty useless to search windir etc. for dlls }
  232. if (not found) and (source_info.system=target_info.system) then
  233. begin
  234. sysdir:=FixPath(GetEnvironmentVariable('windir'),false);
  235. Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,false,founddll);
  236. end;
  237. if (not found) then
  238. begin
  239. message1(exec_w_libfile_not_found,s);
  240. FoundDll:=s;
  241. end;
  242. FindDll:=Found;
  243. end;
  244. { searches an library file }
  245. function FindLibraryFile(s:TCmdStr;const prefix,ext:TCmdStr;var foundfile : TCmdStr) : boolean;
  246. var
  247. found : boolean;
  248. paths : TCmdStr;
  249. begin
  250. findlibraryfile:=false;
  251. foundfile:=s;
  252. if s='' then
  253. exit;
  254. { split path from filename }
  255. paths:=ExtractFilePath(s);
  256. s:=ExtractFileName(s);
  257. { add prefix 'lib' }
  258. if (prefix<>'') and (Copy(s,1,length(prefix))<>prefix) then
  259. s:=prefix+s;
  260. { add extension }
  261. if (ext<>'') and (Copy(s,length(s)-length(ext)+1,length(ext))<>ext) then
  262. s:=s+ext;
  263. { readd the split path }
  264. s:=paths+s;
  265. if FileExists(s,false) then
  266. begin
  267. foundfile:=ScriptFixFileName(s);
  268. FindLibraryFile:=true;
  269. exit;
  270. end;
  271. { find libary
  272. 1. cwd
  273. 2. local libary dir
  274. 3. global libary dir
  275. 4. exe path of the compiler (not when linking on target)
  276. for all searches don't use the directory cache }
  277. found:=FindFile(s, CurDirRelPath(source_info), false,foundfile);
  278. if (not found) and (current_module.outputpath^<>'') then
  279. found:=FindFile(s,current_module.outputpath^,false,foundfile);
  280. if (not found) then
  281. found:=current_module.locallibrarysearchpath.FindFile(s,false,foundfile);
  282. if (not found) then
  283. found:=librarysearchpath.FindFile(s,false,foundfile);
  284. if not(cs_link_on_target in current_settings.globalswitches) and (not found) then
  285. found:=FindFile(s,exepath,false,foundfile);
  286. foundfile:=ScriptFixFileName(foundfile);
  287. findlibraryfile:=found;
  288. end;
  289. {*****************************************************************************
  290. TLINKER
  291. *****************************************************************************}
  292. Constructor TLinker.Create;
  293. begin
  294. Inherited Create;
  295. ObjectFiles:=TCmdStrList.Create_no_double;
  296. SharedLibFiles:=TCmdStrList.Create_no_double;
  297. StaticLibFiles:=TCmdStrList.Create_no_double;
  298. FrameworkFiles:=TCmdStrList.Create_no_double;
  299. end;
  300. Destructor TLinker.Destroy;
  301. begin
  302. ObjectFiles.Free;
  303. SharedLibFiles.Free;
  304. StaticLibFiles.Free;
  305. FrameworkFiles.Free;
  306. end;
  307. procedure TLinker.AddModuleFiles(hp:tmodule);
  308. var
  309. mask : longint;
  310. i,j : longint;
  311. ImportLibrary : TImportLibrary;
  312. ImportSymbol : TImportSymbol;
  313. begin
  314. with hp do
  315. begin
  316. if (flags and uf_has_resourcefiles)<>0 then
  317. HasResources:=true;
  318. if (flags and uf_has_exports)<>0 then
  319. HasExports:=true;
  320. { link unit files }
  321. if (flags and uf_no_link)=0 then
  322. begin
  323. { create mask which unit files need linking }
  324. mask:=link_always;
  325. { static linking ? }
  326. if (cs_link_static in current_settings.globalswitches) then
  327. begin
  328. if (flags and uf_static_linked)=0 then
  329. begin
  330. { if smart not avail then try static linking }
  331. if (flags and uf_smart_linked)<>0 then
  332. begin
  333. Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
  334. mask:=mask or link_smart;
  335. end
  336. else
  337. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  338. end
  339. else
  340. mask:=mask or link_static;
  341. end;
  342. { smart linking ? }
  343. if (cs_link_smart in current_settings.globalswitches) then
  344. begin
  345. if (flags and uf_smart_linked)=0 then
  346. begin
  347. { if smart not avail then try static linking }
  348. if (flags and uf_static_linked)<>0 then
  349. begin
  350. { if not create_smartlink_library, then smart linking happens using the
  351. regular object files
  352. }
  353. if create_smartlink_library then
  354. Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
  355. mask:=mask or link_static;
  356. end
  357. else
  358. Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
  359. end
  360. else
  361. mask:=mask or link_smart;
  362. end;
  363. { shared linking }
  364. if (cs_link_shared in current_settings.globalswitches) then
  365. begin
  366. if (flags and uf_shared_linked)=0 then
  367. begin
  368. { if shared not avail then try static linking }
  369. if (flags and uf_static_linked)<>0 then
  370. begin
  371. Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
  372. mask:=mask or link_static;
  373. end
  374. else
  375. Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
  376. end
  377. else
  378. mask:=mask or link_shared;
  379. end;
  380. { unit files }
  381. while not linkunitofiles.empty do
  382. AddObject(linkunitofiles.getusemask(mask),path^,true);
  383. while not linkunitstaticlibs.empty do
  384. AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
  385. while not linkunitsharedlibs.empty do
  386. AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
  387. end;
  388. { Other needed .o and libs, specified using $L,$LINKLIB,external }
  389. mask:=link_always;
  390. while not linkotherofiles.empty do
  391. AddObject(linkotherofiles.Getusemask(mask),path^,false);
  392. while not linkotherstaticlibs.empty do
  393. AddStaticCLibrary(linkotherstaticlibs.Getusemask(mask));
  394. while not linkothersharedlibs.empty do
  395. AddSharedCLibrary(linkothersharedlibs.Getusemask(mask));
  396. while not linkotherframeworks.empty do
  397. AddFramework(linkotherframeworks.Getusemask(mask));
  398. { Known Library/DLL Imports }
  399. for i:=0 to ImportLibraryList.Count-1 do
  400. begin
  401. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  402. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  403. begin
  404. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  405. AddImportSymbol(ImportLibrary.Name,ImportSymbol.Name,
  406. ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
  407. end;
  408. end;
  409. end;
  410. end;
  411. procedure TLinker.AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
  412. begin
  413. end;
  414. Procedure TLinker.AddObject(const S,unitpath : TCmdStr;isunit:boolean);
  415. begin
  416. ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
  417. end;
  418. Procedure TLinker.AddSharedLibrary(S:TCmdStr);
  419. begin
  420. if s='' then
  421. exit;
  422. { remove prefix 'lib' }
  423. if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
  424. Delete(s,1,length(target_info.sharedlibprefix));
  425. { remove extension if any }
  426. if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
  427. Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
  428. { ready to be added }
  429. SharedLibFiles.Concat(S);
  430. end;
  431. Procedure TLinker.AddStaticLibrary(const S:TCmdStr);
  432. var
  433. ns : TCmdStr;
  434. found : boolean;
  435. begin
  436. if s='' then
  437. exit;
  438. found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
  439. if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
  440. Message1(exec_w_libfile_not_found,s);
  441. StaticLibFiles.Concat(ns);
  442. end;
  443. Procedure TLinker.AddSharedCLibrary(S:TCmdStr);
  444. begin
  445. if s='' then
  446. exit;
  447. { remove prefix 'lib' }
  448. if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
  449. Delete(s,1,length(target_info.sharedclibprefix));
  450. { remove extension if any }
  451. if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
  452. Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
  453. { ready to be added }
  454. SharedLibFiles.Concat(S);
  455. end;
  456. Procedure TLinker.AddFramework(S:TCmdStr);
  457. begin
  458. if s='' then
  459. exit;
  460. { ready to be added }
  461. FrameworkFiles.Concat(S);
  462. end;
  463. Procedure TLinker.AddStaticCLibrary(const S:TCmdStr);
  464. var
  465. ns : TCmdStr;
  466. found : boolean;
  467. begin
  468. if s='' then
  469. exit;
  470. found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
  471. if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
  472. Message1(exec_w_libfile_not_found,s);
  473. StaticLibFiles.Concat(ns);
  474. end;
  475. procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
  476. begin
  477. end;
  478. procedure TLinker.InitSysInitUnitName;
  479. begin
  480. end;
  481. function TLinker.MakeExecutable:boolean;
  482. begin
  483. MakeExecutable:=false;
  484. Message(exec_e_exe_not_supported);
  485. end;
  486. Function TLinker.MakeSharedLibrary:boolean;
  487. begin
  488. MakeSharedLibrary:=false;
  489. Message(exec_e_dll_not_supported);
  490. end;
  491. Function TLinker.MakeStaticLibrary:boolean;
  492. begin
  493. MakeStaticLibrary:=false;
  494. Message(exec_e_dll_not_supported);
  495. end;
  496. Procedure TLinker.ExpandAndApplyOrder(var Src:TCmdStrList);
  497. var
  498. p : TLinkStrMap;
  499. i : longint;
  500. begin
  501. // call Virtual TLinker method to initialize
  502. LoadPredefinedLibraryOrder;
  503. // something to do?
  504. if (LinkLibraryAliases.count=0) and (LinkLibraryOrder.Count=0) Then
  505. exit;
  506. p:=TLinkStrMap.Create;
  507. // expand libaliases, clears src
  508. LinkLibraryAliases.expand(src,p);
  509. // writeln(src.count,' ',p.count,' ',linklibraryorder.count,' ',linklibraryaliases.count);
  510. // apply order
  511. p.UpdateWeights(LinkLibraryOrder);
  512. p.SortOnWeight;
  513. // put back in src
  514. for i:=0 to p.count-1 do
  515. src.insert(p[i].Key);
  516. p.free;
  517. end;
  518. procedure TLinker.LoadPredefinedLibraryOrder;
  519. begin
  520. end;
  521. function TLinker.ReOrderEntries : boolean;
  522. begin
  523. result:=(LinkLibraryOrder.count>0) or (LinkLibraryAliases.count>0);
  524. end;
  525. {*****************************************************************************
  526. TEXTERNALLINKER
  527. *****************************************************************************}
  528. Constructor TExternalLinker.Create;
  529. begin
  530. inherited Create;
  531. { set generic defaults }
  532. FillChar(Info,sizeof(Info),0);
  533. if cs_link_on_target in current_settings.globalswitches then
  534. begin
  535. Info.ResName:=outputexedir+ChangeFileExt(inputfilename,'_link.res');
  536. Info.ScriptName:=outputexedir+ChangeFileExt(inputfilename,'_script.res');
  537. end
  538. else
  539. begin
  540. Info.ResName:='link.res';
  541. Info.ScriptName:='script.res';
  542. end;
  543. { set the linker specific defaults }
  544. SetDefaultInfo;
  545. { Allow Parameter overrides for linker info }
  546. with Info do
  547. begin
  548. if ParaLinkOptions<>'' then
  549. ExtraOptions:=ParaLinkOptions;
  550. if ParaDynamicLinker<>'' then
  551. DynamicLinker:=ParaDynamicLinker;
  552. end;
  553. end;
  554. Destructor TExternalLinker.Destroy;
  555. begin
  556. inherited destroy;
  557. end;
  558. Procedure TExternalLinker.SetDefaultInfo;
  559. begin
  560. end;
  561. Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
  562. var
  563. Found : boolean;
  564. FoundBin : TCmdStr;
  565. UtilExe : TCmdStr;
  566. begin
  567. if cs_link_on_target in current_settings.globalswitches then
  568. begin
  569. { If linking on target, don't add any path PM }
  570. FindUtil:=ChangeFileExt(s,target_info.exeext);
  571. exit;
  572. end;
  573. UtilExe:=ChangeFileExt(s,source_info.exeext);
  574. FoundBin:='';
  575. Found:=false;
  576. if utilsdirectory<>'' then
  577. Found:=FindFile(utilexe,utilsdirectory,false,Foundbin);
  578. if (not Found) then
  579. Found:=FindExe(utilexe,false,Foundbin);
  580. if (not Found) and not(cs_link_nolink in current_settings.globalswitches) then
  581. begin
  582. Message1(exec_e_util_not_found,utilexe);
  583. current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
  584. end;
  585. if (FoundBin<>'') then
  586. Message1(exec_t_using_util,FoundBin);
  587. FindUtil:=FoundBin;
  588. end;
  589. Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
  590. var
  591. exitcode: longint;
  592. begin
  593. DoExec:=true;
  594. if not(cs_link_nolink in current_settings.globalswitches) then
  595. begin
  596. FlushOutput;
  597. if useshell then
  598. exitcode:=shell(maybequoted(command)+' '+para)
  599. else
  600. try
  601. exitcode:=ExecuteProcess(command,para);
  602. except on E:EOSError do
  603. begin
  604. Message(exec_e_cant_call_linker);
  605. current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
  606. DoExec:=false;
  607. end;
  608. end;
  609. if (exitcode<>0) then
  610. begin
  611. Message(exec_e_error_while_linking);
  612. current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
  613. DoExec:=false;
  614. end;
  615. end;
  616. { Update asmres when externmode is set }
  617. if cs_link_nolink in current_settings.globalswitches then
  618. begin
  619. if showinfo then
  620. begin
  621. if DLLsource then
  622. AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
  623. else
  624. AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
  625. end
  626. else
  627. AsmRes.AddLinkCommand(Command,Para,'');
  628. end;
  629. end;
  630. Function TExternalLinker.MakeStaticLibrary:boolean;
  631. function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem) : TCmdStr;
  632. begin
  633. result := '';
  634. while (assigned(item) and ((length(result) + length(item.str) + 1) < maxCmdLength)) do begin
  635. result := result + ' ' + item.str;
  636. item := TCmdStrListItem(item.next);
  637. end;
  638. end;
  639. var
  640. binstr, scriptfile : TCmdStr;
  641. cmdstr, nextcmd, smartpath : TCmdStr;
  642. current : TCmdStrListItem;
  643. script: Text;
  644. scripted_ar : boolean;
  645. success : boolean;
  646. begin
  647. MakeStaticLibrary:=false;
  648. { remove the library, to be sure that it is rewritten }
  649. DeleteFile(current_module.staticlibfilename^);
  650. { Call AR }
  651. smartpath:=FixPath(ChangeFileExt(current_module.asmfilename^,target_info.smartext),false);
  652. SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
  653. binstr := FindUtil(utilsprefix + binstr);
  654. scripted_ar:=target_ar.id=ar_gnu_ar_scripted;
  655. if scripted_ar then
  656. begin
  657. scriptfile := FixFileName(smartpath+'arscript.txt');
  658. Replace(cmdstr,'$SCRIPT',maybequoted(scriptfile));
  659. Assign(script, scriptfile);
  660. Rewrite(script);
  661. try
  662. writeln(script, 'CREATE ' + current_module.staticlibfilename^);
  663. current := TCmdStrListItem(SmartLinkOFiles.First);
  664. while current <> nil do
  665. begin
  666. writeln(script, 'ADDMOD ' + current.str);
  667. current := TCmdStrListItem(current.next);
  668. end;
  669. writeln(script, 'SAVE');
  670. writeln(script, 'END');
  671. finally
  672. Close(script);
  673. end;
  674. success:=DoExec(binstr,cmdstr,false,true);
  675. end
  676. else
  677. begin
  678. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  679. { create AR commands }
  680. success := true;
  681. current := TCmdStrListItem(SmartLinkOFiles.First);
  682. repeat
  683. nextcmd := cmdstr;
  684. Replace(nextcmd,'$FILES',GetNextFiles(2047, current));
  685. success:=DoExec(binstr,nextcmd,false,true);
  686. until (not assigned(current)) or (not success);
  687. end;
  688. if (target_ar.arfinishcmd <> '') then
  689. begin
  690. SplitBinCmd(target_ar.arfinishcmd,binstr,cmdstr);
  691. binstr := FindUtil(utilsprefix + binstr);
  692. Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
  693. success:=DoExec(binstr,cmdstr,false,true);
  694. end;
  695. { Clean up }
  696. if not(cs_asm_leave in current_settings.globalswitches) then
  697. if not(cs_link_nolink in current_settings.globalswitches) then
  698. begin
  699. while not SmartLinkOFiles.Empty do
  700. DeleteFile(SmartLinkOFiles.GetFirst);
  701. if scripted_ar then
  702. DeleteFile(scriptfile);
  703. RemoveDir(smartpath);
  704. end
  705. else
  706. begin
  707. AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
  708. if scripted_ar then
  709. AsmRes.AddDeleteCommand(scriptfile);
  710. AsmRes.AddDeleteDirCommand(smartpath);
  711. end;
  712. MakeStaticLibrary:=success;
  713. end;
  714. {*****************************************************************************
  715. TINTERNALLINKER
  716. *****************************************************************************}
  717. Constructor TInternalLinker.Create;
  718. begin
  719. inherited Create;
  720. linkscript:=TCmdStrList.Create;
  721. FStaticLibraryList:=TFPHashObjectList.Create(true);
  722. FImportLibraryList:=TFPHashObjectList.Create(true);
  723. exemap:=nil;
  724. exeoutput:=nil;
  725. UseStabs:=false;
  726. CObjInput:=TObjInput;
  727. ScriptCount:=0;
  728. IsHandled:=nil;
  729. end;
  730. Destructor TInternalLinker.Destroy;
  731. begin
  732. linkscript.free;
  733. StaticLibraryList.Free;
  734. ImportLibraryList.Free;
  735. if assigned(IsHandled) then
  736. begin
  737. FreeMem(IsHandled,sizeof(boolean)*ScriptCount);
  738. IsHandled:=nil;
  739. ScriptCount:=0;
  740. end;
  741. if assigned(exeoutput) then
  742. begin
  743. exeoutput.free;
  744. exeoutput:=nil;
  745. end;
  746. if assigned(exemap) then
  747. begin
  748. exemap.free;
  749. exemap:=nil;
  750. end;
  751. inherited destroy;
  752. end;
  753. procedure TInternalLinker.AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
  754. var
  755. ImportLibrary : TImportLibrary;
  756. ImportSymbol : TFPHashObject;
  757. begin
  758. ImportLibrary:=TImportLibrary(ImportLibraryList.Find(libname));
  759. if not assigned(ImportLibrary) then
  760. ImportLibrary:=TImportLibrary.Create(ImportLibraryList,libname);
  761. ImportSymbol:=TFPHashObject(ImportLibrary.ImportSymbolList.Find(symname));
  762. if not assigned(ImportSymbol) then
  763. ImportSymbol:=TImportSymbol.Create(ImportLibrary.ImportSymbolList,symname,symmangledname,OrdNr,isvar);
  764. end;
  765. procedure TInternalLinker.Load_ReadObject(const para:TCmdStr);
  766. var
  767. objdata : TObjData;
  768. objinput : TObjinput;
  769. objreader : TObjectReader;
  770. fn : TCmdStr;
  771. begin
  772. fn:=FindObjectFile(para,'',false);
  773. Comment(V_Tried,'Reading object '+fn);
  774. objinput:=CObjInput.Create;
  775. objdata:=objinput.newObjData(para);
  776. objreader:=TObjectreader.create;
  777. if objreader.openfile(fn) then
  778. begin
  779. if objinput.ReadObjData(objreader,objdata) then
  780. exeoutput.addobjdata(objdata);
  781. end;
  782. { release input object }
  783. objinput.free;
  784. objreader.free;
  785. end;
  786. procedure TInternalLinker.Load_ReadStaticLibrary(const para:TCmdStr);
  787. var
  788. objreader : TObjectReader;
  789. begin
  790. { TODO: Cleanup ignoring of FPC generated libimp*.a files}
  791. { Don't load import libraries }
  792. if copy(ExtractFileName(para),1,6)='libimp' then
  793. exit;
  794. Comment(V_Tried,'Opening library '+para);
  795. objreader:=TArObjectreader.create(para);
  796. TStaticLibrary.Create(StaticLibraryList,para,objreader,CObjInput);
  797. end;
  798. procedure TInternalLinker.ParseScript_Handle;
  799. var
  800. s, para, keyword : String;
  801. hp : TCmdStrListItem;
  802. i : longint;
  803. begin
  804. hp:=TCmdStrListItem(linkscript.first);
  805. i:=0;
  806. while assigned(hp) do
  807. begin
  808. inc(i);
  809. s:=hp.str;
  810. if (s='') or (s[1]='#') then
  811. continue;
  812. keyword:=Upper(GetToken(s,' '));
  813. para:=GetToken(s,' ');
  814. if Trim(s)<>'' then
  815. Comment(V_Warning,'Unknown part "'+s+'" in "'+hp.str+'" internal linker script');
  816. if (keyword<>'SYMBOL') and
  817. (keyword<>'SYMBOLS') and
  818. (keyword<>'STABS') and
  819. (keyword<>'PROVIDE') and
  820. (keyword<>'ZEROS') and
  821. (keyword<>'BYTE') and
  822. (keyword<>'WORD') and
  823. (keyword<>'LONG') and
  824. (keyword<>'QUAD') and
  825. (keyword<>'ENTRYNAME') and
  826. (keyword<>'ISSHAREDLIBRARY') and
  827. (keyword<>'IMAGEBASE') and
  828. (keyword<>'READOBJECT') and
  829. (keyword<>'READSTATICLIBRARY') and
  830. (keyword<>'EXESECTION') and
  831. (keyword<>'ENDEXESECTION') and
  832. (keyword<>'OBJSECTION') and
  833. (keyword<>'HEADER')
  834. then
  835. Comment(V_Warning,'Unknown keyword "'+keyword+'" in "'+hp.str
  836. +'" internal linker script');
  837. hp:=TCmdStrListItem(hp.next);
  838. end;
  839. ScriptCount:=i;
  840. if ScriptCount>0 then
  841. begin
  842. GetMem(IsHandled,sizeof(boolean)*ScriptCount);
  843. Fillchar(IsHandled^,sizeof(boolean)*ScriptCount,#0);
  844. end;
  845. end;
  846. procedure TInternalLinker.ParseScript_PostCheck;
  847. var
  848. s : String;
  849. hp : TCmdStrListItem;
  850. i : longint;
  851. begin
  852. hp:=TCmdStrListItem(linkscript.first);
  853. i:=0;
  854. while assigned(hp) do
  855. begin
  856. inc(i);
  857. if not IsHandled^[i] then
  858. begin
  859. s:=hp.str;
  860. Comment(V_Warning,'"'+hp.str+
  861. '" internal linker script not handled');
  862. end;
  863. hp:=TCmdStrListItem(hp.next);
  864. end;
  865. end;
  866. function TInternalLinker.ParsePara(const para : string) : string;
  867. var
  868. res : string;
  869. begin
  870. res:=trim(para);
  871. { Remove enclosing braces }
  872. if (length(res)>0) and (res[1]='(') and
  873. (res[length(res)]=')') then
  874. res:=trim(copy(res,2,length(res)-2));
  875. result:=res;
  876. end;
  877. procedure TInternalLinker.ParseScript_Load;
  878. var
  879. s,
  880. para,
  881. keyword : String;
  882. hp : TCmdStrListItem;
  883. i : longint;
  884. handled : boolean;
  885. begin
  886. exeoutput.Load_Start;
  887. hp:=TCmdStrListItem(linkscript.first);
  888. i:=0;
  889. while assigned(hp) do
  890. begin
  891. inc(i);
  892. s:=hp.str;
  893. if (s='') or (s[1]='#') then
  894. begin
  895. IsHandled^[i]:=true;
  896. continue;
  897. end;
  898. handled:=true;
  899. keyword:=Upper(GetToken(s,' '));
  900. para:=ParsePara(GetToken(s,' '));
  901. if keyword='SYMBOL' then
  902. ExeOutput.Load_Symbol(para)
  903. else if keyword='PROVIDE' then
  904. ExeOutput.Load_ProvideSymbol(para)
  905. else if keyword='ENTRYNAME' then
  906. ExeOutput.Load_EntryName(para)
  907. else if keyword='ISSHAREDLIBRARY' then
  908. ExeOutput.Load_IsSharedLibrary
  909. else if keyword='IMAGEBASE' then
  910. ExeOutput.Load_ImageBase(para)
  911. else if keyword='READOBJECT' then
  912. Load_ReadObject(para)
  913. else if keyword='STABS' then
  914. UseStabs:=true
  915. else if keyword='READSTATICLIBRARY' then
  916. Load_ReadStaticLibrary(para)
  917. else
  918. handled:=false;
  919. if handled then
  920. IsHandled^[i]:=true;
  921. hp:=TCmdStrListItem(hp.next);
  922. end;
  923. end;
  924. procedure TInternalLinker.ParseScript_Order;
  925. var
  926. s,
  927. para,
  928. keyword : String;
  929. hp : TCmdStrListItem;
  930. i : longint;
  931. handled : boolean;
  932. begin
  933. exeoutput.Order_Start;
  934. hp:=TCmdStrListItem(linkscript.first);
  935. i:=0;
  936. while assigned(hp) do
  937. begin
  938. inc(i);
  939. s:=hp.str;
  940. if (s='') or (s[1]='#') then
  941. continue;
  942. handled:=true;
  943. keyword:=Upper(GetToken(s,' '));
  944. para:=ParsePara(GetToken(s,' '));
  945. if keyword='EXESECTION' then
  946. ExeOutput.Order_ExeSection(para)
  947. else if keyword='ENDEXESECTION' then
  948. ExeOutput.Order_EndExeSection
  949. else if keyword='OBJSECTION' then
  950. ExeOutput.Order_ObjSection(para)
  951. else if keyword='ZEROS' then
  952. ExeOutput.Order_Zeros(para)
  953. else if keyword='BYTE' then
  954. ExeOutput.Order_Values(1,para)
  955. else if keyword='WORD' then
  956. ExeOutput.Order_Values(2,para)
  957. else if keyword='LONG' then
  958. ExeOutput.Order_Values(4,para)
  959. else if keyword='QUAD' then
  960. ExeOutput.Order_Values(8,para)
  961. else if keyword='SYMBOL' then
  962. ExeOutput.Order_Symbol(para)
  963. else if keyword='PROVIDE' then
  964. ExeOutput.Order_ProvideSymbol(para)
  965. else
  966. handled:=false;
  967. if handled then
  968. IsHandled^[i]:=true;
  969. hp:=TCmdStrListItem(hp.next);
  970. end;
  971. exeoutput.Order_End;
  972. end;
  973. procedure TInternalLinker.ParseScript_MemPos;
  974. var
  975. s,
  976. para,
  977. keyword : String;
  978. hp : TCmdStrListItem;
  979. i : longint;
  980. handled : boolean;
  981. begin
  982. exeoutput.MemPos_Start;
  983. hp:=TCmdStrListItem(linkscript.first);
  984. i:=0;
  985. while assigned(hp) do
  986. begin
  987. inc(i);
  988. s:=hp.str;
  989. if (s='') or (s[1]='#') then
  990. continue;
  991. handled:=true;
  992. keyword:=Upper(GetToken(s,' '));
  993. para:=ParsePara(GetToken(s,' '));
  994. if keyword='EXESECTION' then
  995. ExeOutput.MemPos_ExeSection(para)
  996. else if keyword='ENDEXESECTION' then
  997. ExeOutput.MemPos_EndExeSection
  998. else if keyword='HEADER' then
  999. ExeOutput.MemPos_Header
  1000. else
  1001. handled:=false;
  1002. if handled then
  1003. IsHandled^[i]:=true;
  1004. hp:=TCmdStrListItem(hp.next);
  1005. end;
  1006. end;
  1007. procedure TInternalLinker.ParseScript_DataPos;
  1008. var
  1009. s,
  1010. para,
  1011. keyword : String;
  1012. hp : TCmdStrListItem;
  1013. i : longint;
  1014. handled : boolean;
  1015. begin
  1016. exeoutput.DataPos_Start;
  1017. hp:=TCmdStrListItem(linkscript.first);
  1018. i:=0;
  1019. while assigned(hp) do
  1020. begin
  1021. inc(i);
  1022. s:=hp.str;
  1023. if (s='') or (s[1]='#') then
  1024. continue;
  1025. handled:=true;
  1026. keyword:=Upper(GetToken(s,' '));
  1027. para:=ParsePara(GetToken(s,' '));
  1028. if keyword='EXESECTION' then
  1029. ExeOutput.DataPos_ExeSection(para)
  1030. else if keyword='ENDEXESECTION' then
  1031. ExeOutput.DataPos_EndExeSection
  1032. else if keyword='HEADER' then
  1033. ExeOutput.DataPos_Header
  1034. else if keyword='SYMBOLS' then
  1035. ExeOutput.DataPos_Symbols
  1036. else
  1037. handled:=false;
  1038. if handled then
  1039. IsHandled^[i]:=true;
  1040. hp:=TCmdStrListItem(hp.next);
  1041. end;
  1042. end;
  1043. procedure TInternalLinker.PrintLinkerScript;
  1044. var
  1045. hp : TCmdStrListItem;
  1046. begin
  1047. if not assigned(exemap) then
  1048. exit;
  1049. exemap.Add('Used linker script');
  1050. exemap.Add('');
  1051. hp:=TCmdStrListItem(linkscript.first);
  1052. while assigned(hp) do
  1053. begin
  1054. exemap.Add(hp.str);
  1055. hp:=TCmdStrListItem(hp.next);
  1056. end;
  1057. end;
  1058. function TInternalLinker.RunLinkScript(const outputname:TCmdStr):boolean;
  1059. label
  1060. myexit;
  1061. var
  1062. bsssize : aword;
  1063. bsssec : TExeSection;
  1064. dbgname : TCmdStr;
  1065. begin
  1066. result:=false;
  1067. Message1(exec_i_linking,outputname);
  1068. FlushOutput;
  1069. { TODO: Load custom linker script}
  1070. DefaultLinkScript;
  1071. exeoutput:=CExeOutput.Create;
  1072. if (cs_link_map in current_settings.globalswitches) then
  1073. exemap:=texemap.create(current_module.mapfilename^);
  1074. PrintLinkerScript;
  1075. { Check that syntax is OK }
  1076. ParseScript_Handle;
  1077. { Load .o files and resolve symbols }
  1078. ParseScript_Load;
  1079. exeoutput.ResolveSymbols(StaticLibraryList);
  1080. { Generate symbols and code to do the importing }
  1081. exeoutput.GenerateLibraryImports(ImportLibraryList);
  1082. { Fill external symbols data }
  1083. exeoutput.FixupSymbols;
  1084. if ErrorCount>0 then
  1085. goto myexit;
  1086. { parse linker options specific for output format }
  1087. exeoutput.ParseScript (linkscript);
  1088. { Create .exe sections and add .o sections }
  1089. ParseScript_Order;
  1090. exeoutput.RemoveUnreferencedSections;
  1091. { if UseStabs then, this would remove
  1092. STABS for empty linker scripts }
  1093. exeoutput.MergeStabs;
  1094. exeoutput.RemoveEmptySections;
  1095. if ErrorCount>0 then
  1096. goto myexit;
  1097. { Calc positions in mem }
  1098. ParseScript_MemPos;
  1099. exeoutput.FixupRelocations;
  1100. exeoutput.PrintMemoryMap;
  1101. if ErrorCount>0 then
  1102. goto myexit;
  1103. if cs_link_separate_dbg_file in current_settings.globalswitches then
  1104. begin
  1105. { create debuginfo, which is an executable without data on disk }
  1106. dbgname:=ChangeFileExt(outputname,'.dbg');
  1107. exeoutput.ExeWriteMode:=ewm_dbgonly;
  1108. ParseScript_DataPos;
  1109. exeoutput.WriteExeFile(dbgname);
  1110. { create executable with link to just created debuginfo file }
  1111. exeoutput.ExeWriteMode:=ewm_exeonly;
  1112. exeoutput.RemoveDebugInfo;
  1113. exeoutput.GenerateDebugLink(ExtractFileName(dbgname),GetFileCRC(dbgname));
  1114. ParseScript_MemPos;
  1115. ParseScript_DataPos;
  1116. exeoutput.WriteExeFile(outputname);
  1117. end
  1118. else
  1119. begin
  1120. exeoutput.ExeWriteMode:=ewm_exefull;
  1121. ParseScript_DataPos;
  1122. exeoutput.WriteExeFile(outputname);
  1123. end;
  1124. { Post check that everything was handled }
  1125. ParseScript_PostCheck;
  1126. { TODO: fixed section names}
  1127. status.codesize:=exeoutput.findexesection('.text').size;
  1128. status.datasize:=exeoutput.findexesection('.data').size;
  1129. bsssec:=exeoutput.findexesection('.bss');
  1130. if assigned(bsssec) then
  1131. bsssize:=bsssec.size
  1132. else
  1133. bsssize:=0;
  1134. { Executable info }
  1135. Message1(execinfo_x_codesize,tostr(status.codesize));
  1136. Message1(execinfo_x_initdatasize,tostr(status.datasize));
  1137. Message1(execinfo_x_uninitdatasize,tostr(bsssize));
  1138. Message1(execinfo_x_stackreserve,tostr(stacksize));
  1139. myexit:
  1140. { close map }
  1141. if assigned(exemap) then
  1142. begin
  1143. exemap.free;
  1144. exemap:=nil;
  1145. end;
  1146. { close exe }
  1147. exeoutput.free;
  1148. exeoutput:=nil;
  1149. result:=true;
  1150. end;
  1151. function TInternalLinker.MakeExecutable:boolean;
  1152. begin
  1153. IsSharedLibrary:=false;
  1154. result:=RunLinkScript(current_module.exefilename^);
  1155. end;
  1156. function TInternalLinker.MakeSharedLibrary:boolean;
  1157. begin
  1158. IsSharedLibrary:=true;
  1159. result:=RunLinkScript(current_module.sharedlibfilename^);
  1160. end;
  1161. {*****************************************************************************
  1162. Init/Done
  1163. *****************************************************************************}
  1164. procedure InitLinker;
  1165. var
  1166. lk : TlinkerClass;
  1167. begin
  1168. if (cs_link_extern in current_settings.globalswitches) and
  1169. assigned(target_info.linkextern) then
  1170. begin
  1171. lk:=TlinkerClass(target_info.linkextern);
  1172. linker:=lk.Create;
  1173. end
  1174. else
  1175. if assigned(target_info.link) then
  1176. begin
  1177. lk:=TLinkerClass(target_info.link);
  1178. linker:=lk.Create;
  1179. end
  1180. else
  1181. linker:=Tlinker.Create;
  1182. end;
  1183. procedure DoneLinker;
  1184. begin
  1185. if assigned(linker) then
  1186. Linker.Free;
  1187. end;
  1188. {*****************************************************************************
  1189. Initialize
  1190. *****************************************************************************}
  1191. const
  1192. ar_gnu_ar_info : tarinfo =
  1193. (
  1194. id : ar_gnu_ar;
  1195. arcmd : 'ar qS $LIB $FILES';
  1196. arfinishcmd : 'ar s $LIB'
  1197. );
  1198. ar_gnu_ar_scripted_info : tarinfo =
  1199. (
  1200. id : ar_gnu_ar_scripted;
  1201. arcmd : 'ar -M < $SCRIPT';
  1202. arfinishcmd : ''
  1203. );
  1204. ar_gnu_gar_info : tarinfo =
  1205. ( id : ar_gnu_gar;
  1206. arcmd : 'gar qS $LIB $FILES';
  1207. arfinishcmd : 'gar s $LIB'
  1208. );
  1209. initialization
  1210. RegisterAr(ar_gnu_ar_info);
  1211. RegisterAr(ar_gnu_ar_scripted_info);
  1212. RegisterAr(ar_gnu_gar_info);
  1213. end.