This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[GOLD] mapping input to output 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, 13 Aug 2012 23:53:44 +0930
- Subject: [GOLD] mapping input to output sections
Powerpc64 needs to map input .toc and .got sections to the output .got
section, as the following accomplishes with GNU ld:
.got : ALIGN(8) { *(.got .toc) }
I gather gold is supposed to operate without a linker script. Is is
reasonable to move section_name_mapping[], section_name_mapping_count,
output_section_name() and match_file_name() from layout.cc to
target.cc so output_section_name() can be overridden in class
Target_powerpc? Or is there a better way to do this sort of trick?
Index: gold/layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.103
diff -u -p -r1.103 layout.h
--- gold/layout.h 2 May 2012 21:37:23 -0000 1.103
+++ gold/layout.h 13 Aug 2012 14:15:07 -0000
@@ -717,12 +717,6 @@ class Layout
|| strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
}
- // Return true if RELOBJ is an input file whose base name matches
- // FILE_NAME. The base name must have an extension of ".o", and
- // must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
- static bool
- match_file_name(const Relobj* relobj, const char* file_name);
-
// Return whether section SHNDX in RELOBJ is a .ctors/.dtors section
// with more than one word being mapped to a .init_array/.fini_array
// section.
@@ -924,17 +918,6 @@ class Layout
Layout(const Layout&);
Layout& operator=(const Layout&);
- // Mapping from input section names to output section names.
- struct Section_name_mapping
- {
- const char* from;
- int fromlen;
- const char* to;
- int tolen;
- };
- static const Section_name_mapping section_name_mapping[];
- static const int section_name_mapping_count;
-
// During a relocatable link, a list of group sections and
// signatures.
struct Group_signature
@@ -1049,12 +1032,6 @@ class Layout
include_section(Sized_relobj_file<size, big_endian>* object, const char* name,
const elfcpp::Shdr<size, big_endian>&);
- // Return the output section name to use given an input section
- // name. Set *PLEN to the length of the name. *PLEN must be
- // initialized to the length of NAME.
- static const char*
- output_section_name(const Relobj*, const char* name, size_t* plen);
-
// Return the number of allocated output sections.
size_t
allocated_output_section_count() const;
Index: gold/layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.232
diff -u -p -r1.232 layout.cc
--- gold/layout.cc 7 Aug 2012 13:24:47 -0000 1.232
+++ gold/layout.cc 13 Aug 2012 14:15:06 -0000
@@ -939,7 +939,10 @@ Layout::choose_output_section(const Relo
if (is_input_section
&& !this->script_options_->saw_sections_clause()
&& !parameters->options().relocatable())
- name = Layout::output_section_name(relobj, name, &len);
+ {
+ Target* target = const_cast<Target*>(¶meters->target());
+ name = target->output_section_name(relobj, name, &len);
+ }
Stringpool::Key name_key;
name = this->namepool_.add_with_length(name, len, true, &name_key);
@@ -4636,185 +4639,6 @@ Layout::set_dynamic_symbol_size(const Sy
gold_unreachable();
}
-// The mapping of input section name prefixes to output section names.
-// In some cases one prefix is itself a prefix of another prefix; in
-// such a case the longer prefix must come first. These prefixes are
-// based on the GNU linker default ELF linker script.
-
-#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
-#define MAPPING_INIT_EXACT(f, t) { f, 0, t, sizeof(t) - 1 }
-const Layout::Section_name_mapping Layout::section_name_mapping[] =
-{
- MAPPING_INIT(".text.", ".text"),
- MAPPING_INIT(".rodata.", ".rodata"),
- MAPPING_INIT(".data.rel.ro.local.", ".data.rel.ro.local"),
- MAPPING_INIT_EXACT(".data.rel.ro.local", ".data.rel.ro.local"),
- MAPPING_INIT(".data.rel.ro.", ".data.rel.ro"),
- MAPPING_INIT_EXACT(".data.rel.ro", ".data.rel.ro"),
- MAPPING_INIT(".data.", ".data"),
- MAPPING_INIT(".bss.", ".bss"),
- MAPPING_INIT(".tdata.", ".tdata"),
- MAPPING_INIT(".tbss.", ".tbss"),
- MAPPING_INIT(".init_array.", ".init_array"),
- MAPPING_INIT(".fini_array.", ".fini_array"),
- MAPPING_INIT(".sdata.", ".sdata"),
- MAPPING_INIT(".sbss.", ".sbss"),
- // FIXME: In the GNU linker, .sbss2 and .sdata2 are handled
- // differently depending on whether it is creating a shared library.
- MAPPING_INIT(".sdata2.", ".sdata"),
- MAPPING_INIT(".sbss2.", ".sbss"),
- MAPPING_INIT(".lrodata.", ".lrodata"),
- MAPPING_INIT(".ldata.", ".ldata"),
- MAPPING_INIT(".lbss.", ".lbss"),
- MAPPING_INIT(".gcc_except_table.", ".gcc_except_table"),
- MAPPING_INIT(".gnu.linkonce.d.rel.ro.local.", ".data.rel.ro.local"),
- MAPPING_INIT(".gnu.linkonce.d.rel.ro.", ".data.rel.ro"),
- MAPPING_INIT(".gnu.linkonce.t.", ".text"),
- MAPPING_INIT(".gnu.linkonce.r.", ".rodata"),
- MAPPING_INIT(".gnu.linkonce.d.", ".data"),
- MAPPING_INIT(".gnu.linkonce.b.", ".bss"),
- MAPPING_INIT(".gnu.linkonce.s.", ".sdata"),
- MAPPING_INIT(".gnu.linkonce.sb.", ".sbss"),
- MAPPING_INIT(".gnu.linkonce.s2.", ".sdata"),
- MAPPING_INIT(".gnu.linkonce.sb2.", ".sbss"),
- MAPPING_INIT(".gnu.linkonce.wi.", ".debug_info"),
- MAPPING_INIT(".gnu.linkonce.td.", ".tdata"),
- MAPPING_INIT(".gnu.linkonce.tb.", ".tbss"),
- MAPPING_INIT(".gnu.linkonce.lr.", ".lrodata"),
- MAPPING_INIT(".gnu.linkonce.l.", ".ldata"),
- MAPPING_INIT(".gnu.linkonce.lb.", ".lbss"),
- MAPPING_INIT(".ARM.extab", ".ARM.extab"),
- MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"),
- MAPPING_INIT(".ARM.exidx", ".ARM.exidx"),
- MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
-};
-#undef MAPPING_INIT
-#undef MAPPING_INIT_EXACT
-
-const int Layout::section_name_mapping_count =
- (sizeof(Layout::section_name_mapping)
- / sizeof(Layout::section_name_mapping[0]));
-
-// Choose the output section name to use given an input section name.
-// Set *PLEN to the length of the name. *PLEN is initialized to the
-// length of NAME.
-
-const char*
-Layout::output_section_name(const Relobj* relobj, const char* name,
- size_t* plen)
-{
- // gcc 4.3 generates the following sorts of section names when it
- // needs a section name specific to a function:
- // .text.FN
- // .rodata.FN
- // .sdata2.FN
- // .data.FN
- // .data.rel.FN
- // .data.rel.local.FN
- // .data.rel.ro.FN
- // .data.rel.ro.local.FN
- // .sdata.FN
- // .bss.FN
- // .sbss.FN
- // .tdata.FN
- // .tbss.FN
-
- // The GNU linker maps all of those to the part before the .FN,
- // except that .data.rel.local.FN is mapped to .data, and
- // .data.rel.ro.local.FN is mapped to .data.rel.ro. The sections
- // beginning with .data.rel.ro.local are grouped together.
-
- // For an anonymous namespace, the string FN can contain a '.'.
-
- // Also of interest: .rodata.strN.N, .rodata.cstN, both of which the
- // GNU linker maps to .rodata.
-
- // The .data.rel.ro sections are used with -z relro. The sections
- // are recognized by name. We use the same names that the GNU
- // linker does for these sections.
-
- // It is hard to handle this in a principled way, so we don't even
- // try. We use a table of mappings. If the input section name is
- // not found in the table, we simply use it as the output section
- // name.
-
- const Section_name_mapping* psnm = section_name_mapping;
- for (int i = 0; i < section_name_mapping_count; ++i, ++psnm)
- {
- if (psnm->fromlen > 0)
- {
- if (strncmp(name, psnm->from, psnm->fromlen) == 0)
- {
- *plen = psnm->tolen;
- return psnm->to;
- }
- }
- else
- {
- if (strcmp(name, psnm->from) == 0)
- {
- *plen = psnm->tolen;
- return psnm->to;
- }
- }
- }
-
- // As an additional complication, .ctors sections are output in
- // either .ctors or .init_array sections, and .dtors sections are
- // output in either .dtors or .fini_array sections.
- if (is_prefix_of(".ctors.", name) || is_prefix_of(".dtors.", name))
- {
- if (parameters->options().ctors_in_init_array())
- {
- *plen = 11;
- return name[1] == 'c' ? ".init_array" : ".fini_array";
- }
- else
- {
- *plen = 6;
- return name[1] == 'c' ? ".ctors" : ".dtors";
- }
- }
- if (parameters->options().ctors_in_init_array()
- && (strcmp(name, ".ctors") == 0 || strcmp(name, ".dtors") == 0))
- {
- // To make .init_array/.fini_array work with gcc we must exclude
- // .ctors and .dtors sections from the crtbegin and crtend
- // files.
- if (relobj == NULL
- || (!Layout::match_file_name(relobj, "crtbegin")
- && !Layout::match_file_name(relobj, "crtend")))
- {
- *plen = 11;
- return name[1] == 'c' ? ".init_array" : ".fini_array";
- }
- }
-
- return name;
-}
-
-// Return true if RELOBJ is an input file whose base name matches
-// FILE_NAME. The base name must have an extension of ".o", and must
-// be exactly FILE_NAME.o or FILE_NAME, one character, ".o". This is
-// to match crtbegin.o as well as crtbeginS.o without getting confused
-// by other possibilities. Overall matching the file name this way is
-// a dreadful hack, but the GNU linker does it in order to better
-// support gcc, and we need to be compatible.
-
-bool
-Layout::match_file_name(const Relobj* relobj, const char* match)
-{
- const std::string& file_name(relobj->name());
- const char* base_name = lbasename(file_name.c_str());
- size_t match_len = strlen(match);
- if (strncmp(base_name, match, match_len) != 0)
- return false;
- size_t base_len = strlen(base_name);
- if (base_len != match_len + 2 && base_len != match_len + 3)
- return false;
- return memcmp(base_name + base_len - 2, ".o", 2) == 0;
-}
-
// Check if a comdat group or .gnu.linkonce section with the given
// NAME is selected for the link. If there is already a section,
// *KEPT_SECTION is set to point to the existing section and the
Index: gold/target.h
===================================================================
RCS file: /cvs/src/src/gold/target.h,v
retrieving revision 1.66
diff -u -p -r1.66 target.h
--- gold/target.h 2 May 2012 21:37:23 -0000 1.66
+++ gold/target.h 13 Aug 2012 14:15:07 -0000
@@ -412,6 +412,19 @@ class Target
define_standard_symbols(Symbol_table* symtab, Layout* layout)
{ this->do_define_standard_symbols(symtab, layout); }
+ // Return the output section name to use given an input section
+ // name. Set *PLEN to the length of the name. *PLEN must be
+ // initialized to the length of NAME.
+ const char*
+ output_section_name(const Relobj* relobj, const char* name, size_t* plen)
+ { return this->do_output_section_name(relobj, name, plen); }
+
+ // Return true if RELOBJ is an input file whose base name matches
+ // FILE_NAME. The base name must have an extension of ".o", and
+ // must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
+ static bool
+ match_file_name(const Relobj* relobj, const char* file_name);
+
protected:
// This struct holds the constant information for a child class. We
// use a struct to avoid the overhead of virtual function calls for
@@ -655,6 +668,10 @@ class Target
do_define_standard_symbols(Symbol_table*, Layout*)
{ }
+ // This may be overridden by the child class.
+ virtual const char*
+ do_output_section_name(const Relobj* relobj, const char* name, size_t* plen);
+
private:
// The implementations of the four do_make_elf_object virtual functions are
// almost identical except for their sizes and endianness. We use a template.
@@ -667,6 +684,17 @@ class Target
Target(const Target&);
Target& operator=(const Target&);
+ // Mapping from input section names to output section names.
+ struct Section_name_mapping
+ {
+ const char* from;
+ int fromlen;
+ const char* to;
+ int tolen;
+ };
+ static const Section_name_mapping section_name_mapping[];
+ static const int section_name_mapping_count;
+
// The target information.
const Target_info* pti_;
// Processor-specific flags.
Index: gold/target.cc
===================================================================
RCS file: /cvs/src/src/gold/target.cc,v
retrieving revision 1.13
diff -u -p -r1.13 target.cc
--- gold/target.cc 20 Apr 2012 22:23:47 -0000 1.13
+++ gold/target.cc 13 Aug 2012 14:15:07 -0000
@@ -26,6 +26,7 @@
#include "symtab.h"
#include "output.h"
#include "target.h"
+#include "libiberty.h"
namespace gold
{
@@ -59,6 +60,185 @@ Target::do_is_local_label_name(const cha
return false;
}
+// The mapping of input section name prefixes to output section names.
+// In some cases one prefix is itself a prefix of another prefix; in
+// such a case the longer prefix must come first. These prefixes are
+// based on the GNU linker default ELF linker script.
+
+#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
+#define MAPPING_INIT_EXACT(f, t) { f, 0, t, sizeof(t) - 1 }
+const Target::Section_name_mapping Target::section_name_mapping[] =
+{
+ MAPPING_INIT(".text.", ".text"),
+ MAPPING_INIT(".rodata.", ".rodata"),
+ MAPPING_INIT(".data.rel.ro.local.", ".data.rel.ro.local"),
+ MAPPING_INIT_EXACT(".data.rel.ro.local", ".data.rel.ro.local"),
+ MAPPING_INIT(".data.rel.ro.", ".data.rel.ro"),
+ MAPPING_INIT_EXACT(".data.rel.ro", ".data.rel.ro"),
+ MAPPING_INIT(".data.", ".data"),
+ MAPPING_INIT(".bss.", ".bss"),
+ MAPPING_INIT(".tdata.", ".tdata"),
+ MAPPING_INIT(".tbss.", ".tbss"),
+ MAPPING_INIT(".init_array.", ".init_array"),
+ MAPPING_INIT(".fini_array.", ".fini_array"),
+ MAPPING_INIT(".sdata.", ".sdata"),
+ MAPPING_INIT(".sbss.", ".sbss"),
+ // FIXME: In the GNU linker, .sbss2 and .sdata2 are handled
+ // differently depending on whether it is creating a shared library.
+ MAPPING_INIT(".sdata2.", ".sdata"),
+ MAPPING_INIT(".sbss2.", ".sbss"),
+ MAPPING_INIT(".lrodata.", ".lrodata"),
+ MAPPING_INIT(".ldata.", ".ldata"),
+ MAPPING_INIT(".lbss.", ".lbss"),
+ MAPPING_INIT(".gcc_except_table.", ".gcc_except_table"),
+ MAPPING_INIT(".gnu.linkonce.d.rel.ro.local.", ".data.rel.ro.local"),
+ MAPPING_INIT(".gnu.linkonce.d.rel.ro.", ".data.rel.ro"),
+ MAPPING_INIT(".gnu.linkonce.t.", ".text"),
+ MAPPING_INIT(".gnu.linkonce.r.", ".rodata"),
+ MAPPING_INIT(".gnu.linkonce.d.", ".data"),
+ MAPPING_INIT(".gnu.linkonce.b.", ".bss"),
+ MAPPING_INIT(".gnu.linkonce.s.", ".sdata"),
+ MAPPING_INIT(".gnu.linkonce.sb.", ".sbss"),
+ MAPPING_INIT(".gnu.linkonce.s2.", ".sdata"),
+ MAPPING_INIT(".gnu.linkonce.sb2.", ".sbss"),
+ MAPPING_INIT(".gnu.linkonce.wi.", ".debug_info"),
+ MAPPING_INIT(".gnu.linkonce.td.", ".tdata"),
+ MAPPING_INIT(".gnu.linkonce.tb.", ".tbss"),
+ MAPPING_INIT(".gnu.linkonce.lr.", ".lrodata"),
+ MAPPING_INIT(".gnu.linkonce.l.", ".ldata"),
+ MAPPING_INIT(".gnu.linkonce.lb.", ".lbss"),
+ MAPPING_INIT(".ARM.extab", ".ARM.extab"),
+ MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"),
+ MAPPING_INIT(".ARM.exidx", ".ARM.exidx"),
+ MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
+};
+#undef MAPPING_INIT
+#undef MAPPING_INIT_EXACT
+
+const int Target::section_name_mapping_count =
+ (sizeof(Target::section_name_mapping)
+ / sizeof(Target::section_name_mapping[0]));
+
+// Choose the output section name to use given an input section name.
+// Set *PLEN to the length of the name. *PLEN is initialized to the
+// length of NAME.
+
+const char*
+Target::do_output_section_name(const Relobj* relobj, const char* name,
+ size_t* plen)
+{
+ // gcc 4.3 generates the following sorts of section names when it
+ // needs a section name specific to a function:
+ // .text.FN
+ // .rodata.FN
+ // .sdata2.FN
+ // .data.FN
+ // .data.rel.FN
+ // .data.rel.local.FN
+ // .data.rel.ro.FN
+ // .data.rel.ro.local.FN
+ // .sdata.FN
+ // .bss.FN
+ // .sbss.FN
+ // .tdata.FN
+ // .tbss.FN
+
+ // The GNU linker maps all of those to the part before the .FN,
+ // except that .data.rel.local.FN is mapped to .data, and
+ // .data.rel.ro.local.FN is mapped to .data.rel.ro. The sections
+ // beginning with .data.rel.ro.local are grouped together.
+
+ // For an anonymous namespace, the string FN can contain a '.'.
+
+ // Also of interest: .rodata.strN.N, .rodata.cstN, both of which the
+ // GNU linker maps to .rodata.
+
+ // The .data.rel.ro sections are used with -z relro. The sections
+ // are recognized by name. We use the same names that the GNU
+ // linker does for these sections.
+
+ // It is hard to handle this in a principled way, so we don't even
+ // try. We use a table of mappings. If the input section name is
+ // not found in the table, we simply use it as the output section
+ // name.
+
+ const Section_name_mapping* psnm = section_name_mapping;
+ for (int i = 0; i < section_name_mapping_count; ++i, ++psnm)
+ {
+ if (psnm->fromlen > 0)
+ {
+ if (strncmp(name, psnm->from, psnm->fromlen) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
+ }
+ else
+ {
+ if (strcmp(name, psnm->from) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
+ }
+ }
+
+ // As an additional complication, .ctors sections are output in
+ // either .ctors or .init_array sections, and .dtors sections are
+ // output in either .dtors or .fini_array sections.
+ if (is_prefix_of(".ctors.", name) || is_prefix_of(".dtors.", name))
+ {
+ if (parameters->options().ctors_in_init_array())
+ {
+ *plen = 11;
+ return name[1] == 'c' ? ".init_array" : ".fini_array";
+ }
+ else
+ {
+ *plen = 6;
+ return name[1] == 'c' ? ".ctors" : ".dtors";
+ }
+ }
+ if (parameters->options().ctors_in_init_array()
+ && (strcmp(name, ".ctors") == 0 || strcmp(name, ".dtors") == 0))
+ {
+ // To make .init_array/.fini_array work with gcc we must exclude
+ // .ctors and .dtors sections from the crtbegin and crtend
+ // files.
+ if (relobj == NULL
+ || (!Target::match_file_name(relobj, "crtbegin")
+ && !Target::match_file_name(relobj, "crtend")))
+ {
+ *plen = 11;
+ return name[1] == 'c' ? ".init_array" : ".fini_array";
+ }
+ }
+
+ return name;
+}
+
+// Return true if RELOBJ is an input file whose base name matches
+// FILE_NAME. The base name must have an extension of ".o", and must
+// be exactly FILE_NAME.o or FILE_NAME, one character, ".o". This is
+// to match crtbegin.o as well as crtbeginS.o without getting confused
+// by other possibilities. Overall matching the file name this way is
+// a dreadful hack, but the GNU linker does it in order to better
+// support gcc, and we need to be compatible.
+
+bool
+Target::match_file_name(const Relobj* relobj, const char* match)
+{
+ const std::string& file_name(relobj->name());
+ const char* base_name = lbasename(file_name.c_str());
+ size_t match_len = strlen(match);
+ if (strncmp(base_name, match, match_len) != 0)
+ return false;
+ size_t base_len = strlen(base_name);
+ if (base_len != match_len + 2 && base_len != match_len + 3)
+ return false;
+ return memcmp(base_name + base_len - 2, ".o", 2) == 0;
+}
+
// Implementations of methods Target::do_make_elf_object are almost identical
// except for the address sizes and endianities. So we extract this
// into a template.
Index: gold/output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.168
diff -u -p -r1.168 output.cc
--- gold/output.cc 11 Aug 2012 04:41:28 -0000 1.168
+++ gold/output.cc 13 Aug 2012 14:15:07 -0000
@@ -3271,7 +3271,7 @@ class Output_section::Input_section_sort
// in order to better support gcc, and we need to be compatible.
bool
match_file_name(const char* file_name) const
- { return Layout::match_file_name(this->input_section_.relobj(), file_name); }
+ { return Target::match_file_name(this->input_section_.relobj(), file_name); }
// Returns 1 if THIS should appear before S in section order, -1 if S
// appears before THIS and 0 if they are not comparable.
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.46
diff -u -p -r1.46 powerpc.cc
--- gold/powerpc.cc 12 Aug 2012 03:07:32 -0000 1.46
+++ gold/powerpc.cc 13 Aug 2012 14:15:07 -0000
@@ -134,6 +125,17 @@ class Target_powerpc : public Sized_targ
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_symbols);
+
+ // Map input .toc section to output .got section.
+ const char*
+ do_output_section_name(const Relobj* relobj, const char* name, size_t* plen)
+ {
+ name = Target::do_output_section_name(relobj, name, plen);
+ if (size == 64 && strcmp (name, ".toc") == 0)
+ name = ".got";
+ return name;
+ }
+
// Finalize the sections.
void
do_finalize_sections(Layout*, const Input_objects*, Symbol_table*);
--
Alan Modra
Australia Development Lab, IBM