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

Reply via email to