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.

Coding > linker scripts

#22780 - MothAttack - Tue Jun 29, 2004 8:46 am

Does anyone about using linker scripts with GNU ld? I have two questions:

ALIGN() only seems to work with values of at least 16. For example, ALIGN(4) has the same effect as ALIGN(16), but ALIGN(256) will indeed align to the next 256 bytes. Is that just how it works? How would I get word-aligned sections, then?

Also, FILL() doesn't seem to work at all. I've tried both the "FILL(x)" and "=x" expressions, but neither has any effect. My sections are ending with repeating copies of four random bytes. (One section ends with "00 00 a0 e1 00 00 a0 e1 00 00 a0 e1", another with "36 00 03 90 36 00 03".) Anyone know what the problem is?

#22824 - Miked0801 - Tue Jun 29, 2004 11:53 pm

Have you gone to gnu.org and looked up the docs on link scripts? They are pretty straight forward - though I will admit that linker scripts are pretty arcane :)

#22833 - MothAttack - Wed Jun 30, 2004 1:13 am

Update: Well, it turns out ALIGN and FILL actually do work. Both these perceived problems stem from the same real problem: ld wants to align all data within a section to the next 16 bytes. Example:

Code:
rom _rom_vma : AT(_rom_lma) {
   _rom_start = ABSOLUTE(.);
   *(rom);
   _rom_end = ABSOLUTE(.);
   _rom_length = _rom_end - _rom_start;
   }


If I use the above section, _rom_end is always rounded up to the nearest 0x10, and therefore _rom_length is always a multiple of 16. Here's the problem: the extra bytes at the end are filled with repeating copies of four random bytes. FILL(0) and =0 both have no effect on these bytes, but filling does work. Another example:

Code:
rom _rom_vma : AT(_rom_lma) {
   *(rom);
   } = 0


This section will end with, e.g.:

12 34 56 78 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1

The bytes "12 34 56 78" are the actual end of the section, and the rest is filling to the next 0x10. But if I do this:

Code:
rom _rom_vma : AT(_rom_lma) {
   *(rom);
   . = ALIGN(32);
   } = 0


Now the section will end with:

12 34 56 78 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

So the =0 expression works. It's just this 16-byte internal alignment that's causing trouble. Is there any way to change this?

#22845 - wintermute - Wed Jun 30, 2004 12:44 pm

Would you care to have a look at this using devkitARM?

I suspect the internal alignment you're seeing might be the compiler aligning object files rather than the linker although I could be wrong. It's also possible that the linker in your toolchain has been patched to do this - it's certainly something I've been considering doing with my toolchain for ease of use.

#22921 - MothAttack - Thu Jul 01, 2004 3:44 am

I made a quick visit to devkit.tk, downloaded devkitARM 6a, and used its copies of as, ld, and objcopy to re-compile my code. The result was no different.

I looked at the final test.gba file with a hex editor, and the alignment is in there. I looked at the test.elf file (after linking but before objcopy), and the alignment is in there. I looked at the test.obj file (after compiling but before linking), and the alignment is in there.

Well, I can't really say if it's alignment in the .OBJ file because the .OBJ file has a whole bunch of stuff that gets thrown out for the final version (symbols and junk). But I can find the string of bytes "12 34 56 78 00 00 a0 e1 00 00 a0 e1 00 00 a0 e1" in the .OBJ file. So clearly the compiler is generating these bytes. (The actual source code ends the section with ".byte 0x12, 0x34, 0x56, 0x78"; the extra bytes aren't in the source.) And the linker seems to like them there. So... Any more ideas?