]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/ubsan/ubsan_handlers.cc
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / compiler-rt / lib / ubsan / ubsan_handlers.cc
CommitLineData
1a4d82fc
JJ
1//===-- ubsan_handlers.cc -------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Error logging entry points for the UBSan runtime.
11//
12//===----------------------------------------------------------------------===//
13
92a42be0
SL
14#include "ubsan_platform.h"
15#if CAN_SANITIZE_UB
1a4d82fc
JJ
16#include "ubsan_handlers.h"
17#include "ubsan_diag.h"
18
19#include "sanitizer_common/sanitizer_common.h"
20
21using namespace __sanitizer;
22using namespace __ubsan;
23
92a42be0
SL
24static bool ignoreReport(SourceLocation SLoc, ReportOptions Opts) {
25 // If source location is already acquired, we don't need to print an error
26 // report for the second time. However, if we're in an unrecoverable handler,
27 // it's possible that location was required by concurrently running thread.
28 // In this case, we should continue the execution to ensure that any of
29 // threads will grab the report mutex and print the report before
30 // crashing the program.
31 return SLoc.isDisabled() && !Opts.DieAfterReport;
32}
33
1a4d82fc 34namespace __ubsan {
92a42be0 35const char *TypeCheckKinds[] = {
1a4d82fc 36 "load of", "store to", "reference binding to", "member access within",
92a42be0
SL
37 "member call on", "constructor call on", "downcast of", "downcast of",
38 "upcast of", "cast to virtual base of"};
1a4d82fc
JJ
39}
40
41static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
92a42be0 42 ReportOptions Opts) {
1a4d82fc 43 Location Loc = Data->Loc.acquire();
1a4d82fc 44 // Use the SourceLocation from Data to track deduplication, even if 'invalid'
92a42be0 45 if (ignoreReport(Loc.getSourceLocation(), Opts))
1a4d82fc 46 return;
92a42be0
SL
47
48 SymbolizedStackHolder FallbackLoc;
49 if (Data->Loc.isInvalid()) {
50 FallbackLoc.reset(getCallerLocation(Opts.pc));
1a4d82fc 51 Loc = FallbackLoc;
92a42be0 52 }
1a4d82fc 53
92a42be0
SL
54 ScopedReport R(Opts, Loc);
55
56 if (!Pointer) {
57 R.setErrorType(ErrorType::NullPointerUse);
1a4d82fc
JJ
58 Diag(Loc, DL_Error, "%0 null pointer of type %1")
59 << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
92a42be0
SL
60 } else if (Data->Alignment && (Pointer & (Data->Alignment - 1))) {
61 R.setErrorType(ErrorType::MisalignedPointerUse);
1a4d82fc
JJ
62 Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, "
63 "which requires %2 byte alignment")
64 << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer
65 << Data->Alignment << Data->Type;
92a42be0
SL
66 } else {
67 R.setErrorType(ErrorType::InsufficientObjectSize);
1a4d82fc
JJ
68 Diag(Loc, DL_Error, "%0 address %1 with insufficient space "
69 "for an object of type %2")
70 << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
92a42be0 71 }
1a4d82fc
JJ
72 if (Pointer)
73 Diag(Pointer, DL_Note, "pointer points here");
74}
92a42be0 75
1a4d82fc
JJ
76void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
77 ValueHandle Pointer) {
92a42be0
SL
78 GET_REPORT_OPTIONS(false);
79 handleTypeMismatchImpl(Data, Pointer, Opts);
1a4d82fc
JJ
80}
81void __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
82 ValueHandle Pointer) {
92a42be0
SL
83 GET_REPORT_OPTIONS(true);
84 handleTypeMismatchImpl(Data, Pointer, Opts);
1a4d82fc
JJ
85 Die();
86}
87
88/// \brief Common diagnostic emission for various forms of integer overflow.
92a42be0
SL
89template <typename T>
90static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
91 const char *Operator, T RHS,
92 ReportOptions Opts) {
1a4d82fc 93 SourceLocation Loc = Data->Loc.acquire();
92a42be0 94 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
95 return;
96
92a42be0
SL
97 bool IsSigned = Data->Type.isSignedIntegerTy();
98 ScopedReport R(Opts, Loc, IsSigned ? ErrorType::SignedIntegerOverflow
99 : ErrorType::UnsignedIntegerOverflow);
100
1a4d82fc
JJ
101 Diag(Loc, DL_Error, "%0 integer overflow: "
102 "%1 %2 %3 cannot be represented in type %4")
92a42be0 103 << (IsSigned ? "signed" : "unsigned")
1a4d82fc
JJ
104 << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
105}
106
92a42be0
SL
107#define UBSAN_OVERFLOW_HANDLER(handler_name, op, abort) \
108 void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \
109 ValueHandle RHS) { \
110 GET_REPORT_OPTIONS(abort); \
111 handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \
112 if (abort) Die(); \
113 }
114
115UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
116UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
117UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
118UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
119UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
120UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
121
122static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
123 ReportOptions Opts) {
1a4d82fc 124 SourceLocation Loc = Data->Loc.acquire();
92a42be0 125 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
126 return;
127
92a42be0
SL
128 bool IsSigned = Data->Type.isSignedIntegerTy();
129 ScopedReport R(Opts, Loc, IsSigned ? ErrorType::SignedIntegerOverflow
130 : ErrorType::UnsignedIntegerOverflow);
131
132 if (IsSigned)
1a4d82fc
JJ
133 Diag(Loc, DL_Error,
134 "negation of %0 cannot be represented in type %1; "
135 "cast to an unsigned type to negate this value to itself")
92a42be0 136 << Value(Data->Type, OldVal) << Data->Type;
1a4d82fc 137 else
92a42be0
SL
138 Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1")
139 << Value(Data->Type, OldVal) << Data->Type;
140}
141
142void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
143 ValueHandle OldVal) {
144 GET_REPORT_OPTIONS(false);
145 handleNegateOverflowImpl(Data, OldVal, Opts);
1a4d82fc
JJ
146}
147void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
148 ValueHandle OldVal) {
92a42be0
SL
149 GET_REPORT_OPTIONS(true);
150 handleNegateOverflowImpl(Data, OldVal, Opts);
1a4d82fc
JJ
151 Die();
152}
153
92a42be0
SL
154static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
155 ValueHandle RHS, ReportOptions Opts) {
1a4d82fc 156 SourceLocation Loc = Data->Loc.acquire();
92a42be0 157 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
158 return;
159
92a42be0
SL
160 ScopedReport R(Opts, Loc);
161
1a4d82fc
JJ
162 Value LHSVal(Data->Type, LHS);
163 Value RHSVal(Data->Type, RHS);
92a42be0
SL
164 if (RHSVal.isMinusOne()) {
165 R.setErrorType(ErrorType::SignedIntegerOverflow);
1a4d82fc
JJ
166 Diag(Loc, DL_Error,
167 "division of %0 by -1 cannot be represented in type %1")
168 << LHSVal << Data->Type;
92a42be0
SL
169 } else {
170 R.setErrorType(Data->Type.isIntegerTy() ? ErrorType::IntegerDivideByZero
171 : ErrorType::FloatDivideByZero);
1a4d82fc 172 Diag(Loc, DL_Error, "division by zero");
92a42be0
SL
173 }
174}
175
176void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
177 ValueHandle LHS, ValueHandle RHS) {
178 GET_REPORT_OPTIONS(false);
179 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
180}
181void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
182 ValueHandle LHS,
183 ValueHandle RHS) {
92a42be0
SL
184 GET_REPORT_OPTIONS(true);
185 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
186 Die();
187}
188
92a42be0
SL
189static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
190 ValueHandle LHS, ValueHandle RHS,
191 ReportOptions Opts) {
1a4d82fc 192 SourceLocation Loc = Data->Loc.acquire();
92a42be0 193 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
194 return;
195
92a42be0
SL
196 ScopedReport R(Opts, Loc);
197
1a4d82fc
JJ
198 Value LHSVal(Data->LHSType, LHS);
199 Value RHSVal(Data->RHSType, RHS);
92a42be0
SL
200 if (RHSVal.isNegative()) {
201 R.setErrorType(ErrorType::InvalidShiftExponent);
1a4d82fc 202 Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal;
92a42be0
SL
203 } else if (RHSVal.getPositiveIntValue() >=
204 Data->LHSType.getIntegerBitWidth()) {
205 R.setErrorType(ErrorType::InvalidShiftExponent);
206 Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2")
207 << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
208 } else if (LHSVal.isNegative()) {
209 R.setErrorType(ErrorType::InvalidShiftBase);
1a4d82fc 210 Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal;
92a42be0
SL
211 } else {
212 R.setErrorType(ErrorType::InvalidShiftBase);
1a4d82fc
JJ
213 Diag(Loc, DL_Error,
214 "left shift of %0 by %1 places cannot be represented in type %2")
92a42be0
SL
215 << LHSVal << RHSVal << Data->LHSType;
216 }
217}
218
219void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
220 ValueHandle LHS,
221 ValueHandle RHS) {
222 GET_REPORT_OPTIONS(false);
223 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
224}
225void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
226 ShiftOutOfBoundsData *Data,
227 ValueHandle LHS,
228 ValueHandle RHS) {
92a42be0
SL
229 GET_REPORT_OPTIONS(true);
230 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
231 Die();
232}
233
92a42be0
SL
234static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
235 ReportOptions Opts) {
1a4d82fc 236 SourceLocation Loc = Data->Loc.acquire();
92a42be0 237 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
238 return;
239
92a42be0
SL
240 ScopedReport R(Opts, Loc, ErrorType::OutOfBoundsIndex);
241
1a4d82fc
JJ
242 Value IndexVal(Data->IndexType, Index);
243 Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
244 << IndexVal << Data->ArrayType;
245}
92a42be0
SL
246
247void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
248 ValueHandle Index) {
249 GET_REPORT_OPTIONS(false);
250 handleOutOfBoundsImpl(Data, Index, Opts);
251}
1a4d82fc
JJ
252void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
253 ValueHandle Index) {
92a42be0
SL
254 GET_REPORT_OPTIONS(true);
255 handleOutOfBoundsImpl(Data, Index, Opts);
1a4d82fc
JJ
256 Die();
257}
258
92a42be0
SL
259static void handleBuiltinUnreachableImpl(UnreachableData *Data,
260 ReportOptions Opts) {
261 ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall);
1a4d82fc 262 Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
92a42be0
SL
263}
264
265void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
266 GET_REPORT_OPTIONS(true);
267 handleBuiltinUnreachableImpl(Data, Opts);
1a4d82fc
JJ
268 Die();
269}
270
92a42be0
SL
271static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
272 ScopedReport R(Opts, Data->Loc, ErrorType::MissingReturn);
1a4d82fc
JJ
273 Diag(Data->Loc, DL_Error,
274 "execution reached the end of a value-returning function "
275 "without returning a value");
92a42be0
SL
276}
277
278void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
279 GET_REPORT_OPTIONS(true);
280 handleMissingReturnImpl(Data, Opts);
1a4d82fc
JJ
281 Die();
282}
283
92a42be0
SL
284static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
285 ReportOptions Opts) {
1a4d82fc 286 SourceLocation Loc = Data->Loc.acquire();
92a42be0 287 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
288 return;
289
92a42be0
SL
290 ScopedReport R(Opts, Loc, ErrorType::NonPositiveVLAIndex);
291
1a4d82fc
JJ
292 Diag(Loc, DL_Error, "variable length array bound evaluates to "
293 "non-positive value %0")
294 << Value(Data->Type, Bound);
295}
92a42be0
SL
296
297void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
298 ValueHandle Bound) {
299 GET_REPORT_OPTIONS(false);
300 handleVLABoundNotPositive(Data, Bound, Opts);
301}
1a4d82fc 302void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
92a42be0
SL
303 ValueHandle Bound) {
304 GET_REPORT_OPTIONS(true);
305 handleVLABoundNotPositive(Data, Bound, Opts);
1a4d82fc
JJ
306 Die();
307}
308
92a42be0
SL
309static bool looksLikeFloatCastOverflowDataV1(void *Data) {
310 // First field is either a pointer to filename or a pointer to a
311 // TypeDescriptor.
312 u8 *FilenameOrTypeDescriptor;
313 internal_memcpy(&FilenameOrTypeDescriptor, Data,
314 sizeof(FilenameOrTypeDescriptor));
315
316 // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
317 // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
318 // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
319 // adding two printable characters will not yield such a value. Otherwise,
320 // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
321 u16 MaybeFromTypeKind =
322 FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
323 return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
324 FilenameOrTypeDescriptor[1] == 0xff;
325}
326
327static void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
328 ReportOptions Opts) {
329 SymbolizedStackHolder CallerLoc;
330 Location Loc;
331 const TypeDescriptor *FromType, *ToType;
332
333 if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
334 auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
335 CallerLoc.reset(getCallerLocation(Opts.pc));
336 Loc = CallerLoc;
337 FromType = &Data->FromType;
338 ToType = &Data->ToType;
339 } else {
340 auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
341 SourceLocation SLoc = Data->Loc.acquire();
342 if (ignoreReport(SLoc, Opts))
343 return;
344 Loc = SLoc;
345 FromType = &Data->FromType;
346 ToType = &Data->ToType;
347 }
348
349 ScopedReport R(Opts, Loc, ErrorType::FloatCastOverflow);
1a4d82fc 350
92a42be0 351 Diag(Loc, DL_Error,
1a4d82fc 352 "value %0 is outside the range of representable values of type %2")
92a42be0 353 << Value(*FromType, From) << *FromType << *ToType;
1a4d82fc 354}
92a42be0
SL
355
356void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
357 GET_REPORT_OPTIONS(false);
358 handleFloatCastOverflow(Data, From, Opts);
359}
360void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
361 ValueHandle From) {
362 GET_REPORT_OPTIONS(true);
363 handleFloatCastOverflow(Data, From, Opts);
1a4d82fc
JJ
364 Die();
365}
366
92a42be0
SL
367static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
368 ReportOptions Opts) {
1a4d82fc 369 SourceLocation Loc = Data->Loc.acquire();
92a42be0 370 if (ignoreReport(Loc, Opts))
1a4d82fc
JJ
371 return;
372
92a42be0
SL
373 // This check could be more precise if we used different handlers for
374 // -fsanitize=bool and -fsanitize=enum.
375 bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'"));
376 ScopedReport R(Opts, Loc, IsBool ? ErrorType::InvalidBoolLoad
377 : ErrorType::InvalidEnumLoad);
378
1a4d82fc
JJ
379 Diag(Loc, DL_Error,
380 "load of value %0, which is not a valid value for type %1")
381 << Value(Data->Type, Val) << Data->Type;
382}
92a42be0
SL
383
384void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
385 ValueHandle Val) {
386 GET_REPORT_OPTIONS(false);
387 handleLoadInvalidValue(Data, Val, Opts);
388}
1a4d82fc
JJ
389void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
390 ValueHandle Val) {
92a42be0
SL
391 GET_REPORT_OPTIONS(true);
392 handleLoadInvalidValue(Data, Val, Opts);
1a4d82fc
JJ
393 Die();
394}
395
92a42be0
SL
396static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
397 ValueHandle Function,
398 ReportOptions Opts) {
399 SourceLocation CallLoc = Data->Loc.acquire();
400 if (ignoreReport(CallLoc, Opts))
401 return;
1a4d82fc 402
92a42be0 403 ScopedReport R(Opts, CallLoc, ErrorType::FunctionTypeMismatch);
1a4d82fc 404
92a42be0
SL
405 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
406 const char *FName = FLoc.get()->info.function;
407 if (!FName)
408 FName = "(unknown)";
409
410 Diag(CallLoc, DL_Error,
1a4d82fc 411 "call to function %0 through pointer to incorrect function type %1")
92a42be0
SL
412 << FName << Data->Type;
413 Diag(FLoc, DL_Note, "%0 defined here") << FName;
414}
415
416void
417__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
418 ValueHandle Function) {
419 GET_REPORT_OPTIONS(false);
420 handleFunctionTypeMismatch(Data, Function, Opts);
1a4d82fc
JJ
421}
422
423void __ubsan::__ubsan_handle_function_type_mismatch_abort(
92a42be0
SL
424 FunctionTypeMismatchData *Data, ValueHandle Function) {
425 GET_REPORT_OPTIONS(true);
426 handleFunctionTypeMismatch(Data, Function, Opts);
427 Die();
428}
429
430static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) {
431 SourceLocation Loc = Data->Loc.acquire();
432 if (ignoreReport(Loc, Opts))
433 return;
434
435 ScopedReport R(Opts, Loc, ErrorType::InvalidNullReturn);
436
437 Diag(Loc, DL_Error, "null pointer returned from function declared to never "
438 "return null");
439 if (!Data->AttrLoc.isInvalid())
440 Diag(Data->AttrLoc, DL_Note, "returns_nonnull attribute specified here");
441}
442
443void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) {
444 GET_REPORT_OPTIONS(false);
445 handleNonNullReturn(Data, Opts);
446}
447
448void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) {
449 GET_REPORT_OPTIONS(true);
450 handleNonNullReturn(Data, Opts);
451 Die();
452}
453
454static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) {
455 SourceLocation Loc = Data->Loc.acquire();
456 if (ignoreReport(Loc, Opts))
457 return;
458
459 ScopedReport R(Opts, Loc, ErrorType::InvalidNullArgument);
460
461 Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to "
462 "never be null") << Data->ArgIndex;
463 if (!Data->AttrLoc.isInvalid())
464 Diag(Data->AttrLoc, DL_Note, "nonnull attribute specified here");
465}
466
467void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
468 GET_REPORT_OPTIONS(false);
469 handleNonNullArg(Data, Opts);
470}
471
472void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
473 GET_REPORT_OPTIONS(true);
474 handleNonNullArg(Data, Opts);
475 Die();
476}
477
478static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function,
479 ReportOptions Opts) {
480 SourceLocation Loc = Data->Loc.acquire();
481 if (ignoreReport(Loc, Opts))
482 return;
483
484 ScopedReport R(Opts, Loc);
485
486 Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
487 "indirect function call")
488 << Data->Type;
489
490 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
491 const char *FName = FLoc.get()->info.function;
492 if (!FName)
493 FName = "(unknown)";
494 Diag(FLoc, DL_Note, "%0 defined here") << FName;
495}
496
497void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data,
498 ValueHandle Function) {
499 GET_REPORT_OPTIONS(false);
500 handleCFIBadIcall(Data, Function, Opts);
501}
502
503void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data,
504 ValueHandle Function) {
505 GET_REPORT_OPTIONS(true);
506 handleCFIBadIcall(Data, Function, Opts);
1a4d82fc
JJ
507 Die();
508}
92a42be0
SL
509
510#endif // CAN_SANITIZE_UB