leonardchan created this revision. leonardchan added reviewers: pcc, eugenis, vitalybuka. leonardchan added a project: Sanitizers. Herald added subscribers: Enna1, jeroen.dobbelaere, hiraditya. Herald added a project: All. leonardchan requested review of this revision. Herald added projects: clang, LLVM. Herald added a subscriber: cfe-commits.
If an existing global has linkonce_odr linkage, then the alias adopts the global's linkonce_odr linkage. The ODR linkages should only be used if its guaranteed by the frontend that all definitions of the symbol are "equivalent", hence they are effectively non-interposable. It's very unlikely however for two aliases to be the same across multiple TUs since they'll likely have different tags. This is a problem if a pass replaces a use of the alias with its local aliasee because if another definition with a separate tag wins at link time, then the local aliasee usage is incorrect. Full context at https://github.com/llvm/llvm-project/issues/60668. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D144035 Files: clang/test/CodeGenCXX/pr60668.cpp llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp llvm/test/Instrumentation/HWAddressSanitizer/odr.ll Index: llvm/test/Instrumentation/HWAddressSanitizer/odr.ll =================================================================== --- /dev/null +++ llvm/test/Instrumentation/HWAddressSanitizer/odr.ll @@ -0,0 +1,7 @@ +; RUN: opt < %s -passes=hwasan -S | FileCheck %s + +; CHECK: @linkonce_odr_obj = linkonce hidden alias +@linkonce_odr_obj = linkonce_odr hidden constant i32 1 + +; CHECK: weak_odr_obj = weak hidden alias +@weak_odr_obj = weak_odr hidden constant i32 1 Index: llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -1568,8 +1568,24 @@ ConstantExpr::getPtrToInt(NewGV, Int64Ty), ConstantInt::get(Int64Ty, uint64_t(Tag) << PointerTagShift)), GV->getType()); + + // Ensure the global doesn't have *ODRLinkage. Those linkages should only be + // used if all other definitions of the global are "equivalent" to this one. + // Since this alias could be defined in other TU's, it's very unlikely they'll + // all have the same tag. + // + // This fixes PR60668. + GlobalValue::LinkageTypes Linkage; + if (GV->hasLinkOnceODRLinkage()) { + Linkage = GlobalValue::LinkOnceAnyLinkage; + } else if (GV->hasWeakODRLinkage()) { + Linkage = GlobalValue::WeakAnyLinkage; + } else { + Linkage = GV->getLinkage(); + } + auto *Alias = GlobalAlias::create(GV->getValueType(), GV->getAddressSpace(), - GV->getLinkage(), "", Aliasee, &M); + Linkage, "", Aliasee, &M); Alias->setVisibility(GV->getVisibility()); Alias->takeName(GV); GV->replaceAllUsesWith(Alias); Index: clang/test/CodeGenCXX/pr60668.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/pr60668.cpp @@ -0,0 +1,28 @@ +// RUN: %clang --target=aarch64-unknown-linux-gnu -O1 -fvisibility=hidden \ +// RUN: -fsanitize=hwaddress -fsanitize=undefined -std=c++17 -fno-exceptions \ +// RUN: -fno-rtti -c %s -S -o - | FileCheck %s + +struct AndroidSizeClassConfig { + static constexpr unsigned Classes[] = { + 0x00020, 0x00030, 0x00040, 0x00050, 0x00060, 0x00070, 0x00090, 0x000b0, + 0x000c0, 0x000e0, 0x00120, 0x00160, 0x001c0, 0x00250, 0x00320, 0x00450, + 0x00670, 0x00830, 0x00a10, 0x00c30, 0x01010, 0x01210, 0x01bd0, 0x02210, + 0x02d90, 0x03790, 0x04010, 0x04810, 0x05a10, 0x07310, 0x08210, 0x10010, + }; +}; + +static const unsigned NumClasses = + sizeof(AndroidSizeClassConfig::Classes) / sizeof(AndroidSizeClassConfig::Classes[0]); + +void func(unsigned); + +void printMap() { + for (unsigned I = 0; I < NumClasses; I++) { + func(AndroidSizeClassConfig::Classes[I]); + } +} + +// CHECK-LABEL: _Z8printMapv +// CHECK: adrp x{{.*}}, :pg_hi21_nc:_ZN22AndroidSizeClassConfig7ClassesE +// CHECK: movk x{{.*}}, #:prel_g3:_ZN22AndroidSizeClassConfig7ClassesE+4294967296 +// CHECK: add x{{.*}}, x19, :lo12:_ZN22AndroidSizeClassConfig7ClassesE
Index: llvm/test/Instrumentation/HWAddressSanitizer/odr.ll =================================================================== --- /dev/null +++ llvm/test/Instrumentation/HWAddressSanitizer/odr.ll @@ -0,0 +1,7 @@ +; RUN: opt < %s -passes=hwasan -S | FileCheck %s + +; CHECK: @linkonce_odr_obj = linkonce hidden alias +@linkonce_odr_obj = linkonce_odr hidden constant i32 1 + +; CHECK: weak_odr_obj = weak hidden alias +@weak_odr_obj = weak_odr hidden constant i32 1 Index: llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -1568,8 +1568,24 @@ ConstantExpr::getPtrToInt(NewGV, Int64Ty), ConstantInt::get(Int64Ty, uint64_t(Tag) << PointerTagShift)), GV->getType()); + + // Ensure the global doesn't have *ODRLinkage. Those linkages should only be + // used if all other definitions of the global are "equivalent" to this one. + // Since this alias could be defined in other TU's, it's very unlikely they'll + // all have the same tag. + // + // This fixes PR60668. + GlobalValue::LinkageTypes Linkage; + if (GV->hasLinkOnceODRLinkage()) { + Linkage = GlobalValue::LinkOnceAnyLinkage; + } else if (GV->hasWeakODRLinkage()) { + Linkage = GlobalValue::WeakAnyLinkage; + } else { + Linkage = GV->getLinkage(); + } + auto *Alias = GlobalAlias::create(GV->getValueType(), GV->getAddressSpace(), - GV->getLinkage(), "", Aliasee, &M); + Linkage, "", Aliasee, &M); Alias->setVisibility(GV->getVisibility()); Alias->takeName(GV); GV->replaceAllUsesWith(Alias); Index: clang/test/CodeGenCXX/pr60668.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/pr60668.cpp @@ -0,0 +1,28 @@ +// RUN: %clang --target=aarch64-unknown-linux-gnu -O1 -fvisibility=hidden \ +// RUN: -fsanitize=hwaddress -fsanitize=undefined -std=c++17 -fno-exceptions \ +// RUN: -fno-rtti -c %s -S -o - | FileCheck %s + +struct AndroidSizeClassConfig { + static constexpr unsigned Classes[] = { + 0x00020, 0x00030, 0x00040, 0x00050, 0x00060, 0x00070, 0x00090, 0x000b0, + 0x000c0, 0x000e0, 0x00120, 0x00160, 0x001c0, 0x00250, 0x00320, 0x00450, + 0x00670, 0x00830, 0x00a10, 0x00c30, 0x01010, 0x01210, 0x01bd0, 0x02210, + 0x02d90, 0x03790, 0x04010, 0x04810, 0x05a10, 0x07310, 0x08210, 0x10010, + }; +}; + +static const unsigned NumClasses = + sizeof(AndroidSizeClassConfig::Classes) / sizeof(AndroidSizeClassConfig::Classes[0]); + +void func(unsigned); + +void printMap() { + for (unsigned I = 0; I < NumClasses; I++) { + func(AndroidSizeClassConfig::Classes[I]); + } +} + +// CHECK-LABEL: _Z8printMapv +// CHECK: adrp x{{.*}}, :pg_hi21_nc:_ZN22AndroidSizeClassConfig7ClassesE +// CHECK: movk x{{.*}}, #:prel_g3:_ZN22AndroidSizeClassConfig7ClassesE+4294967296 +// CHECK: add x{{.*}}, x19, :lo12:_ZN22AndroidSizeClassConfig7ClassesE
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits