llvm.org GIT mirror llvm / b13e877
Start adding support for writing archives in BSD format. No support for the symbol table yet (but will hopefully add it today). We always use the long filename format so that we can align the member, which is an advantage of the BSD format. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241721 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 4 years ago
5 changed file(s) with 69 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
4343
4444 std::pair
4545 writeArchive(StringRef ArcName, std::vector &NewMembers,
46 bool WriteSymtab);
47
46 bool WriteSymtab, object::Archive::Kind Kind);
4847 }
4948
5049 #endif
138138 llvm::sys::path::filename(Arg->getValue()));
139139 }
140140
141 std::pair Result = llvm::writeArchive(
142 getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true);
141 std::pair Result =
142 llvm::writeArchive(getOutputPath(&Args, Members[0]), Members,
143 /*WriteSymtab=*/true, object::Archive::K_GNU);
144
143145 if (Result.second) {
144146 if (Result.first.empty())
145147 Result.first = ArgsArr[0];
116116 }
117117
118118 static void
119 printMemberHeader(raw_fd_ostream &Out, StringRef Name,
119 printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
120 StringRef Name,
120121 std::vector::iterator &StringMapIndexIter,
121122 const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
122123 unsigned Perms, unsigned Size) {
124 if (Kind == object::Archive::K_BSD) {
125 uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
126 // Pad so that even 64 bit object files are aligned.
127 unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
128 unsigned NameWithPadding = Name.size() + Pad;
129 printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
130 printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
131 NameWithPadding + Size);
132 Out << Name;
133 assert(PosAfterHeader == Out.tell());
134 while (Pad--)
135 Out.write(uint8_t(0));
136 return;
137 }
123138 if (Name.size() < 16) {
124139 printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
125140 return;
159174
160175 // Returns the offset of the first reference to a member offset.
161176 static ErrorOr
162 writeSymbolTable(raw_fd_ostream &Out, ArrayRef Members,
177 writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
178 ArrayRef Members,
163179 ArrayRef Buffers,
164180 std::vector &MemberOffsetRefs) {
181 if (Kind != object::Archive::K_GNU)
182 return 0;
183
165184 unsigned StartOffset = 0;
166185 unsigned MemberNum = 0;
167186 std::string NameBuf;
221240 std::pair
222241 llvm::writeArchive(StringRef ArcName,
223242 std::vector &NewMembers,
224 bool WriteSymtab) {
243 bool WriteSymtab, object::Archive::Kind Kind) {
225244 SmallString<128> TmpArchive;
226245 int TmpArchiveFD;
227246 if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
273292 unsigned MemberReferenceOffset = 0;
274293 if (WriteSymtab) {
275294 ErrorOr MemberReferenceOffsetOrErr =
276 writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
295 writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs);
277296 if (auto EC = MemberReferenceOffsetOrErr.getError())
278297 return std::make_pair(ArcName, EC);
279298 MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
280299 }
281300
282301 std::vector StringMapIndexes;
283 writeStringTable(Out, NewMembers, StringMapIndexes);
302 if (Kind != object::Archive::K_BSD)
303 writeStringTable(Out, NewMembers, StringMapIndexes);
284304
285305 unsigned MemberNum = 0;
286306 unsigned NewMemberNum = 0;
295315 if (I.isNewMember()) {
296316 StringRef FileName = I.getNew();
297317 const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
298 printMemberHeader(Out, sys::path::filename(FileName), StringMapIndexIter,
299 Status.getLastModificationTime(), Status.getUser(),
300 Status.getGroup(), Status.permissions(),
301 Status.getSize());
318 printMemberHeader(Out, Kind, sys::path::filename(FileName),
319 StringMapIndexIter, Status.getLastModificationTime(),
320 Status.getUser(), Status.getGroup(),
321 Status.permissions(), Status.getSize());
302322 } else {
303323 object::Archive::child_iterator OldMember = I.getOld();
304 printMemberHeader(Out, I.getName(), StringMapIndexIter,
324 printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter,
305325 OldMember->getLastModified(), OldMember->getUID(),
306326 OldMember->getGID(), OldMember->getAccessMode(),
307327 OldMember->getSize());
1616 CHECK-NEXT: 0123456789abcde/{{................................}}4 `
1717 CHECK-NEXT: bar./0 {{................................}}4 `
1818 CHECK-NEXT: zed.
19
20 RUN: rm -f test-bsd.a
21 RUN: llvm-ar --format=bsd rc test-bsd.a 0123456789abcde 0123456789abcdef
22 RUN: cat test-bsd.a | FileCheck -strict-whitespace --check-prefix=BSD %s
23
24 BSD: !
25 BSD-NEXT: #1/20 {{..............................}} 24 `
26 BSD-NEXT: 0123456789abcde{{.....}}bar.
27 BSD-SAME: #1/16 {{..............................}} 20 `
28 BSD-NEXT: 0123456789abcdefzed.
6868 cl::desc("[relpos] [count] [members]..."));
6969
7070 static cl::opt MRI("M", cl::desc(""));
71
72 namespace {
73 enum Format { Default, GNU, BSD };
74 }
75
76 static cl::opt
77 FormatOpt("format", cl::desc("Archive format to create"),
78 cl::values(clEnumValN(Default, "defalut", "default"),
79 clEnumValN(GNU, "gnu", "gnu"),
80 clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd));
7181
7282 std::string Options;
7383
538548 static void
539549 performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
540550 std::vector *NewMembersP) {
551 object::Archive::Kind Kind;
552 switch (FormatOpt) {
553 case Default:
554 // FIXME: change as the support for other formats improve.
555 Kind = object::Archive::K_GNU;
556 case GNU:
557 Kind = object::Archive::K_GNU;
558 break;
559 case BSD:
560 Kind = object::Archive::K_BSD;
561 break;
562 }
541563 if (NewMembersP) {
542564 std::pair Result =
543 writeArchive(ArchiveName, *NewMembersP, Symtab);
565 writeArchive(ArchiveName, *NewMembersP, Symtab, Kind);
544566 failIfError(Result.second, Result.first);
545567 return;
546568 }
547569 std::vector NewMembers =
548570 computeNewArchiveMembers(Operation, OldArchive);
549 auto Result = writeArchive(ArchiveName, NewMembers, Symtab);
571 auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind);
550572 failIfError(Result.second, Result.first);
551573 }
552574