summaryrefslogtreecommitdiffstats
path: root/libbacktrace
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2018-01-30 19:47:24 -0800
committerChristopher Ferris <cferris@google.com>2018-01-31 14:19:42 -0800
commitd70ea5ea8511ae9b9ae57b17390e4027d20e3390 (patch)
tree958dc628f9a4d173076a54bc7d012d85ecc2473e /libbacktrace
parent01ba1157325a5e6572122f5d46cfd0376b75aa98 (diff)
downloadsystem_core-d70ea5ea8511ae9b9ae57b17390e4027d20e3390.tar.gz
system_core-d70ea5ea8511ae9b9ae57b17390e4027d20e3390.tar.bz2
system_core-d70ea5ea8511ae9b9ae57b17390e4027d20e3390.zip
Move dex pc frame creation into libunwindstack.
Test: Compiles, all unit tests pass. Test: Ran 137-cfi art test in interpreter and verified interpreter Test: frames still show up. Change-Id: Icea90194986faa733a873e8cf467fc2513eb5573
Diffstat (limited to 'libbacktrace')
-rw-r--r--libbacktrace/Android.bp8
-rw-r--r--libbacktrace/UnwindDexFile.cpp162
-rw-r--r--libbacktrace/UnwindDexFile.h70
-rw-r--r--libbacktrace/UnwindStack.cpp93
-rw-r--r--libbacktrace/UnwindStackMap.cpp32
-rw-r--r--libbacktrace/UnwindStackMap.h14
-rw-r--r--libbacktrace/unwind_dex_test.cpp273
7 files changed, 23 insertions, 629 deletions
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 14ae44564..10a4e4634 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -50,7 +50,6 @@ libbacktrace_sources = [
"BacktracePtrace.cpp",
"thread_utils.c",
"ThreadEntry.cpp",
- "UnwindDexFile.cpp",
"UnwindStack.cpp",
"UnwindStackMap.cpp",
]
@@ -110,10 +109,9 @@ cc_library {
static_libs: ["libasync_safe"],
},
vendor: {
- cflags: ["-DNO_LIBDEXFILE"],
- exclude_srcs: ["UnwindDexFile.cpp"],
+ cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
exclude_shared_libs: ["libdexfile"],
- },
+ }
},
whole_static_libs: ["libdemangle"],
}
@@ -145,8 +143,6 @@ cc_test {
"backtrace_test.cpp",
"GetPss.cpp",
"thread_utils.c",
-
- "unwind_dex_test.cpp",
],
cflags: [
diff --git a/libbacktrace/UnwindDexFile.cpp b/libbacktrace/UnwindDexFile.cpp
deleted file mode 100644
index 5780fbb9c..000000000
--- a/libbacktrace/UnwindDexFile.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-
-#include <android-base/unique_fd.h>
-
-#include <dex/code_item_accessors-no_art-inl.h>
-#include <dex/compact_dex_file.h>
-#include <dex/dex_file-inl.h>
-#include <dex/dex_file_loader.h>
-#include <dex/standard_dex_file.h>
-
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-
-#include "UnwindDexFile.h"
-
-UnwindDexFile* UnwindDexFile::Create(uint64_t dex_file_offset_in_memory,
- unwindstack::Memory* memory, unwindstack::MapInfo* info) {
- if (!info->name.empty()) {
- std::unique_ptr<UnwindDexFileFromFile> dex_file(new UnwindDexFileFromFile);
- if (dex_file->Open(dex_file_offset_in_memory - info->start + info->offset, info->name)) {
- return dex_file.release();
- }
- }
-
- std::unique_ptr<UnwindDexFileFromMemory> dex_file(new UnwindDexFileFromMemory);
- if (dex_file->Open(dex_file_offset_in_memory, memory)) {
- return dex_file.release();
- }
- return nullptr;
-}
-
-void UnwindDexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
- uint64_t* method_offset) {
- if (dex_file_ == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < dex_file_->NumClassDefs(); ++i) {
- const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(i);
- const uint8_t* class_data = dex_file_->GetClassData(class_def);
- if (class_data == nullptr) {
- continue;
- }
- for (art::ClassDataItemIterator it(*dex_file_.get(), class_data); it.HasNext(); it.Next()) {
- if (!it.IsAtMethod()) {
- continue;
- }
- const art::DexFile::CodeItem* code_item = it.GetMethodCodeItem();
- if (code_item == nullptr) {
- continue;
- }
- art::CodeItemInstructionAccessor code(*dex_file_.get(), code_item);
- if (!code.HasCodeItem()) {
- continue;
- }
-
- uint64_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
- size_t size = code.InsnsSizeInCodeUnits() * sizeof(uint16_t);
- if (offset <= dex_offset && dex_offset < offset + size) {
- *method_name = dex_file_->PrettyMethod(it.GetMemberIndex(), false);
- *method_offset = dex_offset - offset;
- return;
- }
- }
- }
-}
-
-UnwindDexFileFromFile::~UnwindDexFileFromFile() {
- if (size_ != 0) {
- munmap(mapped_memory_, size_);
- }
-}
-
-bool UnwindDexFileFromFile::Open(uint64_t dex_file_offset_in_file, const std::string& file) {
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- return false;
- }
- struct stat buf;
- if (fstat(fd, &buf) == -1) {
- return false;
- }
- uint64_t length;
- if (buf.st_size < 0 ||
- __builtin_add_overflow(dex_file_offset_in_file, sizeof(art::DexFile::Header), &length) ||
- static_cast<uint64_t>(buf.st_size) < length) {
- return false;
- }
-
- mapped_memory_ = mmap(nullptr, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (mapped_memory_ == MAP_FAILED) {
- return false;
- }
- size_ = buf.st_size;
-
- uint8_t* memory = reinterpret_cast<uint8_t*>(mapped_memory_);
-
- art::DexFile::Header* header =
- reinterpret_cast<art::DexFile::Header*>(&memory[dex_file_offset_in_file]);
- if (!art::StandardDexFile::IsMagicValid(header->magic_) &&
- !art::CompactDexFile::IsMagicValid(header->magic_)) {
- return false;
- }
-
- if (__builtin_add_overflow(dex_file_offset_in_file, header->file_size_, &length) ||
- static_cast<uint64_t>(buf.st_size) < length) {
- return false;
- }
-
- art::DexFileLoader loader;
- std::string error_msg;
- auto dex = loader.Open(&memory[dex_file_offset_in_file], header->file_size_, "", 0, nullptr,
- false, false, &error_msg);
- dex_file_.reset(dex.release());
- return dex_file_ != nullptr;
-}
-
-bool UnwindDexFileFromMemory::Open(uint64_t dex_file_offset_in_memory, unwindstack::Memory* memory) {
- art::DexFile::Header header;
- if (!memory->ReadFully(dex_file_offset_in_memory, &header, sizeof(header))) {
- return false;
- }
-
- if (!art::StandardDexFile::IsMagicValid(header.magic_) &&
- !art::CompactDexFile::IsMagicValid(header.magic_)) {
- return false;
- }
-
- memory_.resize(header.file_size_);
- if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), header.file_size_)) {
- return false;
- }
-
- art::DexFileLoader loader;
- std::string error_msg;
- auto dex =
- loader.Open(memory_.data(), header.file_size_, "", 0, nullptr, false, false, &error_msg);
- dex_file_.reset(dex.release());
- return dex_file_ != nullptr;
-}
diff --git a/libbacktrace/UnwindDexFile.h b/libbacktrace/UnwindDexFile.h
deleted file mode 100644
index dd70abafd..000000000
--- a/libbacktrace/UnwindDexFile.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _LIBBACKTRACE_UNWIND_DEX_FILE_H
-#define _LIBBACKTRACE_UNWIND_DEX_FILE_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <dex/dex_file-inl.h>
-
-namespace unwindstack {
-class Memory;
-struct MapInfo;
-} // namespace unwindstack
-
-class UnwindDexFile {
- public:
- UnwindDexFile() = default;
- virtual ~UnwindDexFile() = default;
-
- void GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset);
-
- static UnwindDexFile* Create(uint64_t dex_file_offset_in_memory, unwindstack::Memory* memory,
- unwindstack::MapInfo* info);
-
- protected:
- std::unique_ptr<const art::DexFile> dex_file_;
-};
-
-class UnwindDexFileFromFile : public UnwindDexFile {
- public:
- UnwindDexFileFromFile() = default;
- virtual ~UnwindDexFileFromFile();
-
- bool Open(uint64_t dex_file_offset_in_file, const std::string& name);
-
- private:
- void* mapped_memory_ = nullptr;
- size_t size_ = 0;
-};
-
-class UnwindDexFileFromMemory : public UnwindDexFile {
- public:
- UnwindDexFileFromMemory() = default;
- virtual ~UnwindDexFileFromMemory() = default;
-
- bool Open(uint64_t dex_file_offset_in_memory, unwindstack::Memory* memory);
-
- private:
- std::vector<uint8_t> memory_;
-};
-
-#endif // _LIBBACKTRACE_UNWIND_DEX_FILE_H
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 158467ec2..7e2e6d05e 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -36,70 +36,15 @@
#include <unwindstack/Regs.h>
#include <unwindstack/RegsGetLocal.h>
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+#include <unwindstack/DexFiles.h>
+#endif
#include <unwindstack/Unwinder.h>
#include "BacktraceLog.h"
-#ifndef NO_LIBDEXFILE
-#include "UnwindDexFile.h"
-#endif
#include "UnwindStack.h"
#include "UnwindStackMap.h"
-static void FillInDexFrame(UnwindStackMap* stack_map, uint64_t dex_pc,
- backtrace_frame_data_t* frame) {
- // The DEX PC points into the .dex section within an ELF file.
- // However, this is a BBS section manually mmaped to a .vdex file,
- // so we need to get the following map to find the ELF data.
- unwindstack::Maps* maps = stack_map->stack_maps();
- auto it = maps->begin();
- uint64_t rel_dex_pc;
- unwindstack::MapInfo* info;
- for (; it != maps->end(); ++it) {
- auto entry = *it;
- if (dex_pc >= entry->start && dex_pc < entry->end) {
- info = entry;
- rel_dex_pc = dex_pc - entry->start;
- frame->map.start = entry->start;
- frame->map.end = entry->end;
- frame->map.offset = entry->offset;
- frame->map.load_bias = entry->load_bias;
- frame->map.flags = entry->flags;
- frame->map.name = entry->name;
- frame->rel_pc = rel_dex_pc;
- break;
- }
- }
- if (it == maps->end() || ++it == maps->end()) {
- return;
- }
-
- auto entry = *it;
- auto process_memory = stack_map->process_memory();
- unwindstack::Elf* elf = entry->GetElf(process_memory, true);
- if (!elf->valid()) {
- return;
- }
-
- // Adjust the relative dex by the offset.
- rel_dex_pc += entry->elf_offset;
-
- uint64_t dex_offset;
- if (!elf->GetFunctionName(rel_dex_pc, &frame->func_name, &dex_offset)) {
- return;
- }
- frame->func_offset = dex_offset;
- if (frame->func_name != "$dexfile") {
- return;
- }
-
-#ifndef NO_LIBDEXFILE
- UnwindDexFile* dex_file = stack_map->GetDexFile(dex_pc - dex_offset, info);
- if (dex_file != nullptr) {
- dex_file->GetMethodInformation(dex_offset, &frame->func_name, &frame->func_offset);
- }
-#endif
-}
-
bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
@@ -110,6 +55,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
if (stack_map->GetJitDebug() != nullptr) {
unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
}
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ if (stack_map->GetDexFiles() != nullptr) {
+ unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
+ }
+#endif
unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
if (error != nullptr) {
switch (unwinder.LastErrorCode()) {
@@ -150,36 +100,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
}
auto unwinder_frames = unwinder.frames();
- // Get the real number of frames we'll need.
- size_t total_frames = 0;
- for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++, total_frames++) {
- if (unwinder_frames[i].dex_pc != 0) {
- total_frames++;
- }
- }
- frames->resize(total_frames);
+ frames->resize(unwinder.NumFrames() - num_ignore_frames);
size_t cur_frame = 0;
for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
auto frame = &unwinder_frames[i];
- // Inject extra 'virtual' frame that represents the dex pc data.
- // The dex pc is magic register defined in the Mterp interpreter,
- // and thus it will be restored/observed in the frame after it.
- // Adding the dex frame first here will create something like:
- // #7 pc 006b1ba1 libartd.so ExecuteMterpImpl+14625
- // #8 pc 0015fa20 core.vdex java.util.Arrays.binarySearch+8
- // #9 pc 0039a1ef libartd.so art::interpreter::Execute+719
- if (frame->dex_pc != 0) {
- backtrace_frame_data_t* dex_frame = &frames->at(cur_frame);
- dex_frame->num = cur_frame++;
- dex_frame->pc = frame->dex_pc;
- dex_frame->rel_pc = frame->dex_pc;
- dex_frame->sp = frame->sp;
- dex_frame->stack_size = 0;
- dex_frame->func_offset = 0;
- FillInDexFrame(stack_map, frame->dex_pc, dex_frame);
- }
-
backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
back_frame->num = cur_frame++;
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 97f8d782d..1622e30d4 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -26,20 +26,11 @@
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
-#include "UnwindDexFile.h"
#include "UnwindStackMap.h"
//-------------------------------------------------------------------------
UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {}
-UnwindStackMap::~UnwindStackMap() {
-#ifndef NO_LIBDEXFILE
- for (auto& entry : dex_files_) {
- delete entry.second;
- }
-#endif
-}
-
bool UnwindStackMap::Build() {
if (pid_ == 0) {
pid_ = getpid();
@@ -54,6 +45,9 @@ bool UnwindStackMap::Build() {
// Create a JitDebug object for getting jit unwind information.
std::vector<std::string> search_libs_{"libart.so", "libartd.so"};
jit_debug_.reset(new unwindstack::JitDebug(process_memory_, search_libs_));
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ dex_files_.reset(new unwindstack::DexFiles(process_memory_));
+#endif
if (!stack_maps_->Parse()) {
return false;
@@ -127,26 +121,6 @@ std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() {
return process_memory_;
}
-#ifdef NO_LIBDEXFILE
-UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t, unwindstack::MapInfo*) {
- return nullptr;
-}
-#else
-UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info) {
- // Lock while we get the data.
- std::lock_guard<std::mutex> guard(dex_lock_);
- UnwindDexFile* dex_file;
- auto entry = dex_files_.find(dex_file_offset);
- if (entry == dex_files_.end()) {
- dex_file = UnwindDexFile::Create(dex_file_offset, process_memory_.get(), info);
- dex_files_[dex_file_offset] = dex_file;
- } else {
- dex_file = entry->second;
- }
- return dex_file;
-}
-#endif
-
UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {}
bool UnwindStackOfflineMap::Build() {
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index be5c59e74..94cbfb2a0 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -27,6 +27,9 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+#include <unwindstack/DexFiles.h>
+#endif
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
@@ -36,7 +39,7 @@ class UnwindDexFile;
class UnwindStackMap : public BacktraceMap {
public:
explicit UnwindStackMap(pid_t pid);
- ~UnwindStackMap();
+ ~UnwindStackMap() = default;
bool Build() override;
@@ -51,7 +54,9 @@ class UnwindStackMap : public BacktraceMap {
unwindstack::JitDebug* GetJitDebug() { return jit_debug_.get(); }
- UnwindDexFile* GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info);
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); }
+#endif
protected:
uint64_t GetLoadBias(size_t index) override;
@@ -59,9 +64,8 @@ class UnwindStackMap : public BacktraceMap {
std::unique_ptr<unwindstack::Maps> stack_maps_;
std::shared_ptr<unwindstack::Memory> process_memory_;
std::unique_ptr<unwindstack::JitDebug> jit_debug_;
-#ifndef NO_LIBDEXFILE
- std::mutex dex_lock_;
- std::unordered_map<uint64_t, UnwindDexFile*> dex_files_;
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ std::unique_ptr<unwindstack::DexFiles> dex_files_;
#endif
};
diff --git a/libbacktrace/unwind_dex_test.cpp b/libbacktrace/unwind_dex_test.cpp
deleted file mode 100644
index 449e66296..000000000
--- a/libbacktrace/unwind_dex_test.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <unordered_map>
-
-#include <android-base/test_utils.h>
-
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-
-#include <dex/code_item_accessors-no_art-inl.h>
-#include <dex/standard_dex_file.h>
-
-#include <gtest/gtest.h>
-
-#include "UnwindDexFile.h"
-
-class MemoryFake : public unwindstack::Memory {
- public:
- MemoryFake() = default;
- virtual ~MemoryFake() = default;
-
- size_t Read(uint64_t addr, void* buffer, size_t size) override;
-
- void SetMemory(uint64_t addr, const void* memory, size_t length);
-
- void Clear() { data_.clear(); }
-
- private:
- std::unordered_map<uint64_t, uint8_t> data_;
-};
-
-void MemoryFake::SetMemory(uint64_t addr, const void* memory, size_t length) {
- const uint8_t* src = reinterpret_cast<const uint8_t*>(memory);
- for (size_t i = 0; i < length; i++, addr++) {
- auto value = data_.find(addr);
- if (value != data_.end()) {
- value->second = src[i];
- } else {
- data_.insert({addr, src[i]});
- }
- }
-}
-
-size_t MemoryFake::Read(uint64_t addr, void* memory, size_t size) {
- uint8_t* dst = reinterpret_cast<uint8_t*>(memory);
- for (size_t i = 0; i < size; i++, addr++) {
- auto value = data_.find(addr);
- if (value == data_.end()) {
- return i;
- }
- dst[i] = value->second;
- }
- return size;
-}
-
-// Borrowed from art/dex/dex_file_test.cc.
-static constexpr uint32_t kDexData[] = {
- 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
- 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
- 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
- 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
- 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
- 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
- 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
- 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
- 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
- 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
- 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
- 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
- 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
- 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
- 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
- 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
- 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
-};
-
-TEST(UnwindDexTest, from_file_open_non_exist) {
- UnwindDexFileFromFile dex_file;
- ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
-}
-
-TEST(UnwindDexTest, from_file_open_too_small) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(art::DexFile::Header) - 2,
- static_cast<size_t>(
- TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2)));
-
- // Header too small.
- UnwindDexFileFromFile dex_file;
- ASSERT_FALSE(dex_file.Open(0, tf.path));
-
- // Header correct, file too small.
- ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
- ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
- tf.fd, kDexData, sizeof(art::DexFile::Header)))));
- ASSERT_FALSE(dex_file.Open(0, tf.path));
-}
-
-TEST(UnwindDexTest, from_file_open) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- UnwindDexFileFromFile dex_file;
- ASSERT_TRUE(dex_file.Open(0, tf.path));
-}
-
-TEST(UnwindDexTest, from_file_open_non_zero_offset) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- UnwindDexFileFromFile dex_file;
- ASSERT_TRUE(dex_file.Open(0x100, tf.path));
-}
-
-TEST(UnwindDexTest, from_memory_fail_too_small_for_header) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
- UnwindDexFileFromMemory dex_file;
-
- ASSERT_FALSE(dex_file.Open(0x1000, &memory));
-}
-
-TEST(UnwindDexTest, from_memory_fail_too_small_for_data) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
- UnwindDexFileFromMemory dex_file;
-
- ASSERT_FALSE(dex_file.Open(0x1000, &memory));
-}
-
-TEST(UnwindDexTest, from_memory_open) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
- UnwindDexFileFromMemory dex_file;
-
- ASSERT_TRUE(dex_file.Open(0x1000, &memory));
-}
-
-TEST(UnwindDexTest, create_using_file) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- MemoryFake memory;
- unwindstack::MapInfo info(0, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x500, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-}
-
-TEST(UnwindDexTest, create_using_file_non_zero_start) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- MemoryFake memory;
- unwindstack::MapInfo info(0x100, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x600, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-}
-
-TEST(UnwindDexTest, create_using_file_non_zero_offset) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- MemoryFake memory;
- unwindstack::MapInfo info(0x100, 0x10000, 0x200, 0x5, tf.path);
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x400, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-}
-
-TEST(UnwindDexTest, create_using_memory_empty_file) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- unwindstack::MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-}
-
-TEST(UnwindDexTest, create_using_memory_file_does_not_exist) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- unwindstack::MapInfo info(0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-}
-
-TEST(UnwindDexTest, create_using_memory_file_is_malformed) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(kDexData) - 10,
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
-
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- unwindstack::MapInfo info(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-
- // Check it came from memory by clearing memory and verifying it fails.
- memory.Clear();
- dex_file.reset(UnwindDexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file == nullptr);
-}
-
-TEST(UnwindDexTest, get_method_not_opened) {
- std::string method("something");
- uint64_t method_offset = 100;
- UnwindDexFile dex_file;
- dex_file.GetMethodInformation(0x100, &method, &method_offset);
- EXPECT_EQ("something", method);
- EXPECT_EQ(100U, method_offset);
-}
-
-TEST(UnwindDexTest, get_method) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- unwindstack::MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<UnwindDexFile> dex_file(UnwindDexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-
- std::string method;
- uint64_t method_offset;
- dex_file->GetMethodInformation(0x102, &method, &method_offset);
- EXPECT_EQ("Main.<init>", method);
- EXPECT_EQ(2U, method_offset);
-
- method = "not_in_a_method";
- method_offset = 0x123;
- dex_file->GetMethodInformation(0x100000, &method, &method_offset);
- EXPECT_EQ("not_in_a_method", method);
- EXPECT_EQ(0x123U, method_offset);
-}