Merge "Allow init to skip mounting /product and /product_services"
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index d9fae52..5167481 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -116,14 +116,21 @@
"libdebuggerd",
"libbacktrace",
"libunwindstack",
- "libdexfile",
+ "libdexfile", // libunwindstack dependency
+ "libdexfile_external", // libunwindstack dependency
+ "libdexfile_support", // libunwindstack dependency
"liblzma",
"libcutils",
],
target: {
recovery: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- exclude_static_libs: ["libdexfile"],
+ exclude_static_libs: [
+ "libartbase",
+ "libdexfile",
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
},
},
@@ -170,12 +177,22 @@
static_libs: [
"libbacktrace",
+ "libdexfile_external", // libunwindstack dependency
+ "libdexfile_support", // libunwindstack dependency
"libunwindstack",
"liblzma",
"libbase",
"libcutils",
"liblog",
],
+ target: {
+ recovery: {
+ exclude_static_libs: [
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
+ },
+ },
}
cc_test {
@@ -216,6 +233,8 @@
static_libs: [
"libdebuggerd",
+ "libdexfile_external", // libunwindstack dependency
+ "libdexfile_support", // libunwindstack dependency
"libunwindstack",
],
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 421ce43..d24c887 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -15,6 +15,7 @@
*/
#include <stdlib.h>
+#include <time.h>
#include <memory>
#include <string>
@@ -494,3 +495,10 @@
expected += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
}
+
+TEST_F(TombstoneTest, dump_timestamp) {
+ setenv("TZ", "UTC", 1);
+ tzset();
+ dump_timestamp(&log_, 0);
+ ASSERT_STREQ("Timestamp: 1970-01-01 00:00:00+0000\n", amfd_data_.c_str());
+}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 1179263..b20014f 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -78,6 +78,15 @@
_LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
}
+static void dump_timestamp(log_t* log, time_t time) {
+ struct tm tm;
+ localtime_r(&time, &tm);
+
+ char buf[strlen("1970-01-01 00:00:00+0830") + 1];
+ strftime(buf, sizeof(buf), "%F %T%z", &tm);
+ _LOG(log, logtype::HEADER, "Timestamp: %s\n", buf);
+}
+
static void dump_probable_cause(log_t* log, const siginfo_t* si, BacktraceMap* map) {
std::string cause;
if (si->si_signo == SIGSEGV && si->si_code == SEGV_MAPERR) {
@@ -654,6 +663,7 @@
_LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_header_info(&log);
+ dump_timestamp(&log, time(nullptr));
auto it = threads.find(target_thread);
if (it == threads.end()) {
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index d3cd459..bd9d675 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -59,7 +59,7 @@
struct flag_list {
const char *name;
- unsigned int flag;
+ uint64_t flag;
};
static struct flag_list mount_flags[] = {
@@ -116,6 +116,7 @@
{"logical", MF_LOGICAL},
{"checkpoint=block", MF_CHECKPOINT_BLK},
{"checkpoint=fs", MF_CHECKPOINT_FS},
+ {"slotselect_other", MF_SLOTSELECT_OTHER},
{0, 0},
};
@@ -207,11 +208,9 @@
return false;
}
-static int parse_flags(char *flags, struct flag_list *fl,
- struct fs_mgr_flag_values *flag_vals,
- char *fs_options, int fs_options_len)
-{
- int f = 0;
+static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_flag_values* flag_vals,
+ char* fs_options, int fs_options_len) {
+ uint64_t f = 0;
int i;
char *p;
char *savep;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 072da97..7d1159b 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -120,6 +120,8 @@
#define MF_CHECKPOINT_FS 0x40000000
#define MF_FIRST_STAGE_MOUNT \
0x80000000
+#define MF_SLOTSELECT_OTHER \
+ 0x100000000
// clang-format on
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index efc29bd..3cb718c 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -21,6 +21,19 @@
#include "fs_mgr.h"
#include "fs_mgr_priv.h"
+// https://source.android.com/devices/tech/ota/ab/ab_implement#partitions
+// All partitions that are A/B-ed should be named as follows (slots are always
+// named a, b, etc.): boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.
+static std::string other_suffix(const std::string& slot_suffix) {
+ if (slot_suffix == "_a") {
+ return "_b";
+ }
+ if (slot_suffix == "_b") {
+ return "_a";
+ }
+ return "";
+}
+
// Returns "_a" or "_b" based on androidboot.slot_suffix in kernel cmdline, or an empty string
// if that parameter does not exist.
std::string fs_mgr_get_slot_suffix() {
@@ -35,7 +48,7 @@
std::string ab_suffix;
for (auto& entry : *fstab) {
- if (!entry.fs_mgr_flags.slot_select) {
+ if (!entry.fs_mgr_flags.slot_select && !entry.fs_mgr_flags.slot_select_other) {
continue;
}
@@ -45,8 +58,10 @@
if (ab_suffix.empty()) return false;
}
- entry.blk_device = entry.blk_device + ab_suffix;
- entry.logical_partition_name = entry.logical_partition_name + ab_suffix;
+ const auto& update_suffix =
+ entry.fs_mgr_flags.slot_select ? ab_suffix : other_suffix(ab_suffix);
+ entry.blk_device = entry.blk_device + update_suffix;
+ entry.logical_partition_name = entry.logical_partition_name + update_suffix;
}
return true;
}
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index d9a5e0a..0997254 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -43,7 +43,7 @@
char* fs_type;
unsigned long flags;
char* fs_options;
- int fs_mgr_flags;
+ uint64_t fs_mgr_flags;
char* key_loc;
char* key_dir;
char* verity_loc;
@@ -123,8 +123,9 @@
// TODO: Remove this union once fstab_rec is deprecated. It only serves as a
// convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
union {
- int val;
+ uint64_t val;
struct {
+ // bit 0
bool wait : 1;
bool check : 1;
bool crypt : 1;
@@ -133,6 +134,8 @@
bool length : 1;
bool recovery_only : 1;
bool swap_prio : 1;
+
+ // bit 8
bool zram_size : 1;
bool verify : 1;
bool force_crypt : 1;
@@ -142,6 +145,8 @@
bool file_encryption : 1;
bool formattable : 1;
bool slot_select : 1;
+
+ // bit 16
bool force_fde_or_fbe : 1;
bool late_mount : 1;
bool no_fail : 1;
@@ -150,6 +155,8 @@
bool reserved_size : 1;
bool quota : 1;
bool erase_blk_size : 1;
+
+ // bit 24
bool logical_blk_size : 1;
bool avb : 1;
bool key_directory : 1;
@@ -158,6 +165,9 @@
bool checkpoint_blk : 1;
bool checkpoint_fs : 1;
bool first_stage_mount : 1;
+
+ // bit 32
+ bool slot_select_other : 1;
};
} fs_mgr_flags;
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index aaee1a7..5957e30 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -290,6 +290,11 @@
fi
inAdb || die "specified device not in adb mode"
isDebuggable || die "device not a debug build"
+enforcing=true
+if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode"
+ enforcing=false
+fi
# Do something
@@ -535,9 +540,11 @@
die "re-read system hello after reboot"
check_eq "${A}" "${B}" system after reboot
# Only root can read vendor if sepolicy permissions are as expected
-B="`adb_cat /vendor/hello`" &&
- die "re-read vendor hello after reboot w/o root"
-check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root
+if ${enforcing}; then
+ B="`adb_cat /vendor/hello`" &&
+ die "re-read vendor hello after reboot w/o root"
+ check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root
+fi
adb_root &&
B="`adb_cat /vendor/hello`" ||
die "re-read vendor hello after reboot"
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 4e0470e..89d4fc0 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -94,7 +94,10 @@
"DexFile.cpp",
"DexFiles.cpp",
],
- exclude_shared_libs: ["libdexfile"],
+ exclude_shared_libs: [
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
},
recovery: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
@@ -102,7 +105,10 @@
"DexFile.cpp",
"DexFiles.cpp",
],
- exclude_shared_libs: ["libdexfile"],
+ exclude_shared_libs: [
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
},
},
@@ -127,7 +133,8 @@
shared_libs: [
"libbase",
- "libdexfile",
+ "libdexfile_external",
+ "libdexfile_support",
"liblog",
"liblzma",
],
@@ -215,6 +222,7 @@
"liblzma",
"libunwindstack",
"libdexfile",
+ "libdexfile_support",
],
static_libs: [
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index 8ec560c..9b0b232 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -23,13 +23,7 @@
#include <memory>
#include <android-base/unique_fd.h>
-
-#include <dex/class_accessor-inl.h>
-#include <dex/code_item_accessors-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 <art_api/ext_dex_file.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
@@ -38,169 +32,71 @@
namespace unwindstack {
-DexFile* DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info) {
+std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
+ MapInfo* info) {
if (!info->name.empty()) {
- std::unique_ptr<DexFileFromFile> dex_file(new DexFileFromFile);
- if (dex_file->Open(dex_file_offset_in_memory - info->start + info->offset, info->name)) {
- return dex_file.release();
+ std::unique_ptr<DexFile> dex_file =
+ DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
+ if (dex_file) {
+ return dex_file;
}
}
-
- std::unique_ptr<DexFileFromMemory> dex_file(new DexFileFromMemory);
- if (dex_file->Open(dex_file_offset_in_memory, memory)) {
- return dex_file.release();
- }
- return nullptr;
-}
-
-DexFileFromFile::~DexFileFromFile() {
- if (size_ != 0) {
- munmap(mapped_memory_, size_);
- }
+ return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name);
}
bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
uint64_t* method_offset) {
- if (dex_file_ == nullptr) {
+ art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset);
+ if (method_info.offset == 0) {
return false;
}
-
- if (!dex_file_->IsInDataSection(dex_file_->Begin() + dex_offset)) {
- return false; // The DEX offset is not within the bytecode of this dex file.
- }
-
- if (dex_file_->IsCompactDexFile()) {
- // The data section of compact dex files might be shared.
- // Check the subrange unique to this compact dex.
- const auto& cdex_header = dex_file_->AsCompactDexFile()->GetHeader();
- uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
- uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
- if (dex_offset < begin || dex_offset >= end) {
- return false; // The DEX offset is not within the bytecode of this dex file.
- }
- }
-
- // The method data is cached in a std::map indexed by method end offset and
- // contains the start offset and the method member index.
- // Only cache the method data as it is searched. Do not read the entire
- // set of method data into the cache at once.
- // This is done because many unwinds only find a single frame with dex file
- // info, so reading the entire method data is wasteful. However, still cache
- // the data so that anything doing multiple unwinds will have this data
- // cached for future use.
-
- // First look in the method cache.
- auto entry = method_cache_.upper_bound(dex_offset);
- if (entry != method_cache_.end() && dex_offset >= entry->second.first) {
- *method_name = dex_file_->PrettyMethod(entry->second.second, false);
- *method_offset = dex_offset - entry->second.first;
- return true;
- }
-
- // Check the methods we haven't cached.
- for (; class_def_index_ < dex_file_->NumClassDefs(); class_def_index_++) {
- art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(class_def_index_));
-
- for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
- art::CodeItemInstructionAccessor code = method.GetInstructions();
- if (!code.HasCodeItem()) {
- continue;
- }
- uint32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
- uint32_t offset_end = offset + code.InsnsSizeInBytes();
- uint32_t member_index = method.GetIndex();
- method_cache_[offset_end] = std::make_pair(offset, member_index);
- if (offset <= dex_offset && dex_offset < offset_end) {
- *method_name = dex_file_->PrettyMethod(member_index, false);
- *method_offset = dex_offset - offset;
- return true;
- }
- }
- }
- return false;
+ *method_name = method_info.name;
+ *method_offset = dex_offset - method_info.offset;
+ return true;
}
-bool DexFileFromFile::Open(uint64_t dex_file_offset_in_file, const std::string& file) {
+std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(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;
+ return nullptr;
}
- 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;
+ std::unique_ptr<art_api::dex::DexFile> art_dex_file =
+ OpenFromFd(fd, dex_file_offset_in_file, file, &error_msg);
+ if (art_dex_file == nullptr) {
+ return nullptr;
+ }
+
+ return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(std::move(*art_dex_file.release())));
}
-bool DexFileFromMemory::Open(uint64_t dex_file_offset_in_memory, Memory* memory) {
- memory_.resize(sizeof(art::DexFile::Header));
- if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), memory_.size())) {
- return false;
- }
+std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
+ Memory* memory,
+ const std::string& name) {
+ std::vector<uint8_t> backing_memory;
- art::DexFile::Header* header = reinterpret_cast<art::DexFile::Header*>(memory_.data());
- uint32_t file_size = header->file_size_;
- if (art::CompactDexFile::IsMagicValid(header->magic_)) {
- // Compact dex file store data section separately so that it can be shared.
- // Therefore we need to extend the read memory range to include it.
- // TODO: This might be wasteful as we might read data in between as well.
- // In practice, this should be fine, as such sharing only happens on disk.
- uint32_t computed_file_size;
- if (__builtin_add_overflow(header->data_off_, header->data_size_, &computed_file_size)) {
- return false;
+ for (size_t size = 0;;) {
+ std::string error_msg;
+ std::unique_ptr<art_api::dex::DexFile> art_dex_file =
+ OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
+
+ if (art_dex_file != nullptr) {
+ return std::unique_ptr<DexFileFromMemory>(
+ new DexFileFromMemory(std::move(*art_dex_file.release()), std::move(backing_memory)));
}
- if (computed_file_size > file_size) {
- file_size = computed_file_size;
+
+ if (!error_msg.empty()) {
+ return nullptr;
}
- } else if (!art::StandardDexFile::IsMagicValid(header->magic_)) {
- return false;
+
+ backing_memory.resize(size);
+ if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(),
+ backing_memory.size())) {
+ return nullptr;
+ }
}
-
- memory_.resize(file_size);
- if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), memory_.size())) {
- return false;
- }
-
- header = reinterpret_cast<art::DexFile::Header*>(memory_.data());
-
- 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;
}
} // namespace unwindstack
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
index c123158..5797dee 100644
--- a/libunwindstack/DexFile.h
+++ b/libunwindstack/DexFile.h
@@ -25,48 +25,41 @@
#include <utility>
#include <vector>
-#include <dex/dex_file-inl.h>
+#include <art_api/ext_dex_file.h>
namespace unwindstack {
-class DexFile {
+class DexFile : protected art_api::dex::DexFile {
public:
- DexFile() = default;
virtual ~DexFile() = default;
bool GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset);
- static DexFile* Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info);
+ static std::unique_ptr<DexFile> Create(uint64_t dex_file_offset_in_memory, Memory* memory,
+ MapInfo* info);
protected:
- void Init();
-
- std::unique_ptr<const art::DexFile> dex_file_;
- std::map<uint32_t, std::pair<uint64_t, uint32_t>> method_cache_; // dex offset to method index.
-
- uint32_t class_def_index_ = 0;
+ DexFile(art_api::dex::DexFile&& art_dex_file) : art_api::dex::DexFile(std::move(art_dex_file)) {}
};
class DexFileFromFile : public DexFile {
public:
- DexFileFromFile() = default;
- virtual ~DexFileFromFile();
-
- bool Open(uint64_t dex_file_offset_in_file, const std::string& name);
+ static std::unique_ptr<DexFileFromFile> Create(uint64_t dex_file_offset_in_file,
+ const std::string& file);
private:
- void* mapped_memory_ = nullptr;
- size_t size_ = 0;
+ DexFileFromFile(art_api::dex::DexFile&& art_dex_file) : DexFile(std::move(art_dex_file)) {}
};
class DexFileFromMemory : public DexFile {
public:
- DexFileFromMemory() = default;
- virtual ~DexFileFromMemory() = default;
-
- bool Open(uint64_t dex_file_offset_in_memory, Memory* memory);
+ static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
+ Memory* memory, const std::string& name);
private:
+ DexFileFromMemory(art_api::dex::DexFile&& art_dex_file, std::vector<uint8_t>&& memory)
+ : DexFile(std::move(art_dex_file)), memory_(std::move(memory)) {}
+
std::vector<uint8_t> memory_;
};
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 451a0b9..63a77e5 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -48,11 +48,7 @@
DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
: Global(memory, search_libs) {}
-DexFiles::~DexFiles() {
- for (auto& entry : files_) {
- delete entry.second;
- }
-}
+DexFiles::~DexFiles() {}
void DexFiles::ProcessArch() {
switch (arch()) {
@@ -137,10 +133,11 @@
DexFile* dex_file;
auto entry = files_.find(dex_file_offset);
if (entry == files_.end()) {
- dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
- files_[dex_file_offset] = dex_file;
+ std::unique_ptr<DexFile> new_dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
+ dex_file = new_dex_file.get();
+ files_[dex_file_offset] = std::move(new_dex_file);
} else {
- dex_file = entry->second;
+ dex_file = entry->second.get();
}
return dex_file;
}
diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h
index c202a33..0336173 100644
--- a/libunwindstack/include/unwindstack/DexFiles.h
+++ b/libunwindstack/include/unwindstack/DexFiles.h
@@ -66,7 +66,7 @@
std::mutex lock_;
bool initialized_ = false;
- std::unordered_map<uint64_t, DexFile*> files_;
+ std::unordered_map<uint64_t, std::unique_ptr<DexFile>> files_;
uint64_t entry_addr_ = 0;
uint64_t (DexFiles::*read_entry_ptr_func_)(uint64_t) = nullptr;
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 95d2176..21ca47b 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -21,44 +21,37 @@
#include <unordered_map>
#include <android-base/file.h>
-
+#include <dex/dex_file.h>
+#include <gtest/gtest.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
-#include <dex/code_item_accessors-inl.h>
-#include <dex/standard_dex_file.h>
-
-#include <gtest/gtest.h>
-
#include "DexFile.h"
-
#include "DexFileData.h"
#include "MemoryFake.h"
namespace unwindstack {
TEST(DexFileTest, from_file_open_non_exist) {
- DexFileFromFile dex_file;
- ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
+ EXPECT_TRUE(DexFileFromFile::Create(0, "/file/does/not/exist") == nullptr);
}
TEST(DexFileTest, from_file_open_too_small) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_EQ(sizeof(art::DexFile::Header) - 2,
+ ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
static_cast<size_t>(
- TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2)));
+ TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
// Header too small.
- DexFileFromFile dex_file;
- ASSERT_FALSE(dex_file.Open(0, tf.path));
+ EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
// 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));
+ EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
}
TEST(DexFileTest, from_file_open) {
@@ -68,8 +61,7 @@
ASSERT_EQ(sizeof(kDexData),
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
- DexFileFromFile dex_file;
- ASSERT_TRUE(dex_file.Open(0, tf.path));
+ EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
}
TEST(DexFileTest, from_file_open_non_zero_offset) {
@@ -80,35 +72,31 @@
ASSERT_EQ(sizeof(kDexData),
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
- DexFileFromFile dex_file;
- ASSERT_TRUE(dex_file.Open(0x100, tf.path));
+ EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr);
}
TEST(DexFileTest, from_memory_fail_too_small_for_header) {
MemoryFake memory;
memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
- DexFileFromMemory dex_file;
- ASSERT_FALSE(dex_file.Open(0x1000, &memory));
+ EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
}
TEST(DexFileTest, from_memory_fail_too_small_for_data) {
MemoryFake memory;
memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
- DexFileFromMemory dex_file;
- ASSERT_FALSE(dex_file.Open(0x1000, &memory));
+ EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
}
TEST(DexFileTest, from_memory_open) {
MemoryFake memory;
memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
- DexFileFromMemory dex_file;
- ASSERT_TRUE(dex_file.Open(0x1000, &memory));
+ EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
}
TEST(DexFileTest, create_using_file) {
@@ -121,8 +109,7 @@
MemoryFake memory;
MapInfo info(nullptr, 0, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_file_non_zero_start) {
@@ -135,8 +122,7 @@
MemoryFake memory;
MapInfo info(nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_file_non_zero_offset) {
@@ -149,24 +135,21 @@
MemoryFake memory;
MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_empty_file) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_file_does_not_exist) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_file_is_malformed) {
@@ -179,22 +162,13 @@
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
+ std::unique_ptr<DexFile> dex_file = DexFile::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(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file == nullptr);
-}
-
-TEST(DexFileTest, get_method_not_opened) {
- std::string method("something");
- uint64_t method_offset = 100;
- DexFile dex_file;
- dex_file.GetMethodInformation(0x100, &method, &method_offset);
- EXPECT_EQ("something", method);
- EXPECT_EQ(100U, method_offset);
+ dex_file = DexFile::Create(0x4000, &memory, &info);
+ EXPECT_TRUE(dex_file == nullptr);
}
TEST(DexFileTest, get_method) {
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 969f26b..267da4a 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -510,9 +510,7 @@
return android::base::Trim(content) == string;
}
-void llkPanicKernel(bool dump, pid_t tid, const char* state,
- const std::string& message = "") __noreturn;
-void llkPanicKernel(bool dump, pid_t tid, const char* state, const std::string& message) {
+void llkPanicKernel(bool dump, pid_t tid, const char* state, const std::string& message = "") {
if (!message.empty()) LOG(ERROR) << message;
auto sysrqTriggerFd = llkFileToWriteFd("/proc/sysrq-trigger");
if (sysrqTriggerFd < 0) {
@@ -521,6 +519,7 @@
// The answer to life, the universe and everything
::exit(42);
// NOTREACHED
+ return;
}
::sync();
if (dump) {
@@ -544,6 +543,13 @@
llkWriteStringToFile(message + (message.empty() ? "" : "\n") +
"SysRq : Trigger a crash : 'livelock,"s + state + "'\n",
"/dev/kmsg");
+ // Because panic is such a serious thing to do, let us
+ // make sure that the tid being inspected still exists!
+ auto piddir = procdir + std::to_string(tid) + "/stat";
+ if (access(piddir.c_str(), F_OK) != 0) {
+ PLOG(WARNING) << piddir;
+ return;
+ }
android::base::WriteStringToFd("c", sysrqTriggerFd);
// NOTREACHED
// DYB
@@ -909,6 +915,7 @@
ms -= llkCycle;
auto myPid = ::getpid();
auto myTid = ::gettid();
+ auto dump = true;
for (auto dp = llkTopDirectory.read(); dp != nullptr; dp = llkTopDirectory.read()) {
std::string piddir;
@@ -1109,9 +1116,10 @@
const auto message = state + " "s + llkFormat(procp->count) + " " +
std::to_string(ppid) + "->" + std::to_string(pid) + "->" +
std::to_string(tid) + " " + procp->getComm() + " [panic]";
- llkPanicKernel(true, tid,
+ llkPanicKernel(dump, tid,
(state == 'Z') ? "zombie" : (state == 'D') ? "driver" : "sleeping",
message);
+ dump = false;
}
LOG(VERBOSE) << "+closedir()";
}