mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-11 13:02:10 +08:00
Add a plugin for processing static library dependencies.
* libdep_plugin.c: New file: Processes archives that contain a special library dependencies element. * Makefile.am: Add build rules for libdep_plugin. * Makefile.in: Regenerate. * NEWS: Mention the new plugin. * ld.texi: Document the new plugin.
This commit is contained in:
parent
a86c6c1964
commit
bf6d803782
@ -1,3 +1,12 @@
|
||||
2020-12-14 Howard Chu <hyc@symas.com>
|
||||
|
||||
* libdep_plugin.c: New file: Processes archives that contain a
|
||||
special library dependencies element.
|
||||
* Makefile.am: Add build rules for libdep_plugin.
|
||||
* Makefile.in: Regenerate.
|
||||
* NEWS: Mention the new plugin.
|
||||
* ld.texi: Document the new plugin.
|
||||
|
||||
2020-12-14 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 26836
|
||||
|
@ -998,6 +998,11 @@ libldtestplug4_la_SOURCES = testplug4.c
|
||||
libldtestplug4_la_CFLAGS= -g -O2
|
||||
libldtestplug4_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
|
||||
bfdplugindir = $(libdir)/bfd-plugins
|
||||
bfdplugin_LTLIBRARIES = libdep.la
|
||||
libdep_la_SOURCES = libdep_plugin.c
|
||||
libdep_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
|
||||
# DOCUMENTATION TARGETS
|
||||
# Manual configuration file; not usually attached to normal configuration,
|
||||
# because almost all configs use "gen" version of manual.
|
||||
|
158
ld/Makefile.in
158
ld/Makefile.in
@ -137,14 +137,49 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES = po/Makefile.in
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libldtestplug_la_LIBADD =
|
||||
am_libldtestplug_la_OBJECTS = libldtestplug_la-testplug.lo
|
||||
libldtestplug_la_OBJECTS = $(am_libldtestplug_la_OBJECTS)
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(bfdplugindir)" "$(DESTDIR)$(bindir)" \
|
||||
"$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"
|
||||
LTLIBRARIES = $(bfdplugin_LTLIBRARIES) $(noinst_LTLIBRARIES)
|
||||
libdep_la_LIBADD =
|
||||
am_libdep_la_OBJECTS = libdep_plugin.lo
|
||||
libdep_la_OBJECTS = $(am_libdep_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
libdep_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libdep_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
libldtestplug_la_LIBADD =
|
||||
am_libldtestplug_la_OBJECTS = libldtestplug_la-testplug.lo
|
||||
libldtestplug_la_OBJECTS = $(am_libldtestplug_la_OBJECTS)
|
||||
libldtestplug_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
|
||||
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
|
||||
$(libldtestplug_la_CFLAGS) $(CFLAGS) \
|
||||
@ -170,8 +205,6 @@ libldtestplug4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
|
||||
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
|
||||
$(libldtestplug4_la_CFLAGS) $(CFLAGS) \
|
||||
$(libldtestplug4_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" \
|
||||
"$(DESTDIR)$(man1dir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_ld_new_OBJECTS = ldgram.$(OBJEXT) ldlex-wrapper.$(OBJEXT) \
|
||||
lexsup.$(OBJEXT) ldlang.$(OBJEXT) mri.$(OBJEXT) \
|
||||
@ -235,9 +268,10 @@ AM_V_YACC = $(am__v_YACC_@AM_V@)
|
||||
am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
|
||||
am__v_YACC_0 = @echo " YACC " $@;
|
||||
am__v_YACC_1 =
|
||||
SOURCES = $(libldtestplug_la_SOURCES) $(libldtestplug2_la_SOURCES) \
|
||||
$(libldtestplug3_la_SOURCES) $(libldtestplug4_la_SOURCES) \
|
||||
$(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES)
|
||||
SOURCES = $(libdep_la_SOURCES) $(libldtestplug_la_SOURCES) \
|
||||
$(libldtestplug2_la_SOURCES) $(libldtestplug3_la_SOURCES) \
|
||||
$(libldtestplug4_la_SOURCES) $(ld_new_SOURCES) \
|
||||
$(EXTRA_ld_new_SOURCES)
|
||||
AM_V_DVIPS = $(am__v_DVIPS_@AM_V@)
|
||||
am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@)
|
||||
am__v_DVIPS_0 = @echo " DVIPS " $@;
|
||||
@ -290,33 +324,6 @@ am__can_run_installinfo = \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
man1dir = $(mandir)/man1
|
||||
NROFF = nroff
|
||||
MANS = $(man_MANS)
|
||||
@ -1013,6 +1020,10 @@ libldtestplug3_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
libldtestplug4_la_SOURCES = testplug4.c
|
||||
libldtestplug4_la_CFLAGS = -g -O2
|
||||
libldtestplug4_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
bfdplugindir = $(libdir)/bfd-plugins
|
||||
bfdplugin_LTLIBRARIES = libdep.la
|
||||
libdep_la_SOURCES = libdep_plugin.c
|
||||
libdep_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
MAINTAINERCLEANFILES = configdoc.texi ld.1 ld.info
|
||||
|
||||
# We want to reconfigure if configure.host or configure.tgt changes.
|
||||
@ -1088,6 +1099,41 @@ distclean-hdr:
|
||||
po/Makefile.in: $(top_builddir)/config.status $(top_srcdir)/po/Make-in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||
|
||||
install-bfdpluginLTLIBRARIES: $(bfdplugin_LTLIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bfdplugin_LTLIBRARIES)'; test -n "$(bfdplugindir)" || list=; \
|
||||
list2=; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
list2="$$list2 $$p"; \
|
||||
else :; fi; \
|
||||
done; \
|
||||
test -z "$$list2" || { \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bfdplugindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bfdplugindir)" || exit 1; \
|
||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(bfdplugindir)'"; \
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(bfdplugindir)"; \
|
||||
}
|
||||
|
||||
uninstall-bfdpluginLTLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bfdplugin_LTLIBRARIES)'; test -n "$(bfdplugindir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(bfdplugindir)/$$f'"; \
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(bfdplugindir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-bfdpluginLTLIBRARIES:
|
||||
-test -z "$(bfdplugin_LTLIBRARIES)" || rm -f $(bfdplugin_LTLIBRARIES)
|
||||
@list='$(bfdplugin_LTLIBRARIES)'; \
|
||||
locs=`for p in $$list; do echo $$p; done | \
|
||||
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
|
||||
sort -u`; \
|
||||
test -z "$$locs" || { \
|
||||
echo rm -f $${locs}; \
|
||||
rm -f $${locs}; \
|
||||
}
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; \
|
||||
@ -1099,6 +1145,9 @@ clean-noinstLTLIBRARIES:
|
||||
rm -f $${locs}; \
|
||||
}
|
||||
|
||||
libdep.la: $(libdep_la_OBJECTS) $(libdep_la_DEPENDENCIES) $(EXTRA_libdep_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(libdep_la_LINK) -rpath $(bfdplugindir) $(libdep_la_OBJECTS) $(libdep_la_LIBADD) $(LIBS)
|
||||
|
||||
libldtestplug.la: $(libldtestplug_la_OBJECTS) $(libldtestplug_la_DEPENDENCIES) $(EXTRA_libldtestplug_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(libldtestplug_la_LINK) $(libldtestplug_la_OBJECTS) $(libldtestplug_la_LIBADD) $(LIBS)
|
||||
|
||||
@ -1492,6 +1541,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldver.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldwrite.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexsup.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdep_plugin.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug2_la-testplug2.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug3_la-testplug3.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug4_la-testplug4.Plo@am__quote@
|
||||
@ -1886,7 +1936,7 @@ all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) $(PROGRAMS) $(MANS) \
|
||||
config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
|
||||
for dir in "$(DESTDIR)$(bfdplugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: $(BUILT_SOURCES)
|
||||
@ -1932,8 +1982,9 @@ maintainer-clean-generic:
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-aminfo clean-binPROGRAMS clean-generic clean-libtool \
|
||||
clean-noinstLTLIBRARIES mostlyclean-am
|
||||
clean-am: clean-aminfo clean-bfdpluginLTLIBRARIES clean-binPROGRAMS \
|
||||
clean-generic clean-libtool clean-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
@ -1955,7 +2006,8 @@ info: info-recursive
|
||||
|
||||
info-am: $(INFO_DEPS)
|
||||
|
||||
install-data-am: install-data-local install-info-am install-man
|
||||
install-data-am: install-bfdpluginLTLIBRARIES install-data-local \
|
||||
install-info-am install-man
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
@ -2095,9 +2147,9 @@ ps: ps-recursive
|
||||
|
||||
ps-am: $(PSS)
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-dvi-am uninstall-html-am \
|
||||
uninstall-info-am uninstall-man uninstall-pdf-am \
|
||||
uninstall-ps-am
|
||||
uninstall-am: uninstall-bfdpluginLTLIBRARIES uninstall-binPROGRAMS \
|
||||
uninstall-dvi-am uninstall-html-am uninstall-info-am \
|
||||
uninstall-man uninstall-pdf-am uninstall-ps-am
|
||||
|
||||
uninstall-man: uninstall-man1
|
||||
|
||||
@ -2106,12 +2158,13 @@ uninstall-man: uninstall-man1
|
||||
|
||||
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
|
||||
am--refresh check check-DEJAGNU check-am clean clean-aminfo \
|
||||
clean-binPROGRAMS clean-cscope clean-generic clean-libtool \
|
||||
clean-noinstLTLIBRARIES cscope cscopelist-am ctags ctags-am \
|
||||
dist-info distclean distclean-DEJAGNU distclean-compile \
|
||||
distclean-generic distclean-hdr distclean-libtool \
|
||||
distclean-local distclean-tags dvi dvi-am html html-am info \
|
||||
info-am install install-am install-binPROGRAMS install-data \
|
||||
clean-bfdpluginLTLIBRARIES clean-binPROGRAMS clean-cscope \
|
||||
clean-generic clean-libtool clean-noinstLTLIBRARIES cscope \
|
||||
cscopelist-am ctags ctags-am dist-info distclean \
|
||||
distclean-DEJAGNU distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-libtool distclean-local distclean-tags \
|
||||
dvi dvi-am html html-am info info-am install install-am \
|
||||
install-bfdpluginLTLIBRARIES install-binPROGRAMS install-data \
|
||||
install-data-am install-data-local install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-exec-local install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
@ -2121,9 +2174,10 @@ uninstall-man: uninstall-man1
|
||||
maintainer-clean-aminfo maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-aminfo mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool mostlyclean-local pdf pdf-am ps ps-am tags \
|
||||
tags-am uninstall uninstall-am uninstall-binPROGRAMS \
|
||||
uninstall-dvi-am uninstall-html-am uninstall-info-am \
|
||||
uninstall-man uninstall-man1 uninstall-pdf-am uninstall-ps-am
|
||||
tags-am uninstall uninstall-am uninstall-bfdpluginLTLIBRARIES \
|
||||
uninstall-binPROGRAMS uninstall-dvi-am uninstall-html-am \
|
||||
uninstall-info-am uninstall-man uninstall-man1 \
|
||||
uninstall-pdf-am uninstall-ps-am
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
3
ld/NEWS
3
ld/NEWS
@ -1,5 +1,8 @@
|
||||
-*- text -*-
|
||||
|
||||
* Add libdep plugin, for linking dependencies of static libraries that
|
||||
were recorded by ar in the __.LIBDEP archive member.
|
||||
|
||||
* Add --error-handling-script=<NAME> command line option to allow a helper
|
||||
script to be invoked when an undefined symbol or a missing library is
|
||||
encountered. This option can be suppressed via the configure time
|
||||
|
53
ld/ld.texi
53
ld/ld.texi
@ -126,6 +126,7 @@ in the section entitled ``GNU Free Documentation License''.
|
||||
* Overview:: Overview
|
||||
* Invocation:: Invocation
|
||||
* Scripts:: Linker Scripts
|
||||
* Plugins:: Linker Plugins
|
||||
@ifset GENERIC
|
||||
* Machine Dependent:: Machine Dependent Features
|
||||
@end ifset
|
||||
@ -6954,6 +6955,58 @@ Any input files read because of an implicit linker script will be read
|
||||
at the position in the command line where the implicit linker script was
|
||||
read. This can affect archive searching.
|
||||
|
||||
@node Plugins
|
||||
@chapter Linker Plugins
|
||||
|
||||
@cindex plugins
|
||||
@cindex linker plugins
|
||||
The linker can use dynamically loaded plugins to modify its behavior.
|
||||
For example, the link-time optimization feature that some compilers
|
||||
support is implemented with a linker plugin.
|
||||
|
||||
Currently there is only one plugin shipped by default, but more may
|
||||
be added here later.
|
||||
|
||||
@menu
|
||||
* libdep Plugin:: Static Library Dependencies Plugin
|
||||
@end menu
|
||||
|
||||
@node libdep Plugin
|
||||
@section Static Library Dependencies Plugin
|
||||
@cindex static library dependencies
|
||||
Originally, static libraries were contained in an archive file consisting
|
||||
just of a collection of relocatable object files. Later they evolved to
|
||||
optionally include a symbol table, to assist in finding the needed objects
|
||||
within a library. There their evolution ended, and dynamic libraries
|
||||
rose to ascendance.
|
||||
|
||||
One useful feature of dynamic libraries was that, more than just collecting
|
||||
multiple objects into a single file, they also included a list of their
|
||||
dependencies, such that one could specify just the name of a single dynamic
|
||||
library at link time, and all of its dependencies would be implicitly
|
||||
referenced as well. But static libraries lacked this feature, so if a
|
||||
link invocation was switched from using dynamic libraries to static
|
||||
libraries, the link command would usually fail unless it was rewritten to
|
||||
explicitly list the dependencies of the static library.
|
||||
|
||||
The GNU @command{ar} utility now supports a @option{--record-libdeps} option
|
||||
to embed dependency lists into static libraries as well, and the @file{libdep}
|
||||
plugin may be used to read this dependency information at link time. The
|
||||
dependency information is stored as a single string, carrying @option{-l}
|
||||
and @option{-L} arguments as they would normally appear in a linker
|
||||
command line. As such, the information can be written with any text
|
||||
utility and stored into any archive, even if GNU @command{ar} is not
|
||||
being used to create the archive. The information is stored in an
|
||||
archive member named @samp{__.LIBDEP}.
|
||||
|
||||
For example, given a library @file{libssl.a} that depends on another
|
||||
library @file{libcrypto.a} which may be found in @file{/usr/local/lib},
|
||||
the @samp{__.LIBDEP} member of @file{libssl.a} would contain
|
||||
|
||||
@smallexample
|
||||
-L/usr/local/lib -lcrypto
|
||||
@end smallexample
|
||||
|
||||
@ifset GENERIC
|
||||
@node Machine Dependent
|
||||
@chapter Machine Dependent Features
|
||||
|
366
ld/libdep_plugin.c
Normal file
366
ld/libdep_plugin.c
Normal file
@ -0,0 +1,366 @@
|
||||
/* libdeps plugin for the GNU linker.
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils.
|
||||
|
||||
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. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "bfd.h"
|
||||
#if BFD_SUPPORTS_PLUGINS
|
||||
#include "plugin-api.h"
|
||||
|
||||
#include <ctype.h> /* For isspace. */
|
||||
|
||||
extern enum ld_plugin_status onload (struct ld_plugin_tv *tv);
|
||||
|
||||
/* Helper for calling plugin api message function. */
|
||||
#define TV_MESSAGE if (tv_message) (*tv_message)
|
||||
|
||||
/* Function pointers to cache hooks passed at onload time. */
|
||||
static ld_plugin_register_claim_file tv_register_claim_file = 0;
|
||||
static ld_plugin_register_all_symbols_read tv_register_all_symbols_read = 0;
|
||||
static ld_plugin_register_cleanup tv_register_cleanup = 0;
|
||||
static ld_plugin_message tv_message = 0;
|
||||
static ld_plugin_add_input_library tv_add_input_library = 0;
|
||||
static ld_plugin_set_extra_library_path tv_set_extra_library_path = 0;
|
||||
|
||||
/* Handle/record information received in a transfer vector entry. */
|
||||
static enum ld_plugin_status
|
||||
parse_tv_tag (struct ld_plugin_tv *tv)
|
||||
{
|
||||
#define SETVAR(x) x = tv->tv_u.x
|
||||
switch (tv->tv_tag)
|
||||
{
|
||||
case LDPT_REGISTER_CLAIM_FILE_HOOK:
|
||||
SETVAR(tv_register_claim_file);
|
||||
break;
|
||||
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
|
||||
SETVAR(tv_register_all_symbols_read);
|
||||
break;
|
||||
case LDPT_REGISTER_CLEANUP_HOOK:
|
||||
SETVAR(tv_register_cleanup);
|
||||
break;
|
||||
case LDPT_MESSAGE:
|
||||
SETVAR(tv_message);
|
||||
break;
|
||||
case LDPT_ADD_INPUT_LIBRARY:
|
||||
SETVAR(tv_add_input_library);
|
||||
break;
|
||||
case LDPT_SET_EXTRA_LIBRARY_PATH:
|
||||
SETVAR(tv_set_extra_library_path);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef SETVAR
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Defs for archive parsing. */
|
||||
#define ARMAGSIZE 8
|
||||
typedef struct arhdr
|
||||
{
|
||||
char ar_name[16];
|
||||
char ar_date[12];
|
||||
char ar_uid[6];
|
||||
char ar_gid[6];
|
||||
char ar_mode[8];
|
||||
char ar_size[10];
|
||||
char ar_fmag[2];
|
||||
} arhdr;
|
||||
|
||||
typedef struct linerec
|
||||
{
|
||||
struct linerec *next;
|
||||
char line[];
|
||||
} linerec;
|
||||
|
||||
#define LIBDEPS "__.LIBDEP/ "
|
||||
|
||||
static linerec *line_head, **line_tail = &line_head;
|
||||
|
||||
static enum ld_plugin_status
|
||||
get_libdeps (int fd)
|
||||
{
|
||||
arhdr ah;
|
||||
int len;
|
||||
unsigned long mlen;
|
||||
linerec *lr;
|
||||
enum ld_plugin_status rc = LDPS_NO_SYMS;
|
||||
|
||||
lseek (fd, ARMAGSIZE, SEEK_SET);
|
||||
for (;;)
|
||||
{
|
||||
len = read (fd, (void *) &ah, sizeof (ah));
|
||||
if (len != sizeof (ah))
|
||||
break;
|
||||
mlen = strtoul (ah.ar_size, NULL, 10);
|
||||
if (!mlen || strncmp (ah.ar_name, LIBDEPS, sizeof (LIBDEPS)-1))
|
||||
{
|
||||
lseek (fd, mlen, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
lr = malloc (sizeof (linerec) + mlen);
|
||||
if (!lr)
|
||||
return LDPS_ERR;
|
||||
lr->next = NULL;
|
||||
len = read (fd, lr->line, mlen);
|
||||
lr->line[mlen-1] = '\0';
|
||||
*line_tail = lr;
|
||||
line_tail = &lr->next;
|
||||
rc = LDPS_OK;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Turn a string into an argvec. */
|
||||
static char **
|
||||
str2vec (char *in)
|
||||
{
|
||||
char **res;
|
||||
char *s, *first, *end;
|
||||
char *sq, *dq;
|
||||
int i;
|
||||
|
||||
end = in + strlen (in);
|
||||
s = in;
|
||||
while (isspace (*s)) s++;
|
||||
first = s;
|
||||
|
||||
i = 1;
|
||||
while ((s = strchr (s, ' ')))
|
||||
{
|
||||
s++;
|
||||
i++;
|
||||
}
|
||||
res = (char **)malloc ((i+1) * sizeof (char *));
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
i = 0;
|
||||
sq = NULL;
|
||||
dq = NULL;
|
||||
res[0] = first;
|
||||
for (s = first; *s; s++)
|
||||
{
|
||||
if (*s == '\\')
|
||||
{
|
||||
memmove (s, s+1, end-s-1);
|
||||
end--;
|
||||
}
|
||||
if (isspace (*s))
|
||||
{
|
||||
if (sq || dq)
|
||||
continue;
|
||||
*s++ = '\0';
|
||||
while (isspace (*s)) s++;
|
||||
if (*s)
|
||||
res[++i] = s;
|
||||
}
|
||||
if (*s == '\'' && !dq)
|
||||
{
|
||||
if (sq)
|
||||
{
|
||||
memmove (sq, sq+1, s-sq-1);
|
||||
memmove (s-2, s+1, end-s-1);
|
||||
end -= 2;
|
||||
s--;
|
||||
sq = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sq = s;
|
||||
}
|
||||
}
|
||||
if (*s == '"' && !sq)
|
||||
{
|
||||
if (dq)
|
||||
{
|
||||
memmove (dq, dq+1, s-dq-1);
|
||||
memmove (s-2, s+1, end-s-1);
|
||||
end -= 2;
|
||||
s--;
|
||||
dq = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
dq = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
res[++i] = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *prevfile;
|
||||
|
||||
/* Standard plugin API registerable hook. */
|
||||
static enum ld_plugin_status
|
||||
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
|
||||
*claimed = 0;
|
||||
|
||||
/* If we've already seen this file, ignore it. */
|
||||
if (prevfile && !strcmp (file->name, prevfile))
|
||||
return LDPS_OK;
|
||||
|
||||
/* If it's not an archive member, ignore it. */
|
||||
if (!file->offset)
|
||||
return LDPS_OK;
|
||||
|
||||
if (prevfile)
|
||||
free (prevfile);
|
||||
|
||||
prevfile = strdup (file->name);
|
||||
if (!prevfile)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* This hook only gets called on actual object files.
|
||||
* We have to examine the archive ourselves, to find
|
||||
* our LIBDEPS member. */
|
||||
rv = get_libdeps (file->fd);
|
||||
if (rv == LDPS_ERR)
|
||||
return rv;
|
||||
|
||||
if (rv == LDPS_OK)
|
||||
{
|
||||
linerec *lr = (linerec *)line_tail;
|
||||
/* Inform the user/testsuite. */
|
||||
TV_MESSAGE (LDPL_INFO, "got deps for library %s: %s",
|
||||
file->name, lr->line);
|
||||
fflush (NULL);
|
||||
}
|
||||
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Standard plugin API registerable hook. */
|
||||
static enum ld_plugin_status
|
||||
onall_symbols_read (void)
|
||||
{
|
||||
linerec *lr;
|
||||
char **vec;
|
||||
enum ld_plugin_status rv = LDPS_OK;
|
||||
|
||||
while ((lr = line_head))
|
||||
{
|
||||
line_head = lr->next;
|
||||
vec = str2vec (lr->line);
|
||||
if (vec)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; vec[i]; i++)
|
||||
{
|
||||
if (vec[i][0] != '-')
|
||||
{
|
||||
TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s",
|
||||
vec[i]);
|
||||
fflush (NULL);
|
||||
continue;
|
||||
}
|
||||
if (vec[i][1] == 'l')
|
||||
rv = tv_add_input_library (vec[i]+2);
|
||||
else if (vec[i][1] == 'L')
|
||||
rv = tv_set_extra_library_path (vec[i]+2);
|
||||
else
|
||||
{
|
||||
TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s",
|
||||
vec[i]);
|
||||
fflush (NULL);
|
||||
}
|
||||
if (rv != LDPS_OK)
|
||||
break;
|
||||
}
|
||||
free (vec);
|
||||
}
|
||||
free (lr);
|
||||
}
|
||||
line_tail = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Standard plugin API registerable hook. */
|
||||
static enum ld_plugin_status
|
||||
oncleanup (void)
|
||||
{
|
||||
if (prevfile)
|
||||
{
|
||||
free (prevfile);
|
||||
prevfile = NULL;
|
||||
}
|
||||
if (line_head)
|
||||
{
|
||||
linerec *lr;
|
||||
while ((lr = line_head))
|
||||
{
|
||||
line_head = lr->next;
|
||||
free (lr);
|
||||
}
|
||||
line_tail = NULL;
|
||||
}
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Standard plugin API entry point. */
|
||||
enum ld_plugin_status
|
||||
onload (struct ld_plugin_tv *tv)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
|
||||
/* This plugin requires a valid tv array. */
|
||||
if (!tv)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* First entry should always be LDPT_MESSAGE, letting us get
|
||||
hold of it easily so we can send output straight away. */
|
||||
if (tv[0].tv_tag == LDPT_MESSAGE)
|
||||
tv_message = tv[0].tv_u.tv_message;
|
||||
|
||||
do
|
||||
if ((rv = parse_tv_tag (tv)) != LDPS_OK)
|
||||
return rv;
|
||||
while ((tv++)->tv_tag != LDPT_NULL);
|
||||
|
||||
/* Register hooks. */
|
||||
if (!tv_register_claim_file)
|
||||
{
|
||||
TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
|
||||
fflush (NULL);
|
||||
return LDPS_ERR;
|
||||
}
|
||||
(*tv_register_claim_file) (onclaim_file);
|
||||
if (!tv_register_all_symbols_read)
|
||||
{
|
||||
TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
|
||||
fflush (NULL);
|
||||
return LDPS_ERR;
|
||||
}
|
||||
(*tv_register_all_symbols_read) (onall_symbols_read);
|
||||
if (!tv_register_cleanup)
|
||||
{
|
||||
TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
|
||||
fflush (NULL);
|
||||
return LDPS_ERR;
|
||||
}
|
||||
(*tv_register_cleanup) (oncleanup);
|
||||
fflush (NULL);
|
||||
return LDPS_OK;
|
||||
}
|
||||
#endif /* BFD_SUPPORTS_PLUGINS */
|
3164
ld/po/ld.pot
3164
ld/po/ld.pot
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user