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