Hide Forgot
Description of problem: The reproducer from bz1035413 [1] fails on aarch64, because the sizes are not equal. While on x86_64, they are both 36 as expected: sizeof(b) = 36 (stop-start) = 36 on aarch64, the (stop-start) (mysection size) is equal to 40: sizeof(b) = 36 (stop-start) = 40 When looking at readelf output, mysection is aligned to 32 on x86_64 while the next section is .bss (aligned to 4). On aarch64, mysection is aligned to 8 and .bss to 1: x86_64: [25] mysection PROGBITS 0000000000601040 00001040 0000000000000024 0000000000000000 WA 0 0 32 [26] .bss NOBITS 0000000000601064 00001064 0000000000000004 0000000000000000 WA 0 0 4 aarch64: [25] mysection PROGBITS 0000000000420028 00010028 0000000000000028 0000000000000000 WA 0 0 8 [26] .bss NOBITS 0000000000420050 00010050 0000000000000008 0000000000000000 WA 0 0 1 The reproducer can be taken from [1] or I have added a printf to make it clearer: #include <stdio.h> struct A { int a; char b[]; }; union B { struct A a; char b[sizeof (struct A) + 31]; }; union B b __attribute__((section ("mysection"))) = { { 1, "123456789012345678901234567890" } }; extern char __start_mysection[], __stop_mysection[]; int main () { __SIZE_TYPE__ start = (__SIZE_TYPE__) __start_mysection; __SIZE_TYPE__ stop = (__SIZE_TYPE__) __stop_mysection; printf("sizeof(b) = %i\n(stop-start) = %i\n", sizeof(b), (stop - start)); if (sizeof (b) != (stop - start)) __builtin_abort (); return 0; } [1] https://bugzilla.redhat.com/show_bug.cgi?id=1035413#c18 Version-Release number of selected component (if applicable): gcc-4.8.5-10.el7.aarch64 How reproducible: 100% Steps to Reproduce: 1. cc -o r r.c 2. ./r 3. Actual results: Reproducer aborts because 36 != 40. Expected results: Reproducer does not abort, 36 = 36. Additional info: --> It does not matter, whether -fno-section-anchors or -fsection-anchors options are used or not. --> It seems it worked in past after fixing bz1035413. --> It works on all other archs.
I believe this is just insufficiently portable testcase (looking at the referenced rhbz, it seems I've suggested it, so mea culpa here). The problem is that various targets (including x86_64) have various ABI and optimization extended alignment rules (in GCC DATA_ABI_ALIGNMENT and DATA_ALIGNMENT macros), which can enlarge the alignment of certain variables. So, while even on aarch64 the union has size 36 and alignment 4 bytes, the aarch64 backend for performance reasons chooses to align it to 8 bytes boundary, which means the assembler then pads the user section after the struct to a multiple of 8 bytes. Using union B b __attribute__((aligned (__alignof__(union B)), section ("mysection"))) = { { 1, "123456789012345678901234567890" } }; instead of union B b __attribute__((section ("mysection"))) = { { 1, "123456789012345678901234567890" } }; fixes this problem, it tells the compiler not to overalign it. Generally it is an implementation detail in which order and with what padding the toolchain emits the variables, emitting them into a user named section and expecting no padding in the entries put into that section is a common but non-portable technique (I think e.g. glibc, or Linux kernel, or prelink and various other apps use it).
Bug in the testcase, not in the compiler.