Hi,
I have some binary files of records saved with Delphi. It is possible to load them with fpc and {$ALIGN 4} on Win32 and Linux i386.
Unfortunately it is not possible with Linux on arm.
I assume the alignment of strings in records is somehow different.
I can reproduce this with a mimimal example:
{$ALIGN 4}
program stringalignmenttest;
uses
sysutils;
type
tRecString = record
string1 : string [4];
string2 : string [16];
string3 : string [8];
end;
tRecInt = record
int1 : shortint;
int2 : integer;
int3 : shortint;
int4 : shortint;
int5 : integer;
end;
var
recstring : tRecString;
recint : tRecInt;
fstr : file of tRecString;
fint : file of TRecInt;
fname : string;
alstring : string;
begin
recint.int1 := 1;
recint.int2 := 2;
recint.int3 := 3;
recint.int4 := 4;
recint.int5 := 5;
recstring.string1 := 'ABCD';
recstring.string2 := 'ABCDEFGHIJKLMNOP';
recstring.string3 := 'ABCDEFGH';
alstring := '-a4';
fname := 'bindump';
{$IFDEF WIN32}
fname += '-win32';
{$ENDIF}
{$IFDEF LINUX}
{$IFDEF CPUARM}
fname += '-linuxarm';
{$ENDIF}
{$IFDEF CPU386}
fname += '-linuxi386';
{$ENDIF}
{$ENDIF}
assignFile(fint, fname + '-int' + alstring);
rewrite(fint);
Write(fint, recint);
closefile(fint);
writeln('sizeof recint: ' + IntToStr(sizeof(recint)));
assignFile(fstr, fname + '-string' + alstring);
rewrite(fstr);
Write(fstr, recstring);
closefile(fstr);
writeln('sizeof recstring: ' + IntToStr(sizeof(recstring)));
writeln('sizeof recstring.string1: ' + IntToStr(sizeof(recstring.string1)));
writeln('sizeof recstring.string2: ' + IntToStr(sizeof(recstring.string2)));
writeln('sizeof recstring.string3: ' + IntToStr(sizeof(recstring.string3)));
end.
Here are the results for arm and i386, both with 2 and 4-byte-alignment
The results for Linux on i386 and Win32 with 4-byte-alignment are:
program output:
$ ./stringalignmenttest
sizeof recint: 16
sizeof recstring: 31
sizeof recstring.string1: 5
sizeof recstring.string2: 17
sizeof recstring.string3: 9
hexdump of the generated files win32 and linux-i386 are the same:
bindump-linuxi386-int-a4
00000000 01 00 00 00 02 00 00 00 03 04 00 00 05 00 00 00 |................|
00000010
bindump-linuxi386-string-a4
00000000 04 41 42 43 44 10 41 42 43 44 45 46 47 48 49 4a |.ABCD.ABCDEFGHIJ|
00000010 4b 4c 4d 4e 4f 50 08 41 42 43 44 45 46 47 48 |KLMNOP.ABCDEFGH|
0000001f
The results for Linux on arm with 4-byte-alignment are:
program output:
sizeof recint: 16
sizeof recstring: 34
sizeof recstring.string1: 5
sizeof recstring.string2: 17
sizeof recstring.string3: 9
hexdump of the generated files on linux-arm:
bindump-linuxarm-int-a4
00000000 01 00 00 00 02 00 00 00 03 04 00 00 05 00 00 00 |................|
00000010
bindump-linuxarm-string-a4
00000000 04 41 42 43 44 00 10 41 42 43 44 45 46 47 48 49 |.ABCD..ABCDEFGHI|
00000010 4a 4b 4c 4d 4e 4f 50 00 08 41 42 43 44 45 46 47 |JKLMNOP..ABCDEFG|
00000020 48 00 |H.|
00000022
The results for Linux on i386 with 2-byte-alignment are:
program output:
./stringalignmenttest
sizeof recint: 12
sizeof recstring: 31
sizeof recstring.string1: 5
sizeof recstring.string2: 17
sizeof recstring.string3: 9
hexdump of the generated files on linux-i386:
bindump-linuxi386-int-a2
00000000 01 00 02 00 00 00 03 04 05 00 00 00 |............|
0000000c
bindump-linuxi386-string-a2
00000000 04 41 42 43 44 10 41 42 43 44 45 46 47 48 49 4a |.ABCD.ABCDEFGHIJ|
00000010 4b 4c 4d 4e 4f 50 08 41 42 43 44 45 46 47 48 |KLMNOP.ABCDEFGH|
0000001f
The results for Linux on arm with 2-byte-alignment are:
program output:
sizeof recint: 12
sizeof recstring: 34
sizeof recstring.string1: 5
sizeof recstring.string2: 17
sizeof recstring.string3: 9
hexdump of the generated files on linux-arm:
bindump-linuxarm-int-a2
00000000 01 00 02 00 00 00 03 04 05 00 00 00 |............|
0000000c
bindump-linuxarm-string-a2
00000000 04 41 42 43 44 00 10 41 42 43 44 45 46 47 48 49 |.ABCD..ABCDEFGHI|
00000010 4a 4b 4c 4d 4e 4f 50 00 08 41 42 43 44 45 46 47 |JKLMNOP..ABCDEFG|
00000020 48 00 |H.|
00000022
I am using fpc 3.0.0 and Lazarus 1.6.1 updated with fpcup on 2016-04-04. Binarys for linux are crosscompiled under Windows 8.1.
It seems that alignment for integers in records does work just as expected, both on i386 and arm.
It seems that strings align to 1 byte on i386 and to 2 bytes on arm, regardless of the compiler directive {$ALIGN}
Is it possible to get the same behavior on arm as on i386?
Is this a bug in fpc?