diff options
author | Howard Chu <hyc@symas.com> | 2020-11-03 15:12:47 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-11-03 15:12:47 +0000 |
commit | f3016d6ce178b76002edde12c30ebe7f608a8e21 (patch) | |
tree | c8c1943182747f75bafa7c34c4b7562ea7dfbbce /binutils | |
parent | fd65497db4098140490e59e3dbf4709da5536081 (diff) | |
download | gdb-f3016d6ce178b76002edde12c30ebe7f608a8e21.zip gdb-f3016d6ce178b76002edde12c30ebe7f608a8e21.tar.gz gdb-f3016d6ce178b76002edde12c30ebe7f608a8e21.tar.bz2 |
Add an option to the archiver to add a section recording library dependencies.
* ar.c (long_options): Add --record-libdeps.
(usage): Mention the new option.
(decode_options): Handle the new option.
(replace_members): If necessary, create a bfd to hold the libdeps
description.
* binemul.c (ar_emul_append_bfd): New function.
(ar_emul_replace_bfd): New function.
(ar_emul_default_append): Replace file_name and target arguments
with new_bfd argument.
(ar_emul_default_replace): Likewise.
* binemul.h: Update prototypes.
(struct bin_emulation_xfer_struct): Update fields.
* doc/binutils.texi: Document the new option.
* NEWS: Mention the new feature.
* emul_aix.c (ar_emul_aix_append): Update.
(ar_emul_aix_replace): Likewise.
* testsuite/binutils-all/ar.exp: Add test of new feature.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 20 | ||||
-rw-r--r-- | binutils/NEWS | 5 | ||||
-rw-r--r-- | binutils/ar.c | 86 | ||||
-rw-r--r-- | binutils/binemul.c | 53 | ||||
-rw-r--r-- | binutils/binemul.h | 15 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 19 | ||||
-rw-r--r-- | binutils/emul_aix.c | 16 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/ar.exp | 41 |
8 files changed, 210 insertions, 45 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 4ae34af..3d6732f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,23 @@ +2020-11-03 Howard Chu <hyc@symas.com> + + * ar.c (long_options): Add --record-libdeps. + (usage): Mention the new option. + (decode_options): Handle the new option. + (replace_members): If necessary, create a bfd to hold the libdeps + description. + * binemul.c (ar_emul_append_bfd): New function. + (ar_emul_replace_bfd): New function. + (ar_emul_default_append): Replace file_name and target arguments + with new_bfd argument. + (ar_emul_default_replace): Likewise. + * binemul.h: Update prototypes. + (struct bin_emulation_xfer_struct): Update fields. + * doc/binutils.texi: Document the new option. + * NEWS: Mention the new feature. + * emul_aix.c (ar_emul_aix_append): Update. + (ar_emul_aix_replace): Likewise. + * testsuite/binutils-all/ar.exp: Add test of new feature. + 2020-10-30 H.J. Lu <hongjiu.lu@intel.com> PR gas/26703 diff --git a/binutils/NEWS b/binutils/NEWS index 35e4e30..02a19ea 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,10 @@ -*- text -*- +* The ar tool's previously unused l modifier is now used for specifying + dependencies of a static library. The arguments of this option + (or --record-libdeps long form option) will be stored verbatim in the + __.LIBDEP member of the archive, which the linker may read at link time. + * Readelf can now display the contents of LTO symbol table sections when asked to do so via the --lto-syms command line option. diff --git a/binutils/ar.c b/binutils/ar.c index 85b342a..56c758c 100644 --- a/binutils/ar.c +++ b/binutils/ar.c @@ -138,6 +138,11 @@ static bfd_boolean full_pathname = FALSE; /* Whether to create a "thin" archive (symbol index only -- no files). */ static bfd_boolean make_thin_archive = FALSE; +#define LIBDEPS "__.LIBDEP" +/* Text to store in the __.LIBDEP archive element for the linker to use. */ +static char * libdeps = NULL; +static bfd * libdeps_bfd = NULL; + static int show_version = 0; static int show_help = 0; @@ -166,6 +171,7 @@ static struct option long_options[] = {"target", required_argument, NULL, OPTION_TARGET}, {"version", no_argument, &show_version, 1}, {"output", required_argument, NULL, OPTION_OUTPUT}, + {"record-libdeps", required_argument, NULL, 'l'}, {NULL, no_argument, NULL, 0} }; @@ -329,6 +335,7 @@ usage (int help) fprintf (s, _(" generic modifiers:\n")); fprintf (s, _(" [c] - do not warn if the library had to be created\n")); fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n")); + fprintf (s, _(" [l <text> ] - specify the dependencies of this library\n")); fprintf (s, _(" [S] - do not build a symbol table\n")); fprintf (s, _(" [T] - make a thin archive\n")); fprintf (s, _(" [v] - be verbose\n")); @@ -336,6 +343,7 @@ usage (int help) fprintf (s, _(" @<file> - read options from <file>\n")); fprintf (s, _(" --target=BFDNAME - specify the target object format as BFDNAME\n")); fprintf (s, _(" --output=DIRNAME - specify the output directory for extraction operations\n")); + fprintf (s, _(" --record-libdeps=<text> - specify the dependencies of this library\n")); #if BFD_SUPPORTS_PLUGINS fprintf (s, _(" optional:\n")); fprintf (s, _(" --plugin <p> - load the specified plugin\n")); @@ -487,7 +495,7 @@ decode_options (int argc, char **argv) argv = new_argv; } - while ((c = getopt_long (argc, argv, "hdmpqrtxlcoOVsSuvabiMNfPTDU", + while ((c = getopt_long (argc, argv, "hdmpqrtxl:coOVsSuvabiMNfPTDU", long_options, NULL)) != EOF) { switch (c) @@ -535,6 +543,9 @@ decode_options (int argc, char **argv) operation = extract; break; case 'l': + if (libdeps != NULL) + fatal (_("libdeps specified more than once")); + libdeps = optarg; break; case 'c': silent_create = 1; @@ -847,6 +858,49 @@ main (int argc, char **argv) if (operation == extract && bfd_is_thin_archive (arch)) fatal (_("`x' cannot be used on thin archives.")); + if (libdeps != NULL) + { + char **new_files; + bfd_size_type reclen = strlen (libdeps) + 1; + + /* Create a bfd to contain the dependencies. + It inherits its type from arch, but we must set the type to + "binary" otherwise bfd_bwrite() will fail. After writing, we + must set the type back to "plugin" otherwise adding it to the + archive will fail. */ + libdeps_bfd = bfd_create (LIBDEPS, arch); + if (libdeps_bfd == NULL) + fatal (_("Cannot create libdeps record.")); + + if (bfd_find_target ("binary", libdeps_bfd) == NULL) + fatal (_("Cannot set libdeps record type to binary.")); + + if (! bfd_set_format (libdeps_bfd, bfd_object)) + fatal (_("Cannot set libdeps object format.")); + + if (! bfd_make_writable (libdeps_bfd)) + fatal (_("Cannot make libdeps object writable.")); + + if (bfd_bwrite (libdeps, reclen, libdeps_bfd) != reclen) + fatal (_("Cannot write libdeps record.")); + + if (! bfd_make_readable (libdeps_bfd)) + fatal (_("Cannot make libdeps object readable.")); + + if (bfd_find_target ("plugin", libdeps_bfd) == NULL) + fatal (_("Cannot reset libdeps record type.")); + + /* Append our libdeps record to the list of files + being operated on. */ + new_files = xmalloc ((file_count + 2) * sizeof (char *)); + for (i = 0; i < file_count; i++) + new_files[i] = files[i]; + new_files[i++] = LIBDEPS; + file_count = i; + files = new_files; + files[i] = NULL; + } + switch (operation) { case print_table: @@ -1432,6 +1486,7 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick) normalize (bfd_get_filename (current), arch)) == 0 && current->arelt_data != NULL) { + bfd_boolean replaced; if (newer_only) { struct stat fsbuf, asbuf; @@ -1453,8 +1508,19 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick) after_bfd = get_pos_bfd (&arch->archive_next, pos_after, bfd_get_filename (current)); - if (ar_emul_replace (after_bfd, *files_to_move, - target, verbose)) + if (libdeps_bfd != NULL + && FILENAME_CMP (normalize (*files_to_move, arch), + LIBDEPS) == 0) + { + replaced = ar_emul_replace_bfd (after_bfd, libdeps_bfd, + verbose); + } + else + { + replaced = ar_emul_replace (after_bfd, *files_to_move, + target, verbose); + } + if (replaced) { /* Snip out this entry from the chain. */ *current_ptr = (*current_ptr)->archive_next; @@ -1470,9 +1536,17 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick) /* Add to the end of the archive. */ after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL); - if (ar_emul_append (after_bfd, *files_to_move, target, - verbose, make_thin_archive)) - changed = TRUE; + if (libdeps_bfd != NULL + && FILENAME_CMP (normalize (*files_to_move, arch), LIBDEPS) == 0) + { + changed |= ar_emul_append_bfd (after_bfd, libdeps_bfd, + verbose, make_thin_archive); + } + else + { + changed |= ar_emul_append (after_bfd, *files_to_move, target, + verbose, make_thin_archive); + } next_file:; diff --git a/binutils/binemul.c b/binutils/binemul.c index 7c71b5b..8a0512e 100644 --- a/binutils/binemul.c +++ b/binutils/binemul.c @@ -42,8 +42,23 @@ bfd_boolean ar_emul_append (bfd **after_bfd, char *file_name, const char *target, bfd_boolean verbose, bfd_boolean flatten) { + bfd *new_bfd; + + new_bfd = bfd_openr (file_name, target); + AR_EMUL_ELEMENT_CHECK (new_bfd, file_name); + if (bin_dummy_emulation.ar_append) + return bin_dummy_emulation.ar_append (after_bfd, new_bfd, + verbose, flatten); + + return FALSE; +} + +bfd_boolean +ar_emul_append_bfd (bfd **after_bfd, bfd *new_bfd, + bfd_boolean verbose, bfd_boolean flatten) +{ if (bin_dummy_emulation.ar_append) - return bin_dummy_emulation.ar_append (after_bfd, file_name, target, + return bin_dummy_emulation.ar_append (after_bfd, new_bfd, verbose, flatten); return FALSE; @@ -93,14 +108,9 @@ do_ar_emul_append (bfd **after_bfd, bfd *new_bfd, } bfd_boolean -ar_emul_default_append (bfd **after_bfd, char *file_name, - const char *target, bfd_boolean verbose, - bfd_boolean flatten) +ar_emul_default_append (bfd **after_bfd, bfd *new_bfd, + bfd_boolean verbose, bfd_boolean flatten) { - bfd *new_bfd; - - new_bfd = bfd_openr (file_name, target); - AR_EMUL_ELEMENT_CHECK (new_bfd, file_name); return do_ar_emul_append (after_bfd, new_bfd, verbose, flatten, any_ok); } @@ -108,23 +118,34 @@ bfd_boolean ar_emul_replace (bfd **after_bfd, char *file_name, const char *target, bfd_boolean verbose) { + bfd *new_bfd; + + new_bfd = bfd_openr (file_name, target); + AR_EMUL_ELEMENT_CHECK (new_bfd, file_name); + if (bin_dummy_emulation.ar_replace) - return bin_dummy_emulation.ar_replace (after_bfd, file_name, - target, verbose); + return bin_dummy_emulation.ar_replace (after_bfd, new_bfd, + verbose); return FALSE; } bfd_boolean -ar_emul_default_replace (bfd **after_bfd, char *file_name, - const char *target, bfd_boolean verbose) +ar_emul_replace_bfd (bfd **after_bfd, bfd *new_bfd, + bfd_boolean verbose) { - bfd *new_bfd; + if (bin_dummy_emulation.ar_replace) + return bin_dummy_emulation.ar_replace (after_bfd, new_bfd, + verbose); - new_bfd = bfd_openr (file_name, target); - AR_EMUL_ELEMENT_CHECK (new_bfd, file_name); + return FALSE; +} - AR_EMUL_REPLACE_PRINT_VERBOSE (verbose, file_name); +bfd_boolean +ar_emul_default_replace (bfd **after_bfd, bfd *new_bfd, + bfd_boolean verbose) +{ + AR_EMUL_REPLACE_PRINT_VERBOSE (verbose, bfd_get_filename (new_bfd)); new_bfd->archive_next = *after_bfd; *after_bfd = new_bfd; diff --git a/binutils/binemul.h b/binutils/binemul.h index d4a14ed..57b2e20 100644 --- a/binutils/binemul.h +++ b/binutils/binemul.h @@ -30,15 +30,19 @@ extern void ar_emul_usage (FILE *); extern void ar_emul_default_usage (FILE *); extern bfd_boolean ar_emul_append (bfd **, char *, const char *, bfd_boolean, bfd_boolean); -extern bfd_boolean ar_emul_default_append (bfd **, char *, const char *, +extern bfd_boolean ar_emul_append_bfd (bfd **, bfd *, + bfd_boolean, bfd_boolean); +extern bfd_boolean ar_emul_default_append (bfd **, bfd *, bfd_boolean, bfd_boolean); extern bfd_boolean do_ar_emul_append (bfd **, bfd *, bfd_boolean, bfd_boolean, bfd_boolean (*)(bfd *)); extern bfd_boolean ar_emul_replace (bfd **, char *, const char *, bfd_boolean); -extern bfd_boolean ar_emul_default_replace (bfd **, char *, - const char *, bfd_boolean); +extern bfd_boolean ar_emul_replace_bfd (bfd **, bfd *, + bfd_boolean); +extern bfd_boolean ar_emul_default_replace (bfd **, bfd *, + bfd_boolean); extern bfd_boolean ar_emul_parse_arg (char *); extern bfd_boolean ar_emul_default_parse_arg (char *); @@ -61,9 +65,8 @@ typedef struct bin_emulation_xfer_struct { /* Print out the extra options. */ void (* ar_usage) (FILE *fp); - bfd_boolean (* ar_append) (bfd **, char *, const char *, bfd_boolean, - bfd_boolean); - bfd_boolean (* ar_replace) (bfd **, char *, const char *, bfd_boolean); + bfd_boolean (* ar_append) (bfd **, bfd *, bfd_boolean, bfd_boolean); + bfd_boolean (* ar_replace) (bfd **, bfd *, bfd_boolean); bfd_boolean (* ar_parse_arg) (char *); } bin_emulation_xfer_type; diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 6203fde..41fd92a 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -170,7 +170,7 @@ in the section entitled ``GNU Free Documentation License''. @c man title ar create, modify, and extract from archives @smallexample -ar [-]@var{p}[@var{mod}] [@option{--plugin} @var{name}] [@option{--target} @var{bfdname}] [@option{--output} @var{dirname}] [@var{relpos}] [@var{count}] @var{archive} [@var{member}@dots{}] +ar [-]@var{p}[@var{mod}] [@option{--plugin} @var{name}] [@option{--target} @var{bfdname}] [@option{--output} @var{dirname}] [@option{--record-libdeps} @var{libdeps}] [@var{relpos}] [@var{count}] @var{archive} [@var{member}@dots{}] ar -M [ <mri-script ] @end smallexample @@ -196,7 +196,9 @@ characters (typical of formats related to coff). @cindex libraries @command{ar} is considered a binary utility because archives of this sort are most often used as @dfn{libraries} holding commonly needed -subroutines. +subroutines. Since libraries often will depend on other libraries, +@command{ar} can also record the dependencies of a library when the +@option{--record-libdeps} option is specified. @cindex symbol index @command{ar} creates an index to the symbols defined in relocatable @@ -254,7 +256,7 @@ program. @smallexample @c man begin SYNOPSIS ar -ar [@option{-X32_64}] [@option{-}]@var{p}[@var{mod}] [@option{--plugin} @var{name}] [@option{--target} @var{bfdname}] [@option{--output} @var{dirname}] [@var{relpos}] [@var{count}] @var{archive} [@var{member}@dots{}] +ar [@option{-X32_64}] [@option{-}]@var{p}[@var{mod}] [@option{--plugin} @var{name}] [@option{--target} @var{bfdname}] [@option{--output} @var{dirname}] [@option{--record-libdeps} @var{libdeps}] [@var{relpos}] [@var{count}] @var{archive} [@var{member}@dots{}] @c man end @end smallexample @@ -448,9 +450,14 @@ member must be present as the @var{relpos} argument, before the @var{archive} specification. (same as @samp{b}). @item l -This modifier is accepted but not used. +@c This modifier was accepted but not used. @c whaffor ar l modifier??? presumably compat; with @c what???---doc@@cygnus.com, 25jan91 +Specify dependencies of this library. The dependencies must immediately +follow this option character, must use the same syntax as the linker +command line, and must be specified within a single argument. I.e., if +multiple items are needed, they must be quoted to form a single command +line argument. For example @samp{L "-L/usr/local/lib -lmydep1 -lmydep2"} @item N Uses the @var{count} parameter. This is used if there are multiple @@ -592,6 +599,10 @@ Note - although the presence of this option does imply a @option{x} extraction operation that option must still be included on the command line. +@item --record-libdeps @var{libdeps} +The @option{--record-libdeps} option is identical to the @option{l} modifier, +just handled in long form. + @end table @c man end diff --git a/binutils/emul_aix.c b/binutils/emul_aix.c index c54e108..726cb3b 100644 --- a/binutils/emul_aix.c +++ b/binutils/emul_aix.c @@ -67,30 +67,20 @@ check_aix (bfd *try_bfd) } static bfd_boolean -ar_emul_aix_append (bfd **after_bfd, char *file_name, const char *target, +ar_emul_aix_append (bfd **after_bfd, bfd *new_bfd, bfd_boolean verbose, bfd_boolean flatten) { - bfd *new_bfd; - - new_bfd = bfd_openr (file_name, target); - AR_EMUL_ELEMENT_CHECK (new_bfd, file_name); - return do_ar_emul_append (after_bfd, new_bfd, verbose, flatten, check_aix); } static bfd_boolean -ar_emul_aix_replace (bfd **after_bfd, char *file_name, const char *target, +ar_emul_aix_replace (bfd **after_bfd, bfd *new_bfd, bfd_boolean verbose) { - bfd *new_bfd; - - new_bfd = bfd_openr (file_name, target); - AR_EMUL_ELEMENT_CHECK (new_bfd, file_name); - if (!check_aix (new_bfd)) return FALSE; - AR_EMUL_REPLACE_PRINT_VERBOSE (verbose, file_name); + AR_EMUL_REPLACE_PRINT_VERBOSE (verbose, bfd_get_filename (new_bfd)); new_bfd->archive_next = *after_bfd; *after_bfd = new_bfd; diff --git a/binutils/testsuite/binutils-all/ar.exp b/binutils/testsuite/binutils-all/ar.exp index 5a9d27c..273a0a3 100644 --- a/binutils/testsuite/binutils-all/ar.exp +++ b/binutils/testsuite/binutils-all/ar.exp @@ -715,6 +715,46 @@ proc many_files { } { pass $testname } +proc test_add_dependencies { } { + global AR + global AS + global srcdir + global subdir + global obj + + set testname "ar adding library dependencies" + + if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.${obj}] { + unresolved $testname + return + } + + if [is_remote host] { + set archive artest.a + set objfile [remote_download host tmpdir/bintest.${obj}] + remote_file host delete $archive + } else { + set archive tmpdir/artest.a + set objfile tmpdir/bintest.${obj} + } + + remote_file build delete tmpdir/artest.a + + set got [binutils_run $AR "-r -c $archive --record-libdeps /foo/bar ${objfile}"] + if ![string match "" $got] { + fail $testname + return + } + + set got [binutils_run $AR "-t $archive"] + if ![string match "*bintest.${obj}
__.LIBDEP*" $got] { + fail $testname + return + } + + pass $testname +} + # Run the tests. # Only run the bfdtest checks if the programs exist. Since these @@ -743,6 +783,7 @@ move_an_element empty_archive extract_an_element many_files +test_add_dependencies if { [is_elf_format] && [supports_gnu_unique] } { unique_symbol |