summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-04-08 07:21:20 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-04-08 07:21:20 +0000
commitc579c4ecdb1950b58d1d837ed878b3b46091ebd2 (patch)
tree613818ffe74f64a3b017ae7c811451e67fce83a0
parent1d25f18decb9cf686986e2e1053197a5f562e417 (diff)
parent9ec39228b009924647be3ab7c9a0de1394e0b62f (diff)
downloadunwinding-c579c4ecdb1950b58d1d837ed878b3b46091ebd2.tar.gz
Snap for 4706961 from c86794178367dbce3271fe307cbaed81fd2617b4 to pi-release
Change-Id: I4121bb5e6453557c7c61f5d569c5d13022ebbc13
-rw-r--r--libbacktrace/UnwindStackMap.cpp13
-rw-r--r--libbacktrace/UnwindStackMap.h3
-rw-r--r--libunwindstack/Android.bp1
-rw-r--r--libunwindstack/Memory.cpp19
-rw-r--r--libunwindstack/include/unwindstack/Memory.h15
-rw-r--r--libunwindstack/tests/MemoryOfflineBufferTest.cpp97
6 files changed, 141 insertions, 7 deletions
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 9c6fed4..d2d6ab8 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -149,13 +149,12 @@ bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& sta
}
// Create the process memory from the stack data.
- uint64_t size = stack.end - stack.start;
- unwindstack::MemoryBuffer* memory = new unwindstack::MemoryBuffer;
- memory->Resize(size);
- memcpy(memory->GetPtr(0), stack.data, size);
- std::shared_ptr<unwindstack::Memory> shared_memory(memory);
-
- process_memory_.reset(new unwindstack::MemoryRange(shared_memory, 0, size, stack.start));
+ if (memory_ == nullptr) {
+ memory_ = new unwindstack::MemoryOfflineBuffer(stack.data, stack.start, stack.end);
+ process_memory_.reset(memory_);
+ } else {
+ memory_->Reset(stack.data, stack.start, stack.end);
+ }
return true;
}
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index ec0d9c1..039f4a2 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -79,6 +79,9 @@ class UnwindStackOfflineMap : public UnwindStackMap {
bool Build(const std::vector<backtrace_map_t>& maps);
bool CreateProcessMemory(const backtrace_stackinfo_t& stack);
+
+ private:
+ unwindstack::MemoryOfflineBuffer* memory_ = nullptr;
};
#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index ab01726..7b8111c 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -219,6 +219,7 @@ cc_test {
"tests/MemoryFake.cpp",
"tests/MemoryFileTest.cpp",
"tests/MemoryLocalTest.cpp",
+ "tests/MemoryOfflineBufferTest.cpp",
"tests/MemoryOfflineTest.cpp",
"tests/MemoryRangeTest.cpp",
"tests/MemoryRemoteTest.cpp",
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index d4ba680..beb2aad 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -345,6 +345,25 @@ size_t MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
return memory_->Read(addr, dst, size);
}
+MemoryOfflineBuffer::MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end)
+ : data_(data), start_(start), end_(end) {}
+
+void MemoryOfflineBuffer::Reset(const uint8_t* data, uint64_t start, uint64_t end) {
+ data_ = data;
+ start_ = start;
+ end_ = end;
+}
+
+size_t MemoryOfflineBuffer::Read(uint64_t addr, void* dst, size_t size) {
+ if (addr < start_ || addr >= end_) {
+ return 0;
+ }
+
+ size_t read_length = std::min(size, static_cast<size_t>(end_ - addr));
+ memcpy(dst, &data_[addr - start_], read_length);
+ return read_length;
+}
+
MemoryOfflineParts::~MemoryOfflineParts() {
for (auto memory : memories_) {
delete memory;
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index 19bce04..c0c07f4 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -151,6 +151,21 @@ class MemoryOffline : public Memory {
std::unique_ptr<MemoryRange> memory_;
};
+class MemoryOfflineBuffer : public Memory {
+ public:
+ MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end);
+ virtual ~MemoryOfflineBuffer() = default;
+
+ void Reset(const uint8_t* data, uint64_t start, uint64_t end);
+
+ size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+ const uint8_t* data_;
+ uint64_t start_;
+ uint64_t end_;
+};
+
class MemoryOfflineParts : public Memory {
public:
MemoryOfflineParts() = default;
diff --git a/libunwindstack/tests/MemoryOfflineBufferTest.cpp b/libunwindstack/tests/MemoryOfflineBufferTest.cpp
new file mode 100644
index 0000000..f022884
--- /dev/null
+++ b/libunwindstack/tests/MemoryOfflineBufferTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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 <vector>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Memory.h>
+
+#include "LogFake.h"
+
+namespace unwindstack {
+
+class MemoryOfflineBufferTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ResetLogs();
+ memory_.reset(new MemoryOfflineBuffer(buffer_.data(), kStart, kEnd));
+ }
+
+ static void SetUpTestCase() {
+ buffer_.resize(kLength);
+ for (size_t i = 0; i < kLength; i++) {
+ buffer_[i] = i % 189;
+ }
+ }
+
+ std::unique_ptr<MemoryOfflineBuffer> memory_;
+
+ static constexpr size_t kLength = 0x2000;
+ static constexpr uint64_t kStart = 0x1000;
+ static constexpr uint64_t kEnd = kStart + kLength;
+ static std::vector<uint8_t> buffer_;
+};
+
+std::vector<uint8_t> MemoryOfflineBufferTest::buffer_;
+
+static void VerifyBuffer(uint8_t* buffer, size_t start_value, size_t length) {
+ for (size_t i = 0; i < length; i++) {
+ ASSERT_EQ((start_value + i) % 189, buffer[i]) << "Failed at byte " << i;
+ }
+}
+
+TEST_F(MemoryOfflineBufferTest, read_out_of_bounds) {
+ std::vector<uint8_t> buffer(1024);
+ ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 1));
+ ASSERT_FALSE(memory_->ReadFully(0xfff, buffer.data(), 1));
+ ASSERT_FALSE(memory_->ReadFully(0xfff, buffer.data(), 2));
+ ASSERT_FALSE(memory_->ReadFully(0x3000, buffer.data(), 1));
+ ASSERT_FALSE(memory_->ReadFully(0x3001, buffer.data(), 1));
+}
+
+TEST_F(MemoryOfflineBufferTest, read) {
+ std::vector<uint8_t> buffer(1024);
+ ASSERT_TRUE(memory_->ReadFully(kStart, buffer.data(), 10));
+ ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0, 10));
+
+ ASSERT_TRUE(memory_->ReadFully(kStart + 555, buffer.data(), 40));
+ ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 555, 40));
+
+ ASSERT_TRUE(memory_->ReadFully(kStart + kLength - 105, buffer.data(), 105));
+ ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), kLength - 105, 105));
+}
+
+TEST_F(MemoryOfflineBufferTest, read_past_end) {
+ std::vector<uint8_t> buffer(1024);
+ ASSERT_EQ(100U, memory_->Read(kStart + kLength - 100, buffer.data(), buffer.size()));
+ VerifyBuffer(buffer.data(), kLength - 100, 100);
+}
+
+TEST_F(MemoryOfflineBufferTest, read_after_reset) {
+ std::vector<uint8_t> buffer(1024);
+ ASSERT_TRUE(memory_->ReadFully(kStart, buffer.data(), 100));
+ ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0, 100));
+
+ memory_->Reset(&buffer_[10], 0x12000, 0x13000);
+ ASSERT_TRUE(memory_->ReadFully(0x12000, buffer.data(), 100));
+ ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 10, 100));
+
+ ASSERT_EQ(50U, memory_->Read(0x13000 - 50, buffer.data(), buffer.size()));
+ ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0x1000 - 50 + 10, 50));
+}
+
+} // namespace unwindstack