]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gold/layout.cc
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gold / layout.cc
index 194d088c2a19a4cce1f22ce53f87db77e983ca99..a27cb071c75d8537800b096287d23eda6cd8a2e0 100644 (file)
@@ -1,6 +1,6 @@
 // layout.cc -- lay out output file sections for gold
 
-// Copyright (C) 2006-2019 Free Software Foundation, Inc.
+// Copyright (C) 2006-2021 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -1099,7 +1099,8 @@ Layout::init_fixed_output_section(const char* name,
   typename elfcpp::Elf_types<size>::Elf_Addr sh_addr = shdr.get_sh_addr();
   typename elfcpp::Elf_types<size>::Elf_Off sh_offset = shdr.get_sh_offset();
   typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size();
-  typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
+  typename elfcpp::Elf_types<size>::Elf_WXword sh_flags =
+      this->get_output_section_flags(shdr.get_sh_flags());
   typename elfcpp::Elf_types<size>::Elf_WXword sh_addralign =
       shdr.get_sh_addralign();
 
@@ -1129,7 +1130,8 @@ Layout::special_ordering_of_input_section(const char* name)
     ".text.unlikely",
     ".text.exit",
     ".text.startup",
-    ".text.hot"
+    ".text.hot",
+    ".text.sorted"
   };
 
   for (size_t i = 0;
@@ -1171,35 +1173,38 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
     {
       // Some flags in the input section should not be automatically
       // copied to the output section.
-      elfcpp::Elf_Xword flags = (shdr.get_sh_flags()
-                                & ~ elfcpp::SHF_COMPRESSED);
+      elfcpp::Elf_Xword sh_flags = (shdr.get_sh_flags()
+                                   & ~ elfcpp::SHF_COMPRESSED);
       name = this->namepool_.add(name, true, NULL);
-      os = this->make_output_section(name, sh_type, flags,
-                                    ORDER_INVALID, false);
+      os = this->make_output_section(name, sh_type, sh_flags, ORDER_INVALID,
+                                    false);
     }
   else
     {
+      // Get the section flags and mask out any flags that do not
+      // take part in section matching.
+      elfcpp::Elf_Xword sh_flags
+         = (this->get_output_section_flags(shdr.get_sh_flags())
+            & ~object->osabi().ignored_sh_flags());
+
       // All ".text.unlikely.*" sections can be moved to a unique
       // segment with --text-unlikely-segment option.
       bool text_unlikely_segment
-          = (parameters->options().text_unlikely_segment()
-             && is_prefix_of(".text.unlikely",
-                             object->section_name(shndx).c_str()));
+         = (parameters->options().text_unlikely_segment()
+            && is_prefix_of(".text.unlikely",
+                            object->section_name(shndx).c_str()));
       if (text_unlikely_segment)
-        {
-         elfcpp::Elf_Xword flags
-           = this->get_output_section_flags(shdr.get_sh_flags());
-
+       {
          Stringpool::Key name_key;
          const char* os_name = this->namepool_.add(".text.unlikely", true,
                                                    &name_key);
-         os = this->get_output_section(os_name, name_key, sh_type, flags,
+         os = this->get_output_section(os_name, name_key, sh_type, sh_flags,
                                        ORDER_INVALID, false);
-          // Map this output section to a unique segment.  This is done to
-          // separate "text" that is not likely to be executed from "text"
-          // that is likely executed.
+         // Map this output section to a unique segment.  This is done to
+         // separate "text" that is not likely to be executed from "text"
+         // that is likely executed.
          os->set_is_unique_segment();
-        }
+       }
       else
        {
          // Plugins can choose to place one or more subsets of sections in
@@ -1211,28 +1216,24 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
          if (it == this->section_segment_map_.end())
            {
              os = this->choose_output_section(object, name, sh_type,
-                                              shdr.get_sh_flags(), true,
-                                              ORDER_INVALID, false, false,
-                                              true);
+                                              sh_flags, true, ORDER_INVALID,
+                                              false, false, true);
            }
          else
            {
              // We know the name of the output section, directly call
              // get_output_section here by-passing choose_output_section.
-             elfcpp::Elf_Xword flags
-               = this->get_output_section_flags(shdr.get_sh_flags());
-
              const char* os_name = it->second->name;
              Stringpool::Key name_key;
              os_name = this->namepool_.add(os_name, true, &name_key);
-             os = this->get_output_section(os_name, name_key, sh_type, flags,
-                                       ORDER_INVALID, false);
+             os = this->get_output_section(os_name, name_key, sh_type,
+                                           sh_flags, ORDER_INVALID, false);
              if (!os->is_unique_segment())
-               {
-                 os->set_is_unique_segment();
-                 os->set_extra_segment_flags(it->second->flags);
-                 os->set_segment_alignment(it->second->align);
-               }
+               {
+                 os->set_is_unique_segment();
+                 os->set_extra_segment_flags(it->second->flags);
+                 os->set_segment_alignment(it->second->align);
+               }
            }
          }
       if (os == NULL)
@@ -2061,12 +2062,15 @@ Layout::attach_allocated_section_to_segment(const Target* target,
   // segment.
   if (os->type() == elfcpp::SHT_NOTE)
     {
+      uint64_t os_align = os->addralign();
+
       // See if we already have an equivalent PT_NOTE segment.
       for (p = this->segment_list_.begin();
           p != segment_list_.end();
           ++p)
        {
          if ((*p)->type() == elfcpp::PT_NOTE
+             && (*p)->align() == os_align
              && (((*p)->flags() & elfcpp::PF_W)
                  == (seg_flags & elfcpp::PF_W)))
            {
@@ -2080,6 +2084,7 @@ Layout::attach_allocated_section_to_segment(const Target* target,
          Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
                                                           seg_flags);
          oseg->add_output_section_to_nonload(os, seg_flags);
+         oseg->set_align(os_align);
        }
     }
 
@@ -2267,9 +2272,9 @@ Layout::layout_gnu_property(unsigned int note_type,
       const int size = parameters->target().get_size();
       const bool is_big_endian = parameters->target().is_big_endian();
       if (size == 32)
-        {
-          if (is_big_endian)
-            {
+       {
+         if (is_big_endian)
+           {
 #ifdef HAVE_TARGET_32_BIG
              parameters->sized_target<32, true>()->
                  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
@@ -2277,9 +2282,9 @@ Layout::layout_gnu_property(unsigned int note_type,
 #else
              gold_unreachable();
 #endif
-            }
-          else
-            {
+           }
+         else
+           {
 #ifdef HAVE_TARGET_32_LITTLE
              parameters->sized_target<32, false>()->
                  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
@@ -2287,12 +2292,12 @@ Layout::layout_gnu_property(unsigned int note_type,
 #else
              gold_unreachable();
 #endif
-            }
-        }
+           }
+       }
       else if (size == 64)
-        {
-          if (is_big_endian)
-            {
+       {
+         if (is_big_endian)
+           {
 #ifdef HAVE_TARGET_64_BIG
              parameters->sized_target<64, true>()->
                  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
@@ -2300,9 +2305,9 @@ Layout::layout_gnu_property(unsigned int note_type,
 #else
              gold_unreachable();
 #endif
-            }
-          else
-            {
+           }
+         else
+           {
 #ifdef HAVE_TARGET_64_LITTLE
              parameters->sized_target<64, false>()->
                  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
@@ -2310,10 +2315,10 @@ Layout::layout_gnu_property(unsigned int note_type,
 #else
              gold_unreachable();
 #endif
-            }
-        }
+           }
+       }
       else
-        gold_unreachable();
+       gold_unreachable();
       return;
     }
 
@@ -2473,6 +2478,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab)
 void
 Layout::define_section_symbols(Symbol_table* symtab)
 {
+  const elfcpp::STV visibility = parameters->options().start_stop_visibility_enum();
   for (Section_list::const_iterator p = this->section_list_.begin();
        p != this->section_list_.end();
        ++p)
@@ -2494,7 +2500,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
                                        0, // symsize
                                        elfcpp::STT_NOTYPE,
                                        elfcpp::STB_GLOBAL,
-                                       elfcpp::STV_PROTECTED,
+                                       visibility,
                                        0, // nonvis
                                        false, // offset_is_from_end
                                        true); // only_if_ref
@@ -2507,7 +2513,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
                                        0, // symsize
                                        elfcpp::STT_NOTYPE,
                                        elfcpp::STB_GLOBAL,
-                                       elfcpp::STV_PROTECTED,
+                                       visibility,
                                        0, // nonvis
                                        true, // offset_is_from_end
                                        true); // only_if_ref
@@ -2920,6 +2926,8 @@ Layout::read_layout_from_file()
     gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
               filename, strerror(errno));
 
+  File_read::record_file_read(filename);
+
   std::getline(in, line);   // this chops off the trailing \n, if any
   unsigned int position = 1;
   this->set_section_ordering_specified();
@@ -3180,6 +3188,10 @@ Layout::create_note(const char* name, int note_type,
 #else
   const int size = 32;
 #endif
+  // The NT_GNU_PROPERTY_TYPE_0 note is aligned to the pointer size.
+  const int addralign = ((note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0
+                        ? parameters->target().get_size()
+                        : size) / 8);
 
   // The contents of the .note section.
   size_t namesz = strlen(name) + 1;
@@ -3243,7 +3255,7 @@ Layout::create_note(const char* name, int note_type,
     return NULL;
 
   Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
-                                                          size / 8,
+                                                          addralign,
                                                           "** note header");
   os->add_output_section_data(posd);
 
@@ -3297,7 +3309,7 @@ Layout::create_gnu_properties_note()
       write_sized_value(datasz, 4, p + 4, is_big_endian);
       memcpy(p + 8, prop->second.pr_data, datasz);
       if (aligned_datasz > datasz)
-        memset(p + 8 + datasz, 0, aligned_datasz - datasz);
+       memset(p + 8 + datasz, 0, aligned_datasz - datasz);
       p += 8 + aligned_datasz;
     }
   Output_section_data* posd = new Output_data_const(desc, descsz, 4);
@@ -3701,6 +3713,11 @@ Layout::segment_precedes(const Output_segment* seg1,
     {
       if (type1 != type2)
        return type1 < type2;
+      uint64_t align1 = seg1->align();
+      uint64_t align2 = seg2->align();
+      // Place segments with larger alignments first.
+      if (align1 != align2)
+       return align1 > align2;
       gold_assert(flags1 != flags2
                  || this->script_options_->saw_phdrs_clause());
       return flags1 < flags2;
@@ -5350,8 +5367,16 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
     flags |= elfcpp::DF_1_NOW;
   if (parameters->options().Bgroup())
     flags |= elfcpp::DF_1_GROUP;
+  if (parameters->options().pie())
+    flags |= elfcpp::DF_1_PIE;
   if (flags != 0)
     odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
+
+  flags = 0;
+  if (parameters->options().unique())
+    flags |= elfcpp::DF_GNU_1_UNIQUE;
+  if (flags != 0)
+    odyn->add_constant(elfcpp::DT_GNU_FLAGS_1, flags);
 }
 
 // Set the size of the _DYNAMIC symbol table to be the size of the
@@ -6152,6 +6177,10 @@ Close_task_runner::run(Workqueue*, const Task*)
   if (this->options_->oformat_enum() != General_options::OBJECT_FORMAT_ELF)
     this->layout_->write_binary(this->of_);
 
+  if (this->options_->dependency_file())
+    File_read::write_dependency_file(this->options_->dependency_file(),
+                                    this->options_->output_file_name());
+
   this->of_->close();
 }