llvm-project/lldb/source/Host/common/ZipFileResolver.cpp
Kazuki Sakamoto 12dee9d3cd [lldb][Android] Support zip .so file
In Android API level 23 and above, dynamic loader is able to load .so file
directly from APK, which is zip file.
https://android.googlesource.com/platform/bionic/+/master/
android-changes-for-ndk-developers.md#
opening-shared-libraries-directly-from-an-apk

The .so file is page aligned and uncompressed, so
ObjectFileELF::GetModuleSpecifications works with .so file offset and size
directly from zip file without extracting it. (D152757)

GDBRemoteCommunicationServerCommon::GetModuleInfo returns a module spec to LLDB
with "zip_path!/so_path" file spec, which is passed through from Android
dynamic loader, and the .so file offset and size.

PlatformAndroid::DownloadModuleSlice uses 'shell dd' to download the .so file
slice from the zip file with the .so file offset and size.

Differential Revision: https://reviews.llvm.org/D152759
2023-06-20 15:21:46 -07:00

58 lines
2.3 KiB
C++

//===-- ZipFileResolver.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/common/ZipFileResolver.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/ZipFile.h"
using namespace lldb_private;
using namespace llvm::support;
bool ZipFileResolver::ResolveSharedLibraryPath(const FileSpec &file_spec,
FileKind &file_kind,
std::string &file_path,
lldb::offset_t &so_file_offset,
lldb::offset_t &so_file_size) {
// When bionic loads .so file from APK or zip file, this file_spec will be
// "zip_path!/so_path". Otherwise it is just a normal file path.
static constexpr llvm::StringLiteral k_zip_separator("!/");
std::string path(file_spec.GetPath());
size_t pos = path.find(k_zip_separator);
if (pos == std::string::npos) {
// This file_spec does not contain the zip separator.
// Treat this file_spec as a normal file.
// so_file_offset and so_file_size should be 0.
file_kind = FileKind::eFileKindNormal;
file_path = path;
so_file_offset = 0;
so_file_size = 0;
return true;
}
// This file_spec is a zip .so path. Extract the zip path and the .so path.
std::string zip_path(path.substr(0, pos));
std::string so_path(path.substr(pos + k_zip_separator.size()));
// Try to find the .so file from the zip file.
FileSpec zip_file_spec(zip_path);
uint64_t zip_file_size = FileSystem::Instance().GetByteSize(zip_file_spec);
lldb::DataBufferSP zip_data =
FileSystem::Instance().CreateDataBuffer(zip_file_spec, zip_file_size);
if (ZipFile::Find(zip_data, so_path, so_file_offset, so_file_size)) {
// Found the .so file from the zip file and got the file offset and size.
// Return the zip path. so_file_offset and so_file_size are already set.
file_kind = FileKind::eFileKindZip;
file_path = zip_path;
return true;
}
return false;
}