This is an archive of the discontinued LLVM Phabricator instance.

[libunwind] Install the headers by default
ClosedPublic

Authored by ldionne on Oct 11 2022, 6:22 AM.

Details

Reviewers
ldionne
Group Reviewers
Restricted Project
Commits
rGf8409af354c1: [libunwind] Install the headers by default
Summary

Just like we install libc++ and libc++abi headers by default when we
install the library, it makes sense to install the libunwind headers
by default when we build libunwind. In the current state of things,
there is an increased risk that folks are using older (previously
installed) libunwind headers along with a recent libunwind dylib,
which is not ideal.

Diff Detail

Event Timeline

ldionne created this revision.Oct 11 2022, 6:22 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptOct 11 2022, 6:22 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
ldionne requested review of this revision.Oct 11 2022, 6:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 11 2022, 6:22 AM
ldionne accepted this revision.Oct 11 2022, 12:18 PM

The runtimes CI passed.

This revision is now accepted and ready to land.Oct 11 2022, 12:18 PM
This revision was landed with ongoing or failed builds.Oct 11 2022, 12:18 PM
This revision was automatically updated to reflect the committed changes.

clang's unwind.h also gets installed and is found first when included from a source file (and it includes_next the libunwind's version, but only for apple platforms).
Not sure I understand the logic, may it be somehow related to the fact that clang driver supports different unwind libraries?
Either way, installing libunwind's header by default does not update clang's version, so the issue persists.

clang's unwind.h also gets installed and is found first when included from a source file (and it includes_next the libunwind's version, but only for apple platforms).
Not sure I understand the logic, may it be somehow related to the fact that clang driver supports different unwind libraries?
Either way, installing libunwind's header by default does not update clang's version, so the issue persists.

I think https://github.com/llvm/llvm-project/commit/032d422 is relevant here. It seems to be intentional that Clang doesn't use unwind.h outside of Apple.

clang's unwind.h also gets installed and is found first when included from a source file (and it includes_next the libunwind's version, but only for apple platforms).
Not sure I understand the logic, may it be somehow related to the fact that clang driver supports different unwind libraries?
Either way, installing libunwind's header by default does not update clang's version, so the issue persists.

I think https://github.com/llvm/llvm-project/commit/032d422 is relevant here. It seems to be intentional that Clang doesn't use unwind.h outside of Apple.

If I read it correctly, it says that clang's unwind.h supersedes the system unwind.h,
and that this has been proven for all targets except Apple (and that's why it includes_next
the system header on Apple platforms).
With the current state of things, the installed unwind.h (from libunwind) can only affect Apple targets.
Other targets will use clang's unwind.h, which is not synced with libunwind's unwind.h, potentially causing bugs.

The commit also says that there are no incompatibilities. May be it was true at that time,
but the headers currently diverge. Even _Unwind_Exception definitions are different:

clang's:

typedef uintptr_t _Unwind_Word __attribute__((__mode__(__unwind_word__)));
...
struct _Unwind_Exception {
  _Unwind_Exception_Class exception_class;
  _Unwind_Exception_Cleanup_Fn exception_cleanup;
#if !defined (__USING_SJLJ_EXCEPTIONS__) && defined (__SEH__)
  _Unwind_Word private_[6];
#else
  _Unwind_Word private_1;
  _Unwind_Word private_2;
#endif
  /* The Itanium ABI requires that _Unwind_Exception objects are "double-word
   * aligned".  GCC has interpreted this to mean "use the maximum useful
   * alignment for the target"; so do we. */
} __attribute__((__aligned__));

libunwind's:

struct _Unwind_Exception {
  _Unwind_Exception_Class exception_class;
  void (*exception_cleanup)(_Unwind_Reason_Code reason,
                            _Unwind_Exception *exc);
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
  uintptr_t private_[6];
#else
  uintptr_t private_1; // non-zero means forced unwind
  uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#endif
#if __SIZEOF_POINTER__ == 4
  // The implementation of _Unwind_Exception uses an attribute mode on the
  // above fields which has the side effect of causing this whole struct to
  // round up to 32 bytes in size (48 with SEH). To be more explicit, we add
  // pad fields added for binary compatibility.
  uint32_t reserved[3];
#endif
  // The Itanium ABI requires that _Unwind_Exception objects are "double-word
  // aligned".  GCC has interpreted this to mean "use the maximum useful
  // alignment for the target"; so do we.
} __attribute__((__aligned__));

IMO clang's unwind.h should be as good as deleted. However, @aaron.ballman suggested
on discord that it might be there for use with -ffreestanding. Can that make sense?

The commit also says that there are no incompatibilities. May be it was true at that time,
but the headers currently diverge. Even _Unwind_Exception definitions are different:

Hmm, yeah, I guess that was unavoidable and it's pretty bad.

IMO clang's unwind.h should be as good as deleted.

FWIW that would also be my immediate reaction -- I'm not sure why it would make much sense for Clang to provide the header associated to another library.

However, @aaron.ballman suggested on discord that it might be there for use with -ffreestanding. Can that make sense?

I am not sure why a freestanding implementation would require <unwind.h>, but if it does, then my reflex would be to say that it should get it from its unwinder library (aka libunwind or other). In my mind, freestanding is not the same as "no runtime libraries". If you are in freestanding and you still want exceptions, you'll need some unwind library to support that no matter what.

So naively, I'd be fine with removing the Clang version, but I wouldn't be surprised if there's a bunch of reasons why this can't work. If you want, you could create a review and we can have a discussion and ping the right people on it.

I am not sure why a freestanding implementation would require <unwind.h>, but if it does, then my reflex would be to say that it should get it from its unwinder library (aka libunwind or other). In my mind, freestanding is not the same as "no runtime libraries". If you are in freestanding and you still want exceptions, you'll need some unwind library to support that no matter what.

I agree.

So naively, I'd be fine with removing the Clang version, but I wouldn't be surprised if there's a bunch of reasons why this can't work. If you want, you could create a review and we can have a discussion and ping the right people on it.

I'll try not to forget to create a review when I have more time.

The commit also says that there are no incompatibilities. May be it was true at that time,
but the headers currently diverge. Even _Unwind_Exception definitions are different:

Hmm, yeah, I guess that was unavoidable and it's pretty bad.

IMO clang's unwind.h should be as good as deleted.

FWIW that would also be my immediate reaction -- I'm not sure why it would make much sense for Clang to provide the header associated to another library.

However, @aaron.ballman suggested on discord that it might be there for use with -ffreestanding. Can that make sense?

I am not sure why a freestanding implementation would require <unwind.h>, but if it does, then my reflex would be to say that it should get it from its unwinder library (aka libunwind or other). In my mind, freestanding is not the same as "no runtime libraries". If you are in freestanding and you still want exceptions, you'll need some unwind library to support that no matter what.

So naively, I'd be fine with removing the Clang version, but I wouldn't be surprised if there's a bunch of reasons why this can't work. If you want, you could create a review and we can have a discussion and ping the right people on it.

Ah, sorry for introducing confusion. IIRC, I was speaking more generally about why we provide headers and then include_next to the system from them (we do that sometimes so we can provide macros in freestanding but then defer to the system for hosted). I don't know if we have any freestanding needs for <unwind.h>. When we discussed freestanding recently, I think we were heading towards consensus that we expect users to provide a freestanding-compatible libc implementation like we already expect them to do for hosted; the compiler headers should only be producing simple macros or calls to intrinsics. So that matches what @ldionne says about freestanding not meaning "no runtime library".