Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[llvm][fatlto] Drop any CFI related instrumentation after emitting bitcode #112788

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Oct 17, 2024

We want to support CFI instrumentation for the bitcode section, without
miscompiling the object code portion of a FatLTO object. We can reuse
the existing mechanisms in the LowerTypeTestsPass to do that, by just
adding the pass to the FatLTO pipeline after the EmbedBitcodePass with
the correct options set.

Fixes #112053

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Oct 17, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 17, 2024

@llvm/pr-subscribers-clang

Author: Paul Kirth (ilovepi)

Changes

We want to support CFI instrumentation for the bitcode section, without
miscompiling the object code portion of a FatLTO object. We can reuse
the existing mechanisms in the LowerTypeTestsPass to do that, by just
adding the pass to the FatLTO pipeline after the EmbedBitcodePass with
the correct options set.

Fixes #112053


Full diff: https://github.com/llvm/llvm-project/pull/112788.diff

2 Files Affected:

  • (added) clang/test/CodeGen/fat-lto-objects-cfi.cpp (+46)
  • (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+4)
diff --git a/clang/test/CodeGen/fat-lto-objects-cfi.cpp b/clang/test/CodeGen/fat-lto-objects-cfi.cpp
new file mode 100644
index 00000000000000..022e74fd9b6f22
--- /dev/null
+++ b/clang/test/CodeGen/fat-lto-objects-cfi.cpp
@@ -0,0 +1,46 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clangxx --target=x86_64-unknown-fuchsia -O2 -flto -ffat-lto-objects \
+// RUN:          -fsanitize=cfi -fvisibility=hidden -S -emit-llvm -o - %s \
+// RUN:   | FileCheck %s
+
+// CHECK: llvm.embedded.object
+// CHECK-SAME: section ".llvm.lto"
+
+// CHECK-LABEL: define hidden void @foo
+//      CHECK: entry:
+// CHECK-NEXT:   %cmp14.not = icmp eq i64 %len, 0
+// CHECK-NEXT:   br i1 %cmp14.not, label %for.end7, label %for.cond1.preheader.preheader
+//      CHECK: for.cond1.preheader.preheader:                    ; preds = %entry
+// CHECK-NEXT:   %arrayidx.1 = getelementptr inbounds nuw i8, ptr %ptr, i64 4
+// CHECK-NEXT:   br label %for.cond1.preheader
+
+// CHECK-NOT: @llvm.type.test
+
+// The code below is a reduced case from https://github.com/llvm/llvm-project/issues/112053
+#define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs)))
+typedef void func(void* arg, const char* fmt, ...) __PRINTFLIKE(2, 3);
+typedef __SIZE_TYPE__ size_t;
+typedef unsigned long uintptr_t;
+
+extern "C"
+void foo(const void* ptr, size_t len, long disp_addr,
+                     func* printf_func, void* printf_arg) {
+  uintptr_t address = (uintptr_t)ptr;
+  size_t count;
+
+  for (count = 0; count < len; count += 16) {
+    union {
+      unsigned int buf[4];
+      unsigned char cbuf[16];
+    } u;
+    size_t s = 10;
+    size_t i;
+
+    for (i = 0; i < s / 4; i++) {
+      u.buf[i] = ((const unsigned int*)address)[i];
+      printf_func(printf_arg, "%08x ", static_cast<unsigned int>(u.buf[i]));
+    }
+  }
+}
+
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 17710eb94b6ded..81ea6ac7dcdf18 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1629,6 +1629,10 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
     MPM.addPass(buildLTOPreLinkDefaultPipeline(Level));
   MPM.addPass(EmbedBitcodePass(ThinLTO, EmitSummary));
 
+  // If we're doing FatLTO w/ CFI enabled, we don't want the type tests in the
+  // object file.
+  MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true, true));
+
   // Use the ThinLTO post-link pipeline with sample profiling
   if (ThinLTO && PGOOpt && PGOOpt->Action == PGOOptions::SampleUse)
     MPM.addPass(buildThinLTODefaultPipeline(Level, /*ImportSummary=*/nullptr));

@@ -1629,6 +1629,10 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
MPM.addPass(buildLTOPreLinkDefaultPipeline(Level));
MPM.addPass(EmbedBitcodePass(ThinLTO, EmitSummary));

// If we're doing FatLTO w/ CFI enabled, we don't want the type tests in the
// object file.
MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true, true));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this build? The ctor only takes three arguments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, you have a dependent change that adds the argument.

68a064b

I'm not really a big fan of adding another bool argument like this because it makes the callers less clear, can you do something else like make the existing argument into an enum?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR depends on #112787 which adds the fourth argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I'm not super happy w/ the boolean either. The only reason its required is to avoid asserting for the new use case, but that also implies that assertion doesn't always hold, so I'm not sure if its really a good idea to keep it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And apologies for not adding you on both reviews. I had thought I added you and Nikita to #112787, but it looks like I hadn't.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion is to check that the code is only removing type test assumes (possibly involving a phi). So I wouldn't call the functionality that you're adding "always drop type tests". What you're adding is more like "drop type tests" and what's there already is "drop type test assumes". So maybe you can name the enumerators based on that.

Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
Created using spr 1.3.4
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
@ilovepi
Copy link
Contributor Author

ilovepi commented Oct 30, 2024

Hmm, windows seems to be breaking in the premerge tests. I'll try to spell the test w/ a cc1 command line instead, and hopefully that will avoid trying to find the sanitizer ignorelist file.

Created using spr 1.3.4
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
@ilovepi ilovepi changed the base branch from users/ilovepi/spr/main.llvmfatlto-drop-any-cfi-related-instrumentation-after-emitting-bitcode to main October 30, 2024 23:57
@ilovepi
Copy link
Contributor Author

ilovepi commented Oct 31, 2024

The LLDB test failure in premerge is unrelated to FatLTO, so I'm going to go ahead and land this.

@ilovepi ilovepi merged commit 913cd11 into main Oct 31, 2024
8 of 11 checks passed
@ilovepi ilovepi deleted the users/ilovepi/spr/llvmfatlto-drop-any-cfi-related-instrumentation-after-emitting-bitcode branch October 31, 2024 19:40
smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
…tcode (llvm#112788)

We want to support CFI instrumentation for the bitcode section, without
miscompiling the object code portion of a FatLTO object. We can reuse
the existing mechanisms in the LowerTypeTestsPass to do that, by just
adding the pass to the FatLTO pipeline after the EmbedBitcodePass with
the correct options set.

Fixes llvm#112053
smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
…tcode (llvm#112788)

We want to support CFI instrumentation for the bitcode section, without
miscompiling the object code portion of a FatLTO object. We can reuse
the existing mechanisms in the LowerTypeTestsPass to do that, by just
adding the pass to the FatLTO pipeline after the EmbedBitcodePass with
the correct options set.

Fixes llvm#112053
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…tcode (llvm#112788)

We want to support CFI instrumentation for the bitcode section, without
miscompiling the object code portion of a FatLTO object. We can reuse
the existing mechanisms in the LowerTypeTestsPass to do that, by just
adding the pass to the FatLTO pipeline after the EmbedBitcodePass with
the correct options set.

Fixes llvm#112053
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category
Projects
None yet
4 participants