diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp b/contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp new file mode 100644 index 000000000000..f70ccb79d089 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp @@ -0,0 +1,72 @@ +//===-- 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 defined(_WIN32) + // When the file_spec is resolved as a Windows path, the zip .so path will be + // "zip_path!\so_path". Support both patterns on Windows. + static constexpr llvm::StringLiteral k_zip_separator_win("!\\"); + if (pos == std::string::npos) + pos = path.find(k_zip_separator_win); +#endif + + 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())); + +#if defined(_WIN32) + // Replace the .so path to use POSIX file separator for file searching inside + // the zip file. + std::replace(so_path.begin(), so_path.end(), '\\', '/'); +#endif + + // 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; +} |