PageRenderTime 31ms CodeModel.GetById 16ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/compiler/systems/t_embed.pas

https://github.com/slibre/freepascal
Pascal | 939 lines | 800 code | 63 blank | 76 comment | 46 complexity | f307ae7ffcc44cbf7e199f8b14219985 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, LGPL-3.0
  1{
  2    This unit implements support import,export,link routines
  3    for the (arm) GameBoy Advance 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}
 23unit t_embed;
 24
 25{$i fpcdefs.inc}
 26
 27interface
 28
 29
 30implementation
 31
 32    uses
 33       SysUtils,
 34       cutils,cfileutl,cclasses,
 35       globtype,globals,systems,verbose,comphook,script,fmodule,i_embed,link,
 36       cpuinfo;
 37
 38    type
 39       TlinkerEmbedded=class(texternallinker)
 40       private
 41          Function  WriteResponseFile: Boolean;
 42       public
 43          constructor Create; override;
 44          procedure SetDefaultInfo; override;
 45          function  MakeExecutable:boolean; override;
 46          function postprocessexecutable(const fn : string;isdll:boolean):boolean;
 47       end;
 48
 49
 50
 51{*****************************************************************************
 52                                  TlinkerEmbedded
 53*****************************************************************************}
 54
 55Constructor TlinkerEmbedded.Create;
 56begin
 57  Inherited Create;
 58  SharedLibFiles.doubles:=true;
 59  StaticLibFiles.doubles:=true;
 60end;
 61
 62
 63procedure TlinkerEmbedded.SetDefaultInfo;
 64begin
 65  with Info do
 66   begin
 67     ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
 68   end;
 69end;
 70
 71
 72Function TlinkerEmbedded.WriteResponseFile: Boolean;
 73Var
 74  linkres  : TLinkRes;
 75  i        : longint;
 76  HPath    : TCmdStrListItem;
 77  s,s1,s2  : TCmdStr;
 78  prtobj,
 79  cprtobj  : string[80];
 80  linklibc : boolean;
 81  found1,
 82  found2   : boolean;
 83{$ifdef ARM}
 84  LinkStr  : string;
 85{$endif}
 86begin
 87  WriteResponseFile:=False;
 88  linklibc:=(SharedLibFiles.Find('c')<>nil);
 89{$if defined(ARM) or defined(i386) or defined(AVR)}
 90  prtobj:='';
 91{$else}
 92  prtobj:='prt0';
 93{$endif}
 94  cprtobj:='cprt0';
 95  if linklibc then
 96    prtobj:=cprtobj;
 97
 98  { Open link.res file }
 99  LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
100
101  { Write path to search libraries }
102  HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
103  while assigned(HPath) do
104   begin
105    s:=HPath.Str;
106    if (cs_link_on_target in current_settings.globalswitches) then
107     s:=ScriptFixFileName(s);
108    LinkRes.Add('-L'+s);
109    HPath:=TCmdStrListItem(HPath.Next);
110   end;
111  HPath:=TCmdStrListItem(LibrarySearchPath.First);
112  while assigned(HPath) do
113   begin
114    s:=HPath.Str;
115    if s<>'' then
116     LinkRes.Add('SEARCH_DIR("'+s+'")');
117    HPath:=TCmdStrListItem(HPath.Next);
118   end;
119
120  LinkRes.Add('INPUT (');
121  { add objectfiles, start with prt0 always }
122  //s:=FindObjectFile('prt0','',false);
123  if prtobj<>'' then
124    begin
125      s:=FindObjectFile(prtobj,'',false);
126      LinkRes.AddFileName(s);
127    end;
128  { try to add crti and crtbegin if linking to C }
129  if linklibc then
130   begin
131     if librarysearchpath.FindFile('crtbegin.o',false,s) then
132      LinkRes.AddFileName(s);
133     if librarysearchpath.FindFile('crti.o',false,s) then
134      LinkRes.AddFileName(s);
135   end;
136
137  while not ObjectFiles.Empty do
138   begin
139    s:=ObjectFiles.GetFirst;
140    if s<>'' then
141     begin
142      { vlink doesn't use SEARCH_DIR for object files }
143      if not(cs_link_on_target in current_settings.globalswitches) then
144       s:=FindObjectFile(s,'',false);
145      LinkRes.AddFileName((maybequoted(s)));
146     end;
147   end;
148
149  { Write staticlibraries }
150  if not StaticLibFiles.Empty then
151   begin
152    { vlink doesn't need, and doesn't support GROUP }
153    if (cs_link_on_target in current_settings.globalswitches) then
154     begin
155      LinkRes.Add(')');
156      LinkRes.Add('GROUP(');
157     end;
158    while not StaticLibFiles.Empty do
159     begin
160      S:=StaticLibFiles.GetFirst;
161      LinkRes.AddFileName((maybequoted(s)));
162     end;
163   end;
164
165  if (cs_link_on_target in current_settings.globalswitches) then
166   begin
167    LinkRes.Add(')');
168
169    { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
170      here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
171    linklibc:=false;
172    while not SharedLibFiles.Empty do
173     begin
174      S:=SharedLibFiles.GetFirst;
175      if s<>'c' then
176       begin
177        i:=Pos(target_info.sharedlibext,S);
178        if i>0 then
179         Delete(S,i,255);
180        LinkRes.Add('-l'+s);
181       end
182      else
183       begin
184        LinkRes.Add('-l'+s);
185        linklibc:=true;
186       end;
187     end;
188    { be sure that libc&libgcc is the last lib }
189    if linklibc then
190     begin
191      LinkRes.Add('-lc');
192      LinkRes.Add('-lgcc');
193     end;
194   end
195  else
196   begin
197    while not SharedLibFiles.Empty do
198     begin
199      S:=SharedLibFiles.GetFirst;
200      LinkRes.Add('lib'+s+target_info.staticlibext);
201     end;
202    LinkRes.Add(')');
203   end;
204
205  { objects which must be at the end }
206  if linklibc then
207   begin
208     found1:=librarysearchpath.FindFile('crtend.o',false,s1);
209     found2:=librarysearchpath.FindFile('crtn.o',false,s2);
210     if found1 or found2 then
211      begin
212        LinkRes.Add('INPUT(');
213        if found1 then
214         LinkRes.AddFileName(s1);
215        if found2 then
216         LinkRes.AddFileName(s2);
217        LinkRes.Add(')');
218      end;
219   end;
220
221{$ifdef ARM}
222  case current_settings.controllertype of
223      ct_none:
224           begin
225           end;
226      ct_lpc2114,
227      ct_lpc2124,
228      ct_lpc2194,
229      ct_lpc1768,
230      ct_at91sam7s256,
231      ct_at91sam7se256,
232      ct_at91sam7x256,
233      ct_at91sam7xc256,
234
235      ct_stm32f100x4,
236      ct_stm32f100x6,
237      ct_stm32f100x8,
238      ct_stm32f100xB,
239      ct_stm32f100xC,
240      ct_stm32f100xD,
241      ct_stm32f100xE,
242      ct_stm32f101x4,
243      ct_stm32f101x6,
244      ct_stm32f101x8,
245      ct_stm32f101xB,
246      ct_stm32f101xC,
247      ct_stm32f101xD,
248      ct_stm32f101xE,
249      ct_stm32f101xF,
250      ct_stm32f101xG,
251      ct_stm32f102x4,
252      ct_stm32f102x6,
253      ct_stm32f102x8,
254      ct_stm32f102xB,
255      ct_stm32f103x4,
256      ct_stm32f103x6,
257      ct_stm32f103x8,
258      ct_stm32f103xB,
259      ct_stm32f103xC,
260      ct_stm32f103xD,
261      ct_stm32f103xE,
262      ct_stm32f103xF,
263      ct_stm32f103xG,
264      ct_stm32f107x8,
265      ct_stm32f107xB,
266      ct_stm32f107xC,
267
268      { TI - 64 K Flash, 16 K SRAM Devices }
269      ct_lm3s1110,
270      ct_lm3s1133,
271      ct_lm3s1138,
272      ct_lm3s1150,
273      ct_lm3s1162,
274      ct_lm3s1165,
275      ct_lm3s1166,
276      ct_lm3s2110,
277      ct_lm3s2139,
278      ct_lm3s6100,
279      ct_lm3s6110,
280
281      { TI 128 K Flash, 32 K SRAM devices - Fury Class }
282      ct_lm3s1601,
283      ct_lm3s1608,
284      ct_lm3s1620,
285      ct_lm3s1635,
286      ct_lm3s1636,
287      ct_lm3s1637,
288      ct_lm3s1651,
289      ct_lm3s2601,
290      ct_lm3s2608,
291      ct_lm3s2620,
292      ct_lm3s2637,
293      ct_lm3s2651,
294      ct_lm3s6610,
295      ct_lm3s6611,
296      ct_lm3s6618,
297      ct_lm3s6633,
298      ct_lm3s6637,
299      ct_lm3s8630,
300
301      { TI 256 K Flase, 32 K SRAM devices - Fury Class }
302      ct_lm3s1911,
303      ct_lm3s1918,
304      ct_lm3s1937,
305      ct_lm3s1958,
306      ct_lm3s1960,
307      ct_lm3s1968,
308      ct_lm3s1969,
309      ct_lm3s2911,
310      ct_lm3s2918,
311      ct_lm3s2919,
312      ct_lm3s2939,
313      ct_lm3s2948,
314      ct_lm3s2950,
315      ct_lm3s2965,
316      ct_lm3s6911,
317      ct_lm3s6918,
318      ct_lm3s6938,
319      ct_lm3s6950,
320      ct_lm3s6952,
321      ct_lm3s6965,
322      ct_lm3s8930,
323      ct_lm3s8933,
324      ct_lm3s8938,
325      ct_lm3s8962,
326      ct_lm3s8970,
327      ct_lm3s8971,
328
329      { TI - Tempest Tempest - 256 K Flash, 64 K SRAM }
330      ct_lm3s5951,
331      ct_lm3s5956,
332      ct_lm3s1b21,
333      ct_lm3s2b93,
334      ct_lm3s5b91,
335      ct_lm3s9b81,
336      ct_lm3s9b90,
337      ct_lm3s9b92,
338      ct_lm3s9b95,
339      ct_lm3s9b96,
340      ct_sc32442b,
341      ct_thumb2bare:
342        begin
343         with embedded_controllers[current_settings.controllertype] do
344          with linkres do
345            begin
346              Add('ENTRY(_START)');
347              Add('MEMORY');
348              Add('{');
349              if flashsize<>0 then
350                begin
351                  LinkStr := '    flash : ORIGIN = 0x' + IntToHex(flashbase,8)
352                    + ', LENGTH = 0x' + IntToHex(flashsize,8);
353                  Add(LinkStr);
354                end;
355
356              LinkStr := '    ram : ORIGIN = 0x' + IntToHex(srambase,8)
357              	+ ', LENGTH = 0x' + IntToHex(sramsize,8);
358              Add(LinkStr);
359
360              Add('}');
361              Add('_stack_top = 0x' + IntToHex(sramsize+srambase,8) + ';');
362            end;
363        end
364    else
365      if not (cs_link_nolink in current_settings.globalswitches) then
366      	 internalerror(200902011);
367  end;
368
369  with linkres do
370    begin
371      Add('SECTIONS');
372      Add('{');
373      Add('     .text :');
374      Add('    {');
375      Add('    KEEP(*(.init, .init.*))');
376      Add('    *(.text, .text.*)');
377      Add('    *(.strings)');
378      Add('    *(.rodata, .rodata.*)');
379      Add('    *(.comment)');
380      Add('    _etext = .;');
381      if embedded_controllers[current_settings.controllertype].flashsize<>0 then
382        begin
383          Add('    } >flash');
384        end
385      else
386        begin
387          Add('    } >ram');
388        end;
389      Add('    .data :');
390      Add('    {');
391      Add('    _data = .;');
392      Add('    *(.data, .data.*)');
393      Add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
394      Add('    _edata = .;');
395      if embedded_controllers[current_settings.controllertype].flashsize<>0 then
396        begin
397          Add('    } >ram AT >flash');
398        end
399      else
400        begin
401          Add('    } >ram');
402        end;
403      Add('    .bss :');
404      Add('    {');
405      Add('    _bss_start = .;');
406      Add('    *(.bss, .bss.*)');
407      Add('    *(COMMON)');
408      Add('    } >ram');
409      Add('. = ALIGN(4);');
410      Add('_bss_end = . ;');
411      Add('}');
412      Add('_end = .;');
413    end;
414{$endif ARM}
415
416{$ifdef i386}
417  with linkres do
418    begin
419      Add('ENTRY(_START)');
420      Add('SECTIONS');
421      Add('{');
422      Add('     . = 0x100000;');
423      Add('     .text ALIGN (0x1000) :');
424      Add('    {');
425      Add('    KEEP(*(.init, .init.*))');
426      Add('    *(.text, .text.*)');
427      Add('    *(.strings)');
428      Add('    *(.rodata, .rodata.*)');
429      Add('    *(.comment)');
430      Add('    _etext = .;');
431      Add('    }');
432      Add('    .data ALIGN (0x1000) :');
433      Add('    {');
434      Add('    _data = .;');
435      Add('    *(.data, .data.*)');
436      Add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
437      Add('    _edata = .;');
438      Add('    }');
439      Add('    . = ALIGN(4);');
440      Add('    .bss :');
441      Add('    {');
442      Add('    _bss_start = .;');
443      Add('    *(.bss, .bss.*)');
444      Add('    *(COMMON)');
445      Add('    }');
446      Add('_bss_end = . ;');
447      Add('}');
448      Add('_end = .;');
449    end;
450{$endif i386}
451
452{$ifdef AVR}
453  with linkres do
454    begin
455      { linker script from ld 2.19 }
456      Add('ENTRY(_START)');
457      Add('OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")');
458      Add('OUTPUT_ARCH(avr:2)');
459      Add('MEMORY');
460      Add('{');
461      Add('  text      (rx)   : ORIGIN = 0, LENGTH = 8K');
462      Add('  data      (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0');
463      Add('  eeprom    (rw!x) : ORIGIN = 0x810000, LENGTH = 64K');
464      Add('  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = 1K');
465      Add('  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = 1K');
466      Add('  signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K');
467      Add('}');
468      Add('SECTIONS');
469      Add('{');
470      Add('  /* Read-only sections, merged into text segment: */');
471      Add('  .hash          : { *(.hash)		}');
472      Add('  .dynsym        : { *(.dynsym)		}');
473      Add('  .dynstr        : { *(.dynstr)		}');
474      Add('  .gnu.version   : { *(.gnu.version)	}');
475      Add('  .gnu.version_d   : { *(.gnu.version_d)	}');
476      Add('  .gnu.version_r   : { *(.gnu.version_r)	}');
477      Add('  .rel.init      : { *(.rel.init)		}');
478      Add('  .rela.init     : { *(.rela.init)	}');
479      Add('  .rel.text      :');
480      Add('    {');
481      Add('      *(.rel.text)');
482      Add('      *(.rel.text.*)');
483      Add('      *(.rel.gnu.linkonce.t*)');
484      Add('    }');
485      Add('  .rela.text     :');
486      Add('    {');
487      Add('      *(.rela.text)');
488      Add('      *(.rela.text.*)');
489      Add('      *(.rela.gnu.linkonce.t*)');
490      Add('    }');
491      Add('  .rel.fini      : { *(.rel.fini)		}');
492      Add('  .rela.fini     : { *(.rela.fini)	}');
493      Add('  .rel.rodata    :');
494      Add('    {');
495      Add('      *(.rel.rodata)');
496      Add('      *(.rel.rodata.*)');
497      Add('      *(.rel.gnu.linkonce.r*)');
498      Add('    }');
499      Add('  .rela.rodata   :');
500      Add('    {');
501      Add('      *(.rela.rodata)');
502      Add('      *(.rela.rodata.*)');
503      Add('      *(.rela.gnu.linkonce.r*)');
504      Add('    }');
505      Add('  .rel.data      :');
506      Add('    {');
507      Add('      *(.rel.data)');
508      Add('      *(.rel.data.*)');
509      Add('      *(.rel.gnu.linkonce.d*)');
510      Add('    }');
511      Add('  .rela.data     :');
512      Add('    {');
513      Add('      *(.rela.data)');
514      Add('      *(.rela.data.*)');
515      Add('      *(.rela.gnu.linkonce.d*)');
516      Add('    }');
517      Add('  .rel.ctors     : { *(.rel.ctors)	}');
518      Add('  .rela.ctors    : { *(.rela.ctors)	}');
519      Add('  .rel.dtors     : { *(.rel.dtors)	}');
520      Add('  .rela.dtors    : { *(.rela.dtors)	}');
521      Add('  .rel.got       : { *(.rel.got)		}');
522      Add('  .rela.got      : { *(.rela.got)		}');
523      Add('  .rel.bss       : { *(.rel.bss)		}');
524      Add('  .rela.bss      : { *(.rela.bss)		}');
525      Add('  .rel.plt       : { *(.rel.plt)		}');
526      Add('  .rela.plt      : { *(.rela.plt)		}');
527      Add('  /* Internal text space or external memory.  */');
528      Add('  .text   :');
529      Add('  {');
530      Add('    *(.vectors)');
531      Add('    KEEP(*(.vectors))');
532      Add('    /* For data that needs to reside in the lower 64k of progmem.  */');
533      Add('    *(.progmem.gcc*)');
534      Add('    *(.progmem*)');
535      Add('    . = ALIGN(2);');
536      Add('     __trampolines_start = . ;');
537      Add('    /* The jump trampolines for the 16-bit limited relocs will reside here.  */');
538      Add('    *(.trampolines)');
539      Add('    *(.trampolines*)');
540      Add('     __trampolines_end = . ;');
541      Add('    /* For future tablejump instruction arrays for 3 byte pc devices.');
542      Add('       We don''t relax jump/call instructions within these sections.  */');
543      Add('    *(.jumptables)');
544      Add('    *(.jumptables*)');
545      Add('    /* For code that needs to reside in the lower 128k progmem.  */');
546      Add('    *(.lowtext)');
547      Add('    *(.lowtext*)');
548      Add('     __ctors_start = . ;');
549      Add('     *(.ctors)');
550      Add('     __ctors_end = . ;');
551      Add('     __dtors_start = . ;');
552      Add('     *(.dtors)');
553      Add('     __dtors_end = . ;');
554      Add('    KEEP(SORT(*)(.ctors))');
555      Add('    KEEP(SORT(*)(.dtors))');
556      Add('    /* From this point on, we don''t bother about wether the insns are');
557      Add('       below or above the 16 bits boundary.  */');
558      Add('    *(.init0)  /* Start here after reset.  */');
559      Add('    KEEP (*(.init0))');
560      Add('    *(.init1)');
561      Add('    KEEP (*(.init1))');
562      Add('    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */');
563      Add('    KEEP (*(.init2))');
564      Add('    *(.init3)');
565      Add('    KEEP (*(.init3))');
566      Add('    *(.init4)  /* Initialize data and BSS.  */');
567      Add('    KEEP (*(.init4))');
568      Add('    *(.init5)');
569      Add('    KEEP (*(.init5))');
570      Add('    *(.init6)  /* C++ constructors.  */');
571      Add('    KEEP (*(.init6))');
572      Add('    *(.init7)');
573      Add('    KEEP (*(.init7))');
574      Add('    *(.init8)');
575      Add('    KEEP (*(.init8))');
576      Add('    *(.init9)  /* Call main().  */');
577      Add('    KEEP (*(.init9))');
578      Add('    *(.text)');
579      Add('    . = ALIGN(2);');
580      Add('    *(.text.*)');
581      Add('    . = ALIGN(2);');
582      Add('    *(.fini9)  /* _exit() starts here.  */');
583      Add('    KEEP (*(.fini9))');
584      Add('    *(.fini8)');
585      Add('    KEEP (*(.fini8))');
586      Add('    *(.fini7)');
587      Add('    KEEP (*(.fini7))');
588      Add('    *(.fini6)  /* C++ destructors.  */');
589      Add('    KEEP (*(.fini6))');
590      Add('    *(.fini5)');
591      Add('    KEEP (*(.fini5))');
592      Add('    *(.fini4)');
593      Add('    KEEP (*(.fini4))');
594      Add('    *(.fini3)');
595      Add('    KEEP (*(.fini3))');
596      Add('    *(.fini2)');
597      Add('    KEEP (*(.fini2))');
598      Add('    *(.fini1)');
599      Add('    KEEP (*(.fini1))');
600      Add('    *(.fini0)  /* Infinite loop after program termination.  */');
601      Add('    KEEP (*(.fini0))');
602      Add('     _etext = . ;');
603      Add('  }  > text');
604      Add('  .data	  : AT (ADDR (.text) + SIZEOF (.text))');
605      Add('  {');
606      Add('     PROVIDE (__data_start = .) ;');
607      Add('    *(.data)');
608      Add('    *(.data*)');
609      Add('    *(.rodata)  /* We need to include .rodata here if gcc is used */');
610      Add('    *(.rodata*) /* with -fdata-sections.  */');
611      Add('    *(.gnu.linkonce.d*)');
612      Add('    . = ALIGN(2);');
613      Add('     _edata = . ;');
614      Add('     PROVIDE (__data_end = .) ;');
615      Add('  }  > data');
616      Add('  .bss   : AT (ADDR (.bss))');
617      Add('  {');
618      Add('     PROVIDE (__bss_start = .) ;');
619      Add('    *(.bss)');
620      Add('    *(.bss*)');
621      Add('    *(COMMON)');
622      Add('     PROVIDE (__bss_end = .) ;');
623      Add('  }  > data');
624      Add('   __data_load_start = LOADADDR(.data);');
625      Add('   __data_load_end = __data_load_start + SIZEOF(.data);');
626      Add('  /* Global data not cleared after reset.  */');
627      Add('  .noinit  :');
628      Add('  {');
629      Add('     PROVIDE (__noinit_start = .) ;');
630      Add('    *(.noinit*)');
631      Add('     PROVIDE (__noinit_end = .) ;');
632      Add('     _end = . ;');
633      Add('     PROVIDE (__heap_start = .) ;');
634      Add('  }  > data');
635      Add('  .eeprom  :');
636      Add('  {');
637      Add('    *(.eeprom*)');
638      Add('     __eeprom_end = . ;');
639      Add('  }  > eeprom');
640      Add('  .fuse  :');
641      Add('  {');
642      Add('    KEEP(*(.fuse))');
643      Add('    KEEP(*(.lfuse))');
644      Add('    KEEP(*(.hfuse))');
645      Add('    KEEP(*(.efuse))');
646      Add('  }  > fuse');
647      Add('  .lock  :');
648      Add('  {');
649      Add('    KEEP(*(.lock*))');
650      Add('  }  > lock');
651      Add('  .signature  :');
652      Add('  {');
653      Add('    KEEP(*(.signature*))');
654      Add('  }  > signature');
655      Add('  /* Stabs debugging sections.  */');
656      Add('  .stab 0 : { *(.stab) }');
657      Add('  .stabstr 0 : { *(.stabstr) }');
658      Add('  .stab.excl 0 : { *(.stab.excl) }');
659      Add('  .stab.exclstr 0 : { *(.stab.exclstr) }');
660      Add('  .stab.index 0 : { *(.stab.index) }');
661      Add('  .stab.indexstr 0 : { *(.stab.indexstr) }');
662      Add('  .comment 0 : { *(.comment) }');
663      Add('  /* DWARF debug sections.');
664      Add('     Symbols in the DWARF debugging sections are relative to the beginning');
665      Add('     of the section so we begin them at 0.  */');
666      Add('  /* DWARF 1 */');
667      Add('  .debug          0 : { *(.debug) }');
668      Add('  .line           0 : { *(.line) }');
669      Add('  /* GNU DWARF 1 extensions */');
670      Add('  .debug_srcinfo  0 : { *(.debug_srcinfo) }');
671      Add('  .debug_sfnames  0 : { *(.debug_sfnames) }');
672      Add('  /* DWARF 1.1 and DWARF 2 */');
673      Add('  .debug_aranges  0 : { *(.debug_aranges) }');
674      Add('  .debug_pubnames 0 : { *(.debug_pubnames) }');
675      Add('  /* DWARF 2 */');
676      Add('  .debug_info     0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }');
677      Add('  .debug_abbrev   0 : { *(.debug_abbrev) }');
678      Add('  .debug_line     0 : { *(.debug_line) }');
679      Add('  .debug_frame    0 : { *(.debug_frame) }');
680      Add('  .debug_str      0 : { *(.debug_str) }');
681      Add('  .debug_loc      0 : { *(.debug_loc) }');
682      Add('  .debug_macinfo  0 : { *(.debug_macinfo) }');
683      Add('}');
684      { last address of ram on an atmega128 }
685      Add('_stack_top = 0x0fff;');
686    end;
687{$endif AVR}
688
689  { Write and Close response }
690  linkres.writetodisk;
691  linkres.free;
692
693  WriteResponseFile:=True;
694
695end;
696
697
698function TlinkerEmbedded.MakeExecutable:boolean;
699var
700  binstr,
701  cmdstr  : TCmdStr;
702  success : boolean;
703  StaticStr,
704  GCSectionsStr,
705  DynLinkStr,
706  StripStr: string;
707begin
708  { for future use }
709  StaticStr:='';
710  StripStr:='';
711  DynLinkStr:='';
712
713  GCSectionsStr:='--gc-sections';
714  //if not(cs_link_extern in current_settings.globalswitches) then
715  if not(cs_link_nolink in current_settings.globalswitches) then
716   Message1(exec_i_linking,current_module.exefilename);
717
718{ Write used files and libraries }
719  WriteResponseFile();
720
721{ Call linker }
722  SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
723  Replace(cmdstr,'$OPT',Info.ExtraOptions);
724  if not(cs_link_on_target in current_settings.globalswitches) then
725   begin
726    Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.elf')))));
727    Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
728    Replace(cmdstr,'$STATIC',StaticStr);
729    Replace(cmdstr,'$STRIP',StripStr);
730    Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
731    Replace(cmdstr,'$DYNLINK',DynLinkStr);
732   end
733  else
734   begin
735    Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.elf'))));
736    Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
737    Replace(cmdstr,'$STATIC',StaticStr);
738    Replace(cmdstr,'$STRIP',StripStr);
739    Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
740    Replace(cmdstr,'$DYNLINK',DynLinkStr);
741   end;
742  success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
743
744{ Remove ReponseFile }
745  if success and not(cs_link_nolink in current_settings.globalswitches) then
746   DeleteFile(outputexedir+Info.ResName);
747
748{ Post process }
749  if success then
750    success:=PostProcessExecutable(current_module.exefilename+'.elf',false);
751
752  if success and (target_info.system in [system_arm_embedded,system_avr_embedded]) then
753    begin
754      success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O ihex '+
755        ChangeFileExt(current_module.exefilename,'.elf')+' '+
756        ChangeFileExt(current_module.exefilename,'.hex'),true,false);
757    end;
758
759  MakeExecutable:=success;   { otherwise a recursive call to link method }
760end;
761
762
763function TLinkerEmbedded.postprocessexecutable(const fn : string;isdll:boolean):boolean;
764  type
765    TElf32header=packed record
766      magic0123         : longint;
767      file_class        : byte;
768      data_encoding     : byte;
769      file_version      : byte;
770      padding           : array[$07..$0f] of byte;
771
772      e_type            : word;
773      e_machine         : word;
774      e_version         : longint;
775      e_entry           : longint;          { entrypoint }
776      e_phoff           : longint;          { program header offset }
777
778      e_shoff           : longint;          { sections header offset }
779      e_flags           : longint;
780      e_ehsize          : word;             { elf header size in bytes }
781      e_phentsize       : word;             { size of an entry in the program header array }
782      e_phnum           : word;             { 0..e_phnum-1 of entrys }
783      e_shentsize       : word;             { size of an entry in sections header array }
784      e_shnum           : word;             { 0..e_shnum-1 of entrys }
785      e_shstrndx        : word;             { index of string section header }
786    end;
787    TElf32sechdr=packed record
788      sh_name           : longint;
789      sh_type           : longint;
790      sh_flags          : longint;
791      sh_addr           : longint;
792
793      sh_offset         : longint;
794      sh_size           : longint;
795      sh_link           : longint;
796      sh_info           : longint;
797
798      sh_addralign      : longint;
799      sh_entsize        : longint;
800    end;
801
802  function MayBeSwapHeader(h : telf32header) : telf32header;
803    begin
804      result:=h;
805      if source_info.endian<>target_info.endian then
806        with h do
807          begin
808            result.e_type:=swapendian(e_type);
809            result.e_machine:=swapendian(e_machine);
810            result.e_version:=swapendian(e_version);
811            result.e_entry:=swapendian(e_entry);
812            result.e_phoff:=swapendian(e_phoff);
813            result.e_shoff:=swapendian(e_shoff);
814            result.e_flags:=swapendian(e_flags);
815            result.e_ehsize:=swapendian(e_ehsize);
816            result.e_phentsize:=swapendian(e_phentsize);
817            result.e_phnum:=swapendian(e_phnum);
818            result.e_shentsize:=swapendian(e_shentsize);
819            result.e_shnum:=swapendian(e_shnum);
820            result.e_shstrndx:=swapendian(e_shstrndx);
821          end;
822    end;
823
824  function MaybeSwapSecHeader(h : telf32sechdr) : telf32sechdr;
825    begin
826      result:=h;
827      if source_info.endian<>target_info.endian then
828        with h do
829          begin
830            result.sh_name:=swapendian(sh_name);
831            result.sh_type:=swapendian(sh_type);
832            result.sh_flags:=swapendian(sh_flags);
833            result.sh_addr:=swapendian(sh_addr);
834            result.sh_offset:=swapendian(sh_offset);
835            result.sh_size:=swapendian(sh_size);
836            result.sh_link:=swapendian(sh_link);
837            result.sh_info:=swapendian(sh_info);
838            result.sh_addralign:=swapendian(sh_addralign);
839            result.sh_entsize:=swapendian(sh_entsize);
840          end;
841    end;
842
843  var
844    f : file;
845
846  function ReadSectionName(pos : longint) : String;
847    var
848      oldpos : longint;
849      c : char;
850    begin
851      oldpos:=filepos(f);
852      seek(f,pos);
853      Result:='';
854      while true do
855        begin
856          blockread(f,c,1);
857          if c=#0 then
858            break;
859          Result:=Result+c;
860        end;
861      seek(f,oldpos);
862    end;
863
864  var
865    elfheader : TElf32header;
866    secheader : TElf32sechdr;
867    i : longint;
868    stringoffset : longint;
869    secname : string;
870  begin
871    postprocessexecutable:=false;
872    { open file }
873    assign(f,fn);
874    {$push}{$I-}
875    reset(f,1);
876    if ioresult<>0 then
877      Message1(execinfo_f_cant_open_executable,fn);
878    { read header }
879    blockread(f,elfheader,sizeof(tElf32header));
880    elfheader:=MayBeSwapHeader(elfheader);
881    seek(f,elfheader.e_shoff);
882    { read string section header }
883    seek(f,elfheader.e_shoff+sizeof(TElf32sechdr)*elfheader.e_shstrndx);
884    blockread(f,secheader,sizeof(secheader));
885    secheader:=MaybeSwapSecHeader(secheader);
886    stringoffset:=secheader.sh_offset;
887
888    seek(f,elfheader.e_shoff);
889    status.datasize:=0;
890    for i:=0 to elfheader.e_shnum-1 do
891      begin
892        blockread(f,secheader,sizeof(secheader));
893        secheader:=MaybeSwapSecHeader(secheader);
894        secname:=ReadSectionName(stringoffset+secheader.sh_name);
895        if secname='.text' then
896          begin
897            Message1(execinfo_x_codesize,tostr(secheader.sh_size));
898            status.codesize:=secheader.sh_size;
899          end
900        else if secname='.data' then
901          begin
902            Message1(execinfo_x_initdatasize,tostr(secheader.sh_size));
903            inc(status.datasize,secheader.sh_size);
904          end
905        else if secname='.bss' then
906          begin
907            Message1(execinfo_x_uninitdatasize,tostr(secheader.sh_size));
908            inc(status.datasize,secheader.sh_size);
909          end;
910
911      end;
912    close(f);
913    {$pop}
914    if ioresult<>0 then
915      ;
916    postprocessexecutable:=true;
917  end;
918
919
920{*****************************************************************************
921                                     Initialize
922*****************************************************************************}
923
924initialization
925{$ifdef arm}
926  RegisterExternalLinker(system_arm_embedded_info,TlinkerEmbedded);
927  RegisterTarget(system_arm_embedded_info);
928{$endif arm}
929
930{$ifdef avr}
931  RegisterExternalLinker(system_avr_embedded_info,TlinkerEmbedded);
932  RegisterTarget(system_avr_embedded_info);
933{$endif avr}
934
935{$ifdef i386}
936  RegisterExternalLinker(system_i386_embedded_info,TlinkerEmbedded);
937  RegisterTarget(system_i386_embedded_info);
938{$endif i386}
939end.