Fix a typo.
[binutils-gdb.git] / gold / script-sections.cc
index 39aa9bd03dbaea66c5ef62fc16d522831add8058..990a1a2c7712357da122691f1a6a60d53588a195 100644 (file)
@@ -54,6 +54,11 @@ class Sections_element
   virtual ~Sections_element()
   { }
 
+  // Record that an output section is relro.
+  virtual void
+  set_is_relro()
+  { }
+
   // Create any required output sections.  The only real
   // implementation is in Output_section_definition.
   virtual void
@@ -80,7 +85,7 @@ class Sections_element
   // Return whether to place an orphan output section after this
   // element.
   virtual bool
-  place_orphan_here(const Output_section *, bool*) const
+  place_orphan_here(const Output_section *, bool*, bool*) const
   { return false; }
 
   // Set section addresses.  This includes applying assignments if the
@@ -105,11 +110,30 @@ class Sections_element
 
   // Get the list of segments to use for an allocated section when
   // using a PHDRS clause.  If this is an allocated section, return
-  // the Output_section, and set *PHDRS_LIST to the list of PHDRS to
-  // which it should be attached.  If the PHDRS were not specified,
-  // don't change *PHDRS_LIST.
+  // the Output_section, and set *PHDRS_LIST (the first parameter) to
+  // the list of PHDRS to which it should be attached.  If the PHDRS
+  // were not specified, don't change *PHDRS_LIST.  When not returning
+  // NULL, set *ORPHAN (the second parameter) according to whether
+  // this is an orphan section--one that is not mentioned in the
+  // linker script.
   virtual Output_section*
-  allocate_to_segment(String_list**)
+  allocate_to_segment(String_list**, bool*)
+  { return NULL; }
+
+  // Look for an output section by name and return the address, the
+  // load address, the alignment, and the size.  This is used when an
+  // expression refers to an output section which was not actually
+  // created.  This returns true if the section was found, false
+  // otherwise.  The only real definition is for
+  // Output_section_definition.
+  virtual bool
+  get_output_section_info(const char*, uint64_t*, uint64_t*, uint64_t*,
+                          uint64_t*) const
+  { return false; }
+
+  // Return the associated Output_section if there is one.
+  virtual Output_section*
+  get_output_section() const
   { return NULL; }
 
   // Print the element for debugging purposes.
@@ -412,7 +436,7 @@ Output_section_element_dot_assignment::set_section_addresses(
                                                              - *dot_value);
       Output_section_data* posd;
       if (fill->empty())
-       posd = new Output_data_fixed_space(length, 0);
+       posd = new Output_data_zero_fill(length, 0);
       else
        {
          std::string this_fill = this->get_fill_string(fill, length);
@@ -468,6 +492,11 @@ class Output_data_expression : public Output_section_data
   void
   do_write_to_buffer(unsigned char*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** expression")); }
+
  private:
   template<bool big_endian>
   void
@@ -1212,6 +1241,11 @@ class Output_section_definition : public Sections_element
   void
   add_input_section(const Input_section_spec* spec, bool keep);
 
+  // Record that the output section is relro.
+  void
+  set_is_relro()
+  { this->is_relro_ = true; }
+
   // Create any required output sections.
   void
   create_sections(Layout*);
@@ -1232,7 +1266,7 @@ class Output_section_definition : public Sections_element
 
   // Return whether to place an orphan section after this one.
   bool
-  place_orphan_here(const Output_section *os, bool* exact) const;
+  place_orphan_here(const Output_section *os, bool* exact, bool*) const;
 
   // Set the section address.
   void
@@ -1252,12 +1286,23 @@ class Output_section_definition : public Sections_element
   alternate_constraint(Output_section_definition*, Section_constraint);
 
   // Get the list of segments to use for an allocated section when
-  // using a PHDRS clause.  If this is an allocated section, return
-  // the Output_section, and set *PHDRS_LIST to the list of PHDRS to
-  // which it should be attached.  If the PHDRS were not specified,
-  // don't change *PHDRS_LIST.
+  // using a PHDRS clause.
+  Output_section*
+  allocate_to_segment(String_list** phdrs_list, bool* orphan);
+
+  // Look for an output section by name and return the address, the
+  // load address, the alignment, and the size.  This is used when an
+  // expression refers to an output section which was not actually
+  // created.  This returns true if the section was found, false
+  // otherwise.
+  bool
+  get_output_section_info(const char*, uint64_t*, uint64_t*, uint64_t*,
+                          uint64_t*) const;
+
+  // Return the associated Output_section if there is one.
   Output_section*
-  allocate_to_segment(String_list** phdrs_list);
+  get_output_section() const
+  { return this->output_section_; }
 
   // Print the contents to the FILE.  This is for debugging.
   void
@@ -1288,6 +1333,14 @@ class Output_section_definition : public Sections_element
   // The Output_section created for this definition.  This will be
   // NULL if none was created.
   Output_section* output_section_;
+  // The address after it has been evaluated.
+  uint64_t evaluated_address_;
+  // The load address after it has been evaluated.
+  uint64_t evaluated_load_address_;
+  // The alignment after it has been evaluated.
+  uint64_t evaluated_addralign_;
+  // The output section is relro.
+  bool is_relro_;
 };
 
 // Constructor.
@@ -1305,7 +1358,11 @@ Output_section_definition::Output_section_definition(
     fill_(NULL),
     phdrs_(NULL),
     elements_(),
-    output_section_(NULL)
+    output_section_(NULL),
+    evaluated_address_(0),
+    evaluated_load_address_(0),
+    evaluated_addralign_(0),
+    is_relro_(false)
 {
 }
 
@@ -1486,8 +1543,11 @@ Output_section_definition::output_section_name(const char* file_name,
 
 bool
 Output_section_definition::place_orphan_here(const Output_section *os,
-                                            bool* exact) const
+                                            bool* exact,
+                                            bool* is_relro) const
 {
+  *is_relro = this->is_relro_;
+
   // Check for the simple case first.
   if (this->output_section_ != NULL
       && this->output_section_->type() == os->type()
@@ -1648,13 +1708,20 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
       && (this->output_section_->flags() & elfcpp::SHF_ALLOC) != 0)
     this->output_section_->set_address(address);
 
-  if (this->load_address_ != NULL && this->output_section_ != NULL)
+  this->evaluated_address_ = address;
+  this->evaluated_addralign_ = align;
+
+  if (this->load_address_ == NULL)
+    this->evaluated_load_address_ = address;
+  else
     {
       Output_section* dummy;
       uint64_t load_address =
        this->load_address_->eval_with_dot(symtab, layout, true, *dot_value,
                                           this->output_section_, &dummy);
-      this->output_section_->set_load_address(load_address);
+      if (this->output_section_ != NULL)
+        this->output_section_->set_load_address(load_address);
+      this->evaluated_load_address_ = load_address;
     }
 
   uint64_t subalign;
@@ -1716,6 +1783,14 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
   else
     *load_address = (this->output_section_->load_address()
                      + (*dot_value - start_address));
+
+  if (this->output_section_ != NULL)
+    {
+      if (this->is_relro_)
+       this->output_section_->set_is_relro();
+      else
+       this->output_section_->clear_is_relro();
+    }
 }
 
 // Check a constraint (ONLY_IF_RO, etc.) on an output section.  If
@@ -1797,27 +1872,68 @@ Output_section_definition::alternate_constraint(
   this->output_section_ = posd->output_section_;
   posd->output_section_ = NULL;
 
+  if (this->is_relro_)
+    this->output_section_->set_is_relro();
+  else
+    this->output_section_->clear_is_relro();
+
   return true;
 }
 
 // Get the list of segments to use for an allocated section when using
-// a PHDRS clause.  If this is an allocated section, return the
-// Output_section, and set *PHDRS_LIST to the list of PHDRS to which
-// it should be attached.  If the PHDRS were not specified, don't
-// change *PHDRS_LIST.
+// a PHDRS clause.
 
 Output_section*
-Output_section_definition::allocate_to_segment(String_list** phdrs_list)
+Output_section_definition::allocate_to_segment(String_list** phdrs_list,
+                                              bool* orphan)
 {
   if (this->output_section_ == NULL)
     return NULL;
   if ((this->output_section_->flags() & elfcpp::SHF_ALLOC) == 0)
     return NULL;
+  *orphan = false;
   if (this->phdrs_ != NULL)
     *phdrs_list = this->phdrs_;
   return this->output_section_;
 }
 
+// Look for an output section by name and return the address, the load
+// address, the alignment, and the size.  This is used when an
+// expression refers to an output section which was not actually
+// created.  This returns true if the section was found, false
+// otherwise.
+
+bool
+Output_section_definition::get_output_section_info(const char* name,
+                                                   uint64_t* address,
+                                                   uint64_t* load_address,
+                                                   uint64_t* addralign,
+                                                   uint64_t* size) const
+{
+  if (this->name_ != name)
+    return false;
+
+  if (this->output_section_ != NULL)
+    {
+      *address = this->output_section_->address();
+      if (this->output_section_->has_load_address())
+        *load_address = this->output_section_->load_address();
+      else
+        *load_address = *address;
+      *addralign = this->output_section_->addralign();
+      *size = this->output_section_->current_data_size();
+    }
+  else
+    {
+      *address = this->evaluated_address_;
+      *load_address = this->evaluated_load_address_;
+      *addralign = this->evaluated_addralign_;
+      *size = 0;
+    }
+
+  return true;
+}
+
 // Print for debugging.
 
 void
@@ -1894,17 +2010,21 @@ class Orphan_output_section : public Sections_element
 
   // Return whether to place an orphan section after this one.
   bool
-  place_orphan_here(const Output_section *os, bool* exact) const;
+  place_orphan_here(const Output_section *os, bool* exact, bool*) const;
 
   // Set section addresses.
   void
   set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*);
 
   // Get the list of segments to use for an allocated section when
-  // using a PHDRS clause.  If this is an allocated section, return
-  // the Output_section.
+  // using a PHDRS clause.
+  Output_section*
+  allocate_to_segment(String_list**, bool*);
+
+  // Return the associated Output_section.
   Output_section*
-  allocate_to_segment(String_list**);
+  get_output_section() const
+  { return this->os_; }
 
   // Print for debugging.
   void
@@ -1922,12 +2042,14 @@ class Orphan_output_section : public Sections_element
 
 bool
 Orphan_output_section::place_orphan_here(const Output_section* os,
-                                        bool* exact) const
+                                        bool* exact,
+                                        bool* is_relro) const
 {
   if (this->os_->type() == os->type()
       && this->os_->flags() == os->flags())
     {
       *exact = true;
+      *is_relro = this->os_->is_relro();
       return true;
     }
   return false;
@@ -1993,10 +2115,11 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
 // Output_section.  We don't change the list of segments.
 
 Output_section*
-Orphan_output_section::allocate_to_segment(String_list**)
+Orphan_output_section::allocate_to_segment(String_list**, bool* orphan)
 {
   if ((this->os_->flags() & elfcpp::SHF_ALLOC) == 0)
     return NULL;
+  *orphan = true;
   return this->os_;
 }
 
@@ -2132,7 +2255,9 @@ Script_sections::Script_sections()
     in_sections_clause_(false),
     sections_elements_(NULL),
     output_section_(NULL),
-    phdrs_elements_(NULL)
+    phdrs_elements_(NULL),
+    data_segment_align_index_(-1U),
+    saw_relro_end_(false)
 {
 }
 
@@ -2260,6 +2385,39 @@ Script_sections::add_input_section(const Input_section_spec* spec, bool keep)
   this->output_section_->add_input_section(spec, keep);
 }
 
+// This is called when we see DATA_SEGMENT_ALIGN.  It means that any
+// subsequent output sections may be relro.
+
+void
+Script_sections::data_segment_align()
+{
+  if (this->data_segment_align_index_ != -1U)
+    gold_error(_("DATA_SEGMENT_ALIGN may only appear once in a linker script"));
+  this->data_segment_align_index_ = this->sections_elements_->size();
+}
+
+// This is called when we see DATA_SEGMENT_RELRO_END.  It means that
+// any output sections seen since DATA_SEGMENT_ALIGN are relro.
+
+void
+Script_sections::data_segment_relro_end()
+{
+  if (this->saw_relro_end_)
+    gold_error(_("DATA_SEGMENT_RELRO_END may only appear once "
+                "in a linker script"));
+  this->saw_relro_end_ = true;
+
+  if (this->data_segment_align_index_ == -1U)
+    gold_error(_("DATA_SEGMENT_RELRO_END must follow DATA_SEGMENT_ALIGN"));
+  else
+    {
+      for (size_t i = this->data_segment_align_index_;
+          i < this->sections_elements_->size();
+          ++i)
+       (*this->sections_elements_)[i]->set_is_relro();
+    }
+}
+
 // Create any required sections.
 
 void
@@ -2344,15 +2502,18 @@ Script_sections::place_orphan(Output_section* os)
 {
   // Look for an output section definition which matches the output
   // section.  Put a marker after that section.
+  bool is_relro = false;
   Sections_elements::iterator place = this->sections_elements_->end();
   for (Sections_elements::iterator p = this->sections_elements_->begin();
        p != this->sections_elements_->end();
        ++p)
     {
-      bool exact;
-      if ((*p)->place_orphan_here(os, &exact))
+      bool exact = false;
+      bool is_relro_here;
+      if ((*p)->place_orphan_here(os, &exact, &is_relro_here))
        {
          place = p;
+         is_relro = is_relro_here;
          if (exact)
            break;
        }
@@ -2363,6 +2524,11 @@ Script_sections::place_orphan(Output_section* os)
     ++place;
 
   this->sections_elements_->insert(place, new Orphan_output_section(os));
+
+  if (is_relro)
+    os->set_is_relro();
+  else
+    os->clear_is_relro();
 }
 
 // Set the addresses of all the output sections.  Walk through all the
@@ -2405,6 +2571,26 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout)
        }
     }
 
+  // Force the alignment of the first TLS section to be the maximum
+  // alignment of all TLS sections.
+  Output_section* first_tls = NULL;
+  uint64_t tls_align = 0;
+  for (Sections_elements::const_iterator p = this->sections_elements_->begin();
+       p != this->sections_elements_->end();
+       ++p)
+    {
+      Output_section *os = (*p)->get_output_section();
+      if (os != NULL && (os->flags() & elfcpp::SHF_TLS) != 0)
+       {
+         if (first_tls == NULL)
+           first_tls = os;
+         if (os->addralign() > tls_align)
+           tls_align = os->addralign();
+       }
+    }
+  if (first_tls != NULL)
+    first_tls->set_addralign(tls_align);
+
   // For a relocatable link, we implicitly set dot to zero.
   uint64_t dot_value = 0;
   uint64_t load_address = 0;
@@ -2583,7 +2769,8 @@ Script_sections::create_segments(Layout* layout)
          need_new_segment = true;
        }
       else if (is_current_seg_readonly
-              && ((*p)->flags() & elfcpp::SHF_WRITE) != 0)
+              && ((*p)->flags() & elfcpp::SHF_WRITE) != 0
+              && !parameters->options().omagic())
        {
          // Don't put a writable section in the same segment as a
          // non-writable section.
@@ -2637,18 +2824,17 @@ Script_sections::create_segments(Layout* layout)
 
   size_t sizeof_headers = this->total_header_size(layout);
 
-  if ((first_seg->paddr() & (abi_pagesize - 1)) >= sizeof_headers)
-    {
-      first_seg->set_addresses(first_seg->vaddr() - sizeof_headers,
-                              first_seg->paddr() - sizeof_headers);
-      return first_seg;
-    }
-
   uint64_t vma = first_seg->vaddr();
   uint64_t lma = first_seg->paddr();
 
   uint64_t subtract = this->header_size_adjustment(lma, sizeof_headers);
 
+  if ((lma & (abi_pagesize - 1)) >= sizeof_headers)
+    {
+      first_seg->set_addresses(vma - subtract, lma - subtract);
+      return first_seg;
+    }
+
   // If there is no room to squeeze in the headers, then punt.  The
   // resulting executable probably won't run on GNU/Linux, but we
   // trust that the user knows what they are doing.
@@ -2820,7 +3006,8 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
        p != this->sections_elements_->end();
        ++p)
     {
-      Output_section* os = (*p)->allocate_to_segment(&phdr_names);
+      bool orphan;
+      Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan);
       if (os == NULL)
        continue;
 
@@ -2830,6 +3017,27 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
          continue;
        }
 
+      // If this is an orphan section--one that was not explicitly
+      // mentioned in the linker script--then it should not inherit
+      // any segment type other than PT_LOAD.  Otherwise, e.g., the
+      // PT_INTERP segment will pick up following orphan sections,
+      // which does not make sense.  If this is not an orphan section,
+      // we trust the linker script.
+      if (orphan)
+       {
+         String_list::iterator q = phdr_names->begin();
+         while (q != phdr_names->end())
+           {
+             Name_to_segment::const_iterator r = name_to_segment.find(*q);
+             // We give errors about unknown segments below.
+             if (r == name_to_segment.end()
+                 || r->second->type() == elfcpp::PT_LOAD)
+               ++q;
+             else
+               q = phdr_names->erase(q);
+           }
+       }
+
       bool in_load_segment = false;
       for (String_list::const_iterator q = phdr_names->begin();
           q != phdr_names->end();
@@ -2971,6 +3179,29 @@ Script_sections::put_headers_in_phdrs(Output_data* file_header,
     }
 }
 
+// Look for an output section by name and return the address, the load
+// address, the alignment, and the size.  This is used when an
+// expression refers to an output section which was not actually
+// created.  This returns true if the section was found, false
+// otherwise.
+
+bool
+Script_sections::get_output_section_info(const char* name, uint64_t* address,
+                                         uint64_t* load_address,
+                                         uint64_t* addralign,
+                                         uint64_t* size) const
+{
+  if (!this->saw_sections_clause_)
+    return false;
+  for (Sections_elements::const_iterator p = this->sections_elements_->begin();
+       p != this->sections_elements_->end();
+       ++p)
+    if ((*p)->get_output_section_info(name, address, load_address, addralign,
+                                      size))
+      return true;
+  return false;
+}
+
 // Print the SECTIONS clause to F for debugging.
 
 void