Index: include/llvm/Object/Archive.h =================================================================== --- include/llvm/Object/Archive.h +++ include/llvm/Object/Archive.h @@ -178,6 +178,7 @@ enum Kind { K_GNU, + K_GNU64, K_BSD, K_COFF }; Index: lib/Object/Archive.cpp =================================================================== --- lib/Object/Archive.cpp +++ lib/Object/Archive.cpp @@ -162,7 +162,7 @@ return object_error::parse_failed; // GNU long file names end with a /. - if (Parent->kind() == K_GNU) { + if (Parent->kind() == K_GNU || Parent->kind() == K_GNU64) { StringRef::size_type End = StringRef(addr).find('/'); return StringRef(addr, End); } @@ -273,8 +273,11 @@ return; } - if (Name == "/") { + bool has64SymTable = false; + if (Name == "/" || Name == "/SYM64/") { SymbolTable = i; + if (Name == "/SYM64/") + has64SymTable = true; ++i; if (i == e) { @@ -285,7 +288,7 @@ } if (Name == "//") { - Format = K_GNU; + Format = has64SymTable ? K_GNU64 : K_GNU; StringTable = i; ++i; FirstRegular = i; @@ -294,7 +297,7 @@ } if (Name[0] != '/') { - Format = K_GNU; + Format = has64SymTable ? K_GNU64 : K_GNU; FirstRegular = i; ec = object_error::success; return; @@ -348,11 +351,18 @@ ErrorOr Archive::Symbol::getMember() const { const char *Buf = Parent->SymbolTable->getBuffer().begin(); - const char *Offsets = Buf + 4; + const char *Offsets = Buf; + if (Parent->kind() == K_GNU64) + Offsets += sizeof(uint64_t); + else + Offsets += sizeof(uint32_t); uint32_t Offset = 0; if (Parent->kind() == K_GNU) { Offset = *(reinterpret_cast(Offsets) + SymbolIndex); + } else if (Parent->kind() == K_GNU64) { + Offset = + *(reinterpret_cast(Offsets) + SymbolIndex); } else if (Parent->kind() == K_BSD) { // The SymbolIndex is an index into the ranlib structs that start at // Offsets (the first uint32_t is the number of bytes of the ranlib @@ -449,6 +459,9 @@ uint32_t symbol_count = 0; symbol_count = *reinterpret_cast(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); + } else if (kind() == K_GNU64) { + uint64_t symbol_count = *reinterpret_cast(buf); + buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t))); } else if (kind() == K_BSD) { // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t // which is the number of bytes of ranlib structs that follow. The ranlib @@ -486,6 +499,8 @@ uint32_t symbol_count = 0; if (kind() == K_GNU) { symbol_count = *reinterpret_cast(buf); + } else if (kind() == K_GNU64) { + symbol_count = *reinterpret_cast(buf); } else if (kind() == K_BSD) { symbol_count = (*reinterpret_cast(buf)) / (sizeof(uint32_t) * 2); Index: test/Object/nm-irix6.test =================================================================== --- /dev/null +++ test/Object/nm-irix6.test @@ -0,0 +1,27 @@ +# Check reading IRIX 6.0 64-bit archive file. +RUN: llvm-nm %p/Inputs/archive-test.a-irix6-mips64el | FileCheck %s + +CHECK: f1.o: +CHECK-NEXT: 00000028 T f1 +CHECK-NEXT: 00000000 d s_d +CHECK-NEXT: 00000000 t s_foo + +CHECK: f2.o: +CHECK-NEXT: 00000028 T f2 +CHECK-NEXT: 00000000 d s_d +CHECK-NEXT: 00000000 t s_foo + +CHECK: f3.o: +CHECK-NEXT: 00000028 T f3 +CHECK-NEXT: 00000000 d s_d +CHECK-NEXT: 00000000 t s_foo + +CHECK: f4.o: +CHECK-NEXT: 00000028 T f4 +CHECK-NEXT: 00000000 d s_d +CHECK-NEXT: 00000000 t s_foo + +CHECK: f5.o: +CHECK-NEXT: 00000028 T f5 +CHECK-NEXT: 00000000 d s_d +CHECK-NEXT: 00000000 t s_foo