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