diff options
| author | Peter Collingbourne <pcc@google.com> | 2020-04-07 14:04:46 -0700 |
|---|---|---|
| committer | Christopher Ferris <cferris@google.com> | 2020-04-16 00:23:45 -0700 |
| commit | c71e0a652c0d416aa69e70baef447e41dcf9d26a (patch) | |
| tree | 2b12b26774db3645668a3619feb1018a76494033 /libunwindstack/tests/MemoryMteTest.cpp | |
| parent | 585ff01946f016d2af7f724f5f5d2df09c3b620a (diff) | |
libunwindstack: Add Memory::ReadTag() function for reading memory tags.
This uses an experimental Linux kernel API for reading the tags across
processes using ptrace.
Bug: 135772972
Test: Unit tests pass.
Change-Id: Ib1a09d9219166011de80cf250b756bb8a4bcdb0a
Diffstat (limited to 'libunwindstack/tests/MemoryMteTest.cpp')
| -rw-r--r-- | libunwindstack/tests/MemoryMteTest.cpp | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/libunwindstack/tests/MemoryMteTest.cpp b/libunwindstack/tests/MemoryMteTest.cpp new file mode 100644 index 0000000000..3ae322e351 --- /dev/null +++ b/libunwindstack/tests/MemoryMteTest.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(ANDROID_EXPERIMENTAL_MTE) + +#include <sys/mman.h> +#include <sys/types.h> + +#include <gtest/gtest.h> + +#include <bionic/mte.h> + +#include "MemoryLocal.h" +#include "MemoryRemote.h" +#include "TestUtils.h" + +namespace unwindstack { + +static uintptr_t CreateTagMapping() { + uintptr_t mapping = + reinterpret_cast<uintptr_t>(mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE | PROT_MTE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + if (reinterpret_cast<void*>(mapping) == MAP_FAILED) { + return 0; + } +#if defined(__aarch64__) + __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" + : + : "r"(mapping + (1ULL << 56)) + : "memory"); +#endif + return mapping; +} + +TEST(MemoryMteTest, remote_read_tag) { +#if !defined(__aarch64__) + GTEST_SKIP() << "Requires aarch64"; +#else + if (!mte_supported()) { + GTEST_SKIP() << "Requires MTE"; + } +#endif + + uintptr_t mapping = CreateTagMapping(); + ASSERT_NE(0U, mapping); + + pid_t pid; + if ((pid = fork()) == 0) { + while (true) + ; + exit(1); + } + ASSERT_LT(0, pid); + TestScopedPidReaper reap(pid); + + ASSERT_TRUE(TestAttach(pid)); + + MemoryRemote remote(pid); + + EXPECT_EQ(1, remote.ReadTag(mapping)); + EXPECT_EQ(0, remote.ReadTag(mapping + 16)); + + ASSERT_TRUE(TestDetach(pid)); +} + +TEST(MemoryMteTest, local_read_tag) { +#if !defined(__aarch64__) + GTEST_SKIP() << "Requires aarch64"; +#else + if (!mte_supported()) { + GTEST_SKIP() << "Requires MTE"; + } +#endif + + uintptr_t mapping = CreateTagMapping(); + ASSERT_NE(0U, mapping); + + MemoryLocal local; + + EXPECT_EQ(1, local.ReadTag(mapping)); + EXPECT_EQ(0, local.ReadTag(mapping + 16)); +} + +} // namespace unwindstack + +#endif |
