link.pas 45 KB

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