The DexFile handle is allocated from heap in OpenFromFd/OpenFromMemory. After releasing the unique_ptr, the DexFile handle itself is no longer managed by the smart pointer. However, the DexFile handle is not freed in the constructor of DexFileFromFile/DexFileFromMemory. This change uses get() method to get the DexFile pointer while allowing it to be managed by smart pointer so that it can be freed after method end. Added new unit tests to detect leaks. Bug: 151966190 Test: Unwinding can still retrieve dex frame information during crash. Test: Ran new unit tests before change and verified they fail, ran them Test: after the change and verified they don't fail. Signed-off-by: Yong Li <yongl0722@gmail.com> Change-Id: I0627e1e255eb6644aba51e940c1a79ff78d568d7
126 lines
3.7 KiB
C++
126 lines
3.7 KiB
C++
/*
|
|
* 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>
|
|
|
|
#define LOG_TAG "unwind"
|
|
#include <log/log.h>
|
|
|
|
#include <android-base/unique_fd.h>
|
|
#include <art_api/dex_file_support.h>
|
|
|
|
#include <unwindstack/MapInfo.h>
|
|
#include <unwindstack/Memory.h>
|
|
|
|
#include "DexFile.h"
|
|
|
|
namespace unwindstack {
|
|
|
|
static bool CheckDexSupport() {
|
|
if (std::string err_msg; !art_api::dex::TryLoadLibdexfileExternal(&err_msg)) {
|
|
ALOGW("Failed to initialize DEX file support: %s", err_msg.c_str());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool HasDexSupport() {
|
|
static bool has_dex_support = CheckDexSupport();
|
|
return has_dex_support;
|
|
}
|
|
|
|
std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
|
|
MapInfo* info) {
|
|
if (!info->name.empty()) {
|
|
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;
|
|
}
|
|
}
|
|
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) {
|
|
art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset, false);
|
|
if (method_info.offset == 0) {
|
|
return false;
|
|
}
|
|
*method_name = method_info.name;
|
|
*method_offset = dex_offset - method_info.offset;
|
|
return true;
|
|
}
|
|
|
|
std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offset_in_file,
|
|
const std::string& file) {
|
|
if (UNLIKELY(!HasDexSupport())) {
|
|
return nullptr;
|
|
}
|
|
|
|
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
|
|
if (fd == -1) {
|
|
return nullptr;
|
|
}
|
|
|
|
std::string error_msg;
|
|
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(art_dex_file));
|
|
}
|
|
|
|
std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
|
|
Memory* memory,
|
|
const std::string& name) {
|
|
if (UNLIKELY(!HasDexSupport())) {
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<uint8_t> backing_memory;
|
|
|
|
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(art_dex_file, std::move(backing_memory)));
|
|
}
|
|
|
|
if (!error_msg.empty()) {
|
|
return nullptr;
|
|
}
|
|
|
|
backing_memory.resize(size);
|
|
if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(),
|
|
backing_memory.size())) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace unwindstack
|