forked from OSchip/llvm-project
Revert "[DFSan] Remove trampolines to unblock opaque pointers."
This reverts commit 84af90336f
.
This commit is contained in:
parent
003c0b9307
commit
edc33fa569
|
@ -937,20 +937,6 @@ void dfsan_clear_thread_local_state() {
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1120,7 +1106,7 @@ static void DFsanInit(int argc, char **argv, char **envp) {
|
|||
|
||||
dfsan_allocator_init();
|
||||
|
||||
DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr);
|
||||
DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr, nullptr);
|
||||
SetCurrentThread(main_thread);
|
||||
main_thread->Init();
|
||||
|
||||
|
|
|
@ -36,12 +36,6 @@ void dfsan_clear_arg_tls(uptr offset, uptr size);
|
|||
// 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);
|
||||
|
|
|
@ -753,6 +753,7 @@ static void *DFsanThreadStartFunc(void *arg) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -766,7 +767,8 @@ static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||
AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
|
||||
|
||||
DFsanThread *t =
|
||||
DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
|
||||
DFsanThread::Create(start_routine_trampoline,
|
||||
(thread_callback_t)start_routine, arg, track_origins);
|
||||
ScopedBlockSignals block(&t->starting_sigset_);
|
||||
int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
|
||||
|
||||
|
@ -777,22 +779,28 @@ static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
|
||||
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,
|
||||
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,
|
||||
dfsan_origin attr_origin, dfsan_origin start_routine_origin,
|
||||
dfsan_origin arg_origin, dfsan_origin *ret_origin) {
|
||||
return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
|
||||
true);
|
||||
return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
|
||||
start_routine, arg, ret_label, true);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
|
||||
|
@ -817,7 +825,22 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
|
|||
}
|
||||
|
||||
struct dl_iterate_phdr_info {
|
||||
int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
|
||||
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;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
@ -829,28 +852,53 @@ int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
|
|||
dfsan_set_label(
|
||||
0, const_cast<char *>(reinterpret_cast<const char *>(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);
|
||||
}
|
||||
|
||||
dfsan_clear_thread_local_state();
|
||||
return dipi->callback(info, size, dipi->data);
|
||||
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<char *>(info->dlpi_name),
|
||||
strlen(info->dlpi_name) + 1);
|
||||
dfsan_set_label(
|
||||
0, const_cast<char *>(reinterpret_cast<const char *>(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);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
|
||||
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};
|
||||
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 };
|
||||
*ret_label = 0;
|
||||
return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
|
||||
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};
|
||||
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};
|
||||
*ret_label = 0;
|
||||
return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
|
||||
return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi);
|
||||
}
|
||||
|
||||
// This function is only available for glibc 2.27 or newer. Mark it weak so
|
||||
|
@ -1581,7 +1629,10 @@ static void SignalHandler(int signo) {
|
|||
SignalHandlerScope signal_handler_scope;
|
||||
ScopedClearThreadLocalState scoped_clear_tls;
|
||||
|
||||
// Clear shadows for all inputs provided by system.
|
||||
// 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.
|
||||
dfsan_clear_arg_tls(0, sizeof(dfsan_label));
|
||||
|
||||
typedef void (*signal_cb)(int x);
|
||||
|
@ -1682,18 +1733,22 @@ static sighandler_t dfsan_signal(int signum, sighandler_t handler,
|
|||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
sighandler_t __dfsw_signal(int signum, sighandler_t handler,
|
||||
dfsan_label signum_label, dfsan_label handler_label,
|
||||
dfsan_label *ret_label) {
|
||||
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) {
|
||||
return dfsan_signal(signum, handler, ret_label);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
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) {
|
||||
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) {
|
||||
return dfsan_signal(signum, handler, ret_label);
|
||||
}
|
||||
|
||||
|
@ -2033,62 +2088,47 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
|
|||
addrlen_label, ret_label);
|
||||
}
|
||||
|
||||
// Type of the function passed to dfsan_set_write_callback.
|
||||
typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
|
||||
// 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);
|
||||
|
||||
// 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_dfsan_callback_t write_callback = nullptr;
|
||||
write_trampoline_t write_callback_trampoline = nullptr;
|
||||
void *write_callback = nullptr;
|
||||
} write_callback_info;
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
|
||||
write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
|
||||
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,
|
||||
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_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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE int
|
||||
|
@ -2096,9 +2136,10 @@ __dfsw_write(int fd, const void *buf, size_t count,
|
|||
dfsan_label fd_label, dfsan_label buf_label,
|
||||
dfsan_label count_label, dfsan_label *ret_label) {
|
||||
if (write_callback_info.write_callback) {
|
||||
setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
|
||||
0, 0, 0);
|
||||
write_callback_info.write_callback(fd, buf, count);
|
||||
write_callback_info.write_callback_trampoline(
|
||||
write_callback_info.write_callback,
|
||||
fd, buf, count,
|
||||
fd_label, buf_label, count_label);
|
||||
}
|
||||
|
||||
*ret_label = 0;
|
||||
|
@ -2110,10 +2151,10 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
|
|||
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_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);
|
||||
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);
|
||||
}
|
||||
|
||||
*ret_label = 0;
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
|
||||
namespace __dfsan {
|
||||
|
||||
DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg,
|
||||
DFsanThread *DFsanThread::Create(void *start_routine_trampoline,
|
||||
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;
|
||||
|
@ -72,15 +74,23 @@ thread_return_t DFsanThread::ThreadStart() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// 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();
|
||||
CHECK(start_routine_trampoline_);
|
||||
|
||||
return start_routine_(arg_);
|
||||
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);
|
||||
}
|
||||
|
||||
DFsanThread::StackBounds DFsanThread::GetStackBounds() const {
|
||||
|
|
|
@ -24,7 +24,8 @@ class DFsanThread {
|
|||
// NOTE: There is no DFsanThread constructor. It is allocated
|
||||
// via mmap() and *must* be valid in zero-initialized state.
|
||||
|
||||
static DFsanThread *Create(thread_callback_t start_routine, void *arg,
|
||||
static DFsanThread *Create(void *start_routine_trampoline,
|
||||
thread_callback_t start_routine, void *arg,
|
||||
bool track_origins = false);
|
||||
static void TSDDtor(void *tsd);
|
||||
void Destroy();
|
||||
|
@ -58,6 +59,7 @@ class DFsanThread {
|
|||
|
||||
bool AddrIsInStack(uptr addr);
|
||||
|
||||
void *start_routine_trampoline_;
|
||||
thread_callback_t start_routine_;
|
||||
void *arg_;
|
||||
bool track_origins_;
|
||||
|
|
|
@ -478,12 +478,14 @@ class DataFlowSanitizer {
|
|||
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);
|
||||
|
@ -790,6 +792,25 @@ DataFlowSanitizer::DataFlowSanitizer(
|
|||
SpecialCaseList::createOrDie(AllABIListFiles, *vfs::getRealFileSystem()));
|
||||
}
|
||||
|
||||
FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) {
|
||||
assert(!T->isVarArg());
|
||||
SmallVector<Type *, 4> 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<Type *, 4> ArgTypes;
|
||||
|
||||
|
@ -801,8 +822,15 @@ TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
|
|||
for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
|
||||
Type *ParamType = T->getParamType(I);
|
||||
FunctionType *FT;
|
||||
ArgumentIndexMapping.push_back(ArgTypes.size());
|
||||
ArgTypes.push_back(ParamType);
|
||||
if (isa<PointerType>(ParamType) &&
|
||||
(FT = dyn_cast<FunctionType>(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);
|
||||
}
|
||||
}
|
||||
for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
|
||||
ArgTypes.push_back(PrimitiveShadowTy);
|
||||
|
@ -1151,6 +1179,61 @@ DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
|
|||
return NewF;
|
||||
}
|
||||
|
||||
Constant *DataFlowSanitizer::getOrBuildTrampolineFunction(FunctionType *FT,
|
||||
StringRef FName) {
|
||||
FunctionType *FTT = getTrampolineFunctionType(FT);
|
||||
FunctionCallee C = Mod->getOrInsertFunction(FName, FTT);
|
||||
Function *F = dyn_cast<Function>(C.getCallee());
|
||||
if (F && F->isDeclaration()) {
|
||||
F->setLinkage(GlobalValue::LinkOnceODRLinkage);
|
||||
BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
|
||||
std::vector<Value *> 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<Constant>(C.getCallee());
|
||||
}
|
||||
|
||||
// Initialize DataFlowSanitizer runtime functions and declare them in the module
|
||||
void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
|
||||
{
|
||||
|
@ -2822,7 +2905,20 @@ bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) {
|
|||
for (unsigned N = FT->getNumParams(); N != 0; ++I, --N) {
|
||||
Type *T = (*I)->getType();
|
||||
FunctionType *ParamFT;
|
||||
Args.push_back(*I);
|
||||
if (isa<PointerType>(T) &&
|
||||
(ParamFT = dyn_cast<FunctionType>(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);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds shadow arguments.
|
||||
|
|
|
@ -42,7 +42,7 @@ define void @f(i32 %x) {
|
|||
; 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({{.*}} @cb.dfsan, i[[#SBITS]] zeroext 0)
|
||||
; CHECK: call void @__dfsw_customcb({{.*}} @"dfst0$customcb", i8* bitcast ({{.*}} @cb.dfsan to i8*), 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,5 +93,12 @@ define i32 (i32, i32)* @g(i32) {
|
|||
; 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]]*, ...)
|
||||
|
|
|
@ -137,7 +137,7 @@ define {i1, i7} @call_custom_cb({i32, i1} %a, [2 x i7] %b) {
|
|||
; 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 } ({ 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: [[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: [[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,18 +186,20 @@ define {i1, i7} ({i32, i1}, [2 x i7])* @ret_custom() {
|
|||
; 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 } ({ 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: [[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: [[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]]
|
||||
|
@ -248,4 +250,19 @@ define void @custom_varg({i32, i1} %a, ...) {
|
|||
; 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 } ({ i32, i1 }, [2 x i7])*, { i32, i1 }, [2 x i7], i[[#SBITS]], i[[#SBITS]], 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]]
|
||||
|
|
|
@ -16,13 +16,16 @@ declare i8 @a_callback_fun(i32, double)
|
|||
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,
|
||||
|
|
|
@ -199,7 +199,7 @@ define i32 @call_custom_cb_with_ret(i32 %a, i32 %b) {
|
|||
; 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)* @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: {{.*}} = 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: [[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 @@ define void @call_custom_cb_without_ret(i32 %a, i32 %b) {
|
|||
; 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 (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: 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-NEXT: ret void
|
||||
|
||||
call void @custom_cb_without_ret(void (i32, i32)* @cb_without_ret, i32 %a, i32 %b)
|
||||
|
@ -267,7 +267,8 @@ define void @call_custom_cb_without_ret(i32 %a, i32 %b) {
|
|||
; 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: [[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: [[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: [[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
|
||||
|
@ -281,17 +282,38 @@ define void @call_custom_cb_without_ret(i32 %a, i32 %b) {
|
|||
; 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: 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: [[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: 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, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i32, 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: declare void @__dfso_custom_cb_without_ret(void (i32, i32)*, i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]], 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 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*, ...)
|
||||
; CHECK: declare i32 @__dfso_custom_varg_with_ret(i32, i32, i[[#SBITS]], i[[#SBITS]], i[[#SBITS]]*, i[[#SBITS]]*, i32, i32, i32*, i32*, ...)
|
Loading…
Reference in New Issue