[PATCH] ld: Handle special ELF readonly output sections
H.J. Lu
hjl.tools@gmail.com
Tue Mar 31 18:15:27 GMT 2026
There are many special ELF sections which should be readonly. But output
sections created in linker script won't set the SEC_READONLY if they
aren't marked with READONLY. Add bfd_is_special_readonly_section to
return true if a section name is a special ELF readonly section and use
it when creating output sections.
bfd/
PR ld/34024
* bfd-in2.h: Regenerated.
* bfd.c (bfd_is_special_readonly_section): New function.
* elf-bfd.h (elf_backend_data): Add is_special_readonly_section.
(_bfd_elf_is_special_readonly_section): New prototype.
* elf.c (elf_get_special_section): New function.
(_bfd_elf_get_sec_type_attr): Call elf_get_special_section.
(_bfd_elf_is_special_readonly_section): New function.
* elfxx-target.h (elf_backend_is_special_readonly_section): New.
(elfNN_bed): Add elf_backend_is_special_readonly_section.
ld/
PR ld/34024
* ldlang.c (get_os_init_flag): Return SEC_READONLY if the output
section is a special readonly section.
* testsuite/ld-elf/flags2.d: New file.
* testsuite/ld-elf/flags2.ld: Likewise.
* testsuite/ld-elf/flags2.s: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
bfd/bfd-in2.h | 2 ++
bfd/bfd.c | 24 ++++++++++++++++++++++++
bfd/elf-bfd.h | 7 +++++++
bfd/elf.c | 35 ++++++++++++++++++++++++++---------
bfd/elfxx-target.h | 5 +++++
ld/ldlang.c | 5 ++++-
ld/testsuite/ld-elf/flags2.d | 9 +++++++++
ld/testsuite/ld-elf/flags2.ld | 1 +
ld/testsuite/ld-elf/flags2.s | 6 ++++++
9 files changed, 84 insertions(+), 10 deletions(-)
create mode 100644 ld/testsuite/ld-elf/flags2.d
create mode 100644 ld/testsuite/ld-elf/flags2.ld
create mode 100644 ld/testsuite/ld-elf/flags2.s
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 0b934005f9d..70659dfe824 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2818,6 +2818,8 @@ char *bfd_demangle (bfd *, const char *, int);
asymbol *bfd_group_signature (asection *group, asymbol **isympp);
+bool bfd_is_special_readonly_section (bfd *abfd, const char *name);
+
/* Extracted from bfdio.c. */
bfd_size_type bfd_read (void *, bfd_size_type, bfd *)
ATTRIBUTE_WARN_UNUSED_RESULT;
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 31c70890ad9..a198eb8002f 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -3133,3 +3133,27 @@ bfd_group_signature (asection *group, asymbol **isympp)
}
return NULL;
}
+
+/*
+FUNCTION
+ bfd_is_special_readonly_section
+
+SYNOPSIS
+ bool bfd_is_special_readonly_section (bfd *abfd, const char *name);
+
+DESCRIPTION
+ Return true if the BFD section of NAME is a special readonly
+ section.
+*/
+
+bool
+bfd_is_special_readonly_section (bfd *abfd, const char *name)
+{
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ {
+ elf_backend_data *bed = get_elf_backend_data (abfd);
+ return bed->is_special_readonly_section (abfd, name);
+ }
+
+ return false;
+}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 3d2fad49aa4..cb4745166de 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1127,6 +1127,11 @@ struct elf_backend_data
const struct bfd_elf_special_section * (*get_sec_type_attr)
(bfd *, asection *);
+ /* A function that returns true if the given BFD section of name
+ is a special readonly section. */
+ bool (*is_special_readonly_section)
+ (bfd *, const char*);
+
/* A function to handle unusual program segment types when creating BFD
sections from ELF program segments. */
bool (*elf_backend_section_from_phdr)
@@ -2542,6 +2547,8 @@ extern const struct bfd_elf_special_section *_bfd_elf_get_special_section
ATTRIBUTE_HIDDEN;
extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr
(bfd *, asection *) ATTRIBUTE_HIDDEN;
+extern bool _bfd_elf_is_special_readonly_section
+ (bfd *, const char *) ATTRIBUTE_HIDDEN;
extern bool _bfd_elf_link_hide_sym_by_version
(struct bfd_link_info *, struct elf_link_hash_entry *) ATTRIBUTE_HIDDEN;
diff --git a/bfd/elf.c b/bfd/elf.c
index 5f02188b4b5..db7c5620337 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3275,32 +3275,31 @@ _bfd_elf_get_special_section (const char *name,
return NULL;
}
-const struct bfd_elf_special_section *
-_bfd_elf_get_sec_type_attr (bfd *abfd, asection *sec)
+static const struct bfd_elf_special_section *
+elf_get_special_section (bfd *abfd, const char *name,
+ unsigned int use_rela_p)
{
int i;
const struct bfd_elf_special_section *spec;
elf_backend_data *bed;
/* See if this is one of the special sections. */
- if (sec->name == NULL)
+ if (name == NULL)
return NULL;
bed = get_elf_backend_data (abfd);
spec = bed->special_sections;
if (spec)
{
- spec = _bfd_elf_get_special_section (sec->name,
- bed->special_sections,
- sec->use_rela_p);
+ spec = _bfd_elf_get_special_section (name, spec, use_rela_p);
if (spec != NULL)
return spec;
}
- if (sec->name[0] != '.')
+ if (name[0] != '.')
return NULL;
- i = sec->name[1] - 'b';
+ i = name[1] - 'b';
if (i < 0 || i > 'z' - 'b')
return NULL;
@@ -3309,7 +3308,25 @@ _bfd_elf_get_sec_type_attr (bfd *abfd, asection *sec)
if (spec == NULL)
return NULL;
- return _bfd_elf_get_special_section (sec->name, spec, sec->use_rela_p);
+ return _bfd_elf_get_special_section (name, spec, use_rela_p);
+}
+
+const struct bfd_elf_special_section *
+_bfd_elf_get_sec_type_attr (bfd *abfd, asection *sec)
+{
+ return elf_get_special_section (abfd, sec->name, sec->use_rela_p);
+}
+
+bool
+_bfd_elf_is_special_readonly_section (bfd *abfd, const char *name)
+{
+ elf_backend_data *bed;
+ const struct bfd_elf_special_section *spec;
+ bed = get_elf_backend_data (abfd);
+ spec = elf_get_special_section (abfd, name, bed->default_use_rela_p);
+ if (spec == NULL)
+ return false;
+ return (spec->attr & SHF_WRITE) == 0;
}
bool
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 124be5ed0c4..580276a543b 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -443,6 +443,10 @@
#ifndef elf_backend_get_sec_type_attr
#define elf_backend_get_sec_type_attr _bfd_elf_get_sec_type_attr
#endif
+#ifndef elf_backend_is_special_readonly_section
+#define elf_backend_is_special_readonly_section \
+ _bfd_elf_is_special_readonly_section
+#endif
#ifndef elf_backend_section_from_phdr
#define elf_backend_section_from_phdr _bfd_elf_make_section_from_phdr
#endif
@@ -872,6 +876,7 @@ static const struct elf_backend_data elfNN_bed =
elf_backend_section_from_shdr,
elf_backend_section_flags,
elf_backend_get_sec_type_attr,
+ elf_backend_is_special_readonly_section,
elf_backend_section_from_phdr,
elf_backend_fake_sections,
elf_backend_section_from_bfd_section,
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 656edeb4981..b6d19e95401 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2604,7 +2604,10 @@ get_os_init_flag (lang_output_section_statement_type * os)
{
case readonly_section: return SEC_READONLY;
case noload_section: return SEC_NEVER_LOAD;
- default: break;
+ default:
+ if (bfd_is_special_readonly_section (link_info.output_bfd,
+ os->name))
+ return SEC_READONLY;
}
return 0;
diff --git a/ld/testsuite/ld-elf/flags2.d b/ld/testsuite/ld-elf/flags2.d
new file mode 100644
index 00000000000..5fc8571d9dc
--- /dev/null
+++ b/ld/testsuite/ld-elf/flags2.d
@@ -0,0 +1,9 @@
+#name: .rodata section attributes
+#ld: -Tflags2.ld
+#readelf: -S --wide
+
+#...
+Section Headers:
+#...
+ \[[ 0-9]+\] \.rodata.*[ \t]+PROGBITS[ \t0-9a-f]+ A .*
+#pass
diff --git a/ld/testsuite/ld-elf/flags2.ld b/ld/testsuite/ld-elf/flags2.ld
new file mode 100644
index 00000000000..90eeca713e7
--- /dev/null
+++ b/ld/testsuite/ld-elf/flags2.ld
@@ -0,0 +1 @@
+SECTIONS { .rodata : ALIGN(4) { __crc_hello = .; LONG(0x05d25769); } }
diff --git a/ld/testsuite/ld-elf/flags2.s b/ld/testsuite/ld-elf/flags2.s
new file mode 100644
index 00000000000..c5dbfbf0a2f
--- /dev/null
+++ b/ld/testsuite/ld-elf/flags2.s
@@ -0,0 +1,6 @@
+ .text
+ .globl start
+ .type start, %function
+start:
+ .byte 0
+ .section .note.GNU-stack, "", %progbits
--
2.53.0
More information about the Binutils
mailing list