1 {
2     This unit implements support import,export,link routines
3     for the (arm) Nintendo DS target
4 
5     Copyright (c) 2001-2002 by Peter Vreman
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21  ****************************************************************************
22 }
23 unit t_nds;
24 
25 {$i fpcdefs.inc}
26 
27 interface
28 
29 
30 implementation
31 
32     uses
33        aasmbase,
34        SysUtils,
35        cutils,cfileutl,cclasses,
36        globtype,globals,systems,verbose,cscript,fmodule,i_nds,link;
37 
38     type
39        TlinkerNDS=class(texternallinker)
40        private
WriteResponseFilenull41           Function  WriteResponseFile: Boolean;
42        public
43           constructor Create; override;
44           procedure SetDefaultInfo; override;
MakeExecutablenull45           function  MakeExecutable:boolean; override;
46        end;
47 
48 
49 
50 {*****************************************************************************
51                                   TLINKERNDS
52 *****************************************************************************}
53 
54 Constructor TLinkerNDS.Create;
55 begin
56   Inherited Create;
57   SharedLibFiles.doubles:=true;
58   StaticLibFiles.doubles:=true;
59   // set arm9 as default apptype
60   if (apptype <> app_arm9) or (apptype <> app_arm7) then
61     apptype:=app_arm9;
62 end;
63 
64 
65 procedure TLinkerNDS.SetDefaultInfo;
66 begin
67   with Info do
68    begin
69      ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
70    end;
71 end;
72 
73 
TLinkerNDS.WriteResponseFilenull74 Function TLinkerNDS.WriteResponseFile: Boolean;
75 Var
76   linkres  : TLinkRes;
77   i        : longint;
78   HPath    : TCmdStrListItem;
79   s,s1,s2  : TCmdStr;
80   prtobj,
81   cprtobj  : string[80];
82   linklibc,
83   linklibgcc : boolean;
84   found1,
85   found2   : boolean;
86 begin
87   WriteResponseFile:=False;
88   linklibc:=(SharedLibFiles.Find('c')<>nil);
89   linklibgcc:=(SharedLibFiles.Find('gcc')<>nil);
90 
91   prtobj:='';
92   cprtobj:='';
93   case apptype of
94     app_arm9:
95       begin
96         prtobj:='prt09';
97         cprtobj:='cprt09';
98       end;
99     app_arm7:
100       begin
101         prtobj:='prt07';
102         cprtobj:='cprt07';
103       end;
104   end;
105 
106   if (linklibc or linklibgcc) then
107     prtobj:=cprtobj;
108 
109 	{ Open link.res file }
110   LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
111 
112   { Write path to search libraries }
113   HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
114   while assigned(HPath) do
115    begin
116     s:=HPath.Str;
117     if (cs_link_on_target in current_settings.globalswitches) then
118      s:=ScriptFixFileName(s);
119     LinkRes.Add('-L'+s);
120     HPath:=TCmdStrListItem(HPath.Next);
121    end;
122   HPath:=TCmdStrListItem(LibrarySearchPath.First);
123   while assigned(HPath) do
124    begin
125     s:=HPath.Str;
126     if s<>'' then
127      LinkRes.Add('SEARCH_DIR("'+s+'")');
128     HPath:=TCmdStrListItem(HPath.Next);
129    end;
130 
131   LinkRes.Add('INPUT (');
132   { add objectfiles, start with prt0 always }
133   if prtobj<>'' then
134    s:=FindObjectFile(prtobj,'',false);
135   LinkRes.AddFileName(s);
136   { try to add crti and crtbegin if linking to C }
137   if linklibc then
138    begin
139      if librarysearchpath.FindFile('crti.o',false,s) then
140       LinkRes.AddFileName(s);
141    end;
142   if linklibgcc then
143    begin
144      if librarysearchpath.FindFile('crtbegin.o',false,s) then
145        LinkRes.AddFileName(s);
146    end;
147   while not ObjectFiles.Empty do
148    begin
149     s:=ObjectFiles.GetFirst;
150     if s<>'' then
151      begin
152       { vlink doesn't use SEARCH_DIR for object files }
153       if not(cs_link_on_target in current_settings.globalswitches) then
154        s:=FindObjectFile(s,'',false);
155       LinkRes.AddFileName((maybequoted(s)));
156      end;
157    end;
158 
159   { Write staticlibraries }
160   if not StaticLibFiles.Empty then
161    begin
162     { vlink doesn't need, and doesn't support GROUP }
163     if (cs_link_on_target in current_settings.globalswitches) then
164      begin
165       LinkRes.Add(')');
166       LinkRes.Add('GROUP(');
167      end;
168     while not StaticLibFiles.Empty do
169      begin
170       S:=StaticLibFiles.GetFirst;
171       LinkRes.AddFileName((maybequoted(s)));
172      end;
173    end;
174 
175   if (cs_link_on_target in current_settings.globalswitches) then
176    begin
177     LinkRes.Add(')');
178 
179     { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
180       here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
181     linklibc:=false;
182     linklibgcc:=false;
183     while not SharedLibFiles.Empty do
184      begin
185       S:=SharedLibFiles.GetFirst;
186       if s<>'c' then
187        begin
188         i:=Pos(target_info.sharedlibext,S);
189         if i>0 then
190          Delete(S,i,255);
191         LinkRes.Add('-l'+s);
192        end
193       else
194        begin
195         LinkRes.Add('-l'+s);
196         linklibc:=true;
197         linklibgcc:=true;
198        end;
199      end;
200     { be sure that libc&libgcc is the last lib }
201     if linklibgcc then
202      begin
203       LinkRes.Add('-lgcc');
204      end;
205     if linklibc then
206      begin
207       LinkRes.Add('-lc');
208      end;
209    end
210   else
211    begin
212     while not SharedLibFiles.Empty do
213      begin
214       S:=SharedLibFiles.GetFirst;
215       LinkRes.Add('lib'+s+target_info.staticlibext);
216      end;
217     LinkRes.Add(')');
218    end;
219 
220   { objects which must be at the end }
221   if linklibgcc then
222    begin
223      found1:=librarysearchpath.FindFile('crtend.o',false,s1);
224      if found1 then
225       begin
226         LinkRes.Add('INPUT(');
227         if found1 then
228          LinkRes.AddFileName(s1);
229         LinkRes.Add(')');
230       end;
231    end;
232   if linklibc then
233    begin
234      found2:=librarysearchpath.FindFile('crtn.o',false,s2);
235      if found2 then
236       begin
237         LinkRes.Add('INPUT(');
238         if found2 then
239          LinkRes.AddFileName(s2);
240         LinkRes.Add(')');
241       end;
242    end;
243 
244   with linkres do
245     begin
246       if apptype=app_arm9 then //ARM9
247       begin
248         add('MEMORY {');
249         add('	rom	: ORIGIN = 0x08000000, LENGTH = 32M');
250         add('	ewram	: ORIGIN = 0x02000000, LENGTH = 4M - 4k');
251         add('	dtcm	: ORIGIN = 0x0b000000, LENGTH = 16K');
252         add('	vectors	: ORIGIN = 0x01000000, LENGTH = 256');
253         add('	itcm	: ORIGIN = 0x01000100, LENGTH = 32K - 256');
254         add('}');
255         add('');
256         add('OUTPUT_ARCH(arm)');
257         add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")');
258         add('ENTRY(_start)');
259         add('');
260         add('__vectors_start	=	ORIGIN(vectors);');
261         add('__itcm_start	=	ORIGIN(itcm);');
262         add('__ewram_end	=	ORIGIN(ewram) + LENGTH(ewram);');
263         add('__eheap_end	=	ORIGIN(ewram) + LENGTH(ewram);');
264         add('__dtcm_start	=	ORIGIN(dtcm);');
265         add('__dtcm_top	=	ORIGIN(dtcm) + LENGTH(dtcm);');
266         add('__irq_flags	=	__dtcm_top - 0x08;');
267         add('__irq_vector	=	__dtcm_top - 0x04;');
268         add('');
269         add('__sp_svc	=	__dtcm_top - 0x100;');
270         add('__sp_irq	=	__sp_svc - 0x100;');
271         add('__sp_usr	=	__sp_irq - 0x100;');
272         add('');
273         add('SECTIONS');
274         add('{');
275         add('	.init	:');
276         add('	{');
277         add('		__text_start = . ;');
278         add('		KEEP (*(.init))');
279         add('		. = ALIGN(4);  /* REQUIRED. LD is flaky without it. */');
280         add('	} >ewram = 0xff');
281         add('');
282         add('	.plt : { *(.plt) } >ewram = 0xff');
283         add('');
284         add('	.text :   /* ALIGN (4): */');
285         add('	{');
286         add('		*(EXCLUDE_FILE (*.itcm*) .text)');
287         add('');
288         add('		*(.text.*)');
289         add('		*(.stub)');
290         add('		/* .gnu.warning sections are handled specially by elf32.em.  */');
291         add('		*(.gnu.warning)');
292         add('		*(.gnu.linkonce.t*)');
293         add('		*(.glue_7)');
294         add('		*(.glue_7t)');
295         add('		. = ALIGN(4);  /* REQUIRED. LD is flaky without it. */');
296         add('	} >ewram = 0xff');
297         add('');
298         add('	.fini           :');
299         add('	{');
300         add('		KEEP (*(.fini))');
301         add('	} >ewram =0xff');
302         add('');
303         add('	__text_end = . ;');
304         add('');
305         add('	.rodata :');
306         add('	{');
307         add('		*(.rodata)');
308         add('		*all.rodata*(*)');
309         add('		*(.roda)');
310         add('		*(.rodata.*)');
311         add('		*(.gnu.linkonce.r*)');
312         add('		SORT(CONSTRUCTORS)');
313         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
314         add('	} >ewram = 0xff');
315         add('');
316         add('	.ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ewram');
317         add(' 	__exidx_start = .;');
318         add('	ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ewram');
319         add(' 	__exidx_end = .;');
320         add('');
321         add('	/*	Ensure the __preinit_array_start label is properly aligned.  We');
322         add('		could instead move the label definition inside the section, but');
323         add('		the linker would then create the section even if it turns out to');
324         add('		be empty, which isn''t pretty.  */');
325         add('');
326         add('	. = ALIGN(32 / 8);');
327         add('');
328         add('	PROVIDE (__preinit_array_start = .);');
329         add('	.preinit_array     : { KEEP (*(.preinit_array)) } >ewram = 0xff');
330         add('	PROVIDE (__preinit_array_end = .);');
331         add('	PROVIDE (__init_array_start = .);');
332         add('	.init_array     :');
333         add('	{');
334         add('		KEEP (*(SORT(.init_array.*)))');
335         add('		KEEP (*(.init_array))');
336         add('	} >ewram = 0xff');
337         add('	PROVIDE (__init_array_end = .);');
338         add('	PROVIDE (__fini_array_start = .);');
339         add('	.fini_array     :');
340         add('	{');
341         add('		KEEP (*(.fini_array))');
342         add('		KEEP (*(SORT(.fini_array.*)))');
343         add('	} >ewram = 0xff');
344         add('');
345         add('	PROVIDE (__fini_array_end = .);');
346         add('');
347         add('	.ctors :');
348         add('	{');
349         add('	/*	gcc uses crtbegin.o to find the start of the constructors, so');
350         add('		we make sure it is first.  Because this is a wildcard, it');
351         add('		doesn''t matter if the user does not actually link against');
352         add('		crtbegin.o; the linker won''t look for a file to match a');
353         add('		wildcard.  The wildcard also means that it doesn''t matter which');
354         add('		directory crtbegin.o is in.  */');
355         add('		KEEP (*crtbegin.o(.ctors))');
356         add('		KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))');
357         add('		KEEP (*(SORT(.ctors.*)))');
358         add('		KEEP (*(.ctors))');
359         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
360         add('	} >ewram = 0xff');
361         add('');
362         add('	.dtors :');
363         add('	{');
364         add('		KEEP (*crtbegin.o(.dtors))');
365         add('		KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))');
366         add('		KEEP (*(SORT(.dtors.*)))');
367         add('		KEEP (*(.dtors))');
368         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
369         add('	} >ewram = 0xff');
370         add('');
371         add('	.eh_frame :');
372         add('	{');
373         add('		KEEP (*(.eh_frame))');
374         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
375         add('	} >ewram = 0xff');
376         add('');
377         add('	.gcc_except_table :');
378         add('	{');
379         add('		*(.gcc_except_table)');
380         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
381         add('	} >ewram = 0xff');
382         add('	.jcr            : { KEEP (*(.jcr)) } >ewram = 0');
383         add('	.got            : { *(.got.plt) *(.got) *(.rel.got) } >ewram = 0');
384         add('');
385         add('	.ewram ALIGN(4) : ');
386         add('	{');
387         add('		__ewram_start = ABSOLUTE(.) ;');
388         add('		*(.ewram)');
389         add('		*ewram.*(.text)');
390         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
391         add('	} >ewram = 0xff');
392         add('');
393         add('');
394         add('	.data ALIGN(4) :');
395         add('	{');
396         add('		__data_start = ABSOLUTE(.);');
397         add('		*(.data)');
398         add('		*(.data.*)');
399         add('		*(.gnu.linkonce.d*)');
400         add('		CONSTRUCTORS');
401         add('		. = ALIGN(4);');
402         add('		__data_end = ABSOLUTE(.) ;');
403         add('	} >ewram = 0xff');
404         add('');
405         add('');
406         add('	__dtcm_lma = . ;');
407         add('	__bss_vma = . ;');
408         add('');
409         add('	.dtcm __dtcm_start : AT (__dtcm_lma)');
410         add('	{');
411         add('		*(.dtcm)');
412         add('		*(.dtcm.*)');
413         add('		. = ALIGN(4);');
414         add('		__dtcm_end = ABSOLUTE(.);');
415         add('	} >dtcm  = 0xff');
416         add('');
417         add('');
418         add('	__itcm_lma = __dtcm_lma + SIZEOF(.dtcm);');
419         add('');
420         add('	.itcm __itcm_start : AT (__itcm_lma)');
421         add('	{');
422         add('		*(.itcm)');
423         add('		*itcm.*(.text)');
424         add('		. = ALIGN(4);');
425         add('		__itcm_end = ABSOLUTE(.);');
426         add('	} >itcm = 0xff');
427         add('	');
428         add('	__vectors_lma = __itcm_lma + SIZEOF(.itcm);');
429         add('');
430         add('	.vectors __vectors_start : AT (__vectors_lma)');
431         add('	{');
432         add('		*(.vectors)');
433         add('		*vectors.*(.text)');
434         add('		. = ALIGN(4);');
435         add('		__vectors_end = ABSOLUTE(.);');
436         add('	} >vectors = 0xff');
437         add('	');
438         add('	.sbss __dtcm_end (NOLOAD): ');
439         add('	{');
440         add('		__sbss_start = ABSOLUTE(.);');
441         add('		__sbss_start__ = ABSOLUTE(.);');
442         add('		*(.sbss)');
443         add('		. = ALIGN(4);    /* REQUIRED. LD is flaky without it. */');
444         add('		__sbss_end = ABSOLUTE(.);');
445         add('	} >dtcm ');
446         add('');
447         add('	.bss __bss_vma (NOLOAD): ');
448         add('	{');
449         add('		__bss_start = ABSOLUTE(.);');
450         add('		__bss_start__ = ABSOLUTE(.);');
451         add('		*(.dynbss)');
452         add('		*(.gnu.linkonce.b*)');
453         add('		*(.bss*)');
454         add('		*(COMMON)');
455         add('		. = ALIGN(4);    /* REQUIRED. LD is flaky without it. */');
456         add('		__bss_end__ = ABSOLUTE(.) ;');
457         add('		__end__ = ABSOLUTE(.) ;');
458         add('	} AT>ewram ');
459         add('');
460         add('');
461         add('');
462         add('	/* Stabs debugging sections.  */');
463         add('	.stab 0 : { *(.stab) }');
464         add('	.stabstr 0 : { *(.stabstr) }');
465         add('	.stab.excl 0 : { *(.stab.excl) }');
466         add('	.stab.exclstr 0 : { *(.stab.exclstr) }');
467         add('	.stab.index 0 : { *(.stab.index) }');
468         add('	.stab.indexstr 0 : { *(.stab.indexstr) }');
469         add('	.comment 0 : { *(.comment) }');
470         add('	/*	DWARF debug sections.');
471         add('		Symbols in the DWARF debugging sections are relative to the beginning');
472         add('		of the section so we begin them at 0.  */');
473         add('	/* DWARF 1 */');
474         add('	.debug          0 : { *(.debug) }');
475         add('	.line           0 : { *(.line) }');
476         add('	/* GNU DWARF 1 extensions */');
477         add('	.debug_srcinfo  0 : { *(.debug_srcinfo) }');
478         add('	.debug_sfnames  0 : { *(.debug_sfnames) }');
479         add('	/* DWARF 1.1 and DWARF 2 */');
480         add('	.debug_aranges  0 : { *(.debug_aranges) }');
481         add('	.debug_pubnames 0 : { *(.debug_pubnames) }');
482         add('	/* DWARF 2 */');
483         add('	.debug_info     0 : { *(.debug_info) }');
484         add('	.debug_abbrev   0 : { *(.debug_abbrev) }');
485         add('	.debug_line     0 : { *(.debug_line) }');
486         add('	.debug_frame    0 : { *(.debug_frame) }');
487         add('	.debug_str      0 : { *(.debug_str) }');
488         add('	.debug_loc      0 : { *(.debug_loc) }');
489         add('	.debug_macinfo  0 : { *(.debug_macinfo) }');
490         add('	/* SGI/MIPS DWARF 2 extensions */');
491         add('	.debug_weaknames 0 : { *(.debug_weaknames) }');
492         add('	.debug_funcnames 0 : { *(.debug_funcnames) }');
493         add('	.debug_typenames 0 : { *(.debug_typenames) }');
494         add('	.debug_varnames  0 : { *(.debug_varnames) }');
495         add('	.stack 0x80000 : { _stack = .; *(.stack) }');
496         add('	/* These must appear regardless of  .  */');
497         add('}');
498         add('');
499       end;
500       if apptype=app_arm7 then
501       begin
502         add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")');
503         add('OUTPUT_ARCH(arm)');
504         add('ENTRY(_start)');
505         add('');
506         add('MEMORY {');
507         add('');
508         add('	rom	: ORIGIN = 0x08000000, LENGTH = 32M');
509         add('	iwram	: ORIGIN = 0x037f8000, LENGTH = 96K	');
510         add('}');
511         add('');
512         add('__iwram_start	=	ORIGIN(iwram);');
513         add('__iwram_top	=	ORIGIN(iwram)+ LENGTH(iwram);');
514         add('');
515         add('__sp_irq	=	__iwram_top - 0x100;');
516         add('__sp_svc	=	__sp_irq - 0x100;');
517         add('__sp_usr	=	__sp_svc - 0x100;');
518         add('');
519         add('__irq_flags	=	0x04000000 - 8;');
520         add('__irq_flagsaux	=	0x04000000 - 0x40;');
521         add('__irq_vector	=	0x04000000 - 4;');
522         add('');
523         add('SECTIONS');
524         add('{');
525         add('	.init	:');
526         add('	{');
527         add('		__text_start = . ;');
528         add('		KEEP (*(.init))');
529         add('		. = ALIGN(4);  /* REQUIRED. LD is flaky without it. */');
530         add('		} >iwram = 0xff');
531         add('	.plt : { *(.plt) } >iwram = 0xff');
532         add('');
533         add('	.text :   /* ALIGN (4): */');
534         add('	{');
535         add('		*(.text .stub .text.* .gnu.linkonce.t.*)');
536         add('		KEEP (*(.text.*personality*))');
537         add('		/* .gnu.warning sections are handled specially by elf32.em.  */');
538         add('		*(.gnu.warning)');
539         add('		*(.glue_7t) *(.glue_7) *(.vfp11_veneer)');
540         add('		. = ALIGN(4);  /* REQUIRED. LD is flaky without it. */');
541         add('	} >iwram = 0xff');
542         add('');
543         add('	.fini           :');
544         add('	{');
545         add('		KEEP (*(.fini))');
546         add('	} >iwram =0xff');
547         add('');
548         add('	__text_end = . ;');
549         add('');
550         add('	.rodata :');
551         add('	{');
552         add('		*(.rodata)');
553         add('		*all.rodata*(*)');
554         add('		*(.roda)');
555         add('		*(.rodata.*)');
556         add('		*(.gnu.linkonce.r*)');
557         add('		SORT(CONSTRUCTORS)');
558         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
559         add('	} >iwram = 0xff');
560         add('');
561         add('	.ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >iwram');
562         add('	__exidx_start = .;');
563         add('	.ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >iwram');
564         add('	__exidx_end = .;');
565         add('');
566         add('/* Ensure the __preinit_array_start label is properly aligned.  We');
567         add('   could instead move the label definition inside the section, but');
568         add('   the linker would then create the section even if it turns out to');
569         add('   be empty, which isn''t pretty.  */');
570         add('	. = ALIGN(32 / 8);');
571         add('	PROVIDE (__preinit_array_start = .);');
572         add('	.preinit_array     : { KEEP (*(.preinit_array)) } >iwram = 0xff');
573         add('	PROVIDE (__preinit_array_end = .);');
574         add('	PROVIDE (__init_array_start = .);');
575         add('	.init_array     : { KEEP (*(.init_array)) } >iwram = 0xff');
576         add('	PROVIDE (__init_array_end = .);');
577         add('	PROVIDE (__fini_array_start = .);');
578         add('	.fini_array     : { KEEP (*(.fini_array)) } >iwram = 0xff');
579         add('	PROVIDE (__fini_array_end = .);');
580         add('');
581         add('	.ctors :');
582         add('	{');
583         add('	/* gcc uses crtbegin.o to find the start of the constructors, so');
584         add('		we make sure it is first.  Because this is a wildcard, it');
585         add('		doesn''t matter if the user does not actually link against');
586         add('		crtbegin.o; the linker won''t look for a file to match a');
587         add('		wildcard.  The wildcard also means that it doesn''t matter which');
588         add('		directory crtbegin.o is in.  */');
589         add('		KEEP (*crtbegin.o(.ctors))');
590         add('		KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))');
591         add('		KEEP (*(SORT(.ctors.*)))');
592         add('		KEEP (*(.ctors))');
593         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
594         add('	} >iwram = 0xff');
595         add('');
596         add('	.dtors :');
597         add('	{');
598         add('		KEEP (*crtbegin.o(.dtors))');
599         add('		KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))');
600         add('		KEEP (*(SORT(.dtors.*)))');
601         add('		KEEP (*(.dtors))');
602         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
603         add('	} >iwram = 0xff');
604         add('');
605         add('	.eh_frame :');
606         add('	{');
607         add('		KEEP (*(.eh_frame))');
608         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
609         add('	} >iwram = 0xff');
610         add('');
611         add('	.gcc_except_table :');
612         add('	{');
613         add('		*(.gcc_except_table)');
614         add('		. = ALIGN(4);   /* REQUIRED. LD is flaky without it. */');
615         add('	} >iwram = 0xff');
616         add('	.jcr            : { KEEP (*(.jcr)) } >iwram = 0');
617         add('	.got            : { *(.got.plt) *(.got) } >iwram = 0');
618         add('');
619         add('	.data ALIGN(4) : 	{');
620         add('		__data_start = ABSOLUTE(.);');
621         add('		*(.data)');
622         add('		*(.data.*)');
623         add('		*(.gnu.linkonce.d*)');
624         add('		CONSTRUCTORS');
625         add('		. = ALIGN(4);');
626         add('		__data_end = ABSOLUTE(.) ;');
627         add('	} >iwram = 0xff');
628         add('');
629         add('	.bss ALIGN(4) :');
630         add('	{');
631         add('		__bss_start = ABSOLUTE(.);');
632         add('		__bss_start__ = ABSOLUTE(.);');
633         add('		*(.dynbss)');
634         add('		*(.gnu.linkonce.b*)');
635         add('		*(.bss*)');
636         add('		*(COMMON)');
637         add('		. = ALIGN(4);    /* REQUIRED. LD is flaky without it. */');
638         add('		__bss_end__ = ABSOLUTE(.);');
639         add('		__end__ = ABSOLUTE(.);');
640         add('	} >iwram');
641         add('');
642         add('	/* Stabs debugging sections.  */');
643         add('	.stab 0 : { *(.stab) }');
644         add('	.stabstr 0 : { *(.stabstr) }');
645         add('	.stab.excl 0 : { *(.stab.excl) }');
646         add('	.stab.exclstr 0 : { *(.stab.exclstr) }');
647         add('	.stab.index 0 : { *(.stab.index) }');
648         add('	.stab.indexstr 0 : { *(.stab.indexstr) }');
649         add('	.comment 0 : { *(.comment) }');
650         add('	/*	DWARF debug sections.');
651         add('		Symbols in the DWARF debugging sections are relative to the beginning');
652         add('		of the section so we begin them at 0.  */');
653         add('	/* DWARF 1 */');
654         add('	.debug          0 : { *(.debug) }');
655         add('	.line           0 : { *(.line) }');
656         add('	/* GNU DWARF 1 extensions */');
657         add('	.debug_srcinfo  0 : { *(.debug_srcinfo) }');
658         add('	.debug_sfnames  0 : { *(.debug_sfnames) }');
659         add('	/* DWARF 1.1 and DWARF 2 */');
660         add('	.debug_aranges  0 : { *(.debug_aranges) }');
661         add('	.debug_pubnames 0 : { *(.debug_pubnames) }');
662         add('	/* DWARF 2 */');
663         add('	.debug_info     0 : { *(.debug_info) }');
664         add('	.debug_abbrev   0 : { *(.debug_abbrev) }');
665         add('	.debug_line     0 : { *(.debug_line) }');
666         add('	.debug_frame    0 : { *(.debug_frame) }');
667         add('	.debug_str      0 : { *(.debug_str) }');
668         add('	.debug_loc      0 : { *(.debug_loc) }');
669         add('	.debug_macinfo  0 : { *(.debug_macinfo) }');
670         add('	/* SGI/MIPS DWARF 2 extensions */');
671         add('	.debug_weaknames 0 : { *(.debug_weaknames) }');
672         add('	.debug_funcnames 0 : { *(.debug_funcnames) }');
673         add('	.debug_typenames 0 : { *(.debug_typenames) }');
674         add('	.debug_varnames  0 : { *(.debug_varnames) }');
675         add('	.stack 0x80000 : { _stack = .; *(.stack) }');
676         add('	/* These must appear regardless of  .  */');
677         add('}');
678       end;
679     end;
680 
681 { Write and Close response }
682   linkres.writetodisk;
683   linkres.free;
684 
685   WriteResponseFile:=True;
686 
687 end;
688 
689 
MakeExecutablenull690 function TLinkerNDS.MakeExecutable:boolean;
691 var
692   binstr,
693   cmdstr  : TCmdStr;
694   success : boolean;
695   StaticStr,
696   GCSectionsStr,
697   DynLinkStr,
698   MapStr,
699   StripStr: string;
700   preName: string;
701 begin
702   { for future use }
703   StaticStr:='';
704   StripStr:='';
705   MapStr:='';
706   DynLinkStr:='';
707   GCSectionsStr:='';
708   preName:='';
709   case apptype of
710    app_arm9: preName:='.nef';
711    app_arm7: preName:='.nlf';
712   end;
713 
714   if (cs_link_strip in current_settings.globalswitches) and
715      not(cs_link_separate_dbg_file in current_settings.globalswitches) then
716    StripStr:='-s';
717   if (cs_link_map in current_settings.globalswitches) then
718    StripStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
719   if create_smartlink_sections then
720    GCSectionsStr:='--gc-sections';
721   if not(cs_link_nolink in current_settings.globalswitches) then
722    Message1(exec_i_linking,current_module.exefilename);
723 
724 { Write used files and libraries }
725   WriteResponseFile();
726 
727 { Call linker }
728   SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
729   Replace(cmdstr,'$OPT',Info.ExtraOptions);
730 
731   Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,preName)))));
732   Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
733   Replace(cmdstr,'$STATIC',StaticStr);
734   Replace(cmdstr,'$STRIP',StripStr);
735   Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
736   Replace(cmdstr,'$MAP',MapStr);
737   Replace(cmdstr,'$DYNLINK',DynLinkStr);
738 
739   success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
740 
741 { Remove ReponseFile }
742   if (success) and not(cs_link_nolink in current_settings.globalswitches) then
743    DeleteFile(outputexedir+Info.ResName);
744 
745 { Post process }
746   if success then
747     begin
748       success:=DoExec(FindUtil(utilsprefix + 'objcopy'), '-O binary '+
749         ChangeFileExt(current_module.exefilename, preName) + ' ' +
750         ChangeFileExt(current_module.exefilename, preName+target_info.exeext),
751         true,false);
752     end;
753 
754   if success and (apptype=app_arm9) then
755     begin
756       success:=DoExec(FindUtil('ndstool'), '-c ' +
757         ChangeFileExt(current_module.exefilename, '.nds') + ' -9 ' +
758         ChangeFileExt(current_module.exefilename, preName+target_info.exeext),
759         true,false);
760     end;
761   MakeExecutable:=success;   { otherwise a recursive call to link method }
762 end;
763 
764 
765 {*****************************************************************************
766                                      Initialize
767 *****************************************************************************}
768 
769 initialization
770   RegisterLinker(ld_nds,TLinkerNDS);
771   RegisterTarget(system_arm_nds_info);
772 end.
773