11#if defined(_WIN32) || defined(__ANDROID__)
13#define ARMAG "!<arch>\n"
17typedef struct ar_hdr {
20 char ar_uid[6], ar_gid[6];
38#include "llvm/Support/MemoryBuffer.h"
43using namespace llvm::object;
62 llvm::StringRef stringTable) {
63 size_t ar_name_len = 0;
90 str.assign((
const char *)data.
GetData(&offset, 16), 16);
91 if (!(llvm::StringRef(str).startswith(
"//") || stringTable.empty())) {
93 const size_t last_pos = str.find_last_not_of(
' ');
94 if (last_pos != std::string::npos) {
95 if (last_pos + 1 < 16)
96 str.erase(last_pos + 1);
98 int start = strtoul(str.c_str() + 1, &err, 10);
99 int end = stringTable.find(
'\n', start);
100 str.assign(stringTable.data() + start, end - start - 1);
101 ar_name.SetCString(str.c_str());
104 str.assign((
const char *)data.
GetData(&offset, 12), 12);
105 modification_time = strtoul(str.c_str(), &err, 10);
107 str.assign((
const char *)data.
GetData(&offset, 6), 6);
108 uid = strtoul(str.c_str(), &err, 10);
110 str.assign((
const char *)data.
GetData(&offset, 6), 6);
111 gid = strtoul(str.c_str(), &err, 10);
113 str.assign((
const char *)data.
GetData(&offset, 8), 8);
114 mode = strtoul(str.c_str(), &err, 8);
116 str.assign((
const char *)data.
GetData(&offset, 10), 10);
117 size = strtoul(str.c_str(), &err, 10);
119 str.assign((
const char *)data.
GetData(&offset, 2), 2);
121 file_offset = offset;
122 file_size = size - ar_name_len;
131 size_t ar_name_len = 0;
158 str.assign((
const char *)data.
GetData(&offset, 16), 16);
159 if (llvm::StringRef(str).startswith(
"#1/")) {
163 ar_name_len = strtoul(str.c_str() + 3, &err, 10);
166 const size_t last_pos = str.find_last_not_of(
' ');
167 if (last_pos != std::string::npos) {
168 if (last_pos + 1 < 16)
169 str.erase(last_pos + 1);
171 ar_name.SetCString(str.c_str());
174 str.assign((
const char *)data.
GetData(&offset, 12), 12);
175 modification_time = strtoul(str.c_str(), &err, 10);
177 str.assign((
const char *)data.
GetData(&offset, 6), 6);
178 uid = strtoul(str.c_str(), &err, 10);
180 str.assign((
const char *)data.
GetData(&offset, 6), 6);
181 gid = strtoul(str.c_str(), &err, 10);
183 str.assign((
const char *)data.
GetData(&offset, 8), 8);
184 mode = strtoul(str.c_str(), &err, 8);
186 str.assign((
const char *)data.
GetData(&offset, 10), 10);
187 size = strtoul(str.c_str(), &err, 10);
189 str.assign((
const char *)data.
GetData(&offset, 2), 2);
191 if (ar_name_len > 0) {
192 const void *ar_name_ptr = data.
GetData(&offset, ar_name_len);
194 if (ar_name_ptr ==
nullptr)
196 str.assign((
const char *)ar_name_ptr, ar_name_len);
197 ar_name.SetCString(str.c_str());
199 file_offset = offset;
200 file_size = size - ar_name_len;
207 const llvm::sys::TimePoint<> &time,
211 : m_arch(arch), m_modification_time(time), m_file_offset(file_offset),
220 str.assign((
const char *)data.
GetData(&offset, SARMAG), SARMAG);
224 offset = obj.
Extract(data, offset);
227 size_t obj_idx = m_objects.size();
228 m_objects.push_back(obj);
230 m_object_name_to_index_map.Append(obj.
ar_name, obj_idx);
236 m_object_name_to_index_map.Sort();
237 }
else if (str == ThinArchiveMagic) {
244 return m_objects.size();
245 obj_idx = m_objects.size();
246 m_objects.push_back(obj);
248 m_object_name_to_index_map.Append(obj.
ar_name, obj_idx);
255 return m_objects.size();
256 obj_idx = m_objects.size();
257 m_objects.push_back(obj);
259 m_object_name_to_index_map.Append(obj.
ar_name, obj_idx);
261 llvm::StringRef strtab((
const char *)data.
GetData(&offset, obj.
size),
270 obj_idx = m_objects.size();
271 m_objects.push_back(obj);
273 m_object_name_to_index_map.Append(obj.
ar_name, obj_idx);
278 m_object_name_to_index_map.Sort();
280 return m_objects.size();
285 ConstString object_name,
const llvm::sys::TimePoint<> &object_mod_time) {
286 const ObjectNameToIndexMap::Entry *match =
287 m_object_name_to_index_map.FindFirstValueForName(object_name);
290 if (object_mod_time == llvm::sys::TimePoint<>())
291 return &m_objects[match->value];
293 const uint64_t object_modification_date = llvm::sys::toTimeT(object_mod_time);
294 if (m_objects[match->value].modification_time == object_modification_date)
295 return &m_objects[match->value];
297 const ObjectNameToIndexMap::Entry *next_match =
298 m_object_name_to_index_map.FindNextValueForName(match);
300 if (m_objects[next_match->value].modification_time ==
301 object_modification_date)
302 return &m_objects[next_match->value];
303 next_match = m_object_name_to_index_map.FindNextValueForName(next_match);
316 Archive::Map::iterator pos = archive_map.find(file);
319 while (pos != archive_map.end() && pos->first == file) {
322 !pos->second->GetArchitecture().IsCompatibleMatch(arch))
325 pos->second->GetFileOffset() != file_offset)
328 if (pos->second->GetModificationTime() == time) {
338 archive_map.erase(pos);
339 pos = archive_map.find(file);
355 new Archive(arch, time, file_offset, data, archive_type));
357 const size_t num_objects = archive_sp->ParseObjects();
358 if (num_objects > 0) {
359 std::lock_guard<std::recursive_mutex> guard(
372 return g_archive_map;
375std::recursive_mutex &
377 static std::recursive_mutex g_archive_map_mutex;
378 return g_archive_map_mutex;
392 const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
395 ConstString object_name(module_sp->GetObjectName());
404 data.
SetData(data_sp, data_offset, length);
406 if (file && data_sp && archive_type != ArchiveType::Invalid) {
408 "ObjectContainerBSDArchive::CreateInstance (module = %s, file = "
409 "%p, file_offset = 0x%8.8" PRIx64
", file_size = 0x%8.8" PRIx64
")",
410 module_sp->GetFileSpec().GetPath().c_str(),
411 static_cast<const void *
>(file),
static_cast<uint64_t
>(file_offset),
412 static_cast<uint64_t
>(length));
417 DataBufferSP archive_data_sp =
419 if (!archive_data_sp)
425 *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(),
427 std::unique_ptr<ObjectContainerBSDArchive> container_up(
429 archive_data_offset, file, file_offset,
430 length, archive_type));
435 container_up->SetArchive(archive_sp);
436 return container_up.release();
437 }
else if (container_up->ParseHeader())
438 return container_up.release();
444 *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(),
447 std::unique_ptr<ObjectContainerBSDArchive> container_up(
450 archive_sp->GetArchiveType()));
454 container_up->SetArchive(archive_sp);
455 return container_up.release();
465 const char *armag = (
const char *)data.
PeekData(offset,
sizeof(ar_hdr));
466 if (armag ==
nullptr)
467 return ArchiveType::Invalid;
468 if (::strncmp(armag, ARMAG, SARMAG) == 0) {
469 armag += offsetof(
struct ar_hdr, ar_fmag) + SARMAG;
470 if (strncmp(armag, ARFMAG, 2) == 0)
471 return ArchiveType::Archive;
472 }
else if (::strncmp(armag, ThinArchiveMagic, strlen(ThinArchiveMagic)) ==
474 armag += offsetof(
struct ar_hdr, ar_fmag) + strlen(ThinArchiveMagic);
475 if (strncmp(armag, ARFMAG, 2) == 0) {
476 return ArchiveType::ThinArchive;
479 return ArchiveType::Invalid;
483 const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
486 :
ObjectContainer(module_sp, file, file_offset, size, data_sp, data_offset),
503 m_file, module_sp->GetArchitecture(),
516 llvm::SmallString<128> FullPath;
517 if (llvm::sys::path::is_absolute(childPath)) {
518 FullPath = childPath;
521 llvm::sys::path::append(FullPath, childPath);
532 module_sp->GetObjectName(), module_sp->GetObjectModificationTime());
540 std::shared_ptr<DataBuffer> child_data_sp =
543 if (child_data_sp->GetByteSize() != object->
file_size)
544 return ObjectFileSP();
548 object->
file_size, child_data_sp, data_offset);
553 m_archive_sp->GetData().GetSharedDataBuffer(), data_offset);
557 return ObjectFileSP();
569 data.
SetData(data_sp, data_offset, data_sp->GetByteSize());
571 if (!file || !data_sp || archive_type == ArchiveType::Invalid)
574 const size_t initial_count = specs.
GetSize();
578 bool set_archive_arch =
false;
580 set_archive_arch =
true;
584 data.
SetData(data_sp, 0, data_sp->GetByteSize());
586 file,
ArchSpec(), file_mod_time, file_offset, data, archive_type);
591 const size_t num_objects = archive_sp->GetNumObjects();
592 for (
size_t idx = 0; idx < num_objects; ++idx) {
593 const Object *
object = archive_sp->GetObjectAtIndex(idx);
595 if (archive_sp->GetArchiveType() == ArchiveType::ThinArchive) {
604 llvm::sys::TimePoint<> object_mod_time(
614 file_offset +
object->file_offset;
615 if (object->
file_offset < file_size && file_size > object_file_offset) {
617 file, object_file_offset, file_size - object_file_offset,
621 llvm::sys::TimePoint<> object_mod_time(
632 const size_t end_count = specs.
GetSize();
633 size_t num_specs_added = end_count - initial_count;
634 if (set_archive_arch && num_specs_added > 0) {
637 for (
size_t i = initial_count; i < end_count; ++i) {
647 return num_specs_added;
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.
uint16_t mode
Object octal file permissions in the archive.
uint32_t size
Object size in bytes in the archive.
uint16_t gid
Object group id 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 Extract(const lldb_private::DataExtractor &data, lldb::offset_t offset)
lldb::offset_t ExtractFromThin(const lldb_private::DataExtractor &data, lldb::offset_t offset, llvm::StringRef stringTable)
uint16_t uid
Object user id 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.