// symbol table.
void
-Versions::record_version(const General_options* options,
- const Symbol_table* symtab,
+Versions::record_version(const Symbol_table* symtab,
Stringpool* dynpool, const Symbol* sym)
{
gold_assert(!this->is_finalized_);
if (!sym->is_from_dynobj() && !sym->is_copied_from_dynobj())
{
if (parameters->output_is_shared())
- this->add_def(options, sym, version, version_key);
+ this->add_def(sym, version, version_key);
}
else
{
// We've found a symbol SYM defined in version VERSION.
void
-Versions::add_def(const General_options* options, const Symbol* sym,
- const char* version, Stringpool::Key version_key)
+Versions::add_def(const Symbol* sym, const char* version,
+ Stringpool::Key version_key)
{
Key k(version_key, 0);
Version_base* const vbnull = NULL;
// If this is the first version we are defining, first define
// the base version. FIXME: Should use soname here when
// creating a shared object.
- Verdef* vdbase = new Verdef(options->output_file_name(), true, false,
+ Verdef* vdbase = new Verdef(parameters->output_file_name(), true, false,
true);
this->defs_.push_back(vdbase);
// SYM is going into the dynamic symbol table and has a version.
// Record the appropriate version information.
void
- record_version(const General_options*, const Symbol_table* symtab,
- Stringpool*, const Symbol* sym);
+ record_version(const Symbol_table* symtab, Stringpool*, const Symbol* sym);
// Set the version indexes. DYNSYM_INDEX is the index we should use
// for the next dynamic symbol. We add new dynamic symbols to SYMS
// Handle a symbol SYM defined with version VERSION.
void
- add_def(const General_options*, const Symbol* sym, const char* version,
- Stringpool::Key);
+ add_def(const Symbol* sym, const char* version, Stringpool::Key);
// Add a reference to version NAME in file FILENAME.
void
false, // has_make_symbol
false, // has_resolve
true, // has_code_fill
+ true, // is_default_stack_executable
"/usr/lib/libc.so.1", // dynamic_linker
0x08048000, // default_text_segment_address
0x1000, // abi_pagesize
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.
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.
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())
// 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;
// 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;
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.
// 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;
layout(Relobj *object, unsigned int shndx, const char* name,
const elfcpp::Shdr<size, big_endian>& shdr, off_t* offset);
+ // Handle a GNU stack note. This is called once per input object
+ // file. SEEN_GNU_STACK is true if the object file has a
+ // .note.GNU-stack section. GNU_STACK_FLAGS is the section flags
+ // from that section if there was one.
+ void
+ layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
+
// Add an Output_section_data to the layout. This is used for
// special sections like the GOT section.
void
// Create a .note section for gold.
void
- create_note_section();
+ create_gold_note();
+
+ // Record whether the stack must be executable.
+ void
+ create_executable_stack_info(const Target*);
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
Output_section* eh_frame_section_;
// The size of the output file.
off_t output_file_size_;
+ // Whether we have seen an object file marked to require an
+ // executable stack.
+ bool input_requires_executable_stack_;
+ // Whether we have seen at least one object file with an executable
+ // stack marker.
+ bool input_with_gnu_stack_note_;
+ // Whether we have seen at least one object file without an
+ // executable stack marker.
+ bool input_without_gnu_stack_note_;
};
// This task handles writing out data which is not part of a section
std::vector<Map_to_output>& map_sections(this->map_to_output());
map_sections.resize(shnum);
+ // Whether we've seen a .note.GNU-stack section.
+ bool seen_gnu_stack = false;
+ // The flags of a .note.GNU-stack section.
+ uint64_t gnu_stack_flags = 0;
+
// Keep track of which sections to omit.
std::vector<bool> omit(shnum, false);
omit[i] = true;
}
+ // The .note.GNU-stack section is special. It gives the
+ // protection flags that this object file requires for the stack
+ // in memory.
+ if (strcmp(name, ".note.GNU-stack") == 0)
+ {
+ seen_gnu_stack = true;
+ gnu_stack_flags |= shdr.get_sh_flags();
+ omit[i] = true;
+ }
+
bool discard = omit[i];
if (!discard)
{
map_sections[i].offset = offset;
}
+ layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags);
+
delete sd->section_headers;
sd->section_headers = NULL;
delete sd->section_names;
{ return this->general_arg != NULL || this->dependent_arg != NULL; }
};
+// We have a separate table for -z options.
+
+struct options::One_z_option
+{
+ // The name of the option.
+ const char* name;
+
+ // The member function in General_options called to record it.
+ void (General_options::*set)();
+};
+
class options::Command_line_options
{
public:
static const One_option options[];
static const int options_size;
+ static const One_z_option z_options[];
+ static const int z_options_size;
};
} // End namespace gold.
N_("Include only needed archive contents"),
NULL, TWO_DASHES,
&Position_dependent_options::clear_whole_archive),
+
+ GENERAL_ARG('z', NULL,
+ N_("Subcommands as follows:\n\
+ -z execstack Mark output as requiring executable stack\n\
+ -z noexecstack Mark output as not requiring executable stack"),
+ N_("-z SUBCOMMAND"), ONE_DASH,
+ &General_options::handle_z_option),
+
SPECIAL('(', "start-group", N_("Start a library search group"), NULL,
TWO_DASHES, &start_group),
SPECIAL(')', "end-group", N_("End a library search group"), NULL,
const int options::Command_line_options::options_size =
sizeof (options) / sizeof (options[0]);
+// The -z options.
+
+const options::One_z_option
+options::Command_line_options::z_options[] =
+{
+ { "execstack", &General_options::set_execstack },
+ { "noexecstack", &General_options::set_noexecstack },
+};
+
+const int options::Command_line_options::z_options_size =
+ sizeof(z_options) / sizeof(z_options[0]);
+
// The default values for the general options.
General_options::General_options()
threads_(false),
thread_count_initial_(0),
thread_count_middle_(0),
- thread_count_final_(0)
+ thread_count_final_(0),
+ execstack_(EXECSTACK_FROM_INPUT)
{
}
{
}
+// Handle the -z option.
+
+void
+General_options::handle_z_option(const char* arg)
+{
+ const int z_options_size = options::Command_line_options::z_options_size;
+ const gold::options::One_z_option* z_options =
+ gold::options::Command_line_options::z_options;
+ for (int i = 0; i < z_options_size; ++i)
+ {
+ if (strcmp(arg, z_options[i].name) == 0)
+ {
+ (this->*(z_options[i].set))();
+ return;
+ }
+ }
+
+ fprintf(stderr, _("%s: unrecognized -z subcommand: %s\n"),
+ program_name, arg);
+ ::exit(1);
+}
+
// Add the sysroot, if any, to the search paths.
void
if (this->inputs_.in_group())
{
- fprintf(stderr, _("%s: missing group end"), program_name);
+ fprintf(stderr, _("%s: missing group end\n"), program_name);
this->usage();
}
class Command_line_options;
struct One_option;
+struct One_z_option;
} // End namespace gold::options.
thread_count_final() const
{ return this->thread_count_final_; }
+ // -z execstack, -z noexecstack
+ bool
+ is_execstack_set() const
+ { return this->execstack_ != EXECSTACK_FROM_INPUT; }
+
+ bool
+ is_stack_executable() const
+ { return this->execstack_ == EXECSTACK_YES; }
+
private:
// Don't copy this structure.
General_options(const General_options&);
STRIP_DEBUG
};
+ // Whether to mark the stack as executable.
+ enum Execstack
+ {
+ // Not set on command line.
+ EXECSTACK_FROM_INPUT,
+ // Mark the stack as executable.
+ EXECSTACK_YES,
+ // Mark the stack as not executable.
+ EXECSTACK_NO
+ };
+
void
set_export_dynamic()
{ this->export_dynamic_ = true; }
ignore(const char*)
{ }
+ void
+ set_execstack()
+ { this->execstack_ = EXECSTACK_YES; }
+
+ void
+ set_noexecstack()
+ { this->execstack_ = EXECSTACK_NO; }
+
+ // Handle the -z option.
+ void
+ handle_z_option(const char*);
+
// Apply any sysroot to the directory lists.
void
add_sysroot();
int thread_count_initial_;
int thread_count_middle_;
int thread_count_final_;
+ Execstack execstack_;
};
// The current state of the position dependent options.
// updated dynamic symbol index.
unsigned int
-Symbol_table::set_dynsym_indexes(const General_options* options,
- const Target* target,
+Symbol_table::set_dynsym_indexes(const Target* target,
unsigned int index,
std::vector<Symbol*>* syms,
Stringpool* dynpool,
// Record any version information.
if (sym->version() != NULL)
- versions->record_version(options, this, dynpool, sym);
+ versions->record_version(this, dynpool, sym);
}
}
// the vector. The names are stored into the Stringpool. This
// returns an updated dynamic symbol index.
unsigned int
- set_dynsym_indexes(const General_options*, const Target*, unsigned int index,
+ set_dynsym_indexes(const Target*, unsigned int index,
std::vector<Symbol*>*, Stringpool*, Versions*);
// Finalize the symbol table after we have set the final addresses
common_pagesize() const
{ return this->pti_->common_pagesize; }
+ // If we see some object files with .note.GNU-stack sections, and
+ // some objects files without them, this returns whether we should
+ // consider the object files without them to imply that the stack
+ // should be executable.
+ bool
+ is_default_stack_executable() const
+ { return this->pti_->is_default_stack_executable; }
+
// This is called to tell the target to complete any sections it is
// handling. After this all sections must have their final size.
void
bool has_resolve;
// Whether this target has a specific code fill function.
bool has_code_fill;
+ // Whether an object file with no .note.GNU-stack sections implies
+ // that the stack should be executable.
+ bool is_default_stack_executable;
// The default dynamic linker name.
const char* dynamic_linker;
// The default text segment address.
false, // has_make_symbol
false, // has_resolve
false, // has_code_fill
+ false, // is_default_stack_executable
"/dummy", // dynamic_linker
0x08000000, // default_text_segment_address
0x1000, // abi_pagesize
false, // has_make_symbol
false, // has_resolve
true, // has_code_fill
+ true, // is_default_stack_executable
"/lib/ld64.so.1", // program interpreter
0x400000, // default_text_segment_address
0x1000, // abi_pagesize