https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68725

Lukas Wunner <lukas at wunner dot de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lukas at wunner dot de

--- Comment #1 from Lukas Wunner <lukas at wunner dot de> ---
I've just hit the same issue with the 128-bit UUIDs that are used all over the
place in the kernel, in particular in the EFI subsystem.


Reproducer:

#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef struct {
        uint8_t b[16];
} efi_guid_t;

#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)               \
((const efi_guid_t)                                                     \
{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
   (b) & 0xff, ((b) >> 8) & 0xff,                                       \
   (c) & 0xff, ((c) >> 8) & 0xff,                                       \
   (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})

#define EFI_RNG_ALGORITHM_RAW                   EFI_GUID(0xe43176d7, 0xb6e8,
0x4827,  0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
#define EFI_CONSOLE_OUT_DEVICE_GUID             EFI_GUID(0xd3b36f2c, 0xd551,
0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID        EFI_GUID(0xdcfa911d, 0x26eb,
0x469f,  0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
#define HCDP_TABLE_GUID                         EFI_GUID(0xf951938d, 0x620b,
0x42ef,  0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98)

static int efi_print_guid_ptr(const efi_guid_t *vendor)
{
        for (int i = 0; i < sizeof(efi_guid_t) ; i++)
                printf("%hhX", vendor->b[i]);
        printf("\n");
}

static int efi_print_guid(const efi_guid_t vendor)
{
        for (int i = 0; i < sizeof(efi_guid_t) ; i++)
                printf("%hhX", vendor.b[i]);
        printf("\n");
}

void main()
{
        const efi_guid_t guid1 = EFI_RNG_ALGORITHM_RAW;
        const efi_guid_t guid2 = EFI_MEMORY_ATTRIBUTES_TABLE_GUID;

        efi_print_guid_ptr(&guid1);
        efi_print_guid_ptr(&HCDP_TABLE_GUID);

        efi_print_guid(guid2);
        efi_print_guid(EFI_CONSOLE_OUT_DEVICE_GUID);
}


Compiled with -O2 (no other options) on x86_64 results in:

0000000000400440 <main>:
  400440:       55                      push   %rbp
  400441:       53                      push   %rbx
  400442:       48 83 ec 48             sub    $0x48,%rsp
  400446:       48 89 e7                mov    %rsp,%rdi
  400449:       c6 04 24 d7             movb   $0xd7,(%rsp)
  40044d:       c6 44 24 01 76          movb   $0x76,0x1(%rsp)
  400452:       c6 44 24 02 31          movb   $0x31,0x2(%rsp)
  400457:       c6 44 24 03 e4          movb   $0xe4,0x3(%rsp)
  40045c:       48 8d 5c 24 30          lea    0x30(%rsp),%rbx
  400461:       c6 44 24 04 e8          movb   $0xe8,0x4(%rsp)
  400466:       c6 44 24 05 b6          movb   $0xb6,0x5(%rsp)
  40046b:       48 8d 6c 24 40          lea    0x40(%rsp),%rbp
  400470:       c6 44 24 06 27          movb   $0x27,0x6(%rsp)
  400475:       c6 44 24 07 48          movb   $0x48,0x7(%rsp)
  40047a:       c6 44 24 08 b7          movb   $0xb7,0x8(%rsp)
  40047f:       c6 44 24 09 84          movb   $0x84,0x9(%rsp)
  400484:       c6 44 24 0a 7f          movb   $0x7f,0xa(%rsp)
  400489:       c6 44 24 0b fd          movb   $0xfd,0xb(%rsp)
  40048e:       c6 44 24 0c c4          movb   $0xc4,0xc(%rsp)
  400493:       c6 44 24 0d b6          movb   $0xb6,0xd(%rsp)
  400498:       c6 44 24 0e 85          movb   $0x85,0xe(%rsp)
  40049d:       c6 44 24 0f 61          movb   $0x61,0xf(%rsp)
  4004a2:       e8 f9 01 00 00          callq  4006a0 <efi_print_guid_ptr>
  4004a7:       48 8d 7c 24 10          lea    0x10(%rsp),%rdi
  4004ac:       c6 44 24 10 8d          movb   $0x8d,0x10(%rsp)
  4004b1:       c6 44 24 11 93          movb   $0x93,0x11(%rsp)
  4004b6:       c6 44 24 12 51          movb   $0x51,0x12(%rsp)
  4004bb:       c6 44 24 13 f9          movb   $0xf9,0x13(%rsp)
  4004c0:       c6 44 24 14 0b          movb   $0xb,0x14(%rsp)
  4004c5:       c6 44 24 15 62          movb   $0x62,0x15(%rsp)
  4004ca:       c6 44 24 16 ef          movb   $0xef,0x16(%rsp)
  4004cf:       c6 44 24 17 42          movb   $0x42,0x17(%rsp)
  4004d4:       c6 44 24 18 82          movb   $0x82,0x18(%rsp)
  4004d9:       c6 44 24 19 79          movb   $0x79,0x19(%rsp)
  4004de:       c6 44 24 1a a8          movb   $0xa8,0x1a(%rsp)
  4004e3:       c6 44 24 1b 4b          movb   $0x4b,0x1b(%rsp)
  4004e8:       c6 44 24 1c 79          movb   $0x79,0x1c(%rsp)
  4004ed:       c6 44 24 1d 61          movb   $0x61,0x1d(%rsp)
  4004f2:       c6 44 24 1e 78          movb   $0x78,0x1e(%rsp)
  4004f7:       c6 44 24 1f 98          movb   $0x98,0x1f(%rsp)
  4004fc:       e8 9f 01 00 00          callq  4006a0 <efi_print_guid_ptr>
  400501:       48 8b 05 78 02 00 00    mov    0x278(%rip),%rax  # 400780
<guid2.2638>
  400508:       48 8b 15 79 02 00 00    mov    0x279(%rip),%rdx  # 400788
<guid2.2638+0x8>
  40050f:       48 89 44 24 30          mov    %rax,0x30(%rsp)
  400514:       48 89 54 24 38          mov    %rdx,0x38(%rsp)
  400519:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  400520:       0f b6 33                movzbl (%rbx),%esi
  400523:       31 c0                   xor    %eax,%eax
  400525:       bf 64 07 40 00          mov    $0x400764,%edi
  40052a:       48 83 c3 01             add    $0x1,%rbx
  40052e:       e8 dd fe ff ff          callq  400410 <printf@plt>
  400533:       48 39 eb                cmp    %rbp,%rbx
  400536:       75 e8                   jne    400520 <main+0xe0>
  400538:       bf 0a 00 00 00          mov    $0xa,%edi
  40053d:       48 8d 5c 24 20          lea    0x20(%rsp),%rbx
  400542:       48 8d 6c 24 30          lea    0x30(%rsp),%rbp
  400547:       e8 b4 fe ff ff          callq  400400 <putchar@plt>
  40054c:       48 8b 05 1d 02 00 00    mov    0x21d(%rip),%rax  # 400770
<C.0.2641>
  400553:       48 8b 15 1e 02 00 00    mov    0x21e(%rip),%rdx  # 400778
<C.0.2641+0x8>
  40055a:       48 89 44 24 20          mov    %rax,0x20(%rsp)
  40055f:       48 89 54 24 28          mov    %rdx,0x28(%rsp)
  400564:       0f 1f 40 00             nopl   0x0(%rax)
  400568:       0f b6 33                movzbl (%rbx),%esi
  40056b:       31 c0                   xor    %eax,%eax
  40056d:       bf 64 07 40 00          mov    $0x400764,%edi
  400572:       48 83 c3 01             add    $0x1,%rbx
  400576:       e8 95 fe ff ff          callq  400410 <printf@plt>
  40057b:       48 39 dd                cmp    %rbx,%rbp
  40057e:       75 e8                   jne    400568 <main+0x128>
  400580:       bf 0a 00 00 00          mov    $0xa,%edi
  400585:       e8 76 fe ff ff          callq  400400 <putchar@plt>
  40058a:       48 83 c4 48             add    $0x48,%rsp
  40058e:       5b                      pop    %rbx
  40058f:       5d                      pop    %rbp
  400590:       c3                      retq   
  400591:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  400598:       00 00 00 
  40059b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)


Note how the UUIDs are generated on the stack in a very time- and
space-inefficient manner, requiring 64 bytes in the text section instead of
just 16 bytes in rodata.

Note also that this only occurs if the UUIDs are passed to a function by
reference.  If they're passed in by value, as is the case with the calls to
efi_print_guid(), they're put in rodata.  I've also found that if guid1 is
declared static, it can be forced to rodata. But this workaround is not an
option if the compound literal is passed in directly, as in the case of
"efi_print_guid_ptr(&HCDP_TABLE_GUID);".

The C spec says that the compound literal has static storage duration if it
occurs at file scope and automatic storage duration if it occurs at block
scope.  However guid1 is declared const and efi_print_guid_ptr() also declares
the argument const, so there's absolutely no reason to generate the UUID on the
stack at runtime.

Tested with gcc version 6.1.1 20160802 (Debian 6.1.1-11).
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 6.1.1-11'
--with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs
--enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-6 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object
--disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib
--disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-amd64/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-amd64
--with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc --enable-multiarch --with-arch-32=i686 --with-abi=m64
--with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu

Reply via email to