diff --git a/compiler-rt/lib/dfsan/dfsan.h b/compiler-rt/lib/dfsan/dfsan.h --- a/compiler-rt/lib/dfsan/dfsan.h +++ b/compiler-rt/lib/dfsan/dfsan.h @@ -36,6 +36,12 @@ // Zero out the TLS storage. void dfsan_clear_thread_local_state(); +// Set DFSan label and origin TLS of argument for a call. +// Note that offset may not correspond with argument number. +// Some arguments (aggregate/array) will use several offsets. +void dfsan_set_arg_tls(uptr offset, dfsan_label label); +void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o); + // Return the origin associated with the first taint byte in the size bytes // from the address addr. dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, uptr size); diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp --- a/compiler-rt/lib/dfsan/dfsan.cpp +++ b/compiler-rt/lib/dfsan/dfsan.cpp @@ -937,6 +937,20 @@ } } +SANITIZER_INTERFACE_ATTRIBUTE +void dfsan_set_arg_tls(uptr offset, dfsan_label label) { + // 2x to match ShadowTLSAlignment. + // ShadowTLSAlignment should probably be changed. + // TODO: Consider reducing ShadowTLSAlignment to 1. + // Aligning to 2 bytes is probably a remnant of fast16 mode. + ((dfsan_label *)__dfsan_arg_tls)[offset * 2] = label; +} + +SANITIZER_INTERFACE_ATTRIBUTE +void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o) { + __dfsan_arg_origin_tls[offset] = o; +} + extern "C" void dfsan_flush() { const uptr maxVirtualAddress = GetMaxUserVirtualAddress(); for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { @@ -1106,7 +1120,7 @@ dfsan_allocator_init(); - DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr, nullptr); + DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr); SetCurrentThread(main_thread); main_thread->Init(); diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -753,7 +753,6 @@ } static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *start_routine_trampoline, void *start_routine, void *arg, dfsan_label *ret_label, bool track_origins = false) { @@ -767,8 +766,7 @@ AdjustStackSize((void *)(const_cast(attr))); DFsanThread *t = - DFsanThread::Create(start_routine_trampoline, - (thread_callback_t)start_routine, arg, track_origins); + DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins); ScopedBlockSignals block(&t->starting_sigset_); int res = pthread_create(thread, attr, DFsanThreadStartFunc, t); @@ -779,28 +777,22 @@ } SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create( - pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine_trampoline)(void *, void *, dfsan_label, - dfsan_label *), - void *start_routine, void *arg, dfsan_label thread_label, - dfsan_label attr_label, dfsan_label start_routine_label, - dfsan_label arg_label, dfsan_label *ret_label) { - return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline, - start_routine, arg, ret_label); + pthread_t *thread, const pthread_attr_t *attr, void *start_routine, + void *arg, dfsan_label thread_label, dfsan_label attr_label, + dfsan_label start_routine_label, dfsan_label arg_label, + dfsan_label *ret_label) { + return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label); } SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create( - pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine_trampoline)(void *, void *, dfsan_label, - dfsan_label *, dfsan_origin, - dfsan_origin *), - void *start_routine, void *arg, dfsan_label thread_label, - dfsan_label attr_label, dfsan_label start_routine_label, - dfsan_label arg_label, dfsan_label *ret_label, dfsan_origin thread_origin, + pthread_t *thread, const pthread_attr_t *attr, void *start_routine, + void *arg, dfsan_label thread_label, dfsan_label attr_label, + dfsan_label start_routine_label, dfsan_label arg_label, + dfsan_label *ret_label, dfsan_origin thread_origin, dfsan_origin attr_origin, dfsan_origin start_routine_origin, dfsan_origin arg_origin, dfsan_origin *ret_origin) { - return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline, - start_routine, arg, ret_label, true); + return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label, + true); } SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread, @@ -825,22 +817,7 @@ } struct dl_iterate_phdr_info { - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label); - void *callback; - void *data; -}; - -struct dl_iterate_phdr_origin_info { - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label, dfsan_origin info_origin, - dfsan_origin size_origin, dfsan_origin data_origin, - dfsan_origin *ret_origin); - void *callback; + int (*callback)(struct dl_phdr_info *info, size_t size, void *data); void *data; }; @@ -852,53 +829,28 @@ dfsan_set_label( 0, const_cast(reinterpret_cast(info->dlpi_phdr)), sizeof(*info->dlpi_phdr) * info->dlpi_phnum); - dfsan_label ret_label; - return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0, - 0, &ret_label); -} -int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size, - void *data) { - dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data; - dfsan_set_label(0, *info); - dfsan_set_label(0, const_cast(info->dlpi_name), - strlen(info->dlpi_name) + 1); - dfsan_set_label( - 0, const_cast(reinterpret_cast(info->dlpi_phdr)), - sizeof(*info->dlpi_phdr) * info->dlpi_phnum); - dfsan_label ret_label; - dfsan_origin ret_origin; - return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0, - 0, &ret_label, 0, 0, 0, &ret_origin); + dfsan_clear_thread_local_state(); + return dipi->callback(info, size, dipi->data); } SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr( - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label), - void *callback, void *data, dfsan_label callback_label, - dfsan_label data_label, dfsan_label *ret_label) { - dl_iterate_phdr_info dipi = { callback_trampoline, callback, data }; + int (*callback)(struct dl_phdr_info *info, size_t size, void *data), + void *data, dfsan_label callback_label, dfsan_label data_label, + dfsan_label *ret_label) { + dl_iterate_phdr_info dipi = {callback, data}; *ret_label = 0; return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); } SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr( - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label, dfsan_origin info_origin, - dfsan_origin size_origin, - dfsan_origin data_origin, - dfsan_origin *ret_origin), - void *callback, void *data, dfsan_label callback_label, - dfsan_label data_label, dfsan_label *ret_label, - dfsan_origin callback_origin, dfsan_origin data_origin, - dfsan_origin *ret_origin) { - dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data}; + int (*callback)(struct dl_phdr_info *info, size_t size, void *data), + void *data, dfsan_label callback_label, dfsan_label data_label, + dfsan_label *ret_label, dfsan_origin callback_origin, + dfsan_origin data_origin, dfsan_origin *ret_origin) { + dl_iterate_phdr_info dipi = {callback, data}; *ret_label = 0; - return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi); + return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); } // This function is only available for glibc 2.27 or newer. Mark it weak so @@ -1629,10 +1581,7 @@ SignalHandlerScope signal_handler_scope; ScopedClearThreadLocalState scoped_clear_tls; - // Clear shadows for all inputs provided by system. This is why DFSan - // instrumentation generates a trampoline function to each function pointer, - // and uses the trampoline to clear shadows. However sigaction does not use - // a function pointer directly, so we have to do this manually. + // Clear shadows for all inputs provided by system. dfsan_clear_arg_tls(0, sizeof(dfsan_label)); typedef void (*signal_cb)(int x); @@ -1733,22 +1682,18 @@ } SANITIZER_INTERFACE_ATTRIBUTE -sighandler_t __dfsw_signal(int signum, - void *(*handler_trampoline)(void *, int, dfsan_label, - dfsan_label *), - sighandler_t handler, dfsan_label signum_label, - dfsan_label handler_label, dfsan_label *ret_label) { +sighandler_t __dfsw_signal(int signum, sighandler_t handler, + dfsan_label signum_label, dfsan_label handler_label, + dfsan_label *ret_label) { return dfsan_signal(signum, handler, ret_label); } SANITIZER_INTERFACE_ATTRIBUTE -sighandler_t __dfso_signal( - int signum, - void *(*handler_trampoline)(void *, int, dfsan_label, dfsan_label *, - dfsan_origin, dfsan_origin *), - sighandler_t handler, dfsan_label signum_label, dfsan_label handler_label, - dfsan_label *ret_label, dfsan_origin signum_origin, - dfsan_origin handler_origin, dfsan_origin *ret_origin) { +sighandler_t __dfso_signal(int signum, sighandler_t handler, + dfsan_label signum_label, dfsan_label handler_label, + dfsan_label *ret_label, dfsan_origin signum_origin, + dfsan_origin handler_origin, + dfsan_origin *ret_origin) { return dfsan_signal(signum, handler, ret_label); } @@ -2088,47 +2033,62 @@ addrlen_label, ret_label); } -// Type of the trampoline function passed to the custom version of -// dfsan_set_write_callback. -typedef void (*write_trampoline_t)( - void *callback, - int fd, const void *buf, ssize_t count, - dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label); - -typedef void (*write_origin_trampoline_t)( - void *callback, int fd, const void *buf, ssize_t count, - dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, - dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin); +// Type of the function passed to dfsan_set_write_callback. +typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count); // Calls to dfsan_set_write_callback() set the values in this struct. // Calls to the custom version of write() read (and invoke) them. static struct { - write_trampoline_t write_callback_trampoline = nullptr; - void *write_callback = nullptr; + write_dfsan_callback_t write_callback = nullptr; } write_callback_info; -static struct { - write_origin_trampoline_t write_callback_trampoline = nullptr; - void *write_callback = nullptr; -} write_origin_callback_info; - -SANITIZER_INTERFACE_ATTRIBUTE void -__dfsw_dfsan_set_write_callback( - write_trampoline_t write_callback_trampoline, - void *write_callback, - dfsan_label write_callback_label, +SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback( + write_dfsan_callback_t write_callback, dfsan_label write_callback_label, dfsan_label *ret_label) { - write_callback_info.write_callback_trampoline = write_callback_trampoline; write_callback_info.write_callback = write_callback; } SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback( - write_origin_trampoline_t write_callback_trampoline, void *write_callback, - dfsan_label write_callback_label, dfsan_label *ret_label, - dfsan_origin write_callback_origin, dfsan_origin *ret_origin) { - write_origin_callback_info.write_callback_trampoline = - write_callback_trampoline; - write_origin_callback_info.write_callback = write_callback; + write_dfsan_callback_t write_callback, dfsan_label write_callback_label, + dfsan_label *ret_label, dfsan_origin write_callback_origin, + dfsan_origin *ret_origin) { + write_callback_info.write_callback = write_callback; +} + +static inline void setup_tls_args_for_write_callback( + dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, + bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin, + dfsan_origin count_origin) { + // The callback code will expect argument shadow labels in the args TLS, + // and origin labels in the origin args TLS. + // Previously this was done by a trampoline, but we want to remove this: + // https://github.com/llvm/llvm-project/issues/54172 + // + // Instead, this code is manually setting up the args TLS data. + // + // The offsets used need to correspond with the instrumentation code, + // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp + // DFSanFunction::getShadowForTLSArgument. + // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684 + // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125 + // + // Here the arguments are all primitives, but it can be more complex + // to compute offsets for array/aggregate type arguments. + // + // TODO(browneee): Consider a builtin to improve maintainabliity. + // With a builtin, we would provide the argument labels via builtin, + // and the builtin would reuse parts of the instrumentation code to ensure + // that this code and the instrumentation can never be out of sync. + // Note: Currently DFSan instrumentation does not run on this code, so + // the builtin may need to be handled outside DFSan instrumentation. + dfsan_set_arg_tls(0, fd_label); + dfsan_set_arg_tls(1, buf_label); + dfsan_set_arg_tls(2, count_label); + if (origins) { + dfsan_set_arg_origin_tls(0, fd_origin); + dfsan_set_arg_origin_tls(1, buf_origin); + dfsan_set_arg_origin_tls(2, count_origin); + } } SANITIZER_INTERFACE_ATTRIBUTE int @@ -2136,10 +2096,9 @@ dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label) { if (write_callback_info.write_callback) { - write_callback_info.write_callback_trampoline( - write_callback_info.write_callback, - fd, buf, count, - fd_label, buf_label, count_label); + setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false, + 0, 0, 0); + write_callback_info.write_callback(fd, buf, count); } *ret_label = 0; @@ -2151,10 +2110,10 @@ dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, dfsan_origin *ret_origin) { - if (write_origin_callback_info.write_callback) { - write_origin_callback_info.write_callback_trampoline( - write_origin_callback_info.write_callback, fd, buf, count, fd_label, - buf_label, count_label, fd_origin, buf_origin, count_origin); + if (write_callback_info.write_callback) { + setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true, + fd_origin, buf_origin, count_origin); + write_callback_info.write_callback(fd, buf, count); } *ret_label = 0; diff --git a/compiler-rt/lib/dfsan/dfsan_thread.h b/compiler-rt/lib/dfsan/dfsan_thread.h --- a/compiler-rt/lib/dfsan/dfsan_thread.h +++ b/compiler-rt/lib/dfsan/dfsan_thread.h @@ -24,8 +24,7 @@ // NOTE: There is no DFsanThread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. - static DFsanThread *Create(void *start_routine_trampoline, - thread_callback_t start_routine, void *arg, + static DFsanThread *Create(thread_callback_t start_routine, void *arg, bool track_origins = false); static void TSDDtor(void *tsd); void Destroy(); @@ -59,7 +58,6 @@ bool AddrIsInStack(uptr addr); - void *start_routine_trampoline_; thread_callback_t start_routine_; void *arg_; bool track_origins_; diff --git a/compiler-rt/lib/dfsan/dfsan_thread.cpp b/compiler-rt/lib/dfsan/dfsan_thread.cpp --- a/compiler-rt/lib/dfsan/dfsan_thread.cpp +++ b/compiler-rt/lib/dfsan/dfsan_thread.cpp @@ -7,13 +7,11 @@ namespace __dfsan { -DFsanThread *DFsanThread::Create(void *start_routine_trampoline, - thread_callback_t start_routine, void *arg, +DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg, bool track_origins) { uptr PageSize = GetPageSizeCached(); uptr size = RoundUpTo(sizeof(DFsanThread), PageSize); DFsanThread *thread = (DFsanThread *)MmapOrDie(size, __func__); - thread->start_routine_trampoline_ = start_routine_trampoline; thread->start_routine_ = start_routine; thread->arg_ = arg; thread->track_origins_ = track_origins; @@ -74,23 +72,15 @@ return 0; } - CHECK(start_routine_trampoline_); + // The only argument is void* arg. + // + // We have never supported propagating the pointer arg as tainted, + // __dfsw_pthread_create/__dfso_pthread_create ignore the taint label. + // Note that the bytes pointed-to (probably the much more common case) + // can still have taint labels attached to them. + dfsan_clear_thread_local_state(); - typedef void *(*thread_callback_trampoline_t)(void *, void *, dfsan_label, - dfsan_label *); - typedef void *(*thread_callback_origin_trampoline_t)( - void *, void *, dfsan_label, dfsan_label *, dfsan_origin, dfsan_origin *); - - dfsan_label ret_label; - if (!track_origins_) - return ((thread_callback_trampoline_t) - start_routine_trampoline_)((void *)start_routine_, arg_, 0, - &ret_label); - - dfsan_origin ret_origin; - return ((thread_callback_origin_trampoline_t) - start_routine_trampoline_)((void *)start_routine_, arg_, 0, - &ret_label, 0, &ret_origin); + return start_routine_(arg_); } DFsanThread::StackBounds DFsanThread::GetStackBounds() const { diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -480,14 +480,12 @@ bool isInstrumented(const Function *F); bool isInstrumented(const GlobalAlias *GA); bool isForceZeroLabels(const Function *F); - FunctionType *getTrampolineFunctionType(FunctionType *T); TransformedFunction getCustomFunctionType(FunctionType *T); WrapperKind getWrapperKind(Function *F); void addGlobalNameSuffix(GlobalValue *GV); Function *buildWrapperFunction(Function *F, StringRef NewFName, GlobalValue::LinkageTypes NewFLink, FunctionType *NewFT); - Constant *getOrBuildTrampolineFunction(FunctionType *FT, StringRef FName); void initializeCallbackFunctions(Module &M); void initializeRuntimeFunctions(Module &M); void injectMetadataGlobals(Module &M); @@ -794,25 +792,6 @@ SpecialCaseList::createOrDie(AllABIListFiles, *vfs::getRealFileSystem())); } -FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) { - assert(!T->isVarArg()); - SmallVector ArgTypes; - ArgTypes.push_back(T->getPointerTo()); - ArgTypes.append(T->param_begin(), T->param_end()); - ArgTypes.append(T->getNumParams(), PrimitiveShadowTy); - Type *RetType = T->getReturnType(); - if (!RetType->isVoidTy()) - ArgTypes.push_back(PrimitiveShadowPtrTy); - - if (shouldTrackOrigins()) { - ArgTypes.append(T->getNumParams(), OriginTy); - if (!RetType->isVoidTy()) - ArgTypes.push_back(OriginPtrTy); - } - - return FunctionType::get(T->getReturnType(), ArgTypes, false); -} - TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { SmallVector ArgTypes; @@ -824,15 +803,8 @@ for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) { Type *ParamType = T->getParamType(I); FunctionType *FT; - if (isa(ParamType) && - (FT = dyn_cast(ParamType->getPointerElementType()))) { - ArgumentIndexMapping.push_back(ArgTypes.size()); - ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo()); - ArgTypes.push_back(Type::getInt8PtrTy(*Ctx)); - } else { - ArgumentIndexMapping.push_back(ArgTypes.size()); - ArgTypes.push_back(ParamType); - } + ArgumentIndexMapping.push_back(ArgTypes.size()); + ArgTypes.push_back(ParamType); } for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) ArgTypes.push_back(PrimitiveShadowTy); @@ -1181,61 +1153,6 @@ return NewF; } -Constant *DataFlowSanitizer::getOrBuildTrampolineFunction(FunctionType *FT, - StringRef FName) { - FunctionType *FTT = getTrampolineFunctionType(FT); - FunctionCallee C = Mod->getOrInsertFunction(FName, FTT); - Function *F = dyn_cast(C.getCallee()); - if (F && F->isDeclaration()) { - F->setLinkage(GlobalValue::LinkOnceODRLinkage); - BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); - std::vector Args; - Function::arg_iterator AI = F->arg_begin() + 1; - for (unsigned N = FT->getNumParams(); N != 0; ++AI, --N) - Args.push_back(&*AI); - CallInst *CI = CallInst::Create(FT, &*F->arg_begin(), Args, "", BB); - Type *RetType = FT->getReturnType(); - ReturnInst *RI = RetType->isVoidTy() ? ReturnInst::Create(*Ctx, BB) - : ReturnInst::Create(*Ctx, CI, BB); - - // F is called by a wrapped custom function with primitive shadows. So - // its arguments and return value need conversion. - DFSanFunction DFSF(*this, F, /*IsNativeABI=*/true, - /*IsForceZeroLabels=*/false); - Function::arg_iterator ValAI = F->arg_begin(), ShadowAI = AI; - ++ValAI; - for (unsigned N = FT->getNumParams(); N != 0; ++ValAI, ++ShadowAI, --N) { - Value *Shadow = - DFSF.expandFromPrimitiveShadow(ValAI->getType(), &*ShadowAI, CI); - DFSF.ValShadowMap[&*ValAI] = Shadow; - } - Function::arg_iterator RetShadowAI = ShadowAI; - const bool ShouldTrackOrigins = shouldTrackOrigins(); - if (ShouldTrackOrigins) { - ValAI = F->arg_begin(); - ++ValAI; - Function::arg_iterator OriginAI = ShadowAI; - if (!RetType->isVoidTy()) - ++OriginAI; - for (unsigned N = FT->getNumParams(); N != 0; ++ValAI, ++OriginAI, --N) { - DFSF.ValOriginMap[&*ValAI] = &*OriginAI; - } - } - DFSanVisitor(DFSF).visitCallInst(*CI); - if (!RetType->isVoidTy()) { - Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow( - DFSF.getShadow(RI->getReturnValue()), RI); - new StoreInst(PrimitiveShadow, &*RetShadowAI, RI); - if (ShouldTrackOrigins) { - Value *Origin = DFSF.getOrigin(RI->getReturnValue()); - new StoreInst(Origin, &*std::prev(F->arg_end()), RI); - } - } - } - - return cast(C.getCallee()); -} - // Initialize DataFlowSanitizer runtime functions and declare them in the module void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) { { @@ -2907,20 +2824,7 @@ for (unsigned N = FT->getNumParams(); N != 0; ++I, --N) { Type *T = (*I)->getType(); FunctionType *ParamFT; - if (isa(T) && - (ParamFT = dyn_cast(T->getPointerElementType()))) { - std::string TName = "dfst"; - TName += utostr(FT->getNumParams() - N); - TName += "$"; - TName += F.getName(); - Constant *Trampoline = - DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName); - Args.push_back(Trampoline); - Args.push_back( - IRB.CreateBitCast(*I, Type::getInt8PtrTy(*DFSF.DFS.Ctx))); - } else { - Args.push_back(*I); - } + Args.push_back(*I); } // Adds shadow arguments. diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/abilist.ll b/llvm/test/Instrumentation/DataFlowSanitizer/abilist.ll --- a/llvm/test/Instrumentation/DataFlowSanitizer/abilist.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/abilist.ll @@ -42,7 +42,7 @@ ; CHECK: call i32 @__dfsw_custom2(i32 1, i32 2, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext 0, i[[#SBITS]]* %[[LABELRETURN]]) call i32 @custom2(i32 1, i32 2) - ; CHECK: call void @__dfsw_customcb({{.*}} @"dfst0$customcb", i8* bitcast ({{.*}} @cb.dfsan to i8*), i[[#SBITS]] zeroext 0) + ; CHECK: call void @__dfsw_customcb({{.*}} @cb.dfsan, i[[#SBITS]] zeroext 0) call void @customcb(i32 (i32)* @cb) ; CHECK: %[[LABELVA1_0:.*]] = getelementptr inbounds [2 x i[[#SBITS]]], [2 x i[[#SBITS]]]* %[[LABELVA1]], i32 0, i32 0 @@ -93,12 +93,5 @@ ; CHECK: declare void @__dfsw_custom1(i32, i32, i[[#SBITS]], i[[#SBITS]]) ; CHECK: declare i32 @__dfsw_custom2(i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*) -; CHECK-LABEL: define linkonce_odr i32 @"dfst0$customcb" -; CHECK-SAME: (i32 (i32)* %0, i32 %1, i[[#SBITS]] %2, i[[#SBITS]]* %3) -; CHECK: %[[CALL:.*]] = call i32 %0(i32 %1) -; CHECK: %[[RVSHADOW2:.*]] = load i[[#SBITS]], {{.*}} @__dfsan_retval_tls -; CHECK: store i[[#SBITS]] %[[RVSHADOW2]], i[[#SBITS]]* %3 -; CHECK: ret i32 %[[CALL]] - ; CHECK: declare void @__dfsw_custom3(i32, i[[#SBITS]], i[[#SBITS]]*, ...) ; CHECK: declare i32 @__dfsw_custom4(i32, i[[#SBITS]], i[[#SBITS]]*, i[[#SBITS]]*, ...) diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/abilist_aggregate.ll b/llvm/test/Instrumentation/DataFlowSanitizer/abilist_aggregate.ll --- a/llvm/test/Instrumentation/DataFlowSanitizer/abilist_aggregate.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/abilist_aggregate.ll @@ -137,7 +137,7 @@ ; CHECK: [[B0:%.*]] = extractvalue [2 x i[[#SBITS]]] [[B]], 0 ; CHECK: [[B1:%.*]] = extractvalue [2 x i[[#SBITS]]] [[B]], 1 ; CHECK: [[B01:%.*]] = or i[[#SBITS]] [[B0]], [[B1]] - ; CHECK: [[R:%.*]] = call { i1, i7 } @__dfsw_custom_cb({ i1, i7 } ({ i1, i7 } ({ i32, i1 }, [2 x i7])*, { i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*)* @"dfst0$custom_cb", i8* bitcast ({ i1, i7 } ({ i32, i1 }, [2 x i7])* @cb.dfsan to i8*), { i32, i1 } %a, [2 x i7] %b, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext [[A01]], i[[#SBITS]] zeroext [[B01]], i[[#SBITS]]* %labelreturn) + ; CHECK: [[R:%.*]] = call { i1, i7 } @__dfsw_custom_cb({ i1, i7 } ({ i32, i1 }, [2 x i7])* @cb.dfsan, { i32, i1 } %a, [2 x i7] %b, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext [[A01]], i[[#SBITS]] zeroext [[B01]], i[[#SBITS]]* %labelreturn) ; CHECK: [[RE:%.*]] = load i[[#SBITS]], i[[#SBITS]]* %labelreturn, align [[#SBYTES]] ; CHECK: [[RS0:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } undef, i[[#SBITS]] [[RE]], 0 ; CHECK: [[RS1:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[RS0]], i[[#SBITS]] [[RE]], 1 @@ -186,20 +186,18 @@ ; CHECK: [[B:%.*]] = load [2 x i[[#SBITS]]], [2 x i[[#SBITS]]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 [[#mul(2,SBYTES) + max(SBYTES,2)]]) to [2 x i[[#SBITS]]]*), align [[ALIGN:2]] ; CHECK: [[A:%.*]] = load { i[[#SBITS]], i[[#SBITS]] }, { i[[#SBITS]], i[[#SBITS]] }* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]] ; CHECK: [[CB:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]] -; CHECK: [[CAST:%.*]] = bitcast { i1, i7 } ({ i32, i1 }, [2 x i7])* %0 to i8* ; CHECK: [[A0:%.*]] = extractvalue { i[[#SBITS]], i[[#SBITS]] } [[A]], 0 ; CHECK: [[A1:%.*]] = extractvalue { i[[#SBITS]], i[[#SBITS]] } [[A]], 1 ; CHECK: [[A01:%.*]] = or i[[#SBITS]] [[A0]], [[A1]] ; CHECK: [[B0:%.*]] = extractvalue [2 x i[[#SBITS]]] [[B]], 0 ; CHECK: [[B1:%.*]] = extractvalue [2 x i[[#SBITS]]] [[B]], 1 ; CHECK: [[B01:%.*]] = or i[[#SBITS]] [[B0]], [[B1]] -; CHECK: [[R:%.*]] = call { i1, i7 } @__dfsw_custom_cb({ i1, i7 } ({ i1, i7 } ({ i32, i1 }, [2 x i7])*, { i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*)* @"dfst0$custom_cb", i8* [[CAST]], { i32, i1 } %1, [2 x i7] %2, i[[#SBITS]] zeroext [[CB]], i[[#SBITS]] zeroext [[A01]], i[[#SBITS]] zeroext [[B01]], i[[#SBITS]]* %labelreturn) +; CHECK: [[R:%.*]] = call { i1, i7 } @__dfsw_custom_cb({ i1, i7 } ({ i32, i1 }, [2 x i7])* %0, { i32, i1 } %1, [2 x i7] %2, i[[#SBITS]] zeroext [[CB]], i[[#SBITS]] zeroext [[A01]], i[[#SBITS]] zeroext [[B01]], i[[#SBITS]]* %labelreturn) ; CHECK: [[RE:%.*]] = load i[[#SBITS]], i[[#SBITS]]* %labelreturn, align [[#SBYTES]] ; CHECK: [[RS0:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } undef, i[[#SBITS]] [[RE]], 0 ; CHECK: [[RS1:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[RS0]], i[[#SBITS]] [[RE]], 1 ; CHECK: store { i[[#SBITS]], i[[#SBITS]] } [[RS1]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]] - define {i1, i7} @custom_with_ret({i32, i1} %a, [2 x i7] %b) { ; CHECK: define linkonce_odr { i1, i7 } @"dfsw$custom_with_ret"({ i32, i1 } %0, [2 x i7] %1) ; CHECK: %labelreturn = alloca i[[#SBITS]], align [[#SBYTES]] @@ -250,19 +248,4 @@ ; CHECK: declare void @__dfsw_custom_without_ret({ i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]]) ; CHECK: declare void @__dfsw_custom_varg({ i32, i1 }, i[[#SBITS]], i[[#SBITS]]*, ...) -; CHECK: declare { i1, i7 } @__dfsw_custom_cb({ i1, i7 } ({ i1, i7 } ({ i32, i1 }, [2 x i7])*, { i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*)*, i8*, { i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*) - -; CHECK: define linkonce_odr { i1, i7 } @"dfst0$custom_cb"({ i1, i7 } ({ i32, i1 }, [2 x i7])* %0, { i32, i1 } %1, [2 x i7] %2, i[[#SBITS]] %3, i[[#SBITS]] %4, i[[#SBITS]]* %5) { -; CHECK: [[A0:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } undef, i[[#SBITS]] %3, 0 -; CHECK: [[A1:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[A0]], i[[#SBITS]] %3, 1 -; CHECK: [[B0:%.*]] = insertvalue [2 x i[[#SBITS]]] undef, i[[#SBITS]] %4, 0 -; CHECK: [[B1:%.*]] = insertvalue [2 x i[[#SBITS]]] [[B0]], i[[#SBITS]] %4, 1 -; CHECK: store { i[[#SBITS]], i[[#SBITS]] } [[A1]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_arg_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN:2]] -; CHECK: store [2 x i[[#SBITS]]] [[B1]], [2 x i[[#SBITS]]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 [[#mul(2,SBYTES)]]) to [2 x i[[#SBITS]]]*), align [[ALIGN]] -; CHECK: [[R:%.*]] = call { i1, i7 } %0({ i32, i1 } %1, [2 x i7] %2) -; CHECK: %_dfsret = load { i[[#SBITS]], i[[#SBITS]] }, { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]] -; CHECK: [[RE0:%.*]] = extractvalue { i[[#SBITS]], i[[#SBITS]] } %_dfsret, 0 -; CHECK: [[RE1:%.*]] = extractvalue { i[[#SBITS]], i[[#SBITS]] } %_dfsret, 1 -; CHECK: [[RE01:%.*]] = or i[[#SBITS]] [[RE0]], [[RE1]] -; CHECK: store i[[#SBITS]] [[RE01]], i[[#SBITS]]* %5, align [[#SBYTES]] -; CHECK: ret { i1, i7 } [[R]] +; CHECK: declare { i1, i7 } @__dfsw_custom_cb({ i1, i7 } ({ i32, i1 }, [2 x i7])*, { i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*) diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/custom_fun_callback_attributes.ll b/llvm/test/Instrumentation/DataFlowSanitizer/custom_fun_callback_attributes.ll --- a/llvm/test/Instrumentation/DataFlowSanitizer/custom_fun_callback_attributes.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/custom_fun_callback_attributes.ll @@ -16,16 +16,13 @@ define void @call_custom_funs_with_callbacks(i8 (i32, double)* %callback_arg) { ;; The callback should have attribute 'nonnull': ; CHECK: call signext i32 @__dfsw_custom_fun_one_callback( - ; CHECK: nonnull @"dfst0$custom_fun_one_callback" %call1 = call signext i32 @custom_fun_one_callback( i8 (i32, double)* nonnull @a_callback_fun ) ;; Call a custom function with two callbacks. Check their annotations. ; CHECK: call i32 @__dfsw_custom_fun_two_callbacks( - ; CHECK: nonnull @"dfst0$custom_fun_two_callbacks" ; CHECK: i64 12345 - ; CHECK: noalias @"dfst2$custom_fun_two_callbacks" %call2 = call i32 @custom_fun_two_callbacks( i8 (i32, double)* nonnull @a_callback_fun, i64 12345, diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/origin_abilist.ll b/llvm/test/Instrumentation/DataFlowSanitizer/origin_abilist.ll --- a/llvm/test/Instrumentation/DataFlowSanitizer/origin_abilist.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/origin_abilist.ll @@ -199,7 +199,7 @@ ; CHECK: %labelreturn = alloca i[[#SBITS]], align [[#SBYTES]] ; CHECK: [[BS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align 2 ; CHECK: [[AS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align 2 - ; CHECK: {{.*}} = call i32 @__dfso_custom_cb_with_ret(i32 (i32 (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32*)* @"dfst0$custom_cb_with_ret", i8* bitcast (i32 (i32, i32)* @cb_with_ret.dfsan to i8*), i32 %a, i32 %b, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i[[#SBITS]]* %labelreturn, i32 zeroext 0, i32 zeroext [[AO]], i32 zeroext [[BO]], i32* %originreturn) + ; CHECK: {{.*}} = call i32 @__dfso_custom_cb_with_ret(i32 (i32, i32)* @cb_with_ret.dfsan, i32 %a, i32 %b, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i[[#SBITS]]* %labelreturn, i32 zeroext 0, i32 zeroext [[AO]], i32 zeroext [[BO]], i32* %originreturn) ; CHECK: [[RS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* %labelreturn, align [[#SBYTES]] ; CHECK: [[RO:%.*]] = load i32, i32* %originreturn, align 4 ; CHECK: store i[[#SBITS]] [[RS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align 2 @@ -215,7 +215,7 @@ ; CHECK: [[AO:%.*]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 ; CHECK: [[BS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align 2 ; CHECK: [[AS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align 2 - ; CHECK: call void @__dfso_custom_cb_without_ret(void (void (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i32, i32)* @"dfst0$custom_cb_without_ret", i8* bitcast (void (i32, i32)* @cb_without_ret.dfsan to i8*), i32 %a, i32 %b, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i32 zeroext 0, i32 zeroext [[AO]], i32 zeroext [[BO]]) + ; CHECK: call void @__dfso_custom_cb_without_ret(void (i32, i32)* @cb_without_ret.dfsan, i32 %a, i32 %b, i[[#SBITS]] zeroext 0, i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i32 zeroext 0, i32 zeroext [[AO]], i32 zeroext [[BO]]) ; CHECK-NEXT: ret void call void @custom_cb_without_ret(void (i32, i32)* @cb_without_ret, i32 %a, i32 %b) @@ -267,8 +267,7 @@ ; CHECK-NEXT: [[BS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 4) to i[[#SBITS]]*), align 2 ; CHECK-NEXT: [[AS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align 2 ; CHECK-NEXT: [[CS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align 2 -; CHECK-NEXT: [[C:%.*]] = bitcast i32 (i32, i32)* %0 to i8* -; CHECK-NEXT: [[R:%.*]] = call i32 @__dfso_custom_cb_with_ret(i32 (i32 (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32*)* @"dfst0$custom_cb_with_ret", i8* [[C]], i32 %1, i32 %2, i[[#SBITS]] zeroext [[CS]], i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i[[#SBITS]]* %labelreturn, i32 zeroext [[CO]], i32 zeroext [[AO]], i32 zeroext [[BO]], i32* %originreturn) +; CHECK-NEXT: [[R:%.*]] = call i32 @__dfso_custom_cb_with_ret(i32 (i32, i32)* %0, i32 %1, i32 %2, i[[#SBITS]] zeroext [[CS]], i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i[[#SBITS]]* %labelreturn, i32 zeroext [[CO]], i32 zeroext [[AO]], i32 zeroext [[BO]], i32* %originreturn) ; CHECK-NEXT: [[RS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* %labelreturn, align [[#SBYTES]] ; CHECK-NEXT: [[RO:%.*]] = load i32, i32* %originreturn, align 4 ; CHECK-NEXT: store i[[#SBITS]] [[RS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align 2 @@ -282,38 +281,17 @@ ; CHECK-NEXT: [[BS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 4) to i[[#SBITS]]*), align 2 ; CHECK-NEXT: [[AS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align 2 ; CHECK-NEXT: [[CS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align 2 -; CHECK-NEXT: [[C:%.*]] = bitcast void (i32, i32)* %0 to i8* -; CHECK-NEXT: call void @__dfso_custom_cb_without_ret(void (void (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i32, i32)* @"dfst0$custom_cb_without_ret", i8* [[C]], i32 %1, i32 %2, i[[#SBITS]] zeroext [[CS]], i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i32 zeroext [[CO]], i32 zeroext [[AO]], i32 zeroext [[BO]]) +; CHECK-NEXT: call void @__dfso_custom_cb_without_ret(void (i32, i32)* %0, i32 %1, i32 %2, i[[#SBITS]] zeroext [[CS]], i[[#SBITS]] zeroext [[AS]], i[[#SBITS]] zeroext [[BS]], i32 zeroext [[CO]], i32 zeroext [[AO]], i32 zeroext [[BO]]) ; CHECK-NEXT: ret void ; CHECK: declare void @__dfso_custom_without_ret(i32, i32, i[[#SBITS]], i[[#SBITS]], i32, i32) ; CHECK: declare i32 @__dfso_custom_with_ret(i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32*) -; CHECK: declare i32 @__dfso_custom_cb_with_ret(i32 (i32 (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32*)*, i8*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32, i32*) - -; CHECK: define linkonce_odr i32 @"dfst0$custom_cb_with_ret"(i32 (i32, i32)* %0, i32 %1, i32 %2, i[[#SBITS]] %3, i[[#SBITS]] %4, i[[#SBITS]]* %5, i32 %6, i32 %7, i32* %8) -; CHECK: store i32 %6, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 -; CHECK-NEXT: store i[[#SBITS]] %3, i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align 2 -; CHECK-NEXT: store i32 %7, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 -; CHECK-NEXT: store i[[#SBITS]] %4, i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align 2 -; CHECK-NEXT: %9 = call i32 %0(i32 %1, i32 %2) -; CHECK-NEXT: %_dfsret = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align 2 -; CHECK-NEXT: %_dfsret_o = load i32, i32* @__dfsan_retval_origin_tls, align 4 -; CHECK-NEXT: store i[[#SBITS]] %_dfsret, i[[#SBITS]]* %5, align [[#SBYTES]] -; CHECK-NEXT: store i32 %_dfsret_o, i32* %8, align 4 -; CHECK-NEXT: ret i32 %9 - -; CHECK: declare void @__dfso_custom_cb_without_ret(void (void (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i32, i32)*, i8*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i32, i32, i32) - -; CHECK: define linkonce_odr void @"dfst0$custom_cb_without_ret"(void (i32, i32)* %0, i32 %1, i32 %2, i[[#SBITS]] %3, i[[#SBITS]] %4, i32 %5, i32 %6) -; CHECK: store i32 %5, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 -; CHECK-NEXT: store i[[#SBITS]] %3, i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align 2 -; CHECK-NEXT: store i32 %6, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 -; CHECK-NEXT: store i[[#SBITS]] %4, i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align 2 -; CHECK-NEXT: call void %0(i32 %1, i32 %2) -; CHECK-NEXT: ret void +; CHECK: declare i32 @__dfso_custom_cb_with_ret(i32 (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32, i32*) + +; CHECK: declare void @__dfso_custom_cb_without_ret(void (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i32, i32, i32) ; CHECK: declare void @__dfso_custom_varg_without_ret(i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, i32, i32*, ...) -; CHECK: declare i32 @__dfso_custom_varg_with_ret(i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i[[#SBITS]]*, i32, i32, i32*, i32*, ...) \ No newline at end of file +; CHECK: declare i32 @__dfso_custom_varg_with_ret(i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i[[#SBITS]]*, i32, i32, i32*, i32*, ...)