From 68806ff6b6a28758dafc96b9db9a6b7982fa0b2d Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Fri, 17 Jun 2016 22:16:06 +0000 Subject: [PATCH] =?utf8?q?Add=20support=20for=20Darwin=E2=80=99s=20static?= =?utf8?q?=20library=20table=20of=20contents=20with=2064-bit=20offsets=20t?= =?utf8?q?o=20the=20archive=20members.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Darwin added support in its Xcode 8.0 tools (released in the beta) for static library table of contents with 64-bit offsets to the archive members. The change is very straight forward. The table of contents member is named ___.SYMDEF_64 or "___.SYMDEF_64 SORTED" and same layout is used but with fields using 64 bit values instead of 32 bit values. rdar://26869808 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273058 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Archive.h | 3 +- lib/Object/Archive.cpp | 43 ++++++++++++++++-- .../Inputs/macho-toc64-archive-x86_64.a | Bin 0 -> 1576 bytes test/Object/archive-symtab.test | 6 +++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 test/Object/Inputs/macho-toc64-archive-x86_64.a diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 58577347230..231d56a6b5f 100644 --- a/include/llvm/Object/Archive.h +++ b/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> ThinBuffers; }; diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 21621c189cf..15db95123ac 100644 --- a/lib/Object/Archive.cpp +++ b/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::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::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/test/Object/Inputs/macho-toc64-archive-x86_64.a b/test/Object/Inputs/macho-toc64-archive-x86_64.a new file mode 100644 index 0000000000000000000000000000000000000000..e73f3dce6bd4b67b8e6e6e94c06e113731fa2612 GIT binary patch literal 1576 zcmeHGJx>Bb5Zyx}gdkE_XkxKO3vKZBzJSCSjX)^0QA{*Z_Xt9;01QGTR#ql-_R z2Ns0DRbiT*12luF!2Fn$slCIUT)rSZhmmm|5Z)0^68aM=ND`Nw>P3gCUr3oykFfL+ zfKZQ<7IxP5bUmtCU61GL-F^(EQY|I?^#1x0Va&ke3~)pr0}c*02cAJb#_E*6r#+g3 zCPSxdFbSpiIs*|YOZkJ+fa^%#AN9gIi5Og3th5^E`NVE?JFF_vr^!BMt_m6ERk~g8Psc%mICr%|(5@241 zM~JW(=L$~{q0|IGfHA-XBy@kVF60~#4QrVmQCCx&FUkUbFTrZvW+hcslk&qHyBW*& eTzF0DU5%gP-q0Zb&vDRxcxV4}44wG%IsO80F`ID! literal 0 HcmV?d00001 diff --git a/test/Object/archive-symtab.test b/test/Object/archive-symtab.test index 6bad783a8c8..0fcf9adf916 100644 --- a/test/Object/archive-symtab.test +++ b/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 -- 2.50.1