diff options
author | Ramon de C Valle <rcvalle@users.noreply.github.com> | 2023-02-01 16:42:28 +0000 |
---|---|---|
committer | Sami Tolvanen <samitolvanen@google.com> | 2023-02-01 17:48:03 +0000 |
commit | b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e (patch) | |
tree | 79cb5165645fb92108d943c888a3ed6274ca7cf3 /clang/lib | |
parent | 6e3d12951dd7d3305f0e33e0aa4038cbd82f245a (diff) | |
download | llvm-b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e.zip llvm-b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e.tar.gz llvm-b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e.tar.bz2 |
Add CFI integer types normalization
This commit adds a new option (i.e.,
`-fsanitize-cfi-icall-normalize-integers`) for normalizing integer types
as vendor extended types for cross-language LLVM CFI/KCFI support with
other languages that can't represent and encode C/C++ integer types.
Specifically, integer types are encoded as their defined representations
(e.g., 8-bit signed integer, 16-bit signed integer, 32-bit signed
integer, ...) for compatibility with languages that define
explicitly-sized integer types (e.g., i8, i16, i32, ..., in Rust).
``-fsanitize-cfi-icall-normalize-integers`` is compatible with
``-fsanitize-cfi-icall-generalize-pointers``.
This helps with providing cross-language CFI support with the Rust
compiler and is an alternative solution for the issue described and
alternatives proposed in the RFC
https://github.com/rust-lang/rfcs/pull/3296.
For more information about LLVM CFI/KCFI and cross-language LLVM
CFI/KCFI support for the Rust compiler, see the design document in the
tracking issue https://github.com/rust-lang/rust/issues/89653.
Reviewed By: pcc, samitolvanen
Differential Revision: https://reviews.llvm.org/D139395
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 104 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Driver/SanitizerArgs.cpp | 6 |
4 files changed, 122 insertions, 14 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 9540ad2..f932545 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -109,8 +109,10 @@ public: void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, raw_ostream &) override; void mangleCXXRTTI(QualType T, raw_ostream &) override; - void mangleCXXRTTIName(QualType T, raw_ostream &) override; - void mangleTypeName(QualType T, raw_ostream &) override; + void mangleCXXRTTIName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; + void mangleTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override; void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override; @@ -215,6 +217,10 @@ public: class CXXNameMangler { ItaniumMangleContextImpl &Context; raw_ostream &Out; + /// Normalize integer types for cross-language CFI support with other + /// languages that can't represent and encode C/C++ integer types. + bool NormalizeIntegers = false; + bool NullOut = false; /// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated. /// This mode is used when mangler creates another mangler recursively to @@ -413,6 +419,10 @@ public: : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), AbiTagsRoot(AbiTags) {} + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, + bool NormalizeIntegers_) + : Context(C), Out(Out_), NormalizeIntegers(NormalizeIntegers_), + NullOut(false), AbiTagsRoot(AbiTags) {} CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) : Context(Outer.Context), Out(Out_), Structor(Outer.Structor), StructorType(Outer.StructorType), SeqID(Outer.SeqID), @@ -2937,6 +2947,85 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) // ::= u <source-name> # vendor extended type std::string type_name; + // Normalize integer types as vendor extended types: + // u<length>i<type size> + // u<length>u<type size> + if (NormalizeIntegers && T->isInteger()) { + if (T->isSignedInteger()) { + switch (getASTContext().getTypeSize(T)) { + case 8: + // Pick a representative for each integer size in the substitution + // dictionary. (Its actual defined size is not relevant.) + if (mangleSubstitution(BuiltinType::SChar)) + break; + Out << "u2i8"; + addSubstitution(BuiltinType::SChar); + break; + case 16: + if (mangleSubstitution(BuiltinType::Short)) + break; + Out << "u3i16"; + addSubstitution(BuiltinType::Short); + break; + case 32: + if (mangleSubstitution(BuiltinType::Int)) + break; + Out << "u3i32"; + addSubstitution(BuiltinType::Int); + break; + case 64: + if (mangleSubstitution(BuiltinType::Long)) + break; + Out << "u3i64"; + addSubstitution(BuiltinType::Long); + break; + case 128: + if (mangleSubstitution(BuiltinType::Int128)) + break; + Out << "u4i128"; + addSubstitution(BuiltinType::Int128); + break; + default: + llvm_unreachable("Unknown integer size for normalization"); + } + } else { + switch (getASTContext().getTypeSize(T)) { + case 8: + if (mangleSubstitution(BuiltinType::UChar)) + break; + Out << "u2u8"; + addSubstitution(BuiltinType::UChar); + break; + case 16: + if (mangleSubstitution(BuiltinType::UShort)) + break; + Out << "u3u16"; + addSubstitution(BuiltinType::UShort); + break; + case 32: + if (mangleSubstitution(BuiltinType::UInt)) + break; + Out << "u3u32"; + addSubstitution(BuiltinType::UInt); + break; + case 64: + if (mangleSubstitution(BuiltinType::ULong)) + break; + Out << "u3u64"; + addSubstitution(BuiltinType::ULong); + break; + case 128: + if (mangleSubstitution(BuiltinType::UInt128)) + break; + Out << "u4u128"; + addSubstitution(BuiltinType::UInt128); + break; + default: + llvm_unreachable("Unknown integer size for normalization"); + } + } + return; + } switch (T->getKind()) { case BuiltinType::Void: Out << 'v'; @@ -6529,16 +6618,17 @@ void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) { Mangler.mangleType(Ty); } -void ItaniumMangleContextImpl::mangleCXXRTTIName(QualType Ty, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXRTTIName( + QualType Ty, raw_ostream &Out, bool NormalizeIntegers = false) { // <special-name> ::= TS <type> # typeinfo name (null terminated byte string) - CXXNameMangler Mangler(*this, Out); + CXXNameMangler Mangler(*this, Out, NormalizeIntegers); Mangler.getStream() << "_ZTS"; Mangler.mangleType(Ty); } -void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) { - mangleCXXRTTIName(Ty, Out); +void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out, + bool NormalizeIntegers = false) { + mangleCXXRTTIName(Ty, Out, NormalizeIntegers); } void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index dbc7ad1d..d5bc159 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -180,7 +180,8 @@ public: int32_t VBPtrOffset, uint32_t VBIndex, raw_ostream &Out) override; void mangleCXXRTTI(QualType T, raw_ostream &Out) override; - void mangleCXXRTTIName(QualType T, raw_ostream &Out) override; + void mangleCXXRTTIName(QualType T, raw_ostream &Out, + bool NormalizeIntegers) override; void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBTableOffset, uint32_t Flags, @@ -193,7 +194,8 @@ public: mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath, raw_ostream &Out) override; - void mangleTypeName(QualType T, raw_ostream &) override; + void mangleTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber, raw_ostream &) override; void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override; @@ -3593,8 +3595,8 @@ void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) { Mangler.getStream() << "@8"; } -void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, - raw_ostream &Out) { +void MicrosoftMangleContextImpl::mangleCXXRTTIName( + QualType T, raw_ostream &Out, bool NormalizeIntegers = false) { MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << '.'; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); @@ -3761,7 +3763,8 @@ void MicrosoftMangleContextImpl::mangleSEHFinallyBlock( Mangler.mangleName(EnclosingDecl); } -void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { +void MicrosoftMangleContextImpl::mangleTypeName( + QualType T, raw_ostream &Out, bool NormalizeIntegers = false) { // This is just a made up unique string for the purposes of tbaa. undname // does *not* know how to demangle it. MicrosoftCXXNameMangler Mangler(*this, Out); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 24b6337..5535fd5 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1727,7 +1727,11 @@ llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) { std::string OutName; llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName(T, Out); + getCXXABI().getMangleContext().mangleTypeName( + T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers); + + if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers) + Out << ".normalized"; return llvm::ConstantInt::get(Int32Ty, static_cast<uint32_t>(llvm::xxHash64(OutName))); @@ -6945,7 +6949,12 @@ CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, if (isExternallyVisible(T->getLinkage())) { std::string OutName; llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName(T, Out); + getCXXABI().getMangleContext().mangleTypeName( + T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers); + + if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers) + Out << ".normalized"; + Out << Suffix; InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 52bee6a..9056fbd 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -711,6 +711,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, CfiICallGeneralizePointers = Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers); + CfiICallNormalizeIntegers = + Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers); + if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fsanitize-cfi-cross-dso" @@ -1215,6 +1218,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, if (CfiICallGeneralizePointers) CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers"); + if (CfiICallNormalizeIntegers) + CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers"); + if (CfiCanonicalJumpTables) CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables"); |