1061da546Spatrick //===-- ObjectContainerBSDArchive.h -----------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BSD_ARCHIVE_OBJECTCONTAINERBSDARCHIVE_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BSD_ARCHIVE_OBJECTCONTAINERBSDARCHIVE_H 11061da546Spatrick 12061da546Spatrick #include "lldb/Core/UniqueCStringMap.h" 13061da546Spatrick #include "lldb/Symbol/ObjectContainer.h" 14061da546Spatrick #include "lldb/Utility/ArchSpec.h" 15061da546Spatrick #include "lldb/Utility/ConstString.h" 16061da546Spatrick #include "lldb/Utility/FileSpec.h" 17061da546Spatrick 18*f6aab3d8Srobert #include "llvm/Object/Archive.h" 19061da546Spatrick #include "llvm/Support/Chrono.h" 20*f6aab3d8Srobert #include "llvm/Support/Path.h" 21061da546Spatrick 22061da546Spatrick #include <map> 23061da546Spatrick #include <memory> 24061da546Spatrick #include <mutex> 25061da546Spatrick 26*f6aab3d8Srobert enum class ArchiveType { Invalid, Archive, ThinArchive }; 27*f6aab3d8Srobert 28061da546Spatrick class ObjectContainerBSDArchive : public lldb_private::ObjectContainer { 29061da546Spatrick public: 30061da546Spatrick ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp, 31061da546Spatrick lldb::DataBufferSP &data_sp, 32061da546Spatrick lldb::offset_t data_offset, 33061da546Spatrick const lldb_private::FileSpec *file, 34*f6aab3d8Srobert lldb::offset_t offset, lldb::offset_t length, 35*f6aab3d8Srobert ArchiveType archive_type); 36061da546Spatrick 37061da546Spatrick ~ObjectContainerBSDArchive() override; 38061da546Spatrick 39061da546Spatrick // Static Functions 40061da546Spatrick static void Initialize(); 41061da546Spatrick 42061da546Spatrick static void Terminate(); 43061da546Spatrick GetPluginNameStatic()44*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "bsd-archive"; } 45061da546Spatrick GetPluginDescriptionStatic()46*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic() { 47*f6aab3d8Srobert return "BSD Archive object container reader."; 48*f6aab3d8Srobert } 49061da546Spatrick 50061da546Spatrick static lldb_private::ObjectContainer * 51061da546Spatrick CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, 52061da546Spatrick lldb::offset_t data_offset, const lldb_private::FileSpec *file, 53061da546Spatrick lldb::offset_t offset, lldb::offset_t length); 54061da546Spatrick 55061da546Spatrick static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, 56061da546Spatrick lldb::DataBufferSP &data_sp, 57061da546Spatrick lldb::offset_t data_offset, 58061da546Spatrick lldb::offset_t file_offset, 59061da546Spatrick lldb::offset_t length, 60061da546Spatrick lldb_private::ModuleSpecList &specs); 61061da546Spatrick 62*f6aab3d8Srobert static ArchiveType MagicBytesMatch(const lldb_private::DataExtractor &data); 63061da546Spatrick 64061da546Spatrick // Member Functions 65061da546Spatrick bool ParseHeader() override; 66061da546Spatrick GetNumObjects()67061da546Spatrick size_t GetNumObjects() const override { 68061da546Spatrick if (m_archive_sp) 69061da546Spatrick return m_archive_sp->GetNumObjects(); 70061da546Spatrick return 0; 71061da546Spatrick } 72061da546Spatrick 73061da546Spatrick lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override; 74061da546Spatrick 75061da546Spatrick // PluginInterface protocol GetPluginName()76*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 77061da546Spatrick 78061da546Spatrick protected: 79061da546Spatrick struct Object { 80061da546Spatrick Object(); 81061da546Spatrick 82061da546Spatrick void Clear(); 83061da546Spatrick 84*f6aab3d8Srobert lldb::offset_t ExtractFromThin(const lldb_private::DataExtractor &data, 85*f6aab3d8Srobert lldb::offset_t offset, 86*f6aab3d8Srobert llvm::StringRef stringTable); 87*f6aab3d8Srobert 88061da546Spatrick lldb::offset_t Extract(const lldb_private::DataExtractor &data, 89061da546Spatrick lldb::offset_t offset); 90061da546Spatrick /// Object name in the archive. 91061da546Spatrick lldb_private::ConstString ar_name; 92061da546Spatrick 93061da546Spatrick /// Object modification time in the archive. 94be691f3bSpatrick uint32_t modification_time = 0; 95061da546Spatrick 96061da546Spatrick /// Object user id in the archive. 97be691f3bSpatrick uint16_t uid = 0; 98061da546Spatrick 99061da546Spatrick /// Object group id in the archive. 100be691f3bSpatrick uint16_t gid = 0; 101061da546Spatrick 102061da546Spatrick /// Object octal file permissions in the archive. 103be691f3bSpatrick uint16_t mode = 0; 104061da546Spatrick 105061da546Spatrick /// Object size in bytes in the archive. 106be691f3bSpatrick uint32_t size = 0; 107061da546Spatrick 108061da546Spatrick /// File offset in bytes from the beginning of the file of the object data. 109be691f3bSpatrick lldb::offset_t file_offset = 0; 110061da546Spatrick 111061da546Spatrick /// Length of the object data. 112be691f3bSpatrick lldb::offset_t file_size = 0; 113061da546Spatrick }; 114061da546Spatrick 115061da546Spatrick class Archive { 116061da546Spatrick public: 117061da546Spatrick typedef std::shared_ptr<Archive> shared_ptr; 118061da546Spatrick typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map; 119061da546Spatrick 120061da546Spatrick Archive(const lldb_private::ArchSpec &arch, 121061da546Spatrick const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset, 122*f6aab3d8Srobert lldb_private::DataExtractor &data, ArchiveType archive_type); 123061da546Spatrick 124061da546Spatrick ~Archive(); 125061da546Spatrick 126061da546Spatrick static Map &GetArchiveCache(); 127061da546Spatrick 128061da546Spatrick static std::recursive_mutex &GetArchiveCacheMutex(); 129061da546Spatrick 130061da546Spatrick static Archive::shared_ptr FindCachedArchive( 131061da546Spatrick const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch, 132061da546Spatrick const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset); 133061da546Spatrick 134061da546Spatrick static Archive::shared_ptr ParseAndCacheArchiveForFile( 135061da546Spatrick const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch, 136061da546Spatrick const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset, 137*f6aab3d8Srobert lldb_private::DataExtractor &data, ArchiveType archive_type); 138061da546Spatrick GetNumObjects()139061da546Spatrick size_t GetNumObjects() const { return m_objects.size(); } 140061da546Spatrick GetObjectAtIndex(size_t idx)141061da546Spatrick const Object *GetObjectAtIndex(size_t idx) { 142061da546Spatrick if (idx < m_objects.size()) 143061da546Spatrick return &m_objects[idx]; 144061da546Spatrick return nullptr; 145061da546Spatrick } 146061da546Spatrick 147061da546Spatrick size_t ParseObjects(); 148061da546Spatrick 149061da546Spatrick Object *FindObject(lldb_private::ConstString object_name, 150061da546Spatrick const llvm::sys::TimePoint<> &object_mod_time); 151061da546Spatrick GetFileOffset()152061da546Spatrick lldb::offset_t GetFileOffset() const { return m_file_offset; } 153061da546Spatrick GetModificationTime()154061da546Spatrick const llvm::sys::TimePoint<> &GetModificationTime() { 155061da546Spatrick return m_modification_time; 156061da546Spatrick } 157061da546Spatrick GetArchitecture()158061da546Spatrick const lldb_private::ArchSpec &GetArchitecture() const { return m_arch; } 159061da546Spatrick SetArchitecture(const lldb_private::ArchSpec & arch)160061da546Spatrick void SetArchitecture(const lldb_private::ArchSpec &arch) { m_arch = arch; } 161061da546Spatrick 162061da546Spatrick bool HasNoExternalReferences() const; 163061da546Spatrick GetData()164061da546Spatrick lldb_private::DataExtractor &GetData() { return m_data; } 165061da546Spatrick GetArchiveType()166*f6aab3d8Srobert ArchiveType GetArchiveType() { return m_archive_type; } 167*f6aab3d8Srobert 168061da546Spatrick protected: 169061da546Spatrick typedef lldb_private::UniqueCStringMap<uint32_t> ObjectNameToIndexMap; 170061da546Spatrick // Member Variables 171061da546Spatrick lldb_private::ArchSpec m_arch; 172061da546Spatrick llvm::sys::TimePoint<> m_modification_time; 173061da546Spatrick lldb::offset_t m_file_offset; 174061da546Spatrick std::vector<Object> m_objects; 175061da546Spatrick ObjectNameToIndexMap m_object_name_to_index_map; 176061da546Spatrick lldb_private::DataExtractor m_data; ///< The data for this object container 177061da546Spatrick ///so we don't lose data if the .a files 178061da546Spatrick ///gets modified 179*f6aab3d8Srobert ArchiveType m_archive_type; 180061da546Spatrick }; 181061da546Spatrick 182061da546Spatrick void SetArchive(Archive::shared_ptr &archive_sp); 183061da546Spatrick 184061da546Spatrick Archive::shared_ptr m_archive_sp; 185*f6aab3d8Srobert 186*f6aab3d8Srobert ArchiveType m_archive_type; 187061da546Spatrick }; 188061da546Spatrick 189dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BSD_ARCHIVE_OBJECTCONTAINERBSDARCHIVE_H 190