link.pas 46 KB

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