summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Object/Archive.h3
-rw-r--r--llvm/lib/Object/Archive.cpp43
-rw-r--r--llvm/test/Object/Inputs/macho-toc64-archive-x86_64.abin0 -> 1576 bytes
-rw-r--r--llvm/test/Object/archive-symtab.test6
4 files changed, 48 insertions, 4 deletions
diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
index 58577347230..231d56a6b5f 100644
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -183,6 +183,7 @@ public:
K_GNU,
K_MIPS64,
K_BSD,
+ K_DARWIN64,
K_COFF
};
@@ -225,7 +226,7 @@ private:
uint16_t FirstRegularStartOfFile = -1;
void setFirstRegular(const Child &C);
- unsigned Format : 2;
+ unsigned Format : 3;
unsigned IsThin : 1;
mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
};
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index 21621c189cf..15db95123ac 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -330,8 +330,11 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
// 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;
+ if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
+ if (Name == "__.SYMDEF")
+ Format = K_BSD;
+ else // Name == "__.SYMDEF_64"
+ Format = K_DARWIN64;
// We know that the symbol table is not an external file, so we just assert
// there is no error.
SymbolTable = *C->getBuffer();
@@ -358,6 +361,14 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
if (Increment())
return;
}
+ else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
+ Format = K_DARWIN64;
+ // We know that the symbol table is not an external file, so we just
+ // assert there is no error.
+ SymbolTable = *C->getBuffer();
+ if (Increment())
+ return;
+ }
setFirstRegular(*C);
return;
}
@@ -462,7 +473,7 @@ StringRef Archive::Symbol::getName() const {
ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
const char *Buf = Parent->getSymbolTable().begin();
const char *Offsets = Buf;
- if (Parent->kind() == K_MIPS64)
+ if (Parent->kind() == K_MIPS64 || Parent->kind() == K_DARWIN64)
Offsets += sizeof(uint64_t);
else
Offsets += sizeof(uint32_t);
@@ -479,6 +490,14 @@ ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
// the archive of the member that defines the symbol. Which is what
// is needed here.
Offset = read32le(Offsets + SymbolIndex * 8 + 4);
+ } else if (Parent->kind() == K_DARWIN64) {
+ // The SymbolIndex is an index into the ranlib_64 structs that start at
+ // Offsets (the first uint64_t is the number of bytes of the ranlib_64
+ // structs). The ranlib_64 structs are a pair of uint64_t's the first
+ // being a string table offset and the second being the offset into
+ // the archive of the member that defines the symbol. Which is what
+ // is needed here.
+ Offset = read64le(Offsets + SymbolIndex * 16 + 8);
} else {
// Skip offsets.
uint32_t MemberCount = read32le(Buf);
@@ -578,6 +597,22 @@ Archive::symbol_iterator Archive::symbol_begin() const {
// Skip the byte count of the string table.
buf += sizeof(uint32_t);
buf += ran_strx;
+ } else if (kind() == K_DARWIN64) {
+ // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
+ // which is the number of bytes of ranlib_64 structs that follow. The
+ // ranlib_64 structs are a pair of uint64_t's the first being a string
+ // table offset and the second being the offset into the archive of the
+ // member that define the symbol. After that the next uint64_t is the byte
+ // count of the string table followed by the string table.
+ uint64_t ranlib_count = 0;
+ ranlib_count = read64le(buf) / 16;
+ const char *ranlibs = buf + 8;
+ uint64_t ran_strx = 0;
+ ran_strx = read64le(ranlibs);
+ buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
+ // Skip the byte count of the string table.
+ buf += sizeof(uint64_t);
+ buf += ran_strx;
} else {
uint32_t member_count = 0;
uint32_t symbol_count = 0;
@@ -604,6 +639,8 @@ uint32_t Archive::getNumberOfSymbols() const {
return read64be(buf);
if (kind() == K_BSD)
return read32le(buf) / 8;
+ if (kind() == K_DARWIN64)
+ return read64le(buf) / 16;
uint32_t member_count = 0;
member_count = read32le(buf);
buf += 4 + (member_count * 4); // Skip offsets.
diff --git a/llvm/test/Object/Inputs/macho-toc64-archive-x86_64.a b/llvm/test/Object/Inputs/macho-toc64-archive-x86_64.a
new file mode 100644
index 00000000000..e73f3dce6bd
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-toc64-archive-x86_64.a
Binary files differ
diff --git a/llvm/test/Object/archive-symtab.test b/llvm/test/Object/archive-symtab.test
index 6bad783a8c8..0fcf9adf916 100644
--- a/llvm/test/Object/archive-symtab.test
+++ b/llvm/test/Object/archive-symtab.test
@@ -99,6 +99,12 @@ MACHO-NEXT: 0000000000000000 t _bar
MACHO-NEXT: 0000000000000001 T _foo
MACHO-NEXT: 0000000000000002 T _main
+RUN: llvm-nm -M %p/Inputs/macho-toc64-archive-x86_64.a | FileCheck --check-prefix=MACHO-TOC64 %s
+
+MACHO-TOC64: Archive map
+MACHO-TOC64-NEXT: _test in test.o
+MACHO-TOC64-NEXT: _test in xtest.o
+
RUN: rm -f %t.a
RUN: llvm-ar --format=gnu rcsU %t.a %p/Inputs/coff-short-import-code %p/Inputs/coff-short-import-data
RUN: llvm-nm -M %t.a | FileCheck --check-prefix=COFF-SHORT-IMPORT %s
OpenPOWER on IntegriCloud