diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-02-26 17:55:07 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-02-26 17:55:07 +0100 |
commit | 1931c40364bb9fb0a7c4b650917e3ac0e88bf6f4 (patch) | |
tree | 07bd9c137f76ae5287cbbb01e3a8e4c7c3d12595 /gcc/varasm.cc | |
parent | 77576915cfd26e603aba5295dfdac54a5545f5f2 (diff) | |
download | gcc-1931c40364bb9fb0a7c4b650917e3ac0e88bf6f4.zip gcc-1931c40364bb9fb0a7c4b650917e3ac0e88bf6f4.tar.gz gcc-1931c40364bb9fb0a7c4b650917e3ac0e88bf6f4.tar.bz2 |
varasm: Handle private COMDAT function symbol reference in readonly data section [PR113617]
If default_elf_select_rtx_section is called to put a reference to some
local symbol defined in a comdat section into memory, which happens more often
since the r14-4944 RA change, linking might fail.
default_elf_select_rtx_section puts such constants into .data.rel.ro.local
etc. sections and if linker chooses comdat sections from some other TU
and discards the one to which a relocation in .data.rel.ro.local remains,
linker diagnoses error. References to private comdat symbols can only appear
from functions or data objects in the same comdat group, so the following
patch arranges using .data.rel.ro.local.pool.<comdat_name> and similar sections.
2024-02-26 Jakub Jelinek <jakub@redhat.com>
H.J. Lu <hjl.tools@gmail.com>
PR rtl-optimization/113617
* varasm.cc (default_elf_select_rtx_section): For
references to private symbols in comdat sections
use .data.relro.local.pool.<comdat>, .data.relro.pool.<comdat>
or .rodata.<comdat> comdat sections.
* g++.dg/other/pr113617.C: New test.
* g++.dg/other/pr113617.h: New test.
* g++.dg/other/pr113617-aux.cc: New test.
Diffstat (limited to 'gcc/varasm.cc')
-rw-r--r-- | gcc/varasm.cc | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/gcc/varasm.cc b/gcc/varasm.cc index 008d9b1..747f74b 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -7458,17 +7458,63 @@ default_elf_select_rtx_section (machine_mode mode, rtx x, unsigned HOST_WIDE_INT align) { int reloc = compute_reloc_for_rtx (x); + tree decl = nullptr; + const char *prefix = nullptr; + int flags = 0; + + /* If it is a private COMDAT function symbol reference, call + function_rodata_section for the read-only or relocated read-only + data section associated with function DECL so that the COMDAT + section will be used for the private COMDAT function symbol. */ + if (HAVE_COMDAT_GROUP) + { + if (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == PLUS + && CONST_INT_P (XEXP (XEXP (x, 0), 1))) + x = XEXP (XEXP (x, 0), 0); + + if (GET_CODE (x) == SYMBOL_REF) + { + decl = SYMBOL_REF_DECL (x); + if (decl + && (TREE_CODE (decl) != FUNCTION_DECL + || !DECL_COMDAT_GROUP (decl) + || TREE_PUBLIC (decl))) + decl = nullptr; + } + } /* ??? Handle small data here somehow. */ if (reloc & targetm.asm_out.reloc_rw_mask ()) { - if (reloc == 1) + if (decl) + { + prefix = reloc == 1 ? ".data.rel.ro.local" : ".data.rel.ro"; + flags = SECTION_WRITE | SECTION_RELRO; + } + else if (reloc == 1) return get_named_section (NULL, ".data.rel.ro.local", 1); else return get_named_section (NULL, ".data.rel.ro", 3); } + if (decl) + { + const char *comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl)); + if (!prefix) + prefix = ".rodata"; + size_t prefix_len = strlen (prefix); + size_t comdat_len = strlen (comdat); + size_t len = prefix_len + sizeof (".pool.") + comdat_len; + char *name = XALLOCAVEC (char, len); + memcpy (name, prefix, prefix_len); + memcpy (name + prefix_len, ".pool.", sizeof (".pool.") - 1); + memcpy (name + prefix_len + sizeof (".pool.") - 1, comdat, + comdat_len + 1); + return get_section (name, flags | SECTION_LINKONCE, decl); + } + return mergeable_constant_section (mode, align, 0); } |