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

Roland McGrath mcgrathr@google.com
Tue Apr 17 22:03:00 GMT 2012

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.

I tried to hack it in with the following.  But it produces:

	./gold/ld-new: error: invalid STB_LOCAL symbol in external symbols
	./gold/ld-new: error: unsupported symbol binding 0
	./gold/ld-new: error: linker defined: multiple definition of '$a'
	./gold/ld-new: command line: previous definition here

This is not surprising given the comment on define_in_output_data:

  // Define a special symbol based on an Output_data.  It is a
  // multiple definition error if this symbol is already defined.

To wit, if I comment out the second and third add_marker_symbol calls, it
produces a $a symbol correctly.  That is better than nothing, since there
is only one non-instruction word of .plt and it's easier to read around the
inappropriate disassembly of that one word than the inappropriate lack of
disassembly of all the other words.  But we really should emit all three
symbols, like BFD ld does.

A quick glance through the Symbol_table methods did not enclue me as to how
to define multiple locals of the same name.  Suggestions?


diff --git a/gold/arm.cc b/gold/arm.cc
index dc6e64a..b3a8c2e 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -7223,8 +7223,29 @@ class Output_data_plt_arm : public Output_section_data
   { 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);
+  }
+  add_marker_symbol(Output_section* os, Symbol_table* symtab,
+                    Arm_address offset, bool is_data)
+  {
+    symtab->define_in_output_data(is_data ? "$d" : "$a", NULL,
+                                  Symbol_table::PREDEFINED, os,
+                                  offset, 0,
+                                  elfcpp::STT_NOTYPE, elfcpp::STB_LOCAL,
+                                  elfcpp::STV_DEFAULT, 0, false, 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);

More information about the Binutils mailing list