https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119609
Bug ID: 119609 Summary: [powerpc-elf] load_toc_v4_pic_si may clobber r12 and crt Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: aoliva at gcc dot gnu.org Target Milestone: --- A buggy linker script placed .got too far from .text and triggered a latent bug. A small leaf function that needed the got register to compute the address of a global symbol (say intptr_t foo (void) { return (intptr_t)foo; }) ended up with the following got setup sequence: mflr 12 .cfi_register 65, 12 bl _GLOBAL_OFFSET_TABLE_@local-4 mflr 30 mtlr 12 .cfi_restore 65 it is rs6000_emit_prologue, under save_LR_around_toc_setup, that chooses r12: /* If emit_load_toc_table will use the link register, we need to save it. We use R12 for this purpose because emit_load_toc_table can use register 0. The problem is that, when the bl above needs relaxation, the relaxation stubs introduced by the linker, whether for shared or static linking, always clobber r12 and crt, and in the shared case, r0 as well: /* Relaxation trampolines. r12 is available for clobbering (r11, is used for some functions that are allowed to break the ABI). */ static const int shared_stub_entry[] = { 0x7c0802a6, /* mflr 0 */ 0x429f0005, /* bcl 20, 31, .Lxxx */ 0x7d8802a6, /* mflr 12 */ 0x3d8c0000, /* addis 12, 12, (xxx-.Lxxx)@ha */ 0x398c0000, /* addi 12, 12, (xxx-.Lxxx)@l */ 0x7c0803a6, /* mtlr 0 */ 0x7d8903a6, /* mtctr 12 */ 0x4e800420, /* bctr */ }; static const int stub_entry[] = { 0x3d800000, /* lis 12,xxx@ha */ 0x398c0000, /* addi 12,12,xxx@l */ 0x7d8903a6, /* mtctr 12 */ 0x4e800420, /* bctr */ }; Of course adding clobbers to load_toc_v4_pic_si is not enough, the lr save/restore needs to choose a different register too. In the end, fixing the linker script worked around the problem, so I'm not sure I can justify spending further time on this fix, but hopefully I'll be able to return to it at some point. Anyway, I'm filing this in case someone else feels like beating me to the fix.