gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Linker script, crt0 and compiler issues

#81638 - Legolas - Sun Apr 30, 2006 8:21 pm

Really I don't know if tis is the right place where I should start this thread, but... :)

Briefly: I'm working on a porting of the freepascal compiler for gba. Most of the work on the compiler itself is done, and I'm able to compile some small demos with it, by using a reduced crt0.s file taken from somewhere (really I don't remember where).
Now that all seems working fine, I would like to use Jeff Frohwein's crt0 & linkerscript. The problem is that, using it, all rtti and resource strings (coming from freepascal rtl) are put in .bss at 0x03000000, making the executable not working on gba.
Assumed that I don't know anything about linker scripts, can someone point me towards a solution?

Thanks in Advance :)
_________________
My homepage!

#81661 - tepples - Mon May 01, 2006 12:23 am

Any constants should be put in section ".rodata".
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#81670 - wintermute - Mon May 01, 2006 1:44 am

You might also care to look at building your compiler with MinGW rather than cygwin. You'll end up with a faster compiler that doesn't depend on cygwin1.dll.

The devkitARM buildscripts contain the necessary patches for building binutils with MinGW. http://sourceforge.net/project/showfiles.php?group_id=114505&package_id=124206
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#81697 - Legolas - Mon May 01, 2006 2:26 pm

wintermute wrote:
You might also care to look at building your compiler with MinGW rather than cygwin. You'll end up with a faster compiler that doesn't depend on cygwin1.dll.

The devkitARM buildscripts contain the necessary patches for building binutils with MinGW. http://sourceforge.net/project/showfiles.php?group_id=114505&package_id=124206


Yes, in fact I'm using binutils from your devkitARM
_________________
My homepage!

#81875 - Legolas - Tue May 02, 2006 4:30 pm

After a bit of investigation I have found that fpc compiler puts resource strings and RTTI infos in .data segment. It is possible to safely move it in .rodata?
_________________
My homepage!

#81883 - tepples - Tue May 02, 2006 5:04 pm

Any data that will never be modified can go in .rodata. Is there a specification for the language that fpc accepts? If so, does this specification permit a program to overwrite a string constant? If not, then a string constant will never be modified, and it can go in .rodata.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#81887 - wintermute - Tue May 02, 2006 5:18 pm

Legolas wrote:

Yes, in fact I'm using binutils from your devkitARM


cool :) Why do you have cygwin1.dll in the packages though?

Quote:

After a bit of investigation I have found that fpc compiler puts resource strings and RTTI infos in .data segment. It is possible to safely move it in .rodata?


That should work provided the application doesn't expect to be able to write to that data. I'd imagine resource strings could be moved to .rodata with few problems but I'm not sure about RTTI.

You could place .data in EWRAM to give you some breathing space.

Remember that the .data section needs to be copied from ROM to RAM by the crt0.

Most of the standard crt0/linkscript combinations place the stack, .data and .bss in the 32K iwram.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#81889 - Legolas - Tue May 02, 2006 5:28 pm

Ok, I'll try to put all in EWRAM :)

wintermute wrote:
Legolas wrote:

Yes, in fact I'm using binutils from your devkitARM

cool :) Why do you have cygwin1.dll in the packages though?


Well the package in my site is an old version. Now I'm working on a new version that should be fast enough to make games for gba with pascal too :)
_________________
My homepage!

#83111 - Legolas - Sat May 13, 2006 1:21 am

So, I have tryed to move around things among sections, but still does not work. I have found that the problem is that the executable suffers of bad alignment, but only if I link 2 or more objects in it.

For example: an excutable made of prt0.o, main.o and system.o works, but another made of eg. prt0.o, main.o, system.o and math.o doesn't.
_________________
My homepage!

#83158 - wintermute - Sat May 13, 2006 2:19 pm

Can you give me some more details of what you mean by bad alignment? A specific example of source, link command line and a mapfile would help. You can output a mapfile using arm-elf-ld -Map mapfile.txt ...
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#83161 - Legolas - Sat May 13, 2006 2:50 pm

Yes, sorry ^_^
Because of size of map file, I have uploaded all here (makefile, source, map file, ...).
_________________
My homepage!

#83188 - wintermute - Sun May 14, 2006 12:50 am

From a brief look at the rom with no$gba it seems to be blowing it's stack.

Try shifting the .data section into ewram to start with

Code:

OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)




MEMORY {
   rom      : ORIGIN = 0x08000000, LENGTH = 32M
   iwram   : ORIGIN = 0x03000000, LENGTH = 32K
   ewram   : ORIGIN = 0x02000000, LENGTH = 256K
}

__text_start       =   0x8000000;
__eheap_end         =   0x2040000;
__iwram_start      =   0x3000000;
__iwram_end         =   0x3008000;

__sp_irq         =   __iwram_end - 0x100;
__sp_usr         =   __sp_irq - 0x100;



SECTIONS
{

   . = __text_start;
   .init :
   {
      KEEP (*(.init))
      . = ALIGN(4);
   } >rom =0xff

   .plt :
   {
      *(.plt)
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
   } >rom

   .text :   /* ALIGN (4): */
   {
      *(EXCLUDE_FILE (*.iwram*) .text)
      *(.text.*)
      *(.stub)
      /* .gnu.warning sections are handled specially by elf32.em.  */
      *(.gnu.warning)
      *(.gnu.linkonce.t*)
      *(.glue_7)
      *(.glue_7t)
      . = ALIGN(4);  /* REQUIRED. LD is flaky without it. */
   } >rom = 0xff

   __text_end = .;
   .fini           :
   {
      KEEP (*(.fini))
      . = ALIGN(4);  /* REQUIRED. LD is flaky without it. */
   } >rom =0

   .rodata :
   {
      *(.rodata)
      *all.rodata*(*)
      *(.roda)
      *(.rodata.*)
      *(.gnu.linkonce.r*)
      SORT(CONSTRUCTORS)
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
   } >rom = 0xff

   .ctors :
   {
      /*   gcc uses crtbegin.o to find the start of the constructors, so
         we make sure it is first.  Because this is a wildcard, it
         doesn't matter if the user does not actually link against
         crtbegin.o; the linker won't look for a file to match a
         wildcard.  The wildcard also means that it doesn't matter which
         directory crtbegin.o is in.  */
      KEEP (*crtbegin.o(.ctors))
      KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
      KEEP (*(SORT(.ctors.*)))
      KEEP (*(.ctors))
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
  } >rom = 0

   .dtors :
   {
      KEEP (*crtbegin.o(.dtors))
      KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
      KEEP (*(SORT(.dtors.*)))
      KEEP (*(.dtors))
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
   } >rom = 0

   .jcr            : { KEEP (*(.jcr)) } >rom

   .eh_frame :
   {
      KEEP (*(.eh_frame))
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
   } >rom = 0

   .gcc_except_table :
   {
      *(.gcc_except_table)
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
   } >rom = 0




   __iwram_lma = .;

   .iwram __iwram_start : AT (__iwram_lma)
   {
      __iwram_start = ABSOLUTE(.) ;
      *(.iwram)
      *iwram.*(.text)
      . = ALIGN(4);   /* REQUIRED. LD is flaky without it. */
   } >iwram = 0xff

   __iwram_end = . ;

   .bss ALIGN(4) :
   {
      __bss_start = ABSOLUTE(.);
      __bss_start__ = ABSOLUTE(.);
      *(.dynbss)
      *(.gnu.linkonce.b*)
      *(.bss*)
      *(COMMON)
      . = ALIGN(4);    /* REQUIRED. LD is flaky without it. */
   } >iwram

   __bss_end = . ;
   __bss_end__ = . ;


   __iwram_overlay_lma = __iwram_lma + SIZEOF(.iwram);

   __iwram_overlay_start = . ;

   OVERLAY ALIGN(4) : NOCROSSREFS AT (__iwram_overlay_lma)
   {
      .iwram0 { *(.iwram0) . = ALIGN(4);}
      .iwram1 { *(.iwram1) . = ALIGN(4);}
      .iwram2 { *(.iwram2) . = ALIGN(4);}
      .iwram3 { *(.iwram3) . = ALIGN(4);}
      .iwram4 { *(.iwram4) . = ALIGN(4);}
      .iwram5 { *(.iwram5) . = ALIGN(4);}
      .iwram6 { *(.iwram6) . = ALIGN(4);}
      .iwram7 { *(.iwram7) . = ALIGN(4);}
      .iwram8 { *(.iwram8) . = ALIGN(4);}
      .iwram9 { *(.iwram9) . = ALIGN(4);}
   }>iwram = 0xff




   __ewram_lma = LOADADDR(.iwram0) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9);

   __iwram_overlay_end = . ;
   __iheap_start = . ;

   __ewram_start = 0x2000000;
   .ewram __ewram_start : AT (__ewram_lma)
   {
      *(.ewram)
      . = ALIGN(4);  /* REQUIRED. LD is flaky without it. */
   }>ewram = 0xff

   __data_lma = __ewram_lma + SIZEOF(.ewram) ;

   .data ALIGN(4) : AT (__data_lma)
   {
      __data_start = ABSOLUTE(.);
      *(.data)
      *(.data.*)
      *(.gnu.linkonce.d*)
      CONSTRUCTORS
      . = ALIGN(4);
   } >ewram = 0xff

   __data_end  =  .;

   __ewram_overlay_lma = __data_lma + SIZEOF(.data);

   .sbss ALIGN(4):
    {
      __sbss_start = ABSOLUTE(.);
       *(.sbss)
       . = ALIGN(4);
    } >ewram
   
   __sbss_end  = .;

   __ewram_end = . ;
   __ewram_overlay_start = . ;

   OVERLAY ALIGN(4): NOCROSSREFS AT (__ewram_overlay_lma)
   {
      .ewram0 { *(.ewram0) . = ALIGN(4);}
      .ewram1 { *(.ewram1) . = ALIGN(4);}
      .ewram2 { *(.ewram2) . = ALIGN(4);}
      .ewram3 { *(.ewram3) . = ALIGN(4);}
      .ewram4 { *(.ewram4) . = ALIGN(4);}
      .ewram5 { *(.ewram5) . = ALIGN(4);}
      .ewram6 { *(.ewram6) . = ALIGN(4);}
      .ewram7 { *(.ewram7) . = ALIGN(4);}
      .ewram8 { *(.ewram8) . = ALIGN(4);}
      .ewram9 { *(.ewram9) . = ALIGN(4);}
   }>ewram = 0xff

   __pad_lma = LOADADDR(.ewram0) + SIZEOF(.ewram0)+SIZEOF(.ewram1)+SIZEOF(.ewram2)+SIZEOF(.ewram3)+SIZEOF(.ewram4)+SIZEOF(.ewram5)+SIZEOF(.ewram6)+SIZEOF(.ewram7)+SIZEOF(.ewram8)+SIZEOF(.ewram9);

   /* EZF Advance strips trailing 0xff bytes, add a pad section so nothing important is removed */
   .pad ALIGN(4) : AT (__pad_lma)
   {
      LONG(0x52416b64)
      LONG(0x4d)
      . = ALIGN(4);  /* REQUIRED. LD is flaky without it. */
   } = 0xff

   __ewram_overlay_end = . ;
   __eheap_start = . ;

   _end = .;
   __end__ = _end ; /* v1.3 */
   PROVIDE (end = _end); /* v1.3 */




   /* Stabs debugging sections.  */
   .stab 0 : { *(.stab) }
   .stabstr 0 : { *(.stabstr) }
   .stab.excl 0 : { *(.stab.excl) }
   .stab.exclstr 0 : { *(.stab.exclstr) }
   .stab.index 0 : { *(.stab.index) }
   .stab.indexstr 0 : { *(.stab.indexstr) }
   .comment 0 : { *(.comment) }
   /*   DWARF debug sections.
      Symbols in the DWARF debugging sections are relative to the beginning
      of the section so we begin them at 0.  */
   /* DWARF 1 */
   .debug          0 : { *(.debug) }
   .line           0 : { *(.line) }
   /* GNU DWARF 1 extensions */
   .debug_srcinfo  0 : { *(.debug_srcinfo) }
   .debug_sfnames  0 : { *(.debug_sfnames) }
   /* DWARF 1.1 and DWARF 2 */
   .debug_aranges  0 : { *(.debug_aranges) }
   .debug_pubnames 0 : { *(.debug_pubnames) }
   /* DWARF 2 */
   .debug_info     0 : { *(.debug_info) }
   .debug_abbrev   0 : { *(.debug_abbrev) }
   .debug_line     0 : { *(.debug_line) }
   .debug_frame    0 : { *(.debug_frame) }
   .debug_str      0 : { *(.debug_str) }
   .debug_loc      0 : { *(.debug_loc) }
   .debug_macinfo  0 : { *(.debug_macinfo) }
   /* SGI/MIPS DWARF 2 extensions */
   .debug_weaknames 0 : { *(.debug_weaknames) }
   .debug_funcnames 0 : { *(.debug_funcnames) }
   .debug_typenames 0 : { *(.debug_typenames) }
   .debug_varnames  0 : { *(.debug_varnames) }
   .stack 0x80000 : { _stack = .; *(.stack) }
   /* These must appear regardless of  .  */
}



This linkscript can probably be reduced quite a bit as well - you don't really need the overlay sections and I don't think you need the constructor & destructor stuff.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#83191 - Legolas - Sun May 14, 2006 1:07 am

I tryed this liker script, but unfortunately same result. At least now I have all stuff in the right places ^_^
_________________
My homepage!

#83254 - wintermute - Sun May 14, 2006 4:03 pm

I don't see anything that's misaligned in the map output, everything seems to be on 4 byte boundaries.

There appears to be a problem somewhere inside SYSTEM_ALLOC_OSCHUNK$LONGINT$LONGINT$$POINTER which, from it's name, I'd guess is trying to allocate memory. How does Free Pascal determine where it's free memory is addressed?
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#83453 - Legolas - Tue May 16, 2006 2:11 pm

wintermute wrote:

There appears to be a problem somewhere inside SYSTEM_ALLOC_OSCHUNK$LONGINT$LONGINT$$POINTER which, from it's name, I'd guess is trying to allocate memory.


Thanks to your help I have found the bug. That call (SYSTEM_ALLOC_OSCHUNK) grows the heap; Freepascal does not have a flag to disable heap allocation, so I have made some changes to disable it and now it works :)
_________________
My homepage!