1 From 1030297d77ae5110b7873530f645aeec3a4264ba Mon Sep 17 00:00:00 2001
2 From: Yuanfang Chen <yuanfang.chen@sony.com>
3 Date: Mon, 27 Jun 2022 11:33:45 -0700
4 Subject: [PATCH 1/2] [ubsan] Using metadata instead of prologue data for
7 Information in the function `Prologue Data` is intentionally opaque.
8 When a function with `Prologue Data` is duplicated. The self (global
9 value) references inside `Prologue Data` is still pointing to the
10 original function. This may cause errors like `fatal error: error in backend: Cannot represent a difference across sections`.
12 This patch detaches the information from function `Prologue Data`
13 and attaches it to a function metadata node.
15 This and D116130 fix https://github.com/llvm/llvm-project/issues/49689.
19 Differential Revision: https://reviews.llvm.org/D115844
21 (cherry picked from commit 6678f8e505b19069a9dbdc3e3ee088d543752412)
23 llvm/docs/LangRef.rst | 22 ++++++++++++++++++-
24 llvm/include/llvm/IR/FixedMetadataKinds.def | 1 +
25 llvm/include/llvm/IR/MDBuilder.h | 4 ++++
26 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 18 +++++++++++++++
27 llvm/lib/IR/MDBuilder.cpp | 8 +++++++
28 .../Instrumentation/AddressSanitizer.cpp | 10 ++++-----
29 llvm/test/CodeGen/X86/func-sanitizer.ll | 18 +++++++++++++++
30 7 files changed, 75 insertions(+), 6 deletions(-)
31 create mode 100644 llvm/test/CodeGen/X86/func-sanitizer.ll
33 diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
34 index 920834b10897..a5a84a2f297b 100644
35 --- a/llvm/docs/LangRef.rst
36 +++ b/llvm/docs/LangRef.rst
37 @@ -5194,7 +5194,7 @@ multiple metadata attachments with the same identifier.
39 A transformation is required to drop any metadata attachment that it does not
40 know or know it can't preserve. Currently there is an exception for metadata
41 -attachment to globals for ``!type`` and ``!absolute_symbol`` which can't be
42 +attachment to globals for ``!func_sanitize``, ``!type`` and ``!absolute_symbol`` which can't be
43 unconditionally dropped unless the global is itself deleted.
45 Metadata attached to a module using named metadata may not be dropped, with
46 @@ -7080,6 +7080,26 @@ Example:
47 %a.addr = alloca float*, align 8, !annotation !0
50 +'``func_sanitize``' Metadata
51 +^^^^^^^^^^^^^^^^^^^^^^^^^
53 +The ``func_sanitize`` metadata is used to attach two values for the function
54 +sanitizer instrumentation. The first value is the ubsan function signature.
55 +The second value is the address of the proxy variable which stores the address
56 +of the RTTI descriptor. If :ref:`prologue <prologuedata>` and '``func_sanitize``'
57 +are used at the same time, :ref:`prologue <prologuedata>` is emitted before
58 +'``func_sanitize``' in the output.
64 + @__llvm_rtti_proxy = private unnamed_addr constant i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*)
65 + define void @_Z3funv() !func_sanitize !0 {
68 + !0 = !{i32 846595819, i8** @__llvm_rtti_proxy}
73 diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
74 index 31979cd2f9db..baa7a91cbf56 100644
75 --- a/llvm/include/llvm/IR/FixedMetadataKinds.def
76 +++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
77 @@ -42,3 +42,4 @@ LLVM_FIXED_MD_KIND(MD_preserve_access_index, "llvm.preserve.access.index", 27)
78 LLVM_FIXED_MD_KIND(MD_vcall_visibility, "vcall_visibility", 28)
79 LLVM_FIXED_MD_KIND(MD_noundef, "noundef", 29)
80 LLVM_FIXED_MD_KIND(MD_annotation, "annotation", 30)
81 +LLVM_FIXED_MD_KIND(MD_func_sanitize, "func_sanitize", 31)
82 diff --git a/llvm/include/llvm/IR/MDBuilder.h b/llvm/include/llvm/IR/MDBuilder.h
83 index 42829388b79a..21d7b8b6da71 100644
84 --- a/llvm/include/llvm/IR/MDBuilder.h
85 +++ b/llvm/include/llvm/IR/MDBuilder.h
86 @@ -108,6 +108,10 @@ public:
87 /// Merge the new callback encoding \p NewCB into \p ExistingCallbacks.
88 MDNode *mergeCallbackEncodings(MDNode *ExistingCallbacks, MDNode *NewCB);
90 + /// Return metadata feeding to the CodeGen about how to generate a function
91 + /// prologue for the "function" santizier.
92 + MDNode *createRTTIPointerPrologue(Constant *PrologueSig, Constant *RTTI);
94 //===------------------------------------------------------------------===//
96 //===------------------------------------------------------------------===//
97 diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
98 index 3e8e190eecc3..091f16567a36 100644
99 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
100 +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
101 @@ -844,6 +844,24 @@ void AsmPrinter::emitFunctionHeader() {
102 // Emit the prologue data.
103 if (F.hasPrologueData())
104 emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData());
106 + // Emit the function prologue data for the indirect call sanitizer.
107 + if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) {
108 + assert(TM.getTargetTriple().getArch() == Triple::x86 ||
109 + TM.getTargetTriple().getArch() == Triple::x86_64);
110 + assert(MD->getNumOperands() == 2);
112 + auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0));
113 + auto *FTRTTIProxy = mdconst::extract<Constant>(MD->getOperand(1));
114 + assert(PrologueSig && FTRTTIProxy);
115 + emitGlobalConstant(F.getParent()->getDataLayout(), PrologueSig);
117 + const MCExpr *Proxy = lowerConstant(FTRTTIProxy);
118 + const MCExpr *FnExp = MCSymbolRefExpr::create(CurrentFnSym, OutContext);
119 + const MCExpr *PCRel = MCBinaryExpr::createSub(Proxy, FnExp, OutContext);
120 + // Use 32 bit since only small code model is supported.
121 + OutStreamer->emitValue(PCRel, 4u);
125 /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the
126 diff --git a/llvm/lib/IR/MDBuilder.cpp b/llvm/lib/IR/MDBuilder.cpp
127 index 35af8490287b..fc59fda9fe22 100644
128 --- a/llvm/lib/IR/MDBuilder.cpp
129 +++ b/llvm/lib/IR/MDBuilder.cpp
130 @@ -150,6 +150,14 @@ MDNode *MDBuilder::mergeCallbackEncodings(MDNode *ExistingCallbacks,
131 return MDNode::get(Context, Ops);
134 +MDNode *MDBuilder::createRTTIPointerPrologue(Constant *PrologueSig,
136 + SmallVector<Metadata *, 4> Ops;
137 + Ops.push_back(createConstant(PrologueSig));
138 + Ops.push_back(createConstant(RTTI));
139 + return MDNode::get(Context, Ops);
142 MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) {
143 SmallVector<Metadata *, 3> Args(1, nullptr);
145 diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
146 index 8f94172a6402..9d11ef26c1f0 100644
147 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
148 +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
149 @@ -1405,7 +1405,11 @@ static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M,
150 /// Check if \p G has been created by a trusted compiler pass.
151 static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) {
152 // Do not instrument @llvm.global_ctors, @llvm.used, etc.
153 - if (G->getName().startswith("llvm."))
154 + if (G->getName().startswith("llvm.") ||
155 + // Do not instrument gcov counter arrays.
156 + G->getName().startswith("__llvm_gcov_ctr") ||
157 + // Do not instrument rtti proxy symbols for function sanitizer.
158 + G->getName().startswith("__llvm_rtti_proxy"))
161 // Do not instrument asan globals.
162 @@ -1414,10 +1418,6 @@ static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) {
163 G->getName().startswith(kODRGenPrefix))
166 - // Do not instrument gcov counter arrays.
167 - if (G->getName() == "__llvm_gcov_ctr")
173 diff --git a/llvm/test/CodeGen/X86/func-sanitizer.ll b/llvm/test/CodeGen/X86/func-sanitizer.ll
175 index 000000000000..b8d96a346d0c
177 +++ b/llvm/test/CodeGen/X86/func-sanitizer.ll
179 +; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
182 +; CHECK: .cfi_startproc
183 +; CHECK: .long 846595819
184 +; CHECK: .long .L__llvm_rtti_proxy-_Z3funv
185 +; CHECK: .L__llvm_rtti_proxy:
187 +; CHECK: .size .L__llvm_rtti_proxy, 8
189 +@i = linkonce_odr constant i32 1
190 +@__llvm_rtti_proxy = private unnamed_addr constant i32* @i
192 +define dso_local void @_Z3funv() !func_sanitize !0 {
196 +!0 = !{i32 846595819, i32** @__llvm_rtti_proxy}
198 From 640a28cc0fe12741daa4c22f34b618ad57195528 Mon Sep 17 00:00:00 2001
199 From: Yuanfang Chen <yuanfang.chen@sony.com>
200 Date: Mon, 27 Jun 2022 11:36:32 -0700
201 Subject: [PATCH 2/2] [Coroutine] Remove the '!func_sanitize' metadata for
204 There is no proper RTTI for these split functions. So just delete the
207 Fixes https://github.com/llvm/llvm-project/issues/49689.
209 Reviewed By: rjmccall
211 Differential Revision: https://reviews.llvm.org/D116130
213 (cherry picked from commit e2e9e708e5c2c3d5357b4bb355285ef55cd060d9)
215 llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 6 ++++++
216 llvm/test/Transforms/Coroutines/coro-split-00.ll | 12 +++++++-----
217 2 files changed, 13 insertions(+), 5 deletions(-)
219 diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
220 index b5129809c6a6..78134fd297da 100644
221 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
222 +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
223 @@ -923,6 +923,12 @@ void CoroCloner::create() {
224 NewF->setVisibility(savedVisibility);
225 NewF->setUnnamedAddr(savedUnnamedAddr);
226 NewF->setDLLStorageClass(savedDLLStorageClass);
227 + // The function sanitizer metadata needs to match the signature of the
228 + // function it is being attached to. However this does not hold for split
229 + // functions here. Thus remove the metadata for split functions.
230 + if (Shape.ABI == coro::ABI::Switch &&
231 + NewF->hasMetadata(LLVMContext::MD_func_sanitize))
232 + NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
234 // Replace the attributes of the new function:
235 auto OrigAttrs = NewF->getAttributes();
236 diff --git a/llvm/test/Transforms/Coroutines/coro-split-00.ll b/llvm/test/Transforms/Coroutines/coro-split-00.ll
237 index d5c6279a6a87..cf2dc10549e7 100644
238 --- a/llvm/test/Transforms/Coroutines/coro-split-00.ll
239 +++ b/llvm/test/Transforms/Coroutines/coro-split-00.ll
241 ; Tests that coro-split pass splits the coroutine into f, f.resume and f.destroy
242 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
244 -define i8* @f() "coroutine.presplit"="1" {
245 +define i8* @f() "coroutine.presplit"="1" !func_sanitize !0 {
247 %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
248 %need.alloc = call i1 @llvm.coro.alloc(token %id)
249 @@ -32,7 +32,7 @@ suspend:
254 +; CHECK-LABEL: @f() !func_sanitize !0 {
255 ; CHECK: call i8* @malloc
256 ; CHECK: @llvm.coro.begin(token %id, i8* %phi)
257 ; CHECK: store void (%f.Frame*)* @f.resume, void (%f.Frame*)** %resume.addr
258 @@ -43,7 +43,7 @@ suspend:
259 ; CHECK-NOT: call void @free(
260 ; CHECK: ret i8* %hdl
262 -; CHECK-LABEL: @f.resume(
263 +; CHECK-LABEL: @f.resume({{.*}}) {
264 ; CHECK-NOT: call i8* @malloc
265 ; CHECK-NOT: call void @print(i32 0)
266 ; CHECK: call void @print(i32 1)
267 @@ -51,13 +51,13 @@ suspend:
268 ; CHECK: call void @free(
271 -; CHECK-LABEL: @f.destroy(
272 +; CHECK-LABEL: @f.destroy({{.*}}) {
273 ; CHECK-NOT: call i8* @malloc
274 ; CHECK-NOT: call void @print(
275 ; CHECK: call void @free(
278 -; CHECK-LABEL: @f.cleanup(
279 +; CHECK-LABEL: @f.cleanup({{.*}}) {
280 ; CHECK-NOT: call i8* @malloc
281 ; CHECK-NOT: call void @print(
282 ; CHECK-NOT: call void @free(
283 @@ -77,3 +77,5 @@ declare i1 @llvm.coro.end(i8*, i1)
284 declare noalias i8* @malloc(i32)
285 declare void @print(i32)
286 declare void @free(i8*) willreturn
288 +!0 = !{i32 846595819, i8** null}