* layout.cc (Layout::get_output_section): Add is_interp and
authorIan Lance Taylor <ian@airs.com>
Wed, 4 Nov 2009 15:56:03 +0000 (15:56 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 4 Nov 2009 15:56:03 +0000 (15:56 +0000)
is_dynamic_linker_section parameters.  Change all callers.
(Layout::choose_output_section): Likewise.
(Layout::make_output_section): Likewise.
(Layout::add_output_section_data): Add is_dynamic_linker_section
parameter.  Change all callers.
* layout.h (class Layout): Update declarations.
* output.h (class Output_section): Add is_interp, set_is_interp,
is_dynamic_linker_section, set_is_dynamic_linker_section methods.
Add is_interp_, is_dynamic_linker_section_ fields.  Change
generate_code_fills_at_write_ to a bitfield.
* output.cc (Output_section::Output_sections): Initialize new
fields.
(Output_segment::add_output_section): Add do_sort parameter.
Change all callers.

13 files changed:
gold/ChangeLog
gold/arm.cc
gold/common.cc
gold/copy-relocs.cc
gold/i386.cc
gold/layout.cc
gold/layout.h
gold/output.cc
gold/output.h
gold/powerpc.cc
gold/script-sections.cc
gold/sparc.cc
gold/x86_64.cc

index 6a7d5e7..7cb8619 100644 (file)
@@ -1,3 +1,21 @@
+2009-11-04  Ian Lance Taylor  <iant@google.com>
+
+       * layout.cc (Layout::get_output_section): Add is_interp and
+       is_dynamic_linker_section parameters.  Change all callers.
+       (Layout::choose_output_section): Likewise.
+       (Layout::make_output_section): Likewise.
+       (Layout::add_output_section_data): Add is_dynamic_linker_section
+       parameter.  Change all callers.
+       * layout.h (class Layout): Update declarations.
+       * output.h (class Output_section): Add is_interp, set_is_interp,
+       is_dynamic_linker_section, set_is_dynamic_linker_section methods.
+       Add is_interp_, is_dynamic_linker_section_ fields.  Change
+       generate_code_fills_at_write_ to a bitfield.
+       * output.cc (Output_section::Output_sections): Initialize new
+       fields.
+       (Output_segment::add_output_section): Add do_sort parameter.
+       Change all callers.
+
 2009-11-03  Ian Lance Taylor  <iant@google.com>
 
        PR 10860
index f0db899..8998032 100644 (file)
@@ -2166,7 +2166,7 @@ Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout)
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_);
+                                          this->got_, false);
       os->set_is_relro();
 
       // The old GNU linker creates a .got.plt section.  We just
@@ -2177,7 +2177,7 @@ Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout)
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_plt_);
+                                          this->got_plt_, false);
       os->set_is_relro();
 
       // The first three entries are reserved.
@@ -2205,7 +2205,7 @@ Target_arm<big_endian>::rel_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-                                     elfcpp::SHF_ALLOC, this->rel_dyn_);
+                                     elfcpp::SHF_ALLOC, this->rel_dyn_, true);
     }
   return this->rel_dyn_;
 }
@@ -3588,7 +3588,7 @@ Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout,
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-                                 elfcpp::SHF_ALLOC, this->rel_);
+                                 elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 template<bool big_endian>
@@ -3750,7 +3750,7 @@ Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout* layout,
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
-                                     this->plt_);
+                                     this->plt_, false);
     }
   this->plt_->add_entry(gsym);
 }
@@ -4300,7 +4300,8 @@ Target_arm<big_endian>::do_finalize_sections(
                      == NULL);
          Output_segment*  exidx_segment =
            layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
-         exidx_segment->add_output_section(exidx_section, elfcpp::PF_R);
+         exidx_segment->add_output_section(exidx_section, elfcpp::PF_R,
+                                           false);
        }
     }
 }
index f90ae40..4bc6a51 100644 (file)
@@ -239,7 +239,7 @@ Symbol_table::do_allocate_commons_list(
   Output_data_space *poc = new Output_data_space(addralign, ds_name);
   Output_section *os = layout->add_output_section_data(name,
                                                       elfcpp::SHT_NOBITS,
-                                                      flags, poc);
+                                                      flags, poc, false);
   if (os != NULL)
     {
       if (commons_section_type == COMMONS_SMALL)
index 6ef72d3..345c0c6 100644 (file)
@@ -138,7 +138,7 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
       layout->add_output_section_data(".bss",
                                      elfcpp::SHT_NOBITS,
                                      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
-                                     this->dynbss_);
+                                     this->dynbss_, false);
     }
 
   Output_data_space* dynbss = this->dynbss_;
index 2d7168b..d0ed561 100644 (file)
@@ -459,7 +459,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_);
+                                          this->got_, false);
       os->set_is_relro();
 
       // The old GNU linker creates a .got.plt section.  We just
@@ -470,7 +470,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_plt_);
+                                          this->got_plt_, false);
       os->set_is_relro();
 
       // The first three entries are reserved.
@@ -498,7 +498,7 @@ Target_i386::rel_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-                                     elfcpp::SHF_ALLOC, this->rel_dyn_);
+                                     elfcpp::SHF_ALLOC, this->rel_dyn_, true);
     }
   return this->rel_dyn_;
 }
@@ -573,7 +573,7 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-                                 elfcpp::SHF_ALLOC, this->rel_);
+                                 elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 void
@@ -758,7 +758,7 @@ Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym)
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
-                                     this->plt_);
+                                     this->plt_, false);
     }
 
   this->plt_->add_entry(gsym);
index 07fa12f..f0a51b4 100644 (file)
@@ -388,11 +388,14 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set,
 
 // Return the output section to use for section NAME with type TYPE
 // and section flags FLAGS.  NAME must be canonicalized in the string
-// pool, and NAME_KEY is the key.
+// pool, and NAME_KEY is the key.  IS_INTERP is true if this is the
+// .interp section.  IS_DYNAMIC_LINKER_SECTION is true if this section
+// is used by the dynamic linker.
 
 Output_section*
 Layout::get_output_section(const char* name, Stringpool::Key name_key,
-                          elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
+                          elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+                          bool is_interp, bool is_dynamic_linker_section)
 {
   elfcpp::Elf_Xword lookup_flags = flags;
 
@@ -441,7 +444,8 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
        }
 
       if (os == NULL)
-       os = this->make_output_section(name, type, flags);
+       os = this->make_output_section(name, type, flags, is_interp,
+                                      is_dynamic_linker_section);
       ins.first->second = os;
       return os;
     }
@@ -451,13 +455,16 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
 // RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
 // linker created section.  IS_INPUT_SECTION is true if we are
 // choosing an output section for an input section found in a input
-// file.  This will return NULL if the input section should be
-// discarded.
+// file.  IS_INTERP is true if this is the .interp section.
+// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
+// dynamic linker.  This will return NULL if the input section should
+// be discarded.
 
 Output_section*
 Layout::choose_output_section(const Relobj* relobj, const char* name,
                              elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-                             bool is_input_section)
+                             bool is_input_section, bool is_interp,
+                             bool is_dynamic_linker_section)
 {
   // We should not see any input sections after we have attached
   // sections to segments.
@@ -505,7 +512,9 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
 
          name = this->namepool_.add(name, false, NULL);
 
-         Output_section* os = this->make_output_section(name, type, flags);
+         Output_section* os =
+           this->make_output_section(name, type, flags, is_interp,
+                                     is_dynamic_linker_section);
          os->set_found_in_sections_clause();
          *output_section_slot = os;
          return os;
@@ -528,7 +537,8 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
 
   // Find or make the output section.  The output section is selected
   // based on the section name, type, and flags.
-  return this->get_output_section(name, name_key, type, flags);
+  return this->get_output_section(name, name_key, type, flags, is_interp,
+                                 is_dynamic_linker_section);
 }
 
 // Return the output section to use for input section SHNDX, with name
@@ -561,12 +571,13 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
     {
       name = this->namepool_.add(name, true, NULL);
       os = this->make_output_section(name, shdr.get_sh_type(),
-                                    shdr.get_sh_flags());
+                                    shdr.get_sh_flags(), false, false);
     }
   else
     {
       os = this->choose_output_section(object, name, shdr.get_sh_type(),
-                                      shdr.get_sh_flags(), true);
+                                      shdr.get_sh_flags(), true, false,
+                                      false);
       if (os == NULL)
        return NULL;
     }
@@ -617,7 +628,7 @@ Layout::layout_reloc(Sized_relobj<size, big_endian>* object,
   Output_section* os = this->choose_output_section(object, name.c_str(),
                                                   sh_type,
                                                   shdr.get_sh_flags(),
-                                                  false);
+                                                  false, false, false);
 
   os->set_should_link_to_symtab();
   os->set_info_section(data_section);
@@ -664,7 +675,8 @@ Layout::layout_group(Symbol_table* symtab,
   group_section_name = this->namepool_.add(group_section_name, true, NULL);
   Output_section* os = this->make_output_section(group_section_name,
                                                 elfcpp::SHT_GROUP,
-                                                shdr.get_sh_flags());
+                                                shdr.get_sh_flags(),
+                                                false, false);
 
   // We need to find a symbol with the signature in the symbol table.
   // If we don't find one now, we need to look again later.
@@ -718,7 +730,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
                                                   name,
                                                   elfcpp::SHT_PROGBITS,
                                                   elfcpp::SHF_ALLOC,
-                                                  false);
+                                                  false, false, false);
   if (os == NULL)
     return NULL;
 
@@ -734,7 +746,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
                                        ".eh_frame_hdr",
                                        elfcpp::SHT_PROGBITS,
                                        elfcpp::SHF_ALLOC,
-                                       false);
+                                       false, false, false);
 
          if (hdr_os != NULL)
            {
@@ -749,7 +761,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
                  Output_segment* hdr_oseg;
                  hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
                                                       elfcpp::PF_R);
-                 hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
+                 hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false);
                }
 
              this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
@@ -800,10 +812,12 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
 Output_section*
 Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
                                elfcpp::Elf_Xword flags,
-                               Output_section_data* posd)
+                               Output_section_data* posd,
+                               bool is_dynamic_linker_section)
 {
   Output_section* os = this->choose_output_section(NULL, name, type, flags,
-                                                  false);
+                                                  false, false,
+                                                  is_dynamic_linker_section);
   if (os != NULL)
     os->add_output_section_data(posd);
   return os;
@@ -838,11 +852,14 @@ is_compressible_debug_section(const char* secname)
 }
 
 // Make a new Output_section, and attach it to segments as
-// appropriate.
+// appropriate.  IS_INTERP is true if this is the .interp section.
+// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
+// dynamic linker.
 
 Output_section*
 Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
-                           elfcpp::Elf_Xword flags)
+                           elfcpp::Elf_Xword flags, bool is_interp,
+                           bool is_dynamic_linker_section)
 {
   Output_section* os;
   if ((flags & elfcpp::SHF_ALLOC) == 0
@@ -850,7 +867,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
       && is_compressible_debug_section(name))
     os = new Output_compressed_section(&parameters->options(), name, type,
                                       flags);
-
   else if ((flags & elfcpp::SHF_ALLOC) == 0
            && parameters->options().strip_debug_non_line()
            && strcmp(".debug_abbrev", name) == 0)
@@ -876,6 +892,11 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
       os = target->make_output_section(name, type, flags);
     }
 
+  if (is_interp)
+    os->set_is_interp();
+  if (is_dynamic_linker_section)
+    os->set_is_dynamic_linker_section();
+
   parameters->target().new_output_section(os);
 
   this->section_list_.push_back(os);
@@ -971,6 +992,8 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
 
   elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
 
+  bool sort_sections = !this->script_options_->saw_sections_clause();
+
   // In general the only thing we really care about for PT_LOAD
   // segments is whether or not they are writable, so that is how we
   // search for them.  Large data sections also go into their own
@@ -998,7 +1021,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
       if (os->is_large_data_section() && !(*p)->is_large_data_segment())
        continue;
 
-      (*p)->add_output_section(os, seg_flags);
+      (*p)->add_output_section(os, seg_flags, sort_sections);
       break;
     }
 
@@ -1008,7 +1031,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
                                                        seg_flags);
       if (os->is_large_data_section())
        oseg->set_is_large_data_segment();
-      oseg->add_output_section(os, seg_flags);
+      oseg->add_output_section(os, seg_flags, sort_sections);
     }
 
   // If we see a loadable SHT_NOTE section, we create a PT_NOTE
@@ -1024,7 +1047,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
               && (((*p)->flags() & elfcpp::PF_W)
                   == (seg_flags & elfcpp::PF_W)))
             {
-              (*p)->add_output_section(os, seg_flags);
+              (*p)->add_output_section(os, seg_flags, false);
               break;
             }
         }
@@ -1033,7 +1056,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
         {
           Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
                                                            seg_flags);
-          oseg->add_output_section(os, seg_flags);
+          oseg->add_output_section(os, seg_flags, false);
         }
     }
 
@@ -1043,7 +1066,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
     {
       if (this->tls_segment_ == NULL)
        this->make_output_segment(elfcpp::PT_TLS, seg_flags);
-      this->tls_segment_->add_output_section(os, seg_flags);
+      this->tls_segment_->add_output_section(os, seg_flags, false);
     }
 
   // If -z relro is in effect, and we see a relro section, we create a
@@ -1053,7 +1076,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
       gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
       if (this->relro_segment_ == NULL)
        this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
-      this->relro_segment_->add_output_section(os, seg_flags);
+      this->relro_segment_->add_output_section(os, seg_flags, false);
     }
 }
 
@@ -1064,7 +1087,8 @@ Layout::make_output_section_for_script(const char* name)
 {
   name = this->namepool_.add(name, false, NULL);
   Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
-                                                elfcpp::SHF_ALLOC);
+                                                elfcpp::SHF_ALLOC, false,
+                                                false);
   os->set_found_in_sections_clause();
   return os;
 }
@@ -1134,7 +1158,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab)
                                                       elfcpp::SHT_DYNAMIC,
                                                       (elfcpp::SHF_ALLOC
                                                        | elfcpp::SHF_WRITE),
-                                                      false);
+                                                      false, false, true);
   this->dynamic_section_->set_is_relro();
 
   symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
@@ -1732,7 +1756,8 @@ Layout::create_note(const char* name, int note_type,
     flags = elfcpp::SHF_ALLOC;
   Output_section* os = this->choose_output_section(NULL, section_name,
                                                   elfcpp::SHT_NOTE,
-                                                  flags, false);
+                                                  flags, false, false,
+                                                  false);
   if (os == NULL)
     return NULL;
 
@@ -1811,7 +1836,8 @@ Layout::create_executable_stack_info()
       elfcpp::Elf_Xword flags = 0;
       if (is_stack_executable)
        flags |= elfcpp::SHF_EXECINSTR;
-      this->make_output_section(name, elfcpp::SHT_PROGBITS, flags);
+      this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false,
+                               false);
     }
   else
     {
@@ -1971,7 +1997,8 @@ Layout::create_incremental_info_sections()
     this->namepool_.add(".gnu_incremental_inputs", false, NULL);
   Output_section* inputs_os =
     this->make_output_section(incremental_inputs_name,
-                             elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0);
+                             elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
+                             false, false);
   Output_section_data* posd =
       this->incremental_inputs_->create_incremental_inputs_section_data();
   inputs_os->add_output_section_data(posd);
@@ -1981,7 +2008,7 @@ Layout::create_incremental_info_sections()
     this->namepool_.add(".gnu_incremental_strtab", false, NULL);
   Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
                                                         elfcpp::SHT_STRTAB,
-                                                        0);
+                                                        0, false, false);
   Output_data_strtab* strtab_data =
     new Output_data_strtab(this->incremental_inputs_->get_stringpool());
   strtab_os->add_output_section_data(strtab_data);
@@ -2593,7 +2620,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
       const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
       Output_section* osymtab = this->make_output_section(symtab_name,
                                                          elfcpp::SHT_SYMTAB,
-                                                         0);
+                                                         0, false, false);
       this->symtab_section_ = osymtab;
 
       Output_section_data* pos = new Output_data_fixed_space(off - startoff,
@@ -2614,7 +2641,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
                                                               false, NULL);
          Output_section* osymtab_xindex =
            this->make_output_section(symtab_xindex_name,
-                                     elfcpp::SHT_SYMTAB_SHNDX, 0);
+                                     elfcpp::SHT_SYMTAB_SHNDX, 0, false,
+                                     false);
 
          size_t symcount = (off - startoff) / symsize;
          this->symtab_xindex_ = new Output_symtab_xindex(symcount);
@@ -2636,7 +2664,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
       const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
       Output_section* ostrtab = this->make_output_section(strtab_name,
                                                          elfcpp::SHT_STRTAB,
-                                                         0);
+                                                         0, false, false);
 
       Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
       ostrtab->add_output_section_data(pstr);
@@ -2663,7 +2691,8 @@ Layout::create_shstrtab()
 
   const char* name = this->namepool_.add(".shstrtab", false, NULL);
 
-  Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0);
+  Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
+                                                false, false);
 
   // We can't write out this section until we've set all the section
   // names, and we don't set the names of compressed output sections
@@ -2776,7 +2805,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
   Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
                                                       elfcpp::SHT_DYNSYM,
                                                       elfcpp::SHF_ALLOC,
-                                                      false);
+                                                      false, false, true);
 
   Output_section_data* odata = new Output_data_fixed_space(index * symsize,
                                                           align,
@@ -2806,7 +2835,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
        this->choose_output_section(NULL, ".dynsym_shndx",
                                    elfcpp::SHT_SYMTAB_SHNDX,
                                    elfcpp::SHF_ALLOC,
-                                   false);
+                                   false, false, true);
 
       this->dynsym_xindex_ = new Output_symtab_xindex(index);
 
@@ -2829,7 +2858,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
   Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
                                                       elfcpp::SHT_STRTAB,
                                                       elfcpp::SHF_ALLOC,
-                                                      false);
+                                                      false, false, true);
 
   Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
   dynstr->add_output_section_data(strdata);
@@ -2855,7 +2884,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
       Output_section* hashsec = this->choose_output_section(NULL, ".hash",
                                                            elfcpp::SHT_HASH,
                                                            elfcpp::SHF_ALLOC,
-                                                           false);
+                                                           false, false, true);
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
                                                                   hashlen,
@@ -2880,7 +2909,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
       Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
                                                            elfcpp::SHT_GNU_HASH,
                                                            elfcpp::SHF_ALLOC,
-                                                           false);
+                                                           false, false, true);
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
                                                                   hashlen,
@@ -2978,7 +3007,7 @@ Layout::sized_create_version_sections(
   Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
                                                     elfcpp::SHT_GNU_versym,
                                                     elfcpp::SHF_ALLOC,
-                                                    false);
+                                                    false, false, true);
 
   unsigned char* vbuf;
   unsigned int vsize;
@@ -3003,7 +3032,7 @@ Layout::sized_create_version_sections(
       vdsec= this->choose_output_section(NULL, ".gnu.version_d",
                                         elfcpp::SHT_GNU_verdef,
                                         elfcpp::SHF_ALLOC,
-                                        false);
+                                        false, false, true);
 
       unsigned char* vdbuf;
       unsigned int vdsize;
@@ -3028,7 +3057,7 @@ Layout::sized_create_version_sections(
       vnsec = this->choose_output_section(NULL, ".gnu.version_r",
                                          elfcpp::SHT_GNU_verneed,
                                          elfcpp::SHF_ALLOC,
-                                         false);
+                                         false, false, true);
 
       unsigned char* vnbuf;
       unsigned int vnsize;
@@ -3068,14 +3097,14 @@ Layout::create_interp(const Target* target)
   Output_section* osec = this->choose_output_section(NULL, ".interp",
                                                     elfcpp::SHT_PROGBITS,
                                                     elfcpp::SHF_ALLOC,
-                                                    false);
+                                                    false, true, true);
   osec->add_output_section_data(odata);
 
   if (!this->script_options_->saw_phdrs_clause())
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
                                                       elfcpp::PF_R);
-      oseg->add_output_section(osec, elfcpp::PF_R);
+      oseg->add_output_section(osec, elfcpp::PF_R, false);
     }
 }
 
@@ -3091,7 +3120,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
                                                       (elfcpp::PF_R
                                                        | elfcpp::PF_W));
       oseg->add_output_section(this->dynamic_section_,
-                              elfcpp::PF_R | elfcpp::PF_W);
+                              elfcpp::PF_R | elfcpp::PF_W,
+                              false);
     }
 
   Output_data_dynamic* const odyn = this->dynamic_data_;
index 675c658..71afa96 100644 (file)
@@ -360,11 +360,13 @@ class Layout
   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.
+  // special sections like the GOT section.  IS_DYNAMIC_LINKER_SECTION
+  // is true for sections which are used by the dynamic linker, such
+  // as dynamic reloc sections.
   Output_section*
   add_output_section_data(const char* name, elfcpp::Elf_Word type,
                          elfcpp::Elf_Xword flags,
-                         Output_section_data*);
+                         Output_section_data*, bool is_dynamic_linker_section);
 
   // Create dynamic sections if necessary.
   void
@@ -745,18 +747,21 @@ class Layout
   // Return the output section for NAME, TYPE and FLAGS.
   Output_section*
   get_output_section(const char* name, Stringpool::Key name_key,
-                    elfcpp::Elf_Word type, elfcpp::Elf_Xword flags);
+                    elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+                    bool is_interp, bool is_dynamic_linker_section);
 
   // Choose the output section for NAME in RELOBJ.
   Output_section*
   choose_output_section(const Relobj* relobj, const char* name,
                        elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-                       bool is_input_section);
+                       bool is_input_section, bool is_interp,
+                       bool is_dynamic_linker_section);
 
   // Create a new Output_section.
   Output_section*
   make_output_section(const char* name, elfcpp::Elf_Word type,
-                     elfcpp::Elf_Xword flags);
+                     elfcpp::Elf_Xword flags, bool is_interp,
+                     bool is_dynamic_linker_section);
 
   // Attach a section to a segment.
   void
index 61e5c87..5e9b813 100644 (file)
@@ -1797,13 +1797,15 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     is_relro_local_(false),
     is_small_section_(false),
     is_large_section_(false),
+    is_interp_(false),
+    is_dynamic_linker_section_(false),
+    generate_code_fills_at_write_(false),
     tls_offset_(0),
     checkpoint_(NULL),
     merge_section_map_(),
     merge_section_by_properties_map_(),
     relaxed_input_section_map_(),
-    is_relaxed_input_section_map_valid_(true),
-    generate_code_fills_at_write_(false)
+    is_relaxed_input_section_map_valid_(true)
 {
   // An unallocated section has no address.  Forcing this means that
   // we don't need special treatment for symbols defined in debug
@@ -3042,7 +3044,8 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
 
 void
 Output_segment::add_output_section(Output_section* os,
-                                  elfcpp::Elf_Word seg_flags)
+                                  elfcpp::Elf_Word seg_flags,
+                                  bool do_sort)
 {
   gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
   gold_assert(!this->is_max_align_known_);
@@ -3057,6 +3060,10 @@ Output_segment::add_output_section(Output_section* os,
   else
     pdl = &this->output_data_;
 
+  // Note that while there may be many input sections in an output
+  // section, there are normally only a few output sections in an
+  // output segment.  The loops below are expected to be fast.
+
   // So that PT_NOTE segments will work correctly, we need to ensure
   // that all SHT_NOTE sections are adjacent.  This will normally
   // happen automatically, because all the SHT_NOTE input sections
@@ -3065,11 +3072,6 @@ Output_segment::add_output_section(Output_section* os,
   // flags, and thus be in different output sections, but for the
   // different section flags to map into the same segment flags and
   // thus the same output segment.
-
-  // Note that while there may be many input sections in an output
-  // section, there are normally only a few output sections in an
-  // output segment.  This loop is expected to be fast.
-
   if (os->type() == elfcpp::SHT_NOTE && !pdl->empty())
     {
       Output_segment::Output_data_list::iterator p = pdl->end();
@@ -3091,8 +3093,8 @@ Output_segment::add_output_section(Output_section* os,
   // case: we group the SHF_TLS/SHT_NOBITS sections right after the
   // SHF_TLS/SHT_PROGBITS sections.  This lets us set up PT_TLS
   // correctly.  SHF_TLS sections get added to both a PT_LOAD segment
-  // and the PT_TLS segment -- we do this grouping only for the
-  // PT_LOAD segment.
+  // and the PT_TLS segment; we do this grouping only for the PT_LOAD
+  // segment.
   if (this->type_ != elfcpp::PT_TLS
       && (os->flags() & elfcpp::SHF_TLS) != 0)
     {
@@ -3222,6 +3224,67 @@ Output_segment::add_output_section(Output_section* os,
       gold_unreachable();
     }
 
+  // We do some further output section sorting in order to make the
+  // generated program run more efficiently.  We should only do this
+  // when not using a linker script, so it is controled by the DO_SORT
+  // parameter.
+  if (do_sort)
+    {
+      // FreeBSD requires the .interp section to be in the first page
+      // of the executable.  That is a more efficient location anyhow
+      // for any OS, since it means that the kernel will have the data
+      // handy after it reads the program headers.
+      if (os->is_interp() && !pdl->empty())
+       {
+         pdl->insert(pdl->begin(), os);
+         return;
+       }
+
+      // Put loadable non-writable notes immediately after the .interp
+      // sections, so that the PT_NOTE segment is on the first page of
+      // the executable.
+      if (os->type() == elfcpp::SHT_NOTE
+         && (os->flags() & elfcpp::SHF_WRITE) == 0
+         && !pdl->empty())
+       {
+         Output_segment::Output_data_list::iterator p = pdl->begin();
+         if ((*p)->is_section() && (*p)->output_section()->is_interp())
+           ++p;
+         pdl->insert(p, os);
+       }
+
+      // If this section is used by the dynamic linker, and it is not
+      // writable, then put it first, after the .interp section and
+      // any loadable notes.  This makes it more likely that the
+      // dynamic linker will have to read less data from the disk.
+      if (os->is_dynamic_linker_section()
+         && !pdl->empty()
+         && (os->flags() & elfcpp::SHF_WRITE) == 0)
+       {
+         bool is_reloc = (os->type() == elfcpp::SHT_REL
+                          || os->type() == elfcpp::SHT_RELA);
+         Output_segment::Output_data_list::iterator p = pdl->begin();
+         while (p != pdl->end()
+                && (*p)->is_section()
+                && ((*p)->output_section()->is_dynamic_linker_section()
+                    || (*p)->output_section()->type() == elfcpp::SHT_NOTE))
+           {
+             // Put reloc sections after the other ones.  Putting the
+             // dynamic reloc sections first confuses BFD, notably
+             // objcopy and strip.
+             if (!is_reloc
+                 && ((*p)->output_section()->type() == elfcpp::SHT_REL
+                     || (*p)->output_section()->type() == elfcpp::SHT_RELA))
+               break;
+             ++p;
+           }
+         pdl->insert(p, os);
+         return;
+       }
+    }
+
+  // If there were no constraints on the output section, just add it
+  // to the end of the list.
   pdl->push_back(os);
 }
 
index 841efd3..7e1c73b 100644 (file)
@@ -2378,6 +2378,27 @@ class Output_section : public Output_data
   is_large_data_section()
   { return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; }
 
+  // True if this is the .interp section which goes into the PT_INTERP
+  // segment.
+  bool
+  is_interp() const
+  { return this->is_interp_; }
+
+  // Record that this is the interp section.
+  void
+  set_is_interp()
+  { this->is_interp_ = true; }
+
+  // True if this is a section used by the dynamic linker.
+  bool
+  is_dynamic_linker_section() const
+  { return this->is_dynamic_linker_section_; }
+
+  // Record that this is a section used by the dynamic linker.
+  void
+  set_is_dynamic_linker_section()
+  { this->is_dynamic_linker_section_ = true; }
+
   // Return whether this section should be written after all the input
   // sections are complete.
   bool
@@ -3318,6 +3339,13 @@ class Output_section : public Output_data
   bool is_small_section_ : 1;
   // True if this is a large section.
   bool is_large_section_ : 1;
+  // True if this is the .interp section going into the PT_INTERP
+  // segment.
+  bool is_interp_ : 1;
+  // True if this is section is read by the dynamic linker.
+  bool is_dynamic_linker_section_ : 1;
+  // Whether code-fills are generated at write.
+  bool generate_code_fills_at_write_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
@@ -3328,13 +3356,11 @@ class Output_section : public Output_data
   // Map from merge section properties to merge_sections;
   Merge_section_by_properties_map merge_section_by_properties_map_;
   // Map from input sections to relaxed input sections.  This is mutable
-  // beacause it is udpated lazily.  We may need to update it in a
+  // because it is updated lazily.  We may need to update it in a
   // const qualified method.
   mutable Output_section_data_by_input_section_map relaxed_input_section_map_;
   // Whether relaxed_input_section_map_ is valid.
   mutable bool is_relaxed_input_section_map_valid_;
-  // Whether code-fills are generated at write.
-  bool generate_code_fills_at_write_;
 };
 
 // An output segment.  PT_LOAD segments are built from collections of
@@ -3403,9 +3429,12 @@ class Output_segment
   uint64_t
   maximum_alignment();
 
-  // Add an Output_section to this segment.
+  // Add the Output_section OS to this segment.  SEG_FLAGS is the
+  // segment flags to use.  DO_SORT is true if we should sort the
+  // placement of the input section for more efficient generated code.
   void
-  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags);
+  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags,
+                    bool do_sort);
 
   // Remove an Output_section from this segment.  It is an error if it
   // is not present.
index 081a8f5..0475f8e 100644 (file)
@@ -708,7 +708,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab,
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
-                                     this->got_);
+                                     this->got_, false);
 
       // Create the GOT2 or TOC in the .got section.
       if (size == 32)
@@ -717,7 +717,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab,
          layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS,
                                          elfcpp::SHF_ALLOC
                                          | elfcpp::SHF_WRITE,
-                                         this->got2_);
+                                         this->got2_, false);
        }
       else
        {
@@ -725,7 +725,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab,
          layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS,
                                          elfcpp::SHF_ALLOC
                                          | elfcpp::SHF_WRITE,
-                                         this->toc_);
+                                         this->toc_, false);
        }
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
@@ -751,7 +751,7 @@ Target_powerpc<size, big_endian>::rela_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-                                     elfcpp::SHF_ALLOC, this->rela_dyn_);
+                                     elfcpp::SHF_ALLOC, this->rela_dyn_, true);
     }
   return this->rela_dyn_;
 }
@@ -811,7 +811,7 @@ Output_data_plt_powerpc<size, big_endian>::Output_data_plt_powerpc(Layout* layou
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-                                 elfcpp::SHF_ALLOC, this->rel_);
+                                 elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 template<int size, bool big_endian>
@@ -940,7 +940,7 @@ Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR
                                       | elfcpp::SHF_WRITE),
-                                     this->plt_);
+                                     this->plt_, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
@@ -1502,7 +1502,7 @@ Target_powerpc<size, big_endian>::scan_relocs(
     Output_section* os = layout->add_output_section_data(".sdata", 0,
                                                         elfcpp::SHF_ALLOC
                                                         | elfcpp::SHF_WRITE,
-                                                        sdata);
+                                                        sdata, false);
     symtab->define_in_output_data("_SDA_BASE_", NULL,
                                  os,
                                  32768, 0,
index 8fb9a73..f38cbd0 100644 (file)
@@ -3094,7 +3094,7 @@ Script_sections::create_segments(Layout* layout)
          is_current_seg_readonly = true;
        }
 
-      current_seg->add_output_section(*p, seg_flags);
+      current_seg->add_output_section(*p, seg_flags, false);
 
       if (((*p)->flags() & elfcpp::SHF_WRITE) != 0)
        is_current_seg_readonly = false;
@@ -3173,7 +3173,7 @@ Script_sections::create_note_and_tls_segments(
            Layout::section_flags_to_segment((*p)->flags());
          Output_segment* oseg = layout->make_output_segment(elfcpp::PT_NOTE,
                                                             seg_flags);
-         oseg->add_output_section(*p, seg_flags);
+         oseg->add_output_section(*p, seg_flags, false);
 
          // Incorporate any subsequent SHT_NOTE sections, in the
          // hopes that the script is sensible.
@@ -3182,7 +3182,7 @@ Script_sections::create_note_and_tls_segments(
                 && (*pnext)->type() == elfcpp::SHT_NOTE)
            {
              seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
-             oseg->add_output_section(*pnext, seg_flags);
+             oseg->add_output_section(*pnext, seg_flags, false);
              p = pnext;
              ++pnext;
            }
@@ -3197,14 +3197,14 @@ Script_sections::create_note_and_tls_segments(
            Layout::section_flags_to_segment((*p)->flags());
          Output_segment* oseg = layout->make_output_segment(elfcpp::PT_TLS,
                                                             seg_flags);
-         oseg->add_output_section(*p, seg_flags);
+         oseg->add_output_section(*p, seg_flags, false);
 
          Layout::Section_list::const_iterator pnext = p + 1;
          while (pnext != sections->end()
                 && ((*pnext)->flags() & elfcpp::SHF_TLS) != 0)
            {
              seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
-             oseg->add_output_section(*pnext, seg_flags);
+             oseg->add_output_section(*pnext, seg_flags, false);
              p = pnext;
              ++pnext;
            }
@@ -3358,7 +3358,7 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
 
              elfcpp::Elf_Word seg_flags =
                Layout::section_flags_to_segment(os->flags());
-             r->second->add_output_section(os, seg_flags);
+             r->second->add_output_section(os, seg_flags, false);
 
              if (r->second->type() == elfcpp::PT_LOAD)
                {
index dc825f7..25f03d1 100644 (file)
@@ -1022,7 +1022,7 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab,
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_);
+                                          this->got_, false);
       os->set_is_relro();
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
@@ -1048,7 +1048,7 @@ Target_sparc<size, big_endian>::rela_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-                                     elfcpp::SHF_ALLOC, this->rela_dyn_);
+                                     elfcpp::SHF_ALLOC, this->rela_dyn_, true);
     }
   return this->rela_dyn_;
 }
@@ -1150,7 +1150,7 @@ Output_data_plt_sparc<size, big_endian>::Output_data_plt_sparc(Layout* layout)
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-                                 elfcpp::SHF_ALLOC, this->rel_);
+                                 elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 template<int size, bool big_endian>
@@ -1367,7 +1367,7 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR
                                       | elfcpp::SHF_WRITE),
-                                     this->plt_);
+                                     this->plt_, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
index 249d1f4..c325fc0 100644 (file)
@@ -467,7 +467,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_);
+                                          this->got_, false);
       os->set_is_relro();
 
       // The old GNU linker creates a .got.plt section.  We just
@@ -478,7 +478,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
-                                          this->got_plt_);
+                                          this->got_plt_, false);
       os->set_is_relro();
 
       // The first three entries are reserved.
@@ -506,7 +506,7 @@ Target_x86_64::rela_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-                                     elfcpp::SHF_ALLOC, this->rela_dyn_);
+                                     elfcpp::SHF_ALLOC, this->rela_dyn_, true);
     }
   return this->rela_dyn_;
 }
@@ -606,7 +606,7 @@ Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout,
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-                                 elfcpp::SHF_ALLOC, this->rel_);
+                                 elfcpp::SHF_ALLOC, this->rel_, true);
 }
 
 void
@@ -802,7 +802,7 @@ Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout)
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
-                                     this->plt_);
+                                     this->plt_, false);
     }
 }