This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[GOLD] sort powerpc64 toc sections
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Cc: Ian Lance Taylor <iant at google dot com>
- Date: Mon, 10 Dec 2012 23:11:08 +1030
- Subject: [GOLD] sort powerpc64 toc sections
This adds another missing piece of powerpc gold support. When linking
large binaries with a mix of objects, some compiled with
-mcmodel=small, it is necessary to ensure the -mcmodel=small objects
have their toc sections placed in the first 64k of the output toc/got
section. We hit this problem building gcc's libjava if the system
libc is small model, which is usually the case.
OK to apply?
* options.h (General_options): Add --no-toc-sort.
* output.h (Output_section::input_sections): Provide non-const variant.
* powerpc.cc (Powerpc_relobj::has_small_toc_reloc_,
set_has_small_toc_reloc, has_small_toc_reloc): New variable and
accessors.
(Target_powerpc::Scan::local, global): Call set_has_small_toc_reloc.
(class Sort_toc_sections): New.
(Target_powerpc::do_finalize_sections): Sort toc sections.
Index: gold/options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.179
diff -u -p -r1.179 options.h
--- gold/options.h 7 Dec 2012 00:03:18 -0000 1.179
+++ gold/options.h 10 Dec 2012 11:58:36 -0000
@@ -1112,6 +1112,9 @@ class General_options
DEFINE_bool(no_toc_optimize, options::TWO_DASHES, '\0', false,
N_("(PowerPC64 only) Don't optimize TOC code sequences"), NULL);
+ DEFINE_bool(no_toc_sort, options::TWO_DASHES, '\0', false,
+ N_("(PowerPC64 only) Don't sort TOC and GOT sections"), NULL);
+
DEFINE_set(undefined, options::TWO_DASHES, 'u',
N_("Create undefined reference to SYMBOL"), N_("SYMBOL"));
Index: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.143
diff -u -p -r1.143 output.h
--- gold/output.h 3 Dec 2012 05:48:47 -0000 1.143
+++ gold/output.h 10 Dec 2012 11:58:36 -0000
@@ -3941,6 +3941,10 @@ class Output_section : public Output_dat
input_sections() const
{ return this->input_sections_; }
+ Input_section_list&
+ input_sections()
+ { return this->input_sections_; }
+
protected:
// Return the output section--i.e., the object itself.
Output_section*
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.78
diff -u -p -r1.78 powerpc.cc
--- gold/powerpc.cc 10 Dec 2012 11:45:18 -0000 1.78
+++ gold/powerpc.cc 10 Dec 2012 11:58:36 -0000
@@ -71,7 +71,7 @@ public:
Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
const typename elfcpp::Ehdr<size, big_endian>& ehdr)
: Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
- special_(0), opd_valid_(false),
+ special_(0), has_small_toc_reloc_(false), opd_valid_(false),
opd_ent_(), access_from_map_(), has14_(), stub_table_()
{ }
@@ -228,6 +228,14 @@ public:
{ return 0x8000; }
void
+ set_has_small_toc_reloc()
+ { has_small_toc_reloc_ = true; }
+
+ bool
+ has_small_toc_reloc() const
+ { return has_small_toc_reloc_; }
+
+ void
set_has_14bit_branch(unsigned int shndx)
{
if (shndx >= this->has14_.size())
@@ -281,6 +289,10 @@ private:
// For 32-bit the .got2 section shdnx, for 64-bit the .opd section shndx.
unsigned int special_;
+ // For 64-bit, whether this object uses small model relocs to access
+ // the toc.
+ bool has_small_toc_reloc_;
+
// Set at the start of gc_process_relocs, when we know opd_ent_
// vector is valid. The flag could be made atomic and set in
// do_read_relocs with memory_order_release and then tested with
@@ -4690,6 +4702,21 @@ Target_powerpc<size, big_endian>::Scan::
unsupported_reloc_local(object, r_type);
break;
}
+
+ switch (r_type)
+ {
+ case elfcpp::R_POWERPC_GOT_TLSLD16:
+ case elfcpp::R_POWERPC_GOT_TLSGD16:
+ case elfcpp::R_POWERPC_GOT_TPREL16:
+ case elfcpp::R_POWERPC_GOT_DTPREL16:
+ case elfcpp::R_POWERPC_GOT16:
+ case elfcpp::R_PPC64_GOT16_DS:
+ case elfcpp::R_PPC64_TOC16:
+ case elfcpp::R_PPC64_TOC16_DS:
+ ppc_object->set_has_small_toc_reloc();
+ default:
+ break;
+ }
}
// Report an unsupported relocation against a global symbol.
@@ -5126,6 +5153,21 @@ Target_powerpc<size, big_endian>::Scan::
unsupported_reloc_global(object, r_type, gsym);
break;
}
+
+ switch (r_type)
+ {
+ case elfcpp::R_POWERPC_GOT_TLSLD16:
+ case elfcpp::R_POWERPC_GOT_TLSGD16:
+ case elfcpp::R_POWERPC_GOT_TPREL16:
+ case elfcpp::R_POWERPC_GOT_DTPREL16:
+ case elfcpp::R_POWERPC_GOT16:
+ case elfcpp::R_PPC64_GOT16_DS:
+ case elfcpp::R_PPC64_TOC16:
+ case elfcpp::R_PPC64_TOC16_DS:
+ ppc_object->set_has_small_toc_reloc();
+ default:
+ break;
+ }
}
// Process relocations for gc.
@@ -5346,6 +5388,31 @@ Target_powerpc<size, big_endian>::define
}
}
+// Sort linker created .got section first (for the header), then input
+// sections belonging to files using small model code.
+
+template<bool big_endian>
+class Sort_toc_sections
+{
+ public:
+ bool
+ operator()(const Output_section::Input_section& is1,
+ const Output_section::Input_section& is2) const
+ {
+ if (!is1.is_input_section() && is2.is_input_section())
+ return true;
+ bool small1
+ = (is1.is_input_section()
+ && (static_cast<const Powerpc_relobj<64, big_endian>*>(is1.relobj())
+ ->has_small_toc_reloc()));
+ bool small2
+ = (is2.is_input_section()
+ && (static_cast<const Powerpc_relobj<64, big_endian>*>(is2.relobj())
+ ->has_small_toc_reloc()));
+ return small1 && !small2;
+ }
+};
+
// Finalize the sections.
template<int size, bool big_endian>
@@ -5399,6 +5466,15 @@ Target_powerpc<size, big_endian>::do_fin
// need to mess with the relaxation machinery checkpointing.
this->got_section(symtab, layout);
this->make_brlt_section(layout);
+
+ if (!parameters->options().no_toc_sort())
+ {
+ Output_section* os = this->got_->output_section();
+ if (os != NULL && os->input_sections().size() > 1)
+ std::stable_sort(os->input_sections().begin(),
+ os->input_sections().end(),
+ Sort_toc_sections<big_endian>());
+ }
}
}
--
Alan Modra
Australia Development Lab, IBM