Index: clang/test/CodeGen/asan-globals.cpp =================================================================== --- clang/test/CodeGen/asan-globals.cpp +++ clang/test/CodeGen/asan-globals.cpp @@ -6,6 +6,7 @@ // RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.ignorelist-src // RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=IGNORELIST-SRC // RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=kernel-address -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=IGNORELIST-SRC +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -o - %s -S -triple x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=ELF-SIZE int global; int dyn_init_global = global; @@ -55,20 +56,20 @@ // CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} // CHECK: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} // CHECK: ![[GLOBAL]] = !{{{.*}} ![[GLOBAL_LOC:[0-9]+]], !"global", i1 false, i1 false} -// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 10, i32 5} +// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 11, i32 5} // CHECK: ![[DYN_INIT_GLOBAL]] = !{{{.*}} ![[DYN_INIT_LOC:[0-9]+]], !"dyn_init_global", i1 true, i1 false} -// CHECK: ![[DYN_INIT_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 11, i32 5} +// CHECK: ![[DYN_INIT_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 12, i32 5} // CHECK: ![[ATTR_GLOBAL]] = !{{{.*attributed_global.*}}, null, null, i1 false, i1 true} // CHECK: ![[DISABLE_INSTR_GLOBAL]] = !{{{.*disable_instrumentation_global.*}}, null, null, i1 false, i1 true} // CHECK: ![[IGNORELISTED_GLOBAL]] = !{{{.*ignorelisted_global.*}}, null, null, i1 false, i1 true} // CHECK: ![[SECTIONED_GLOBAL]] = !{{{.*}} ![[SECTIONED_GLOBAL_LOC:[0-9]+]], !"sectioned_global", i1 false, i1 false} -// CHECK: ![[SECTIONED_GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 16, i32 50} +// CHECK: ![[SECTIONED_GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 17, i32 50} // CHECK: ![[SPECIAL_GLOBAL]] = !{{{.*}} ![[SPECIAL_GLOBAL_LOC:[0-9]+]], !"__special_global", i1 false, i1 false} -// CHECK: ![[SPECIAL_GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 18, i32 5} +// CHECK: ![[SPECIAL_GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 19, i32 5} // CHECK: ![[STATIC_VAR]] = !{{{.*}} ![[STATIC_LOC:[0-9]+]], !"static_var", i1 false, i1 false} -// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 22, i32 14} +// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 23, i32 14} // CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"", i1 false, i1 false} -// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 23, i32 25} +// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 24, i32 25} // IGNORELIST-SRC: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[DISABLE_INSTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[SECTIONED_GLOBAL:[0-9]+]], ![[SPECIAL_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} // IGNORELIST-SRC: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} @@ -82,3 +83,9 @@ // IGNORELIST-SRC: ![[SPECIAL_GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} // IGNORELIST-SRC: ![[STATIC_VAR]] = !{{{.*}} null, null, i1 false, i1 true} // IGNORELIST-SRC: ![[LITERAL]] = !{{{.*}} null, null, i1 false, i1 true} + +// ELF-SIZE: .globl global +// ELF-SIZE-NEXT: .p2align 5 +// ELF-SIZE-NEXT: global: +// ELF-SIZE-NEXT: .zero 32 +// ELF-SIZE-NEXT: .size global, 4 Index: llvm/include/llvm/IR/DerivedTypes.h =================================================================== --- llvm/include/llvm/IR/DerivedTypes.h +++ llvm/include/llvm/IR/DerivedTypes.h @@ -226,6 +226,7 @@ /// This is null if the type is an literal struct or if it is a identified /// type that has an empty name. void *SymbolTableEntry = nullptr; + llvm::Optional ExplicitSize; public: StructType(const StructType &) = delete; @@ -249,8 +250,9 @@ } /// This static method is the primary way to create a literal StructType. - static StructType *get(LLVMContext &Context, ArrayRef Elements, - bool isPacked = false); + static StructType *get(LLVMContext &Context, ArrayRef Elements, + bool isPacked = false, + llvm::Optional ExplicitSize = {}); /// Create an empty structure type. static StructType *get(LLVMContext &Context, bool isPacked = false); @@ -308,6 +310,12 @@ setBody(ArrayRef({elt1, elts...})); } + llvm::Optional getExplicitSize() const { return ExplicitSize; } + + void setExplicitSize(llvm::Optional NewExplicitSize) { + ExplicitSize = NewExplicitSize; + } + /// Return true if the specified type is valid as a element type. static bool isValidElementType(Type *ElemTy); Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -690,10 +690,14 @@ emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); - if (MAI->hasDotTypeDotSizeDirective()) + if (MAI->hasDotTypeDotSizeDirective()) { + if (const auto *Struct = dyn_cast(GV->getValueType())) + if (llvm::Optional ExplicitSize = Struct->getExplicitSize()) + Size = *ExplicitSize; // .size foo, 42 OutStreamer->emitELFSize(EmittedInitSym, MCConstantExpr::create(Size, OutContext)); + } OutStreamer->AddBlankLine(); } Index: llvm/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/lib/IR/LLVMContextImpl.h +++ llvm/lib/IR/LLVMContextImpl.h @@ -92,8 +92,11 @@ struct KeyTy { ArrayRef ETypes; bool isPacked; + Optional ExplicitSize; - KeyTy(const ArrayRef &E, bool P) : ETypes(E), isPacked(P) {} + KeyTy(const ArrayRef &E, bool P, + Optional ExplicitSize = {}) + : ETypes(E), isPacked(P), ExplicitSize(ExplicitSize) {} KeyTy(const StructType *ST) : ETypes(ST->elements()), isPacked(ST->isPacked()) {} @@ -103,7 +106,7 @@ return false; if (ETypes != that.ETypes) return false; - return true; + return ExplicitSize == that.ExplicitSize; } bool operator!=(const KeyTy &that) const { return !this->operator==(that); } }; Index: llvm/lib/IR/Type.cpp =================================================================== --- llvm/lib/IR/Type.cpp +++ llvm/lib/IR/Type.cpp @@ -403,10 +403,11 @@ // Primitive Constructors. -StructType *StructType::get(LLVMContext &Context, ArrayRef ETypes, - bool isPacked) { +StructType *StructType::get(LLVMContext &Context, ArrayRef ETypes, + bool isPacked, + llvm::Optional ExplicitSize) { LLVMContextImpl *pImpl = Context.pImpl; - const AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked); + AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked, ExplicitSize); StructType *ST; // Since we only want to allocate a fresh struct type in case none is found @@ -421,6 +422,7 @@ ST = new (Context.pImpl->Alloc) StructType(Context); ST->setSubclassData(SCDB_IsLiteral); // Literal struct. ST->setBody(ETypes, isPacked); + ST->setExplicitSize(ExplicitSize); *Insertion.first = ST; } else { // The struct type was found. Just return it. @@ -518,7 +520,7 @@ } StructType *StructType::get(LLVMContext &Context, bool isPacked) { - return get(Context, None, isPacked); + return get(Context, None, isPacked, {}); } StructType *StructType::create(LLVMContext &Context, ArrayRef Elements, Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2475,11 +2475,13 @@ /*AllowMerging*/ true, kAsanGenPrefix); Type *Ty = G->getValueType(); + uint64_t Size = G->getParent()->getDataLayout().getTypeAllocSize(Ty); const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes); Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); - StructType *NewTy = StructType::get(Ty, RightRedZoneTy); + StructType *NewTy = + StructType::get(Ty->getContext(), {Ty, RightRedZoneTy}, false, Size); Constant *NewInitializer = ConstantStruct::get( NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy));