[dfsan] Add full fast8 support

Complete support for fast8:
- amend shadow size and mapping in runtime
- remove fast16 mode and -dfsan-fast-16-labels flag
- remove legacy mode and make fast8 mode the default
- remove dfsan-fast-8-labels flag
- remove functions in dfsan interface only applicable to legacy
- remove legacy-related instrumentation code and tests
- update documentation.

Reviewed By: stephan.yichao.zhao, browneee

Differential Revision: https://reviews.llvm.org/D103745
This commit is contained in:
George Balatsouras 2021-06-04 15:34:02 -07:00
parent 3b69318eef
commit 5b4dda550e
80 changed files with 516 additions and 4666 deletions

View File

@ -140,59 +140,14 @@ For example:
Example
=======
DataFlowSanitizer supports up to 8 labels, to achieve low CPU and code
size overhead. Base labels are simply 8-bit unsigned integers that are
powers of 2 (i.e. 1, 2, 4, 8, ..., 128), and union labels are created
by ORing base labels.
The following program demonstrates label propagation by checking that
the correct labels are propagated.
.. code-block:: c++
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
int k = 3;
dfsan_label k_label = dfsan_create_label("k", 0);
dfsan_set_label(k_label, &k, sizeof(k));
dfsan_label ij_label = dfsan_get_label(i + j);
assert(dfsan_has_label(ij_label, i_label));
assert(dfsan_has_label(ij_label, j_label));
assert(!dfsan_has_label(ij_label, k_label));
dfsan_label ijk_label = dfsan_get_label(i + j + k);
assert(dfsan_has_label(ijk_label, i_label));
assert(dfsan_has_label(ijk_label, j_label));
assert(dfsan_has_label(ijk_label, k_label));
return 0;
}
fast16labels mode
=================
If you need 16 or fewer labels, you can use fast16labels instrumentation for
less CPU and code size overhead. To use fast16labels instrumentation, you'll
need to specify `-fsanitize=dataflow -mllvm -dfsan-fast-16-labels` in your
compile and link commands and use a modified API for creating and managing
labels.
In fast16labels mode, base labels are simply 16-bit unsigned integers that are
powers of 2 (i.e. 1, 2, 4, 8, ..., 32768), and union labels are created by ORing
base labels. In this mode DFSan does not manage any label metadata, so the
functions `dfsan_create_label`, `dfsan_union`, `dfsan_get_label_info`,
`dfsan_has_label`, `dfsan_has_label_with_desc`, `dfsan_get_label_count`, and
`dfsan_dump_labels` are unsupported. Instead of using them, the user should
maintain any necessary metadata about base labels themselves.
For example:
.. code-block:: c++
#include <sanitizer/dfsan_interface.h>
@ -216,6 +171,11 @@ For example:
assert(!(ij_label & k_label)); // ij_label doesn't have k_label
assert(ij_label == 3); // Verifies all of the above
// Or, equivalently:
assert(dfsan_has_label(ij_label, i_label));
assert(dfsan_has_label(ij_label, j_label));
assert(!dfsan_has_label(ij_label, k_label));
dfsan_label ijk_label = dfsan_get_label(i + j + k);
assert(ijk_label & i_label); // ijk_label has i_label
@ -223,6 +183,11 @@ For example:
assert(ijk_label & k_label); // ijk_label has k_label
assert(ijk_label == 7); // Verifies all of the above
// Or, equivalently:
assert(dfsan_has_label(ijk_label, i_label));
assert(dfsan_has_label(ijk_label, j_label));
assert(dfsan_has_label(ijk_label, k_label));
return 0;
}

View File

@ -12,9 +12,7 @@ DataFlowSanitizer is a program instrumentation which can associate
a number of taint labels with any data stored in any memory region
accessible by the program. The analysis is dynamic, which means that
it operates on a running program, and tracks how the labels propagate
through that program. The tool shall support a large (>100) number
of labels, such that programs which operate on large numbers of data
items may be analysed with each data item being tracked separately.
through that program.
Use Cases
---------
@ -28,16 +26,13 @@ ensure it isn't exiting the program anywhere it shouldn't be.
Interface
---------
A number of functions are provided which will create taint labels,
attach labels to memory regions and extract the set of labels
associated with a specific memory region. These functions are declared
in the header file ``sanitizer/dfsan_interface.h``.
A number of functions are provided which will attach taint labels to
memory regions and extract the set of labels associated with a
specific memory region. These functions are declared in the header
file ``sanitizer/dfsan_interface.h``.
.. code-block:: c
/// Creates and returns a base label with the given description and user data.
dfsan_label dfsan_create_label(const char *desc, void *userdata);
/// Sets the label for each address in [addr,addr+size) to \c label.
void dfsan_set_label(dfsan_label label, void *addr, size_t size);
@ -53,93 +48,57 @@ in the header file ``sanitizer/dfsan_interface.h``.
/// value.
dfsan_label dfsan_get_label(long data);
/// Retrieves a pointer to the dfsan_label_info struct for the given label.
const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label);
/// Returns whether the given label label contains the label elem.
int dfsan_has_label(dfsan_label label, dfsan_label elem);
/// If the given label label contains a label with the description desc, returns
/// that label, else returns 0.
dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc);
/// Computes the union of \c l1 and \c l2, resulting in a union label.
dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
Taint label representation
--------------------------
As stated above, the tool must track a large number of taint
labels. This poses an implementation challenge, as most multiple-label
tainting systems assign one label per bit to shadow storage, and
union taint labels using a bitwise or operation. This will not scale
to clients which use hundreds or thousands of taint labels, as the
label union operation becomes O(n) in the number of supported labels,
and data associated with it will quickly dominate the live variable
set, causing register spills and hampering performance.
We use an 8-bit unsigned integer for the representation of a
label. The label identifier 0 is special, and means that the data item
is unlabelled. This is optimizing for low CPU and code size overhead
of the instrumentation. When a label union operation is requested at a
join point (any arithmetic or logical operation with two or more
operands, such as addition), we can simply OR the two labels in O(1).
Instead, a low overhead approach is proposed which is best-case O(log\
:sub:`2` n) during execution. The underlying assumption is that
the required space of label unions is sparse, which is a reasonable
assumption to make given that we are optimizing for the case where
applications mostly copy data from one place to another, without often
invoking the need for an actual union operation. The representation
of a taint label is a 16-bit integer, and new labels are allocated
sequentially from a pool. The label identifier 0 is special, and means
that the data item is unlabelled.
When a label union operation is requested at a join point (any
arithmetic or logical operation with two or more operands, such as
addition), the code checks whether a union is required, whether the
same union has been requested before, and whether one union label
subsumes the other. If so, it returns the previously allocated union
label. If not, it allocates a new union label from the same pool used
for new labels.
Specifically, the instrumentation pass will insert code like this
to decide the union label ``lu`` for a pair of labels ``l1``
and ``l2``:
.. code-block:: c
if (l1 == l2)
lu = l1;
else
lu = __dfsan_union(l1, l2);
The equality comparison is outlined, to provide an early exit in
the common cases where the program is processing unlabelled data, or
where the two data items have the same label. ``__dfsan_union`` is
a runtime library function which performs all other union computation.
Further optimizations are possible, for example if ``l1`` is known
at compile time to be zero (e.g. it is derived from a constant),
``l2`` can be used for ``lu``, and vice versa.
Users are responsible for managing the 8 integer labels (i.e., keeping
track of what labels they have used so far, picking one that is yet
unused, etc).
Memory layout and label management
----------------------------------
The following is the current memory layout for Linux/x86\_64:
The following is the memory layout for Linux/x86\_64:
+---------------+---------------+--------------------+
| Start | End | Use |
+===============+===============+====================+
| 0x700000008000|0x800000000000 | application memory |
+---------------+---------------+--------------------+
| 0x200200000000|0x700000008000 | unused |
| 0x300000000000|0x700000008000 | unused |
+---------------+---------------+--------------------+
| 0x200000000000|0x200200000000 | union table |
| 0x200000008000|0x300000000000 | origin |
+---------------+---------------+--------------------+
| 0x000000010000|0x200000000000 | shadow memory |
| 0x200000000000|0x200000008000 | unused |
+---------------+---------------+--------------------+
| 0x100000008000|0x200000000000 | shadow memory |
+---------------+---------------+--------------------+
| 0x000000010000|0x100000008000 | unused |
+---------------+---------------+--------------------+
| 0x000000000000|0x000000010000 | reserved by kernel |
+---------------+---------------+--------------------+
Each byte of application memory corresponds to two bytes of shadow
memory, which are used to store its taint label. As for LLVM SSA
Each byte of application memory corresponds to a single byte of shadow
memory, which is used to store its taint label. As for LLVM SSA
registers, we have not found it necessary to associate a label with
each byte or bit of data, as some other tools do. Instead, labels are
associated directly with registers. Loads will result in a union of
all shadow labels corresponding to bytes loaded (which most of the
time will be short circuited by the initial comparison) and stores will
result in a copy of the label to the shadow of all bytes stored to.
all shadow labels corresponding to bytes loaded, and stores will
result in a copy of the label of the stored value to the shadow of all
bytes stored to.
Propagating labels through arguments
------------------------------------

View File

@ -21,34 +21,15 @@
extern "C" {
#endif
typedef uint16_t dfsan_label;
typedef uint8_t dfsan_label;
typedef uint32_t dfsan_origin;
/// Stores information associated with a specific label identifier. A label
/// may be a base label created using dfsan_create_label, with associated
/// text description and user data, or an automatically created union label,
/// which represents the union of two label identifiers (which may themselves
/// be base or union labels).
struct dfsan_label_info {
// Fields for union labels, set to 0 for base labels.
dfsan_label l1;
dfsan_label l2;
// Fields for base labels.
const char *desc;
void *userdata;
};
/// Signature of the callback argument to dfsan_set_write_callback().
typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count);
/// Computes the union of \c l1 and \c l2, possibly creating a union label in
/// the process.
/// Computes the union of \c l1 and \c l2, resulting in a union label.
dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
/// Creates and returns a base label with the given description and user data.
dfsan_label dfsan_create_label(const char *desc, void *userdata);
/// Sets the label for each address in [addr,addr+size) to \c label.
void dfsan_set_label(dfsan_label label, void *addr, size_t size);
@ -73,19 +54,9 @@ dfsan_origin dfsan_get_origin(long data);
/// Retrieves the label associated with the data at the given address.
dfsan_label dfsan_read_label(const void *addr, size_t size);
/// Retrieves a pointer to the dfsan_label_info struct for the given label.
const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label);
/// Returns whether the given label label contains the label elem.
int dfsan_has_label(dfsan_label label, dfsan_label elem);
/// If the given label label contains a label with the description desc, returns
/// that label, else returns 0.
dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc);
/// Returns the number of labels allocated.
size_t dfsan_get_label_count(void);
/// Flushes the DFSan shadow, i.e. forgets about all labels currently associated
/// with the application memory. Use this call to start over the taint tracking
/// within the same process.
@ -99,12 +70,6 @@ void dfsan_flush(void);
/// callback executes. Pass in NULL to remove any callback.
void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);
/// Writes the labels currently used by the program to the given file
/// descriptor. The lines of the output have the following format:
///
/// <label> <parent label 1> <parent label 2> <label description if any>
void dfsan_dump_labels(int fd);
/// Interceptor hooks.
/// Whenever a dfsan's custom function is called the corresponding
/// hook is called it non-zero. The hooks should be defined by the user.

View File

@ -36,14 +36,6 @@
using namespace __dfsan;
typedef atomic_uint16_t atomic_dfsan_label;
static const dfsan_label kInitializingLabel = -1;
static const uptr kNumLabels = 1 << (sizeof(dfsan_label) * 8);
static atomic_dfsan_label __dfsan_last_label;
static dfsan_label_info __dfsan_label_info[kNumLabels];
Flags __dfsan::flags_data;
// The size of TLS variables. These constants must be kept in sync with the ones
@ -80,22 +72,22 @@ int __dfsan_get_track_origins() {
// | |
// | unused |
// | |
// +--------------------+ 0x300200000000 (kUnusedAddr)
// | union table |
// +--------------------+ 0x300000000000 (kUnionTableAddr)
// +--------------------+ 0x300000000000 (kUnusedAddr)
// | origin |
// +--------------------+ 0x200000000000 (kOriginAddr)
// +--------------------+ 0x200000008000 (kOriginAddr)
// | unused |
// +--------------------+ 0x200000000000
// | shadow memory |
// +--------------------+ 0x000000010000 (kShadowAddr)
// +--------------------+ 0x100000008000 (kShadowAddr)
// | unused |
// +--------------------+ 0x000000010000
// | reserved by kernel |
// +--------------------+ 0x000000000000
//
// To derive a shadow memory address from an application memory address,
// bits 44-46 are cleared to bring the address into the range
// [0x000000008000,0x100000000000). Then the address is shifted left by 1 to
// account for the double byte representation of shadow labels and move the
// address into the shadow memory range. See the function shadow_for below.
// To derive a shadow memory address from an application memory address, bits
// 45-46 are cleared to bring the address into the range
// [0x100000008000,0x200000000000). See the function shadow_for below.
//
// On Linux/MIPS64, memory is laid out as follows:
//
// +--------------------+ 0x10000000000 (top of memory)
@ -104,11 +96,11 @@ int __dfsan_get_track_origins() {
// | |
// | unused |
// | |
// +--------------------+ 0x2200000000 (kUnusedAddr)
// | union table |
// +--------------------+ 0x2000000000 (kUnionTableAddr)
// +--------------------+ 0x2000000000 (kUnusedAddr)
// | shadow memory |
// +--------------------+ 0x0000010000 (kShadowAddr)
// +--------------------+ 0x1000008000 (kShadowAddr)
// | unused |
// +--------------------+ 0x0000010000
// | reserved by kernel |
// +--------------------+ 0x0000000000
@ -120,9 +112,7 @@ int __dfsan_get_track_origins() {
// | |
// | unused |
// | |
// +--------------------+ 0x1200000000 (kUnusedAddr)
// | union table |
// +--------------------+ 0x1000000000 (kUnionTableAddr)
// +--------------------+ 0x1000000000 (kUnusedAddr)
// | shadow memory |
// +--------------------+ 0x0000010000 (kShadowAddr)
// | reserved by kernel |
@ -136,9 +126,7 @@ int __dfsan_get_track_origins() {
// | |
// | unused |
// | |
// +--------------------+ 0x1200000000 (kUnusedAddr)
// | union table |
// +--------------------+ 0x8000000000 (kUnionTableAddr)
// +--------------------+ 0x8000000000 (kUnusedAddr)
// | shadow memory |
// +--------------------+ 0x0000010000 (kShadowAddr)
// | reserved by kernel |
@ -156,102 +144,19 @@ int __dfsan_get_track_origins() {
// | |
// | unused |
// | |
// +--------------------+ 0x1200000000 (kUnusedAddr)
// | union table |
// +--------------------+ 0x8000000000 (kUnionTableAddr)
// +--------------------+ 0x8000000000 (kUnusedAddr)
// | shadow memory |
// +--------------------+ 0x0000010000 (kShadowAddr)
// | reserved by kernel |
// +--------------------+ 0x0000000000
typedef atomic_dfsan_label dfsan_union_table_t[kNumLabels][kNumLabels];
#ifdef DFSAN_RUNTIME_VMA
// Runtime detected VMA size.
int __dfsan::vmaSize;
#endif
static uptr UnusedAddr() {
return UnionTableAddr() + sizeof(dfsan_union_table_t);
}
static atomic_dfsan_label *union_table(dfsan_label l1, dfsan_label l2) {
return &(*(dfsan_union_table_t *) UnionTableAddr())[l1][l2];
}
// Checks we do not run out of labels.
static void dfsan_check_label(dfsan_label label) {
if (label == kInitializingLabel) {
Report("FATAL: DataFlowSanitizer: out of labels\n");
Die();
}
}
// Resolves the union of two unequal labels. Nonequality is a precondition for
// this function (the instrumentation pass inlines the equality test).
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
dfsan_label __dfsan_union(dfsan_label l1, dfsan_label l2) {
DCHECK_NE(l1, l2);
if (l1 == 0)
return l2;
if (l2 == 0)
return l1;
// If no labels have been created, yet l1 and l2 are non-zero, we are using
// fast16labels mode.
if (atomic_load(&__dfsan_last_label, memory_order_relaxed) == 0)
return l1 | l2;
if (l1 > l2)
Swap(l1, l2);
atomic_dfsan_label *table_ent = union_table(l1, l2);
// We need to deal with the case where two threads concurrently request
// a union of the same pair of labels. If the table entry is uninitialized,
// (i.e. 0) use a compare-exchange to set the entry to kInitializingLabel
// (i.e. -1) to mark that we are initializing it.
dfsan_label label = 0;
if (atomic_compare_exchange_strong(table_ent, &label, kInitializingLabel,
memory_order_acquire)) {
// Check whether l2 subsumes l1. We don't need to check whether l1
// subsumes l2 because we are guaranteed here that l1 < l2, and (at least
// in the cases we are interested in) a label may only subsume labels
// created earlier (i.e. with a lower numerical value).
if (__dfsan_label_info[l2].l1 == l1 ||
__dfsan_label_info[l2].l2 == l1) {
label = l2;
} else {
label =
atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1;
dfsan_check_label(label);
__dfsan_label_info[label].l1 = l1;
__dfsan_label_info[label].l2 = l2;
}
atomic_store(table_ent, label, memory_order_release);
} else if (label == kInitializingLabel) {
// Another thread is initializing the entry. Wait until it is finished.
do {
internal_sched_yield();
label = atomic_load(table_ent, memory_order_acquire);
} while (label == kInitializingLabel);
}
return label;
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
dfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) {
dfsan_label label = ls[0];
for (uptr i = 1; i != n; ++i) {
dfsan_label next_label = ls[i];
if (label != next_label)
label = __dfsan_union(label, next_label);
}
return label;
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
dfsan_label __dfsan_union_load_fast16labels(const dfsan_label *ls, uptr n) {
dfsan_label label = ls[0];
for (uptr i = 1; i != n; ++i)
label |= ls[i];
@ -301,24 +206,10 @@ __dfsan_vararg_wrapper(const char *fname) {
Die();
}
// Like __dfsan_union, but for use from the client or custom functions. Hence
// the equality comparison is done here before calling __dfsan_union.
// Resolves the union of two labels.
SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
dfsan_union(dfsan_label l1, dfsan_label l2) {
if (l1 == l2)
return l1;
return __dfsan_union(l1, l2);
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
dfsan_label dfsan_create_label(const char *desc, void *userdata) {
dfsan_label label =
atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1;
dfsan_check_label(label);
__dfsan_label_info[label].l1 = __dfsan_label_info[label].l2 = 0;
__dfsan_label_info[label].desc = desc;
__dfsan_label_info[label].userdata = userdata;
return label;
return l1 | l2;
}
// Return the origin of the first taint byte in the size bytes from the address
@ -429,7 +320,7 @@ static void CopyOrigin(const void *dst, const void *src, uptr size,
// Align src up.
uptr s = AlignUp((uptr)src);
dfsan_origin *src_o = (dfsan_origin *)origin_for((void *)s);
u64 *src_s = (u64 *)shadow_for((void *)s);
u32 *src_s = (u32 *)shadow_for((void *)s);
dfsan_origin *src_end = (dfsan_origin *)origin_for((void *)(s + (end - beg)));
dfsan_origin *dst_o = (dfsan_origin *)origin_for((void *)beg);
dfsan_origin last_src_o = 0;
@ -465,7 +356,7 @@ static void ReverseCopyOrigin(const void *dst, const void *src, uptr size,
uptr s = AlignUp((uptr)src);
dfsan_origin *src =
(dfsan_origin *)origin_for((void *)(s + end - beg - kOriginAlign));
u64 *src_s = (u64 *)shadow_for((void *)(s + end - beg - kOriginAlign));
u32 *src_s = (u32 *)shadow_for((void *)(s + end - beg - kOriginAlign));
dfsan_origin *src_begin = (dfsan_origin *)origin_for((void *)s);
dfsan_origin *dst =
(dfsan_origin *)origin_for((void *)(end - kOriginAlign));
@ -628,7 +519,7 @@ void dfsan_copy_memory(void *dst, const void *src, uptr size) {
// origin chain with the previous ID o and the current stack trace. This is
// used by instrumentation to reduce code size when too much code is inserted.
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_maybe_store_origin(
u16 s, void *p, uptr size, dfsan_origin o) {
dfsan_label s, void *p, uptr size, dfsan_origin o) {
if (UNLIKELY(s)) {
GET_CALLER_PC_BP_SP;
(void)sp;
@ -726,8 +617,7 @@ void dfsan_add_label(dfsan_label label, void *addr, uptr size) {
}
for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp)
if (*labelp != label)
*labelp = __dfsan_union(*labelp, label);
*labelp |= label;
}
// Unlike the other dfsan interface functions the behavior of this function
@ -783,57 +673,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_label_origin(dfsan_label label,
__dfsan_set_label(label, origin, addr, size);
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label) {
return &__dfsan_label_info[label];
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE int
dfsan_has_label(dfsan_label label, dfsan_label elem) {
if (label == elem)
return true;
const dfsan_label_info *info = dfsan_get_label_info(label);
if (info->l1 != 0) {
return dfsan_has_label(info->l1, elem) || dfsan_has_label(info->l2, elem);
} else {
return false;
}
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
dfsan_has_label_with_desc(dfsan_label label, const char *desc) {
const dfsan_label_info *info = dfsan_get_label_info(label);
if (info->l1 != 0) {
return dfsan_has_label_with_desc(info->l1, desc) ||
dfsan_has_label_with_desc(info->l2, desc);
} else {
return internal_strcmp(desc, info->desc) == 0;
}
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
dfsan_get_label_count(void) {
dfsan_label max_label_allocated =
atomic_load(&__dfsan_last_label, memory_order_relaxed);
return static_cast<uptr>(max_label_allocated);
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
dfsan_dump_labels(int fd) {
dfsan_label last_label =
atomic_load(&__dfsan_last_label, memory_order_relaxed);
for (uptr l = 1; l <= last_label; ++l) {
char buf[64];
internal_snprintf(buf, sizeof(buf), "%u %u %u ", l,
__dfsan_label_info[l].l1, __dfsan_label_info[l].l2);
WriteToFile(fd, buf, internal_strlen(buf));
if (__dfsan_label_info[l].l1 == 0 && __dfsan_label_info[l].desc) {
WriteToFile(fd, __dfsan_label_info[l].desc,
internal_strlen(__dfsan_label_info[l].desc));
}
WriteToFile(fd, "\n", 1);
}
return (label & elem) == elem;
}
class Decorator : public __sanitizer::SanitizerCommonDecorator {
@ -1068,22 +910,6 @@ static void InitializePlatformEarly() {
#endif
}
static void dfsan_fini() {
if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) {
fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly);
if (fd == kInvalidFd) {
Report("WARNING: DataFlowSanitizer: unable to open output file %s\n",
flags().dump_labels_at_exit);
return;
}
Report("INFO: DataFlowSanitizer: dumping labels to %s\n",
flags().dump_labels_at_exit);
dfsan_dump_labels(fd);
CloseFile(fd);
}
}
extern "C" void dfsan_flush() {
if (!MmapFixedSuperNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()))
Die();
@ -1115,11 +941,6 @@ static void DFsanInit(int argc, char **argv, char **envp) {
initialize_interceptors();
// Register the fini callback to run when the program terminates successfully
// or it is killed by the runtime.
Atexit(dfsan_fini);
AddDieCallback(dfsan_fini);
// Set up threads
DFsanTSDInit(DFsanTSDDtor);
@ -1129,8 +950,6 @@ static void DFsanInit(int argc, char **argv, char **envp) {
SetCurrentThread(main_thread);
main_thread->ThreadStart();
__dfsan_label_info[kInitializingLabel].desc = "<init label>";
dfsan_init_is_running = false;
dfsan_inited = true;
}

View File

@ -18,21 +18,14 @@
#include "dfsan_platform.h"
using __sanitizer::u16;
using __sanitizer::u32;
using __sanitizer::u8;
using __sanitizer::uptr;
// Copy declarations from public sanitizer/dfsan_interface.h header here.
typedef u16 dfsan_label;
typedef u8 dfsan_label;
typedef u32 dfsan_origin;
struct dfsan_label_info {
dfsan_label l1;
dfsan_label l2;
const char *desc;
void *userdata;
};
extern "C" {
void dfsan_add_label(dfsan_label label, void *addr, uptr size);
void dfsan_set_label(dfsan_label label, void *addr, uptr size);
@ -68,7 +61,7 @@ extern bool dfsan_init_is_running;
void initialize_interceptors();
inline dfsan_label *shadow_for(void *ptr) {
return (dfsan_label *) ((((uptr) ptr) & ShadowMask()) << 1);
return (dfsan_label *)(((uptr)ptr) & ShadowMask());
}
inline const dfsan_label *shadow_for(const void *ptr) {
@ -76,7 +69,7 @@ inline const dfsan_label *shadow_for(const void *ptr) {
}
inline uptr unaligned_origin_for(uptr ptr) {
return OriginAddr() + (ptr & ShadowMask());
return OriginAddr() - ShadowAddr() + (ptr & ShadowMask());
}
inline dfsan_origin *origin_for(void *ptr) {
@ -98,6 +91,15 @@ inline bool has_valid_shadow_addr(const void *ptr) {
return is_shadow_addr_valid((uptr)ptr_s);
}
inline bool is_origin_addr_valid(uptr origin_addr) {
return (uptr)origin_addr >= OriginAddr() && (uptr)origin_addr < UnusedAddr();
}
inline bool has_valid_origin_addr(const void *ptr) {
const dfsan_origin *ptr_orig = origin_for(ptr);
return is_origin_addr_valid((uptr)ptr_orig);
}
void dfsan_copy_memory(void *dst, const void *src, uptr size);
void dfsan_allocator_init();

View File

@ -26,9 +26,6 @@ DFSAN_FLAG(
"(e.g., when comparing strings, ignore the fact that the output of the"
"comparison might be data-dependent on the content of the strings). This"
"applies only to the custom functions defined in 'custom.c'.")
DFSAN_FLAG(const char *, dump_labels_at_exit, "", "The path of the file where "
"to dump the labels when the "
"program terminates.")
DFSAN_FLAG(
int, origin_history_size, Origin::kMaxDepth,
"The limit of origin chain length. Non-positive values mean unlimited.")

View File

@ -14,41 +14,45 @@
#ifndef DFSAN_PLATFORM_H
#define DFSAN_PLATFORM_H
#include "sanitizer_common/sanitizer_common.h"
namespace __dfsan {
using __sanitizer::uptr;
#if defined(__x86_64__)
struct Mapping {
static const uptr kShadowAddr = 0x10000;
static const uptr kOriginAddr = 0x200000000000;
static const uptr kUnionTableAddr = 0x300000000000;
static const uptr kShadowAddr = 0x100000008000;
static const uptr kOriginAddr = 0x200000008000;
static const uptr kUnusedAddr = 0x300000000000;
static const uptr kAppAddr = 0x700000008000;
static const uptr kShadowMask = ~0x700000000000;
static const uptr kShadowMask = ~0x600000000000;
};
#elif defined(__mips64)
struct Mapping {
static const uptr kShadowAddr = 0x10000;
static const uptr kUnionTableAddr = 0x2000000000;
static const uptr kShadowAddr = 0x1000008000;
static const uptr kUnusedAddr = 0x2000000000;
static const uptr kAppAddr = 0xF000008000;
static const uptr kShadowMask = ~0xF000000000;
static const uptr kShadowMask = ~0xE000000000;
};
#elif defined(__aarch64__)
struct Mapping39 {
static const uptr kShadowAddr = 0x10000;
static const uptr kUnionTableAddr = 0x1000000000;
static const uptr kUnusedAddr = 0x1000000000;
static const uptr kAppAddr = 0x7000008000;
static const uptr kShadowMask = ~0x7800000000;
};
struct Mapping42 {
static const uptr kShadowAddr = 0x10000;
static const uptr kUnionTableAddr = 0x8000000000;
static const uptr kUnusedAddr = 0x8000000000;
static const uptr kAppAddr = 0x3ff00008000;
static const uptr kShadowMask = ~0x3c000000000;
};
struct Mapping48 {
static const uptr kShadowAddr = 0x10000;
static const uptr kUnionTableAddr = 0x8000000000;
static const uptr kUnusedAddr = 0x8000000000;
static const uptr kAppAddr = 0xffff00008000;
static const uptr kShadowMask = ~0xfffff0000000;
};
@ -64,7 +68,7 @@ enum MappingType {
#if defined(__x86_64__)
MAPPING_ORIGIN_ADDR,
#endif
MAPPING_UNION_TABLE_ADDR,
MAPPING_UNUSED_ADDR,
MAPPING_APP_ADDR,
MAPPING_SHADOW_MASK
};
@ -77,7 +81,8 @@ uptr MappingImpl(void) {
case MAPPING_ORIGIN_ADDR:
return Mapping::kOriginAddr;
#endif
case MAPPING_UNION_TABLE_ADDR: return Mapping::kUnionTableAddr;
case MAPPING_UNUSED_ADDR:
return Mapping::kUnusedAddr;
case MAPPING_APP_ADDR: return Mapping::kAppAddr;
case MAPPING_SHADOW_MASK: return Mapping::kShadowMask;
}
@ -113,9 +118,7 @@ uptr OriginAddr() {
}
ALWAYS_INLINE
uptr UnionTableAddr() {
return MappingArchImpl<MAPPING_UNION_TABLE_ADDR>();
}
uptr UnusedAddr() { return MappingArchImpl<MAPPING_UNUSED_ADDR>(); }
ALWAYS_INLINE
uptr AppAddr() {

View File

@ -17,11 +17,9 @@
// and also provides basic-block coverage for every input.
//
// Build:
// 1. Compile this file (DataFlow.cpp) with -fsanitize=dataflow -mllvm
// -dfsan-fast-16-labels and -O2.
// 1. Compile this file (DataFlow.cpp) with -fsanitize=dataflow and -O2.
// 2. Compile DataFlowCallbacks.cpp with -O2 -fPIC.
// 3. Build the fuzz target with -g -fsanitize=dataflow
// -mllvm -dfsan-fast-16-labels
// -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp
// 4. Link those together with -fsanitize=dataflow
//
@ -82,7 +80,7 @@ static inline bool BlockIsEntry(size_t BlockIdx) {
return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY;
}
const int kNumLabels = 16;
const int kNumLabels = 8;
// Prints all instrumented functions.
static int PrintFunctions() {

View File

@ -1,5 +1,5 @@
// RUN: %clangxx_dfsan -mllvm -dfsan-fast-16-labels=true %s -fno-exceptions -o %t && %run %t
// RUN: %clangxx_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -fno-exceptions -o %t && %run %t
// RUN: %clangxx_dfsan %s -fno-exceptions -o %t && %run %t
// RUN: %clangxx_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 %s -fno-exceptions -o %t && %run %t
//
// REQUIRES: x86_64-target-arch
//

View File

@ -10,7 +10,7 @@
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_label i_label = 1;
dfsan_set_label(i_label, &i, sizeof(i));
dfsan_label new_label = dfsan_get_label(i);
@ -19,7 +19,7 @@ int main(void) {
dfsan_label read_label = dfsan_read_label(&i, sizeof(i));
assert(i_label == read_label);
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_label j_label = 2;
dfsan_add_label(j_label, &i, sizeof(i));
read_label = dfsan_read_label(&i, sizeof(i));

View File

@ -1,10 +1,10 @@
// RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
// RUN: %clang_dfsan -DFAST_16_LABELS -mllvm -dfsan-fast-16-labels %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
// RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t
// RUN: %clang_dfsan -DFAST_16_LABELS -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
// RUN: %clang_dfsan -DFAST_16_LABELS -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
// RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
// RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
//
// Tests custom implementations of various glibc functions.
//
@ -1944,19 +1944,11 @@ void test_snprintf() {
void test_fork() {}
int main(void) {
#ifdef FAST_16_LABELS
i_label = 1;
j_label = 2;
k_label = 4;
m_label = 8;
n_label = 16;
#else
i_label = dfsan_create_label("i", 0);
j_label = dfsan_create_label("j", 0);
k_label = dfsan_create_label("k", 0);
m_label = dfsan_create_label("m", 0);
n_label = dfsan_create_label("n", 0);
#endif
i_j_label = dfsan_union(i_label, j_label);
assert(i_j_label != i_label);
assert(i_j_label != j_label);

View File

@ -1,71 +0,0 @@
// RUN: %clang_dfsan %s -o %t
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout %run %t 2>&1 | FileCheck %s
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
//
// REQUIRES: x86_64-target-arch
// Tests that labels are properly dumped at program termination.
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
#include <stdio.h>
int main(int argc, char** argv) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
int k = 3;
dfsan_label k_label = dfsan_create_label("k", 0);
dfsan_set_label(k_label, &k, sizeof(k));
dfsan_label ij_label = dfsan_get_label(i + j);
dfsan_label ijk_label = dfsan_get_label(i + j + k);
fprintf(stderr, "i %d j %d k %d ij %d ijk %d\n", i_label, j_label, k_label,
ij_label, ijk_label);
// CHECK: 1 0 0 i
// CHECK: 2 0 0 j
// CHECK: 3 0 0 k
// CHECK: 4 1 2
// CHECK: 5 3 4
if (argc > 1) {
// Exhaust the labels.
unsigned long num_labels = 1 << (sizeof(dfsan_label) * 8);
for (unsigned long i = ijk_label + 1; i < num_labels - 2; ++i) {
dfsan_label l = dfsan_create_label("l", 0);
assert(l == i);
}
// Consume the last available label.
dfsan_label l = dfsan_union(5, 6);
assert(l == num_labels - 2);
// Try to allocate another label (either explicitly or by unioning two
// existing labels), but expect a crash.
if (argv[1][0] == 'c') {
l = dfsan_create_label("l", 0);
} else {
l = dfsan_union(6, 7);
}
// CHECK-OOL: FATAL: DataFlowSanitizer: out of labels
// CHECK-OOL: 1 0 0 i
// CHECK-OOL: 2 0 0 j
// CHECK-OOL: 3 0 0 k
// CHECK-OOL: 4 1 2
// CHECK-OOL: 5 3 4
// CHECK-OOL: 6 0 0
// CHECK-OOL: 65534 5 6
// CHECK-OOL: 65535 0 0 <init label>
}
return 0;
}

View File

@ -81,9 +81,9 @@ int main(int Argc, char *Argv[]) {
assert(Argc == 2);
int I = 1, J = 2;
LabelI = dfsan_create_label("I", 0);
LabelI = 1;
dfsan_set_label(LabelI, &I, sizeof(I));
LabelJ = dfsan_create_label("J", 0);
LabelJ = 2;
dfsan_set_label(LabelJ, &J, sizeof(J));
LabelIJ = dfsan_union(LabelI, LabelJ);
@ -113,7 +113,7 @@ int main(int Argc, char *Argv[]) {
assert(I != J);
LenArgv = strlen(Argv[1]);
LabelArgv = dfsan_create_label("Argv", 0);
LabelArgv = 4;
dfsan_set_label(LabelArgv, Argv[1], LenArgv);
char Buf[64];

View File

@ -1,10 +1,8 @@
// RUN: %clang_dfsan %s -mllvm -dfsan-fast-16-labels -o %t
// RUN: %clang_dfsan %s -o %t
// RUN: %run %t
//
// REQUIRES: x86_64-target-arch
//
// Tests fast16labels mode.
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
@ -19,11 +17,11 @@ int main(int argc, char *argv[]) {
int a = 10;
int b = 20;
dfsan_set_label(8, &a, sizeof(a));
dfsan_set_label(512, &b, sizeof(b));
dfsan_set_label(128, &b, sizeof(b));
int c = foo(a, b);
printf("A: 0x%x\n", dfsan_get_label(a));
printf("B: 0x%x\n", dfsan_get_label(b));
dfsan_label l = dfsan_get_label(c);
printf("C: 0x%x\n", l);
assert(l == 520); // OR of the other two labels.
assert(l == 136); // OR of the other two labels.
}

View File

@ -14,7 +14,7 @@ int f(int i) {
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_label i_label = 2;
dfsan_set_label(i_label, &i, sizeof(i));
// CHECK: WARNING: DataFlowSanitizer: call to uninstrumented function f

View File

@ -1,6 +1,6 @@
// Tests dfsan_flush().
// RUN: %clang_dfsan %s -o %t && %run %t
// RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && %run %t
// RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 %s -o %t && %run %t
//
// REQUIRES: x86_64-target-arch

View File

@ -10,19 +10,22 @@
int f(int x) {
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_label j_label = 2;
dfsan_set_label(j_label, &j, sizeof(j));
return x + j;
}
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_label i_label = 4;
dfsan_set_label(i_label, &i, sizeof(i));
dfsan_label ij_label = dfsan_get_label(f(i));
assert(dfsan_has_label(ij_label, i_label));
assert(dfsan_has_label_with_desc(ij_label, "j"));
/* Must be consistent with the one in f(). */
dfsan_label j_label = 2;
assert(dfsan_has_label(ij_label, 2));
return 0;
}

View File

@ -2,10 +2,10 @@
// Run a number of threads that create new chained origins, then fork
// and verify that origin reads do not deadlock in the child process.
//
// RUN: %clangxx_dfsan -mllvm -dfsan-fast-16-labels=true %s -o %t
// RUN: %clangxx_dfsan %s -o %t
// RUN: %run %t 2>&1 | FileCheck %s
//
// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t
// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 %s -o %t
// RUN: DFSAN_OPTIONS=store_context_size=1000,origin_history_size=0,origin_history_per_stack_limit=0 %run %t 2>&1 | FileCheck %s
//
// REQUIRES: x86_64-target-arch

View File

@ -1,5 +1,5 @@
// RUN: %clang_dfsan -mllvm -dfsan-fast-16-labels -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && %run %t
// RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && %run %t
// RUN: %clang_dfsan -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && %run %t
// RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && %run %t
//
// Tests custom implementations of various glibc functions.
//

View File

@ -1,77 +0,0 @@
// RUN: %clang_dfsan -DLIB -c %s -o %t.lib.o && \
// RUN: %clang_dfsan -c %s -o %t.o && \
// RUN: %clang_dfsan %t.lib.o %t.o -o %t.bin && \
// RUN: %run %t.bin
// RUN: %clang_dfsan -mllvm -dfsan-args-abi -DLIB -c %s -o %t.lib.o && \
// RUN: %clang_dfsan -mllvm -dfsan-args-abi -c %s -o %t.o && \
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %t.o %t.lib.o -o %t.bin && \
// RUN: %run %t.bin
//
// REQUIRES: x86_64-target-arch
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
#ifdef LIB
// Compiling this file with and without LIB defined allows this file to be
// built as two separate translation units. This ensures that the code
// can not be optimized in a way that removes behavior we wish to test. For
// example, computing a value should cause labels to be allocated only if
// the computation is actually done. Putting the computation here prevents
// the compiler from optimizing away the computation (and labeling) that
// tests wish to verify.
int add_in_separate_translation_unit(int a, int b) {
return a + b;
}
int multiply_in_separate_translation_unit(int a, int b) {
return a * b;
}
#else
int add_in_separate_translation_unit(int i, int j);
int multiply_in_separate_translation_unit(int i, int j);
int main(void) {
size_t label_count;
// No labels allocated yet.
label_count = dfsan_get_label_count();
assert(0 == label_count);
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
// One label allocated for i.
label_count = dfsan_get_label_count();
assert(1u == label_count);
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
// Check that a new label was allocated for j.
label_count = dfsan_get_label_count();
assert(2u == label_count);
// Create a value that combines i and j.
int i_plus_j = add_in_separate_translation_unit(i, j);
// Check that a label was created for the union of i and j.
label_count = dfsan_get_label_count();
assert(3u == label_count);
// Combine i and j in a different way. Check that the existing label is
// reused, and a new label is not created.
int j_times_i = multiply_in_separate_translation_unit(j, i);
label_count = dfsan_get_label_count();
assert(3u == label_count);
assert(dfsan_get_label(i_plus_j) == dfsan_get_label(j_times_i));
return 0;
}
#endif // #ifdef LIB

View File

@ -1,10 +1,10 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch

View File

@ -1,6 +1,6 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch

View File

@ -1,6 +1,5 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: %clang_dfsan -gmlt %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch

View File

@ -1,6 +1,6 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch
@ -8,13 +8,13 @@
int main(int argc, char *argv[]) {
uint64_t a = 10;
dfsan_set_label(8, &a, sizeof(a));
dfsan_set_label(1, &a, sizeof(a));
size_t origin_addr =
(((size_t)&a & ~0x700000000000LL + 0x200000000000LL) & ~0x3UL);
(((size_t)&a & ~0x600000000000LL + 0x100000000000LL) & ~0x3UL);
asm("mov %0, %%rax": :"r"(origin_addr));
asm("movq $0, (%rax)");
dfsan_print_origin_trace(&a, "invalid");
}
// CHECK: Taint value 0x8 (at {{.*}}) origin tracking (invalid)
// CHECK: Taint value 0x8 (at {{.*}}) has invalid origin tracking. This can be a DFSan bug.
// CHECK: Taint value 0x1 (at {{.*}}) origin tracking (invalid)
// CHECK: Taint value 0x1 (at {{.*}}) has invalid origin tracking. This can be a DFSan bug.

View File

@ -1,6 +1,6 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch
//

View File

@ -1,26 +1,26 @@
// RUN: %clang_dfsan -gmlt -DTEST64 -DALIGN=8 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DTEST64 -DALIGN=8 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -DTEST32 -DALIGN=4 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DTEST32 -DALIGN=4 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -DALIGN=2 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DALIGN=2 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// rUN: %clang_dfsan -DTEST64 -DALIGN=5 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// rUN: %run %t >%t.out 2>&1
// rUN: FileCheck %s --check-prefix=CHECK < %t.out
//
// rUN: %clang_dfsan -DTEST32 -DALIGN=3 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// rUN: %run %t >%t.out 2>&1
// rUN: FileCheck %s --check-prefix=CHECK < %t.out
//
// RUN: %clang_dfsan -gmlt -DALIGN=1 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DTEST64 -DALIGN=4 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -DTEST32 -DALIGN=2 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -DALIGN=1 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch
//

View File

@ -1,7 +1,7 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t
//
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// RUN: DFSAN_OPTIONS=origin_history_size=2 %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK2 < %t.out

View File

@ -1,8 +1,8 @@
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK0 < %t.out
//
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK10 < %t.out
//

View File

@ -1,8 +1,8 @@
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK0 < %t.out
//
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK10 < %t.out
//

View File

@ -1,8 +1,8 @@
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK0 < %t.out
//
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK10 < %t.out
//

View File

@ -1,6 +1,6 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch

View File

@ -1,10 +1,10 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch

View File

@ -1,8 +1,8 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//

View File

@ -1,4 +1,4 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=2 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=2 %s -o %t && \
// RUN: %run %t > %t.out 2>&1
// RUN: FileCheck %s < %t.out
//

View File

@ -1,8 +1,8 @@
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK0 < %t.out
//
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DOFFSET=10 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK10 < %t.out
//

View File

@ -1,6 +1,6 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch

View File

@ -3,19 +3,19 @@
// Origin tracking uses ChainedOriginDepot that is not async signal safe, so we
// do not track origins inside signal handlers.
//
// RUN: %clang_dfsan -gmlt -DUSE_SIGNAL_ACTION -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DUSE_SIGNAL_ACTION -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -DUSE_SIGNAL_ACTION -mllvm -dfsan-instrument-with-call-threshold=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -DUSE_SIGNAL_ACTION -mllvm -dfsan-instrument-with-call-threshold=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-instrument-with-call-threshold=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-instrument-with-call-threshold=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//

View File

@ -3,11 +3,11 @@
// Origin tracking uses ChainedOriginDepot that is not async signal safe, so we
// do not track origins inside signal handlers.
//
// RUN: %clangxx_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clangxx_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clangxx_dfsan -gmlt -mllvm -dfsan-instrument-with-call-threshold=0 -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clangxx_dfsan -gmlt -mllvm -dfsan-instrument-with-call-threshold=0 -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//

View File

@ -1,5 +1,5 @@
// RUN: %clangxx_dfsan %s -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O0 -DO0 -o %t && %run %t
// RUN: %clangxx_dfsan %s -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O1 -o %t && %run %t
// RUN: %clangxx_dfsan %s -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O0 -DO0 -o %t && %run %t
// RUN: %clangxx_dfsan %s -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O1 -o %t && %run %t
//
// REQUIRES: x86_64-target-arch

View File

@ -13,15 +13,15 @@ int main(void) {
assert(dfsan_union(0, 0) == 0);
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_label i_label = 1;
dfsan_set_label(i_label, &i, sizeof(i));
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_label j_label = 2;
dfsan_set_label(j_label, &j, sizeof(j));
int k = 3;
dfsan_label k_label = dfsan_create_label("k", 0);
dfsan_label k_label = 4;
dfsan_set_label(k_label, &k, sizeof(k));
int k2 = 4;

View File

@ -1,10 +1,10 @@
// RUN: %clang_dfsan -mllvm -dfsan-fast-16-labels=true %s -o %t && %run %t
// RUN: %clang_dfsan %s -o %t && %run %t
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//

View File

@ -1,7 +1,7 @@
// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -o %t && setarch `uname -m` -R %run %t
// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -o %t && setarch `uname -m` -R %run %t
// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -o %t && setarch `uname -m` -R %run %t
// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -o %t && setarch `uname -m` -R %run %t
// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && setarch `uname -m` -R %run %t
// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && setarch `uname -m` -R %run %t
//
// REQUIRES: x86_64-target-arch
@ -45,7 +45,7 @@ int main(int argc, char **argv) {
size_t after_mmap = get_rss_kb();
// store labels to all addresses. The overhead is 2x.
const dfsan_label label = dfsan_create_label("l", 0);
const dfsan_label label = 8;
char val = 0xff;
dfsan_set_label(label, &val, sizeof(val));
memset(p, val, map_size);

View File

@ -1,6 +1,5 @@
// RUN: %clang_dfsan -DUSE_SIGNAL_ACTION -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %run %t
// RUN: %clang_dfsan -mllvm -dfsan-fast-16-labels=true %s -o %t && %run %t
// RUN: %clang_dfsan -DUSE_SIGNAL_ACTION %s -o %t && %run %t
// RUN: %clang_dfsan %s -o %t && %run %t
//
// REQUIRES: x86_64-target-arch

View File

@ -1,6 +1,6 @@
// RUN: %clangxx_dfsan -mllvm -dfsan-fast-16-labels=true %s -o %t && %run %t
// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && %run %t
// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && %run %t
// RUN: %clangxx_dfsan %s -o %t && %run %t
// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 %s -o %t && %run %t
// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && %run %t
//
// Test that the state of shadows from a sigaction handler are consistent.
//

View File

@ -1,6 +1,4 @@
// RUN: %clang_dfsan %s -O1 -mllvm -dfsan-fast-16-labels=true -DFAST16_O1 -o %t && %run %t
// RUN: %clang_dfsan %s -O1 -DO1 -o %t && %run %t
// RUN: %clang_dfsan %s -O0 -mllvm -dfsan-fast-16-labels=true -DFAST16_O0 -o %t && %run %t
// RUN: %clang_dfsan %s -O1 -o %t && %run %t
// RUN: %clang_dfsan %s -O0 -DO0 -o %t && %run %t
//
// REQUIRES: x86_64-target-arch
@ -40,13 +38,8 @@ Pair copy_pair2(const Pair pair0) {
int main(void) {
int i = 1;
char *ptr = NULL;
#if defined(FAST16_O1) || defined(FAST16_O0)
dfsan_label i_label = 1;
dfsan_label ptr_label = 2;
#else
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_label ptr_label = dfsan_create_label("ptr", 0);
#endif
dfsan_set_label(i_label, &i, sizeof(i));
dfsan_set_label(ptr_label, &ptr, sizeof(ptr));
@ -56,12 +49,7 @@ int main(void) {
dfsan_label i1_label = dfsan_read_label(&i1, sizeof(i1));
dfsan_label ptr1_label = dfsan_read_label(&ptr1, sizeof(ptr1));
#if defined(O0) || defined(O1)
assert(dfsan_has_label(i1_label, i_label));
assert(dfsan_has_label(i1_label, ptr_label));
assert(dfsan_has_label(ptr1_label, i_label));
assert(dfsan_has_label(ptr1_label, ptr_label));
#elif defined(FAST16_O0)
#if defined(O0)
assert(i1_label == (i_label | ptr_label));
assert(ptr1_label == (i_label | ptr_label));
#else
@ -75,12 +63,7 @@ int main(void) {
dfsan_label i2_label = dfsan_read_label(&i2, sizeof(i2));
dfsan_label ptr2_label = dfsan_read_label(&ptr2, sizeof(ptr2));
#if defined(O0) || defined(O1)
assert(dfsan_has_label(i2_label, i_label));
assert(dfsan_has_label(i2_label, ptr_label));
assert(dfsan_has_label(ptr2_label, i_label));
assert(dfsan_has_label(ptr2_label, ptr_label));
#elif defined(FAST16_O0)
#if defined(O0)
assert(i2_label == (i_label | ptr_label));
assert(ptr2_label == (i_label | ptr_label));
#else
@ -94,12 +77,7 @@ int main(void) {
dfsan_label i3_label = dfsan_read_label(&i3, sizeof(i3));
dfsan_label ptr3_label = dfsan_read_label(&ptr3, sizeof(ptr3));
#if defined(O0) || defined(O1)
assert(dfsan_has_label(i3_label, i_label));
assert(dfsan_has_label(i3_label, ptr_label));
assert(dfsan_has_label(ptr3_label, i_label));
assert(dfsan_has_label(ptr3_label, ptr_label));
#elif defined(FAST16_O0)
#if defined(O0)
assert(i3_label == (i_label | ptr_label));
assert(ptr3_label == (i_label | ptr_label));
#else

View File

@ -2,10 +2,10 @@
REQUIRES: linux, x86_64
# Build the tracer and the test.
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fPIC %S/../../lib/fuzzer/dataflow/DataFlowCallbacks.cpp -o %t-DataFlowCallbacks.o
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/ThreeFunctionsTest.cpp %t-DataFlow*.o -o %t-ThreeFunctionsTestDF
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/Labels20Test.cpp %t-DataFlow*.o -o %t-Labels20TestDF
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/ThreeFunctionsTest.cpp %t-DataFlow*.o -o %t-ThreeFunctionsTestDF
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/Labels20Test.cpp %t-DataFlow*.o -o %t-Labels20TestDF
RUN: %cpp_compiler %S/ThreeFunctionsTest.cpp -o %t-ThreeFunctionsTest
# Dump the function list.

View File

@ -2,9 +2,9 @@
REQUIRES: linux, x86_64
# Build the tracer and the test.
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fPIC %S/../../lib/fuzzer/dataflow/DataFlowCallbacks.cpp -o %t-DataFlowCallbacks.o
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/OnlySomeBytesTest.cpp %t-DataFlow*.o -o %t-DFT
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/OnlySomeBytesTest.cpp %t-DataFlow*.o -o %t-DFT
RUN: %cpp_compiler %S/OnlySomeBytesTest.cpp -o %t-Fuzz
# Test that the fork mode can collect and use the DFT

View File

@ -2,9 +2,9 @@
REQUIRES: linux, x86_64
# Build the tracer and the test.
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fPIC %S/../../lib/fuzzer/dataflow/DataFlowCallbacks.cpp -o %t-DataFlowCallbacks.o
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/OnlySomeBytesTest.cpp %t-DataFlow*.o -o %t-DFT
RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp %S/OnlySomeBytesTest.cpp %t-DataFlow*.o -o %t-DFT
RUN: %cpp_compiler %S/OnlySomeBytesTest.cpp -o %t-Fuzz
# Prepare the inputs.

View File

@ -18,11 +18,9 @@
/// The analysis is based on automatic propagation of data flow labels (also
/// known as taint labels) through a program as it performs computation.
///
/// There are two possible memory layouts. In the first one, each byte of
/// application memory is backed by a shadow memory byte. The shadow byte can
/// represent up to 8 labels. To enable this you must specify the
/// -dfsan-fast-8-labels flag. On Linux/x86_64, memory is then laid out as
/// follows:
/// Each byte of application memory is backed by a shadow memory byte. The
/// shadow byte can represent up to 8 labels. On Linux/x86_64, memory is then
/// laid out as follows:
///
/// +--------------------+ 0x800000000000 (top of memory)
/// | application memory |
@ -30,11 +28,11 @@
/// | |
/// | unused |
/// | |
/// +--------------------+ 0x300200000000 (kUnusedAddr)
/// | union table |
/// +--------------------+ 0x300000000000 (kUnionTableAddr)
/// +--------------------+ 0x300000000000 (kUnusedAddr)
/// | origin |
/// +--------------------+ 0x200000008000 (kOriginAddr)
/// | unused |
/// +--------------------+ 0x200000000000
/// | shadow memory |
/// +--------------------+ 0x100000008000 (kShadowAddr)
/// | unused |
@ -43,34 +41,9 @@
/// +--------------------+ 0x000000000000
///
///
/// In the second memory layout, each byte of application memory is backed by
/// two bytes of shadow memory which hold the label. That means we can represent
/// either 16 labels (with -dfsan-fast-16-labels flag) or 2^16 labels (on the
/// default legacy mode) per byte. On Linux/x86_64, memory is then laid out as
/// follows:
///
/// +--------------------+ 0x800000000000 (top of memory)
/// | application memory |
/// +--------------------+ 0x700000008000 (kAppAddr)
/// | |
/// | unused |
/// | |
/// +--------------------+ 0x300200000000 (kUnusedAddr)
/// | union table |
/// +--------------------+ 0x300000000000 (kUnionTableAddr)
/// | origin |
/// +--------------------+ 0x200000008000 (kOriginAddr)
/// | shadow memory |
/// +--------------------+ 0x000000010000 (kShadowAddr)
/// | reserved by kernel |
/// +--------------------+ 0x000000000000
///
///
/// To derive a shadow memory address from an application memory address,
/// bits 44-46 are cleared to bring the address into the range
/// [0x000000008000,0x100000000000). Then the address is shifted left by 1 to
/// account for the double byte representation of shadow labels and move the
/// address into the shadow memory range. See the function
/// To derive a shadow memory address from an application memory address, bits
/// 45-46 are cleared to bring the address into the range
/// [0x100000008000,0x200000000000). See the function
/// DataFlowSanitizer::getShadowAddress below.
///
/// For more information, please refer to the design document:
@ -230,22 +203,6 @@ static cl::opt<bool> ClEventCallbacks(
cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
cl::Hidden, cl::init(false));
// Use a distinct bit for each base label, enabling faster unions with less
// instrumentation. Limits the max number of base labels to 16.
static cl::opt<bool> ClFast16Labels(
"dfsan-fast-16-labels",
cl::desc("Use more efficient instrumentation, limiting the number of "
"labels to 16."),
cl::Hidden, cl::init(false));
// Use a distinct bit for each base label, enabling faster unions with less
// instrumentation. Limits the max number of base labels to 8.
static cl::opt<bool> ClFast8Labels(
"dfsan-fast-8-labels",
cl::desc("Use more efficient instrumentation, limiting the number of "
"labels to 8."),
cl::Hidden, cl::init(false));
// Controls whether the pass tracks the control flow of select instructions.
static cl::opt<bool> ClTrackSelectControlFlow(
"dfsan-track-select-control-flow",
@ -387,6 +344,8 @@ class DataFlowSanitizer {
friend struct DFSanFunction;
friend class DFSanVisitor;
enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
enum {
OriginWidthBits = 32,
OriginWidthBytes = OriginWidthBits / 8
@ -428,15 +387,11 @@ class DataFlowSanitizer {
WK_Custom
};
unsigned ShadowWidthBits;
unsigned ShadowWidthBytes;
Module *Mod;
LLVMContext *Ctx;
Type *Int8Ptr;
IntegerType *OriginTy;
PointerType *OriginPtrTy;
ConstantInt *OriginBase;
ConstantInt *ZeroOrigin;
/// The shadow type for all primitive types and vector types.
IntegerType *PrimitiveShadowTy;
@ -444,14 +399,14 @@ class DataFlowSanitizer {
IntegerType *IntptrTy;
ConstantInt *ZeroPrimitiveShadow;
ConstantInt *ShadowPtrMask;
ConstantInt *ShadowPtrMul;
ConstantInt *ShadowBase;
ConstantInt *OriginBase;
Constant *ArgTLS;
ArrayType *ArgOriginTLSTy;
Constant *ArgOriginTLS;
Constant *RetvalTLS;
Constant *RetvalOriginTLS;
Constant *ExternalShadowMask;
FunctionType *DFSanUnionFnTy;
FunctionType *DFSanUnionLoadFnTy;
FunctionType *DFSanLoadLabelAndOriginFnTy;
FunctionType *DFSanUnimplementedFnTy;
@ -465,10 +420,7 @@ class DataFlowSanitizer {
FunctionType *DFSanChainOriginIfTaintedFnTy;
FunctionType *DFSanMemOriginTransferFnTy;
FunctionType *DFSanMaybeStoreOriginFnTy;
FunctionCallee DFSanUnionFn;
FunctionCallee DFSanCheckedUnionFn;
FunctionCallee DFSanUnionLoadFn;
FunctionCallee DFSanUnionLoadFastLabelsFn;
FunctionCallee DFSanLoadLabelAndOriginFn;
FunctionCallee DFSanUnimplementedFn;
FunctionCallee DFSanSetLabelFn;
@ -510,7 +462,6 @@ class DataFlowSanitizer {
void initializeCallbackFunctions(Module &M);
void initializeRuntimeFunctions(Module &M);
void injectMetadataGlobals(Module &M);
bool init(Module &M);
/// Advances \p OriginAddr to point to the next 32-bit origin and then loads
@ -518,19 +469,15 @@ class DataFlowSanitizer {
Value *loadNextOrigin(Instruction *Pos, Align OriginAlign,
Value **OriginAddr);
/// Returns whether fast8 or fast16 mode has been specified.
bool hasFastLabelsEnabled();
/// Returns whether the given load byte size is amenable to inlined
/// optimization patterns.
bool hasLoadSizeForFastPath(uint64_t Size);
/// Returns whether the pass tracks origins. Support only fast16 mode in TLS
/// ABI mode.
/// Returns whether the pass tracks origins. Supports only TLS ABI mode.
bool shouldTrackOrigins();
/// Returns whether the pass tracks labels for struct fields and array
/// indices. Support only fast16 mode in TLS ABI mode.
/// indices. Supports only TLS ABI mode.
bool shouldTrackFieldsAndIndices();
/// Returns a zero constant with the shadow type of OrigTy.
@ -590,7 +537,6 @@ struct DFSanFunction {
DenseSet<Instruction *> SkipInsts;
std::vector<Value *> NonZeroChecks;
bool AvoidNewBlocks;
struct CachedShadow {
BasicBlock *Block; // The block where Shadow is defined.
@ -608,9 +554,6 @@ struct DFSanFunction {
DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI)
: DFS(DFS), F(F), IA(DFS.getInstrumentedABI()), IsNativeABI(IsNativeABI) {
DT.recalculate(*F);
// FIXME: Need to track down the register allocator issue which causes poor
// performance in pathological cases with large numbers of basic blocks.
AvoidNewBlocks = F->size() > 1000;
}
/// Computes the shadow address for a given function argument.
@ -702,15 +645,11 @@ private:
/// Returns the shadow value of an argument A.
Value *getShadowForTLSArgument(Argument *A);
/// The fast path of loading shadow in legacy mode.
Value *loadLegacyShadowFast(Value *ShadowAddr, uint64_t Size,
Align ShadowAlign, Instruction *Pos);
/// The fast path of loading shadow in fast-16-label mode.
/// The fast path of loading shadows.
std::pair<Value *, Value *>
loadFast16ShadowFast(Value *ShadowAddr, Value *OriginAddr, uint64_t Size,
Align ShadowAlign, Align OriginAlign, Value *FirstOrigin,
Instruction *Pos);
loadShadowFast(Value *ShadowAddr, Value *OriginAddr, uint64_t Size,
Align ShadowAlign, Align OriginAlign, Value *FirstOrigin,
Instruction *Pos);
Align getOriginAlign(Align InstAlignment);
@ -820,14 +759,6 @@ private:
DataFlowSanitizer::DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles) {
if (ClFast8Labels && ClFast16Labels) {
report_fatal_error(
"cannot set both -dfsan-fast-8-labels and -dfsan-fast-16-labels");
}
ShadowWidthBits = ClFast8Labels ? 8 : 16;
ShadowWidthBytes = ShadowWidthBits / 8;
std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
llvm::append_range(AllABIListFiles, ClABIListFiles);
// FIXME: should we propagate vfs::FileSystem to this constructor?
@ -922,11 +853,6 @@ bool DataFlowSanitizer::isZeroShadow(Value *V) {
return isa<ConstantAggregateZero>(V);
}
bool DataFlowSanitizer::hasFastLabelsEnabled() {
static const bool HasFastLabelsEnabled = ClFast8Labels || ClFast16Labels;
return HasFastLabelsEnabled;
}
bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t Size) {
uint64_t ShadowSize = Size * ShadowWidthBytes;
return ShadowSize % 8 == 0 || ShadowSize == 4;
@ -934,14 +860,12 @@ bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t Size) {
bool DataFlowSanitizer::shouldTrackOrigins() {
static const bool ShouldTrackOrigins =
ClTrackOrigins && getInstrumentedABI() == DataFlowSanitizer::IA_TLS &&
hasFastLabelsEnabled();
ClTrackOrigins && getInstrumentedABI() == DataFlowSanitizer::IA_TLS;
return ShouldTrackOrigins;
}
bool DataFlowSanitizer::shouldTrackFieldsAndIndices() {
return getInstrumentedABI() == DataFlowSanitizer::IA_TLS &&
hasFastLabelsEnabled();
return getInstrumentedABI() == DataFlowSanitizer::IA_TLS;
}
Constant *DataFlowSanitizer::getZeroShadow(Type *OrigTy) {
@ -1100,21 +1024,19 @@ bool DataFlowSanitizer::init(Module &M) {
PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
IntptrTy = DL.getIntPtrType(*Ctx);
ZeroPrimitiveShadow = ConstantInt::getSigned(PrimitiveShadowTy, 0);
ShadowPtrMul = ConstantInt::getSigned(IntptrTy, ShadowWidthBytes);
OriginBase = ConstantInt::get(IntptrTy, 0x200000000000LL);
ZeroOrigin = ConstantInt::getSigned(OriginTy, 0);
// TODO: these should be platform-specific and set in the switch-stmt below.
ShadowBase = ConstantInt::get(IntptrTy, 0x100000008000LL);
OriginBase = ConstantInt::get(IntptrTy, 0x200000008000LL);
switch (TargetTriple.getArch()) {
case Triple::x86_64:
ShadowPtrMask = ClFast8Labels
? ConstantInt::getSigned(IntptrTy, ~0x600000000000LL)
: ConstantInt::getSigned(IntptrTy, ~0x700000000000LL);
ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x600000000000LL);
break;
case Triple::mips64:
case Triple::mips64el:
ShadowPtrMask = ClFast8Labels
? ConstantInt::getSigned(IntptrTy, ~0xE000000000LL)
: ConstantInt::getSigned(IntptrTy, ~0xF000000000LL);
ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xE000000000LL);
break;
case Triple::aarch64:
case Triple::aarch64_be:
@ -1125,9 +1047,6 @@ bool DataFlowSanitizer::init(Module &M) {
report_fatal_error("unsupported triple");
}
Type *DFSanUnionArgs[2] = {PrimitiveShadowTy, PrimitiveShadowTy};
DFSanUnionFnTy =
FunctionType::get(PrimitiveShadowTy, DFSanUnionArgs, /*isVarArg=*/false);
Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
/*isVarArg=*/false);
@ -1306,32 +1225,6 @@ Constant *DataFlowSanitizer::getOrBuildTrampolineFunction(FunctionType *FT,
// Initialize DataFlowSanitizer runtime functions and declare them in the module
void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
{
AttributeList AL;
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
Attribute::NoUnwind);
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
Attribute::ReadNone);
AL = AL.addAttribute(M.getContext(), AttributeList::ReturnIndex,
Attribute::ZExt);
AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
DFSanUnionFn =
Mod->getOrInsertFunction("__dfsan_union", DFSanUnionFnTy, AL);
}
{
AttributeList AL;
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
Attribute::NoUnwind);
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
Attribute::ReadNone);
AL = AL.addAttribute(M.getContext(), AttributeList::ReturnIndex,
Attribute::ZExt);
AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
DFSanCheckedUnionFn =
Mod->getOrInsertFunction("dfsan_union", DFSanUnionFnTy, AL);
}
{
AttributeList AL;
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
@ -1343,17 +1236,6 @@ void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
DFSanUnionLoadFn =
Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy, AL);
}
{
AttributeList AL;
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
Attribute::NoUnwind);
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
Attribute::ReadOnly);
AL = AL.addAttribute(M.getContext(), AttributeList::ReturnIndex,
Attribute::ZExt);
DFSanUnionLoadFastLabelsFn = Mod->getOrInsertFunction(
"__dfsan_union_load_fast16labels", DFSanUnionLoadFnTy, AL);
}
{
AttributeList AL;
AL = AL.addAttribute(M.getContext(), AttributeList::FunctionIndex,
@ -1406,13 +1288,8 @@ void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
"__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
}
DFSanRuntimeFunctions.insert(DFSanUnionFn.getCallee()->stripPointerCasts());
DFSanRuntimeFunctions.insert(
DFSanCheckedUnionFn.getCallee()->stripPointerCasts());
DFSanRuntimeFunctions.insert(
DFSanUnionLoadFn.getCallee()->stripPointerCasts());
DFSanRuntimeFunctions.insert(
DFSanUnionLoadFastLabelsFn.getCallee()->stripPointerCasts());
DFSanRuntimeFunctions.insert(
DFSanLoadLabelAndOriginFn.getCallee()->stripPointerCasts());
DFSanRuntimeFunctions.insert(
@ -1878,13 +1755,16 @@ Value *DataFlowSanitizer::getShadowOffset(Value *Addr, IRBuilder<> &IRB) {
std::pair<Value *, Value *>
DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
Instruction *Pos) {
// Returns ((Addr & shadow_mask) + origin_base) & ~4UL
// Returns ((Addr & shadow_mask) + origin_base - shadow_base) & ~4UL
IRBuilder<> IRB(Pos);
Value *ShadowOffset = getShadowOffset(Addr, IRB);
Value *ShadowPtr = getShadowAddress(Addr, Pos, ShadowOffset);
Value *OriginPtr = nullptr;
if (shouldTrackOrigins()) {
Value *OriginLong = IRB.CreateAdd(ShadowOffset, OriginBase);
static Value *OriginByShadowOffset = ConstantInt::get(
IntptrTy, OriginBase->getZExtValue() - ShadowBase->getZExtValue());
Value *OriginLong = IRB.CreateAdd(ShadowOffset, OriginByShadowOffset);
const Align Alignment = llvm::assumeAligned(InstAlignment.value());
// When alignment is >= 4, Addr must be aligned to 4, otherwise it is UB.
// So Mask is unnecessary.
@ -1900,15 +1780,11 @@ DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
Value *DataFlowSanitizer::getShadowAddress(Value *Addr, Instruction *Pos,
Value *ShadowOffset) {
IRBuilder<> IRB(Pos);
if (!ShadowPtrMul->isOne())
ShadowOffset = IRB.CreateMul(ShadowOffset, ShadowPtrMul);
return IRB.CreateIntToPtr(ShadowOffset, PrimitiveShadowPtrTy);
}
Value *DataFlowSanitizer::getShadowAddress(Value *Addr, Instruction *Pos) {
// Returns (Addr & shadow_mask) x 2
// Returns (Addr & shadow_mask)
IRBuilder<> IRB(Pos);
Value *ShadowOffset = getShadowOffset(Addr, IRB);
return getShadowAddress(Addr, Pos, ShadowOffset);
@ -1961,37 +1837,8 @@ Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) {
Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
IRBuilder<> IRB(Pos);
if (DFS.hasFastLabelsEnabled()) {
CCS.Block = Pos->getParent();
CCS.Shadow = IRB.CreateOr(PV1, PV2);
} else if (AvoidNewBlocks) {
CallInst *Call = IRB.CreateCall(DFS.DFSanCheckedUnionFn, {PV1, PV2});
Call->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
Call->addParamAttr(0, Attribute::ZExt);
Call->addParamAttr(1, Attribute::ZExt);
CCS.Block = Pos->getParent();
CCS.Shadow = Call;
} else {
BasicBlock *Head = Pos->getParent();
Value *Ne = IRB.CreateICmpNE(PV1, PV2);
BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen(
Ne, Pos, /*Unreachable=*/false, DFS.ColdCallWeights, &DT));
IRBuilder<> ThenIRB(BI);
CallInst *Call = ThenIRB.CreateCall(DFS.DFSanUnionFn, {PV1, PV2});
Call->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
Call->addParamAttr(0, Attribute::ZExt);
Call->addParamAttr(1, Attribute::ZExt);
BasicBlock *Tail = BI->getSuccessor(0);
PHINode *Phi =
PHINode::Create(DFS.PrimitiveShadowTy, 2, "", &Tail->front());
Phi->addIncoming(Call, Call->getParent());
Phi->addIncoming(PV1, Head);
CCS.Block = Tail;
CCS.Shadow = Phi;
}
CCS.Block = Pos->getParent();
CCS.Shadow = IRB.CreateOr(PV1, PV2);
std::set<Value *> UnionElems;
if (V1Elems != ShadowElements.end()) {
@ -2116,7 +1963,7 @@ Value *DataFlowSanitizer::loadNextOrigin(Instruction *Pos, Align OriginAlign,
return IRB.CreateAlignedLoad(OriginTy, *OriginAddr, OriginAlign);
}
std::pair<Value *, Value *> DFSanFunction::loadFast16ShadowFast(
std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
Value *ShadowAddr, Value *OriginAddr, uint64_t Size, Align ShadowAlign,
Align OriginAlign, Value *FirstOrigin, Instruction *Pos) {
const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
@ -2135,7 +1982,7 @@ std::pair<Value *, Value *> DFSanFunction::loadFast16ShadowFast(
// Specifically, when the shadow size in bytes (i.e., loaded bytes x shadow
// per byte) is either:
// - a multiple of 8 (common)
// - equal to 4 (only for load32 in fast-8 mode)
// - equal to 4 (only for load32)
//
// For the second case, we can fit the wide shadow in a 32-bit integer. In all
// other cases, we use a 64-bit integer to hold the wide shadow.
@ -2204,84 +2051,6 @@ std::pair<Value *, Value *> DFSanFunction::loadFast16ShadowFast(
: DFS.ZeroOrigin};
}
Value *DFSanFunction::loadLegacyShadowFast(Value *ShadowAddr, uint64_t Size,
Align ShadowAlign,
Instruction *Pos) {
// Fast path for the common case where each byte has identical shadow: load
// shadow 64 (or 32) bits at a time, fall out to a __dfsan_union_load call if
// any shadow is non-equal.
BasicBlock *FallbackBB = BasicBlock::Create(*DFS.Ctx, "", F);
IRBuilder<> FallbackIRB(FallbackBB);
CallInst *FallbackCall = FallbackIRB.CreateCall(
DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
FallbackCall->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
const uint64_t ShadowSize = Size * DFS.ShadowWidthBytes;
assert(Size >= 4 && "Not large enough load size for fast path!");
// Same as in loadFast16AShadowsFast. In the case of load32, we can fit the
// wide shadow in a 32-bit integer instead.
Type *WideShadowTy =
ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) : Type::getInt64Ty(*DFS.Ctx);
// Compare each of the shadows stored in the loaded 64 bits to each other,
// by computing (WideShadow rotl ShadowWidthBits) == WideShadow.
IRBuilder<> IRB(Pos);
unsigned WideShadowBitWidth = WideShadowTy->getIntegerBitWidth();
Value *WideAddr = IRB.CreateBitCast(ShadowAddr, WideShadowTy->getPointerTo());
Value *WideShadow =
IRB.CreateAlignedLoad(WideShadowTy, WideAddr, ShadowAlign);
Value *TruncShadow = IRB.CreateTrunc(WideShadow, DFS.PrimitiveShadowTy);
Value *ShlShadow = IRB.CreateShl(WideShadow, DFS.ShadowWidthBits);
Value *ShrShadow =
IRB.CreateLShr(WideShadow, WideShadowBitWidth - DFS.ShadowWidthBits);
Value *RotShadow = IRB.CreateOr(ShlShadow, ShrShadow);
Value *ShadowsEq = IRB.CreateICmpEQ(WideShadow, RotShadow);
BasicBlock *Head = Pos->getParent();
BasicBlock *Tail = Head->splitBasicBlock(Pos->getIterator());
if (DomTreeNode *OldNode = DT.getNode(Head)) {
std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end());
DomTreeNode *NewNode = DT.addNewBlock(Tail, Head);
for (auto *Child : Children)
DT.changeImmediateDominator(Child, NewNode);
}
// In the following code LastBr will refer to the previous basic block's
// conditional branch instruction, whose true successor is fixed up to point
// to the next block during the loop below or to the tail after the final
// iteration.
BranchInst *LastBr = BranchInst::Create(FallbackBB, FallbackBB, ShadowsEq);
ReplaceInstWithInst(Head->getTerminator(), LastBr);
DT.addNewBlock(FallbackBB, Head);
const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs < Size;
ByteOfs += BytesPerWideShadow) {
BasicBlock *NextBB = BasicBlock::Create(*DFS.Ctx, "", F);
DT.addNewBlock(NextBB, LastBr->getParent());
IRBuilder<> NextIRB(NextBB);
WideAddr = NextIRB.CreateGEP(WideShadowTy, WideAddr,
ConstantInt::get(DFS.IntptrTy, 1));
Value *NextWideShadow =
NextIRB.CreateAlignedLoad(WideShadowTy, WideAddr, ShadowAlign);
ShadowsEq = NextIRB.CreateICmpEQ(WideShadow, NextWideShadow);
LastBr->setSuccessor(0, NextBB);
LastBr = NextIRB.CreateCondBr(ShadowsEq, FallbackBB, FallbackBB);
}
LastBr->setSuccessor(0, Tail);
FallbackIRB.CreateBr(Tail);
PHINode *Shadow =
PHINode::Create(DFS.PrimitiveShadowTy, 2, "", &Tail->front());
Shadow->addIncoming(FallbackCall, FallbackBB);
Shadow->addIncoming(TruncShadow, LastBr->getParent());
return Shadow;
}
std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
Value *Addr, uint64_t Size, Align InstAlignment, Instruction *Pos) {
const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
@ -2369,21 +2138,14 @@ std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
}
}
bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(Size);
bool HasFastLabelsEnabled = DFS.hasFastLabelsEnabled();
if (HasFastLabelsEnabled && HasSizeForFastPath)
return loadFast16ShadowFast(ShadowAddr, OriginAddr, Size, ShadowAlign,
OriginAlign, Origin, Pos);
if (!AvoidNewBlocks && HasSizeForFastPath)
return {loadLegacyShadowFast(ShadowAddr, Size, ShadowAlign, Pos), Origin};
if (HasSizeForFastPath)
return loadShadowFast(ShadowAddr, OriginAddr, Size, ShadowAlign,
OriginAlign, Origin, Pos);
IRBuilder<> IRB(Pos);
FunctionCallee &UnionLoadFn = HasFastLabelsEnabled
? DFS.DFSanUnionLoadFastLabelsFn
: DFS.DFSanUnionLoadFn;
CallInst *FallbackCall = IRB.CreateCall(
UnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
FallbackCall->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
return {FallbackCall, Origin};
}

View File

@ -1,6 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-args-abi -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-args-abi -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-args-abi -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,6 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI
; RUN: opt < %s -dfsan -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s --check-prefixes=CHECK,LEGACY
; RUN: opt < %s -dfsan -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI
; RUN: opt < %s -dfsan -dfsan-args-abi -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s --check-prefixes=CHECK,ARGS_ABI
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -33,19 +31,12 @@ define {i1, i7} @call_functional({i32, i1} %a, [2 x i7] %b) {
; TLS_ABI-NEXT: %[[#REG+10]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } %[[#REG+9]], i[[#SBITS]] %[[#REG+8]], 1
; TLS_ABI: store { i[[#SBITS]], i[[#SBITS]] } %[[#REG+10]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
; LEGACY: @"dfs$call_functional"
; LEGACY: [[B:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[A:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; LEGACY: [[U:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext [[A]], i[[#SBITS]] zeroext [[B]])
; LEGACY: [[PH:%.*]] = phi i[[#SBITS]] [ [[U]], {{.*}} ], [ [[A]], {{.*}} ]
; LEGACY: store i[[#SBITS]] [[PH]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; ARGS_ABI: @"dfs$call_functional"
; ARGS_ABI: [[U:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext %2, i[[#SBITS]] zeroext %3)
; ARGS_ABI: [[PH:%.*]] = phi i[[#SBITS]] [ %7, {{.*}} ], [ %2, {{.*}} ]
; ARGS_ABI: [[R0:%.*]] = insertvalue { { i1, i7 }, i[[#SBITS]] } undef, { i1, i7 } %r, 0
; ARGS_ABI: [[R1:%.*]] = insertvalue { { i1, i7 }, i[[#SBITS]] } [[R0]], i[[#SBITS]] [[PH]], 1
; ARGS_ABI: ret { { i1, i7 }, i[[#SBITS]] } [[R1]]
; ARGS_ABI: @"dfs$call_functional"({ i32, i1 } %0, [2 x i7] %1, i[[#SBITS]] %2, i[[#SBITS]] %3)
; ARGS_ABI: %[[#U:]] = or i[[#SBITS]] %2, %3
; ARGS_ABI: %r = call { i1, i7 } @functional({ i32, i1 } %0, [2 x i7] %1)
; ARGS_ABI: %[[#R:]] = insertvalue { { i1, i7 }, i[[#SBITS]] } undef, { i1, i7 } %r, 0
; ARGS_ABI: %[[#R+1]] = insertvalue { { i1, i7 }, i[[#SBITS]] } %[[#R]], i[[#SBITS]] %[[#U]], 1
; ARGS_ABI: ret { { i1, i7 }, i[[#SBITS]] } %[[#R+1]]
%r = call {i1, i7} @functional({i32, i1} %a, [2 x i7] %b)
ret {i1, i7} %r

View File

@ -7,13 +7,12 @@ target triple = "x86_64-unknown-linux-gnu"
define i8 @add(i8 %a, i8 %b) {
; CHECK: @"dfs$add"
; CHECK-DAG: %[[ALABEL:.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[ARGTLSTYPE:\[100 x i64\]]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; CHECK-DAG: %[[BLABEL:.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[ARGTLSTYPE]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[UNION:.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext %[[ALABEL]], i[[#SBITS]] zeroext %[[BLABEL]])
; CHECK: %[[ADDLABEL:.*]] = phi i[[#SBITS]] [ %[[UNION]], {{.*}} ], [ %[[ALABEL]], {{.*}} ]
; CHECK: add i8
; CHECK: store i[[#SBITS]] %[[ADDLABEL]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: ret i8
; CHECK-DAG: %[[#ALABEL:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[ARGTLSTYPE:\[100 x i64\]]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; CHECK-DAG: %[[#BLABEL:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[ARGTLSTYPE]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[#UNION:]] = or i[[#SBITS]] %[[#ALABEL]], %[[#BLABEL]]
; CHECK: %c = add i8 %a, %b
; CHECK: store i[[#SBITS]] %[[#UNION]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: ret i8 %c
%c = add i8 %a, %b
ret i8 %c
}
@ -22,10 +21,10 @@ define i8 @sub(i8 %a, i8 %b) {
; CHECK: @"dfs$sub"
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: sub i8
; CHECK: or i[[#SBITS]]
; CHECK: %c = sub i8 %a, %b
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
; CHECK: ret i8 %c
%c = sub i8 %a, %b
ret i8 %c
}
@ -34,10 +33,10 @@ define i8 @mul(i8 %a, i8 %b) {
; CHECK: @"dfs$mul"
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: mul i8
; CHECK: or i[[#SBITS]]
; CHECK: %c = mul i8 %a, %b
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
; CHECK: ret i8 %c
%c = mul i8 %a, %b
ret i8 %c
}
@ -46,10 +45,10 @@ define i8 @sdiv(i8 %a, i8 %b) {
; CHECK: @"dfs$sdiv"
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: sdiv i8
; CHECK: or i[[#SBITS]]
; CHECK: %c = sdiv i8 %a, %b
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
; CHECK: ret i8 %c
%c = sdiv i8 %a, %b
ret i8 %c
}
@ -58,10 +57,10 @@ define i8 @udiv(i8 %a, i8 %b) {
; CHECK: @"dfs$udiv"
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: udiv i8
; CHECK: or i[[#SBITS]]
; CHECK: %c = udiv i8 %a, %b
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
; CHECK: ret i8 %c
%c = udiv i8 %a, %b
ret i8 %c
}
@ -69,9 +68,9 @@ define i8 @udiv(i8 %a, i8 %b) {
define double @fneg(double %a) {
; CHECK: @"dfs$fneg"
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: fneg double
; CHECK: %c = fneg double %a
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret double
; CHECK: ret double %c
%c = fneg double %a
ret double %c
}

View File

@ -1,15 +1,9 @@
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,LEGACY
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-event-callbacks=true -S | FileCheck %s --check-prefixes=CHECK,EVENT_CALLBACKS
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-event-callbacks=true -S | FileCheck %s --check-prefixes=CHECK,EVENT_CALLBACKS
; RUN: opt < %s -dfsan -dfsan-event-callbacks=true -S | FileCheck %s --check-prefixes=CHECK,EVENT_CALLBACKS
; RUN: opt < %s -dfsan -dfsan-args-abi -S | FileCheck %s --check-prefixes=CHECK,ARGS_ABI
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -102,13 +96,6 @@ define [1 x i1] @load_array1([1 x i1]* %p) {
; FAST: [[S1:%.*]] = insertvalue [1 x i[[#SBITS]]] undef, i[[#SBITS]] [[U]], 0
; FAST: store [1 x i[[#SBITS]]] [[S1]], [1 x i[[#SBITS]]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to [1 x i[[#SBITS]]]*), align [[ALIGN]]
; LEGACY: @"dfs$load_array1"
; LEGACY: [[P:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[L:%.*]] = load i[[#SBITS]], i[[#SBITS]]* {{.*}}, align [[#SBYTES]]
; LEGACY: [[U:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext [[L]], i[[#SBITS]] zeroext [[P]])
; LEGACY: [[PH:%.*]] = phi i[[#SBITS]] [ [[U]], {{.*}} ], [ [[L]], {{.*}} ]
; LEGACY: store i[[#SBITS]] [[PH]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
%a = load [1 x i1], [1 x i1]* %p
ret [1 x i1] %a
}
@ -164,13 +151,6 @@ define [4 x i1] @load_array4([4 x i1]* %p) {
; FAST: [[S4:%.*]] = insertvalue [4 x i[[#SBITS]]] [[S3]], i[[#SBITS]] [[O]], 3
; FAST: store [4 x i[[#SBITS]]] [[S4]], [4 x i[[#SBITS]]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to [4 x i[[#SBITS]]]*), align 2
; LEGACY: @"dfs$load_array4"
; LEGACY: [[P:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[PH1:%.*]] = phi i[[#SBITS]]
; LEGACY: [[U:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext [[PH1]], i[[#SBITS]] zeroext [[P]])
; LEGACY: [[PH:%.*]] = phi i[[#SBITS]] [ [[U]], {{.*}} ], [ [[PH1]], {{.*}} ]
; LEGACY: store i[[#SBITS]] [[PH]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
%a = load [4 x i1], [4 x i1]* %p
ret [4 x i1] %a
}
@ -220,13 +200,6 @@ define void @store_zero_array([4 x i1]* %p) {
}
define void @store_array2([2 x i1] %a, [2 x i1]* %p) {
; LEGACY: @"dfs$store_array2"
; LEGACY: [[S:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[SP0:%.*]] = getelementptr i[[#SBITS]], i[[#SBITS]]* [[SP:%.*]], i32 0
; LEGACY: store i[[#SBITS]] [[S]], i[[#SBITS]]* [[SP0]], align [[#SBYTES]]
; LEGACY: [[SP1:%.*]] = getelementptr i[[#SBITS]], i[[#SBITS]]* [[SP]], i32 1
; LEGACY: store i[[#SBITS]] [[S]], i[[#SBITS]]* [[SP1]], align [[#SBYTES]]
; EVENT_CALLBACKS: @"dfs$store_array2"
; EVENT_CALLBACKS: [[E12:%.*]] = or i[[#SBITS]]
; EVENT_CALLBACKS: [[P:%.*]] = bitcast [2 x i1]* %p to i8*

View File

@ -1,9 +1,6 @@
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK16
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -dfsan-instrument-with-call-threshold=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK16,CHECK_ORIGIN
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -dfsan-instrument-with-call-threshold=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK16,CHECK_ORIGIN
; RUN: opt < %s -dfsan -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-instrument-with-call-threshold=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -21,7 +18,6 @@ entry:
; CHECK-NOT: @__dfsan_arg_tls
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -42,7 +38,6 @@ define i32 @AtomicRmwMax(i32* %p, i32 %x) {
; CHECK-NOT: @__dfsan_arg_tls
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -65,7 +60,6 @@ define i32 @Cmpxchg(i32* %p, i32 %a, i32 %b) {
; CHECK-NOT: @__dfsan_arg_tls
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -89,7 +83,6 @@ define i32 @CmpxchgMonotonic(i32* %p, i32 %a, i32 %b) {
; CHECK-NOT: @__dfsan_arg_tls
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -213,7 +206,6 @@ define void @AtomicStore(i32* %p, i32 %x) {
; CHECK_ORIGIN-NOT: 35184372088832
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -234,7 +226,6 @@ define void @AtomicStoreRelease(i32* %p, i32 %x) {
; CHECK_ORIGIN-NOT: 35184372088832
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -255,7 +246,6 @@ define void @AtomicStoreMonotonic(i32* %p, i32 %x) {
; CHECK_ORIGIN-NOT: 35184372088832
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]
@ -276,7 +266,6 @@ define void @AtomicStoreUnordered(i32* %p, i32 %x) {
; CHECK_ORIGIN-NOT: 35184372088832
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:INTP+2]] = mul i64 %[[#INTP+1]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR64:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#NUM_BITS:mul(SBITS,4)]]*
; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SHADOW_PTR64]], align [[#SBYTES]]

View File

@ -1,6 +1,5 @@
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,CHECK_NO_ORIGIN -DSHADOW_MASK=-123145302310913
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN -DSHADOW_MASK=-123145302310913
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN -DSHADOW_MASK=-105553116266497
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,CHECK_NO_ORIGIN -DSHADOW_MASK=-105553116266497 --dump-input-context=100
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN -DSHADOW_MASK=-105553116266497 --dump-input-context=100
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -35,20 +34,11 @@ define void @store(i8* %p) {
; CHECK: declare void @__dfsan_mem_transfer_callback(i[[#SBITS]]*, i64)
; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]])
; CHECK: ; Function Attrs: nounwind readnone
; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext, i[[#SBITS]] zeroext) #0
; CHECK: ; Function Attrs: nounwind readnone
; CHECK-NEXT: declare zeroext i[[#SBITS]] @dfsan_union(i[[#SBITS]] zeroext, i[[#SBITS]] zeroext) #0
; CHECK: ; Function Attrs: nounwind readonly
; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load(i[[#SBITS]]*, i64)
; CHECK: ; Function Attrs: nounwind readonly
; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load(i[[#SBITS]]*, i64) #1
; CHECK: ; Function Attrs: nounwind readonly
; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load_fast16labels(i[[#SBITS]]*, i64) #1
; CHECK: ; Function Attrs: nounwind readonly
; CHECK-NEXT: declare zeroext i64 @__dfsan_load_label_and_origin(i8*, i64) #1
; CHECK-NEXT: declare zeroext i64 @__dfsan_load_label_and_origin(i8*, i64)
; CHECK: declare void @__dfsan_unimplemented(i8*)
; CHECK: declare void @__dfsan_set_label(i[[#SBITS]] zeroext, i32 zeroext, i8*, i64)

View File

@ -1,6 +1,4 @@
; RUN: opt < %s -dfsan -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -S | FileCheck %s
; RUN: opt < %s -passes=dfsan -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-combine-offset-labels-on-gep=false -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
; RUN: opt < %s -dfsan -dfsan-combine-offset-labels-on-gep=false -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-combine-offset-labels-on-gep=false -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-combine-offset-labels-on-gep=false -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,15 +1,12 @@
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,CHECK16
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,CHECK16
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK
; RUN: opt < %s -dfsan -S | FileCheck %s
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
define i32 @test(i32 %a, i32* nocapture readonly %b) #0 {
; CHECK: @"dfs$test"
; CHECK: %[[RV:.*]] load{{.*}}__dfsan_shadow_ptr_mask
; CHECK: ptrtoint i32* {{.*}} to i64
; CHECK: and {{.*}}%[[RV:.*]]
; CHECK16: mul i64
; CHECK: @"dfs$test"
; CHECK: %[[RV:.*]] load{{.*}}__dfsan_shadow_ptr_mask
; CHECK: ptrtoint i32* {{.*}} to i64
; CHECK: and {{.*}}%[[RV:.*]]
%1 = load i32, i32* %b, align 4
%2 = add nsw i32 %1, %a
ret i32 %2

View File

@ -1,172 +0,0 @@
; Test that -dfsan-fast-16-labels mode uses inline ORs rather than calling
; __dfsan_union or __dfsan_union_load.
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -S | FileCheck %s --implicit-check-not="call{{.*}}__dfsan_union" --check-prefixes=CHECK,CHECK16
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -S | FileCheck %s --implicit-check-not="call{{.*}}__dfsan_union" --check-prefixes=CHECK,CHECK8
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]]
; CHECK: @__dfsan_retval_tls = external thread_local(initialexec) global [[TLS_ARR]]
; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]]
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
define i8 @add(i8 %a, i8 %b) {
; CHECK-LABEL: define i8 @"dfs$add"
; CHECK-DAG: %[[ALABEL:.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; CHECK-DAG: %[[BLABEL:.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[ADDLABEL:.*]] = or i[[#SBITS]] %[[ALABEL]], %[[BLABEL]]
; CHECK: %c = add i8 %a, %b
; CHECK: store i[[#SBITS]] %[[ADDLABEL]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: ret i8 %c
%c = add i8 %a, %b
ret i8 %c
}
define i8 @load8(i8* %p) {
; CHECK-LABEL: define i8 @"dfs$load8"
; CHECK-SAME: (i8* %[[PADDR:.*]])
; CHECK-NEXT: %[[#ARG:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#R:]] = ptrtoint i8* %[[PADDR]] to i64
; CHECK-NEXT: %[[#PS:R+1]] = and i64 %[[#R]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#PS:R+2]] = mul i64 %[[#R+1]], 2
; CHECK-NEXT: %[[#SADDR:]] = inttoptr i64 %[[#PS]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#S:]] = load i[[#SBITS]], i[[#SBITS]]* %[[#SADDR]]
; CHECK-NEXT: %[[#S_OUT:S+1]] = or i[[#SBITS]] %[[#S]], %[[#ARG]]
; CHECK-NEXT: %a = load i8, i8* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#S_OUT]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i8 %a
%a = load i8, i8* %p
ret i8 %a
}
define i16 @load16(i16* %p) {
; CHECK-LABEL: define i16 @"dfs$load16"
; CHECK-SAME: (i16* %[[PADDR:.*]])
; CHECK-NEXT: %[[#ARG:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#R:]] = ptrtoint i16* %[[PADDR]] to i64
; CHECK-NEXT: %[[#PS:R+1]] = and i64 %[[#R]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#PS:R+2]] = mul i64 %[[#R+1]], 2
; CHECK-NEXT: %[[#SADDR:]] = inttoptr i64 %[[#PS]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SADDR+1]] = getelementptr i[[#SBITS]], i[[#SBITS]]* %[[#SADDR]], i64 1
; CHECK-NEXT: %[[#S:]] = load i[[#SBITS]], i[[#SBITS]]* %[[#SADDR]]
; CHECK-NEXT: %[[#S+1]] = load i[[#SBITS]], i[[#SBITS]]* %[[#SADDR+1]]
; CHECK-NEXT: %[[#S+2]] = or i[[#SBITS]] %[[#S]], %[[#S+1]]
; CHECK-NEXT: %[[#S_OUT:S+3]] = or i[[#SBITS]] %[[#S+2]], %[[#ARG]]
; CHECK-NEXT: %a = load i16, i16* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#S_OUT]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i16 %a
%a = load i16, i16* %p
ret i16 %a
}
define i32 @load32(i32* %p) {
; CHECK-LABEL: define i32 @"dfs$load32"
; CHECK-SAME: (i32* %[[PADDR:.*]])
; CHECK-NEXT: %[[#ARG:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#R:]] = ptrtoint i32* %[[PADDR]] to i64
; CHECK-NEXT: %[[#PS:R+1]] = and i64 %[[#R]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#PS:R+2]] = mul i64 %[[#R+1]], 2
; CHECK-NEXT: %[[#SADDR:]] = inttoptr i64 %[[#PS]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SADDR+1]] = bitcast i[[#SBITS]]* %[[#SADDR]] to i[[#WBITS:mul(SBITS,4)]]*
; CHECK-NEXT: %[[#WS:]] = load i[[#WBITS]], i[[#WBITS]]* %[[#SADDR+1]]
; CHECK-NEXT: %[[#WS+1]] = lshr i[[#WBITS]] %[[#WS]], [[#mul(SBITS,2)]]
; CHECK-NEXT: %[[#WS+2]] = or i[[#WBITS]] %[[#WS]], %[[#WS+1]]
; CHECK-NEXT: %[[#WS+3]] = lshr i[[#WBITS]] %[[#WS+2]], [[#SBITS]]
; CHECK-NEXT: %[[#WS+4]] = or i[[#WBITS]] %[[#WS+2]], %[[#WS+3]]
; CHECK-NEXT: %[[#WS+5]] = trunc i[[#WBITS]] %[[#WS+4]] to i[[#SBITS]]
; CHECK-NEXT: %[[#S_OUT:WS+6]] = or i[[#SBITS]] %[[#WS+5]], %[[#ARG]]
; CHECK-NEXT: %a = load i32, i32* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#S_OUT]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i32 %a
%a = load i32, i32* %p
ret i32 %a
}
define i64 @load64(i64* %p) {
; CHECK-LABEL: define i64 @"dfs$load64"
; CHECK-SAME: (i64* %[[PADDR:.*]])
; CHECK-NEXT: %[[#ARG:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#R:]] = ptrtoint i64* %[[PADDR]] to i64
; CHECK-NEXT: %[[#PS:R+1]] = and i64 %[[#R]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#PS:R+2]] = mul i64 %[[#R+1]], 2
; CHECK-NEXT: %[[#SADDR:]] = inttoptr i64 %[[#PS]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SADDR+1]] = bitcast i[[#SBITS]]* %[[#SADDR]] to i64*
; CHECK-NEXT: %[[#WS:]] = load i64, i64* %[[#SADDR+1]]
; COMM: On fast16, the 2x64 shadow bits need to be ORed first.
; CHECK16-NEXT: %[[#SADDR_NEXT:]] = getelementptr i64, i64* %[[#SADDR+1]], i64 1
; CHECK16-NEXT: %[[#WS_NEXT:]] = load i64, i64* %[[#SADDR_NEXT]]
; CHECK16-NEXT: %[[#WS:]] = or i64 %[[#WS]], %[[#WS_NEXT]]
; CHECK16-NEXT: %[[#WS+1]] = lshr i64 %[[#WS]], 32
; CHECK16-NEXT: %[[#WS+2]] = or i64 %[[#WS]], %[[#WS+1]]
; CHECK16-NEXT: %[[#WS+3]] = lshr i64 %[[#WS+2]], 16
; CHECK16-NEXT: %[[#WS+4]] = or i64 %[[#WS+2]], %[[#WS+3]]
; CHECK16-NEXT: %[[#WS+5]] = trunc i64 %[[#WS+4]] to i[[#SBITS]]
; CHECK16-NEXT: %[[#S_OUT:]] = or i[[#SBITS]] %[[#WS+5]], %[[#ARG]]
; COMM: On fast8, no need to OR the wide shadow but one more shift is needed.
; CHECK8-NEXT: %[[#WS+1]] = lshr i64 %[[#WS]], 32
; CHECK8-NEXT: %[[#WS+2]] = or i64 %[[#WS]], %[[#WS+1]]
; CHECK8-NEXT: %[[#WS+3]] = lshr i64 %[[#WS+2]], 16
; CHECK8-NEXT: %[[#WS+4]] = or i64 %[[#WS+2]], %[[#WS+3]]
; CHECK8-NEXT: %[[#WS+5]] = lshr i64 %[[#WS+4]], 8
; CHECK8-NEXT: %[[#WS+6]] = or i64 %[[#WS+4]], %[[#WS+5]]
; CHECK8-NEXT: %[[#WS+7]] = trunc i64 %[[#WS+6]] to i[[#SBITS]]
; CHECK8-NEXT: %[[#S_OUT:]] = or i[[#SBITS]] %[[#WS+7]], %[[#ARG]]
; CHECK-NEXT: %a = load i64, i64* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#S_OUT]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i64 %a
%a = load i64, i64* %p
ret i64 %a
}
define i128 @load128(i128* %p) {
; CHECK-LABEL: define i128 @"dfs$load128"
; CHECK-SAME: (i128* %[[PADDR:.*]])
; CHECK-NEXT: %[[#ARG:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#R:]] = ptrtoint i128* %[[PADDR]] to i64
; CHECK-NEXT: %[[#PS:R+1]] = and i64 %[[#R]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#PS:R+2]] = mul i64 %[[#R+1]], 2
; CHECK-NEXT: %[[#SADDR:]] = inttoptr i64 %[[#PS]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SADDR+1]] = bitcast i[[#SBITS]]* %[[#SADDR]] to i64*
; CHECK-NEXT: %[[#S:]] = load i64, i64* %[[#SADDR+1]]
; CHECK-NEXT: %[[#S+1]] = getelementptr i64, i64* %[[#SADDR+1]], i64 1
; CHECK-NEXT: %[[#S+2]] = load i64, i64* %[[#S+1]]
; CHECK-NEXT: %[[#WS:S+3]] = or i64 %[[#S]], %[[#S+2]]
; COMM: On fast16, we need to OR 4x64bits for the wide shadow, before ORing its bytes.
; CHECK16-NEXT: %[[#S+4]] = getelementptr i64, i64* %[[#S+1]], i64 1
; CHECK16-NEXT: %[[#S+5]] = load i64, i64* %[[#S+4]]
; CHECK16-NEXT: %[[#S+6]] = or i64 %[[#S+3]], %[[#S+5]]
; CHECK16-NEXT: %[[#S+7]] = getelementptr i64, i64* %[[#S+4]], i64 1
; CHECK16-NEXT: %[[#S+8]] = load i64, i64* %[[#S+7]]
; CHECK16-NEXT: %[[#WS:S+9]] = or i64 %[[#S+6]], %[[#S+8]]
; CHECK16-NEXT: %[[#WS+1]] = lshr i64 %[[#WS]], 32
; CHECK16-NEXT: %[[#WS+2]] = or i64 %[[#WS]], %[[#WS+1]]
; CHECK16-NEXT: %[[#WS+3]] = lshr i64 %[[#WS+2]], 16
; CHECK16-NEXT: %[[#WS+4]] = or i64 %[[#WS+2]], %[[#WS+3]]
; CHECK16-NEXT: %[[#WS+5]] = trunc i64 %[[#WS+4]] to i[[#SBITS]]
; CHECK16-NEXT: %[[#S_OUT:]] = or i[[#SBITS]] %[[#WS+5]], %[[#ARG]]
; COMM: On fast8, we need to OR 2x64bits for the wide shadow, before ORing its bytes (one more shift).
; CHECK8-NEXT: %[[#WS+1]] = lshr i64 %[[#WS]], 32
; CHECK8-NEXT: %[[#WS+2]] = or i64 %[[#WS]], %[[#WS+1]]
; CHECK8-NEXT: %[[#WS+3]] = lshr i64 %[[#WS+2]], 16
; CHECK8-NEXT: %[[#WS+4]] = or i64 %[[#WS+2]], %[[#WS+3]]
; CHECK8-NEXT: %[[#WS+5]] = lshr i64 %[[#WS+4]], 8
; CHECK8-NEXT: %[[#WS+6]] = or i64 %[[#WS+4]], %[[#WS+5]]
; CHECK8-NEXT: %[[#WS+7]] = trunc i64 %[[#WS+6]] to i[[#SBITS]]
; CHECK8-NEXT: %[[#S_OUT:]] = or i[[#SBITS]] %[[#WS+7]], %[[#ARG]]
; CHECK-NEXT: %a = load i128, i128* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#S_OUT]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i128 %a
%a = load i128, i128* %p
ret i128 %a
}

View File

@ -1,176 +1,156 @@
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-load=1 -S | FileCheck %s --check-prefix=COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-load=0 -S | FileCheck %s --check-prefix=NO_COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-load=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define {} @load0({}* %p) {
; COMBINE_PTR_LABEL: @"dfs$load0"
; COMBINE_PTR_LABEL: load
; COMBINE_PTR_LABEL-NOT: load
; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]]
; CHECK: @__dfsan_retval_tls = external thread_local(initialexec) global [[TLS_ARR]]
; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]]
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
define {} @load0({}* %p) {
; CHECK-LABEL: @"dfs$load0"
; CHECK-NEXT: %a = load {}, {}* %p, align 1
; CHECK-NEXT: store {} zeroinitializer, {}* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to {}*), align [[ALIGN:2]]
; CHECK-NEXT: ret {} %a
; NO_COMBINE_PTR_LABEL: @"dfs$load0"
; NO_COMBINE_PTR_LABEL: load
; NO_COMBINE_PTR_LABEL-NOT: load
%a = load {}, {}* %p
ret {} %a
}
define i8 @load8(i8* %p) {
; COMBINE_PTR_LABEL: @"dfs$load8"
; COMBINE_PTR_LABEL: load i16, i16*
; COMBINE_PTR_LABEL: ptrtoint i8* {{.*}} to i64
; COMBINE_PTR_LABEL: and i64
; COMBINE_PTR_LABEL: mul i64
; COMBINE_PTR_LABEL: inttoptr i64
; COMBINE_PTR_LABEL: load i16, i16*
; COMBINE_PTR_LABEL: icmp ne i16
; COMBINE_PTR_LABEL: call zeroext i16 @__dfsan_union
; COMBINE_PTR_LABEL: load i8, i8*
; COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; COMBINE_PTR_LABEL: ret i8
; NO_COMBINE_PTR_LABEL: @"dfs$load8"
; NO_COMBINE_PTR_LABEL: ptrtoint i8*
; NO_COMBINE_PTR_LABEL: and i64
; NO_COMBINE_PTR_LABEL: mul i64
; NO_COMBINE_PTR_LABEL: inttoptr i64 {{.*}} to i16*
; NO_COMBINE_PTR_LABEL: load i16, i16*
; NO_COMBINE_PTR_LABEL: load i8, i8*
; NO_COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; NO_COMBINE_PTR_LABEL: ret i8
; CHECK-LABEL: @"dfs$load8"
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i8* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW:]] = load i[[#SBITS]], i[[#SBITS]]* %[[#SHADOW_PTR]]
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; CHECK-NEXT: %a = load i8, i8* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#SHADOW]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i8 %a
%a = load i8, i8* %p
ret i8 %a
}
define i16 @load16(i16* %p) {
; COMBINE_PTR_LABEL: @"dfs$load16"
; COMBINE_PTR_LABEL: ptrtoint i16*
; COMBINE_PTR_LABEL: and i64
; COMBINE_PTR_LABEL: mul i64
; COMBINE_PTR_LABEL: inttoptr i64 {{.*}} i16*
; COMBINE_PTR_LABEL: getelementptr i16
; COMBINE_PTR_LABEL: load i16, i16*
; COMBINE_PTR_LABEL: load i16, i16*
; COMBINE_PTR_LABEL: icmp ne
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMBINE_PTR_LABEL: icmp ne i16
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMBINE_PTR_LABEL: load i16, i16*
; COMBINE_PTR_LABEL: store {{.*}} @__dfsan_retval_tls
; COMBINE_PTR_LABEL: ret i16
; CHECK-LABEL: @"dfs$load16"
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i16* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW_PTR+1]] = getelementptr i[[#SBITS]], i[[#SBITS]]* %[[#SHADOW_PTR]], i64 1
; CHECK-NEXT: %[[#SHADOW:]] = load i[[#SBITS]], i[[#SBITS]]* %[[#SHADOW_PTR]]
; CHECK-NEXT: %[[#SHADOW+1]] = load i[[#SBITS]], i[[#SBITS]]* %[[#SHADOW_PTR+1]]
; NO_COMBINE_PTR_LABEL: @"dfs$load16"
; NO_COMBINE_PTR_LABEL: ptrtoint i16*
; NO_COMBINE_PTR_LABEL: and i64
; NO_COMBINE_PTR_LABEL: mul i64
; NO_COMBINE_PTR_LABEL: inttoptr i64 {{.*}} i16*
; NO_COMBINE_PTR_LABEL: getelementptr i16, i16*
; NO_COMBINE_PTR_LABEL: load i16, i16*
; NO_COMBINE_PTR_LABEL: load i16, i16*
; NO_COMBINE_PTR_LABEL: icmp ne i16
; NO_COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; NO_COMBINE_PTR_LABEL: load i16, i16*
; NO_COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; NO_COMBINE_PTR_LABEL: ret i16
; CHECK-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#SHADOW+1]]
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; CHECK-NEXT: %a = load i16, i16* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#SHADOW]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i16 %a
%a = load i16, i16* %p
ret i16 %a
}
define i32 @load32(i32* %p) {
; COMBINE_PTR_LABEL: @"dfs$load32"
; COMBINE_PTR_LABEL: ptrtoint i32*
; COMBINE_PTR_LABEL: and i64
; COMBINE_PTR_LABEL: mul i64
; COMBINE_PTR_LABEL: inttoptr i64 {{.*}} i16*
; COMBINE_PTR_LABEL: bitcast i16* {{.*}} i64*
; COMBINE_PTR_LABEL: load i64, i64*
; COMBINE_PTR_LABEL: trunc i64 {{.*}} i16
; COMBINE_PTR_LABEL: shl i64
; COMBINE_PTR_LABEL: lshr i64
; COMBINE_PTR_LABEL: or i64
; COMBINE_PTR_LABEL: icmp eq i64
; COMBINE_PTR_LABEL: icmp ne i16
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMBINE_PTR_LABEL: load i32, i32*
; COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; COMBINE_PTR_LABEL: ret i32
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union_load
; NO_COMBINE_PTR_LABEL: @"dfs$load32"
; NO_COMBINE_PTR_LABEL: ptrtoint i32*
; NO_COMBINE_PTR_LABEL: and i64
; NO_COMBINE_PTR_LABEL: mul i64
; NO_COMBINE_PTR_LABEL: inttoptr i64 {{.*}} i16*
; NO_COMBINE_PTR_LABEL: bitcast i16* {{.*}} i64*
; NO_COMBINE_PTR_LABEL: load i64, i64*
; NO_COMBINE_PTR_LABEL: trunc i64 {{.*}} i16
; NO_COMBINE_PTR_LABEL: shl i64
; NO_COMBINE_PTR_LABEL: lshr i64
; NO_COMBINE_PTR_LABEL: or i64
; NO_COMBINE_PTR_LABEL: icmp eq i64
; NO_COMBINE_PTR_LABEL: load i32, i32*
; NO_COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; NO_COMBINE_PTR_LABEL: ret i32
; NO_COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union_load
; CHECK-LABEL: @"dfs$load32"
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i[[#WSBITS:mul(SBITS,4)]]*
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = load i[[#WSBITS]], i[[#WSBITS]]* %[[#WIDE_SHADOW_PTR]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i[[#WSBITS]] %[[#WIDE_SHADOW]], [[#mul(SBITS,2)]]
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i[[#WSBITS]] %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i[[#WSBITS]] %[[#WIDE_SHADOW]], [[#SBITS]]
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i[[#WSBITS]] %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#SHADOW:]] = trunc i[[#WSBITS]] %[[#WIDE_SHADOW]] to i[[#SBITS]]
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; CHECK-NEXT: %a = load i32, i32* %p, align 4
; CHECK-NEXT: store i[[#SBITS]] %[[#SHADOW]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i32 %a
%a = load i32, i32* %p
ret i32 %a
}
define i64 @load64(i64* %p) {
; COMBINE_PTR_LABEL: @"dfs$load64"
; COMBINE_PTR_LABEL: ptrtoint i64*
; COMBINE_PTR_LABEL: and i64
; COMBINE_PTR_LABEL: mul i64
; COMBINE_PTR_LABEL: inttoptr i64 {{.*}} i16*
; COMBINE_PTR_LABEL: bitcast i16* {{.*}} i64*
; COMBINE_PTR_LABEL: load i64, i64*
; COMBINE_PTR_LABEL: trunc i64 {{.*}} i16
; COMBINE_PTR_LABEL: shl i64
; COMBINE_PTR_LABEL: lshr i64
; COMBINE_PTR_LABEL: or i64
; COMBINE_PTR_LABEL: icmp eq i64
; COMBINE_PTR_LABEL: icmp ne i16
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMBINE_PTR_LABEL: load i64, i64*
; COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; COMBINE_PTR_LABEL: ret i64
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union_load
; COMBINE_PTR_LABEL: getelementptr i64, i64* {{.*}} i64
; COMBINE_PTR_LABEL: load i64, i64*
; COMBINE_PTR_LABEL: icmp eq i64
; NO_COMBINE_PTR_LABEL: @"dfs$load64"
; NO_COMBINE_PTR_LABEL: ptrtoint i64*
; NO_COMBINE_PTR_LABEL: and i64
; NO_COMBINE_PTR_LABEL: mul i64
; NO_COMBINE_PTR_LABEL: inttoptr i64 {{.*}} i16*
; NO_COMBINE_PTR_LABEL: bitcast i16* {{.*}} i64*
; NO_COMBINE_PTR_LABEL: load i64, i64*
; NO_COMBINE_PTR_LABEL: trunc i64 {{.*}} i16
; NO_COMBINE_PTR_LABEL: shl i64
; NO_COMBINE_PTR_LABEL: lshr i64
; NO_COMBINE_PTR_LABEL: or i64
; NO_COMBINE_PTR_LABEL: icmp eq i64
; NO_COMBINE_PTR_LABEL: load i64, i64*
; NO_COMBINE_PTR_LABEL: store i16 {{.*}} @__dfsan_retval_tls
; NO_COMBINE_PTR_LABEL: ret i64
; NO_COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union_load
; NO_COMBINE_PTR_LABEL: getelementptr i64, i64* {{.*}} i64
; NO_COMBINE_PTR_LABEL: load i64, i64*
; NO_COMBINE_PTR_LABEL: icmp eq i64
; CHECK-LABEL: @"dfs$load64"
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i64* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i64*
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = load i64, i64* %[[#WIDE_SHADOW_PTR]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 8
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; CHECK-NEXT: %a = load i64, i64* %p, align 8
; CHECK-NEXT: store i[[#SBITS]] %[[#SHADOW]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i64 %a
%a = load i64, i64* %p
ret i64 %a
}
define i128 @load128(i128* %p) {
; CHECK-LABEL: @"dfs$load128"
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i128* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i64*
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = load i64, i64* %[[#WIDE_SHADOW_PTR]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR2:]] = getelementptr i64, i64* %[[#WIDE_SHADOW_PTR]], i64 1
; CHECK-NEXT: %[[#WIDE_SHADOW2:]] = load i64, i64* %[[#WIDE_SHADOW_PTR2]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW2]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 8
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; CHECK-NEXT: %a = load i128, i128* %p, align 8
; CHECK-NEXT: store i[[#SBITS]] %[[#SHADOW]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i128 %a
%a = load i128, i128* %p
ret i128 %a
}
define i17 @load17(i17* %p) {
; CHECK-LABEL: @"dfs$load17"
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i17* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#SHADOW:]] = call zeroext i8 @__dfsan_union_load(i[[#SBITS]]* %[[#SHADOW_PTR]], i64 3)
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; CHECK-NEXT: %a = load i17, i17* %p
; CHECK-NEXT: store i[[#SBITS]] %[[#SHADOW]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i17 %a
%a = load i17, i17* %p
ret i17 %a
}
@X = constant i1 1
define i1 @load_global() {
; NO_COMBINE_PTR_LABEL: @"dfs$load_global"
; NO_COMBINE_PTR_LABEL: store i16 0, i16* bitcast ([100 x i64]* @__dfsan_retval_tls to i16*), align 2
; CHECK-LABEL: @"dfs$load_global"
; CHECK-NEXT: %a = load i1, i1* @X
; CHECK-NEXT: store i[[#SBITS]] 0, i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK-NEXT: ret i1 %a
%a = load i1, i1* @X
ret i1 %a

View File

@ -1,7 +1,5 @@
; RUN: opt < %s -dfsan -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK_ORIGIN
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s
;
; %15 and %17 have the same key in shadow cache. They should not reuse the same
; shadow because their blocks do not dominate each other. Origin tracking

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,7 +1,5 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels -S | FileCheck %s --check-prefixes=CHECK,CHECK8,COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,CHECK8
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels -S | FileCheck %s --check-prefixes=CHECK,CHECK16,COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,CHECK16
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -38,7 +36,6 @@ define i16* @load_escaped_alloca() {
; CHECK-LABEL: @"dfs$load_escaped_alloca"
; CHECK: %[[#INTP:]] = ptrtoint i16* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR0:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_OFFSET:]] = add i64 %[[#INTP+1]], [[#%.10d,ORIGIN_MASK:]]
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = and i64 %[[#ORIGIN_OFFSET]], -4
@ -76,7 +73,6 @@ define i1 @load1(i1* %p) {
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i1* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_OFFSET:]] = add i64 %[[#INTP+1]], [[#ORIGIN_MASK]]
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = and i64 %[[#ORIGIN_OFFSET]], -4
@ -104,7 +100,6 @@ define i16 @load16(i1 %i, i16* %p) {
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i16* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR0:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_OFFSET:]] = add i64 %[[#INTP+1]], [[#ORIGIN_MASK]]
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = and i64 %[[#ORIGIN_OFFSET]], -4
@ -133,9 +128,8 @@ define i32 @load32(i32* %p) {
; COMBINE_LOAD_PTR-NEXT: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i32* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = add i64 %[[#INTP+1]], [[#ORIGIN_MASK]]
; CHECK-NEXT: %[[#ORIGIN_PTR:]] = inttoptr i64 %[[#ORIGIN_ADDR]] to i32*
@ -166,41 +160,26 @@ define i64 @load64(i64* %p) {
; COMBINE_LOAD_PTR-NEXT: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[#INTP:]] = ptrtoint i64* %p to i64
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i64* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = add i64 %[[#INTP+1]], [[#ORIGIN_MASK]]
; CHECK-NEXT: %[[#ORIGIN_PTR:]] = inttoptr i64 %[[#ORIGIN_ADDR]] to i32*
; CHECK-NEXT: %[[#ORIGIN:]] = load i32, i32* %[[#ORIGIN_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i64*
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = load i64, i64* %[[#WIDE_SHADOW_PTR]], align [[#SBYTES]]
; COMM: On fast16, the 2x64 shadow bits need to be ORed first.
; CHECK16-NEXT: %[[#WIDE_SHADOW_PTR2:]] = getelementptr i64, i64* %[[#WIDE_SHADOW_PTR]], i64 1
; CHECK16-NEXT: %[[#WIDE_SHADOW2:]] = load i64, i64* %[[#WIDE_SHADOW_PTR2]], align [[#SBYTES]]
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW2]]
; CHECK16-NEXT: %[[#ORIGIN_PTR2:]] = getelementptr i32, i32* %[[#ORIGIN_PTR]], i64 1
; CHECK16-NEXT: %[[#ORIGIN2:]] = load i32, i32* %[[#ORIGIN_PTR2]], align 8
; CHECK16-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK16-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK16-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; CHECK16-NEXT: %[[#SHADOW_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW2]], 0
; CHECK16-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW_NZ]], i32 %[[#ORIGIN2]], i32 %[[#ORIGIN]]
; COMM: On fast8, no need to OR the wide shadow but one more shift is needed.
; CHECK8-NEXT: %[[#WIDE_SHADOW_LO:]] = shl i64 %[[#WIDE_SHADOW]], 32
; CHECK8-NEXT: %[[#ORIGIN_PTR2:]] = getelementptr i32, i32* %[[#ORIGIN_PTR]], i64 1
; CHECK8-NEXT: %[[#ORIGIN2:]] = load i32, i32* %[[#ORIGIN_PTR2]], align 8
; CHECK8-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK8-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK8-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK8-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK8-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 8
; CHECK8-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK8-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; CHECK-NEXT: %[[#WIDE_SHADOW_LO:]] = shl i64 %[[#WIDE_SHADOW]], 32
; CHECK-NEXT: %[[#ORIGIN2_PTR:]] = getelementptr i32, i32* %[[#ORIGIN_PTR]], i64 1
; CHECK-NEXT: %[[#ORIGIN2:]] = load i32, i32* %[[#ORIGIN2_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 8
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; CHECK-NEXT: %[[#SHADOW_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW_LO]], 0
; CHECK-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW_NZ]], i32 %[[#ORIGIN]], i32 %[[#ORIGIN2]]
; CHECK8-NEXT: %[[#SHADOW_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW_LO]], 0
; CHECK8-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW_NZ]], i32 %[[#ORIGIN]], i32 %[[#ORIGIN2]]
@ -246,66 +225,38 @@ define i128 @load128(i128* %p) {
; COMBINE_LOAD_PTR-NEXT: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4
; COMBINE_LOAD_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[#INTP:]] = ptrtoint i128* %p to i64
; CHECK-NEXT: %[[#INTP:]] = ptrtoint i128* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:INTP+1]] = and i64 %[[#INTP]], [[#MASK]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = add i64 %[[#INTP+1]], [[#ORIGIN_MASK]]
; CHECK-NEXT: %[[#ORIGIN_PTR:]] = inttoptr i64 %[[#ORIGIN_ADDR]] to i32*
; CHECK-NEXT: %[[#ORIGIN:]] = load i32, i32* %[[#ORIGIN_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i64*
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = load i64, i64* %[[#WIDE_SHADOW_PTR]], align [[#SBYTES]]
; CHECK8-NEXT: %[[#WIDE_SHADOW_LO:]] = shl i64 %[[#WIDE_SHADOW]], 32
; CHECK8-NEXT: %[[#ORIGIN_PTR2:]] = getelementptr i32, i32* %[[#ORIGIN_PTR]], i64 1
; CHECK8-NEXT: %[[#ORIGIN2:]] = load i32, i32* %[[#ORIGIN_PTR2]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW_PTR2:]] = getelementptr i64, i64* %[[#WIDE_SHADOW_PTR]], i64 1
; CHECK-NEXT: %[[#WIDE_SHADOW2:]] = load i64, i64* %[[#WIDE_SHADOW_PTR2]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW2]]
; COMM: On fast16, we need to OR 4x64bits for the wide shadow, before ORing its bytes.
; CHECK16-NEXT: %[[#ORIGIN_PTR2:]] = getelementptr i32, i32* %[[#ORIGIN_PTR]], i64 1
; CHECK16-NEXT: %[[#ORIGIN2:]] = load i32, i32* %[[#ORIGIN_PTR2]], align 8
; CHECK16-NEXT: %[[#WIDE_SHADOW_PTR3:]] = getelementptr i64, i64* %[[#WIDE_SHADOW_PTR2]], i64 1
; CHECK16-NEXT: %[[#WIDE_SHADOW3:]] = load i64, i64* %[[#WIDE_SHADOW_PTR3]], align [[#SBYTES]]
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW3]]
; CHECK16-NEXT: %[[#ORIGIN_PTR3:]] = getelementptr i32, i32* %[[#ORIGIN_PTR2]], i64 1
; CHECK16-NEXT: %[[#ORIGIN3:]] = load i32, i32* %[[#ORIGIN_PTR3]], align 8
; CHECK16-NEXT: %[[#WIDE_SHADOW_PTR4:]] = getelementptr i64, i64* %[[#WIDE_SHADOW_PTR3]], i64 1
; CHECK16-NEXT: %[[#WIDE_SHADOW4:]] = load i64, i64* %[[#WIDE_SHADOW_PTR4]], align [[#SBYTES]]
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW4]]
; CHECK16-NEXT: %[[#ORIGIN_PTR4:]] = getelementptr i32, i32* %[[#ORIGIN_PTR3]], i64 1
; CHECK16-NEXT: %[[#ORIGIN4:]] = load i32, i32* %[[#ORIGIN_PTR4]], align 8
; CHECK16-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK16-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK16-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK16-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; CHECK16-NEXT: %[[#SHADOW2_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW2]], 0
; CHECK16-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW2_NZ]], i32 %[[#ORIGIN2]], i32 %[[#ORIGIN]]
; CHECK16-NEXT: %[[#SHADOW3_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW3]], 0
; CHECK16-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW3_NZ]], i32 %[[#ORIGIN3]], i32 %[[#ORIGIN]]
; CHECK16-NEXT: %[[#SHADOW4_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW4]], 0
; CHECK16-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW4_NZ]], i32 %[[#ORIGIN4]], i32 %[[#ORIGIN]]
; COMM: On fast8, we need to OR 2x64bits for the wide shadow, before ORing its bytes (one more shift).
; CHECK8-NEXT: %[[#ORIGIN_PTR3:]] = getelementptr i32, i32* %[[#ORIGIN_PTR2]], i64 1
; CHECK8-NEXT: %[[#ORIGIN3:]] = load i32, i32* %[[#ORIGIN_PTR3]], align 8
; CHECK8-NEXT: %[[#WIDE_SHADOW2_LO:]] = shl i64 %[[#WIDE_SHADOW2]], 32
; CHECK8-NEXT: %[[#ORIGIN_PTR4:]] = getelementptr i32, i32* %[[#ORIGIN_PTR3]], i64 1
; CHECK8-NEXT: %[[#ORIGIN4:]] = load i32, i32* %[[#ORIGIN_PTR4]], align 8
; CHECK8-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK8-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK8-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK8-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK8-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 8
; CHECK8-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK8-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; CHECK8-NEXT: %[[#SHADOW_LO_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW_LO]], 0
; CHECK8-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW_LO_NZ]], i32 %[[#ORIGIN]], i32 %[[#ORIGIN2]]
; CHECK8-NEXT: %[[#SHADOW2_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW2]], 0
; CHECK8-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW2_NZ]], i32 %[[#ORIGIN4]], i32 %[[#ORIGIN]]
; CHECK8-NEXT: %[[#SHADOW2_LO_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW2_LO]], 0
; CHECK8-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW2_LO_NZ]], i32 %[[#ORIGIN3]], i32 %[[#ORIGIN]]
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = add i64 %[[#SHADOW_ADDR]], [[#ORIGIN_MASK]]
; CHECK-NEXT: %[[#ORIGIN1_PTR:]] = inttoptr i64 %[[#ORIGIN_ADDR]] to i32*
; CHECK-NEXT: %[[#ORIGIN1:]] = load i32, i32* %[[#ORIGIN1_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW1_PTR:]] = bitcast i[[#SBITS]]* %[[#SHADOW_PTR]] to i64*
; CHECK-NEXT: %[[#WIDE_SHADOW1:]] = load i64, i64* %[[#WIDE_SHADOW1_PTR]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW1_LO:]] = shl i64 %[[#WIDE_SHADOW1]], 32
; CHECK-NEXT: %[[#ORIGIN2_PTR:]] = getelementptr i32, i32* %[[#ORIGIN1_PTR]], i64 1
; CHECK-NEXT: %[[#ORIGIN2:]] = load i32, i32* %[[#ORIGIN2_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW2_PTR:]] = getelementptr i64, i64* %[[#WIDE_SHADOW1_PTR]], i64 1
; CHECK-NEXT: %[[#WIDE_SHADOW2:]] = load i64, i64* %[[#WIDE_SHADOW2_PTR]], align [[#SBYTES]]
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW1]], %[[#WIDE_SHADOW2]]
; CHECK-NEXT: %[[#ORIGIN3_PTR:]] = getelementptr i32, i32* %[[#ORIGIN2_PTR]], i64 1
; CHECK-NEXT: %[[#ORIGIN3:]] = load i32, i32* %[[#ORIGIN3_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW2_LO:]] = shl i64 %[[#WIDE_SHADOW2]], 32
; CHECK-NEXT: %[[#ORIGIN4_PTR:]] = getelementptr i32, i32* %[[#ORIGIN3_PTR]], i64 1
; CHECK-NEXT: %[[#ORIGIN4:]] = load i32, i32* %[[#ORIGIN4_PTR]], align 8
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 32
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 16
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#WIDE_SHADOW_SHIFTED:]] = lshr i64 %[[#WIDE_SHADOW]], 8
; CHECK-NEXT: %[[#WIDE_SHADOW:]] = or i64 %[[#WIDE_SHADOW]], %[[#WIDE_SHADOW_SHIFTED]]
; CHECK-NEXT: %[[#SHADOW:]] = trunc i64 %[[#WIDE_SHADOW]] to i[[#SBITS]]
; CHECK-NEXT: %[[#SHADOW1_LO_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW1_LO]], 0
; CHECK-NEXT: %[[#ORIGIN12:]] = select i1 %[[#SHADOW1_LO_NZ]], i32 %[[#ORIGIN1]], i32 %[[#ORIGIN2]]
; CHECK-NEXT: %[[#SHADOW2_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW2]], 0
; CHECK-NEXT: %[[#ORIGIN124:]] = select i1 %[[#SHADOW2_NZ]], i32 %[[#ORIGIN4]], i32 %[[#ORIGIN12]]
; CHECK-NEXT: %[[#SHADOW2_LO_NZ:]] = icmp ne i64 %[[#WIDE_SHADOW2_LO]], 0
; CHECK-NEXT: %[[#ORIGIN:]] = select i1 %[[#SHADOW2_LO_NZ]], i32 %[[#ORIGIN3]], i32 %[[#ORIGIN124]]
; COMBINE_LOAD_PTR-NEXT: %[[#SHADOW:]] = or i[[#SBITS]] %[[#SHADOW]], %[[#PS]]
; COMBINE_LOAD_PTR-NEXT: %[[#NZ:]] = icmp ne i[[#SBITS]] %[[#PS]], 0

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,7 +1,5 @@
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=1 -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,TRACK_CONTROL_FLOW
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=0 -dfsan-track-origins=1 -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CONTROL_FLOW
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=1 -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,TRACK_CONTROL_FLOW
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=0 -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CONTROL_FLOW
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=1 -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,TRACK_CONTROL_FLOW
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=0 -dfsan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CONTROL_FLOW
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,7 +1,5 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels -dfsan-combine-pointer-labels-on-store -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels -S | FileCheck %s --check-prefixes=CHECK,CHECK16
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels -dfsan-combine-pointer-labels-on-store -S | FileCheck %s --check-prefixes=CHECK,CHECK16,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-combine-pointer-labels-on-store -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -55,7 +53,6 @@ define void @store_nonzero_to_escaped_alloca(i16 %a) {
; CHECK-NEXT: %[[#AS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; CHECK: %[[#INTP:]] = ptrtoint i16* %p to i64
; CHECK-NEXT: %[[#SHADOW_ADDR:]] = and i64 %[[#INTP]], [[#%.10d,MASK:]]
; CHECK16-NEXT: %[[#SHADOW_ADDR:]] = mul i64 %[[#SHADOW_ADDR]], 2
; CHECK-NEXT: %[[#SHADOW_PTR0:]] = inttoptr i64 %[[#SHADOW_ADDR]] to i[[#SBITS]]*
; CHECK-NEXT: %[[#ORIGIN_OFFSET:]] = add i64 %[[#INTP+1]], [[#%.10d,ORIGIN_MASK:]]
; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = and i64 %[[#ORIGIN_OFFSET]], -4

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-8-labels=true -dfsan-instrument-with-call-threshold=0 -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -dfsan-instrument-with-call-threshold=0 -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-instrument-with-call-threshold=0 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,4 @@
; RUN: opt < %s -dfsan -dfsan-track-origins=2 -dfsan-fast-8-labels -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=2 -dfsan-fast-16-labels -S | FileCheck %s
; RUN: opt < %s -dfsan -dfsan-track-origins=2 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,6 +1,4 @@
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,LEGACY
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -8,15 +6,11 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
define {i32, i32} @test({i32, i32} %a, i1 %c) {
; LEGACY: [[AL:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[PL:%.*]] = phi i[[#SBITS]] [ [[AL]], %T ], [ [[AL]], %F ]
; LEGACY: store i[[#SBITS]] [[PL]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; FAST: [[AL:%.*]] = load { i[[#SBITS]], i[[#SBITS]] }, { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_arg_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN:2]]
; FAST: [[AL0:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[AL]], i[[#SBITS]] 0, 0
; FAST: [[AL1:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[AL]], i[[#SBITS]] 0, 1
; FAST: [[PL:%.*]] = phi { i[[#SBITS]], i[[#SBITS]] } [ [[AL0]], %T ], [ [[AL1]], %F ]
; FAST: store { i[[#SBITS]], i[[#SBITS]] } [[PL]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
; CHECK: %[[#AL:]] = load { i[[#SBITS]], i[[#SBITS]] }, { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_arg_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN:2]]
; CHECK: %[[#AL0:]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } %[[#AL]], i[[#SBITS]] 0, 0
; CHECK: %[[#AL1:]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } %[[#AL]], i[[#SBITS]] 0, 1
; CHECK: %[[#PL:]] = phi { i[[#SBITS]], i[[#SBITS]] } [ %[[#AL0]], %T ], [ %[[#AL1]], %F ]
; CHECK: store { i[[#SBITS]], i[[#SBITS]] } %[[#PL]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([100 x i64]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
entry:
br i1 %c, label %T, label %F

View File

@ -1,9 +1,5 @@
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=1 -S | FileCheck %s --check-prefixes=CHECK,TRACK_CF,TRACK_CF_LEGACY
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=0 -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CF,NO_TRACK_CF_LEGACY
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -dfsan-track-select-control-flow=1 -S | FileCheck %s --check-prefixes=CHECK,TRACK_CF,TRACK_CF_FAST
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -dfsan-track-select-control-flow=0 -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CF,NO_TRACK_CF_FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -dfsan-track-select-control-flow=1 -S | FileCheck %s --check-prefixes=CHECK,TRACK_CF,TRACK_CF_FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -dfsan-track-select-control-flow=0 -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CF,NO_TRACK_CF_FAST
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=true -S | FileCheck %s --check-prefixes=CHECK,TRACK_CF
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=false -S | FileCheck %s --check-prefixes=CHECK,NO_TRACK_CF
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -18,11 +14,7 @@ define i8 @select8(i1 %c, i8 %t, i8 %f) {
; TRACK_CF: %[[#R+1]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: %[[#R+2]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: %[[#R+3]] = select i1 %c, i[[#SBITS]] %[[#R+1]], i[[#SBITS]] %[[#R]]
; TRACK_CF_LEGACY: %[[#R+4]] = icmp ne i[[#SBITS]] %[[#R+2]], %[[#R+3]]
; TRACK_CF_LEGACY: %[[#R+6]] = call {{.*}} i[[#SBITS]] @__dfsan_union(i[[#SBITS]] {{.*}} %[[#R+2]], i[[#SBITS]] {{.*}} %[[#R+3]])
; TRACK_CF_LEGACY: %[[#RO:]] = phi i[[#SBITS]] [ %[[#R+6]], {{.*}} ], [ %[[#R+2]], {{.*}} ]
; COMM: The union is simply an OR when fast labels are used.
; TRACK_CF_FAST: %[[#RO:]] = or i[[#SBITS]] %[[#R+2]], %[[#R+3]]
; TRACK_CF: %[[#RO:]] = or i[[#SBITS]] %[[#R+2]], %[[#R+3]]
; TRACK_CF: %a = select i1 %c, i8 %t, i8 %f
; TRACK_CF: store i[[#SBITS]] %[[#RO]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: ret i8 %a
@ -44,11 +36,7 @@ define i8 @select8e(i1 %c, i8 %tf) {
; TRACK_CF: @"dfs$select8e"
; TRACK_CF: %[[#R:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: %[[#R+1]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF_LEGACY: %[[#R+2]] = icmp ne i[[#SBITS]] %[[#R+1]], %[[#R]]
; TRACK_CF_LEGACY: %[[#R+4]] = call {{.*}} i[[#SBITS]] @__dfsan_union(i[[#SBITS]] {{.*}} %[[#R+1]], i[[#SBITS]] {{.*}} %[[#R]])
; TRACK_CF_LEGACY: %[[#RO:]] = phi i[[#SBITS]] [ %[[#R+4]], {{.*}} ], [ %[[#R+1]], {{.*}} ]
; COMM: The union is simply an OR when fast labels are used.
; TRACK_CF_FAST: %[[#RO:]] = or i[[#SBITS]] %[[#R+1]], %[[#R]]
; TRACK_CF: %[[#RO:]] = or i[[#SBITS]] %[[#R+1]], %[[#R]]
; TRACK_CF: %a = select i1 %c, i8 %tf, i8 %tf
; TRACK_CF: store i[[#SBITS]] %[[#RO]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: ret i8 %a
@ -69,15 +57,8 @@ define <4 x i8> @select8v(<4 x i1> %c, <4 x i8> %t, <4 x i8> %f) {
; TRACK_CF: %[[#R:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 4) to i[[#SBITS]]*), align [[ALIGN:2]]
; TRACK_CF: %[[#R+1]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: %[[#R+2]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF_LEGACY: %[[#R+3]] = icmp ne i[[#SBITS]] %[[#R+1]], %[[#R]]
; TRACK_CF_LEGACY: %[[#R+5]] = call {{.*}} i[[#SBITS]] @__dfsan_union(i[[#SBITS]] {{.*}} %[[#R+1]], i[[#SBITS]] zeroext %[[#R]])
; TRACK_CF_LEGACY: %[[#R+7]] = phi i[[#SBITS]] [ %[[#R+5]], {{.*}} ], [ %[[#R+1]], {{.*}} ]
; TRACK_CF_LEGACY: %[[#R+8]] = icmp ne i[[#SBITS]] %[[#R+2]], %[[#R+7]]
; TRACK_CF_LEGACY: %[[#R+10]] = call {{.*}} i[[#SBITS]] @__dfsan_union(i[[#SBITS]] {{.*}} %[[#R+2]], i[[#SBITS]] zeroext %[[#R+7]])
; TRACK_CF_LEGACY: %[[#RO:]] = phi i[[#SBITS]] [ %[[#R+10]], {{.*}} ], [ %[[#R+2]], {{.*}} ]
; COMM: The union is simply an OR when fast labels are used.
; TRACK_CF_FAST: %[[#R+3]] = or i[[#SBITS]] %[[#R+1]], %[[#R]]
; TRACK_CF_FAST: %[[#RO:]] = or i[[#SBITS]] %[[#R+2]], %[[#R+3]]
; TRACK_CF: %[[#R+3]] = or i[[#SBITS]] %[[#R+1]], %[[#R]]
; TRACK_CF: %[[#RO:]] = or i[[#SBITS]] %[[#R+2]], %[[#R+3]]
; TRACK_CF: %a = select <4 x i1> %c, <4 x i8> %t, <4 x i8> %f
; TRACK_CF: store i[[#SBITS]] %[[#RO]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; TRACK_CF: ret <4 x i8> %a
@ -86,11 +67,7 @@ define <4 x i8> @select8v(<4 x i1> %c, <4 x i8> %t, <4 x i8> %f) {
; NO_TRACK_CF: %[[#R:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 4) to i[[#SBITS]]*), align [[ALIGN:2]]
; NO_TRACK_CF: %[[#R+1]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]]
; NO_TRACK_CF: %[[#R+2]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; NO_TRACK_CF_LEGACY: %[[#R+3]] = icmp ne i[[#SBITS]] %[[#R+1]], %[[#R]]
; NO_TRACK_CF_LEGACY: %[[#R+5]] = call {{.*}} i[[#SBITS]] @__dfsan_union(i[[#SBITS]] {{.*}} %[[#R+1]], i[[#SBITS]] {{.*}} %[[#R]])
; NO_TRACK_CF_LEGACY: %[[#RO:]] = phi i[[#SBITS]] [ %6, {{.*}} ], [ %2, {{.*}} ]
; COMM: The union is simply an OR when fast labels are used.
; NO_TRACK_CF_FAST: %[[#RO:]] = or i[[#SBITS]] %[[#R+1]], %[[#R]]
; NO_TRACK_CF: %[[#RO:]] = or i[[#SBITS]] %[[#R+1]], %[[#R]]
; NO_TRACK_CF: %a = select <4 x i1> %c, <4 x i8> %t, <4 x i8> %f
; NO_TRACK_CF: store i[[#SBITS]] %[[#RO]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; NO_TRACK_CF: ret <4 x i8> %a

View File

@ -1,6 +1,4 @@
; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -dfsan -S --dfsan-abilist=%S/Inputs/shadow-args-abilist.txt | FileCheck %s
; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -dfsan -S --dfsan-abilist=%S/Inputs/shadow-args-abilist.txt -dfsan-fast-16-labels | FileCheck %s
; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -dfsan -S --dfsan-abilist=%S/Inputs/shadow-args-abilist.txt -dfsan-fast-8-labels | FileCheck %s
; REQUIRES: x86-registered-target

View File

@ -1,9 +1,5 @@
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-store=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK16,COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-store=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK16,NO_COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -dfsan-combine-pointer-labels-on-store=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK16,COMBINE_PTR_LABEL_FAST
; RUN: opt < %s -dfsan -dfsan-fast-16-labels -dfsan-combine-pointer-labels-on-store=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK16,NO_COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -dfsan-combine-pointer-labels-on-store=1 -S | FileCheck %s --check-prefixes=CHECK,COMBINE_PTR_LABEL_FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels -dfsan-combine-pointer-labels-on-store=0 -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-store=1 -S | FileCheck %s --check-prefixes=CHECK,COMBINE_PTR_LABEL
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-store=0 -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_PTR_LABEL
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -23,19 +19,10 @@ define void @store0({} %v, {}* %p) {
define void @store8(i8 %v, i8* %p) {
; CHECK-LABEL: @"dfs$store8"
; CHECK: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: icmp ne i[[#SBITS]]
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMM: When not in legacy mode, the three instructions above will
; be replaced with the following:
; COMBINE_PTR_LABEL_FAST: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL_FAST: or i[[#SBITS]]
; COMBINE_PTR_LABEL: or i[[#SBITS]]
; CHECK: ptrtoint i8* {{.*}} i64
; CHECK-NEXT: and i64
; CHECK16-NEXT: mul i64
; CHECK-NEXT: inttoptr i64 {{.*}} i[[#SBITS]]*
; CHECK-NEXT: getelementptr i[[#SBITS]], i[[#SBITS]]*
; CHECK-NEXT: store i[[#SBITS]]
@ -49,19 +36,10 @@ define void @store8(i8 %v, i8* %p) {
define void @store16(i16 %v, i16* %p) {
; CHECK-LABEL: @"dfs$store16"
; CHECK: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: icmp ne i[[#SBITS]]
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMM: When not in legacy mode, the three instructions above will
; be replaced with the following:
; COMBINE_PTR_LABEL_FAST: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL_FAST: or i[[#SBITS]]
; COMBINE_PTR_LABEL: or i[[#SBITS]]
; CHECK: ptrtoint i16* {{.*}} i64
; CHECK-NEXT: and i64
; CHECK16-NEXT: mul i64
; CHECK-NEXT: inttoptr i64 {{.*}} i[[#SBITS]]*
; CHECK-NEXT: getelementptr i[[#SBITS]], i[[#SBITS]]*
; CHECK-NEXT: store i[[#SBITS]]
@ -77,19 +55,10 @@ define void @store16(i16 %v, i16* %p) {
define void @store32(i32 %v, i32* %p) {
; CHECK-LABEL: @"dfs$store32"
; CHECK: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: icmp ne i[[#SBITS]]
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMM: When not in legacy mode, the three instructions above will
; be replaced with the following:
; COMBINE_PTR_LABEL_FAST: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL_FAST: or i[[#SBITS]]
; COMBINE_PTR_LABEL: or i[[#SBITS]]
; CHECK: ptrtoint i32* {{.*}} i64
; CHECK-NEXT: and i64
; CHECK16-NEXT: mul i64
; CHECK-NEXT: inttoptr i64 {{.*}} i[[#SBITS]]*
; CHECK-NEXT: getelementptr i[[#SBITS]], i[[#SBITS]]*
; CHECK-NEXT: store i[[#SBITS]]
@ -109,19 +78,10 @@ define void @store32(i32 %v, i32* %p) {
define void @store64(i64 %v, i64* %p) {
; CHECK-LABEL: @"dfs$store64"
; CHECK: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL: icmp ne i[[#SBITS]]
; COMBINE_PTR_LABEL: call {{.*}} @__dfsan_union
; COMM: When not in legacy mode, the three instructions above will
; be replaced with the following:
; COMBINE_PTR_LABEL_FAST: load i[[#SBITS]], i[[#SBITS]]* {{.*}} @__dfsan_arg_tls
; COMBINE_PTR_LABEL_FAST: or i[[#SBITS]]
; COMBINE_PTR_LABEL: or i[[#SBITS]]
; CHECK: ptrtoint i64* {{.*}} i64
; CHECK-NEXT: and i64
; CHECK16-NEXT: mul i64
; CHECK-NEXT: inttoptr i64 {{.*}} i[[#SBITS]]*
; CHECK-COUNT-8: insertelement {{.*}} i[[#SBITS]]
; CHECK-NEXT: bitcast i[[#SBITS]]* {{.*}} <8 x i[[#SBITS]]>*

View File

@ -1,16 +1,10 @@
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,LEGACY
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-event-callbacks=true -S | FileCheck %s --check-prefixes=CHECK,EVENT_CALLBACKS
; RUN: opt < %s -dfsan -dfsan-event-callbacks=true -S | FileCheck %s --check-prefixes=CHECK,EVENT_CALLBACKS
; RUN: opt < %s -dfsan -dfsan-args-abi -S | FileCheck %s --check-prefixes=CHECK,ARGS_ABI
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-track-select-control-flow=false -S | FileCheck %s --check-prefixes=CHECK,NO_SELECT_CONTROL
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-track-select-control-flow=false -S | FileCheck %s --check-prefixes=CHECK,NO_SELECT_CONTROL
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,FAST
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR
; RUN: opt < %s -dfsan -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR
; RUN: opt < %s -dfsan -dfsan-track-select-control-flow=false -S | FileCheck %s --check-prefixes=CHECK,NO_SELECT_CONTROL
; RUN: opt < %s -dfsan -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -91,11 +85,6 @@ define {i1, i32} @select_struct(i1 %c, {i1, i32} %a, {i1, i32} %b) {
; FAST: %[[#R+9]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } %[[#R+8]], i[[#SBITS]] %[[#R+7]], 1
; FAST: store { i[[#SBITS]], i[[#SBITS]] } %[[#R+9]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
; LEGACY: @"dfs$select_struct"
; LEGACY: [[U:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union
; LEGACY: [[P:%.*]] = phi i[[#SBITS]] [ [[U]],
; LEGACY: store i[[#SBITS]] [[P]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align 2
%s = select i1 %c, {i1, i32} %a, {i1, i32} %b
ret {i1, i32} %s
}
@ -109,13 +98,6 @@ define { i32, i32 } @asm_struct(i32 %0, i32 %1) {
; FAST: [[S1:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[S0]], i[[#SBITS]] [[E01]], 1
; FAST: store { i[[#SBITS]], i[[#SBITS]] } [[S1]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
; LEGACY: @"dfs$asm_struct"
; LEGACY: [[E1:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[E0:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; LEGACY: [[E01:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext [[E0]], i[[#SBITS]] zeroext [[E1]])
; LEGACY: [[P:%.*]] = phi i[[#SBITS]] [ [[E01]], {{.*}} ], [ [[E0]], {{.*}} ]
; LEGACY: store i[[#SBITS]] [[P]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
entry:
%a = call { i32, i32 } asm "", "=r,=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1)
ret { i32, i32 } %a
@ -124,9 +106,6 @@ entry:
define {i32, i32} @const_struct() {
; FAST: @"dfs$const_struct"
; FAST: store { i[[#SBITS]], i[[#SBITS]] } zeroinitializer, { i[[#SBITS]], i[[#SBITS]] }* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align 2
; LEGACY: @"dfs$const_struct"
; LEGACY: store i[[#SBITS]] 0, i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align 2
ret {i32, i32} { i32 42, i32 11 }
}
@ -136,9 +115,6 @@ define i1 @extract_struct({i1, i5} %s) {
; FAST: [[EM:%.*]] = extractvalue { i[[#SBITS]], i[[#SBITS]] } [[SM]], 0
; FAST: store i[[#SBITS]] [[EM]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
; LEGACY: @"dfs$extract_struct"
; LEGACY: [[SM:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: store i[[#SBITS]] [[SM]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
%e2 = extractvalue {i1, i5} %s, 0
ret i1 %e2
}
@ -149,13 +125,6 @@ define {i1, i5} @insert_struct({i1, i5} %s, i5 %e1) {
; FAST: [[SM:%.*]] = load { i[[#SBITS]], i[[#SBITS]] }, { i[[#SBITS]], i[[#SBITS]] }* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
; FAST: [[SM1:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } [[SM]], i[[#SBITS]] [[EM]], 1
; FAST: store { i[[#SBITS]], i[[#SBITS]] } [[SM1]], { i[[#SBITS]], i[[#SBITS]] }* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to { i[[#SBITS]], i[[#SBITS]] }*), align [[ALIGN]]
; LEGACY: @"dfs$insert_struct"
; LEGACY: [[EM:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN:2]]
; LEGACY: [[SM:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; LEGACY: [[U:%.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext [[SM]], i[[#SBITS]] zeroext [[EM]])
; LEGACY: [[P:%.*]] = phi i[[#SBITS]] [ [[U]], {{.*}} ], [ [[SM]], {{.*}} ]
; LEGACY: store i[[#SBITS]] [[P]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]
%s1 = insertvalue {i1, i5} %s, i5 %e1, 1
ret {i1, i5} %s1
}

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,9 @@
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]]
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
@a = common global i32 0
@b = common global i32 0
@ -9,10 +12,10 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK-LABEL: @"dfs$f"
define void @f(i32 %x, i32 %y) {
; CHECK: call{{.*}}__dfsan_union
; CHECK: or i[[#SBITS]]
%xay = add i32 %x, %y
store i32 %xay, i32* @a
; CHECK-NOT: call{{.*}}__dfsan_union
; CHECK-NOT: or i[[#SBITS]]
%xmy = mul i32 %x, %y
store i32 %xmy, i32* @b
ret void
@ -26,13 +29,13 @@ define void @g(i1 %p, i32 %x, i32 %y) {
br i1 %p, label %l1, label %l2
l1:
; CHECK: call{{.*}}__dfsan_union
; CHECK: or i[[#SBITS]]
%xay = add i32 %x, %y
store i32 %xay, i32* @a
br label %l3
l2:
; CHECK: call{{.*}}__dfsan_union
; CHECK: or i[[#SBITS]]
%xmy = mul i32 %x, %y
store i32 %xmy, i32* @b
br label %l3
@ -45,9 +48,9 @@ l3:
; CHECK-LABEL: @"dfs$h"
define i32 @h(i32 %x, i32 %y) {
; CHECK: call{{.*}}__dfsan_union
; CHECK: or i[[#SBITS]]
%xay = add i32 %x, %y
; CHECK-NOT: call{{.*}}__dfsan_union
; CHECK-NOT: or i[[#SBITS]]
%xayax = add i32 %xay, %x
ret i32 %xayax
}

View File

@ -1,7 +1,5 @@
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI,TLS_ABI_LEGACY
; RUN: opt < %s -dfsan -dfsan-args-abi -S | FileCheck %s --check-prefixes=CHECK,ARGS_ABI
; RUN: opt < %s -dfsan -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI,TLS_ABI_FAST
; RUN: opt < %s -dfsan -dfsan-fast-8-labels=true -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI,TLS_ABI_FAST
; RUN: opt < %s -dfsan -S | FileCheck %s --check-prefixes=CHECK,TLS_ABI
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -37,12 +35,7 @@ define <4 x i1> @icmp_vector(<4 x i8> %a, <4 x i8> %b) {
; TLS_ABI-LABEL: @"dfs$icmp_vector"
; TLS_ABI-NEXT: %[[B:.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN:2]]
; TLS_ABI-NEXT: %[[A:.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]]
; TLS_ABI_LEGACY: %[[U:.*]] = call zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext %[[A]], i[[#SBITS]] zeroext %[[B]])
; TLS_ABI_LEGACY: %[[L:.*]] = phi i[[#SBITS]] [ %[[U]], {{.*}} ], [ %[[A]], {{.*}} ]
; COM: With fast labels enabled, union is just an OR.
; TLS_ABI_FAST: %[[L:.*]] = or i[[#SBITS]] %[[A]], %[[B]]
; TLS_ABI: %[[L:.*]] = or i[[#SBITS]] %[[A]], %[[B]]
; TLS_ABI: %r = icmp eq <4 x i8> %a, %b
; TLS_ABI: store i[[#SBITS]] %[[L]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_retval_tls to i[[#SBITS]]*), align [[ALIGN]]