// Program to generate core files to test MTE tag features. // // This file uses ACLE intrinsics as detailed in: // https://developer.arm.com/documentation/101028/0012/10--Memory-tagging-intrinsics?lang=en // // Compile with: // -march=armv8.5-a+memtag -g main.c -o a.out.mte // -march=armv8.5-a+memtag -g main.c -DNO_MTE -o a.out.nomte // // /proc/self/coredump_filter was set to 2 when the core files were made. #include #include #include #include #include #include int main(int argc, char const *argv[]) { #ifdef NO_MTE *(char *)(0) = 0; #endif if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | // Allow all tags to be generated by the addg // instruction __arm_mte_increment_tag produces. (0xffff << PR_MTE_TAG_SHIFT), 0, 0, 0)) { return 1; } size_t page_size = sysconf(_SC_PAGESIZE); char *mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (!mte_buf) return 1; printf("mte_buf: %p\n", mte_buf); // Allocate some untagged memory before the tagged memory. char *buf = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (!buf) return 1; printf("buf: %p\n", buf); // This write means that the memory for buf is included in the corefile. // So we can read from the end of it into mte_buf during the test. *buf = 1; // These must be next to each other for the tests to work. // // mte_buf // buf // if ((mte_buf - buf) != page_size) { return 1; } // Set incrementing tags until end of the page. char *tagged_ptr = mte_buf; // This ignores tag bits when subtracting the addresses. while (__arm_mte_ptrdiff(tagged_ptr, mte_buf) < page_size) { // Set the allocation tag for this location. __arm_mte_set_tag(tagged_ptr); // + 16 for 16 byte granules. // Earlier we allowed all tag values, so this will give us an // incrementing pattern 0-0xF wrapping back to 0. tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); } // Will fault because logical tag 0 != allocation tag 1. *(mte_buf + 16) = 1; return 0; }