link.pas 47 KB

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