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]

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


On Tue, Apr 17, 2012 at 3:56 PM, Cary Coutant <ccoutant@google.com> wrote:
>> I haven't tried this, but I think you might be able to add a method to
>> class Symbol_table that adds a bare Sized_symbol (that is not in the
>> global symbol table) to the forced_locals_ list. Then
>> Symbol_table::sized_finalize() will take care of adding the symbol to
>> the output symbol table as a local.

I tried this, to no avail (the symbols don't appear in the output at all).
Patch below for reference.

>> You might even be able to just create a new Sized_symbol and call
>> Symbol_table::force_local() with it.

I couldn't do that outside Symbol_table because force_local is private.

> Looking at this more closely, I see that we do in fact already call
> define_in_output_data() to create STB_LOCAL symbols (e.g.,
> _GLOBAL_OFFSET_TABLE, _DYNAMIC).

Just using define_in_output_data directly works fine to define one symbol.
But it falls down when we need to define another symbol by the same name,
which is generally kosher for local symbols and is what's required for the
$a magic symbol.

> I'm thinking the right thing to do here is to pass the binding to
> Symbol_table::define_special_symbol(). If the binding is STB_LOCAL, it
> should create a new Sized_symbol and add it to the forced_locals_ list
> instead of to the global symbol table.

I think I understand what you're saying.  But I don't understand what's
going on in that function nearly well enough to implement it.


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..6abc6e8 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.
@@ -1934,6 +1934,57 @@ 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 = new Sized_symbol<size>();
+  sym->init_output_data(name, NULL, od, value, symsize, type,
+                        elfcpp::STB_LOCAL, elfcpp::STV_DEFAULT, 0,
+                        offset_is_from_end, defined == PREDEFINED);
+  this->force_local(sym);
+  return sym;
+}
+
 // Define a symbol based on an Output_segment.

 Symbol*
diff --git a/gold/symtab.h b/gold/symtab.h
index feed245..2b3e89e 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>*


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