11#if defined(_WIN32) || defined(__ANDROID__)
16typedef struct ar_hdr {
19 char ar_uid[6], ar_gid[6];
38#include "llvm/Object/Archive.h"
39#include "llvm/Support/MemoryBuffer.h"
44using namespace llvm::object;
59 printf(
"name = \"%s\"\n", ar_name.GetCString());
60 printf(
"mtime = 0x%8.8" PRIx32
"\n", modification_time);
61 printf(
"size = 0x%8.8" PRIx32
" (%" PRIu32
")\n", size, size);
62 printf(
"file_offset = 0x%16.16" PRIx64
" (%" PRIu64
")\n", file_offset,
64 printf(
"file_size = 0x%16.16" PRIx64
" (%" PRIu64
")\n\n", file_size,
69 const llvm::sys::TimePoint<> &time,
73 : m_arch(arch), m_modification_time(time), m_file_offset(file_offset),
82 std::unique_ptr<llvm::MemoryBuffer> mem_buffer =
83 llvm::MemoryBuffer::getMemBuffer(
89 auto exp_ar = llvm::object::Archive::create(mem_buffer->getMemBufferRef());
94 auto llvm_archive = std::move(exp_ar.get());
96 llvm::Error iter_err = llvm::Error::success();
98 for (
const auto &child: llvm_archive->children(iter_err)) {
100 auto exp_name = child.getName();
105 "failed to get archive object name: {0}");
109 auto exp_mtime = child.getLastModified();
112 std::chrono::duration_cast<std::chrono::seconds>(
113 std::chrono::time_point_cast<std::chrono::seconds>(
114 exp_mtime.get()).time_since_epoch()).count();
117 "failed to get archive object time: {0}");
121 auto exp_size = child.getRawSize();
123 obj.
size = exp_size.get();
126 "failed to get archive object size: {0}");
132 auto exp_file_size = child.getSize();
137 "failed to get archive object file size: {0}");
140 m_object_name_to_index_map.Append(obj.
ar_name, m_objects.size());
141 m_objects.push_back(obj);
145 "failed to iterate over archive objects: {0}");
148 m_object_name_to_index_map.Sort();
149 return m_objects.size();
154 ConstString object_name,
const llvm::sys::TimePoint<> &object_mod_time) {
155 const ObjectNameToIndexMap::Entry *match =
156 m_object_name_to_index_map.FindFirstValueForName(object_name);
159 if (object_mod_time == llvm::sys::TimePoint<>())
160 return &m_objects[match->value];
162 const uint64_t object_modification_date = llvm::sys::toTimeT(object_mod_time);
163 if (m_objects[match->value].modification_time == object_modification_date)
164 return &m_objects[match->value];
166 const ObjectNameToIndexMap::Entry *next_match =
167 m_object_name_to_index_map.FindNextValueForName(match);
169 if (m_objects[next_match->value].modification_time ==
170 object_modification_date)
171 return &m_objects[next_match->value];
172 next_match = m_object_name_to_index_map.FindNextValueForName(next_match);
185 Archive::Map::iterator pos = archive_map.find(file);
188 while (pos != archive_map.end() && pos->first == file) {
191 !pos->second->GetArchitecture().IsCompatibleMatch(arch))
194 pos->second->GetFileOffset() != file_offset)
197 if (pos->second->GetModificationTime() == time) {
207 archive_map.erase(pos);
208 pos = archive_map.find(file);
224 new Archive(arch, time, file_offset, data, archive_type));
226 const size_t num_objects = archive_sp->ParseObjects();
227 if (num_objects > 0) {
228 std::lock_guard<std::recursive_mutex> guard(
241 return g_archive_map;
244std::recursive_mutex &
246 static std::recursive_mutex g_archive_map_mutex;
247 return g_archive_map_mutex;
264 ConstString object_name(module_sp->GetObjectName());
273 data.
SetData(data_sp, data_offset, length);
275 if (file && data_sp && archive_type != ArchiveType::Invalid) {
277 "ObjectContainerBSDArchive::CreateInstance (module = %s, file = "
278 "%p, file_offset = 0x%8.8" PRIx64
", file_size = 0x%8.8" PRIx64
")",
279 module_sp->GetFileSpec().GetPath().c_str(),
280 static_cast<const void *
>(file),
static_cast<uint64_t
>(file_offset),
281 static_cast<uint64_t
>(length));
288 if (!archive_data_sp)
294 *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(),
296 std::unique_ptr<ObjectContainerBSDArchive> container_up(
298 archive_data_offset, file, file_offset,
299 length, archive_type));
304 container_up->SetArchive(archive_sp);
305 return container_up.release();
306 }
else if (container_up->ParseHeader())
307 return container_up.release();
313 *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(),
316 std::unique_ptr<ObjectContainerBSDArchive> container_up(
319 archive_sp->GetArchiveType()));
323 container_up->SetArchive(archive_sp);
324 return container_up.release();
334 const char *armag = (
const char *)data.
PeekData(offset,
335 sizeof(ar_hdr) + SARMAG);
336 if (armag ==
nullptr)
337 return ArchiveType::Invalid;
339 if (strncmp(armag, ArchiveMagic, SARMAG) == 0)
340 result = ArchiveType::Archive;
341 else if (strncmp(armag, ThinArchiveMagic, SARMAG) == 0)
342 result = ArchiveType::ThinArchive;
344 return ArchiveType::Invalid;
346 armag += offsetof(
struct ar_hdr, ar_fmag) + SARMAG;
347 if (strncmp(armag, ARFMAG, 2) == 0)
349 return ArchiveType::Invalid;
356 :
ObjectContainer(module_sp, file, file_offset, size, data_sp, data_offset),
373 m_file, module_sp->GetArchitecture(),
386 llvm::SmallString<128> FullPath;
387 if (llvm::sys::path::is_absolute(childPath)) {
388 FullPath = childPath;
391 llvm::sys::path::append(FullPath, childPath);
402 module_sp->GetObjectName(), module_sp->GetObjectModificationTime());
410 std::shared_ptr<DataBuffer> child_data_sp =
413 if (!child_data_sp ||
414 child_data_sp->GetByteSize() != object->
file_size)
419 object->
file_size, child_data_sp, data_offset);
424 m_archive_sp->GetData().GetSharedDataBuffer(), data_offset);
440 data.
SetData(data_sp, data_offset, data_sp->GetByteSize());
442 if (!file || !data_sp || archive_type == ArchiveType::Invalid)
445 const size_t initial_count = specs.
GetSize();
449 bool set_archive_arch =
false;
451 set_archive_arch =
true;
455 data.
SetData(data_sp, 0, data_sp->GetByteSize());
457 file,
ArchSpec(), file_mod_time, file_offset, data, archive_type);
462 const size_t num_objects = archive_sp->GetNumObjects();
463 for (
size_t idx = 0; idx < num_objects; ++idx) {
464 const Object *
object = archive_sp->GetObjectAtIndex(idx);
466 if (archive_sp->GetArchiveType() == ArchiveType::ThinArchive) {
475 llvm::sys::TimePoint<> object_mod_time(
485 file_offset +
object->file_offset;
486 if (object->
file_offset < file_size && file_size > object_file_offset) {
488 file, object_file_offset, file_size - object_file_offset,
492 llvm::sys::TimePoint<> object_mod_time(
503 const size_t end_count = specs.
GetSize();
504 size_t num_specs_added = end_count - initial_count;
505 if (set_archive_arch && num_specs_added > 0) {
508 for (
size_t i = initial_count; i < end_count; ++i) {
518 return num_specs_added;
#define LLDB_LOG_ERROR(log, error,...)
FileSpec GetChildFileSpecificationsFromThin(llvm::StringRef childPath, const FileSpec &parentFileSpec)
#define LLDB_PLUGIN_DEFINE(PluginName)
#define LLDB_SCOPED_TIMERF(...)
Object * FindObject(lldb_private::ConstString object_name, const llvm::sys::TimePoint<> &object_mod_time)
Archive(const lldb_private::ArchSpec &arch, const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset, lldb_private::DataExtractor &data, ArchiveType archive_type)
static std::recursive_mutex & GetArchiveCacheMutex()
static Archive::shared_ptr ParseAndCacheArchiveForFile(const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch, const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset, lldb_private::DataExtractor &data, ArchiveType archive_type)
std::multimap< lldb_private::FileSpec, shared_ptr > Map
std::shared_ptr< Archive > shared_ptr
static Map & GetArchiveCache()
static Archive::shared_ptr FindCachedArchive(const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch, const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset)
static lldb_private::ObjectContainer * CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t offset, lldb::offset_t length)
static llvm::StringRef GetPluginNameStatic()
lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override
Selects an architecture in an object file.
bool ParseHeader() override
Attempts to parse the object header.
static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs)
static ArchiveType MagicBytesMatch(const lldb_private::DataExtractor &data)
static llvm::StringRef GetPluginDescriptionStatic()
ArchiveType m_archive_type
~ObjectContainerBSDArchive() override
Archive::shared_ptr m_archive_sp
void SetArchive(Archive::shared_ptr &archive_sp)
ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t offset, lldb::offset_t length, ArchiveType archive_type)
An architecture specification class.
bool IsValid() const
Tests if this ArchSpec is valid.
A uniqued constant string class.
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
void Clear()
Clear this object's state.
const ConstString & GetDirectory() const
Directory string const get accessor.
llvm::sys::TimePoint GetModificationTime(const FileSpec &file_spec) const
Returns the modification time of the given file.
static FileSystem & Instance()
std::shared_ptr< DataBuffer > CreateDataBuffer(const llvm::Twine &path, uint64_t size=0, uint64_t offset=0)
Create memory buffer from path.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const
ModuleSpec & GetModuleSpecRefAtIndex(size_t i)
void SetObjectSize(uint64_t object_size)
ConstString & GetObjectName()
ArchSpec & GetArchitecture()
void SetObjectOffset(uint64_t object_offset)
llvm::sys::TimePoint & GetObjectModificationTime()
A plug-in interface definition class for object containers.
DataExtractor m_data
The data for this object file so things can be parsed lazily.
FileSpec m_file
The file that represents this container objects (which can be different from the module's file).
lldb::addr_t m_offset
The offset in bytes into the file, or the address in memory.
static lldb::ObjectFileSP FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file_spec, lldb::offset_t file_offset, lldb::offset_t file_size, lldb::DataBufferSP &data_sp, lldb::offset_t &data_offset)
Find a ObjectFile plug-in that can parse file_spec.
static size_t GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset, lldb::offset_t file_size, ModuleSpecList &specs, lldb::DataBufferSP data_sp=lldb::DataBufferSP())
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
#define LLDB_INVALID_OFFSET
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::ObjectFile > ObjectFileSP
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::Module > ModuleSP
uint32_t size
Object size in bytes in the archive.
uint32_t modification_time
Object modification time in the archive.
lldb_private::ConstString ar_name
Object name in the archive.
lldb::offset_t file_size
Length of the object data.
lldb::offset_t file_offset
File offset in bytes from the beginning of the file of the object data.