https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112408
Bug ID: 112408 Summary: [12/13/14 regression] d21 loops in getCpuInfo0B in Solaris/x86 kernel zone Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: d Assignee: ibuclaw at gdcproject dot org Reporter: ro at gcc dot gnu.org Target Milestone: --- Host: i386-pc-solaris2.11, x86_64-pc-linux-gnu Target: i386-pc-solaris2.11, x86_64-pc-linux-gnu Build: i386-pc-solaris2.11, x86_64-pc-linux-gnu While preparing GCC builds for a new Solaris 11.4/x86 GCC CFarm system, I re-ran into an issue with D programs looping inside a Solaris kernel zone (a VM), while the same binaries work fine on bare metal. I've now managed to root-cause the issue. When bootstrapping e.g. GCC 13 with GCC 9.5.0 or 11.4.0, configuring libphobos in stage 1 loops. This can be reproduced with $ cat conftest.d module object; extern(C) int main() { return 0; } $ d21 conftest.d which loops indefinitely. d21 show the following stacktrace: Thread 2 received signal SIGINT, Interrupt. [Switching to Thread 1 (LWP 1)] _D4core5cpuid12getCpuInfo0BFNbNiNeZv () at gcc-11.4.0/libphobos/libdruntime/core/cpuid.d:669 669 if (b!=0) { 1: x/i $pc => 0x442b311 <_D4core5cpuid12getCpuInfo0BFNbNiNeZv+33>: test %ebx,%ebx (gdb) bt #0 _D4core5cpuid12getCpuInfo0BFNbNiNeZv () at gcc-11.4.0/libphobos/libdruntime/core/cpuid.d:669 #1 0x000000000442b7e3 in _D4core5cpuid8cpuidX86FNbNiNeZv () at gcc-11.4.0/libphobos/libdruntime/core/cpuid.d:953 #2 0x000000000442bd75 in _D4core5cpuid18_sharedStaticCtor1FNbNiNeZv () at gcc-11.4.0/libphobos/libdruntime/core/cpuid.d:1073 #3 0x000000000441a421 in runModuleFuncs (this=0x0, modules=...) at gcc-11.4.0/libphobos/libdruntime/rt/minfo.d:858 #4 _D2rt5minfo11ModuleGroup8runCtorsMFZv (this=...) at gcc-11.4.0/libphobos/libdruntime/rt/minfo.d:728 #5 0x000000000441b5bd in __foreachbody1 (this=<optimized out>, sg=...) at gcc-11.4.0/libphobos/libdruntime/rt/minfo.d:796 #6 0x000000000440ffd2 in _D3gcc8sections3elf3DSO7opApplyFMDFKSQBjQBiQBcQBbZiZi (dg=...) at gcc-11.4.0/libphobos/libdruntime/gcc/sections/elf.d:106 #7 0x000000000441a61e in rt_moduleCtor () at gcc-11.4.0/libphobos/libdruntime/rt/minfo.d:793 #8 0x000000000440f880 in rt_init () at gcc-11.4.0/libphobos/libdruntime/rt/dmain2.d:129 #9 0x00000000022f4c16 in d_init_options (decoded_options=0x47e1f00) at gcc-13.2.0/gcc/d/d-lang.cc:290 #10 0x0000000002ac5fbc in toplev::main (this=0x7fffbffff97a, argc=2, argv=0x7fffbffff9b8) at gcc-13.2.0/gcc/toplev.cc:2240 #11 0x0000000004301c46 in main (argc=2, argv=0x7fffbffff9b8) at gcc-13.2.0/gcc/main.cc:39 Running getCpuInfo0B side-by-side in the kernel zone and on bare metal shows: kernel zone bare metal level 0 a 0 1 b 1 2 level 1 a 0 5 b 1 28 level 2 a 0 0 b 1 0 and so on for each higher level. So inside a kernel zone, a!=0 || b!=0 remains true, explaining the loop. If I'm reading the spec (Intel® 64 and IA-32 Architectures Software Developer’s Manual, Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4, Order Number: 325462-081US, September 2023, Vol. 2A, 3-225, p.821) correctly, this is a bug in the kernel zone software: A sub-leaf returning an invalid domain always returns 0 in EAX and EBX. OTOH I don't see why getCpuInfo0B needs to loop here since it's only interested in levels 0 and 1 anyway. This affects all DMD-based versions of GDC, while the previous C++-based versions are fine.