Don't crash in 'llvm -s' when an archive has no symtab.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 10 Jul 2013 20:14:22 +0000 (20:14 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 10 Jul 2013 20:14:22 +0000 (20:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186029 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Object/Archive.cpp
test/Object/nm-archive.test
tools/llvm-nm/llvm-nm.cpp

index 292d50a17633a2f2c1da64a920f00a23b34f6e02..91cc4efde22d4ffb8a6a16442b38690b02409d8d 100644 (file)
@@ -210,7 +210,7 @@ error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
 }
 
 Archive::Archive(MemoryBuffer *source, error_code &ec)
-  : Binary(Binary::ID_Archive, source) {
+  : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) {
   // Check for sufficient magic.
   if (!source || source->getBufferSize()
                  < (8 + sizeof(ArchiveMemberHeader)) // Smallest archive.
@@ -375,6 +375,9 @@ Archive::Symbol Archive::Symbol::getNext() const {
 }
 
 Archive::symbol_iterator Archive::begin_symbols() const {
+  if (SymbolTable == end_children())
+    return symbol_iterator(Symbol(this, 0, 0));
+
   const char *buf = SymbolTable->getBuffer().begin();
   if (kind() == K_GNU) {
     uint32_t symbol_count = 0;
@@ -395,6 +398,9 @@ Archive::symbol_iterator Archive::begin_symbols() const {
 }
 
 Archive::symbol_iterator Archive::end_symbols() const {
+  if (SymbolTable == end_children())
+    return symbol_iterator(Symbol(this, 0, 0));
+
   const char *buf = SymbolTable->getBuffer().begin();
   uint32_t symbol_count = 0;
   if (kind() == K_GNU) {
index 922983c887fbee5f4b43c080430d64f577764b07..99efc1bec67d16f16fd63814291023bd33775db6 100644 (file)
@@ -1,25 +1,32 @@
 RUN: llvm-nm %p/Inputs/archive-test.a-coff-i386 \
 RUN:         | FileCheck %s -check-prefix COFF
 
+COFF: trivial-object-test.coff-i386:
+COFF-NEXT: 00000000 d .data
+COFF-NEXT: 00000000 t .text
+COFF-NEXT: 00000000 d L_.str
+COFF-NEXT:          U _SomeOtherFunction
+COFF-NEXT: 00000000 T _main
+COFF-NEXT:          U _puts
+
+
 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
 
+BITCODE:          U SomeOtherFunction
+BITCODE-NEXT:          T main
+BITCODE-NEXT:          U puts
+
+
 Test we don't error with an archive with no symtab.
 RUN: llvm-nm %p/Inputs/archive-test.a-gnu-no-symtab
 
+
 Or in an archive with no symtab or string table.
 RUN: llvm-nm %p/Inputs/archive-test.a-gnu-minimal
 
-COFF: trivial-object-test.coff-i386:
-COFF-NEXT: 00000000 d .data
-COFF-NEXT: 00000000 t .text
-COFF-NEXT: 00000000 d L_.str
-COFF-NEXT:          U _SomeOtherFunction
-COFF-NEXT: 00000000 T _main
-COFF-NEXT:          U _puts
 
-BITCODE:          U SomeOtherFunction
-BITCODE-NEXT:          T main
-BITCODE-NEXT:          U puts
+And don't crash when asked to print a non existing symtab.
+RUN: llvm-nm -s %p/Inputs/archive-test.a-gnu-minimal
index c33289bd875c76727b131cf3f8beb730c92253d9..01dd1c33fdcadcfb4ff9647276ad76e61f52dbda 100644 (file)
@@ -365,21 +365,24 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
 
     if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
       if (ArchiveMap) {
-        outs() << "Archive map" << "\n";
-        for (object::Archive::symbol_iterator i = a->begin_symbols(), 
-             e = a->end_symbols(); i != e; ++i) {
-          object::Archive::child_iterator c;
-          StringRef symname;
-          StringRef filename;
-          if (error(i->getMember(c))) 
+        object::Archive::symbol_iterator I = a->begin_symbols();
+        object::Archive::symbol_iterator E = a->end_symbols();
+        if (I !=E) {
+          outs() << "Archive map" << "\n";
+          for (; I != E; ++I) {
+            object::Archive::child_iterator c;
+            StringRef symname;
+            StringRef filename;
+            if (error(I->getMember(c)))
               return;
-          if (error(i->getName(symname)))
+            if (error(I->getName(symname)))
               return;
-          if (error(c->getName(filename)))
+            if (error(c->getName(filename)))
               return;
-          outs() << symname << " in " << filename << "\n";
+            outs() << symname << " in " << filename << "\n";
+          }
+          outs() << "\n";
         }
-        outs() << "\n";
       }
 
       for (object::Archive::child_iterator i = a->begin_children(),