aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Host/common/ZipFileResolver.cpp72
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;
+}