Skip to content

Commit adf6d32

Browse files
committed
[ubsan_minimal] Allow UBSan handler from Minimal runtime to acceprt arguments
Also renamed minimal-specific WEAK_DEF anchor from __ubsan_report_error to __ubsan_minimal_report_error. A new __ubsan_minimal_report_error accepts address of the variable being inspected.
1 parent 12da87b commit adf6d32

File tree

2 files changed

+92
-32
lines changed

2 files changed

+92
-32
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3717,6 +3717,33 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
37173717
}
37183718
}
37193719

3720+
// Adapts the arguments to the handler function.
3721+
// It is expected that {StaticArgs..., DynamicArgs...} sequence matches the
3722+
// corresponding XxxData type from the ubsan_handlers.h file.
3723+
// Minimal hadler can use a subset of the arguments.
3724+
static void
3725+
AdaptArgsToHandler(CodeGenModule &CGM, SanitizerHandler CheckHandler,
3726+
ArrayRef<llvm::Constant *> StaticArgs,
3727+
ArrayRef<llvm::Value *> DynamicArgs,
3728+
SmallVectorImpl<llvm::Constant *> &HandlerStaticArgs,
3729+
SmallVectorImpl<llvm::Value *> &HandlerDynamicArgs) {
3730+
if (!CGM.getCodeGenOpts().SanitizeMinimalRuntime) {
3731+
HandlerStaticArgs.assign(StaticArgs.begin(), StaticArgs.end());
3732+
HandlerDynamicArgs.assign(DynamicArgs.begin(), DynamicArgs.end());
3733+
return;
3734+
}
3735+
3736+
switch (CheckHandler) {
3737+
case SanitizerHandler::TypeMismatch:
3738+
// Pass value pointer only. It adds minimal overhead.
3739+
HandlerDynamicArgs.assign(DynamicArgs.begin(), DynamicArgs.end());
3740+
break;
3741+
default:
3742+
// No arguments for other checks.
3743+
break;
3744+
}
3745+
}
3746+
37203747
void CodeGenFunction::EmitCheck(
37213748
ArrayRef<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>> Checked,
37223749
SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs,
@@ -3794,28 +3821,37 @@ void CodeGenFunction::EmitCheck(
37943821
// representing operand values.
37953822
SmallVector<llvm::Value *, 4> Args;
37963823
SmallVector<llvm::Type *, 4> ArgTypes;
3797-
if (!CGM.getCodeGenOpts().SanitizeMinimalRuntime) {
3798-
Args.reserve(DynamicArgs.size() + 1);
3799-
ArgTypes.reserve(DynamicArgs.size() + 1);
3800-
3801-
// Emit handler arguments and create handler function type.
3802-
if (!StaticArgs.empty()) {
3803-
llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
3804-
auto *InfoPtr = new llvm::GlobalVariable(
3805-
CGM.getModule(), Info->getType(), false,
3806-
llvm::GlobalVariable::PrivateLinkage, Info, "", nullptr,
3807-
llvm::GlobalVariable::NotThreadLocal,
3808-
CGM.getDataLayout().getDefaultGlobalsAddressSpace());
3809-
InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
3810-
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
3811-
Args.push_back(InfoPtr);
3812-
ArgTypes.push_back(Args.back()->getType());
3813-
}
38143824

3815-
for (llvm::Value *DynamicArg : DynamicArgs) {
3816-
Args.push_back(EmitCheckValue(DynamicArg));
3817-
ArgTypes.push_back(IntPtrTy);
3818-
}
3825+
SmallVector<llvm::Constant *, 4> HandlerStaticArgs;
3826+
SmallVector<llvm::Value *, 4> HandlerDynamicArgs;
3827+
AdaptArgsToHandler(CGM, CheckHandler, StaticArgs, DynamicArgs,
3828+
HandlerStaticArgs, HandlerDynamicArgs);
3829+
3830+
Args.reserve(HandlerDynamicArgs.size() + 1);
3831+
ArgTypes.reserve(HandlerDynamicArgs.size() + 1);
3832+
3833+
// Emit handler arguments and create handler function type.
3834+
if (!HandlerStaticArgs.empty()) {
3835+
llvm::Constant *Info = llvm::ConstantStruct::getAnon(HandlerStaticArgs);
3836+
auto *InfoPtr = new llvm::GlobalVariable(
3837+
CGM.getModule(), Info->getType(),
3838+
// Non-constant global is used in non-minimal handler to deduplicate
3839+
// reports. Minimal handler stores history statically.
3840+
// TODO: make it constant for non-minimal handler.
3841+
/*isConstant=*/
3842+
CGM.getCodeGenOpts().SanitizeMinimalRuntime,
3843+
llvm::GlobalVariable::PrivateLinkage, Info, "", nullptr,
3844+
llvm::GlobalVariable::NotThreadLocal,
3845+
CGM.getDataLayout().getDefaultGlobalsAddressSpace());
3846+
InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
3847+
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
3848+
Args.push_back(InfoPtr);
3849+
ArgTypes.push_back(Args.back()->getType());
3850+
}
3851+
3852+
for (llvm::Value *DynamicArg : HandlerDynamicArgs) {
3853+
Args.push_back(EmitCheckValue(DynamicArg));
3854+
ArgTypes.push_back(IntPtrTy);
38193855
}
38203856

38213857
llvm::FunctionType *FnType =

compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,25 @@ static char *append_hex(uintptr_t d, char *buf, const char *end) {
3434
return buf;
3535
}
3636

37-
static void format_msg(const char *kind, uintptr_t caller, char *buf,
38-
const char *end) {
37+
static void format_msg(const char *kind, uintptr_t caller,
38+
const uintptr_t *address, char *buf, const char *end) {
3939
buf = append_str("ubsan: ", buf, end);
4040
buf = append_str(kind, buf, end);
4141
buf = append_str(" by 0x", buf, end);
4242
buf = append_hex(caller, buf, end);
43+
if (address) {
44+
buf = append_str(" address 0x", buf, end);
45+
buf = append_hex(*address, buf, end);
46+
}
4347
buf = append_str("\n", buf, end);
4448
if (buf == end)
4549
--buf; // Make sure we don't cause a buffer overflow.
4650
*buf = '\0';
4751
}
4852

49-
SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind,
50-
uintptr_t caller) {
53+
SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_minimal_report_error,
54+
const char *kind, uintptr_t caller,
55+
const uintptr_t *address) {
5156
if (caller == 0)
5257
return;
5358
while (true) {
@@ -80,15 +85,16 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind,
8085
__sanitizer::atomic_store_relaxed(&caller_pcs[sz], caller);
8186

8287
char msg_buf[128];
83-
format_msg(kind, caller, msg_buf, msg_buf + sizeof(msg_buf));
88+
format_msg(kind, caller, address, msg_buf, msg_buf + sizeof(msg_buf));
8489
message(msg_buf);
8590
}
8691
}
8792

88-
SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_fatal, const char *kind,
89-
uintptr_t caller) {
93+
SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_minimal_report_error_fatal,
94+
const char *kind, uintptr_t caller,
95+
const uintptr_t *address) {
9096
// Use another handlers, in case it's already overriden.
91-
__ubsan_report_error(kind, caller);
97+
__ubsan_minimal_report_error(kind, caller, address);
9298
}
9399

94100
#if defined(__ANDROID__)
@@ -121,21 +127,39 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
121127

122128
#define HANDLER_RECOVER(name, kind) \
123129
INTERFACE void __ubsan_handle_##name##_minimal() { \
124-
__ubsan_report_error(kind, GET_CALLER_PC()); \
130+
__ubsan_minimal_report_error(kind, GET_CALLER_PC(), nullptr); \
125131
}
126132

127133
#define HANDLER_NORECOVER(name, kind) \
128134
INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
129135
uintptr_t caller = GET_CALLER_PC(); \
130-
__ubsan_report_error_fatal(kind, caller); \
136+
__ubsan_minimal_report_error_fatal(kind, caller, nullptr); \
131137
abort_with_message(kind, caller); \
132138
}
133139

134140
#define HANDLER(name, kind) \
135141
HANDLER_RECOVER(name, kind) \
136142
HANDLER_NORECOVER(name, kind)
137143

138-
HANDLER(type_mismatch, "type-mismatch")
144+
#define HANDLER_RECOVER_PTR(name, kind) \
145+
INTERFACE void __ubsan_handle_##name##_minimal(const uintptr_t address) { \
146+
__ubsan_minimal_report_error(kind, GET_CALLER_PC(), &address); \
147+
}
148+
149+
#define HANDLER_NORECOVER_PTR(name, kind) \
150+
INTERFACE void __ubsan_handle_##name##_minimal_abort( \
151+
const uintptr_t address) { \
152+
uintptr_t caller = GET_CALLER_PC(); \
153+
__ubsan_minimal_report_error_fatal(kind, caller, &address); \
154+
abort_with_message(kind, caller); \
155+
}
156+
157+
// A version of a handler that takes a pointer to a value.
158+
#define HANDLER_PTR(name, kind) \
159+
HANDLER_RECOVER_PTR(name, kind) \
160+
HANDLER_NORECOVER_PTR(name, kind)
161+
162+
HANDLER_PTR(type_mismatch, "type-mismatch")
139163
HANDLER(alignment_assumption, "alignment-assumption")
140164
HANDLER(add_overflow, "add-overflow")
141165
HANDLER(sub_overflow, "sub-overflow")

0 commit comments

Comments
 (0)