/compiler/systems/t_embed.pas
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.