2014-03-31 Cary Coutant * 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