From a55816b3fc6570eae4f3aaf2c092756ec122602a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 9 Jul 2015 15:56:23 +0000 Subject: [PATCH] Basic support for BSD symbol tables in archives. This could be optimized and for now we only produce __.SYMDEF and not "__.SYMDEF SORTED". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241814 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/ArchiveWriter.cpp | 56 +++++++++++++++++++++++---------- test/Object/archive-symtab.test | 21 +++++++++++++ 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp index ef8aaafab35..c485b34a081 100644 --- a/lib/Object/ArchiveWriter.cpp +++ b/lib/Object/ArchiveWriter.cpp @@ -184,10 +184,8 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, ArrayRef Members, ArrayRef Buffers, std::vector &MemberOffsetRefs) { - if (Kind != object::Archive::K_GNU) - return 0; - - unsigned StartOffset = 0; + unsigned HeaderStartOffset = 0; + unsigned BodyStartOffset = 0; SmallString<128> NameBuf; raw_svector_ostream NameOS(NameBuf); LLVMContext Context; @@ -200,10 +198,15 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, continue; // FIXME: check only for "not an object file" errors. object::SymbolicFile &Obj = *ObjOrErr.get(); - if (!StartOffset) { - printGNUSmallMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); - StartOffset = Out.tell(); - print32(Out, Kind, 0); + if (!HeaderStartOffset) { + HeaderStartOffset = Out.tell(); + if (Kind == object::Archive::K_GNU) + printGNUSmallMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); + else + printBSDMemberHeader(Out, "__.SYMDEF", sys::TimeValue::now(), 0, 0, 0, + 0); + BodyStartOffset = Out.tell(); + print32(Out, Kind, 0); // number of entries or bytes } for (const object::BasicSymbolRef &S : Obj.symbols()) { @@ -214,29 +217,45 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, continue; if (Symflags & object::SymbolRef::SF_Undefined) continue; + + unsigned NameOffset = NameOS.tell(); if (auto EC = S.printName(NameOS)) return EC; NameOS << '\0'; MemberOffsetRefs.push_back(MemberNum); - print32(Out, Kind, 0); + if (Kind == object::Archive::K_BSD) + print32(Out, Kind, NameOffset); + print32(Out, Kind, 0); // member offset } } - Out << NameOS.str(); - if (StartOffset == 0) + if (HeaderStartOffset == 0) return 0; + StringRef StringTable = NameOS.str(); + if (Kind == object::Archive::K_BSD) + print32(Out, Kind, StringTable.size()); // byte count of the string table + Out << StringTable; + if (Out.tell() % 2) Out << '\0'; + // Patch up the size of the symbol table now that we know how big it is. unsigned Pos = Out.tell(); - Out.seek(StartOffset - 12); - printWithSpacePadding(Out, Pos - StartOffset, 10); - Out.seek(StartOffset); + const unsigned MemberHeaderSize = 60; + Out.seek(HeaderStartOffset + 48); // offset of the size field. + printWithSpacePadding(Out, Pos - MemberHeaderSize - HeaderStartOffset, 10); + + // Patch up the number of symbols. + Out.seek(BodyStartOffset); unsigned NumSyms = MemberOffsetRefs.size(); - print32(Out, Kind, NumSyms); + if (Kind == object::Archive::K_GNU) + print32(Out, Kind, NumSyms); + else + print32(Out, Kind, NumSyms * 8); + Out.seek(Pos); - return StartOffset + 4; + return BodyStartOffset + 4; } std::pair @@ -337,8 +356,11 @@ llvm::writeArchive(StringRef ArcName, if (MemberReferenceOffset) { Out.seek(MemberReferenceOffset); - for (unsigned MemberNum : MemberOffsetRefs) + for (unsigned MemberNum : MemberOffsetRefs) { + if (Kind == object::Archive::K_BSD) + Out.seek(Out.tell() + 4); // skip over the string offset print32(Out, Kind, MemberOffset[MemberNum]); + } } Output.keep(); diff --git a/test/Object/archive-symtab.test b/test/Object/archive-symtab.test index 01f17bcc8b6..5de2f2b5e1d 100644 --- a/test/Object/archive-symtab.test +++ b/test/Object/archive-symtab.test @@ -66,3 +66,24 @@ RUN: llvm-nm -M %p/Inputs/macho-archive-unsorted-x86_64.a | FileCheck %s --check BSD-MachO: Archive map BSD-MachO: _bar in bar.o BSD-MachO: _foo in foo.o + +RUN: rm -f %t.a +RUN: llvm-ar --format=bsd rcs %t.a %p/Inputs/trivial-object-test.macho-x86-64 %p/Inputs/trivial-object-test2.macho-x86-64 +RUN: llvm-nm -M %t.a | FileCheck --check-prefix=MACHO %s + +MACHO: Archive map +MACHO-NEXT: _main in trivial-object-test.macho-x86-64 +MACHO-NEXT: _foo in trivial-object-test2.macho-x86-64 +MACHO-NEXT: _main in trivial-object-test2.macho-x86-64 +MACHO-NOT: bar + +MACHO: trivial-object-test.macho-x86-64 +MACHO-NEXT: 0000000000000028 s L_.str +MACHO-NEXT: U _SomeOtherFunction +MACHO-NEXT: 0000000000000000 T _main +MACHO-NEXT: U _puts + +MACHO: trivial-object-test2.macho-x86-64 +MACHO-NEXT: 0000000000000000 t _bar +MACHO-NEXT: 0000000000000001 T _foo +MACHO-NEXT: 0000000000000002 T _main -- 2.34.1