73 lines · cpp
1//===-- ZipFileResolver.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/common/ZipFileResolver.h"10#include "lldb/Host/FileSystem.h"11#include "lldb/Utility/DataBuffer.h"12#include "lldb/Utility/FileSpec.h"13#include "lldb/Utility/ZipFile.h"14 15using namespace lldb_private;16using namespace llvm::support;17 18bool ZipFileResolver::ResolveSharedLibraryPath(const FileSpec &file_spec,19 FileKind &file_kind,20 std::string &file_path,21 lldb::offset_t &so_file_offset,22 lldb::offset_t &so_file_size) {23 // When bionic loads .so file from APK or zip file, this file_spec will be24 // "zip_path!/so_path". Otherwise it is just a normal file path.25 static constexpr llvm::StringLiteral k_zip_separator("!/");26 std::string path(file_spec.GetPath());27 size_t pos = path.find(k_zip_separator);28 29#if defined(_WIN32)30 // When the file_spec is resolved as a Windows path, the zip .so path will be31 // "zip_path!\so_path". Support both patterns on Windows.32 static constexpr llvm::StringLiteral k_zip_separator_win("!\\");33 if (pos == std::string::npos)34 pos = path.find(k_zip_separator_win);35#endif36 37 if (pos == std::string::npos) {38 // This file_spec does not contain the zip separator.39 // Treat this file_spec as a normal file.40 // so_file_offset and so_file_size should be 0.41 file_kind = FileKind::eFileKindNormal;42 file_path = path;43 so_file_offset = 0;44 so_file_size = 0;45 return true;46 }47 48 // This file_spec is a zip .so path. Extract the zip path and the .so path.49 std::string zip_path(path.substr(0, pos));50 std::string so_path(path.substr(pos + k_zip_separator.size()));51 52#if defined(_WIN32)53 // Replace the .so path to use POSIX file separator for file searching inside54 // the zip file.55 std::replace(so_path.begin(), so_path.end(), '\\', '/');56#endif57 58 // Try to find the .so file from the zip file.59 FileSpec zip_file_spec(zip_path);60 uint64_t zip_file_size = FileSystem::Instance().GetByteSize(zip_file_spec);61 lldb::DataBufferSP zip_data =62 FileSystem::Instance().CreateDataBuffer(zip_file_spec, zip_file_size);63 if (ZipFile::Find(zip_data, so_path, so_file_offset, so_file_size)) {64 // Found the .so file from the zip file and got the file offset and size.65 // Return the zip path. so_file_offset and so_file_size are already set.66 file_kind = FileKind::eFileKindZip;67 file_path = zip_path;68 return true;69 }70 71 return false;72}73