[clang] [ObjC]: Make type encoding safe in symbol names (PR #77797)
Frederik Carlier via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 11 09:03:34 PST 2024
https://github.com/qmfrederik created https://github.com/llvm/llvm-project/pull/77797
Type encodings are part of symbol names in the Objective C ABI. Replace characters which are reseved in symbol names:
- ELF: avoid including '@' characters in type encodings
- Windows: avoid including '=' characters in type encodings
>From 5511454cae83ed61062c49a19c56edaf6b9ee1dd Mon Sep 17 00:00:00 2001
From: Frederik Carlier <frederik.carlier at keysight.com>
Date: Wed, 10 Jan 2024 16:51:18 +0000
Subject: [PATCH] [ObjC]: Make type encoding safe in symbol names
Type encodings are part of symbol names in the Objective C ABI. Replace
characters which are reseved in symbol names:
- ELF: avoid including '@' characters in type encodings
- Windows: avoid including '=' characters in type encodings
---
clang/lib/CodeGen/CGObjCGNU.cpp | 31 ++++++++++--------
clang/test/CodeGenObjC/encode-test-6.m | 44 +++++++++++++++++++++-----
2 files changed, 54 insertions(+), 21 deletions(-)
diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp
index cd1a0b6a130ff0..6e76765cea3db1 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -1431,12 +1431,25 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
const std::string &TypeEncoding) override {
return GetConstantSelector(Sel, TypeEncoding);
}
+ std::string GetSymbolNameForTypeEncoding(const std::string &TypeEncoding) {
+ std::string MangledTypes = std::string(TypeEncoding);
+ // @ is used as a special character in ELF symbol names (used for symbol
+ // versioning), so mangle the name to not include it. Replace it with a
+ // character that is not a valid type encoding character (and, being
+ // non-printable, never will be!)
+ if (CGM.getTriple().isOSBinFormatELF())
+ std::replace(MangledTypes.begin(), MangledTypes.end(),
+ '@', '\1');
+ // = in dll exported names causes lld to fail when linking on Windows.
+ if (CGM.getTriple().isOSWindows())
+ std::replace(MangledTypes.begin(), MangledTypes.end(),
+ '=', '\2');
+ return MangledTypes;
+ }
llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
if (TypeEncoding.empty())
return NULLPtr;
- std::string MangledTypes = std::string(TypeEncoding);
- std::replace(MangledTypes.begin(), MangledTypes.end(),
- '@', '\1');
+ std::string MangledTypes = GetSymbolNameForTypeEncoding(std::string(TypeEncoding));
std::string TypesVarName = ".objc_sel_types_" + MangledTypes;
auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
if (!TypesGlobal) {
@@ -1453,13 +1466,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
}
llvm::Constant *GetConstantSelector(Selector Sel,
const std::string &TypeEncoding) override {
- // @ is used as a special character in symbol names (used for symbol
- // versioning), so mangle the name to not include it. Replace it with a
- // character that is not a valid type encoding character (and, being
- // non-printable, never will be!)
- std::string MangledTypes = TypeEncoding;
- std::replace(MangledTypes.begin(), MangledTypes.end(),
- '@', '\1');
+ std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding);
auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" +
MangledTypes).str();
if (auto *GV = TheModule.getNamedGlobal(SelVarName))
@@ -1671,9 +1678,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
const ObjCIvarDecl *Ivar) override {
std::string TypeEncoding;
CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding);
- // Prevent the @ from being interpreted as a symbol version.
- std::replace(TypeEncoding.begin(), TypeEncoding.end(),
- '@', '\1');
+ TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding);
const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
+ '.' + Ivar->getNameAsString() + '.' + TypeEncoding;
return Name;
diff --git a/clang/test/CodeGenObjC/encode-test-6.m b/clang/test/CodeGenObjC/encode-test-6.m
index 261eb7fb3368b2..1eb6808c7d12f8 100644
--- a/clang/test/CodeGenObjC/encode-test-6.m
+++ b/clang/test/CodeGenObjC/encode-test-6.m
@@ -1,5 +1,14 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o %t %s
-// RUN: FileCheck < %t %s
+// RUN: FileCheck -check-prefix CHECK-DWARF < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -o %t %s
+// RUN: FileCheck -check-prefix CHECK-MINGW < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -fobjc-runtime=gnustep-2.0 -o %t %s
+// RUN: FileCheck -check-prefix CHECK-MSVC < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -o %t %s
+// RUN: FileCheck -check-prefix CHECK-ELF < %t %s
typedef struct {} Z;
@@ -13,8 +22,17 @@ -(void)bar:(Z)a {}
-(void)foo:(Z)a: (char*)b : (Z)c : (double) d {}
@end
-// CHECK: private unnamed_addr constant [14 x i8] c"v16 at 0:8{?=}16
-// CHECK: private unnamed_addr constant [26 x i8] c"v32 at 0:8{?=}16*16{?=}24d24
+// CHECK-DWARF: private unnamed_addr constant [14 x i8] c"v16 at 0:8{?=}16
+// CHECK-DWARF: private unnamed_addr constant [26 x i8] c"v32 at 0:8{?=}16*16{?=}24d24
+
+// CHECK-MINGW: @".objc_sel_types_v16 at 0:8{?\02}16" = linkonce_odr hidden constant [14 x i8] c"v16 at 0:8{?=}16\00"
+// CHECK-MINGW: @".objc_sel_types_v32 at 0:8{?\02}16*16{?\02}24d24" = linkonce_odr hidden constant [26 x i8] c"v32 at 0:8{?=}16*16{?=}24d24\00"
+
+// CHECK-MSVC: @".objc_sel_types_v20 at 0:8{?\02}16" = linkonce_odr hidden constant [14 x i8] c"v20 at 0:8{?=}16\00"
+// CHECK-MSVC: @".objc_sel_types_v40 at 0:8{?\02}16*20{?\02}28d32" = linkonce_odr hidden constant [26 x i8] c"v40 at 0:8{?=}16*20{?=}28d32\00"
+
+// CHECK-ELF: @".objc_sel_types_v16\010:8{?=}16" = linkonce_odr hidden constant [14 x i8] c"v16 at 0:8{?=}16\00"
+// CHECK-ELF: @".objc_sel_types_v32\010:8{?=}16*16{?=}24d24" = linkonce_odr hidden constant [26 x i8] c"v32 at 0:8{?=}16*16{?=}24d24\00"
@interface NSObject @end
@@ -31,7 +49,10 @@ @implementation BABugExample
@synthesize property = _property;
@end
-// CHECK: private unnamed_addr constant [8 x i8] c"@16
+// CHECK-DWARF: private unnamed_addr constant [8 x i8] c"@16
+// CHECK-MINGW: @".objc_sel_types_ at 16@0:8" = linkonce_odr hidden constant [8 x i8] c"@16 at 0:8\00"
+// CHECK-MSVC: @".objc_sel_types_ at 16@0:8" = linkonce_odr hidden constant [8 x i8] c"@16 at 0:8\00"
+// CHECK-ELF @".objc_sel_types_\0116\010:8" = linkonce_odr hidden constant [8 x i8] c"@16 at 0:8\00"
@class SCNCamera;
typedef SCNCamera C3DCamera;
@@ -48,7 +69,10 @@ @implementation SCNCamera
C3DCameraStorage _storage;
}
@end
-// CHECK: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22@\22SCNCamera\22}\00"
+// CHECK-DWARF: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22@\22SCNCamera\22}\00"
+// CHECK-MINGW: @"__objc_ivar_offset_SCNCamera._storage.{?\02@}"
+// CHECK-MSVC: @"__objc_ivar_offset_SCNCamera._storage.{?\02@}"
+// CHECK-ELF: @"__objc_ivar_offset_SCNCamera._storage.{?=\01}"
int i;
typeof(@encode(typeof(i))) e = @encode(typeof(i));
@@ -56,6 +80,10 @@ @implementation SCNCamera
{
return e;
}
-// CHECK: @e ={{.*}} global [2 x i8] c"i\00", align 1
-// CHECK: define{{.*}} ptr @Test()
-// CHECK: ret ptr @e
+// CHECK-DWARF: @e ={{.*}} global [2 x i8] c"i\00", align 1
+// CHECK-DWARF: define{{.*}} ptr @Test()
+// CHECK-DWARF: ret ptr @e
+
+// CHECK-MSVC: @e = dso_local global [2 x i8] c"i\00", align 1
+// CHECK-MINGW: @e = dso_local global [2 x i8] c"i\00", align 1
+// CHECK-ELF: @e = global [2 x i8] c"i\00", align 1
More information about the cfe-commits
mailing list