link.pas 45 KB

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