From 82838bd626b10f1a82b0de29728c26f4458ec514 Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Thu, 3 Mar 2016 12:09:06 -0800 Subject: [PATCH] Add new plugin hooks to support querying section alignment and size. include/ 2016-03-03 Than McIntosh * plugin-api.h: Add new hooks to the plugin transfer vector to to support querying section alignment and section size. (ld_plugin_get_input_section_alignment): New hook. (ld_plugin_get_input_section_size): New hook. (ld_plugin_tag): Add LDPT_GET_INPUT_SECTION_ALIGNMENT and LDPT_GET_INPUT_SECTION_SIZE. (ld_plugin_tv): Add tv_get_input_section_alignment and tv_get_input_section_size. gold/ 2016-03-03 Than McIntosh * plugin.cc (Plugin::load): Include hooks for get_input_section_size and get_input_section_alignment in transfer vector. (get_input_section_alignment): New function. (get_input_section_size): New function. * testsuite/Makefile.am: Add plugin_layout_with_alignment.sh test. * testsuite/Makefile.in: [Regenerate.] * testsuite/plugin_section_alignment.cc: New test file. * testsuite/plugin_layout_with_alignment.cc: New test file. * testsuite/plugin_layout_with_alignment.sh: New test file. --- gold/plugin.cc | 66 ++++- gold/testsuite/Makefile.am | 15 + gold/testsuite/Makefile.in | 23 +- .../testsuite/plugin_layout_with_alignment.cc | 72 +++++ .../testsuite/plugin_layout_with_alignment.sh | 66 +++++ gold/testsuite/plugin_section_alignment.cc | 267 ++++++++++++++++++ include/plugin-api.h | 26 +- 7 files changed, 530 insertions(+), 5 deletions(-) create mode 100644 gold/testsuite/plugin_layout_with_alignment.cc create mode 100644 gold/testsuite/plugin_layout_with_alignment.sh create mode 100644 gold/testsuite/plugin_section_alignment.cc diff --git a/gold/plugin.cc b/gold/plugin.cc index 4aeb3ea708..bb7d6b2606 100644 --- a/gold/plugin.cc +++ b/gold/plugin.cc @@ -158,6 +158,15 @@ unique_segment_for_sections(const char* segment_name, uint64_t align, const struct ld_plugin_section *section_list, unsigned int num_sections); + +static enum ld_plugin_status +get_input_section_alignment(const struct ld_plugin_section section, + unsigned int* addralign); + +static enum ld_plugin_status +get_input_section_size(const struct ld_plugin_section section, + uint64_t* secsize); + }; #endif // ENABLE_PLUGINS @@ -202,7 +211,7 @@ Plugin::load() sscanf(ver, "%d.%d", &major, &minor); // Allocate and populate a transfer vector. - const int tv_fixed_size = 27; + const int tv_fixed_size = 29; int tv_size = this->args_.size() + tv_fixed_size; ld_plugin_tv* tv = new ld_plugin_tv[tv_size]; @@ -328,6 +337,14 @@ Plugin::load() 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_GET_INPUT_SECTION_ALIGNMENT; + tv[i].tv_u.tv_get_input_section_alignment = get_input_section_alignment; + + ++i; + tv[i].tv_tag = LDPT_GET_INPUT_SECTION_SIZE; + tv[i].tv_u.tv_get_input_section_size = get_input_section_size; + ++i; tv[i].tv_tag = LDPT_NULL; tv[i].tv_u.tv_val = 0; @@ -1730,6 +1747,53 @@ get_input_section_contents(const struct ld_plugin_section section, return LDPS_OK; } +// Get the alignment of the specified section in the object corresponding +// to the handle. This plugin interface can only be called in the +// claim_file handler of the plugin. + +static enum ld_plugin_status +get_input_section_alignment(const struct ld_plugin_section section, + unsigned int* addralign) +{ + gold_assert(parameters->options().has_plugins()); + + if (!parameters->options().plugins()->in_claim_file_handler()) + return LDPS_ERR; + + Object* obj + = parameters->options().plugins()->get_elf_object(section.handle); + + if (obj == NULL) + return LDPS_BAD_HANDLE; + + *addralign = obj->section_addralign(section.shndx); + return LDPS_OK; +} + +// Get the size of the specified section in the object corresponding +// to the handle. This plugin interface can only be called in the +// claim_file handler of the plugin. + +static enum ld_plugin_status +get_input_section_size(const struct ld_plugin_section section, + uint64_t* secsize) +{ + gold_assert(parameters->options().has_plugins()); + + if (!parameters->options().plugins()->in_claim_file_handler()) + return LDPS_ERR; + + Object* obj + = parameters->options().plugins()->get_elf_object(section.handle); + + if (obj == NULL) + return LDPS_BAD_HANDLE; + + *secsize = obj->section_size(section.shndx); + return LDPS_OK; +} + + // Specify the ordering of sections in the final layout. The sections are // specified as (handle,shndx) pairs in the two arrays in the order in // which they should appear in the final layout. diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index d78ec6cfaf..f8bf1e6250 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -2101,6 +2101,21 @@ plugin_section_order.so: plugin_section_order.o plugin_section_order.o: plugin_section_order.c $(COMPILE) -O0 -c -fpic -o $@ $< +check_SCRIPTS += plugin_layout_with_alignment.sh +check_DATA += plugin_layout_with_alignment.stdout +MOSTLYCLEANFILES += plugin_layout_with_alignment +plugin_layout_with_alignment.o: plugin_layout_with_alignment.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $< +plugin_layout_with_alignment: plugin_layout_with_alignment.o plugin_section_alignment.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_alignment.so" plugin_layout_with_alignment.o +plugin_layout_with_alignment.stdout: plugin_layout_with_alignment + $(TEST_NM) -n --synthetic plugin_layout_with_alignment > plugin_layout_with_alignment.stdout + +plugin_section_alignment.so: plugin_section_alignment.o + $(CXXLINK) -Bgcctestdir/ -shared plugin_section_alignment.o +plugin_section_alignment.o: plugin_section_alignment.cc + $(CXXCOMPILE) -O0 -c -fpic -o $@ $< + endif PLUGINS check_PROGRAMS += exclude_libs_test diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 874d0bfbe7..48cd6310a3 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -474,9 +474,13 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@@TLS_TRUE@am__append_43 = plugin_test_tls.err @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@@TLS_TRUE@am__append_44 = plugin_test_tls.err @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_45 = unused.c \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout -@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_46 = plugin_final_layout.sh -@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_47 = plugin_final_layout.stdout plugin_final_layout_readelf.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_layout_with_alignment +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_46 = plugin_final_layout.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_layout_with_alignment.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_47 = plugin_final_layout.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout_readelf.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_layout_with_alignment.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_48 = exclude_libs_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ local_labels_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test @@ -4561,6 +4565,8 @@ plugin_test_tls.sh.log: plugin_test_tls.sh @p='plugin_test_tls.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) plugin_final_layout.sh.log: plugin_final_layout.sh @p='plugin_final_layout.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +plugin_layout_with_alignment.sh.log: plugin_layout_with_alignment.sh + @p='plugin_layout_with_alignment.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) exclude_libs_test.sh.log: exclude_libs_test.sh @p='exclude_libs_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) discard_locals_test.sh.log: discard_locals_test.sh @@ -6131,6 +6137,17 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(LINK) -Bgcctestdir/ -shared plugin_section_order.o @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.o: plugin_section_order.c @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -O0 -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_with_alignment.o: plugin_layout_with_alignment.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_with_alignment: plugin_layout_with_alignment.o plugin_section_alignment.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_alignment.so" plugin_layout_with_alignment.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_layout_with_alignment.stdout: plugin_layout_with_alignment +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_NM) -n --synthetic plugin_layout_with_alignment > plugin_layout_with_alignment.stdout + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_alignment.so: plugin_section_alignment.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared plugin_section_alignment.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_alignment.o: plugin_section_alignment.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXCOMPILE) -O0 -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test.syms: exclude_libs_test @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@libexclude_libs_test_1.a: exclude_libs_test_1.o diff --git a/gold/testsuite/plugin_layout_with_alignment.cc b/gold/testsuite/plugin_layout_with_alignment.cc new file mode 100644 index 0000000000..0824d74a91 --- /dev/null +++ b/gold/testsuite/plugin_layout_with_alignment.cc @@ -0,0 +1,72 @@ +// plugin_layout_with_alignment.cc -- a test case for gold + +// Copyright (C) 2016 Free Software Foundation, Inc. +// Written by Than McIntosh . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// Verify that plugin interfaces for section size and alignment work +// correctly, and that section ordering via plugins is working +// for .bss/.rodata/.data sections. + +// --- Initialized .rodata items + +__attribute__ ((section(".rodata.v1_a2"))) +const short rodata_item1 = 101; + +__attribute__ ((section(".rodata.v2_a1"))) +const char rodata_item2 = 'a'; + +__attribute__ ((section(".rodata.v3_a8"))) +const double rodata_item3 = 777.777; + +__attribute__ ((section(".rodata.v4_a1"))) +const char rodata_item4[7] = {'1', '2', '3', '4', '5', '6', '7'}; + +// --- Initialized .data items + +__attribute__ ((section(".data.v1_a2"))) +short rwdata_item1 = 101; + +__attribute__ ((section(".data.v2_a1"))) +char rwdata_item2 = 'a'; + +__attribute__ ((section(".data.v3_a8"))) +double rwdata_item3 = 'b'; + +__attribute__ ((section(".data.v4_a1"))) +char rwdata_item4[3] = {'a', 'b', 'c'}; + +// --- Uninitialized .data items + +__attribute__ ((section(".bss.v1_a2"))) +short bss_item1; + +__attribute__ ((section(".bss.v2_a1"))) +char bss_item2; + +__attribute__ ((section(".bss.v3_a8"))) +struct blah { union { double d; char c; } u; } bss_item3; + +__attribute__ ((section(".bss.v4_a1"))) +char bss_item4[3]; + +int main () +{ + return 0; +} diff --git a/gold/testsuite/plugin_layout_with_alignment.sh b/gold/testsuite/plugin_layout_with_alignment.sh new file mode 100644 index 0000000000..c5f07aec28 --- /dev/null +++ b/gold/testsuite/plugin_layout_with_alignment.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# plugin_layout_with_alignment.sh -- test + +# Copyright (C) 2016 Free Software Foundation, Inc. +# Written by Than McIntosh . + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify plugin alignment and size +# interfaces and working correctly in combination with section ordering. +# intended. File plugin_layout_with_alignment.cc is in this test. + + +set -e + +check() +{ + awk " +BEGIN { saw1 = 0; saw2 = 0; saw3 = 0; saw4 = 0; counter = 1; err = 0; ord = \"\"; } +/.*$2\$/ { saw1 = counter; counter = counter + 1; ord = ord \" $2\"; } +/.*$3\$/ { saw2 = counter; counter = counter + 1; ord = ord \" $3\"; } +/.*$4\$/ { saw3 = counter; counter = counter + 1; ord = ord \" $4\"; } +/.*$5\$/ { saw4 = counter; counter = counter + 1; ord = ord \" $5\"; } +END { + if (!saw1) { + printf \"did not see $2\\n\"; + exit 1; + } + if (!saw2) { + printf \"did not see $3\\n\"; + exit 1; + } + if (!saw3) { + printf \"did not see $4\\n\"; + exit 1; + } + if (!saw4) { + printf \"did not see $5\\n\"; + exit 1; + } + if (saw1 != 1 || saw2 != 2 || saw3 != 3 || saw4 != 4) { + printf \"incorrect ordering:\\nwas:%s\\nshould have been: $2 $3 $4 $5\\n\", ord; + exit 1; + } + }" $1 +} + +check plugin_layout_with_alignment.stdout "bss_item3" "bss_item1" "bss_item4" "bss_item2" +check plugin_layout_with_alignment.stdout "rwdata_item2" "rwdata_item4" "rwdata_item1" "rwdata_item3" +check plugin_layout_with_alignment.stdout "rodata_item3" "rodata_item1" "rodata_item2" "rodata_item4" diff --git a/gold/testsuite/plugin_section_alignment.cc b/gold/testsuite/plugin_section_alignment.cc new file mode 100644 index 0000000000..6f64bdc6e8 --- /dev/null +++ b/gold/testsuite/plugin_section_alignment.cc @@ -0,0 +1,267 @@ +// plugin_section_alignment.cc -- plugins to test ordering with {size,alignment} +// +// Copyright (C) 2016 Free Software Foundation, Inc. +// Written by Than McIntosh . +// +// This file is part of gold. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include "plugin-api.h" + +static ld_plugin_get_input_section_count get_input_section_count = NULL; +static ld_plugin_get_input_section_alignment get_input_section_alignment = NULL; +static ld_plugin_get_input_section_size get_input_section_size = NULL; +static ld_plugin_get_input_section_name get_input_section_name = NULL; +static ld_plugin_update_section_order update_section_order = NULL; +static ld_plugin_allow_section_ordering allow_section_ordering = NULL; + +extern "C" { + enum ld_plugin_status onload(struct ld_plugin_tv *tv); + enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file, + int *claimed); + enum ld_plugin_status all_symbols_read_hook(void); +} + +typedef enum { FL_BSS, FL_DATA, FL_RODATA, FL_UNKNOWN } sec_flavor; + +inline static int is_prefix_of(const char *prefix, const char *str) +{ + return strncmp(prefix, str, strlen(prefix)) == 0; +} + +inline static sec_flavor flavor_from_name(const char *secname) +{ + if (is_prefix_of(".data.v", secname)) { + return FL_DATA; + } else if (is_prefix_of(".bss.v", secname)) { + return FL_BSS; + } else if (is_prefix_of(".rodata.v", secname)) { + return FL_RODATA; + } else { + return FL_UNKNOWN; + } +} + +struct SectionInfo { + ld_plugin_section plugin_section; + std::string name; + uint64_t size; + sec_flavor flavor; + unsigned align; + + static bool SectionInfoLt(const SectionInfo &i1, + const SectionInfo &i2) + { + if (i1.flavor != i2.flavor) { + return ((unsigned) i1.flavor) < ((unsigned) i2.flavor); + } + switch (i1.flavor) { + case FL_DATA: + // Sort data items by increasing alignment then increasing size + if (i1.align != i2.align) { + return ((unsigned) i1.align) < ((unsigned) i2.align); + } + if (i1.size != i2.size) { + return ((unsigned) i1.size) < ((unsigned) i2.size); + } + break; + case FL_BSS: + // Sort bss items by decreasing alignment then decreasing size + if (i1.align != i2.align) { + return ((unsigned) i2.align) < ((unsigned) i1.align); + } + if (i1.size != i2.size) { + return ((unsigned) i2.size) < ((unsigned) i1.size); + } + break; + case FL_RODATA: + // Sort rodata items by decreasing alignment then increasing size + if (i1.align != i2.align) { + return ((unsigned) i2.align) < ((unsigned) i1.align); + } + if (i1.size != i2.size) { + return ((unsigned) i1.size) < ((unsigned) i2.size); + } + default: + break; + } + + // Break ties by name + return i1.name.compare(i2.name) < 0; + } + +}; +typedef std::vector section_info_vector; +section_info_vector raw_sections; + +// Set to 1 for debugging output +unsigned trace = 0; + +extern "C" { + +// Plugin entry point. +enum ld_plugin_status onload(struct ld_plugin_tv *tv) +{ + struct ld_plugin_tv *entry; + for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry) + { + switch (entry->tv_tag) + { + case LDPT_OPTION: + if (!strcmp(entry->tv_u.tv_string,"-trace")) { + fprintf(stderr, "enabling tracing\n"); + trace += 1; + } else { + fprintf(stderr, "unknown plugin option %s", entry->tv_u.tv_string); + } + break; + case LDPT_REGISTER_CLAIM_FILE_HOOK: + assert((*entry->tv_u.tv_register_claim_file)(claim_file_hook) == + LDPS_OK); + break; + case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: + assert((*entry->tv_u.tv_register_all_symbols_read)( + all_symbols_read_hook) == LDPS_OK); + break; + case LDPT_GET_INPUT_SECTION_COUNT: + get_input_section_count = *entry->tv_u.tv_get_input_section_count; + break; + case LDPT_GET_INPUT_SECTION_NAME: + get_input_section_name = *entry->tv_u.tv_get_input_section_name; + break; + case LDPT_GET_INPUT_SECTION_ALIGNMENT: + get_input_section_alignment = + *entry->tv_u.tv_get_input_section_alignment; + break; + case LDPT_GET_INPUT_SECTION_SIZE: + get_input_section_size = *entry->tv_u.tv_get_input_section_size; + break; + case LDPT_UPDATE_SECTION_ORDER: + update_section_order = *entry->tv_u.tv_update_section_order; + break; + case LDPT_ALLOW_SECTION_ORDERING: + allow_section_ordering = *entry->tv_u.tv_allow_section_ordering; + break; + default: + break; + } + } + + if (get_input_section_count == NULL || get_input_section_alignment == NULL || + get_input_section_size == NULL || get_input_section_name == NULL || + update_section_order == NULL || allow_section_ordering == NULL) { + fprintf(stderr, "Some interfaces are missing\n"); + return LDPS_ERR; + } + + return LDPS_OK; +} + +// This function is called by the linker for every new object it encounters. +enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file, + int *claimed) +{ + static bool is_ordering_specified = false; + struct ld_plugin_section section; + unsigned count = 0; + unsigned shndx; + + *claimed = 0; + if (!is_ordering_specified) { + // Inform the linker to prepare for section reordering. + (*allow_section_ordering)(); + is_ordering_specified = true; + } + + (*get_input_section_count)(file->handle, &count); + + for (shndx = 0; shndx < count; ++shndx) { + char *name = NULL; + + section.handle = file->handle; + section.shndx = shndx; + (*get_input_section_name)(section, &name); + if (is_prefix_of(".data.v", name) || + is_prefix_of(".bss.v", name) || + is_prefix_of(".rodata.v", name)) { + SectionInfo si; + si.plugin_section.handle = file->handle; + si.plugin_section.shndx = shndx; + (*get_input_section_size)(section, &si.size); + (*get_input_section_alignment)(section, &si.align); + si.name = name; + si.flavor = flavor_from_name(name); + raw_sections.push_back(si); + } + } + + return LDPS_OK; +} + +// This function is called by the linker after all the symbols have been read. +// At this stage, it is fine to tell the linker the desired function order. + +enum ld_plugin_status all_symbols_read_hook(void) +{ + // We expect to see a total of twelve sections -- if this is not the case + // then something went wrong somewhere along the way. + if (raw_sections.size() != 12) { + fprintf(stderr, "Expected 12 sections, found %u sections", + (unsigned) raw_sections.size()); + return LDPS_ERR; + } + + std::sort(raw_sections.begin(), raw_sections.end(), + SectionInfo::SectionInfoLt); + + struct ld_plugin_section section_list[12]; + for (unsigned ii = 0; ii < 12; ++ii) { + section_list[ii] = raw_sections[ii].plugin_section; + } + + if (trace) { + fprintf(stderr, "Specified section order is:\n"); + for (section_info_vector::iterator it = raw_sections.begin(); + it != raw_sections.end(); + ++it) { + const SectionInfo &si = (*it); + fprintf(stderr, "Idx=%u Name=%s Align=%u Size=%u\n", + si.plugin_section.shndx, si.name.c_str(), si.align, + (unsigned) si.size); + } + } + + update_section_order(section_list, 12); + + return LDPS_OK; +} + +} // end extern "C" diff --git a/include/plugin-api.h b/include/plugin-api.h index 811e6e4da3..a794a37049 100644 --- a/include/plugin-api.h +++ b/include/plugin-api.h @@ -345,6 +345,26 @@ enum ld_plugin_status const struct ld_plugin_section * section_list, unsigned int num_sections); +/* The linker's interface for retrieving the section alignment requirement + of a specific section in an object. This interface should only be invoked in the + claim_file handler. This function sets *ADDRALIGN to the ELF sh_addralign + value of the input section. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_section_alignment) (const struct ld_plugin_section section, + unsigned int *addralign); + +/* The linker's interface for retrieving the section size of a specific section + in an object. This interface should only be invoked in the claim_file handler. + This function sets *SECSIZE to the ELF sh_size + value of the input section. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_section_size) (const struct ld_plugin_section section, + uint64_t *secsize); + enum ld_plugin_level { LDPL_INFO, @@ -385,7 +405,9 @@ enum ld_plugin_tag LDPT_GET_SYMBOLS_V2 = 25, LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS = 26, LDPT_UNIQUE_SEGMENT_FOR_SECTIONS = 27, - LDPT_GET_SYMBOLS_V3 = 28 + LDPT_GET_SYMBOLS_V3 = 28, + LDPT_GET_INPUT_SECTION_ALIGNMENT = 29, + LDPT_GET_INPUT_SECTION_SIZE = 30 }; /* The plugin transfer vector. */ @@ -417,6 +439,8 @@ struct ld_plugin_tv ld_plugin_allow_section_ordering tv_allow_section_ordering; ld_plugin_allow_unique_segment_for_sections tv_allow_unique_segment_for_sections; ld_plugin_unique_segment_for_sections tv_unique_segment_for_sections; + ld_plugin_get_input_section_alignment tv_get_input_section_alignment; + ld_plugin_get_input_section_size tv_get_input_section_size; } tv_u; };