This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
gold patch committed: Fix x86_64 Linux kernel build
- From: Ian Lance Taylor <iant at google dot com>
- To: binutils at sourceware dot org
- Date: Wed, 24 Jun 2009 12:51:41 -0700
- Subject: gold patch committed: Fix x86_64 Linux kernel build
I committed this patch to gold to fix the x86_64 Linux kernel build.
The main issue was handling the case of adding an SHF_ALLOC section to a
section which was originally created without SHF_ALLOC. This can only
happen when using a linker script, and it happens with some Linux kernel
scripts that load the .note sections. I also had to fix the case of a
linker script discarding the .note sections. I moved the creation of
the automatic .note sections (.note.gnu.build-id, etc.) to happen before
sections are attached to segments, so that I didn't have to reattach the
section when it changed from non-ALLOC to ALLOC.
Ian
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.
Index: gold.cc
===================================================================
RCS file: /cvs/src/src/gold/gold.cc,v
retrieving revision 1.64
diff -p -u -r1.64 gold.cc
--- gold.cc 24 Jun 2009 05:01:16 -0000 1.64
+++ gold.cc 24 Jun 2009 19:47:07 -0000
@@ -386,6 +386,9 @@ queue_middle_tasks(const General_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();
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.130
diff -p -u -r1.130 layout.cc
--- layout.cc 24 Jun 2009 05:09:11 -0000 1.130
+++ layout.cc 24 Jun 2009 19:47:07 -0000
@@ -416,7 +416,10 @@ Layout::choose_output_section(const Relo
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_s
}
}
+// 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* in
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, in
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(con
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();
}
}
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.66
diff -p -u -r1.66 layout.h
--- layout.h 24 Jun 2009 00:38:00 -0000 1.66
+++ layout.h 24 Jun 2009 19:47:07 -0000
@@ -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
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.91
diff -p -u -r1.91 output.cc
--- output.cc 22 Jun 2009 06:51:53 -0000 1.91
+++ output.cc 24 Jun 2009 19:47:08 -0000
@@ -1995,6 +1995,24 @@ Output_section::add_merge_input_section(
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
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.79
diff -p -u -r1.79 output.h
--- output.h 22 Jun 2009 06:51:53 -0000 1.79
+++ output.h 24 Jun 2009 19:47:08 -0000
@@ -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_dat
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