Bug 1374816 - union size and section sizes mismatch on aarch64
Summary: union size and section sizes mismatch on aarch64
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: gcc
Version: 7.3
Hardware: aarch64
OS: Unspecified
medium
medium
Target Milestone: rc
: ---
Assignee: Jakub Jelinek
QA Contact: Michael Petlan
URL:
Whiteboard:
Depends On:
Blocks: 1357680
TreeView+ depends on / blocked
 
Reported: 2016-09-09 17:48 UTC by Michael Petlan
Modified: 2017-03-08 15:18 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2017-03-08 15:18:45 UTC
Target Upstream Version:


Attachments (Terms of Use)

Description Michael Petlan 2016-09-09 17:48:28 UTC
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.

Comment 2 Jakub Jelinek 2016-09-20 14:28:29 UTC
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).

Comment 3 Jakub Jelinek 2017-03-08 15:18:45 UTC
Bug in the testcase, not in the compiler.


Note You need to log in before you can comment on or make changes to this bug.