gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / object.cc
index 2b58f04ce6646d10158c7e2fe10417b144dc6ce3..c486a2011d5c4d5167272ca83d93cd20f90bbf3d 100644 (file)
@@ -1,6 +1,6 @@
 // object.cc -- support for an object file for linking in gold
 
-// Copyright (C) 2006-2018 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -751,11 +751,13 @@ build_compressed_section_map(
              const unsigned char* contents =
                  obj->section_contents(i, &len, false);
              uint64_t uncompressed_size;
+             Compressed_section_info info;
              if (is_zcompressed)
                {
                  // Skip over the ".zdebug" prefix.
                  name += 7;
                  uncompressed_size = get_uncompressed_size(contents, len);
+                 info.addralign = shdr.get_sh_addralign();
                }
              else
                {
@@ -763,8 +765,8 @@ build_compressed_section_map(
                  name += 6;
                  elfcpp::Chdr<size, big_endian> chdr(contents);
                  uncompressed_size = chdr.get_ch_size();
+                 info.addralign = chdr.get_ch_addralign();
                }
-             Compressed_section_info info;
              info.size = convert_to_section_size_type(uncompressed_size);
              info.flag = shdr.get_sh_flags();
              info.contents = NULL;
@@ -1282,6 +1284,114 @@ Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
     this->set_relocs_must_follow_section_writes();
 }
 
+// Layout an input .note.gnu.property section.
+
+// This note section has an *extremely* non-standard layout.
+// The gABI spec says that ELF-64 files should have 8-byte fields and
+// 8-byte alignment in the note section, but the Gnu tools generally
+// use 4-byte fields and 4-byte alignment (see the comment for
+// Layout::create_note).  This section uses 4-byte fields (i.e.,
+// namesz, descsz, and type are always 4 bytes), the name field is
+// padded to a multiple of 4 bytes, but the desc field is padded
+// to a multiple of 4 or 8 bytes, depending on the ELF class.
+// The individual properties within the desc field always use
+// 4-byte pr_type and pr_datasz fields, but pr_data is padded to
+// a multiple of 4 or 8 bytes, depending on the ELF class.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::layout_gnu_property_section(
+    Layout* layout,
+    unsigned int shndx)
+{
+  section_size_type contents_len;
+  const unsigned char* pcontents = this->section_contents(shndx,
+                                                         &contents_len,
+                                                         false);
+  const unsigned char* pcontents_end = pcontents + contents_len;
+
+  // Loop over all the notes in this section.
+  while (pcontents < pcontents_end)
+    {
+      if (pcontents + 16 > pcontents_end)
+       {
+         gold_warning(_("%s: corrupt .note.gnu.property section "
+                        "(note too short)"),
+                      this->name().c_str());
+         return;
+       }
+
+      size_t namesz = elfcpp::Swap<32, big_endian>::readval(pcontents);
+      size_t descsz = elfcpp::Swap<32, big_endian>::readval(pcontents + 4);
+      unsigned int ntype = elfcpp::Swap<32, big_endian>::readval(pcontents + 8);
+      const unsigned char* pname = pcontents + 12;
+
+      if (namesz != 4 || strcmp(reinterpret_cast<const char*>(pname), "GNU") != 0)
+       {
+         gold_warning(_("%s: corrupt .note.gnu.property section "
+                        "(name is not 'GNU')"),
+                      this->name().c_str());
+         return;
+       }
+
+      if (ntype != elfcpp::NT_GNU_PROPERTY_TYPE_0)
+       {
+         gold_warning(_("%s: unsupported note type %d "
+                        "in .note.gnu.property section"),
+                      this->name().c_str(), ntype);
+         return;
+       }
+
+      size_t aligned_namesz = align_address(namesz, 4);
+      const unsigned char* pdesc = pname + aligned_namesz;
+
+      if (pdesc + descsz > pcontents + contents_len)
+       {
+         gold_warning(_("%s: corrupt .note.gnu.property section"),
+                      this->name().c_str());
+         return;
+       }
+
+      const unsigned char* pprop = pdesc;
+
+      // Loop over the program properties in this note.
+      while (pprop < pdesc + descsz)
+       {
+         if (pprop + 8 > pdesc + descsz)
+           {
+             gold_warning(_("%s: corrupt .note.gnu.property section"),
+                          this->name().c_str());
+             return;
+           }
+         unsigned int pr_type = elfcpp::Swap<32, big_endian>::readval(pprop);
+         size_t pr_datasz = elfcpp::Swap<32, big_endian>::readval(pprop + 4);
+         pprop += 8;
+         if (pprop + pr_datasz > pdesc + descsz)
+           {
+             gold_warning(_("%s: corrupt .note.gnu.property section"),
+                          this->name().c_str());
+             return;
+           }
+         layout->layout_gnu_property(ntype, pr_type, pr_datasz, pprop, this);
+         pprop += align_address(pr_datasz, size / 8);
+       }
+
+      pcontents = pdesc + align_address(descsz, size / 8);
+    }
+}
+
+// This a copy of lto_section defined in GCC (lto-streamer.h)
+
+struct lto_section
+{
+  int16_t major_version;
+  int16_t minor_version;
+  unsigned char slim_object;
+
+  /* Flags is a private field that is not defined publicly.  */
+  uint16_t flags;
+};
+
 // 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
@@ -1538,6 +1648,14 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
              omit[i] = true;
            }
 
+         // Handle .note.gnu.property sections.
+         if (sh_type == elfcpp::SHT_NOTE
+             && strcmp(name, ".note.gnu.property") == 0)
+           {
+             this->layout_gnu_property_section(layout, i);
+             omit[i] = true;
+           }
+
          bool discard = omit[i];
          if (!discard)
            {
@@ -1638,9 +1756,13 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                  out_section_offsets[i] = invalid_address;
                }
              else if (this->is_deferred_layout())
-               this->deferred_layout_.push_back(
-                   Deferred_layout(i, name, sh_type, pshdrs,
-                                   reloc_shndx[i], reloc_type[i]));
+               {
+                 out_sections[i] = reinterpret_cast<Output_section*>(2);
+                 out_section_offsets[i] = invalid_address;
+                 this->deferred_layout_.push_back(
+                     Deferred_layout(i, name, sh_type, pshdrs,
+                                     reloc_shndx[i], reloc_type[i]));
+               }
              else
                eh_frame_sections.push_back(i);
              continue;
@@ -1755,10 +1877,30 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                debug_types_sections.push_back(i);
            }
        }
+
+      /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
+        section.  */
+      const char *lto_section_name = ".gnu.lto_.lto.";
+      if (strncmp (name, lto_section_name, strlen (lto_section_name)) == 0)
+       {
+         section_size_type contents_len;
+         const unsigned char* pcontents
+           = this->section_contents(i, &contents_len, false);
+         if (contents_len >= sizeof(lto_section))
+           {
+             const lto_section* lsection
+               = reinterpret_cast<const lto_section*>(pcontents);
+             if (lsection->slim_object)
+               layout->set_lto_slim_object();
+           }
+       }
     }
 
   if (!is_pass_two)
-    layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
+    {
+      layout->merge_gnu_properties(this);
+      layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
+    }
 
   // Handle the .eh_frame sections after the other sections.
   gold_assert(!is_pass_one || eh_frame_sections.empty());
@@ -1970,7 +2112,7 @@ template<int size, bool big_endian>
 void
 Sized_relobj_file<size, big_endian>::do_add_symbols(Symbol_table* symtab,
                                                    Read_symbols_data* sd,
-                                                   Layout*)
+                                                   Layout* layout)
 {
   if (sd->symbols == NULL)
     {
@@ -1989,6 +2131,11 @@ Sized_relobj_file<size, big_endian>::do_add_symbols(Symbol_table* symtab,
 
   this->symbols_.resize(symcount);
 
+  if (!parameters->options().relocatable()
+      && layout->is_lto_slim_object ())
+    gold_info(_("%s: plugin needed to handle lto object"),
+             this->name().c_str());
+
   const char* sym_names =
     reinterpret_cast<const char*>(sd->symbol_names->data());
   symtab->add_from_relobj(this,
@@ -2499,6 +2646,10 @@ Sized_relobj_file<size, big_endian>::do_finalize_local_symbols(
              lv->set_output_symtab_index(index);
              ++index;
            }
+         if (lv->is_ifunc_symbol()
+             && (lv->has_output_symtab_entry()
+                 || lv->needs_output_dynsym_entry()))
+           symtab->set_has_gnu_output();
          break;
        case CFLV_DISCARDED:
        case CFLV_ERROR:
@@ -2840,7 +2991,7 @@ Sized_relobj_file<size, big_endian>::map_to_kept_section(
              // Since we're using this mapping for relocation processing,
              // we don't want to match sections unless they have the same
              // size.
-             uint64_t kept_size;
+             uint64_t kept_size = 0;
              if (kept_section->find_comdat_section(section_name, &kept_shndx,
                                                    &kept_size))
                {
@@ -2850,7 +3001,7 @@ Sized_relobj_file<size, big_endian>::map_to_kept_section(
            }
          else
            {
-             uint64_t kept_size;
+             uint64_t kept_size = 0;
              if (kept_section->find_single_comdat_section(&kept_shndx,
                                                           &kept_size)
                  && sh_size == kept_size)
@@ -2953,7 +3104,8 @@ const unsigned char*
 Object::decompressed_section_contents(
     unsigned int shndx,
     section_size_type* plen,
-    bool* is_new)
+    bool* is_new,
+    uint64_t* palign)
 {
   section_size_type buffer_size;
   const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
@@ -2980,6 +3132,8 @@ Object::decompressed_section_contents(
     {
       *plen = uncompressed_size;
       *is_new = false;
+      if (palign != NULL)
+       *palign = p->second.addralign;
       return p->second.contents;
     }
 
@@ -3001,6 +3155,8 @@ Object::decompressed_section_contents(
   // once in this pass.
   *plen = uncompressed_size;
   *is_new = true;
+  if (palign != NULL)
+    *palign = p->second.addralign;
   return uncompressed_data;
 }
 
This page took 0.027179 seconds and 4 git commands to generate.