t_gba.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. {
  2. This unit implements support import,export,link routines
  3. for the (arm) GameBoy Advance target
  4. Copyright (c) 2001-2002 by Peter Vreman
  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 t_gba;
  19. {$i fpcdefs.inc}
  20. interface
  21. implementation
  22. uses
  23. link,
  24. cutils,cclasses,
  25. globtype,globals,systems,verbose,script,fmodule,i_gba;
  26. type
  27. TlinkerGBA=class(texternallinker)
  28. private
  29. Function WriteResponseFile: Boolean;
  30. public
  31. constructor Create; override;
  32. procedure SetDefaultInfo; override;
  33. function MakeExecutable:boolean; override;
  34. end;
  35. {*****************************************************************************
  36. TLINKERGBA
  37. *****************************************************************************}
  38. Constructor TLinkerGba.Create;
  39. begin
  40. Inherited Create;
  41. SharedLibFiles.doubles:=true;
  42. StaticLibFiles.doubles:=true;
  43. end;
  44. procedure TLinkerGba.SetDefaultInfo;
  45. begin
  46. with Info do
  47. begin
  48. ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
  49. end;
  50. end;
  51. Function TLinkerGba.WriteResponseFile: Boolean;
  52. Var
  53. linkres : TLinkRes;
  54. i : longint;
  55. HPath : TStringListItem;
  56. s : string;
  57. linklibc : boolean;
  58. begin
  59. WriteResponseFile:=False;
  60. { Open link.res file }
  61. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  62. { Write path to search libraries }
  63. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  64. while assigned(HPath) do
  65. begin
  66. s:=HPath.Str;
  67. if (cs_link_on_target in aktglobalswitches) then
  68. s:=ScriptFixFileName(s);
  69. LinkRes.Add('-L'+s);
  70. HPath:=TStringListItem(HPath.Next);
  71. end;
  72. HPath:=TStringListItem(LibrarySearchPath.First);
  73. while assigned(HPath) do
  74. begin
  75. s:=HPath.Str;
  76. if s<>'' then
  77. LinkRes.Add('SEARCH_DIR('+(maybequoted(s))+')');
  78. HPath:=TStringListItem(HPath.Next);
  79. end;
  80. LinkRes.Add('INPUT (');
  81. { add objectfiles, start with prt0 always }
  82. s:=FindObjectFile('prt0','',false);
  83. LinkRes.AddFileName(s);
  84. while not ObjectFiles.Empty do
  85. begin
  86. s:=ObjectFiles.GetFirst;
  87. if s<>'' then
  88. begin
  89. { vlink doesn't use SEARCH_DIR for object files }
  90. if not(cs_link_on_target in aktglobalswitches) then
  91. s:=FindObjectFile(s,'',false);
  92. LinkRes.AddFileName((maybequoted(s)));
  93. end;
  94. end;
  95. { Write staticlibraries }
  96. if not StaticLibFiles.Empty then
  97. begin
  98. { vlink doesn't need, and doesn't support GROUP }
  99. if (cs_link_on_target in aktglobalswitches) then
  100. begin
  101. LinkRes.Add(')');
  102. LinkRes.Add('GROUP(');
  103. end;
  104. while not StaticLibFiles.Empty do
  105. begin
  106. S:=StaticLibFiles.GetFirst;
  107. LinkRes.AddFileName((maybequoted(s)));
  108. end;
  109. end;
  110. if (cs_link_on_target in aktglobalswitches) then
  111. begin
  112. LinkRes.Add(')');
  113. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  114. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  115. linklibc:=false;
  116. while not SharedLibFiles.Empty do
  117. begin
  118. S:=SharedLibFiles.GetFirst;
  119. if s<>'c' then
  120. begin
  121. i:=Pos(target_info.sharedlibext,S);
  122. if i>0 then
  123. Delete(S,i,255);
  124. LinkRes.Add('-l'+s);
  125. end
  126. else
  127. begin
  128. LinkRes.Add('-l'+s);
  129. linklibc:=true;
  130. end;
  131. end;
  132. { be sure that libc&libgcc is the last lib }
  133. if linklibc then
  134. begin
  135. LinkRes.Add('-lc');
  136. LinkRes.Add('-lgcc');
  137. end;
  138. end
  139. else
  140. begin
  141. while not SharedLibFiles.Empty do
  142. begin
  143. S:=SharedLibFiles.GetFirst;
  144. LinkRes.Add('lib'+s+target_info.staticlibext);
  145. end;
  146. LinkRes.Add(')');
  147. end;
  148. with linkres do
  149. begin
  150. add('/* Linker Script Original v1.3 by Jeff Frohwein */');
  151. add('/* v1.0 - Original release */');
  152. add('/* v1.1 - Added proper .data section support */');
  153. add('/* v1.2 - Added support for c++ & iwram overlays */');
  154. add('/* - Major contributions by Jason Wilkins. */');
  155. add('/* v1.3 - .ewram section now can be used when */');
  156. add('/* compiling for MULTIBOOT mode. This fixes */');
  157. add('/* malloc() in DevKitAdvance which depends */');
  158. add('/* on __eheap_start instead of end to define*/');
  159. add('/* the starting location of heap space. */');
  160. add('/* External global variable __gba_iwram_heap*/');
  161. add('/* support added to allow labels end, _end, */');
  162. add('/* & __end__ to point to end of iwram or */');
  163. add('/* the end of ewram. */');
  164. add('/* Additions by WinterMute */');
  165. add('/* v1.4 - .sbss section added for unitialised */');
  166. add('/* data in ewram */');
  167. add('/* v1.5 - padding section added to stop EZF */');
  168. add('/* stripping important data */');
  169. add('');
  170. add('/* This file is released into the public domain */');
  171. add('/* for commercial or non-commercial use with no */');
  172. add('/* restrictions placed upon it. */');
  173. add('');
  174. add('/* NOTE!!!: This linker script defines the RAM & */');
  175. add('/* ROM start addresses. In order for it to work */');
  176. add('/* properly, remove -Ttext and -Tbss linker */');
  177. add('/* options from your makefile if they are */');
  178. add('/* present. */');
  179. add('');
  180. add('/* You can use the following to view section */');
  181. add('/* addresses in your .elf file: */');
  182. add('/* objdump -h file.elf */');
  183. add('/* Please note that empty sections may incorrectly*/');
  184. add('/* list the lma address as the vma address for */');
  185. add('/* some versions of objdump. */');
  186. add('');
  187. add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")');
  188. add('OUTPUT_ARCH(arm)');
  189. add('ENTRY(_start)');
  190. add('/* SEARCH_DIR(/bin/arm); */');
  191. add('');
  192. add('/* The linker script function "var1 += var2;" sometimes */');
  193. add('/* reports incorrect values in the *.map file but the */');
  194. add('/* actual value it calculates is usually, if not always, */');
  195. add('/* correct. If you leave out the ". = ALIGN(4);" at the */');
  196. add('/* end of each section then the return value of SIZEOF() */');
  197. add('/* is sometimes incorrect and "var1 += var2;" appears to */');
  198. add('/* not work as well. "var1 += var2" style functions are */');
  199. add('/* avoided below as a result. */');
  200. add('');
  201. add('MEMORY {');
  202. add('');
  203. add('rom : ORIGIN = 0x08000000, LENGTH = 32M');
  204. add('iwram : ORIGIN = 0x03000000, LENGTH = 32K');
  205. add('ewram : ORIGIN = 0x02000000, LENGTH = 256K');
  206. add('}');
  207. add('');
  208. add('/*');
  209. add('__text_start = 0x8000000;');
  210. add('__eheap_end = 0x2040000;');
  211. add('__iwram_start = 0x3000000;');
  212. add('__iwram_end = 0x3008000;');
  213. add('');
  214. add('__sp_irq = __iwram_end - 0x100;');
  215. add('__sp_usr = __sp_irq - 0x100;');
  216. add('*/');
  217. add('__text_start = ORIGIN(rom);');
  218. add('/* __eheap_end = ORIGIN(ewram) + 0x40000; */');
  219. add('__eheap_end = ORIGIN(ewram) + LENGTH(ewram);');
  220. add('__iwram_start = ORIGIN(iwram);');
  221. add('/* __iwram_end = ORIGIN(iwram) + 0x8000; */');
  222. add('__iwram_end = ORIGIN(iwram) + LENGTH(iwram); ');
  223. add('__sp_irq = __iwram_end - 0x100;');
  224. add('__sp_usr = __sp_irq - 0x100;');
  225. add('');
  226. add('');
  227. add('SECTIONS');
  228. add('{');
  229. add('. = __text_start;');
  230. add('.init :');
  231. add('{');
  232. add('KEEP (*(.init))');
  233. add('. = ALIGN(4);');
  234. add('} >rom =0xff');
  235. add('');
  236. add('.plt :');
  237. add('{');
  238. add('*(.plt)');
  239. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  240. add('} >rom');
  241. add('');
  242. add('.text : /* ALIGN (4): */');
  243. add('{');
  244. add('*(EXCLUDE_FILE (*.iwram*) .text)');
  245. add('*(.text.*)');
  246. add('*(.stub)');
  247. add('/* .gnu.warning sections are handled specially by elf32.em. */');
  248. add('*(.gnu.warning)');
  249. add('*(.gnu.linkonce.t*)');
  250. add('*(.glue_7)');
  251. add('*(.glue_7t)');
  252. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  253. add('} >rom = 0xff');
  254. add('');
  255. add('__text_end = .;');
  256. add('.fini :');
  257. add('{');
  258. add('KEEP (*(.fini))');
  259. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  260. add('} >rom =0');
  261. add('');
  262. add('.rodata :');
  263. add('{');
  264. add('*(.rodata)');
  265. add('*all.rodata*(*)');
  266. add('*(.roda)');
  267. add('*(.rodata.*)');
  268. add('*(.gnu.linkonce.r*)');
  269. add('SORT(CONSTRUCTORS)');
  270. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  271. add('} >rom = 0xff');
  272. add('');
  273. add('.ctors :');
  274. add('{');
  275. add('/* gcc uses crtbegin.o to find the start of the constructors, so');
  276. add('we make sure it is first. Because this is a wildcard, it');
  277. add('doesn''t matter if the user does not actually link against');
  278. add('crtbegin.o; the linker won''t look for a file to match a');
  279. add('wildcard. The wildcard also means that it doesn''t matter which');
  280. add('directory crtbegin.o is in. */');
  281. add('KEEP (*crtbegin.o(.ctors))');
  282. add('KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))');
  283. add('KEEP (*(SORT(.ctors.*)))');
  284. add('KEEP (*(.ctors))');
  285. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  286. add('} >rom = 0');
  287. add('');
  288. add('.dtors :');
  289. add('{');
  290. add('KEEP (*crtbegin.o(.dtors))');
  291. add('KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))');
  292. add('KEEP (*(SORT(.dtors.*)))');
  293. add('KEEP (*(.dtors))');
  294. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  295. add('} >rom = 0');
  296. add('');
  297. add('.jcr : { KEEP (*(.jcr)) } >rom ');
  298. add('');
  299. add('.eh_frame :');
  300. add('{');
  301. add('KEEP (*(.eh_frame))');
  302. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  303. add('} >rom = 0');
  304. add('');
  305. add('.gcc_except_table :');
  306. add('{');
  307. add('*(.gcc_except_table)');
  308. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  309. add('} >rom = 0');
  310. add('');
  311. add('__iwram_lma = .;');
  312. add('');
  313. add('.iwram __iwram_start : AT (__iwram_lma)');
  314. add('{');
  315. add('__iwram_start = ABSOLUTE(.) ;');
  316. add('*(.iwram)');
  317. add('*iwram.*(.text)');
  318. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  319. add('} >iwram = 0xff');
  320. add('');
  321. add('__data_lma = __iwram_lma + SIZEOF(.iwram) ;');
  322. add('__iwram_end = . ;');
  323. add('');
  324. add('.bss ALIGN(4) :');
  325. add('{');
  326. add('__bss_start = ABSOLUTE(.);');
  327. add('__bss_start__ = ABSOLUTE(.);');
  328. add('*(.dynbss)');
  329. add('*(.gnu.linkonce.b*)');
  330. add('*(.bss*)');
  331. add('*(COMMON)');
  332. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  333. add('} >iwram');
  334. add('');
  335. add('__bss_end = . ;');
  336. add('__bss_end__ = . ;');
  337. add('');
  338. add('.data ALIGN(4) : AT (__data_lma)');
  339. add('{');
  340. add('__data_start = ABSOLUTE(.);');
  341. add('*(.data)');
  342. add('*(.data.*)');
  343. add('*(.gnu.linkonce.d*)');
  344. add('CONSTRUCTORS');
  345. add('. = ALIGN(4);');
  346. add('} >iwram = 0xff');
  347. add('');
  348. add('__iwram_overlay_lma = __data_lma + SIZEOF(.data);');
  349. add('');
  350. add('__data_end = .;');
  351. add('__iwram_overlay_start = . ;');
  352. add('');
  353. add('OVERLAY ALIGN(4) : NOCROSSREFS AT (__iwram_overlay_lma)');
  354. add('{');
  355. add('.iwram0 { *(.iwram0) . = ALIGN(4);}');
  356. add('.iwram1 { *(.iwram1) . = ALIGN(4);}');
  357. add('.iwram2 { *(.iwram2) . = ALIGN(4);}');
  358. add('.iwram3 { *(.iwram3) . = ALIGN(4);}');
  359. add('.iwram4 { *(.iwram4) . = ALIGN(4);}');
  360. add('.iwram5 { *(.iwram5) . = ALIGN(4);}');
  361. add('.iwram6 { *(.iwram6) . = ALIGN(4);}');
  362. add('.iwram7 { *(.iwram7) . = ALIGN(4);}');
  363. add('.iwram8 { *(.iwram8) . = ALIGN(4);}');
  364. add('.iwram9 { *(.iwram9) . = ALIGN(4);}');
  365. add('}>iwram = 0xff');
  366. add('');
  367. add('__ewram_lma = LOADADDR(.iwram0) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9);');
  368. add('');
  369. add('__iwram_overlay_end = . ;');
  370. add('__iheap_start = . ;');
  371. add('');
  372. add('__ewram_start = 0x2000000;');
  373. add('.ewram __ewram_start : AT (__ewram_lma)');
  374. add('{');
  375. add('*(.ewram)');
  376. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  377. add('}>ewram = 0xff');
  378. add('');
  379. add('__ewram_overlay_lma = __ewram_lma + SIZEOF(.ewram);');
  380. add('');
  381. add('.sbss ALIGN(4):');
  382. add('{');
  383. add('__sbss_start = ABSOLUTE(.);');
  384. add('*(.sbss)');
  385. add('. = ALIGN(4);');
  386. add('} >ewram');
  387. add(' ');
  388. add('__sbss_end = .;');
  389. add('');
  390. add('__ewram_end = . ;');
  391. add('__ewram_overlay_start = . ;');
  392. add('');
  393. add('OVERLAY ALIGN(4): NOCROSSREFS AT (__ewram_overlay_lma)');
  394. add('{');
  395. add('.ewram0 { *(.ewram0) . = ALIGN(4);}');
  396. add('.ewram1 { *(.ewram1) . = ALIGN(4);}');
  397. add('.ewram2 { *(.ewram2) . = ALIGN(4);}');
  398. add('.ewram3 { *(.ewram3) . = ALIGN(4);}');
  399. add('.ewram4 { *(.ewram4) . = ALIGN(4);}');
  400. add('.ewram5 { *(.ewram5) . = ALIGN(4);}');
  401. add('.ewram6 { *(.ewram6) . = ALIGN(4);}');
  402. add('.ewram7 { *(.ewram7) . = ALIGN(4);}');
  403. add('.ewram8 { *(.ewram8) . = ALIGN(4);}');
  404. add('.ewram9 { *(.ewram9) . = ALIGN(4);}');
  405. add('}>ewram = 0xff');
  406. add('');
  407. add('__pad_lma = LOADADDR(.ewram0) + SIZEOF(.ewram0)+SIZEOF(.ewram1)+SIZEOF(.ewram2)+SIZEOF(.ewram3)+SIZEOF(.ewram4)+SIZEOF(.ewram5)+SIZEOF(.ewram6)+SIZEOF(.ewram7)+SIZEOF(.ewram8)+SIZEOF(.ewram9);');
  408. add('');
  409. add('/* EZF Advance strips trailing 0xff bytes, add a pad section so nothing important is removed */');
  410. add('.pad ALIGN(4) : AT (__pad_lma)');
  411. add('{');
  412. add('LONG(0x52416b64)');
  413. add('LONG(0x4d)');
  414. add('. = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
  415. add('} = 0xff');
  416. add('');
  417. add('__ewram_overlay_end = . ;');
  418. add('__eheap_start = . ;');
  419. add('');
  420. add('_end = .;');
  421. add('__end__ = _end ; /* v1.3 */');
  422. add('PROVIDE (end = _end); /* v1.3 */');
  423. add('');
  424. add('/* Stabs debugging sections. */');
  425. add('.stab 0 : { *(.stab) }');
  426. add('.stabstr 0 : { *(.stabstr) }');
  427. add('.stab.excl 0 : { *(.stab.excl) }');
  428. add('.stab.exclstr 0 : { *(.stab.exclstr) }');
  429. add('.stab.index 0 : { *(.stab.index) }');
  430. add('.stab.indexstr 0 : { *(.stab.indexstr) }');
  431. add('.comment 0 : { *(.comment) }');
  432. add('/* DWARF debug sections.');
  433. add('Symbols in the DWARF debugging sections are relative to the beginning');
  434. add('of the section so we begin them at 0. */');
  435. add('/* DWARF 1 */');
  436. add('.debug 0 : { *(.debug) }');
  437. add('.line 0 : { *(.line) }');
  438. add('/* GNU DWARF 1 extensions */');
  439. add('.debug_srcinfo 0 : { *(.debug_srcinfo) }');
  440. add('.debug_sfnames 0 : { *(.debug_sfnames) }');
  441. add('/* DWARF 1.1 and DWARF 2 */');
  442. add('.debug_aranges 0 : { *(.debug_aranges) }');
  443. add('.debug_pubnames 0 : { *(.debug_pubnames) }');
  444. add('/* DWARF 2 */');
  445. add('.debug_info 0 : { *(.debug_info) }');
  446. add('.debug_abbrev 0 : { *(.debug_abbrev) }');
  447. add('.debug_line 0 : { *(.debug_line) }');
  448. add('.debug_frame 0 : { *(.debug_frame) }');
  449. add('.debug_str 0 : { *(.debug_str) }');
  450. add('.debug_loc 0 : { *(.debug_loc) }');
  451. add('.debug_macinfo 0 : { *(.debug_macinfo) }');
  452. add('/* SGI/MIPS DWARF 2 extensions */');
  453. add('.debug_weaknames 0 : { *(.debug_weaknames) }');
  454. add('.debug_funcnames 0 : { *(.debug_funcnames) }');
  455. add('.debug_typenames 0 : { *(.debug_typenames) }');
  456. add('.debug_varnames 0 : { *(.debug_varnames) }');
  457. add('.stack 0x80000 : { _stack = .; *(.stack) }');
  458. add('/* These must appear regardless of . */');
  459. add('}');
  460. end;
  461. { Write and Close response }
  462. linkres.writetodisk;
  463. linkres.free;
  464. WriteResponseFile:=True;
  465. end;
  466. function TLinkerGba.MakeExecutable:boolean;
  467. var
  468. binstr : string;
  469. cmdstr : TCmdStr;
  470. success : boolean;
  471. StaticStr,
  472. GCSectionsStr,
  473. DynLinkStr,
  474. StripStr: string;
  475. begin
  476. { for future use }
  477. StaticStr:='';
  478. StripStr:='';
  479. DynLinkStr:='';
  480. GCSectionsStr:='--gc-sections';
  481. //if not(cs_link_extern in aktglobalswitches) then
  482. if not(cs_link_nolink in aktglobalswitches) then
  483. Message1(exec_i_linking,current_module.exefilename^);
  484. { Write used files and libraries }
  485. WriteResponseFile();
  486. { Call linker }
  487. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  488. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  489. if not(cs_link_on_target in aktglobalswitches) then
  490. begin
  491. Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ForceExtension(current_module.exefilename^,'.elf')))));
  492. Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
  493. Replace(cmdstr,'$STATIC',StaticStr);
  494. Replace(cmdstr,'$STRIP',StripStr);
  495. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  496. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  497. end
  498. else
  499. begin
  500. Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(ForceExtension(current_module.exefilename^,'.elf'))));
  501. Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
  502. Replace(cmdstr,'$STATIC',StaticStr);
  503. Replace(cmdstr,'$STRIP',StripStr);
  504. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  505. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  506. end;
  507. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  508. { Remove ReponseFile }
  509. if (success) and not(cs_link_nolink in aktglobalswitches) then
  510. RemoveFile(outputexedir+Info.ResName);
  511. { Post process }
  512. if success then
  513. begin
  514. success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
  515. ForceExtension(current_module.exefilename^,'.elf')+' '+
  516. current_module.exefilename^,true,false);
  517. end;
  518. MakeExecutable:=success; { otherwise a recursive call to link method }
  519. end;
  520. {*****************************************************************************
  521. Initialize
  522. *****************************************************************************}
  523. initialization
  524. RegisterExternalLinker(system_arm_gba_info,TLinkerGba);
  525. RegisterTarget(system_arm_gba_info);
  526. end.