diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 25 | ||||
-rw-r--r-- | gold/gold.cc | 3 | ||||
-rw-r--r-- | gold/layout.cc | 31 | ||||
-rw-r--r-- | gold/layout.h | 6 | ||||
-rw-r--r-- | gold/output.cc | 18 | ||||
-rw-r--r-- | gold/output.h | 22 |
6 files changed, 83 insertions, 22 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 85326d1..efa806f 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,30 @@ 2009-06-24 Ian Lance Taylor <iant@google.com> + PR 10156 + * layout.cc (Layout::choose_output_section): If we find an + existing section, update the flags. + (Layout::create_notes): New function, broken out of + Layout::finalize. + (Layout::finalize): Don't create note sections. + (Layout::create_note): Don't crash if linker script discards + section. + (Layout::create_gold_note): Likewise. + (Layout::create_build_id): Likewise. Don't set + after_input_sections on the section. + (Layout::create_executable_stack_info): Remove target parameter. + Change caller. + * layout.h (class Layout): Declare create_notes. Update + declaration of create_executable_stack_info. + * gold.cc (queue_middle_tasks): Call create_notes. + * output.cc (Output_section::update_flags_for_input_section): Move + here from output.h. If SHF_ALLOC flag is newly set, mark address + invalid. + * output.h (Output_data::mark_address_invalid): New function. + (class Output_section): Only declare, not define, + update_flags_for_input_section. Remove set_flags. + +2009-06-24 Ian Lance Taylor <iant@google.com> + * script-sections.cc (Output_section_definition:: set_section_addresses): Rename shadowing local load_address to laddr. diff --git a/gold/gold.cc b/gold/gold.cc index ae4b8b8..c65ba29 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -386,6 +386,9 @@ queue_middle_tasks(const General_options& options, // TODO: if this is too slow, do this as a task, rather than inline. symtab->detect_odr_violations(task, options.output_file_name()); + // Create any automatic note sections. + layout->create_notes(); + // Create any output sections required by any linker script. layout->create_script_sections(); diff --git a/gold/layout.cc b/gold/layout.cc index 4014ec0..e8625d2 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -416,7 +416,10 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, if (output_section_slot != NULL) { if (*output_section_slot != NULL) - return *output_section_slot; + { + (*output_section_slot)->update_flags_for_input_section(flags); + return *output_section_slot; + } // We don't put sections found in the linker script into // SECTION_NAME_MAP_. That keeps us from getting confused @@ -1028,6 +1031,16 @@ Layout::layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags) } } +// Create automatic note sections. + +void +Layout::create_notes() +{ + this->create_gold_note(); + this->create_executable_stack_info(); + this->create_build_id(); +} + // Create the dynamic sections which are needed before we read the // relocs. @@ -1198,9 +1211,6 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, this->count_local_symbols(task, input_objects); - this->create_gold_note(); - this->create_executable_stack_info(target); - this->create_build_id(); this->link_stabs_sections(); Output_segment* phdr_seg = NULL; @@ -1442,6 +1452,9 @@ Layout::create_note(const char* name, int note_type, Output_section* os = this->choose_output_section(NULL, section_name, elfcpp::SHT_NOTE, flags, false); + if (os == NULL) + return NULL; + Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz, size / 8, "** note header"); @@ -1467,6 +1480,8 @@ Layout::create_gold_note() Output_section *os = this->create_note("GNU", elfcpp::NT_GNU_GOLD_VERSION, ".note.gnu.gold-version", desc.size(), false, &trailing_padding); + if (os == NULL) + return; Output_section_data* posd = new Output_data_const(desc, 4); os->add_output_section_data(posd); @@ -1491,7 +1506,7 @@ Layout::create_gold_note() // library, we create a PT_GNU_STACK segment. void -Layout::create_executable_stack_info(const Target* target) +Layout::create_executable_stack_info() { bool is_stack_executable; if (parameters->options().is_execstack_set()) @@ -1503,7 +1518,8 @@ Layout::create_executable_stack_info(const Target* target) if (this->input_requires_executable_stack_) is_stack_executable = true; else if (this->input_without_gnu_stack_note_) - is_stack_executable = target->is_default_stack_executable(); + is_stack_executable = + parameters->target().is_default_stack_executable(); else is_stack_executable = false; } @@ -1600,6 +1616,8 @@ Layout::create_build_id() Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_BUILD_ID, ".note.gnu.build-id", descsz, true, &trailing_padding); + if (os == NULL) + return; if (!desc.empty()) { @@ -1622,7 +1640,6 @@ Layout::create_build_id() gold_assert(trailing_padding == 0); this->build_id_note_ = new Output_data_zero_fill(descsz, 4); os->add_output_section_data(this->build_id_note_); - os->set_after_input_sections(); } } diff --git a/gold/layout.h b/gold/layout.h index f538b64..86234a1 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -208,6 +208,10 @@ class Layout void define_section_symbols(Symbol_table*); + // Create automatic note sections. + void + create_notes(); + // Create sections for linker scripts. void create_script_sections() @@ -474,7 +478,7 @@ class Layout // Record whether the stack must be executable. void - create_executable_stack_info(const Target*); + create_executable_stack_info(); // Create a build ID note if needed. void diff --git a/gold/output.cc b/gold/output.cc index 911a49a..64fcb37 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1995,6 +1995,24 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, return true; } +// Update the output section flags based on input section flags. + +void +Output_section::update_flags_for_input_section(elfcpp::Elf_Xword flags) +{ + // If we created the section with SHF_ALLOC clear, we set the + // address. If we are now setting the SHF_ALLOC flag, we need to + // undo that. + if ((this->flags_ & elfcpp::SHF_ALLOC) == 0 + && (flags & elfcpp::SHF_ALLOC) != 0) + this->mark_address_invalid(); + + this->flags_ |= (flags + & (elfcpp::SHF_WRITE + | elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR)); +} + // Given an address OFFSET relative to the start of input section // SHNDX in OBJECT, return whether this address is being included in // the final link. This should only be called if SHNDX in OBJECT has diff --git a/gold/output.h b/gold/output.h index 3e46ad8..f9cbfa6 100644 --- a/gold/output.h +++ b/gold/output.h @@ -330,6 +330,13 @@ class Output_data // Functions that child classes may call. + // Reset the address. The Output_section class needs this when an + // SHF_ALLOC input section is added to an output section which was + // formerly not SHF_ALLOC. + void + mark_address_invalid() + { this->is_address_valid_ = false; } + // Set the size of the data. void set_data_size(off_t data_size) @@ -1948,22 +1955,9 @@ class Output_section : public Output_data flags() const { return this->flags_; } - // Set the section flags. This may only be used with the Layout - // code when it is prepared to move the section to a different - // segment. - void - set_flags(elfcpp::Elf_Xword flags) - { this->flags_ = flags; } - // Update the output section flags based on input section flags. void - update_flags_for_input_section(elfcpp::Elf_Xword flags) - { - this->flags_ |= (flags - & (elfcpp::SHF_WRITE - | elfcpp::SHF_ALLOC - | elfcpp::SHF_EXECINSTR)); - } + update_flags_for_input_section(elfcpp::Elf_Xword flags); // Return the entsize field. uint64_t |