Create a note section with the version of gold.
authorIan Lance Taylor <iant@google.com>
Tue, 9 Oct 2007 21:37:55 +0000 (21:37 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 9 Oct 2007 21:37:55 +0000 (21:37 +0000)
gold/gold.h
gold/layout.cc
gold/layout.h
gold/version.cc

index 91669ee10d412b9f49ce4529b4882f4a7d20ea02..63bcb79c960e358115c5ad74a1597851312ff4b3 100644 (file)
@@ -211,6 +211,10 @@ extern void do_gold_unreachable(const char*, int, const char*)
 extern void
 print_version(bool print_short);
 
+// Get the version string.
+extern const char*
+get_version_string();
+
 // Queue up the first set of tasks.
 extern void
 queue_initial_tasks(const General_options&,
index e878456c61ae9159f45ead5a12986257a4a97996..af91d41d221a7c0181949c9b13d2bc74075de091 100644 (file)
@@ -521,6 +521,8 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
 
   target->finalize_sections(this);
 
+  this->create_note_section();
+
   Output_segment* phdr_seg = NULL;
   if (input_objects->any_dynamic())
     {
@@ -606,6 +608,79 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
   return off;
 }
 
+// Create a .note section for an executable or shared library.  This
+// records the version of gold used to create the binary.
+
+void
+Layout::create_note_section()
+{
+  if (parameters->output_is_object())
+    return;
+
+  const int size = parameters->get_size();
+
+  // The contents of the .note section.
+  const char* name = "GNU";
+  std::string desc(std::string("gold ") + gold::get_version_string());
+  size_t namesz = strlen(name) + 1;
+  size_t aligned_namesz = align_address(namesz, size / 8);
+  size_t descsz = desc.length() + 1;
+  size_t aligned_descsz = align_address(descsz, size / 8);
+  const int note_type = 4;
+
+  size_t notesz = 3 * (size / 8) + aligned_namesz + aligned_descsz;
+
+  unsigned char buffer[128];
+  gold_assert(sizeof buffer >= notesz);
+  memset(buffer, 0, notesz);
+
+  bool is_big_endian = parameters->is_big_endian();
+
+  if (size == 32)
+    {
+      if (!is_big_endian)
+       {
+         elfcpp::Swap<32, false>::writeval(buffer, namesz);
+         elfcpp::Swap<32, false>::writeval(buffer + 4, descsz);
+         elfcpp::Swap<32, false>::writeval(buffer + 8, note_type);
+       }
+      else
+       {
+         elfcpp::Swap<32, true>::writeval(buffer, namesz);
+         elfcpp::Swap<32, true>::writeval(buffer + 4, descsz);
+         elfcpp::Swap<32, true>::writeval(buffer + 8, note_type);
+       }
+    }
+  else if (size == 64)
+    {
+      if (!is_big_endian)
+       {
+         elfcpp::Swap<64, false>::writeval(buffer, namesz);
+         elfcpp::Swap<64, false>::writeval(buffer + 8, descsz);
+         elfcpp::Swap<64, false>::writeval(buffer + 16, note_type);
+       }
+      else
+       {
+         elfcpp::Swap<64, true>::writeval(buffer, namesz);
+         elfcpp::Swap<64, true>::writeval(buffer + 8, descsz);
+         elfcpp::Swap<64, true>::writeval(buffer + 16, note_type);
+       }
+    }
+  else
+    gold_unreachable();
+
+  memcpy(buffer + 3 * (size / 8), name, namesz);
+  memcpy(buffer + 3 * (size / 8) + aligned_namesz, desc.data(), descsz);
+
+  const char* note_name = this->namepool_.add(".note", NULL);
+  Output_section* os = this->make_output_section(note_name,
+                                                elfcpp::SHT_NOTE,
+                                                0);
+  Output_section_data* posd = new Output_data_const(buffer, notesz,
+                                                   size / 8);
+  os->add_output_section_data(posd);
+}
+
 // Return whether SEG1 should be before SEG2 in the output file.  This
 // is based entirely on the segment type and flags.  When this is
 // called the segment addresses has normally not yet been set.
index 3e09d62ca30b1e4db2d1901284a1d1b9787abb28..90cc22bb20cfc500e44695c7a1cd4d3d160b7906 100644 (file)
@@ -213,6 +213,10 @@ class Layout
                  const elfcpp::Shdr<size, big_endian>&,
                  Output_section*, off_t*);
 
+  // Create a .note section for gold.
+  void
+  create_note_section();
+
   // Find the first read-only PT_LOAD segment, creating one if
   // necessary.
   Output_segment*
index d7ad19cc59c431d1267ca0d4963ee31fa5286dd4..dda3d7ef3ae19bcf9b3399d2064239b10649e1bb 100644 (file)
@@ -55,4 +55,12 @@ This program has absolutely no warranty.\n"));
     }
 }
 
+// Return the version string.
+
+const char*
+get_version_string()
+{
+  return version_string;
+}
+
 } // End namespace gold.