From de7dd2bdee702cd4a187c09427bd42b7eee239ec Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Sat, 31 May 2008 16:35:56 +0000 Subject: [PATCH] PR ld/6430 * testsuite/ld-elfcomm/elfcomm.exp (test_sort_common): Test the ascending/descending argument to the --sort-common command line option. * testsuite/ld-elfcomm/sort-common.s: New file. * ld.h (enum sort_order): New. * ldlang.c (lang_check: Fix comment. (lang_common): Sort commons in ascending or descending order. (lang_one_common): Likewise. * lexsup.c (ld_options): Have --sort-common take an option argument. (parse_args): Handle argument to --sort-common. * ld.texinfo (--sort-common): Document new optional argument. * NEWS: Mention new feature. --- ld/ChangeLog | 13 +++++ ld/NEWS | 5 +- ld/ld.h | 4 +- ld/ld.texinfo | 13 ++--- ld/ldlang.c | 38 ++++++++++++--- ld/lexsup.c | 15 ++++-- ld/testsuite/ChangeLog | 8 ++++ ld/testsuite/ld-elfcomm/elfcomm.exp | 68 +++++++++++++++++++++++++++ ld/testsuite/ld-elfcomm/sort-common.s | 6 +++ 9 files changed, 153 insertions(+), 17 deletions(-) create mode 100644 ld/testsuite/ld-elfcomm/sort-common.s diff --git a/ld/ChangeLog b/ld/ChangeLog index d896b6f606f..206ab3ce98b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,16 @@ +2008-05-31 Evandro Menezes + + PR ld/6430 + * ld.h (enum sort_order): New. + * ldlang.c (lang_check: Fix comment. + (lang_common): Sort commons in ascending or descending order. + (lang_one_common): Likewise. + * lexsup.c (ld_options): Have --sort-common take an option + argument. + (parse_args): Handle argument to --sort-common. + * ld.texinfo (--sort-common): Document new optional argument. + * NEWS: Mention new feature. + 2008-05-28 Christophe Lyon * ld.texinfo: State that farcalls stubs are supported for ARM-EABI diff --git a/ld/NEWS b/ld/NEWS index a10f222fd05..8066c33c385 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,8 +1,11 @@ -*- text -*- +* The --sort-common switch now has an optional argument which specifies the + direction of sorting. + * The M68K linker now supports multiple GOT generation schemes controlled via the --got= command line option. -* The ARM ELF linker will now generate stubs for function calls to symbols that +* The ARM EABI linker will now generate stubs for function calls to symbols that are too far away. The placement of the stubs is controlled by a new linker command line option: --stub-group-size=N. diff --git a/ld/ld.h b/ld/ld.h index 69371df880d..43a4ba21157 100644 --- a/ld/ld.h +++ b/ld/ld.h @@ -99,6 +99,8 @@ typedef struct name_list { } name_list; +typedef enum {sort_none, sort_ascending, sort_descending} sort_order; + /* A wildcard specification. */ typedef enum { @@ -265,7 +267,7 @@ typedef struct { /* If TRUE, warning messages are fatal */ bfd_boolean fatal_warnings; - bfd_boolean sort_common; + sort_order sort_common; bfd_boolean text_read_only; diff --git a/ld/ld.texinfo b/ld/ld.texinfo index f4a347350eb..a2ec34a2190 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1622,13 +1622,14 @@ and SunOS platforms. On SunOS, the linker will automatically create a shared library if the @option{-e} option is not used and there are undefined symbols in the link. -@item --sort-common +@item --sort-common [= ascending | descending] @kindex --sort-common -This option tells @command{ld} to sort the common symbols by alignment when -it places them in the appropriate output sections. First come all the -sixteen-byte aligned symbols, then all the eight-byte, then all the -four-byte, then all the two-byte, and then everything else. This is to -prevent gaps between symbols due to alignment constraints. +This option tells @command{ld} to sort the common symbols by alignment in +ascending or descending order when it places them in the appropriate output +sections. The symbol alignments considered are sixteen-byte or larger, +eight-byte, four-byte, two-byte, and one-byte. This is to prevent gaps +between symbols due to alignment constraints. If no sorting order is +specified, then descending order is assumed. @kindex --sort-section name @item --sort-section name diff --git a/ld/ldlang.c b/ld/ldlang.c index d3018b28a65..c8aac293f7e 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#include + #include "sysdep.h" #include "bfd.h" #include "libiberty.h" @@ -2699,6 +2701,13 @@ closest_target_match (const bfd_target *target, void *data) if (target->flavour != original->flavour) return 0; + /* Ignore generic big and little endian elf vectors. */ + if ( strcmp (target->name, "elf32-big") == 0 + || strcmp (target->name, "elf64-big") == 0 + || strcmp (target->name, "elf32-little") == 0 + || strcmp (target->name, "elf64-little") == 0) + return 0; + /* If we have not found a potential winner yet, then record this one. */ if (winner == NULL) { @@ -5419,7 +5428,7 @@ lang_check (void) /* Look through all the global common symbols and attach them to the correct section. The -sort-common command line switch may be used - to roughly sort the entries by size. */ + to roughly sort the entries by alignment. */ static void lang_common (void) @@ -5434,10 +5443,24 @@ lang_common (void) bfd_link_hash_traverse (link_info.hash, lang_one_common, NULL); else { - int power; + unsigned int power; - for (power = 4; power >= 0; power--) - bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); + if (config.sort_common == sort_descending) + { + for (power = 4; power > 0; power--) + bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); + + power = 0; + bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); + } + else + { + for (power = 0; power <= 4; power++) + bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); + + power = UINT_MAX; + bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); + } } } @@ -5456,8 +5479,11 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) size = h->u.c.size; power_of_two = h->u.c.p->alignment_power; - if (config.sort_common - && power_of_two < (unsigned int) *(int *) info) + if (config.sort_common == sort_descending + && power_of_two < *(unsigned int *) info) + return TRUE; + else if (config.sort_common == sort_ascending + && power_of_two > *(unsigned int *) info) return TRUE; section = h->u.c.p->section; diff --git a/ld/lexsup.c b/ld/lexsup.c index 1e133d9f9a5..5a30cfb13e7 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -473,8 +473,10 @@ static const struct ld_option ld_options[] = '\0', NULL, N_("Create a position independent executable"), ONE_DASH }, { {"pic-executable", no_argument, NULL, OPTION_PIE}, '\0', NULL, NULL, TWO_DASHES }, - { {"sort-common", no_argument, NULL, OPTION_SORT_COMMON}, - '\0', NULL, N_("Sort common symbols by size"), TWO_DASHES }, + { {"sort-common", optional_argument, NULL, OPTION_SORT_COMMON}, + '\0', N_("[=ascending|descending]"), + N_("Sort common symbols by alignment [in specified order]"), + TWO_DASHES }, { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON}, '\0', NULL, NULL, NO_HELP }, { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION}, @@ -1142,7 +1144,14 @@ parse_args (unsigned argc, char **argv) command_line.soname = optarg; break; case OPTION_SORT_COMMON: - config.sort_common = TRUE; + if (optarg == NULL + || strcmp (optarg, N_("descending")) == 0) + config.sort_common = sort_descending; + else if (strcmp (optarg, N_("ascending")) == 0) + config.sort_common = sort_ascending; + else + einfo (_("%P%F: invalid common section sorting option: %s\n"), + optarg); break; case OPTION_SORT_SECTION: if (strcmp (optarg, N_("name")) == 0) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 8a0464264e4..5b55275c424 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2008-05-31 Nick Clifton + + PR ld/6430 + * ld-elfcomm/elfcomm.exp (test_sort_common): Test the + ascending/descending argument to the --sort-common command line + option. + * ld-elfcomm/sort-common.s: New file. + 2008-05-28 Christophe Lyon * ld-arm/arm-elf.exp: Skip farcalls tests for non-ARM-EABI diff --git a/ld/testsuite/ld-elfcomm/elfcomm.exp b/ld/testsuite/ld-elfcomm/elfcomm.exp index f7de6fcac19..daed58b90b0 100644 --- a/ld/testsuite/ld-elfcomm/elfcomm.exp +++ b/ld/testsuite/ld-elfcomm/elfcomm.exp @@ -28,6 +28,74 @@ if ![is_elf_format] { return } +proc test_sort_common {} { + global exec_output + global objdump + global srcdir + global subdir + global as + global ld + + set test "--sort-common (descending)" + + verbose "Check to see that --sort-common sorts in descending alignment" + + # We do not run the sort common tests for the DLX target because we know that the linker + # will seg-fault. The built-in DLX linker script requires that there be something in the + # .text section and our sort-common.s file does not provide anything. + if [istarget dlx-*-*] { + untested "$test" + return 0 + } + + if { ![ld_assemble $as $srcdir/$subdir/sort-common.s tmpdir/sort-common.o] } { + unresolved "$test" + return 0 + } + + if { ![ld_simple_link $ld tmpdir/sort-common.dx "--sort-common=descending tmpdir/sort-common.o"] } { + fail "$test" + return 0 + } + + send_log "$objdump --syms tmpdir/sort-common.dx | grep var | sort\n" + set exec_output [run_host_cmd "$objdump" "--syms tmpdir/sort-common.dx | grep var | sort"] + + # Don't know why, but the CR ports fail this test. + setup_xfail "cr16-*-*" "crx-*-*" + + # Note: The second regexp is for targets which put small commons in a .sbss + # section and large commons in a .bss section. + if { ![regexp ".*var_16.*var_8.*var_4.*var_2.*var_1.*" $exec_output] + && ![regexp ".*sbss.*var_8.*var_4.*var_2.*var_1.*bss.*var_16.*" $exec_output] } { + fail $test + } else { + pass $test + } + + set test "--sort-common (ascending)" + + verbose "Check to see that --sort-common=ascending sorts in ascending alignment" + + if { ![ld_simple_link $ld tmpdir/sort-common.ax "--sort-common=ascending tmpdir/sort-common.o"] } { + fail "$test" + return 0 + } + + send_log "$objdump --syms tmpdir/sort-common.ax | grep var | sort\n" + set exec_output [run_host_cmd "$objdump" "--syms tmpdir/sort-common.ax | grep var | sort"] + + if {![regexp ".*var_1.*var_2.*var_4.*var_8.*var_16.*" $exec_output]} { + fail $test + return 0 + } + + pass $test + return 1 +} + +test_sort_common + set test1 "size/aligment change of common symbols" set test1w1 "$test1 (warning 1)" set test1w2 "$test1 (warning 2)" diff --git a/ld/testsuite/ld-elfcomm/sort-common.s b/ld/testsuite/ld-elfcomm/sort-common.s new file mode 100644 index 00000000000..478d73ef551 --- /dev/null +++ b/ld/testsuite/ld-elfcomm/sort-common.s @@ -0,0 +1,6 @@ + .comm var_1byte_align,1,1 + .comm var_2byte_align,2,2 + .comm var_4byte_align,4,4 + .comm var_8byte_align,8,8 + .comm var_16byte_align,16,16 + -- 2.30.2