[RFC] Move static archive dependencies into ld
Michael Matz
matz@suse.de
Fri Feb 17 15:03:57 GMT 2023
More information about the Binutils mailing list
Fri Feb 17 15:03:57 GMT 2023
- Previous message (by thread): [PATCH v1 2/5] ldgram.y: CRC64
- Next message (by thread): [RFC] Move static archive dependencies into ld
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hello, this is an RFC for now. When met with some acceptance I'll cobble up a similar thing for gold as well and then make the libdep.so plugin only emit a warning message that its functionality is obsoleted and moved into ld itself. As Cary put it back in 2020 when the plugin was added: ( https://sourceware.org/pipermail/binutils/2020-December/114536.html ) "Did I miss any discussion about whether this feature should/could be implemented directly in the linkers, rather than via a plugin? I wouldn't be opposed to it." I pretty much think that yes, the functionality absolutely needs to be in the linker itself, not in a plugin, at least if we want to see some use of it in the real world. Amusingly I was triggered to look into this by libbfd itself: Recently it got a dependency to libsframe and when shipping only static archives to build against (which we as distro consciously do) that leads to build errors in various 3rdparty packages wanting to link against libbfd (no matter how bad an idea that is). Now, adding a '-plugin $magicdir/libdep.so' to the build flags of each such package is no better than just adding '-lsframe' in each case, so the plugin really doesn't help anything. Had the functionality already been in the linker itself we could have just added "--record-libdeps='-lsframe'" when building libbfd.a and be done with it. So, let's try to prepare for the future and at least now make ld interpret such dependencies on its own. So, what do people think? Ciao, Michael. --------------------------------------- needing a plugin to interpret static archive dependencies (as added by 'ar --record-libdeps') effectively means they are unused. Which is too bad, because they are actually useful. So implement them in ld itself. ld/ldmain.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/ld/ldmain.c b/ld/ldmain.c index 8c2fc9b8d8c..dc86ddf3ca8 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -876,6 +876,143 @@ add_keepsyms_file (const char *filename) link_info.strip = strip_some; fclose (file); } + +/* 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 **)xmalloc ((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; +} + +#define LIBDEPS "__.LIBDEP" + +/* Check if ARCHIVE has a '__.LIBDEP' member and if so interpret its + content as linker command line arguments (only -L and -l are accepted). + The special member is expected amongst the first few. */ + +static void +check_archive_deps (bfd *archive) +{ + int count = 3; + bfd *member; + + if (bfd_is_thin_archive (archive)) + return; + + /* We look for the magic member only in the first few archive + members. */ + member = bfd_openr_next_archived_file (archive, NULL); + while (member != NULL && count--) + { + ufile_ptr memsize = bfd_get_file_size (member); + if (memsize + && !strcmp (bfd_get_filename (member), LIBDEPS)) + { + char *buf = (char *) xmalloc (memsize); + if (buf + && bfd_seek (member, (file_ptr) 0, SEEK_SET) == 0 + && bfd_bread (buf, memsize, member) == memsize) + { + char **vec; + vec = str2vec (buf); + if (vec) + { + int i; + for (i = 0; vec[i]; i++) + { + if (vec[i][0] != '-') + einfo ("ignoring libdep argument %s", vec[i]); + else if (vec[i][1] == 'l') + lang_add_input_file (xstrdup (vec[i]+2), + lang_input_file_is_l_enum, + NULL); + else if (vec[i][1] == 'L') + ldfile_add_library_path (vec[i]+2, false); + else + einfo ("ignoring libdep argument %s", vec[i]); + } + free (vec); + } + } + free (buf); + break; + } + member = bfd_openr_next_archived_file (archive, member); + } +} /* Callbacks from the BFD linker routines. */ @@ -941,7 +1078,12 @@ add_archive_element (struct bfd_link_info *info, from the archive. See ldlang.c:find_rescan_insertion. */ parent = bfd_usrdata (abfd->my_archive); if (parent != NULL && !parent->flags.reload) - parent->next = input; + { + if (!parent->next) + /* The first time we see an archive use we check for dependencies. */ + check_archive_deps (abfd->my_archive); + parent->next = input; + } ldlang_add_file (input); -- 2.39.1
- Previous message (by thread): [PATCH v1 2/5] ldgram.y: CRC64
- Next message (by thread): [RFC] Move static archive dependencies into ld
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list