gold regression vs BFD ld: __ehdr_start

Cary Coutant ccoutant@google.com
Mon Mar 31 21:03:00 GMT 2014


>> I think what has to happen is something analogous to what BFD ld does now:
>> Add the symbol early on in an undefined or indeterminate state, and then
>> define it (or don't) later on.  It's not very clear to me how to do that
>> correctly in gold.  It would seem clearest if it can be done in
>> define_standard_symbols.  But I don't know what Layout::finalize (where
>> it's created now) should do to find it and adjust it to point at the right
>> segment.  I also don't know how either case would interact with a user
>> defining (in input or script) this symbol name himself, in which case (IIRC
>> the BFD ld behavior) the user's symbol should be wholly unmolested (but it
>> might be that BFD ld uses the user's value but marks it STV_HIDDEN
>> anyway--I'm not sure).
>
> I don't know why __ehdr_start is defined in Layout::finalize.  As you
> suggest, it should be defined by define_standard_symbols instead,
> setting the only_if_ref field to true.  If necessary, Layout::finalize
> can adjust the symbol value using init_output_segment, but only if the
> symbol is marked as predefined.  Layout::finalize can simply look up
> the symbol by name.

The attached patch should fix this. Can you give it a try, and if it
works, I'll add a testcase and check it in.

-cary

2014-03-31  Cary Coutant  <ccoutant@google.com>

        * gold/defstd.cc (in_segment): Define __ehdr_start here...
        * gold/layout.cc (Layout::finalize): ...Instead of here.  Set the
        output segment when known.
        * gold/symtab.cc (Symbol::set_output_segment): New function.
        * gold/symtab.h (Symbol::set_output_segment): New function.
-------------- next part --------------
2014-03-31  Cary Coutant  <ccoutant@google.com>

	* gold/defstd.cc (in_segment): Define __ehdr_start here...
	* gold/layout.cc (Layout::finalize): ...Instead of here.  Set the
	output segment when known.
	* gold/symtab.cc (Symbol::set_output_segment): New function.
	* gold/symtab.h (Symbol::set_output_segment): New function.

diff --git a/gold/defstd.cc b/gold/defstd.cc
index a50e75d..cee68a0 100644
--- a/gold/defstd.cc
+++ b/gold/defstd.cc
@@ -141,6 +141,20 @@ const Define_symbol_in_segment in_segment[] =
     true			// only_if_ref
   },
   {
+    "__ehdr_start",		// name
+    elfcpp::PT_LOAD,		// segment_type
+    elfcpp::PF(0),		// segment_flags_set
+    elfcpp::PF(0),		// segment_flags_clear
+    0,				// value
+    0,				// size
+    elfcpp::STT_NOTYPE,		// type
+    elfcpp::STB_GLOBAL,		// binding
+    elfcpp::STV_HIDDEN,		// visibility
+    0,				// nonvis
+    Symbol::SEGMENT_START,	// offset_from_base
+    true			// only_if_ref
+  },
+  {
     "etext",			// name
     elfcpp::PT_LOAD,		// segment_type
     elfcpp::PF_X,		// segment_flags_set
diff --git a/gold/layout.cc b/gold/layout.cc
index c96516c..99460cc 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -2743,12 +2743,15 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // If there is a load segment that contains the file and program headers,
   // provide a symbol __ehdr_start pointing there.
   // A program can use this to examine itself robustly.
-  if (load_seg != NULL)
-    symtab->define_in_output_segment("__ehdr_start", NULL,
-				     Symbol_table::PREDEFINED, load_seg, 0, 0,
-				     elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
-				     elfcpp::STV_HIDDEN, 0,
-				     Symbol::SEGMENT_START, true);
+  Symbol *ehdr_start = symtab->lookup("__ehdr_start");
+  if (ehdr_start != NULL && ehdr_start->is_predefined())
+    {
+      if (load_seg != NULL)
+	ehdr_start->set_output_segment(load_seg, Symbol::SEGMENT_START);
+      else
+	gold_error("program references \"__ehdr_start\","
+		   " but no load segment contains the ELF header");
+    }
 
   // Set the file offsets of all the non-data sections we've seen so
   // far which don't have to wait for the input sections.  We need
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 1a69f5b..58db441 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -527,6 +527,17 @@ Symbol::set_output_section(Output_section* os)
     }
 }
 
+// Set the symbol's output segment.  This is used for pre-defined
+// symbols whose segments aren't known until after layout is done
+// (e.g., __ehdr_start).
+void
+Symbol::set_output_segment(Output_segment* os, Segment_offset_base base)
+{
+  gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
+  this->u_.in_output_segment.output_segment = os;
+  this->u_.in_output_segment.offset_base = base;
+}
+
 // Class Symbol_table.
 
 Symbol_table::Symbol_table(unsigned int count,
diff --git a/gold/symtab.h b/gold/symtab.h
index b06c7b4..1ff5c22 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -782,6 +782,12 @@ class Symbol
   void
   set_output_section(Output_section*);
 
+  // Set the symbol's output segment.  This is used for pre-defined
+  // symbols whose segments aren't known until after layout is done
+  // (e.g., __ehdr_start).
+  void
+  set_output_segment(Output_segment*, Segment_offset_base);
+
   // Return whether there should be a warning for references to this
   // symbol.
   bool


More information about the Binutils mailing list