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-exception 6 // 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 15 using namespace lldb_private; 16 using namespace llvm::support; 17 18 bool 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 be 24 // "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 be 31 // "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 #endif 36 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 inside 54 // the zip file. 55 std::replace(so_path.begin(), so_path.end(), '\\', '/'); 56 #endif 57 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