//===-- sanitizer_procmaps_test.cpp ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is a part of ThreadSanitizer/AddressSanitizer runtime. // //===----------------------------------------------------------------------===// #if !defined(_WIN32) // There are no /proc/maps on Windows. # include "sanitizer_common/sanitizer_procmaps.h" # include # include # include # include "gtest/gtest.h" static void noop() {} extern const char *argv0; namespace __sanitizer { # if SANITIZER_LINUX && !SANITIZER_ANDROID TEST(MemoryMappingLayout, CodeRange) { uptr start, end; bool res = GetCodeRangeForFile("[vdso]", &start, &end); EXPECT_EQ(res, true); EXPECT_GT(start, 0U); EXPECT_LT(start, end); } # endif TEST(MemoryMappingLayout, DumpListOfModules) { const char *last_slash = strrchr(argv0, '/'); const char *binary_name = last_slash ? last_slash + 1 : argv0; MemoryMappingLayout memory_mapping(false); const uptr kMaxModules = 100; InternalMmapVector modules; modules.reserve(kMaxModules); memory_mapping.DumpListOfModules(&modules); EXPECT_GT(modules.size(), 0U); bool found = false; for (uptr i = 0; i < modules.size(); ++i) { if (modules[i].containsAddress((uptr)&noop)) { // Verify that the module name is sane. if (strstr(modules[i].full_name(), binary_name) != 0) found = true; } modules[i].clear(); } EXPECT_TRUE(found); } TEST(MemoryMapping, LoadedModuleArchAndUUID) { if (SANITIZER_APPLE) { MemoryMappingLayout memory_mapping(false); const uptr kMaxModules = 100; InternalMmapVector modules; modules.reserve(kMaxModules); memory_mapping.DumpListOfModules(&modules); for (uptr i = 0; i < modules.size(); ++i) { ModuleArch arch = modules[i].arch(); // Darwin unit tests are only run on i386/x86_64/x86_64h/arm64. if (SANITIZER_WORDSIZE == 32) { EXPECT_EQ(arch, kModuleArchI386); } else if (SANITIZER_WORDSIZE == 64) { EXPECT_TRUE(arch == kModuleArchX86_64 || arch == kModuleArchX86_64H || arch == kModuleArchARM64 || arch == kModuleArchARM64E); } const u8 *uuid = modules[i].uuid(); u8 null_uuid[kModuleUUIDSize] = {0}; EXPECT_NE(memcmp(null_uuid, uuid, kModuleUUIDSize), 0); } } } # if (SANITIZER_LINUX || SANITIZER_NETBSD || SANITIZER_SOLARIS) && \ defined(_LP64) const char *const parse_unix_input = R"( 7fb9862f1000-7fb9862f3000 rw-p 00000000 00:00 0 Size: 8 kB Rss: 4 kB 7fb9864ae000-7fb9864b1000 r--p 001ba000 fd:01 22413919 /lib/x86_64-linux-gnu/libc-2.32.so Size: 12 kB Rss: 12 kB )"; TEST(MemoryMapping, ParseUnixMemoryProfile) { struct entry { uptr p; uptr rss; bool file; }; typedef std::vector entries_t; entries_t entries; std::vector input(parse_unix_input, parse_unix_input + strlen(parse_unix_input)); ParseUnixMemoryProfile( [](uptr p, uptr rss, bool file, uptr *mem) { reinterpret_cast(mem)->push_back({p, rss, file}); }, reinterpret_cast(&entries), &input[0], input.size()); EXPECT_EQ(entries.size(), 2ul); EXPECT_EQ(entries[0].p, 0x7fb9862f1000ul); EXPECT_EQ(entries[0].rss, 4ul << 10); EXPECT_EQ(entries[0].file, false); EXPECT_EQ(entries[1].p, 0x7fb9864ae000ul); EXPECT_EQ(entries[1].rss, 12ul << 10); EXPECT_EQ(entries[1].file, true); } TEST(MemoryMapping, ParseUnixMemoryProfileTruncated) { // ParseUnixMemoryProfile used to crash on truncated inputs. // This test allocates 2 pages, protects the second one // and places the input at the very end of the first page // to test for over-reads. uptr page = GetPageSizeCached(); char *mem = static_cast( MmapOrDie(2 * page, "ParseUnixMemoryProfileTruncated")); EXPECT_TRUE(MprotectNoAccess(reinterpret_cast(mem + page), page)); const uptr len = strlen(parse_unix_input); for (uptr i = 0; i < len; i++) { char *smaps = mem + page - len + i; memcpy(smaps, parse_unix_input, len - i); ParseUnixMemoryProfile([](uptr p, uptr rss, bool file, uptr *mem) {}, nullptr, smaps, len - i); } UnmapOrDie(mem, 2 * page); } # endif } // namespace __sanitizer #endif // !defined(_WIN32)