bug#27866: Handle clang's internal libraries when finding compiler's internal libraries
Alex Ameen <[email protected]> Sun, 15 May 2022 17:46:51 -0500
| Newsgroups | gmane.comp.gnu.libtool.bugs |
|---|---|
| Message-ID | <[email protected]> |
Nice catch, I fat-fingered that one.
Could you share the workspace you tested in, or a snippet? I need to
make a test case.
There was one aspect I wanted some clarity on though from the patches
MSYS developed, which was "why is it that `m4/libtool.m4' used
`*NAME*.a' when `build-aux/ltmain.in' used `*/libNAME*.$libext', and why
they allowed `libgcc*' in `ltmain.in' but not `m4/libtool.m4'. I'm glad
I looked into it because when I investigated the original patches'
commit logs I realized that these were really just aimed at getting the
builds for a small number of MSYS2 packages to succeed ( in the author's
case VLC was the one they were focused on ); and that really this wasn't
really designed to be a general purpose patch to `libtool'. From what I
can tell MSYS2 is only using `libtool' for like 15 packages, so for
their use case hard coding a few whitelisted libraries is totally fine.
I'm actually really glad I dug into this more because In the field this
would have caused serious UB issues - the likes of which are actually
what led me to learn about linking/loading and eventually towards `libtool'.
I think my initial gut feeling on this one was right, and I'm probably
going to revert that change and iron this out in a project branch that
handles this alongside some related issues with flag-specs. The
underlying problem here, which has been discussed in a few other threads
is that `libtool' tries to outsmart the user and the compiler-collection
by reinterpreting flags library linkage flags like `-l:libfoo.a' or
`./libfoo.so', replacing them with `libfoo.la' and in rare cases even
swapping system libs which entirely different alternatives for a
particular platform.
In the MSYS patches their issue was that `libtool' doesn't respect the
flag-spec/implicit linkage for either GCC or Clang - so libraries which
are implicitly linked by the compiler-collection such as `libgcc_s.so'
or `libclang_rt.a' don't get added, usually what you get instead is a
manual invocation of `ld'. The result is that libtool removes certain
libs which are normally added by the compiler-collection's invocation of
`ld':
```
ld /path-to-libc/{crt1,crti}.o \
/path-to-cc/lib/crt<CC-init>.o \ # CC adds, but not `libtool'
<USER-FLAGS> \
-L/path-to-cc/lib -l<CC-libc-overrides> \ # CC adds, but not `libtool' ( almost always a static lib )
-L/path-to-libc/lib -lc \
-l<CC-runtime> \ # CC adds, but not `libtool' ( usually a shared lib )
/path-to-cc/lib/crt<CC-cleanup>.o \ # CC adds, but not `libtool' ( this one can get you in the most trouble )
/path-to-libc/crtn.o;
```
While the issues they're dealing with for Clang really focus on the RT
and libc override style libraries - the CC specific `.o' files can be a
real silent killer ( I know from experience before becoming maintainer
). The solution I'd like for this is going to take some time to develop,
and is going to require some real changes to the stated behavior of
`libtool' ( definitely not backwards compatible ) - but `libtool' needs
to either parse flag-specs and perfectly reproduce the underlying CC's
implicit libs, or it needs to stop directly invoking `ld'.
The big issue I see with the MSYS patches, and similar ad-hoc patches
that have been submitted to work around issues in flag-specs
`-fsanitize=' for example ) is that they often explicitly add linkage
for the relevant libraries, and fail to add linkage for the `.o' files.
The nasty thing about this is that it'll probably work fine 99% of the
time, but the 1% of the time that it misbehaves will be nearly
impossible to debug. You have initialization/cleanup routine in those
`.o' files that alter the initialization of executables and shared
libraries in discreet ways which effect a subset of of the RT and libc
override implementations provided by CCs - if those routines aren't
linked you often won't get a failure at link-editing time, rather you'll
get bizarre UB at runtime and ( in my experience ) by the time you
figure out what's wrong you'll have read two books, read the manuals for
CC and `ld' backwards and forwards a dozen times, GDB sessions will
haunt your dreams, and four months of your life have passed by lol.
In my case the mistake didn't involve `libtool', it was just a dev
dropping the ball while porting a Makefile from AIX to Linux. It's worth
noting, that as obnoxious as it is that `libtool' doesn't try to
replicate the CC linkage - in cases where people didn't try to work
around this by manually linking their CC specific libs, they would be
protected from the issue I encountered. I startled myself today
realizing that I checked in a patch that would have caused `libtool' to
make the exact issue that led me to learn about linking ( the irony
would have been palpable ). I am interested to learn if the patches MSYS
is using have caused the sort of UB I dealt with, I've got a list of at
least 3 issues I'd wager they run into with C++ "old ABI", `pthread',
and `dlopen'.
On 5/15/22 15:21, Martin Storsjö wrote:
> On Sun, 15 May 2022, Alex Ameen wrote:
>
>> Earlier this week I read through the thread, and created a patch
>> based on the ones posted. This was checked if you would like to
>> experiment with it.
>>
>> What I did notice was that this change has a wider effect than the
>> problem statement initially suggests. I'm not crazy about the way it
>> has a conditional behavior for two specific libraries since it is an
>> ad-hoc solution directed at two compiler-collections, as opposed to a
>> general purpose solution; but for the time being I see this as a
>> practical change.
>>
>> As a side effect this change should also resolve issues with certain
>> flag-specs such as `-fsanitize' which is nice; but the impact of
>> unknown side effects is something I expect will rear its head in the
>> near future. With that in mind, I think this is a necessary change,
>> but I want to express up front that "I'm confident this will break a
>> lot of existing builds, and I consider this to be a first draft".
>>
>> I would greatly appreciate y'all taking this for a spin on any
>> available projects you have to get a sense of how it will behave "in
>> the field". This change really effects "unspecified behavior" that
>> the test-suite isn't designed to audit, but nonetheless has a
>> practical effect on users.
>
> Thanks!
>
> I tested this now, and it doesn't work quite as is - it needs this
> modification:
>
> diff --git a/m4/libtool.m4 b/m4/libtool.m4
> index ab5af335..9c084816 100644
> --- a/m4/libtool.m4
> +++ b/m4/libtool.m4
> @@ -7554,7 +7554,7 @@ if AC_TRY_EVAL(ac_compile); then
> for p in `eval "$output_verbose_link_cmd"`; do
> case $prev$p in
>
> - -L* | -R* | -l* | */clang_rt*.a)
> + -L* | -R* | -l* | */libclang_rt*.a)
> # Some compilers place space between "-{L,R}" and the path.
> # Remove the space.
> if test x-L = "$p" ||
>
> (This was correct in one out of two instances in
> 1d2577357ee704da2d6d7c7da119ad82ba8ca172.)
>
> With that changed, it does seem to work as it should for me on a test
> project.
>
> // Martin
>
_______________________________________________
Bug-libtool mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-libtool