Elf interface for new unwinder.
This cl includes the code to read arm unwind information from a shared
library.
Bug: 23762183
Test: Passes all unit tests. I can dump the arm unwind information
Test: for an arm shared library.
Change-Id: I43501ea2eab843b81de8bd5128401dd1971af8d3
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index 336e4fe..1fcf842 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -48,14 +48,40 @@
return false;
}
+bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
+ uint64_t last_read_byte;
+ if (__builtin_add_overflow(size, addr, &last_read_byte)) {
+ return false;
+ }
+ if (last_read_byte > raw_.size()) {
+ return false;
+ }
+ memcpy(dst, &raw_[addr], size);
+ return true;
+}
+
+uint8_t* MemoryBuffer::GetPtr(size_t offset) {
+ if (offset < raw_.size()) {
+ return &raw_[offset];
+ }
+ return nullptr;
+}
+
MemoryFileAtOffset::~MemoryFileAtOffset() {
+ Clear();
+}
+
+void MemoryFileAtOffset::Clear() {
if (data_) {
munmap(&data_[-offset_], size_ + offset_);
data_ = nullptr;
}
}
-bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset) {
+bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) {
+ // Clear out any previous data if it exists.
+ Clear();
+
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd == -1) {
return false;
@@ -71,6 +97,10 @@
offset_ = offset & (getpagesize() - 1);
uint64_t aligned_offset = offset & ~(getpagesize() - 1);
size_ = buf.st_size - aligned_offset;
+ if (size < (UINT64_MAX - offset_) && size + offset_ < size_) {
+ // Truncate the mapped size.
+ size_ = size + offset_;
+ }
void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset);
if (map == MAP_FAILED) {
return false;
@@ -91,6 +121,12 @@
}
static bool PtraceRead(pid_t pid, uint64_t addr, long* value) {
+#if !defined(__LP64__)
+ // Cannot read an address greater than 32 bits.
+ if (addr > UINT32_MAX) {
+ return false;
+ }
+#endif
// ptrace() returns -1 and sets errno when the operation fails.
// To disambiguate -1 from a valid result, we clear errno beforehand.
errno = 0;