summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2006-06-11 00:20:43 +0000
committerUlrich Drepper <drepper@redhat.com>2006-06-11 00:20:43 +0000
commit2d88028a7b30d9e9be8e5af089cd6dcc22f80ce1 (patch)
tree5a10d1118c2d8d0d696c6b83c796c77ed7c30414
parent697f4db2f34c054a2f93b45dbdbbaec82e34a409 (diff)
downloadelfutils-2d88028a7b30d9e9be8e5af089cd6dcc22f80ce1.tar.gz
Implement -z execstack/noexecstack options.
-rw-r--r--src/ChangeLog9
-rw-r--r--src/ld.c4
-rw-r--r--src/ld.h8
-rw-r--r--src/ldgeneric.c46
4 files changed, 65 insertions, 2 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index fb4e011d..8bfd20c4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
+2006-06-10 Ulrich Drepper <drepper@redhat.com>
+
+ * ld.c (parse_z_option): Recognize execstack and noexecstack.
+ * ld.h (struct ld_state): Add execstack field.
+ * ldgeneric.c (add_relocatable_file): Recognize .note.GNU-stack
+ sections.
+ (ld_generic_create_outfile): Fix program header creation in native
+ linker. Add PT_GNU_STACK program header.
+
2006-06-09 Ulrich Drepper <drepper@redhat.com>
* i386_ld.c (elf_i386_finalize_plt): Don't change symbol table entries
diff --git a/src/ld.c b/src/ld.c
index 53386569..79efb3ac 100644
--- a/src/ld.c
+++ b/src/ld.c
@@ -931,6 +931,10 @@ parse_z_option (const char *arg)
ld_state.as_needed = false;
else if (strcmp (arg, "systemlibrary") == 0)
ld_state.is_system_library = true;
+ else if (strcmp (arg, "execstack") == 0)
+ ld_state.execstack = execstack_true;
+ else if (strcmp (arg, "noexecstack") == 0)
+ ld_state.execstack = execstack_false_force;
else if (strcmp (arg, "allextract") != 0
&& strcmp (arg, "defaultextract") != 0
&& strcmp (arg, "weakextract") != 0
diff --git a/src/ld.h b/src/ld.h
index 6e8e7b5f..1d964814 100644
--- a/src/ld.h
+++ b/src/ld.h
@@ -956,6 +956,14 @@ struct ld_state
bool default_bind_local;
bool default_bind_global;
+ /* Execuatable stack selection. */
+ enum execstack
+ {
+ execstack_false = 0,
+ execstack_true,
+ execstack_false_force
+ } execstack;
+
/* True if only used sections are used. */
bool gc_sections;
diff --git a/src/ldgeneric.c b/src/ldgeneric.c
index 6cad1ac7..07cf3e19 100644
--- a/src/ldgeneric.c
+++ b/src/ldgeneric.c
@@ -1028,6 +1028,9 @@ add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype)
size_t nsymbols = 0;
size_t nlocalsymbols = 0;
bool has_merge_sections = false;
+ /* Unless we have different information we assume the code needs
+ an executable stack. */
+ enum execstack execstack = execstack_true;
/* Prerequisites. */
assert (fileinfo->elf != NULL);
@@ -1234,9 +1237,29 @@ add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype)
|| shdr->sh_type == SHT_INIT_ARRAY
|| shdr->sh_type == SHT_FINI_ARRAY
|| shdr->sh_type == SHT_PREINIT_ARRAY))
- add_section (fileinfo, &fileinfo->scninfo[cnt]);
+ {
+ /* Check whether the check needs to be executable. */
+ if (shdr->sh_type == SHT_PROGBITS
+ && strcmp (elf_strptr (fileinfo->elf, fileinfo->shstrndx,
+ shdr->sh_name),
+ ".note.GNU-stack") == 0
+ && (shdr->sh_flags & SHF_EXECINSTR) == 0)
+ execstack = execstack_false;
+ printf("%s %d\n", elf_strptr (fileinfo->elf, fileinfo->shstrndx,
+ shdr->sh_name),(int)execstack);
+
+ add_section (fileinfo, &fileinfo->scninfo[cnt]);
+ }
}
+ /* Now we know more about the requirements for an executable stack
+ of the result. */
+ if (fileinfo->file_type == relocatable_file_type
+ && execstack == execstack_true
+ && ld_state.execstack != execstack_false_force)
+ ld_state.execstack = execstack_true;
+ printf("%s: state = %d\n", fileinfo->fname,(int)ld_state.execstack);
+
/* Handle the symbols. Record defined and undefined symbols in the
hash table. In theory there can be a file without any symbol
table. */
@@ -5573,6 +5596,10 @@ cannot create hash table section for output file: %s"),
XXX Determine whether the segment is non-empty. */
nphdr = 0;
+
+ /* We always add a PT_GNU_stack entry. */
+ ++nphdr;
+
segment = ld_state.output_segments;
while (segment != NULL)
{
@@ -5772,7 +5799,7 @@ internal error: nobits section follows nobits section"));
xelf_getehdr (ld_state.outelf, ehdr);
assert (ehdr != NULL);
- xelf_getphdr_ptr (ld_state.outelf, 1, phdr);
+ xelf_getphdr_ptr (ld_state.outelf, 0, phdr);
phdr->p_type = PT_PHDR;
phdr->p_offset = ehdr->e_phoff;
phdr->p_vaddr = ld_state.output_segments->addr + phdr->p_offset;
@@ -5784,6 +5811,21 @@ internal error: nobits section follows nobits section"));
(void) xelf_update_phdr (ld_state.outelf, 0, phdr);
+ /* Add the stack information. */
+ xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr);
+ phdr->p_type = PT_GNU_STACK;
+ phdr->p_offset = 0;
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = 0;
+ phdr->p_memsz = 0;
+ phdr->p_flags = ld_state.execstack == execstack_true ? PF_X : 0;
+ phdr->p_align = 0;
+
+ (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr);
+ ++nphdr;
+
+
/* Adjust the addresses in the address fields of the symbol
records according to the load addresses of the sections. */
if (ld_state.need_symtab)