Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions clang/docs/ControlFlowIntegrity.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ of undefined behavior that can potentially allow attackers to subvert the
program's control flow. These schemes have been optimized for performance,
allowing developers to enable them in release builds.

To enable Clang's available CFI schemes, use the flag ``-fsanitize=cfi``.
You can also enable a subset of available :ref:`schemes <cfi-schemes>`.
As currently implemented, all schemes rely on link-time optimization (LTO);
so it is required to specify ``-flto``, and the linker used must support LTO,
for example via the `gold plugin`_.
To enable Clang's available CFI schemes, use the flag
``-fsanitize=cfi``. You can also enable a subset of available
:ref:`schemes <cfi-schemes>`. As currently implemented, all schemes
except for ``kcfi`` rely on link-time optimization (LTO); so it is
Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to separate commit: 984ec70

required to specify ``-flto`` or ``-flto=thin``, and the linker used
must support LTO, for example via the `gold plugin`_.

To allow the checks to be implemented efficiently, the program must
be structured such that certain object files are compiled with CFI
Expand All @@ -41,6 +42,11 @@ default visibility setting is ``-fvisibility=default``, which would disable
CFI checks for classes without visibility attributes. Most users will want
to specify ``-fvisibility=hidden``, which enables CFI checks for such classes.

When using ``-fsanitize=cfi*`` with ``-flto=thin``, it is recommended
to reduce link times by passing `-funique-source-file-names
<UsersManual.html#cmdoption-f-no-unique-source-file-names>`_, provided
that your program is compatible with it.

Experimental support for :ref:`cross-DSO control flow integrity
<cfi-cross-dso>` exists that does not require classes to have hidden LTO
visibility. This cross-DSO support has unstable ABI at this time.
Expand Down
7 changes: 7 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2297,6 +2297,13 @@ are listed below.
pure ThinLTO, as all split regular LTO modules are merged and LTO linked
with regular LTO.

.. option:: -f[no-]unique-source-file-names

When enabled, allows the compiler to assume that each object file
passed to the linker has been compiled using a unique source file
name. This is useful for reducing link times when doing ThinLTO
in combination with whole-program devirtualization or CFI.

.. option:: -fforce-emit-vtables

In order to improve devirtualization, forces emitting of vtables even in
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types
///< CFI icall function signatures
CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
///< instead of creating a local jump table.
CODEGENOPT(UniqueSourceFileNames, 1, 0) ///< Allow the compiler to assume that TUs
///< have unique source file names at link time
CODEGENOPT(SanitizeKcfiArity, 1, 0) ///< Embed arity in KCFI patchable function prefix
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4140,6 +4140,13 @@ def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
HelpText<"Do not process trigraph sequences">,
Visibility<[ClangOption, CC1Option]>;
defm unique_source_file_names: BoolOption<"f", "unique-source-file-names",
CodeGenOpts<"UniqueSourceFileNames">, DefaultFalse,
PosFlag<SetTrue, [], [CC1Option], "Allow">,
NegFlag<SetFalse, [], [], "Do not allow">,
BothFlags<[], [ClangOption], " the compiler to assume that each translation unit has a unique "
"source file name at link time">>,
Group<f_clang_Group>;
def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,10 @@ void CodeGenModule::Release() {
1);
}

if (CodeGenOpts.UniqueSourceFileNames) {
getModule().addModuleFlag(llvm::Module::Max, "Unique Source File Names", 1);
}

if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
// KCFI assumes patchable-function-prefix is the same for all indirectly
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7744,6 +7744,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.addOptInFlag(CmdArgs, options::OPT_fexperimental_late_parse_attributes,
options::OPT_fno_experimental_late_parse_attributes);

Args.addOptInFlag(CmdArgs, options::OPT_funique_source_file_names,
options::OPT_fno_unique_source_file_names);

// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
if (!StatsFile.empty()) {
Expand Down
2 changes: 2 additions & 0 deletions clang/test/CodeGen/unique-source-file-names.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// RUN: %clang_cc1 -funique-source-file-names -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
// CHECK: !{i32 7, !"Unique Source File Names", i32 1}
5 changes: 5 additions & 0 deletions clang/test/Driver/unique-source-file-names.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// RUN: %clang -funique-source-file-names -### %s 2> %t
// RUN: FileCheck < %t %s

// CHECK: "-cc1"
// CHECK: "-funique-source-file-names"
22 changes: 11 additions & 11 deletions llvm/lib/Transforms/Utils/ModuleUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,17 +355,17 @@ std::string llvm::getUniqueModuleId(Module *M) {
Md5.update(ArrayRef<uint8_t>{0});
};

for (auto &F : *M)
AddGlobal(F);
for (auto &GV : M->globals())
AddGlobal(GV);
for (auto &GA : M->aliases())
AddGlobal(GA);
for (auto &IF : M->ifuncs())
AddGlobal(IF);

if (!ExportsSymbols)
return "";
auto *UniqueSourceFileNames = mdconst::extract_or_null<ConstantInt>(
M->getModuleFlag("Unique Source File Names"));
if (UniqueSourceFileNames && UniqueSourceFileNames->getZExtValue()) {
Md5.update(M->getSourceFileName());
} else {
for (auto &GV : M->global_values())
AddGlobal(GV);
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider inlining the lambda since there is now only one use

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


if (!ExportsSymbols)
return "";
}

MD5::MD5Result R;
Md5.final(R);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
; RUN: opt -thinlto-bc -thin-link-bitcode-file=%t2 -thinlto-split-lto-unit -o %t %s
; RUN: llvm-modextract -b -n 1 -o %t1 %t
; RUN: llvm-dis -o - %t1 | FileCheck %s

source_filename = "unique-source-file-names.c"

@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @f, ptr null }]

; CHECK: @g.45934e8a5251fb7adbecfff71a4e70ed =
@g = internal global i8 42, !type !0

declare void @sink(ptr)

define internal void @f() {
call void @sink(ptr @g)
ret void
}

!0 = !{i32 0, !"typeid"}

!llvm.module.flags = !{!1}
!1 = !{i32 1, !"Unique Source File Names", i32 1}
Loading