aboutsummaryrefslogtreecommitdiff
path: root/gold/plugin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/plugin.cc')
-rw-r--r--gold/plugin.cc78
1 files changed, 77 insertions, 1 deletions
diff --git a/gold/plugin.cc b/gold/plugin.cc
index 5aadc55..c39e11ec 100644
--- a/gold/plugin.cc
+++ b/gold/plugin.cc
@@ -115,6 +115,15 @@ update_section_order(const struct ld_plugin_section *section_list,
static enum ld_plugin_status
allow_section_ordering();
+static enum ld_plugin_status
+allow_unique_segment_for_sections();
+
+static enum ld_plugin_status
+unique_segment_for_sections(const char* segment_name,
+ uint64_t flags,
+ uint64_t align,
+ const struct ld_plugin_section *section_list,
+ unsigned int num_sections);
};
#endif // ENABLE_PLUGINS
@@ -159,7 +168,7 @@ Plugin::load()
sscanf(ver, "%d.%d", &major, &minor);
// Allocate and populate a transfer vector.
- const int tv_fixed_size = 24;
+ const int tv_fixed_size = 26;
int tv_size = this->args_.size() + tv_fixed_size;
ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
@@ -273,6 +282,15 @@ Plugin::load()
tv[i].tv_u.tv_allow_section_ordering = allow_section_ordering;
++i;
+ tv[i].tv_tag = LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS;
+ tv[i].tv_u.tv_allow_unique_segment_for_sections
+ = allow_unique_segment_for_sections;
+
+ ++i;
+ tv[i].tv_tag = LDPT_UNIQUE_SEGMENT_FOR_SECTIONS;
+ tv[i].tv_u.tv_unique_segment_for_sections = unique_segment_for_sections;
+
+ ++i;
tv[i].tv_tag = LDPT_NULL;
tv[i].tv_u.tv_val = 0;
@@ -1685,6 +1703,64 @@ allow_section_ordering()
return LDPS_OK;
}
+// Let the linker know that a subset of sections could be mapped
+// to a unique segment.
+
+static enum ld_plugin_status
+allow_unique_segment_for_sections()
+{
+ gold_assert(parameters->options().has_plugins());
+ Layout* layout = parameters->options().plugins()->layout();
+ layout->set_unique_segment_for_sections_specified();
+ return LDPS_OK;
+}
+
+// This function should map the list of sections specified in the
+// SECTION_LIST to a unique segment. ELF segments do not have names
+// and the NAME is used to identify Output Section which should contain
+// the list of sections. This Output Section will then be mapped to
+// a unique segment. FLAGS is used to specify if any additional segment
+// flags need to be set. For instance, a specific segment flag can be
+// set to identify this segment. Unsetting segment flags is not possible.
+// ALIGN specifies the alignment of the segment.
+
+static enum ld_plugin_status
+unique_segment_for_sections(const char* segment_name,
+ uint64_t flags,
+ uint64_t align,
+ const struct ld_plugin_section* section_list,
+ unsigned int num_sections)
+{
+ gold_assert(parameters->options().has_plugins());
+
+ if (num_sections == 0)
+ return LDPS_OK;
+
+ if (section_list == NULL)
+ return LDPS_ERR;
+
+ Layout* layout = parameters->options().plugins()->layout();
+ gold_assert (layout != NULL);
+
+ Layout::Unique_segment_info* s = new Layout::Unique_segment_info;
+ s->name = segment_name;
+ s->flags = flags;
+ s->align = align;
+
+ for (unsigned int i = 0; i < num_sections; ++i)
+ {
+ Object* obj = parameters->options().plugins()->get_elf_object(
+ section_list[i].handle);
+ if (obj == NULL)
+ return LDPS_BAD_HANDLE;
+ unsigned int shndx = section_list[i].shndx;
+ Const_section_id secn_id(obj, shndx);
+ layout->insert_section_segment_map(secn_id, s);
+ }
+
+ return LDPS_OK;
+}
+
#endif // ENABLE_PLUGINS
// Allocate a Pluginobj object of the appropriate size and endianness.