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

Roland McGrath mcgrathr@google.com
Wed Apr 18 04:48:00 GMT 2012


On Tue, Apr 17, 2012 at 4:24 PM, Cary Coutant <ccoutant@google.com> wrote:
> I think your patch is pretty close to working. The problem is that
> Symbol_table::sized_write_globals() only visits symbols in the global
> symbol table, so it never sees the ones in forced_locals_ that weren't
> also added to the global table. I think you need a separate
> generated_locals_ list, change Symbol_table::sized_finalize() to
> iterate over that list the same way it does over forced_locals_, and
> add a loop to Symbol_table::sized_write_globals() to iterate over the
> generated_locals_ list to write them out.

Here's my attempt at that.  It produces three new symbol table entries.
But they are nameless and SHN_UNDEF instead of the names and sections
they should have.


Thanks,
Roland


diff --git a/gold/arm.cc b/gold/arm.cc
index dc6e64a..063aa57 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -7223,8 +7223,27 @@ 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)
+  {
+    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 +7449,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..29a170f 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();
@@ -2824,6 +2914,37 @@ Symbol_table::sized_write_globals(const
Stringpool* sympool,
   else
     dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size);

+  // Next do all the symbols which have been generated as local.
+  // They too must appear before all global symbols.
+  if (0)
+  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)
+	{
+	  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);
+	}
+    }
+
   for (Symbol_table_type::const_iterator p = this->table_.begin();
        p != this->table_.end();
        ++p)
diff --git a/gold/symtab.h b/gold/symtab.h
index feed245..fae194a 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,12 @@ class Symbol_table
 		     unsigned char nonvis, bool only_if_ref,
                      bool force_override);

+  // Define a special local symbol based on an Output_data.
+  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 +1722,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 +1887,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.



More information about the Binutils mailing list