Add support for gnu archives with a string table and no symtab.

While there, use early returns to reduce nesting.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185547 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2013-07-03 15:57:14 +00:00
parent 40d40dd44e
commit 09a7f6016a
3 changed files with 60 additions and 27 deletions

View File

@ -114,13 +114,19 @@ Archive::Archive(MemoryBuffer *source, error_code &ec)
child_iterator i = begin_children(false);
child_iterator e = end_children();
if (i == e) {
ec = object_error::parse_failed;
return;
}
// FIXME: this function should be able to use raw names.
StringRef name;
if ((ec = i->getName(name)))
return;
// Below is the pattern that is used to figure out the archive format
// GNU archive format
// First member : / (points to the symbol table )
// First member : / (may exist, if it exists, points to the symbol table )
// Second member : // (may exist, if it exists, points to the string table)
// Note : The string table is used if the filename exceeds 15 characters
// BSD archive format
@ -136,40 +142,59 @@ Archive::Archive(MemoryBuffer *source, error_code &ec)
// even if the string table is empty. However, lib.exe does not in fact
// seem to create the third member if there's no member whose filename
// exceeds 15 characters. So the third member is optional.
if (name == "__.SYMDEF") {
Format = K_BSD;
SymbolTable = i;
ec = object_error::success;
return;
}
if (name == "/") {
SymbolTable = i;
StringTable = e;
if (i != e) ++i;
++i;
if (i == e) {
ec = object_error::parse_failed;
return;
}
if ((ec = i->getName(name)))
return;
if (name[0] != '/') {
Format = K_GNU;
} else if ((name.size() > 1) && (name == "//")) {
Format = K_GNU;
StringTable = i;
++i;
} else {
Format = K_COFF;
if (i != e) {
SymbolTable = i;
++i;
}
if (i != e) {
if ((ec = i->getName(name)))
return;
if (name == "//")
StringTable = i;
}
}
} else if (name == "__.SYMDEF") {
Format = K_BSD;
SymbolTable = i;
StringTable = e;
}
}
if (name == "//") {
Format = K_GNU;
StringTable = i;
ec = object_error::success;
return;
}
if (name[0] != '/') {
Format = K_GNU;
ec = object_error::success;
return;
}
if (name != "/") {
ec = object_error::parse_failed;
return;
}
Format = K_COFF;
SymbolTable = i;
++i;
if (i == e) {
ec = object_error::success;
return;
}
if ((ec = i->getName(name)))
return;
if (name == "//")
StringTable = i;
ec = object_error::success;
}

View File

@ -0,0 +1,5 @@
!<arch>
// 24 `
a-very-long-file-name/
/0 1372864788 1000 1000 100664 0 `

View File

@ -1,10 +1,13 @@
RUN: llvm-nm %p/Inputs/archive-test.a-coff-i386 \
RUN: | FileCheck %s -check-prefix COFF
RUN: llvm-as %p/Inputs/trivial.ll -o=%t1
RUN: rm -f %t2
RUN: llvm-ar rcs %t2 %t1
RUN: llvm-nm %t2 | FileCheck %s -check-prefix BITCODE
Test we don't error with an archive with no symtab.
RUN: llvm-nm %p/Inputs/archive-test.a-gnu-no-symtab
COFF: trivial-object-test.coff-i386:
COFF-NEXT: 00000000 d .data