[llvm-bugs] [Bug 52404] New: ASan increases alignment of global variable that has explicit alignment

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Nov 4 08:22:07 PDT 2021


            Bug ID: 52404
           Summary: ASan increases alignment of global variable that has
                    explicit alignment
           Product: clang
           Version: 13.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: thiago at kde.org
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org,
                    neeilans at live.com, richard-llvm at metafoo.co.uk

I am not sure this is a bug. It may be only a query about whether the behaviour
is desired.
References: http://bugreports.qt.io/browse/QTBUG-97941,

Simplified testcase:
$ cat test.cpp
alignas(void*) __attribute__((section(".mydata"))) struct Foo 
  int i; 
} mydata = {};
$ clang++ -S -o - test.cpp | sed -n '/.type.*mydata/,/.size.*mydata/p'
        .type   mydata, at object                  # @mydata
        .section        .mydata,"aw", at progbits
        .globl  mydata
        .p2align        3
        .zero   4
        .size   mydata, 4
$ clang++ -fsanitize=address -S -o - test.cpp | sed -n
        .type   mydata, at object                  # @mydata
        .section        .mydata,"aw", at progbits
        .globl  mydata
        .p2align        5
        .zero   32
        .size   mydata, 32

As the example shows, Clang increased the alignment of the variable above what
was asked for in the alignas() declaration. The same applies to
__attribute__((aligned(alignof(void *))).

Adding __attribute__((no_sanitize_address)) solves this problem. GCC neither
needs this argument nor allows it to be there, printing a warning if you add
it. The fact that you can use ASan with GCC on a global variable that is not
aligned to 32 means it's not necessary to be aligned to 32.

The problem is not the alignment of the variable itself, but that of the
section where the variable is located. The increased alignment of this variable
causes the ELF section to also be aligned to 32.

The real problem for me is that when the section name starts with ".note.", so
it's added as a PT_NOTE to the ELF Program Headers of the resulting library or
executable. The alignment of the phdr will be the alignment of the section,
which is the alignment of this variable. But ELF Notes must be aligned to
either 4 or 8; any other values are not permitted (strictly speaking, only the
ELF class' alignment should be allowed, but historically alignment 4 is handled
on 64-bit).

Even if one tried to parse other alignments, the internal data would be bad if
the alignment is not what's expected. The ELF note header is:

 uint32_t n_namesz;
 uint32_t n_descsz;
 uint32_t n_type;
 char notename[n_namesz];

That's 12 bytes followed by the note name of n_namesz bytes, followed by enough
padding bytes to align the note description (the payload) to the note's
alignment. Solaris and Qt Project note names are 12 bytes, bringing it to 24,
so suitably aligned to 4 or 8. GNU notes have name size 4 as "GNU\0", making
the entire header 16 bytes, which is suitably aligned to both possible values,
but also 16. Neither case is valid for 32-byte alignment and will produce
garbage on decoding.

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20211104/46ac1d60/attachment.html>

More information about the llvm-bugs mailing list