This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] gold/arm: define $a/$d markers in .plt


When gold generates an ARM .plt section, it fails to define any magic
marker symbols (local symbols named $a or $d).  These are necessary to
make objdump -d disassemble the .plt contents rather than just showing
them as data words.

This patch makes it generate the necessary marker symbols at the start of
the .plt section.

The Symbol_table changes are all based on Cary's advice earlier in this
thread.  I really can't explain or vouch for this being the best way to
enable the missing functionality: defining local synthetic symbols without
regard to preexisting symbols of the same name.

No regressions in 'make check' (x86_64-linux-gnu host).  I verified the new
functionality with a trivial ARM link that generates some PLT entries.

Ok for trunk?


Thanks,
Roland


gold/
2012-04-18  Roland McGrath  <mcgrathr@google.com>

	* arm.cc (Output_data_plt_arm::add_marker_symbols): New method.
	(Output_data_plt_arm::add_marker_symbol): New method.
	(Target_arm::make_plt_entry): Call it.

	* symtab.h (Symbol_table::define_local_in_output_data): New method.
	(Symbol_table::do_define_local_in_output_data): New template method.
	(Symbol_table::generated_locals_): New member.
	* symtab.cc (Symbol_table::Symbol_table): Initialize it.
	(Symbol_table::define_local_in_output_data): New method.
	(Symbol_table::do_define_local_in_output_data): New method.
	(Symbol_table::sized_finalize): Add generated_locals_ to symtab
	similar to forced_locals_.
	(Symbol_table::sized_write_globals): Write generated_locals_ out.

diff --git a/gold/arm.cc b/gold/arm.cc
index dc6e64a..6232192 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -7223,8 +7223,29 @@ class Output_data_plt_arm : public Output_section_data
   get_plt_entry_size()
   { return sizeof(plt_entry); }

+  // Define marker symbols at the start of the PLT so that
+  // objdump will know to disassemble it as ARM instructions.
+  void
+  add_marker_symbols(Output_section* os, Symbol_table* symtab)
+  {
+    // The last word of first_plt_entry is data.
+    // The leading words, and all of subsequent entries, are ARM instructions.
+    this->add_marker_symbol(os, symtab, 0, false);
+    this->add_marker_symbol(os, symtab, 16, true);
+    this->add_marker_symbol(os, symtab, 20, false);
+  }
+
  protected:
   void
+  add_marker_symbol(Output_section* os, Symbol_table* symtab,
+		    Arm_address offset, bool is_data)
+  {
+    symtab->define_local_in_output_data(is_data ? "$d" : "$a",
+					Symbol_table::PREDEFINED, os,
+					offset, 0, elfcpp::STT_NOTYPE, false);
+  }
+
+  void
   do_adjust_output_section(Output_section* os);

   // Write to a map file.
@@ -7430,10 +7451,13 @@
Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout*
layout,
       this->got_section(symtab, layout);

       this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_);
-      layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
-				      (elfcpp::SHF_ALLOC
-				       | elfcpp::SHF_EXECINSTR),
+
+      Output_section* os = layout->add_output_section_data
+	(".plt", elfcpp::SHT_PROGBITS,
+	 (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR),
 				      this->plt_, ORDER_PLT, false);
+
+      this->plt_->add_marker_symbols(os, symtab);
     }
   this->plt_->add_entry(gsym);
 }
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 1edb88d..cf09853 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -1,6 +1,6 @@
 // symtab.cc -- the gold symbol table

-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006,2007,2008,2009,2010,2011,2012 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.

 // This file is part of gold.
@@ -532,7 +532,7 @@ Symbol_table::Symbol_table(unsigned int count,
                            const Version_script_info& version_script)
   : saw_undefined_(0), offset_(0), table_(count), namepool_(),
     forwarders_(), commons_(), tls_commons_(), small_commons_(),
-    large_commons_(), forced_locals_(), warnings_(),
+    large_commons_(), forced_locals_(), generated_locals_(), warnings_(),
     version_script_(version_script), gc_(NULL), icf_(NULL)
 {
   namepool_.reserve(count);
@@ -1934,6 +1934,81 @@ Symbol_table::do_define_in_output_data(
     }
 }

+// Define a special local symbol based on an Output_data.
+
+Symbol*
+Symbol_table::define_local_in_output_data(const char* name,
+					  Defined defined, Output_data* od,
+					  uint64_t value, uint64_t symsize,
+					  elfcpp::STT type,
+					  bool offset_is_from_end)
+{
+  if (parameters->target().get_size() == 32)
+    {
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
+      return this->do_define_local_in_output_data<32>(name, defined, od,
+						      value, symsize, type,
+						      offset_is_from_end);
+#else
+      gold_unreachable();
+#endif
+    }
+  else if (parameters->target().get_size() == 64)
+    {
+#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
+      return this->do_define_local_in_output_data<64>(name, defined, od,
+						      value, symsize, type,
+						      offset_is_from_end);
+#else
+      gold_unreachable();
+#endif
+    }
+  else
+    gold_unreachable();
+}
+
+// Define a special local symbol based on an Output_data, sized version.
+
+template<int size>
+Sized_symbol<size>*
+Symbol_table::do_define_local_in_output_data(
+    const char* name, Defined defined, Output_data* od,
+    typename elfcpp::Elf_types<size>::Elf_Addr value,
+    typename elfcpp::Elf_types<size>::Elf_WXword symsize,
+    elfcpp::STT type, bool offset_is_from_end)
+{
+  Sized_symbol<size>* sym;
+
+  const Target& target = parameters->target();
+  if (!target.has_make_symbol())
+    sym = new Sized_symbol<size>();
+  else
+    {
+      if (parameters->target().is_big_endian())
+	{
+	  Sized_target<size, true>* sized_target =
+	    parameters->sized_target<size, true>();
+	  sym = sized_target->make_symbol();
+	}
+      else
+	{
+	  Sized_target<size, false>* sized_target =
+	    parameters->sized_target<size, false>();
+	  sym = sized_target->make_symbol();
+	}
+
+      if (sym == NULL)
+	return NULL;
+    }
+
+  sym->init_output_data(name, NULL, od, value, symsize, type,
+			elfcpp::STB_LOCAL, elfcpp::STV_DEFAULT, 0,
+			offset_is_from_end, defined == PREDEFINED);
+  sym->set_is_forced_local();
+  this->generated_locals_.push_back(sym);
+  return sym;
+}
+
 // Define a symbol based on an Output_segment.

 Symbol*
@@ -2515,6 +2590,21 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool,
 	}
     }

+  // Next do all the symbols which have been generated as local.
+  // They too must appear before all global symbols.
+  for (Forced_locals::iterator p = this->generated_locals_.begin();
+       p != this->generated_locals_.end();
+       ++p)
+    {
+      Symbol* sym = *p;
+      gold_assert(sym->is_forced_local());
+      if (this->sized_finalize_symbol<size>(sym))
+	{
+	  this->add_to_final_symtab<size>(sym, pool, &index, &off);
+	  ++*plocal_symcount;
+	}
+    }
+
   // Now do all the remaining symbols.
   for (Symbol_table_type::iterator p = this->table_.begin();
        p != this->table_.end();
@@ -2976,6 +3066,36 @@ Symbol_table::sized_write_globals(const
Stringpool* sympool,
 	}
     }

+  // Next do all the symbols which have been generated as local.
+  for (Forced_locals::const_iterator p = this->generated_locals_.begin();
+       p != this->generated_locals_.end();
+       ++p)
+    {
+      Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(*p);
+      unsigned int sym_index = sym->symtab_index();
+      unsigned int shndx = sym->output_data()->out_shndx();
+      typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value();
+
+      gold_assert(sym->binding() == elfcpp::STB_LOCAL);
+
+      if (shndx >= elfcpp::SHN_LORESERVE)
+	{
+	  if (sym_index != -1U)
+	    symtab_xindex->add(sym_index, shndx);
+	  shndx = elfcpp::SHN_XINDEX;
+	}
+
+      if (sym_index != -1U)
+	{
+	  sym_index -= first_global_index;
+	  gold_assert(sym_index < output_count);
+	  unsigned char* ps = psyms + (sym_index * sym_size);
+	  this->sized_write_symbol<size, big_endian>(sym, sym_value, shndx,
+						     elfcpp::STB_LOCAL,
+						     sympool, ps);
+	}
+    }
+
   of->write_output_view(this->offset_, oview_size, psyms);
   if (dynamic_view != NULL)
     of->write_output_view(this->dynamic_offset_, dynamic_size, dynamic_view);
diff --git a/gold/symtab.h b/gold/symtab.h
index feed245..243de8b 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -1,6 +1,6 @@
 // symtab.h -- the gold symbol table   -*- C++ -*-

-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006,2007,2008,2009,2010,2011,2012 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.

 // This file is part of gold.
@@ -1393,6 +1393,13 @@ class Symbol_table
 		     unsigned char nonvis, bool only_if_ref,
                      bool force_override);

+  // Define a special local symbol based on an Output_data.
+  // This can define multiple symbols of the same name.
+  Symbol*
+  define_local_in_output_data(const char* name, Defined,
+			      Output_data*, uint64_t value, uint64_t symsize,
+			      elfcpp::STT type, bool offset_is_from_end);
+
   // Define a set of symbols in output sections.  If ONLY_IF_REF is
   // true, only define them if they are referenced.
   void
@@ -1716,6 +1723,15 @@ class Symbol_table
 			   elfcpp::STV visibility, unsigned char nonvis,
 			   bool offset_is_from_end, bool only_if_ref);

+  // Define a local symbol in an Output_data, sized version.
+  template<int size>
+  Sized_symbol<size>*
+  do_define_local_in_output_data(
+    const char* name, Defined, Output_data*,
+    typename elfcpp::Elf_types<size>::Elf_Addr value,
+    typename elfcpp::Elf_types<size>::Elf_WXword symsize,
+    elfcpp::STT type, bool offset_is_from_end);
+
   // Define a symbol in an Output_segment, sized version.
   template<int size>
   Sized_symbol<size>*
@@ -1872,6 +1888,8 @@ class Symbol_table
   // expect there to be very many of them, so we keep a list of them
   // rather than walking the whole table to find them.
   Forced_locals forced_locals_;
+  // A list of symbols that were generated as local.
+  Forced_locals generated_locals_;
   // Manage symbol warnings.
   Warnings warnings_;
   // Manage potential One Definition Rule (ODR) violations.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]