This is an archive of the discontinued LLVM Phabricator instance.

Simplify handling of builtin with inline redefinition
ClosedPublic

Authored by serge-sans-paille on Sep 17 2021, 8:24 AM.

Details

Summary

It is a common practice in glibc header to provide an inline redefinition of an
existing function. It is especially the case for fortified function.

Clang currently has an imperfect approach to the problem, using a combination of
trivially recursive function detection and noinline attribute.

Simplify the logic by suffixing these functions by .inline during codegen, so
that they are not recognized as builtin by llvm.

After that patch, clang passes all tests from:

https://github.com/serge-sans-paille/fortify-test-suite

Diff Detail

Event Timeline

serge-sans-paille requested review of this revision.Sep 17 2021, 8:24 AM
serge-sans-paille created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptSep 17 2021, 8:24 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
kees added a subscriber: kees.Sep 17 2021, 9:17 AM

Does this address https://bugs.llvm.org/show_bug.cgi?id=50322 ? (I assume this is a new version of https://reviews.llvm.org/D92657 ?)

@kees this does fix https://bugs.llvm.org/show_bug.cgi?id=50322 , but only if the memcpy "inline definition" is flagged as a __attribute__((always_inline))

Thanks for the patch!

Please fix the lint checks. git-clang-format HEAD~ should help, and IIRC there is a git hook when using arc diff (though maybe that requires one time setup? I seem to have an .arclint file in my llvm-projects checkout.

clang/lib/CodeGen/CodeGenFunction.cpp
1306
clang/test/CodeGen/memcpy-inline-builtin.c
2

Would -emit-codegen-only be more appropriate here than -disable-llvm-passes?

8

I'm not sure what this refers to in the comment?

Also, this whole bit about always_inline smells fishy to me. The semantics of gnu_inline is that no body is emitted. If you don't want a body don't use gnu_inline. Or was this set of qualifiers+fn attrs taken directly from the kernel, or glibc? FunctionDecl::isInlineBuiltinDeclaration only checks for builtin ID, has body, and whether inline was specified.

21

Can you use llvm/utils/update_cc_test_checks.py to autogen full checks for this file? I think it would be helpful to reviewers to be able to see everything that's generated here, even if we only really care that the call is to the .inline suffixed version.

clang/test/CodeGen/pr9614.c
44

Can you elaborate on these changes? Surprising.

Please amend the bug description to link to:

(You can do git commit --amend; arc diff --verbatim to have arc update the patch description in phab and keep it in sync with local changes.

clang/test/CodeGen/memcpy-inline-builtin.c
2

No; but I don't think we need -disable-llvm-passes since we haven't explicitly enabled additional optimization modes via -O flags? ie. I suspect if we drop -disable-llvm-passes then nothing changes?

Update formatting / extra comments

Update test to be more explicit about their intent / run them through update_cc_test_checks

serge-sans-paille marked 6 inline comments as done.Sep 21 2021, 1:54 AM
serge-sans-paille added inline comments.
clang/test/CodeGen/memcpy-inline-builtin.c
2

-disable-llvm-passes was tehre to disable the always inliner. I used another approach to keep merker from the inlined function and keep the test easy to review.

8

Comment updated. Basically these attributes are needed for a function to be considered by clang as redfinable, which is the case here. these attributes are extensively used in glibc headers for that purpose.

clang/test/CodeGen/pr9614.c
44

Before the patch, the redefined version of bas was ignored as the function is a trivially recursive redefinition. Thanks to current patch, the redefinition is correctly detected, renamed and inlined (the always inliner still runs here)

nickdesaulniers accepted this revision.Sep 21 2021, 1:53 PM

Looks reasonable. Can you give us some time to test this on the Linux kernel?

clang/test/CodeGen/memcpy-inline-builtin.c
4

are you able to leave off the -unknown-unknown from the triple? I assume those are the defaults; I know you can with llc but not sure about clang.

This revision is now accepted and ready to land.Sep 21 2021, 1:53 PM
serge-sans-paille marked 3 inline comments as done.Sep 22 2021, 12:35 AM

Looks reasonable. Can you give us some time to test this on the Linux kernel?

Sure, who can refuse some extra testing? Please ping the thread once you're done with the extra testing.

Set default as suggested by @nickdesaulniers

ychen added a subscriber: ychen.Sep 22 2021, 12:24 PM
kees added a comment.Sep 27 2021, 2:47 PM

I'm setting up to test this patch (thank you!) using my current kernel FORTIFY improvements. Right now I have a bunch of compile-time behavior selftests written:
https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/commit/?h=for-next/overflow&id=3c5221f3f4fd865a780f544b72c68f4209bd2e76

It should be possible to do an A/B test against those from the kernel's view of its FORTIFY functions. However, due to other bugs with __builtin_object_size(), the kernel still can't use name-matched inlines:
https://github.com/ClangBuiltLinux/linux/issues/1401
i.e. D109967 will fix half of what is needed, but the plan in the kernel right now is to work around the problem entirely by using macros instead.

I'll report back on the results of my testing, though, since it should give a good sense of how much coverage the kernel can gain back with this bug fixed.

kees added a comment.Sep 27 2021, 4:39 PM

Yeah, I can confirm that many cases are improved with this patch (others are more sensitive and depend on the __bos behavior I mentioned). With the 17 kernel FORTIFY self-tests, all 17 fail without this patch. With this patch, 9 start passing. Nice!

This revision was landed with ongoing or failed builds.Sep 28 2021, 4:24 AM
This revision was automatically updated to reflect the committed changes.

@kees great, thanks for confirming - I just landed the patch. Can you share a pointer to the missing pieces? I'm interested in implemented the missing parts.

for the record: I had to apply that extra patch: bd379915de38a9af3d65e19075a6a64ebbb8d6db which enforces the always_inline attribute

kda added a subscriber: kda.Sep 28 2021, 11:29 AM

Broke fast buildbot: https://lab.llvm.org/buildbot/#/builders/5/builds/12360

reverting...

A guide to reproducing sanitizer bots can be found here: https://github.com/google/sanitizers/wiki/SanitizerBotReproduceBuild

@kda : thanks for the builbot reference. The issue you're pointing at occurs *before* bd379915de38a9af3d65e19075a6a64ebbb8d6db which specifically fixes the issue spotted by the buildbot. As a consequnece I'm relanding the patch on top of that fix.

thakis added a subscriber: thakis.Sep 28 2021, 12:48 PM

This breaks tests on windows and macOS eg http://45.33.8.238/win/46075/step_7.txt

Please take a look and revert for now if it takes a while to fix.

And on Windows: http://45.33.8.238/win/46077/summary.html ! Thanks for pointing those.

rnk added a comment.Oct 5 2021, 8:44 PM

Thanks for doing this, this approach looks like it incorporated my feedback on the previous approach.

clang/lib/CodeGen/CodeGenModule.cpp
3177

Can this trivially recursive builtin detection stuff be removed now? That would be great.

Thanks for doing this, this approach looks like it incorporated my feedback on the previous approach.

Yeah, listened to the wise men... and struggled a lot doing so ;-)

clang/lib/CodeGen/CodeGenModule.cpp
3177

Let me give it a try!

Herald added a project: Restricted Project. · View Herald TranscriptNov 12 2023, 12:08 AM
clang/test/CodeGen/memcpy-inline-builtin.c