From ab960177557f35cafc2adf8a8b0a6b7a3c192f61 Mon Sep 17 00:00:00 2001 From: xujiali Date: Thu, 9 Jan 2025 11:36:12 +0800 Subject: [PATCH] [PAC] Add new attributes for DFI Introduce new attributes, pac_excl and pac_seql, for sensitive fields within a struct, and modify the struct layout to accommodate these PAC fields. Issue: https://gitee.com/openharmony/third_party_llvm-project/issues/IBGBLP Signed-off-by: xujiali --- clang/include/clang/Basic/Attr.td | 14 +++ clang/include/clang/Basic/AttrDocs.td | 16 ++++ clang/lib/Pac/PacDfi.cpp | 93 ++++++++++++++++++- ...a-attribute-supported-attributes-list.test | 2 + 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index f79e9ef3fa10..a85bccc5b457 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1759,6 +1759,20 @@ def PacPtrTag : InheritableAttr { let Documentation = [PacPtrTagDocs]; let SimpleHandler = 1; } + +def PacExclTag : InheritableAttr { + let Spellings = [GCC<"pac_excl">]; + let Subjects = SubjectList<[Field], ErrorDiag>; + let Documentation = [PacExclTagDocs]; + let SimpleHandler = 1; +} + +def PacSeqlTag : InheritableAttr { + let Spellings = [GCC<"pac_seql">]; + let Subjects = SubjectList<[Field], ErrorDiag>; + let Documentation = [PacSeqlTagDocs]; + let SimpleHandler = 1; +} // OHOS_LOCAL end def ReturnsTwice : InheritableAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 74e76f42e04c..647950214b81 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1369,6 +1369,22 @@ def PacPtrTagDocs : Documentation { The ``pac_protected_ptr`` attribute asks the compiler to protect the struct pointer type field with PA }]; } + +def PacExclTagDocs : Documentation { + let Category = DocCatField; + let Content = [{ +The ``pac_excl`` attribute asks the compiler to protect the struct field with PA +by exclusive load/store instructions + }]; +} + +def PacSeqlTagDocs : Documentation { + let Category = DocCatField; + let Content = [{ +The ``pac_seql`` attribute asks the compiler to protect the struct field with PA +by seqlock method + }]; +} // OHOS_LOCAL end def ObjCRequiresSuperDocs : Documentation { diff --git a/clang/lib/Pac/PacDfi.cpp b/clang/lib/Pac/PacDfi.cpp index 2a2e502f4e25..d73e16edf888 100644 --- a/clang/lib/Pac/PacDfi.cpp +++ b/clang/lib/Pac/PacDfi.cpp @@ -27,15 +27,80 @@ using namespace clang; std::map RecordDecl2StructName; std::map> PacPtrNameInfos; std::map> PacFieldNameInfos; +std::map> PacFieldExclNameInfos; +std::map> PacFieldSeqlNameInfos; std::map RecordDecl2StructType; + +bool IsBaseTypeNotArrStruct(RecordDecl *TagDecl, FieldDecl *Field, DiagnosticsEngine &Diags) +{ + if (Field->getType()->isConstantArrayType()) { + Diags.Report(Field->getLocation(), diag::warn_unsupported_pac_dfi_type) << "array" + << Field->getAttr()->getSpelling(); + return false; + } + return true; +} + +void AppendFieldDecl(RecordDecl *TagDecl, FieldDecl *TargetField, FieldDecl *NewField) +{ + const RecordDecl::field_iterator TargetFieldIt = std::find(TagDecl->field_begin(), TagDecl->field_end(), TargetField); + if (TargetFieldIt != TagDecl->field_end()) { + llvm::SmallVector Fields; + + for (FieldDecl *TmpFD :TagDecl->fields()) { + Fields.push_back(TmpFD); + } + for (FieldDecl *TmpFD : Fields) { + TagDecl->removeDecl(TmpFD); + } + for (FieldDecl *TmpFD : Fields) { + TagDecl->addDecl(TmpFD); + if (TmpFD == TargetField) { + TagDecl->addDecl(NewField); + } + } + } +} + +void AppendPacFieldDecl(RecordDecl *TagDecl, FieldDecl *Field, ASTContext &Ctx) +{ + auto IntType = Ctx.getBitIntType(true, 64); + FieldDecl *PacFD = FieldDecl::Create(Ctx, TagDecl, SourceLocation(), SourceLocation(), + nullptr, IntType, nullptr, nullptr, true, ICIS_NoInit); + llvm::APInt PacAlign(32, 16); + Field->addAttr(AlignedAttr::CreateImplicit( + Ctx, + true, + IntegerLiteral::Create(Ctx, PacAlign, Ctx.IntTy, + SourceLocation()), + {}, + AttributeCommonInfo::AS_GNU, + AlignedAttr::GNU_aligned)); + AppendFieldDecl(TagDecl, Field, PacFD); +} + +void AppendPacArrayFieldDecl(RecordDecl *TagDecl, FieldDecl *Field, unsigned ArySize, ASTContext &Ctx) +{ + auto Int64Ty = Ctx.getBitIntType(true, 64); + auto Int64ArrayTy = Ctx.getConstantArrayType(Int64Ty, llvm::APInt(64, ArySize), + nullptr, ArrayType::Normal, 0); + FieldDecl *PacArrayFD = FieldDecl::Create(Ctx, TagDecl, SourceLocation(), SourceLocation(), + nullptr, Int64ArrayTy, nullptr, nullptr, true, ICIS_NoInit); + + AppendFieldDecl(TagDecl, Field, PacArrayFD); +} + void PacDfiParseStruct(RecordDecl *TagDecl, ASTContext &Ctx, DiagnosticsEngine &Diags) { if (!llvm::PARTS::useDataFieldTag()) { return; } + // find pac_tag attr fields, and insert new fields std::vector PacPtrNames; std::vector PacFieldNames; + std::vector PacFieldExclNames; + std::vector PacFieldSeqlNames; unsigned int ArraySize = 0; for (auto *Field : TagDecl->fields()) { @@ -59,6 +124,19 @@ void PacDfiParseStruct(RecordDecl *TagDecl, ASTContext &Ctx, DiagnosticsEngine & << Field->getAttr()->getSpelling(); continue; } + if (Field->hasAttr()) { + if (!IsBaseTypeNotArrStruct(TagDecl, Field, Diags)) { + continue; + } + AppendPacFieldDecl(TagDecl, Field, Ctx); + PacFieldExclNames.push_back(Field); + continue; + } + if (Field->hasAttr()) { + AppendPacArrayFieldDecl(TagDecl, Field, Inc, Ctx); + PacFieldSeqlNames.push_back(Field); + continue; + } ArraySize += Inc; PacFieldNames.push_back(Field); } else if (Field->hasAttr()) { @@ -85,6 +163,12 @@ void PacDfiParseStruct(RecordDecl *TagDecl, ASTContext &Ctx, DiagnosticsEngine & if (!PacPtrNames.empty()) { PacPtrNameInfos.insert(std::make_pair(TagDecl, PacPtrNames)); } + if (!PacFieldExclNames.empty()) { + PacFieldExclNameInfos.insert(std::make_pair(TagDecl, PacFieldExclNames)); + } + if (!PacFieldSeqlNames.empty()) { + PacFieldSeqlNameInfos.insert(std::make_pair(TagDecl, PacFieldSeqlNames)); + } } void PacDfiCreateMetaData(std::map> &fieldInfos, StringRef mdName, @@ -126,6 +210,12 @@ void PacDfiEmitStructFieldsMetadata(llvm::Module &M, CodeGen::CodeGenModule *CGM if (!PacPtrNameInfos.empty()) { PacDfiCreateMetaData(PacPtrNameInfos, "pa_ptr_field_info", M, CGM, func); } + if (!PacFieldExclNameInfos.empty()) { + PacDfiCreateMetaData(PacFieldExclNameInfos, "pa_excl_field_info", M, CGM, func); + } + if (!PacFieldSeqlNameInfos.empty()) { + PacDfiCreateMetaData(PacFieldSeqlNameInfos, "pa_seql_field_info", M, CGM, func); + } } void PacDfiRecordDecl2StructName(const RecordDecl *RD, llvm::StructType *Entry) @@ -137,4 +227,5 @@ void PacDfiRecordDecl2StructName(const RecordDecl *RD, llvm::StructType *Entry) return; } RecordDecl2StructName.insert(std::make_pair(RD, Entry->getName())); -} \ No newline at end of file +} + diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 1a5775f4e14b..32f590ab964a 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -148,7 +148,9 @@ // CHECK-NEXT: Owner (SubjectMatchRule_record_not_is_union) // OHOS_LOCAL begin // CHECK-NEXT: PacDataTag (SubjectMatchRule_field) +// CHECK-NEXT: PacExclTag (SubjectMatchRule_field) // CHECK-NEXT: PacPtrTag (SubjectMatchRule_field) +// CHECK-NEXT: PacSeqlTag (SubjectMatchRule_field) // OHOS_LOCAL end // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) -- Gitee