diff options
-rw-r--r-- | libunwindstack/Android.bp | 1 | ||||
-rw-r--r-- | libunwindstack/Memory.cpp | 11 | ||||
-rw-r--r-- | libunwindstack/MemoryLocalUnsafe.h | 33 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Memory.h | 4 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Unwinder.h | 2 | ||||
-rw-r--r-- | libunwindstack/tests/MemoryLocalUnsafeTest.cpp | 65 |
6 files changed, 115 insertions, 1 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index f0b4f2e..8fb5c3d 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -347,6 +347,7 @@ cc_defaults { "tests/MemoryCacheTest.cpp", "tests/MemoryFileTest.cpp", "tests/MemoryLocalTest.cpp", + "tests/MemoryLocalUnsafeTest.cpp", "tests/MemoryOfflineBufferTest.cpp", "tests/MemoryOfflineTest.cpp", "tests/MemoryRangeTest.cpp", diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp index 258c54a..0594a7a 100644 --- a/libunwindstack/Memory.cpp +++ b/libunwindstack/Memory.cpp @@ -40,6 +40,7 @@ #include "MemoryCache.h" #include "MemoryFileAtOffset.h" #include "MemoryLocal.h" +#include "MemoryLocalUnsafe.h" #include "MemoryOffline.h" #include "MemoryOfflineBuffer.h" #include "MemoryRange.h" @@ -201,6 +202,10 @@ std::shared_ptr<Memory> Memory::CreateFileMemory(const std::string& path, uint64 return nullptr; } +std::shared_ptr<Memory> Memory::CreateProcessMemoryLocalUnsafe() { + return std::shared_ptr<Memory>(new MemoryLocalUnsafe()); +} + std::shared_ptr<Memory> Memory::CreateProcessMemory(pid_t pid) { if (pid == getpid()) { return std::shared_ptr<Memory>(new MemoryLocal()); @@ -581,4 +586,10 @@ void MemoryThreadCache::Clear() { } } +size_t MemoryLocalUnsafe::Read(uint64_t addr, void* dst, size_t size) { + void* raw_ptr = reinterpret_cast<void*>(addr); + memcpy(dst, raw_ptr, size); + return size; +} + } // namespace unwindstack diff --git a/libunwindstack/MemoryLocalUnsafe.h b/libunwindstack/MemoryLocalUnsafe.h new file mode 100644 index 0000000..130f025 --- /dev/null +++ b/libunwindstack/MemoryLocalUnsafe.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 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. + */ + +#pragma once + +#include <stdint.h> + +#include <unwindstack/Memory.h> + +namespace unwindstack { + +class MemoryLocalUnsafe : public Memory { + public: + MemoryLocalUnsafe() = default; + virtual ~MemoryLocalUnsafe() = default; + + size_t Read(uint64_t addr, void* dst, size_t size) override; +}; + +} // namespace unwindstack diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h index 112fe19..ec95bb4 100644 --- a/libunwindstack/include/unwindstack/Memory.h +++ b/libunwindstack/include/unwindstack/Memory.h @@ -35,6 +35,10 @@ class Memory { static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid); static std::shared_ptr<Memory> CreateProcessMemoryCached(pid_t pid); static std::shared_ptr<Memory> CreateProcessMemoryThreadCached(pid_t pid); + // This should only be used for performance. Using this could result + // in crashes if used to try and read stack data. + static std::shared_ptr<Memory> CreateProcessMemoryLocalUnsafe(); + static std::shared_ptr<Memory> CreateOfflineMemory(const uint8_t* data, uint64_t start, uint64_t end); static std::shared_ptr<Memory> CreateFileMemory(const std::string& path, uint64_t offset, diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index d78da5c..91fd1d5 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -85,7 +85,7 @@ class Unwinder { static std::string FormatFrame(ArchEnum arch, const FrameData& frame, bool display_build_id = true); - void SetArch(ArchEnum arch) { arch_ = arch; }; + void SetArch(ArchEnum arch) { arch_ = arch; } void SetJitDebug(JitDebug* jit_debug); diff --git a/libunwindstack/tests/MemoryLocalUnsafeTest.cpp b/libunwindstack/tests/MemoryLocalUnsafeTest.cpp new file mode 100644 index 0000000..fdd5614 --- /dev/null +++ b/libunwindstack/tests/MemoryLocalUnsafeTest.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 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. + */ + +#include <stdint.h> +#include <string.h> +#include <sys/mman.h> + +#include <vector> + +#include <gtest/gtest.h> + +#include "MemoryLocalUnsafe.h" + +namespace unwindstack { + +TEST(MemoryLocalUnsafeTest, read_smoke) { + std::vector<uint8_t> src(1024); + memset(src.data(), 0x4c, 1024); + + auto local = Memory::CreateProcessMemoryLocalUnsafe(); + + std::vector<uint8_t> dst(1024); + ASSERT_TRUE(local->ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024)); + ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024)); + for (size_t i = 0; i < 1024; i++) { + ASSERT_EQ(0x4cU, dst[i]); + } + + memset(src.data(), 0x23, 512); + ASSERT_TRUE(local->ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024)); + ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024)); + for (size_t i = 0; i < 512; i++) { + ASSERT_EQ(0x23U, dst[i]); + } + for (size_t i = 512; i < 1024; i++) { + ASSERT_EQ(0x4cU, dst[i]); + } +} + +TEST(MemoryLocalUnsafeTest, read_crash) { + void* mapping = + mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_NE(MAP_FAILED, mapping); + + mprotect(mapping, getpagesize(), PROT_NONE); + + auto local = Memory::CreateProcessMemoryLocalUnsafe(); + std::vector<uint8_t> buffer(100); + ASSERT_DEATH(local->Read(reinterpret_cast<uint64_t>(mapping), buffer.data(), buffer.size()), ""); +} + +} // namespace unwindstack |