23 using namespace object;
24 using namespace llvm::support::endian;
26 static const char *
const Magic =
"!<arch>\n";
29 void Archive::anchor() { }
33 if (
Name[0] ==
'/' ||
Name[0] ==
'#')
41 assert(end <=
sizeof(
Name) && end > 0);
48 if (
llvm::StringRef(Size,
sizeof(Size)).rtrim(
" ").getAsInteger(10, Ret))
62 if (
StringRef(LastModified,
sizeof(LastModified)).rtrim(
" ")
63 .getAsInteger(10, Seconds))
73 if (
StringRef(UID,
sizeof(UID)).rtrim(
" ").getAsInteger(10, Ret))
80 if (
StringRef(GID,
sizeof(GID)).rtrim(
" ").getAsInteger(10, Ret))
93 if (!Parent->IsThin || Header->
getName() ==
"/" || Header->
getName() ==
"//")
111 return getHeader()->getSize();
112 return Data.size() - StartOfFile;
116 return getHeader()->getSize();
123 if (std::error_code EC = Name.getError())
126 Parent->getMemoryBufferRef().getBufferIdentifier();
130 if (std::error_code EC = Buf.
getError())
132 Parent->ThinBuffers.push_back(std::move(*Buf));
133 return Parent->ThinBuffers.back()->getBuffer();
137 size_t SpaceToSkip =
Data.size();
142 const char *NextLoc =
Data.data() + SpaceToSkip;
145 if (NextLoc >= Parent->Data.getBufferEnd())
146 return Child(Parent,
nullptr);
148 return Child(Parent, NextLoc);
152 const char *a = Parent->Data.getBuffer().data();
153 const char *c =
Data.data();
154 uint64_t offset = c - a;
161 if (name[0] ==
'/') {
162 if (name.
size() == 1)
164 if (name.
size() == 2 && name[1] ==
'/')
171 const char *
addr = Parent->StringTable->Data.begin()
175 if (Parent->StringTable == Parent->child_end()
176 || addr < (Parent->StringTable->Data.begin()
178 || addr > (Parent->StringTable->Data.begin()
180 + Parent->StringTable->getSize()))
197 if (name[name.
size() - 1] ==
'/')
204 if (std::error_code EC = NameOrErr.
getError())
208 if (std::error_code EC = Buf.
getError())
216 if (std::error_code EC = BuffOrErr.
getError())
224 std::unique_ptr<Archive>
Ret(
new Archive(Source, EC));
227 return std::move(Ret);
249 ec = std::error_code();
274 if (Name ==
"__.SYMDEF") {
279 ec = std::error_code();
290 Name = NameOrErr.
get();
291 if (Name ==
"__.SYMDEF SORTED" || Name ==
"__.SYMDEF") {
304 bool has64SymTable =
false;
305 if (Name ==
"/" || Name ==
"/SYM64/") {
307 if (Name ==
"/SYM64/")
308 has64SymTable =
true;
312 ec = std::error_code();
323 ec = std::error_code();
327 if (Name[0] !=
'/') {
330 ec = std::error_code();
345 ec = std::error_code();
357 ec = std::error_code();
373 return Child(
this,
nullptr);
381 const char *Buf = Parent->getSymbolTable().begin();
384 Offsets +=
sizeof(uint64_t);
386 Offsets +=
sizeof(uint32_t);
388 if (Parent->kind() ==
K_GNU) {
389 Offset =
read32be(Offsets + SymbolIndex * 4);
390 }
else if (Parent->kind() ==
K_MIPS64) {
391 Offset =
read64be(Offsets + SymbolIndex * 8);
392 }
else if (Parent->kind() ==
K_BSD) {
399 Offset =
read32le(Offsets + SymbolIndex * 8 + 4);
402 uint32_t MemberCount =
read32le(Buf);
403 Buf += MemberCount * 4 + 4;
405 uint32_t SymbolCount =
read32le(Buf);
406 if (SymbolIndex >= SymbolCount)
410 const char *Indices = Buf + 4;
414 uint16_t OffsetIndex =
read16le(Indices + SymbolIndex * 2);
418 if (OffsetIndex >= MemberCount)
421 Offset =
read32le(Offsets + OffsetIndex * 4);
424 const char *Loc = Parent->getData().begin() + Offset;
431 if (Parent->kind() ==
K_BSD) {
445 const char *Buf = Parent->getSymbolTable().begin();
446 uint32_t RanlibCount = 0;
451 if (t.SymbolIndex + 1 < RanlibCount) {
452 const char *Ranlibs = Buf + 4;
453 uint32_t CurRanStrx = 0;
454 uint32_t NextRanStrx = 0;
455 CurRanStrx =
read32le(Ranlibs + t.SymbolIndex * 8);
456 NextRanStrx =
read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
457 t.StringIndex -= CurRanStrx;
458 t.StringIndex += NextRanStrx;
462 t.StringIndex = Parent->getSymbolTable().find(
'\0', t.StringIndex) + 1;
474 uint32_t symbol_count = 0;
476 buf +=
sizeof(uint32_t) + (symbol_count * (
sizeof(uint32_t)));
478 uint64_t symbol_count =
read64be(buf);
479 buf +=
sizeof(uint64_t) + (symbol_count * (
sizeof(uint64_t)));
487 uint32_t ranlib_count = 0;
489 const char *ranlibs = buf + 4;
490 uint32_t ran_strx = 0;
492 buf +=
sizeof(uint32_t) + (ranlib_count * (2 * (
sizeof(uint32_t))));
494 buf +=
sizeof(uint32_t);
497 uint32_t member_count = 0;
498 uint32_t symbol_count = 0;
500 buf += 4 + (member_count * 4);
502 buf += 4 + (symbol_count * 2);
522 uint32_t member_count = 0;
524 buf += 4 + (member_count * 4);
532 for (; bs != es; ++bs) {
534 if (SymName == name) {
539 return ResultOrErr.
get();
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
const_iterator end(StringRef path)
Get end iterator over path.
std::error_code getError() const
Represents either an error or a value T.
Archive(MemoryBufferRef Source, std::error_code &EC)
symbol_iterator symbol_end() const
size_t size() const
size - Get the string size.
static const char *const ThinMagic
ErrorOr< std::unique_ptr< Binary > > getAsBinary(LLVMContext *Context=nullptr) const
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
uint64_t getRawSize() const
uint64_t getChildOffset() const
child_iterator child_begin(bool SkipInternal=true) const
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
const char * getBufferStart() const
StringRef getSymbolTable() const
uint64_t read64be(const void *p)
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
StringRef rtrim(StringRef Chars=" \t\n\v\f\r") const
Return string with consecutive characters in Chars starting from the right removed.
void remove_filename(SmallVectorImpl< char > &path)
Remove the last component from path unless it is the root dir.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ErrorOr< MemoryBufferRef > getMemoryBufferRef() const
static StringRef getName(Value *V)
This file implements a class to represent arbitrary precision integral constant values and operations...
MemoryBufferRef getMemoryBufferRef() const
ErrorOr< child_iterator > getMember() const
bool hasSymbolTable() const
ErrorOr< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
uint32_t read32le(const void *p)
child_iterator child_end() const
This is an important class for using LLVM in a threaded context.
uint32_t read32be(const void *p)
StringRef getName() const
Child(const Archive *Parent, const char *Start)
child_iterator findSym(StringRef name) const
size_t getBufferSize() const
static const char *const Magic
symbol_iterator symbol_begin() const
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
StringRef getBuffer() const
void fromEpochTime(SecondsType seconds)
Converts the seconds argument from PosixTime to the corresponding TimeValue and assigns that value to...
static ErrorOr< std::unique_ptr< Archive > > create(MemoryBufferRef Source)
StringRef getRawName() const
ErrorOr< StringRef > getName() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
uint16_t read16le(const void *p)
uint32_t getNumberOfSymbols() const
This class is used where a precise fixed point in time is required.
ErrorOr< StringRef > getBuffer() const
StringRef - Represent a constant reference to a string, i.e.