This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Remove HIDE_FROM_ABI from virtual functions
ClosedPublic

Authored by ldionne on Dec 20 2022, 8:43 PM.

Details

Reviewers
Mordante
Group Reviewers
Restricted Project
Commits
rG5efc81166d86: [libc++] Remove HIDE_FROM_ABI from virtual functions
Summary

_LIBCPP_HIDE_FROM_ABI (which is what _LIBCPP_INLINE_VISIBILITY is) uses
ABI tags to avoid ODR violations when linking together object files
compiled against different versions of libc++. However, pointer
authentication uses the mangled name of the function to sign the
function pointer in the vtable, which means that the ABI tag effectively
changes how the pointers are signed.

This leads to PAC failures when passing an object that holds one of these
pointers in its vtable across an ABI boundary: one side will sign the
pointer using one function mangling (with one ABI tag), and the other
side will authenticate the pointer expecting it to have a different
mangled name, which won't work.

To make sure this does not regress in the future, this patch also adds
a clang-query test to detect incorrect applications of _LIBCPP_HIDE_FROM_ABI.

Diff Detail

Event Timeline

ldionne created this revision.Dec 20 2022, 8:43 PM
Herald added a project: Restricted Project. · View Herald TranscriptDec 20 2022, 8:43 PM
ldionne requested review of this revision.Dec 20 2022, 8:43 PM
Herald added a project: Restricted Project. · View Herald TranscriptDec 20 2022, 8:43 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript

@philnik Do you think writing a clang-tidy check for this would be hard?

@philnik Do you think writing a clang-tidy check for this would be hard?

match
cxxMethodDecl(isVirtual(),
              hasAttr("attr::AbiTag"),
              unless(isExpansionInSystemHeader())
             )

should do the trick (using clang-query for now). Looking at the CI failures I'm not sure just removing the _LIBCPP_HIDE_FROM_ABI is the right call here. Maybe we need something like _LIBCPP_HIDE_VIRTUAL_FUNCTION_FROM_ABI that gives the functions internal linkage. That didn't suffer from this problem, right? (And also maybe mention the problem in the _LIBCPP_HIDE_FROM_ABI explanation in <__config>.)

ldionne updated this revision to Diff 484580.Dec 21 2022, 7:28 AM
ldionne edited the summary of this revision. (Show Details)

Add test, comments and _LIBCPP_HIDDEN.

match
cxxMethodDecl(isVirtual(),
              hasAttr("attr::AbiTag"),
              unless(isExpansionInSystemHeader())
             )

should do the trick (using clang-query for now). Looking at the CI failures I'm not sure just removing the _LIBCPP_HIDE_FROM_ABI is the right call here. Maybe we need something like _LIBCPP_HIDE_VIRTUAL_FUNCTION_FROM_ABI that gives the functions internal linkage. That didn't suffer from this problem, right? (And also maybe mention the problem in the _LIBCPP_HIDE_FROM_ABI explanation in <__config>.)

Thanks a lot, this is magic. It actually found many more instances of the same problem! This tool is really growing on me.

Mordante accepted this revision.Dec 21 2022, 8:45 AM
Mordante added a subscriber: Mordante.

I also feel clang-query is really useful. This change really convinces me to spend some time with it too.
LGTM!

libcxx/test/libcxx/clang_query/abi_tag_on_virtual.query
24

Nice comment!

This revision is now accepted and ready to land.Dec 21 2022, 8:45 AM
ldionne updated this revision to Diff 484668.Dec 21 2022, 1:48 PM

Add _LIBCPP_HIDE_FROM_ABI_VIRTUAL

This revision was automatically updated to reflect the committed changes.