PR gold/13163
[binutils-gdb.git] / gold / script-sections.cc
index 3bcc9e6adaa981821888f78aa16e8c64194fe1a7..eba6b9d71e2abe2d30766c91383882b9d0e80b47 100644 (file)
@@ -892,6 +892,12 @@ class Output_section_element_dot_assignment : public Output_section_element
     : val_(val)
   { }
 
+  // An assignment to dot within an output section is enough to force
+  // the output section to exist.
+  bool
+  needs_output_section() const
+  { return true; }
+
   // Finalize the symbol.
   void
   finalize_symbols(Symbol_table* symtab, const Layout* layout,
@@ -3936,6 +3942,18 @@ Script_sections::create_note_and_tls_segments(
 
          saw_tls = true;
        }
+
+      // If we are making a shared library, and we see a section named
+      // .interp then put the .interp section in a PT_INTERP segment.
+      // This is for GNU ld compatibility.
+      if (strcmp((*p)->name(), ".interp") == 0)
+       {
+         elfcpp::Elf_Word seg_flags =
+           Layout::section_flags_to_segment((*p)->flags());
+         Output_segment* oseg = layout->make_output_segment(elfcpp::PT_INTERP,
+                                                            seg_flags);
+         oseg->add_output_section_to_nonload(*p, seg_flags);
+       }
     }
 }
 
@@ -4038,15 +4056,37 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
        p != this->sections_elements_->end();
        ++p)
     {
-      bool orphan;
+      bool is_orphan;
       String_list* old_phdr_names = phdr_names;
-      Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan);
+      Output_section* os = (*p)->allocate_to_segment(&phdr_names, &is_orphan);
       if (os == NULL)
        continue;
 
+      elfcpp::Elf_Word seg_flags =
+       Layout::section_flags_to_segment(os->flags());
+
       if (phdr_names == NULL)
        {
-         gold_error(_("allocated section not in any segment"));
+         // Don't worry about empty orphan sections.
+         if (is_orphan && os->current_data_size() > 0)
+           gold_error(_("allocated section %s not in any segment"),
+                      os->name());
+
+         // To avoid later crashes drop this section into the first
+         // PT_LOAD segment.
+         for (Phdrs_elements::const_iterator ppe =
+                this->phdrs_elements_->begin();
+              ppe != this->phdrs_elements_->end();
+              ++ppe)
+           {
+             Output_segment* oseg = (*ppe)->segment();
+             if (oseg->type() == elfcpp::PT_LOAD)
+               {
+                 oseg->add_output_section_to_load(layout, os, seg_flags);
+                 break;
+               }
+           }
+
          continue;
        }
 
@@ -4061,7 +4101,7 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
       // 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)
+      if (is_orphan)
        {
          // Enable PT_LOAD segments only filtering until we see another
          // list of segment names.
@@ -4082,9 +4122,6 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
                  && r->second->type() != elfcpp::PT_LOAD)
                continue;
 
-             elfcpp::Elf_Word seg_flags =
-               Layout::section_flags_to_segment(os->flags());
-
              if (r->second->type() != elfcpp::PT_LOAD)
                r->second->add_output_section_to_nonload(os, seg_flags);
              else