diff options
author | Michael J. Spencer <bigcheesegs@gmail.com> | 2011-10-25 22:30:42 +0000 |
---|---|---|
committer | Michael J. Spencer <bigcheesegs@gmail.com> | 2011-10-25 22:30:42 +0000 |
commit | aaf98ead114bcd51cd2479badfe28b8d0e4895c2 (patch) | |
tree | aa3e3bf5d30473497596d45f797467ed47c3c4ed /lib/Object | |
parent | c8aa726ec22a362bf9fe0d81fdcf68a48bfc999f (diff) | |
download | external_llvm-aaf98ead114bcd51cd2479badfe28b8d0e4895c2.zip external_llvm-aaf98ead114bcd51cd2479badfe28b8d0e4895c2.tar.gz external_llvm-aaf98ead114bcd51cd2479badfe28b8d0e4895c2.tar.bz2 |
Object/Archive: Add BSD style long file name support and skip internal members.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142981 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/Archive.cpp | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index e2eaff5..348b753 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -32,7 +32,11 @@ struct ArchiveMemberHeader { ///! Get the name without looking up long names. StringRef getName() const { - char EndCond = Name[0] == '/' ? ' ' : '/'; + char EndCond; + if (Name[0] == '/' || Name[0] == '#') + EndCond = ' '; + else + EndCond = '/'; StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond); if (end == StringRef::npos) end = sizeof(Name); @@ -53,6 +57,21 @@ const ArchiveMemberHeader *ToHeader(const char *base) { } } +static bool isInternalMember(const ArchiveMemberHeader &amh) { + const char *internals[] = { + "/", + "//", + "#_LLVM_SYM_TAB_#" + }; + + StringRef name = amh.getName(); + for (std::size_t i = 0; i < sizeof(internals) / sizeof(*internals); ++i) { + if (name == internals[i]) + return true; + } + return false; +} + Archive::Child Archive::Child::getNext() const { size_t SpaceToSkip = sizeof(ArchiveMemberHeader) + ToHeader(Data.data())->getSize(); @@ -101,6 +120,11 @@ error_code Archive::Child::getName(StringRef &Result) const { return object_error::parse_failed; Result = addr; return object_error::success; + } else if (name.startswith("#1/")) { + APInt name_size; + name.substr(3).getAsInteger(10, name_size); + Result = Data.substr(0, name_size.getZExtValue()); + return object_error::success; } // It's a simple name. if (name[name.size() - 1] == '/') @@ -111,14 +135,27 @@ error_code Archive::Child::getName(StringRef &Result) const { } uint64_t Archive::Child::getSize() const { - return ToHeader(Data.data())->getSize(); + uint64_t size = ToHeader(Data.data())->getSize(); + // Don't include attached name. + StringRef name = ToHeader(Data.data())->getName(); + if (name.startswith("#1/")) { + APInt name_size; + name.substr(3).getAsInteger(10, name_size); + size -= name_size.getZExtValue(); + } + return size; } MemoryBuffer *Archive::Child::getBuffer() const { StringRef name; if (getName(name)) return NULL; - return MemoryBuffer::getMemBuffer(Data.substr(sizeof(ArchiveMemberHeader), - getSize()), + int size = sizeof(ArchiveMemberHeader); + if (name.startswith("#1/")) { + APInt name_size; + name.substr(3).getAsInteger(10, name_size); + size += name_size.getZExtValue(); + } + return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()), name, false); } @@ -144,7 +181,7 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) } // Get the string table. It's the 3rd member. - child_iterator StrTable = begin_children(); + child_iterator StrTable = begin_children(false); child_iterator e = end_children(); for (int i = 0; StrTable != e && i < 2; ++StrTable, ++i) {} @@ -156,11 +193,15 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) ec = object_error::success; } -Archive::child_iterator Archive::begin_children() const { +Archive::child_iterator Archive::begin_children(bool skip_internal) const { const char *Loc = Data->getBufferStart() + Magic.size(); size_t Size = sizeof(ArchiveMemberHeader) + ToHeader(Loc)->getSize(); - return Child(this, StringRef(Loc, Size)); + Child c(this, StringRef(Loc, Size)); + // Skip internals at the beginning of an archive. + if (skip_internal && isInternalMember(*ToHeader(Loc))) + return c.getNext(); + return c; } Archive::child_iterator Archive::end_children() const { |