PR gold/12629
authorIan Lance Taylor <ian@airs.com>
Thu, 30 Jun 2011 00:50:13 +0000 (00:50 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 30 Jun 2011 00:50:13 +0000 (00:50 +0000)
* object.cc (Sized_relobj_file::layout_section): Change shdr
parameter to be const.
(Sized_relobj_file::layout_eh_frame_section): New function, broken
out of do_layout.
(Sized_relobj_file::do_layout): Defer .eh_frame sections if
appropriate.  Call layout_eh_frame_section.
(Sized_relobj_file::do_layout_deferred_sections): Handle .eh_frame
sections.
* object.h (class Sized_relobj_file): Update declarations.

gold/ChangeLog
gold/object.cc
gold/object.h

index ae2142716aad46f55ffe5440bba99f1751d7970b..62ee3cad8be379b00d3190cac4a635c827605288 100644 (file)
@@ -1,3 +1,16 @@
+2011-06-29  Ian Lance Taylor  <iant@google.com>
+
+       PR gold/12629
+       * object.cc (Sized_relobj_file::layout_section): Change shdr
+       parameter to be const.
+       (Sized_relobj_file::layout_eh_frame_section): New function, broken
+       out of do_layout.
+       (Sized_relobj_file::do_layout): Defer .eh_frame sections if
+       appropriate.  Call layout_eh_frame_section.
+       (Sized_relobj_file::do_layout_deferred_sections): Handle .eh_frame
+       sections.
+       * object.h (class Sized_relobj_file): Update declarations.
+
 2011-06-29  Ian Lance Taylor  <iant@google.com>
 
        PR gold/12652
index 322f56edf2aba9e8b0823cb4366c54a142229745..d3835df900011d46834d306d4bc2806224984dc9 100644 (file)
@@ -1018,12 +1018,13 @@ Sized_relobj_file<size, big_endian>::include_linkonce_section(
 
 template<int size, bool big_endian>
 inline void
-Sized_relobj_file<size, big_endian>::layout_section(Layout* layout,
-                                                   unsigned int shndx,
-                                                   const char* name,
-                                                   typename This::Shdr& shdr,
-                                                   unsigned int reloc_shndx,
-                                                   unsigned int reloc_type)
+Sized_relobj_file<size, big_endian>::layout_section(
+    Layout* layout,
+    unsigned int shndx,
+    const char* name,
+    const typename This::Shdr& shdr,
+    unsigned int reloc_shndx,
+    unsigned int reloc_type)
 {
   off_t offset;
   Output_section* os = layout->layout(this, shndx, name, shdr,
@@ -1042,6 +1043,53 @@ Sized_relobj_file<size, big_endian>::layout_section(Layout* layout,
     this->set_relocs_must_follow_section_writes();
 }
 
+// Layout an input .eh_frame section.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
+    Layout* layout,
+    const unsigned char* symbols_data,
+    section_size_type symbols_size,
+    const unsigned char* symbol_names_data,
+    section_size_type symbol_names_size,
+    unsigned int shndx,
+    const typename This::Shdr& shdr,
+    unsigned int reloc_shndx,
+    unsigned int reloc_type)
+{
+  gold_assert(this->has_eh_frame_);
+
+  off_t offset;
+  Output_section* os = layout->layout_eh_frame(this,
+                                              symbols_data,
+                                              symbols_size,
+                                              symbol_names_data,
+                                              symbol_names_size,
+                                              shndx,
+                                              shdr,
+                                              reloc_shndx,
+                                              reloc_type,
+                                              &offset);
+  this->output_sections()[shndx] = os;
+  if (os == NULL || offset == -1)
+    {
+      // An object can contain at most one section holding exception
+      // frame information.
+      gold_assert(this->discarded_eh_frame_shndx_ == -1U);
+      this->discarded_eh_frame_shndx_ = shndx;
+      this->section_offsets()[shndx] = invalid_address;
+    }
+  else
+    this->section_offsets()[shndx] = convert_types<Address, off_t>(offset);
+
+  // If this section requires special handling, and if there are
+  // relocs that aply to it, then we must do the special handling
+  // before we apply the relocs.
+  if (os != NULL && offset == -1 && reloc_shndx != 0)
+    this->set_relocs_must_follow_section_writes();
+}
+
 // Lay out the input sections.  We walk through the sections and check
 // whether they should be included in the link.  If they should, we
 // pass them to the Layout object, which will return an output section
@@ -1367,7 +1415,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
               out_sections[i] = reinterpret_cast<Output_section*>(1);
               out_section_offsets[i] = invalid_address;
             }
-          else
+          else if (should_defer_layout)
+           this->deferred_layout_.push_back(Deferred_layout(i, name,
+                                                            pshdrs,
+                                                            reloc_shndx[i],
+                                                            reloc_type[i]));
+         else
             eh_frame_sections.push_back(i);
           continue;
         }
@@ -1527,7 +1580,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        p != eh_frame_sections.end();
        ++p)
     {
-      gold_assert(this->has_eh_frame_);
       gold_assert(external_symbols_offset != 0);
 
       unsigned int i = *p;
@@ -1535,33 +1587,15 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       pshdr = section_headers_data + i * This::shdr_size;
       typename This::Shdr shdr(pshdr);
 
-      off_t offset;
-      Output_section* os = layout->layout_eh_frame(this,
-                                                  symbols_data,
-                                                  symbols_size,
-                                                  symbol_names_data,
-                                                  symbol_names_size,
-                                                  i, shdr,
-                                                  reloc_shndx[i],
-                                                  reloc_type[i],
-                                                  &offset);
-      out_sections[i] = os;
-      if (os == NULL || offset == -1)
-       {
-         // An object can contain at most one section holding exception
-         // frame information.
-         gold_assert(this->discarded_eh_frame_shndx_ == -1U);
-         this->discarded_eh_frame_shndx_ = i;
-         out_section_offsets[i] = invalid_address;
-       }
-      else
-        out_section_offsets[i] = convert_types<Address, off_t>(offset);
-
-      // If this section requires special handling, and if there are
-      // relocs that apply to it, then we must do the special handling
-      // before we apply the relocs.
-      if (os != NULL && offset == -1 && reloc_shndx[i] != 0)
-       this->set_relocs_must_follow_section_writes();
+      this->layout_eh_frame_section(layout,
+                                   symbols_data,
+                                   symbols_size,
+                                   symbol_names_data,
+                                   symbol_names_size,
+                                   i,
+                                   shdr,
+                                   reloc_shndx[i],
+                                   reloc_type[i]);
     }
 
   if (is_gc_pass_two)
@@ -1600,8 +1634,27 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
       if (!this->is_section_included(deferred->shndx_))
         continue;
 
-      this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
-                           shdr, deferred->reloc_shndx_, deferred->reloc_type_);
+      if (parameters->options().relocatable()
+         || deferred->name_ != ".eh_frame"
+         || !this->check_eh_frame_flags(&shdr))
+       this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
+                            shdr, deferred->reloc_shndx_,
+                            deferred->reloc_type_);
+      else
+       {
+         // Reading the symbols again here may be slow.
+         Read_symbols_data sd;
+         this->read_symbols(&sd);
+         this->layout_eh_frame_section(layout,
+                                       sd.symbols->data(),
+                                       sd.symbols_size,
+                                       sd.symbol_names->data(),
+                                       sd.symbol_names_size,
+                                       deferred->shndx_,
+                                       shdr,
+                                       deferred->reloc_shndx_,
+                                       deferred->reloc_type_);
+       }
     }
 
   this->deferred_layout_.clear();
index 8735f9e976cad99139d93ea8723bc2c98d153c31..9c363cd6f72b03660795290a568f9e074250d779 100644 (file)
@@ -2306,9 +2306,18 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   // Layout an input section.
   void
   layout_section(Layout* layout, unsigned int shndx, const char* name,
-                 typename This::Shdr& shdr, unsigned int reloc_shndx,
+                 const typename This::Shdr& shdr, unsigned int reloc_shndx,
                  unsigned int reloc_type);
 
+  // Layout an input .eh_frame section.
+  void
+  layout_eh_frame_section(Layout* layout, const unsigned char* symbols_data,
+                         section_size_type symbols_size,
+                         const unsigned char* symbol_names_data,
+                         section_size_type symbol_names_size,
+                         unsigned int shndx, const typename This::Shdr&,
+                         unsigned int reloc_shndx, unsigned int reloc_type);
+
   // Write section data to the output file.  Record the views and
   // sizes in VIEWS for use when relocating.
   void