[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] Alignment



More information about alignment and compatibility issues.

The only important alignment for compatibility is the one used by GCC. It has always been 2 for MiNT (but it is 4 for other m68k platforms).

The GCC alignment is important for (at least) 2 things:

1) Structure members alignment. This is crucial for compatibility. If a program (or LDG dynamic library) expects to find some data at a specific offset, of course it will crash if the data is not exactly at the same place.

2) Aligning global variables to the specified alignment for performance purpose. Because the current GCC alignment is 2, the variables of type "long" of "structure containing longs" may or may not be aligned on 4-byte boundaries. The alignment of the global variables is a performance issue, but not a compatibility problem.

Then at the binutils level:
gas takes in input an asm source file, assemble it without modifying any offset (regardless to the binutils alignment), then it generates sections (.text, .data) with the following characteristics :

1) The section is marked as needing to be aligned on the "binutils alignment". This rule will have to be respected by the linker.

2) The section size is adjusted in order to be a multiple of the "binutils alignment". Thanks to that, when the linker will append another section coming from another .o file just after it, the alignment will be respected.

What happens in the binutils-2.13 for MiNT ?

GCC generates 2-byte aligned code.

Then gas uses a 4-byte alignment. It is totally useless: only the first global variable will respect that alignment. The following ones will only respect what was generated by GCC: alignment on 2.

Then ld links all the .o files, and respect their (bogus) alignment.

Then the OS load the executable in memory. If the OS loads the executable to a multiple of 4, the linker alignment will be respected. But if the OS loads the executable to a multiple of 2 only, all that alignment stuff will be totally useless ! I remember I saw such things on my STe with TOS 1.62, but I need to make further tests.

A quick summary :
1) GCC must respect the hardcoded "GCC alignment"
2) gas must produce .o files in respect to the alignment requested by GCC.
3) ld must produce executable files in respect to the alignment requested by every .o file. 4) The OS must respect the alignment of the executable files when loading them into memory.

If any of the above points is not respected, all that "performance alignment" tweaking will be useless.

You can see the alignements with the binutils objdump command:

$ m68k-atari-mint-objdump -h hello.o

hello.o:     file format a.out-zero-big

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000aa  00000000  00000000  00000020  2**1
                  CONTENTS, ALLOC, LOAD, RELOC, CODE
  1 .data         00000008  000000aa  000000aa  000000ca  2**1
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  000000b2  000000b2  00000000  2**1
                  ALLOC

$ m68k-atari-mint-objdump -h hello.tos

hello.tos:     file format a.out-mintprg

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000bed6  000000e4  000000e4  00000100  2**1
                  CONTENTS, ALLOC, LOAD, CODE
  1 .data         000005ac  0000bfba  0000bfba  0000bfd6  2**1
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000b86  0000c566  0000c566  00000000  2**1
                  ALLOC

The column "Algn" indicates the alignment. Note that the notation "**" indicates "power". So "2**1" is 2, and "2**2" is 4. For MiNT exectuables (without virtual memory - sigh), the VMA address is the offset of the section in memory, relative to the start of the .text segment. The VMA address of the .text segment in executables is e4 instead of 00 because of the size of the extended MiNT header.

Note the name of the .o file format. It is not actually saved into the a.out object files, it is hardcoded into the binutils (!). So objdump-2.13 will always display "a.out-mint", and objdump-2.18 will always display "a.out-zero-big"

I specially improved the objdump tool in binutils 2.18. It's output is now 100% accurate.

--
Vincent Rivière