aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-23 05:05:48 +0000
committerIan Lance Taylor <iant@google.com>2007-10-23 05:05:48 +0000
commit35cdfc9a874553807400007ffa36cf2884ba40f6 (patch)
tree2cb1c5ca78a50b21d20e709d9d066fad27f1f6e5 /gold/layout.cc
parent5cab6006497314f0d6785c5a5898be9f28713c72 (diff)
downloadgdb-35cdfc9a874553807400007ffa36cf2884ba40f6.zip
gdb-35cdfc9a874553807400007ffa36cf2884ba40f6.tar.gz
gdb-35cdfc9a874553807400007ffa36cf2884ba40f6.tar.bz2
Add support for PT_GNU_STACK.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc86
1 files changed, 79 insertions, 7 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index ae2b23f..22d3b59 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -67,7 +67,10 @@ Layout::Layout(const General_options& options)
unattached_section_list_(), special_output_list_(),
tls_segment_(NULL), symtab_section_(NULL),
dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
- eh_frame_section_(NULL), output_file_size_(-1)
+ eh_frame_section_(NULL), output_file_size_(-1),
+ input_requires_executable_stack_(false),
+ input_with_gnu_stack_note_(false),
+ input_without_gnu_stack_note_(false)
{
// Make space for more than enough segments for a typical file.
// This is just for efficiency--it's OK if we wind up needing more.
@@ -404,6 +407,27 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
return os;
}
+// Handle the .note.GNU-stack section at layout time. SEEN_GNU_STACK
+// is whether we saw a .note.GNU-stack section in the object file.
+// GNU_STACK_FLAGS is the section flags. The flags give the
+// protection required for stack memory. We record this in an
+// executable as a PT_GNU_STACK segment. If an object file does not
+// have a .note.GNU-stack segment, we must assume that it is an old
+// object. On some targets that will force an executable stack.
+
+void
+Layout::layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags)
+{
+ if (!seen_gnu_stack)
+ this->input_without_gnu_stack_note_ = true;
+ else
+ {
+ this->input_with_gnu_stack_note_ = true;
+ if ((gnu_stack_flags & elfcpp::SHF_EXECINSTR) != 0)
+ this->input_requires_executable_stack_ = true;
+ }
+}
+
// Create the dynamic sections which are needed before we read the
// relocs.
@@ -542,7 +566,8 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
target->finalize_sections(this);
- this->create_note_section();
+ this->create_gold_note();
+ this->create_executable_stack_info(target);
Output_segment* phdr_seg = NULL;
if (!parameters->doing_static_link())
@@ -635,7 +660,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
// records the version of gold used to create the binary.
void
-Layout::create_note_section()
+Layout::create_gold_note()
{
if (parameters->output_is_object())
return;
@@ -651,7 +676,7 @@ Layout::create_note_section()
// version 2.16.91), and glibc always generates the latter for
// .note.ABI-tag (as of version 1.6), so that's the one we go with
// here.
-#ifdef GABI_FORMAT_FOR_DOTNOTE_SECTION // this is not defined by default
+#ifdef GABI_FORMAT_FOR_DOTNOTE_SECTION // This is not defined by default.
const int size = parameters->get_size();
#else
const int size = 32;
@@ -719,6 +744,54 @@ Layout::create_note_section()
os->add_output_section_data(posd);
}
+// Record whether the stack should be executable. This can be set
+// from the command line using the -z execstack or -z noexecstack
+// options. Otherwise, if any input file has a .note.GNU-stack
+// section with the SHF_EXECINSTR flag set, the stack should be
+// executable. Otherwise, if at least one input file a
+// .note.GNU-stack section, and some input file has no .note.GNU-stack
+// section, we use the target default for whether the stack should be
+// executable. Otherwise, we don't generate a stack note. When
+// generating a object file, we create a .note.GNU-stack section with
+// the appropriate marking. When generating an executable or shared
+// library, we create a PT_GNU_STACK segment.
+
+void
+Layout::create_executable_stack_info(const Target* target)
+{
+ bool is_stack_executable;
+ if (this->options_.is_execstack_set())
+ is_stack_executable = this->options_.is_stack_executable();
+ else if (!this->input_with_gnu_stack_note_)
+ return;
+ else
+ {
+ if (this->input_requires_executable_stack_)
+ is_stack_executable = true;
+ else if (this->input_without_gnu_stack_note_)
+ is_stack_executable = target->is_default_stack_executable();
+ else
+ is_stack_executable = false;
+ }
+
+ if (parameters->output_is_object())
+ {
+ const char* name = this->namepool_.add(".note.GNU-stack", false, NULL);
+ elfcpp::Elf_Xword flags = 0;
+ if (is_stack_executable)
+ flags |= elfcpp::SHF_EXECINSTR;
+ this->make_output_section(name, elfcpp::SHT_PROGBITS, flags);
+ }
+ else
+ {
+ int flags = elfcpp::PF_R | elfcpp::PF_W;
+ if (is_stack_executable)
+ flags |= elfcpp::PF_X;
+ Output_segment* oseg = new Output_segment(elfcpp::PT_GNU_STACK, flags);
+ this->segment_list_.push_back(oseg);
+ }
+}
+
// Return whether SEG1 should be before SEG2 in the output file. This
// is based entirely on the segment type and flags. When this is
// called the segment addresses has normally not yet been set.
@@ -1126,9 +1199,8 @@ Layout::create_dynamic_symtab(const Target* target, Symbol_table* symtab,
// FIXME: We have to tell set_dynsym_indexes whether the
// -E/--export-dynamic option was used.
- index = symtab->set_dynsym_indexes(&this->options_, target, index,
- pdynamic_symbols, &this->dynpool_,
- pversions);
+ index = symtab->set_dynsym_indexes(target, index, pdynamic_symbols,
+ &this->dynpool_, pversions);
int symsize;
unsigned int align;