https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81653
Bug ID: 81653 Summary: gcc configured with --enable-default-pie on SPARC miscompiles hand-written .s files Product: gcc Version: 6.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: driver Assignee: unassigned at gcc dot gnu.org Reporter: bruno at clisp dot org Target Milestone: --- Created attachment 41884 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41884&action=edit Test case program, part 1 GCC, configured with --enable-default-pie on SPARC, miscompiles hand-written .s files that happen to access global variables. The cause is that it passes the option "-K PIC" to the assembler; the assembler then interprets the .s file differently (by putting different relocations into the .o file). The resulting executable does not work. Test case: Find attached main.c and getter.s. With a GCC not configured with --enable-default-pie: $ gcc -m32 main.c getter.s $ ./a.out $ echo $? 42 With a GCC configured with --enable-default-pie: $ gcc -m32 main.c getter.s $ ./a.out Segmentation fault $ gdb a.out (gdb) run Starting program: /home/haible/a.out Program received signal SIGSEGV, Segmentation fault. 0x700006c8 in getter () (gdb) disassemble getter Dump of assembler code for function getter: 0x700006c0 <+0>: sethi %hi(0), %g1 0x700006c4 <+4>: or %g1, 0x10, %g1 ! 0x10 => 0x700006c8 <+8>: ld [ %g1 ], %o0 0x700006cc <+12>: retl 0x700006d0 <+16>: nop End of assembler dump. (gdb) print $g1 $1 = 16 Details about this GCC version: $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/sparc64-linux-gnu/6/lto-wrapper Target: sparc64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 6.4.0-2' --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 --program-prefix=sparc64-linux-gnu- --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-libquadmath --enable-plugin --enable-default-pie --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-sparc64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-sparc64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-sparc64 --with-arch-directory=sparc64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc=auto --enable-multiarch --enable-targets=all --with-cpu-32=ultrasparc --with-long-double-128 --enable-multilib --enable-checking=release --build=sparc64-linux-gnu --host=sparc64-linux-gnu --target=sparc64-linux-gnu Thread model: posix gcc version 6.4.0 20170724 (Debian 6.4.0-2) Analysis of the difference between that and this GCC: 1) The "as" invocation was as -v -s -Av9a -32 -relax -o /tmp/cci9hbn2.o getter.s and in this GCC version is as -v -s -K PIC -Av9a -32 -relax -o /tmp/ccYeBhLa.o getter.s 2) The relocations in the object file: That GCC: $ gcc -m32 -c getter.s -o getter.o $ objdump --disassemble --reloc getter.o getter.o: file format elf32-sparc Disassembly of section .text: 00000000 <getter>: 0: 03 00 00 00 sethi %hi(0), %g1 0: R_SPARC_HI22 variable 4: 82 10 60 00 mov %g1, %g1 ! 0 <getter> 4: R_SPARC_LO10 variable 8: d0 00 40 00 ld [ %g1 ], %o0 c: 81 c3 e0 08 retl 10: 01 00 00 00 nop This GCC: $ gcc -m32 -c getter.s -o getter.o $ objdump --disassemble --reloc getter.o getter.o: file format elf32-sparc Disassembly of section .text: 00000000 <getter>: 0: 03 00 00 00 sethi %hi(0), %g1 0: R_SPARC_GOT22 variable 4: 82 10 60 00 mov %g1, %g1 ! 0 <getter> 4: R_SPARC_GOT10 variable 8: d0 00 40 00 ld [ %g1 ], %o0 c: 81 c3 e0 08 retl 10: 01 00 00 00 nop As you can see, the assembler has inserted different relocations with "-K PIC" than without. 3) The instructions in the linked a.out file: That GCC: $ objdump --disassemble a.out 00010480 <main>: 10480: 9d e3 bf a0 save %sp, -96, %sp 10484: 03 00 00 88 sethi %hi(0x22000), %g1 10488: 82 10 60 68 or %g1, 0x68, %g1 ! 22068 <variable> 1048c: 84 10 20 2a mov 0x2a, %g2 10490: c4 20 40 00 st %g2, [ %g1 ] 10494: 40 00 00 06 call 104ac <getter> 10498: 01 00 00 00 nop 1049c: 82 10 00 08 mov %o0, %g1 104a0: b0 10 00 01 mov %g1, %i0 104a4: 81 cf e0 08 rett %i7 + 8 104a8: 01 00 00 00 nop 000104ac <getter>: 104ac: 03 00 00 88 sethi %hi(0x22000), %g1 104b0: 82 10 60 68 or %g1, 0x68, %g1 ! 22068 <variable> 104b4: d0 00 40 00 ld [ %g1 ], %o0 104b8: 81 c3 e0 08 retl 104bc: 01 00 00 00 nop This GCC: $ objdump --disassemble a.out 00000680 <main>: 680: 9d e3 bf a0 save %sp, -96, %sp 684: 2f 00 00 46 sethi %hi(0x11800), %l7 688: ae 05 e1 74 add %l7, 0x174, %l7 ! 11974 <__FRAME_END__+0x111e4> 68c: 7f ff ff 85 call 4a0 <__sparc_get_pc_thunk.l7> 690: 01 00 00 00 nop 694: 03 00 00 00 sethi %hi(0), %g1 698: 82 18 60 9c xor %g1, 0x9c, %g1 69c: 82 05 c0 01 add %l7, %g1, %g1 6a0: 84 10 20 2a mov 0x2a, %g2 6a4: c4 20 40 00 st %g2, [ %g1 ] 6a8: 40 00 00 06 call 6c0 <getter> 6ac: 01 00 00 00 nop 6b0: 82 10 00 08 mov %o0, %g1 6b4: b0 10 00 01 mov %g1, %i0 6b8: 81 cf e0 08 return %i7 + 8 6bc: 01 00 00 00 nop 000006c0 <getter>: 6c0: 03 00 00 00 sethi %hi(0), %g1 6c4: 82 10 60 10 or %g1, 0x10, %g1 ! 10 <_init-0x3e4> 6c8: d0 00 40 00 ld [ %g1 ], %o0 6cc: 81 c3 e0 08 retl 6d0: 01 00 00 00 nop 6d4: 01 00 00 00 nop 6d8: 01 00 00 00 nop 6dc: 01 00 00 00 nop You can see the effect: The 'getter' function no longer references 'variable'.