https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79439
Bug ID: 79439 Summary: Missing nop instruction after recursive call corrupts TOC register Product: gcc Version: 6.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: fw at gcc dot gnu.org Target Milestone: --- Target: ppc64le-redhat-linux Consider this test case: int f (void); void g (void) { } void rec (int a) { if (f ()) rec (a + 1); rec (a); g (); } GCC 6.3.1 generates the following code on ppc64le-redhat-linux (Fedora 25): rec: .LCF1: 0: addis 2,12,.TOC.-.LCF1@ha addi 2,2,.TOC.-.LCF1@l .localentry rec,.-rec mflr 0 std 31,-8(1) mr 31,3 std 0,16(1) stdu 1,-48(1) bl f nop cmpdi 7,3,0 beq 7,.L3 addi 3,31,1 extsw 3,3 bl rec .L3: mr 3,31 bl rec bl g nop addi 1,1,48 ld 0,16(1) ld 31,-8(1) mtlr 0 blr .long 0 .byte 0,0,0,1,128,1,0,0 That is, there is no nop instruction the after the “bl rec” instructions. The ELF v2 ABI requires the presence of this instruction, so that the static linker can replace it with a load of the saved TOC pointer to restore the original value of the TOC pointer register. Apparently, GCC assumes that the call is always to a function in the same module, so the TOC pointer restore is never needed. But “rec” can be interposed from another translation unit and the original function definition can be access through dlsym and executed, so this assumption is incorrect. The missing TOC pointer restore means that the PLT stubs supplied by the static linker will not work, and subsequent function calls can crash. This was originally reported as a glibc bug: <https://sourceware.org/bugzilla/show_bug.cgi?id=21116> The test case is LAPACK, which is apparently written in Fortran, but I expect that this is a target issue which exists independent of the front end.