[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