* object.cc (Sized_relobj::layout_section): New function.
[deliverable/binutils-gdb.git] / gold / layout.cc
index a4003d557367e2e56edbe715b4bf7113a70f97ce..a4f17e535574b487eadf2559bbc5b6e1f2585f0b 100644 (file)
 #include "dynobj.h"
 #include "ehframe.h"
 #include "compressed_output.h"
+#include "reduced_debug_output.h"
 #include "reloc.h"
+#include "descriptors.h"
 #include "layout.h"
+#include "plugin.h"
 
 namespace gold
 {
@@ -110,6 +113,8 @@ Layout::Layout(const General_options& options, Script_options* script_options)
     added_eh_frame_data_(false),
     eh_frame_hdr_section_(NULL),
     build_id_note_(NULL),
+    debug_abbrev_(NULL),
+    debug_info_(NULL),
     group_signatures_(),
     output_file_size_(-1),
     input_requires_executable_stack_(false),
@@ -160,6 +165,19 @@ static const char* gdb_sections[] =
   ".debug_str",
 };
 
+static const char* lines_only_debug_sections[] =
+{ ".debug_abbrev",
+  // ".debug_aranges",   // not used by gdb as of 6.7.1
+  // ".debug_frame",
+  ".debug_info",
+  ".debug_line",
+  // ".debug_loc",
+  // ".debug_macinfo",
+  // ".debug_pubnames",  // not used by gdb as of 6.7.1
+  // ".debug_ranges",
+  ".debug_str",
+};
+
 static inline bool
 is_gdb_debug_section(const char* str)
 {
@@ -170,6 +188,18 @@ is_gdb_debug_section(const char* str)
   return false;
 }
 
+static inline bool
+is_lines_only_debug_section(const char* str)
+{
+  // We can do this faster: binary search or a hashtable.  But why bother?
+  for (size_t i = 0;
+       i < sizeof(lines_only_debug_sections)/sizeof(*lines_only_debug_sections);
+       ++i)
+    if (strcmp(str, lines_only_debug_sections[i]) == 0)
+      return true;
+  return false;
+}
+
 // Whether to include this section in the link.
 
 template<int size, bool big_endian>
@@ -177,17 +207,27 @@ bool
 Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
                        const elfcpp::Shdr<size, big_endian>& shdr)
 {
+  if (shdr.get_sh_flags() & elfcpp::SHF_EXCLUDE)
+    return false;
+
   switch (shdr.get_sh_type())
     {
     case elfcpp::SHT_NULL:
     case elfcpp::SHT_SYMTAB:
     case elfcpp::SHT_DYNSYM:
-    case elfcpp::SHT_STRTAB:
     case elfcpp::SHT_HASH:
     case elfcpp::SHT_DYNAMIC:
     case elfcpp::SHT_SYMTAB_SHNDX:
       return false;
 
+    case elfcpp::SHT_STRTAB:
+      // Discard the sections which have special meanings in the ELF
+      // ABI.  Keep others (e.g., .stabstr).  We could also do this by
+      // checking the sh_link fields of the appropriate sections.
+      return (strcmp(name, ".dynstr") != 0
+             && strcmp(name, ".strtab") != 0
+             && strcmp(name, ".shstrtab") != 0);
+
     case elfcpp::SHT_RELA:
     case elfcpp::SHT_REL:
     case elfcpp::SHT_GROUP:
@@ -204,6 +244,14 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
          if (is_debug_info_section(name))
            return false;
        }
+      if (parameters->options().strip_debug_non_line()
+         && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+       {
+         // Debugging sections can only be recognized by name.
+         if (is_prefix_of(".debug", name)
+              && !is_lines_only_debug_section(name))
+           return false;
+       }
       if (parameters->options().strip_debug_gdb()
          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
        {
@@ -212,6 +260,14 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
               && !is_gdb_debug_section(name))
            return false;
        }
+      if (parameters->options().strip_lto_sections()
+          && !parameters->options().relocatable()
+          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+        {
+          // Ignore LTO sections containing intermediate code.
+          if (is_prefix_of(".gnu.lto_", name))
+            return false;
+        }
       return true;
 
     default:
@@ -405,6 +461,8 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
               const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
               unsigned int reloc_shndx, unsigned int, off_t* off)
 {
+  *off = 0;
+
   if (!this->include_section(object, name, shdr))
     return NULL;
 
@@ -702,7 +760,26 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
       && strcmp(this->options_.compress_debug_sections(), "none") != 0
       && is_compressible_debug_section(name))
     os = new Output_compressed_section(&this->options_, name, type, flags);
-  else
+
+  else if ((flags & elfcpp::SHF_ALLOC) == 0
+           && this->options_.strip_debug_non_line()
+           && strcmp(".debug_abbrev", name) == 0)
+    {
+      os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section(
+          name, type, flags);
+      if (this->debug_info_)
+        this->debug_info_->set_abbreviations(this->debug_abbrev_);
+    }
+  else if ((flags & elfcpp::SHF_ALLOC) == 0
+           && this->options_.strip_debug_non_line()
+           && strcmp(".debug_info", name) == 0)
+    {
+      os = this->debug_info_ = new Output_reduced_debug_info_section(
+          name, type, flags);
+      if (this->debug_abbrev_)
+        this->debug_info_->set_abbreviations(this->debug_abbrev_);
+    }
+ else
     os = new Output_section(name, type, flags);
 
   this->section_list_.push_back(os);
@@ -801,7 +878,8 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
        ++p)
     {
       if ((*p)->type() == elfcpp::PT_LOAD
-          && ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))
+         && (parameters->options().omagic()
+             || ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W)))
         {
           // If -Tbss was specified, we need to separate the data
           // and BSS segments.
@@ -855,8 +933,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
   if ((flags & elfcpp::SHF_TLS) != 0)
     {
       if (this->tls_segment_ == NULL)
-        this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS,
-                                                       seg_flags);
+       this->make_output_segment(elfcpp::PT_TLS, seg_flags);
       this->tls_segment_->add_output_section(os, seg_flags);
     }
 
@@ -866,8 +943,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->relro_segment_ = this->make_output_segment(elfcpp::PT_GNU_RELRO,
-                                                        seg_flags);
+       this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
       this->relro_segment_->add_output_section(os, seg_flags);
     }
 }
@@ -1044,7 +1120,8 @@ Layout::find_first_load_seg()
     {
       if ((*p)->type() == elfcpp::PT_LOAD
          && ((*p)->flags() & elfcpp::PF_R) != 0
-         && ((*p)->flags() & elfcpp::PF_W) == 0)
+         && (parameters->options().omagic()
+             || ((*p)->flags() & elfcpp::PF_W) == 0))
        return *p;
     }
 
@@ -1441,14 +1518,14 @@ Layout::create_build_id()
       char buffer[uuidsz];
       memset(buffer, 0, uuidsz);
 
-      int descriptor = ::open("/dev/urandom", O_RDONLY);
+      int descriptor = open_descriptor(-1, "/dev/urandom", O_RDONLY);
       if (descriptor < 0)
        gold_error(_("--build-id=uuid failed: could not open /dev/urandom: %s"),
                   strerror(errno));
       else
        {
          ssize_t got = ::read(descriptor, buffer, uuidsz);
-         ::close(descriptor);
+         release_descriptor(descriptor, true);
          if (got < 0)
            gold_error(_("/dev/urandom: read failed: %s"), strerror(errno));
          else if (static_cast<size_t>(got) != uuidsz)
@@ -1666,6 +1743,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
        }
     }
 
+  const bool check_sections = parameters->options().check_sections();
+  Output_segment* last_load_segment = NULL;
+
   bool was_readonly = false;
   for (Segment_list::iterator p = this->segment_list_.begin();
        p != this->segment_list_.end();
@@ -1705,20 +1785,26 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
 
          uint64_t aligned_addr = 0;
          uint64_t abi_pagesize = target->abi_pagesize();
+         uint64_t common_pagesize = target->common_pagesize();
 
-         // FIXME: This should depend on the -n and -N options.
-         (*p)->set_minimum_p_align(target->common_pagesize());
+         if (!parameters->options().nmagic()
+             && !parameters->options().omagic())
+           (*p)->set_minimum_p_align(common_pagesize);
 
          if (are_addresses_set)
            {
-             // Adjust the file offset to the same address modulo the
-             // page size.
-             uint64_t unsigned_off = off;
-             uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1))
-                                     | (addr & (abi_pagesize - 1)));
-             if (aligned_off < unsigned_off)
-               aligned_off += abi_pagesize;
-             off = aligned_off;
+             if (!parameters->options().nmagic()
+                 && !parameters->options().omagic())
+               {
+                 // Adjust the file offset to the same address modulo
+                 // the page size.
+                 uint64_t unsigned_off = off;
+                 uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1))
+                                         | (addr & (abi_pagesize - 1)));
+                 if (aligned_off < unsigned_off)
+                   aligned_off += abi_pagesize;
+                 off = aligned_off;
+               }
            }
          else
            {
@@ -1753,7 +1839,6 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
 
          if (!are_addresses_set && aligned_addr != addr)
            {
-             uint64_t common_pagesize = target->common_pagesize();
              uint64_t first_off = (common_pagesize
                                    - (aligned_addr
                                       & (common_pagesize - 1)));
@@ -1777,6 +1862,25 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
 
          if (((*p)->flags() & elfcpp::PF_W) == 0)
            was_readonly = true;
+
+         // Implement --check-sections.  We know that the segments
+         // are sorted by LMA.
+         if (check_sections && last_load_segment != NULL)
+           {
+             gold_assert(last_load_segment->paddr() <= (*p)->paddr());
+             if (last_load_segment->paddr() + last_load_segment->memsz()
+                 > (*p)->paddr())
+               {
+                 unsigned long long lb1 = last_load_segment->paddr();
+                 unsigned long long le1 = lb1 + last_load_segment->memsz();
+                 unsigned long long lb2 = (*p)->paddr();
+                 unsigned long long le2 = lb2 + (*p)->memsz();
+                 gold_error(_("load segment overlap [0x%llx -> 0x%llx] and "
+                              "[0x%llx -> 0x%llx]"),
+                            lb1, le1, lb2, le2);
+               }
+           }
+         last_load_segment = *p;
        }
     }
 
@@ -2661,6 +2765,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
     }
   if (parameters->options().shared() && this->has_static_tls())
     flags |= elfcpp::DF_STATIC_TLS;
+  if (parameters->options().origin())
+    flags |= elfcpp::DF_ORIGIN;
   odyn->add_constant(elfcpp::DT_FLAGS, flags);
 
   flags = 0;
@@ -2682,6 +2788,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
     flags &= ~(elfcpp::DF_1_INITFIRST
               | elfcpp::DF_1_NODELETE
               | elfcpp::DF_1_NOOPEN);
+  if (parameters->options().origin())
+    flags |= elfcpp::DF_1_ORIGIN;
   if (flags)
     odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
 }
@@ -2852,6 +2960,14 @@ Layout::add_comdat(Relobj* object, unsigned int shndx,
   if (ins.first->second.group_)
     {
       // We've already seen a real section group with this signature.
+      // If the kept group is from a plugin object, and we're in
+      // the replacement phase, accept the new one as a replacement.
+      if (ins.first->second.object_ == NULL
+          && parameters->options().plugins()->in_replacement_phase())
+        {
+          ins.first->second = kept;
+          return true;
+        }
       return false;
     }
   else if (group)
@@ -2905,6 +3021,12 @@ Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
   gold_assert(!parameters->options().relocatable());
   Output_segment* oseg = new Output_segment(type, flags);
   this->segment_list_.push_back(oseg);
+
+  if (type == elfcpp::PT_TLS)
+    this->tls_segment_ = oseg;
+  else if (type == elfcpp::PT_GNU_RELRO)
+    this->relro_segment_ = oseg;
+
   return oseg;
 }
 
This page took 0.026989 seconds and 4 git commands to generate.