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 i = begin_children(false);
child_iterator e = end_children(); 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; StringRef name;
if ((ec = i->getName(name))) if ((ec = i->getName(name)))
return; return;
// Below is the pattern that is used to figure out the archive format // Below is the pattern that is used to figure out the archive format
// GNU 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) // Second member : // (may exist, if it exists, points to the string table)
// Note : The string table is used if the filename exceeds 15 characters // Note : The string table is used if the filename exceeds 15 characters
// BSD archive format // 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 // 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 // seem to create the third member if there's no member whose filename
// exceeds 15 characters. So the third member is optional. // exceeds 15 characters. So the third member is optional.
if (name == "__.SYMDEF") {
Format = K_BSD;
SymbolTable = i;
ec = object_error::success;
return;
}
if (name == "/") { if (name == "/") {
SymbolTable = i; SymbolTable = i;
StringTable = e;
if (i != e) ++i; ++i;
if (i == e) { if (i == e) {
ec = object_error::parse_failed; ec = object_error::parse_failed;
return; return;
} }
if ((ec = i->getName(name))) if ((ec = i->getName(name)))
return; return;
if (name[0] != '/') { }
Format = K_GNU;
} else if ((name.size() > 1) && (name == "//")) { if (name == "//") {
Format = K_GNU; Format = K_GNU;
StringTable = i; StringTable = i;
++i; ec = object_error::success;
} else { return;
Format = K_COFF; }
if (i != e) {
SymbolTable = i; if (name[0] != '/') {
++i; Format = K_GNU;
} ec = object_error::success;
if (i != e) { return;
if ((ec = i->getName(name))) }
return;
if (name == "//") if (name != "/") {
StringTable = i; ec = object_error::parse_failed;
} return;
} }
} else if (name == "__.SYMDEF") {
Format = K_BSD; Format = K_COFF;
SymbolTable = i; SymbolTable = i;
StringTable = e;
} ++i;
if (i == e) {
ec = object_error::success;
return;
}
if ((ec = i->getName(name)))
return;
if (name == "//")
StringTable = i;
ec = object_error::success; 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: llvm-nm %p/Inputs/archive-test.a-coff-i386 \
RUN: | FileCheck %s -check-prefix COFF RUN: | FileCheck %s -check-prefix COFF
RUN: llvm-as %p/Inputs/trivial.ll -o=%t1 RUN: llvm-as %p/Inputs/trivial.ll -o=%t1
RUN: rm -f %t2 RUN: rm -f %t2
RUN: llvm-ar rcs %t2 %t1 RUN: llvm-ar rcs %t2 %t1
RUN: llvm-nm %t2 | FileCheck %s -check-prefix BITCODE 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: trivial-object-test.coff-i386:
COFF-NEXT: 00000000 d .data COFF-NEXT: 00000000 d .data