diff options
author | Cary Coutant <ccoutant@gmail.com> | 2016-03-03 12:09:06 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-03-03 12:09:06 -0800 |
commit | 82838bd626b10f1a82b0de29728c26f4458ec514 (patch) | |
tree | 696a1f1565a3a667826b6b1c62bbf7e9449e67cb /gold/testsuite | |
parent | 95ecdfbfcbf508919652a0254ee2b8c6572a949e (diff) | |
download | gdb-82838bd626b10f1a82b0de29728c26f4458ec514.zip gdb-82838bd626b10f1a82b0de29728c26f4458ec514.tar.gz gdb-82838bd626b10f1a82b0de29728c26f4458ec514.tar.bz2 |
Add new plugin hooks to support querying section alignment and size.
include/
2016-03-03 Than McIntosh <thanm@google.com>
* 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 <thanm@google.com>
* 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.
Diffstat (limited to 'gold/testsuite')
-rw-r--r-- | gold/testsuite/Makefile.am | 15 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 23 | ||||
-rw-r--r-- | gold/testsuite/plugin_layout_with_alignment.cc | 72 | ||||
-rw-r--r-- | gold/testsuite/plugin_layout_with_alignment.sh | 66 | ||||
-rw-r--r-- | gold/testsuite/plugin_section_alignment.cc | 267 |
5 files changed, 440 insertions, 3 deletions
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index d78ec6c..f8bf1e6 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 874d0bf..48cd631 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 0000000..0824d74 --- /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 <thanm@google.com>. + +// 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 0000000..c5f07ae --- /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 <thanm@google.com>. + +# 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 0000000..6f64bdc --- /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 <thanm@google.com>. +// +// 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 <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <string> +#include <vector> +#include <algorithm> + +#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<SectionInfo> 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" |