link.pas 46 KB

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