This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
RFC: Map GNU attributes section to PT_GNU_STACK segment
- From: "H.J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Tue, 14 Aug 2007 19:51:28 -0700
- Subject: RFC: Map GNU attributes section to PT_GNU_STACK segment
We keep GNU attributes section in executable and shared library. Also
There is a PT_GNU_STACK segment. But only its segment type is used.
This patch maps GNU attributes section to PT_GNU_STACK segment and
makes PT_GNU_ATTRIBUTES an alias of PT_GNU_STACK so that GNU attributes
section is available to ELF loader.
Any comments?
H.J.
----
--- binutils/bfd/elf.c.attri 2007-08-14 12:49:05.000000000 -0700
+++ binutils/bfd/elf.c 2007-08-14 19:43:44.000000000 -0700
@@ -1083,7 +1083,7 @@ get_segment_type (unsigned int p_type)
case PT_PHDR: pt = "PHDR"; break;
case PT_TLS: pt = "TLS"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
- case PT_GNU_STACK: pt = "STACK"; break;
+ case PT_GNU_ATTRIBUTES: pt = "ATTRIBUTES"; break;
case PT_GNU_RELRO: pt = "RELRO"; break;
default: pt = NULL; break;
}
@@ -2359,8 +2359,9 @@ bfd_section_from_phdr (bfd *abfd, Elf_In
return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
"eh_frame_hdr");
- case PT_GNU_STACK:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+ case PT_GNU_ATTRIBUTES:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+ "attributes");
case PT_GNU_RELRO:
return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
@@ -3304,7 +3305,8 @@ get_program_header_size (bfd *abfd, stru
{
size_t segs;
asection *s;
- const struct elf_backend_data *bed;
+ asection *attr = NULL;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
/* Assume we will need exactly two PT_LOAD segments: one for text
and one for data. */
@@ -3339,14 +3341,25 @@ get_program_header_size (bfd *abfd, stru
++segs;
}
- if (elf_tdata (abfd)->stack_flags)
- {
- /* We need a PT_GNU_STACK segment. */
- ++segs;
- }
-
for (s = abfd->sections; s != NULL; s = s->next)
{
+ if (elf_section_type (s) == bed->obj_attrs_section_type)
+ {
+ BFD_ASSERT (attr == NULL);
+ attr = s;
+
+ /* PT_GNU_STACK and PT_GNU_ATTRIBUTES use the same segment.
+ If there is no flags for PT_GNU_STACK, we set it to
+ default. */
+ if (! elf_tdata (abfd)->stack_flags)
+ {
+ if (bed->default_execstack)
+ elf_tdata (abfd)->stack_flags = PF_R | PF_W | PF_X;
+ else
+ elf_tdata (abfd)->stack_flags = PF_R | PF_W;
+ }
+ }
+
if ((s->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s->name, ".note"))
{
@@ -3368,6 +3381,12 @@ get_program_header_size (bfd *abfd, stru
}
}
+ if (elf_tdata (abfd)->stack_flags)
+ {
+ /* We need a PT_GNU_STACK segment. */
+ ++segs;
+ }
+
for (s = abfd->sections; s != NULL; s = s->next)
{
if (s->flags & SEC_THREAD_LOCAL)
@@ -3405,7 +3424,6 @@ get_program_header_size (bfd *abfd, stru
}
/* Let the backend count up any program headers it might need. */
- bed = get_elf_backend_data (abfd);
if (bed->elf_backend_additional_program_headers)
{
int a;
@@ -3552,6 +3570,7 @@ _bfd_elf_map_sections_to_segments (bfd *
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
+ asection *attr = NULL;
/* Select the allocated sections, and sort them. */
@@ -3562,6 +3581,12 @@ _bfd_elf_map_sections_to_segments (bfd *
i = 0;
for (s = abfd->sections; s != NULL; s = s->next)
{
+ if (elf_section_type (s) == bed->obj_attrs_section_type)
+ {
+ BFD_ASSERT (attr == NULL);
+ attr = s;
+ }
+
if ((s->flags & SEC_ALLOC) != 0)
{
sections[i] = s;
@@ -3949,6 +3974,15 @@ _bfd_elf_map_sections_to_segments (bfd *
m->p_flags = elf_tdata (abfd)->stack_flags;
m->p_flags_valid = 1;
+ if (attr)
+ {
+ /* PT_GNU_ATTRIBUTES uses the same segment as
+ PT_GNU_STACK. If there is attribute asection,
+ add it for PT_GNU_ATTRIBUTES segment. */
+ m->count = 1;
+ m->sections[0] = attr;
+ }
+
*pm = m;
pm = &m->next;
}
@@ -5178,31 +5212,34 @@ rewrite_elf_program_header (bfd *ibfd, b
2. It is an allocated segment,
3. There is an output section associated with it,
4. The section has not already been allocated to a previous segment.
- 5. PT_GNU_STACK segments do not include any sections.
+ 5. PT_GNU_STACK and PT_GNU_ATTRIBUTES use thes same segment,
+ which contains attribute section.
6. PT_TLS segment includes only SHF_TLS sections.
7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.
8. PT_DYNAMIC should not contain empty sections at the beginning
(with the possible exception of .dynamic). */
#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed) \
- ((((segment->p_paddr \
- ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
- : IS_CONTAINED_BY_VMA (section, segment)) \
- && (section->flags & SEC_ALLOC) != 0) \
- || IS_COREFILE_NOTE (segment, section)) \
- && segment->p_type != PT_GNU_STACK \
- && (segment->p_type != PT_TLS \
- || (section->flags & SEC_THREAD_LOCAL)) \
- && (segment->p_type == PT_LOAD \
- || segment->p_type == PT_TLS \
- || (section->flags & SEC_THREAD_LOCAL) == 0) \
- && (segment->p_type != PT_DYNAMIC \
- || SECTION_SIZE (section, segment) > 0 \
- || (segment->p_paddr \
- ? segment->p_paddr != section->lma \
- : segment->p_vaddr != section->vma) \
- || (strcmp (bfd_get_section_name (ibfd, section), ".dynamic") \
- == 0)) \
- && ! section->segment_mark)
+ ((segment->p_type == PT_GNU_ATTRIBUTES \
+ && elf_section_type (section) == bed->obj_attrs_section_type) \
+ || ((((segment->p_paddr \
+ ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
+ : IS_CONTAINED_BY_VMA (section, segment)) \
+ && (section->flags & SEC_ALLOC) != 0) \
+ || IS_COREFILE_NOTE (segment, section)) \
+ && segment->p_type != PT_GNU_STACK \
+ && (segment->p_type != PT_TLS \
+ || (section->flags & SEC_THREAD_LOCAL)) \
+ && (segment->p_type == PT_LOAD \
+ || segment->p_type == PT_TLS \
+ || (section->flags & SEC_THREAD_LOCAL) == 0) \
+ && (segment->p_type != PT_DYNAMIC \
+ || SECTION_SIZE (section, segment) > 0 \
+ || (segment->p_paddr \
+ ? segment->p_paddr != section->lma \
+ : segment->p_vaddr != section->vma) \
+ || (strcmp (bfd_get_section_name (ibfd, section), \
+ ".dynamic") == 0)) \
+ && ! section->segment_mark))
/* If the output section of a section in the input segment is NULL,
it is removed from the corresponding output segment. */
--- binutils/binutils/readelf.c.attri 2007-08-14 12:49:05.000000000 -0700
+++ binutils/binutils/readelf.c 2007-08-14 19:44:22.000000000 -0700
@@ -2470,7 +2470,8 @@ get_segment_type (unsigned long p_type)
case PT_GNU_EH_FRAME:
return "GNU_EH_FRAME";
- case PT_GNU_STACK: return "GNU_STACK";
+ case PT_GNU_ATTRIBUTES:
+ return "GNU_ATTRIBUTES";
case PT_GNU_RELRO: return "GNU_RELRO";
default:
--- binutils/include/elf/common.h.attri 2007-08-14 12:49:05.000000000 -0700
+++ binutils/include/elf/common.h 2007-08-14 16:45:19.000000000 -0700
@@ -308,6 +308,7 @@
#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) /* Frame unwind information */
#define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME /* Solaris uses the same value */
#define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */
+#define PT_GNU_ATTRIBUTES PT_GNU_STACK /* Attribute flags */
#define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */
#define PT_GNU_SHR (PT_LOOS + 0x474e554) /* Sharable segment */