summaryrefslogtreecommitdiff
path: root/lib/Object/Archive.cpp
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2011-10-25 22:30:42 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2011-10-25 22:30:42 +0000
commitaaf98ead114bcd51cd2479badfe28b8d0e4895c2 (patch)
treeaa3e3bf5d30473497596d45f797467ed47c3c4ed /lib/Object/Archive.cpp
parentc8aa726ec22a362bf9fe0d81fdcf68a48bfc999f (diff)
downloadllvm-aaf98ead114bcd51cd2479badfe28b8d0e4895c2.tar.gz
llvm-aaf98ead114bcd51cd2479badfe28b8d0e4895c2.tar.bz2
llvm-aaf98ead114bcd51cd2479badfe28b8d0e4895c2.tar.xz
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/Archive.cpp')
-rw-r--r--lib/Object/Archive.cpp55
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp
index e2eaff53c1..348b7536e8 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 {