Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit b13e877

Browse files
committed
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
1 parent 31512fe commit b13e877

File tree

5 files changed

+69
-16
lines changed

5 files changed

+69
-16
lines changed

include/llvm/Object/ArchiveWriter.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ class NewArchiveIterator {
4444

4545
std::pair<StringRef, std::error_code>
4646
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
47-
bool WriteSymtab);
48-
47+
bool WriteSymtab, object::Archive::Kind Kind);
4948
}
5049

5150
#endif

lib/LibDriver/LibDriver.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,10 @@ int llvm::libDriverMain(llvm::ArrayRef<const char*> ArgsArr) {
139139
llvm::sys::path::filename(Arg->getValue()));
140140
}
141141

142-
std::pair<StringRef, std::error_code> Result = llvm::writeArchive(
143-
getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true);
142+
std::pair<StringRef, std::error_code> Result =
143+
llvm::writeArchive(getOutputPath(&Args, Members[0]), Members,
144+
/*WriteSymtab=*/true, object::Archive::K_GNU);
145+
144146
if (Result.second) {
145147
if (Result.first.empty())
146148
Result.first = ArgsArr[0];

lib/Object/ArchiveWriter.cpp

+30-10
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,25 @@ static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
117117
}
118118

119119
static void
120-
printMemberHeader(raw_fd_ostream &Out, StringRef Name,
120+
printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
121+
StringRef Name,
121122
std::vector<unsigned>::iterator &StringMapIndexIter,
122123
const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
123124
unsigned Perms, unsigned Size) {
125+
if (Kind == object::Archive::K_BSD) {
126+
uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
127+
// Pad so that even 64 bit object files are aligned.
128+
unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
129+
unsigned NameWithPadding = Name.size() + Pad;
130+
printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
131+
printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
132+
NameWithPadding + Size);
133+
Out << Name;
134+
assert(PosAfterHeader == Out.tell());
135+
while (Pad--)
136+
Out.write(uint8_t(0));
137+
return;
138+
}
124139
if (Name.size() < 16) {
125140
printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
126141
return;
@@ -160,9 +175,13 @@ static void writeStringTable(raw_fd_ostream &Out,
160175

161176
// Returns the offset of the first reference to a member offset.
162177
static ErrorOr<unsigned>
163-
writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
178+
writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
179+
ArrayRef<NewArchiveIterator> Members,
164180
ArrayRef<MemoryBufferRef> Buffers,
165181
std::vector<unsigned> &MemberOffsetRefs) {
182+
if (Kind != object::Archive::K_GNU)
183+
return 0;
184+
166185
unsigned StartOffset = 0;
167186
unsigned MemberNum = 0;
168187
std::string NameBuf;
@@ -222,7 +241,7 @@ writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
222241
std::pair<StringRef, std::error_code>
223242
llvm::writeArchive(StringRef ArcName,
224243
std::vector<NewArchiveIterator> &NewMembers,
225-
bool WriteSymtab) {
244+
bool WriteSymtab, object::Archive::Kind Kind) {
226245
SmallString<128> TmpArchive;
227246
int TmpArchiveFD;
228247
if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
@@ -274,14 +293,15 @@ llvm::writeArchive(StringRef ArcName,
274293
unsigned MemberReferenceOffset = 0;
275294
if (WriteSymtab) {
276295
ErrorOr<unsigned> MemberReferenceOffsetOrErr =
277-
writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
296+
writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs);
278297
if (auto EC = MemberReferenceOffsetOrErr.getError())
279298
return std::make_pair(ArcName, EC);
280299
MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
281300
}
282301

283302
std::vector<unsigned> StringMapIndexes;
284-
writeStringTable(Out, NewMembers, StringMapIndexes);
303+
if (Kind != object::Archive::K_BSD)
304+
writeStringTable(Out, NewMembers, StringMapIndexes);
285305

286306
unsigned MemberNum = 0;
287307
unsigned NewMemberNum = 0;
@@ -296,13 +316,13 @@ llvm::writeArchive(StringRef ArcName,
296316
if (I.isNewMember()) {
297317
StringRef FileName = I.getNew();
298318
const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
299-
printMemberHeader(Out, sys::path::filename(FileName), StringMapIndexIter,
300-
Status.getLastModificationTime(), Status.getUser(),
301-
Status.getGroup(), Status.permissions(),
302-
Status.getSize());
319+
printMemberHeader(Out, Kind, sys::path::filename(FileName),
320+
StringMapIndexIter, Status.getLastModificationTime(),
321+
Status.getUser(), Status.getGroup(),
322+
Status.permissions(), Status.getSize());
303323
} else {
304324
object::Archive::child_iterator OldMember = I.getOld();
305-
printMemberHeader(Out, I.getName(), StringMapIndexIter,
325+
printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter,
306326
OldMember->getLastModified(), OldMember->getUID(),
307327
OldMember->getGID(), OldMember->getAccessMode(),
308328
OldMember->getSize());

test/Object/archive-format.test

+10
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@ CHECK-NEXT: 0123456789abcdef/
1717
CHECK-NEXT: 0123456789abcde/{{................................}}4 `
1818
CHECK-NEXT: bar./0 {{................................}}4 `
1919
CHECK-NEXT: zed.
20+
21+
RUN: rm -f test-bsd.a
22+
RUN: llvm-ar --format=bsd rc test-bsd.a 0123456789abcde 0123456789abcdef
23+
RUN: cat test-bsd.a | FileCheck -strict-whitespace --check-prefix=BSD %s
24+
25+
BSD: !<arch>
26+
BSD-NEXT: #1/20 {{..............................}} 24 `
27+
BSD-NEXT: 0123456789abcde{{.....}}bar.
28+
BSD-SAME: #1/16 {{..............................}} 20 `
29+
BSD-NEXT: 0123456789abcdefzed.

tools/llvm-ar/llvm-ar.cpp

+24-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ static cl::list<std::string>
7070

7171
static cl::opt<bool> MRI("M", cl::desc(""));
7272

73+
namespace {
74+
enum Format { Default, GNU, BSD };
75+
}
76+
77+
static cl::opt<Format>
78+
FormatOpt("format", cl::desc("Archive format to create"),
79+
cl::values(clEnumValN(Default, "defalut", "default"),
80+
clEnumValN(GNU, "gnu", "gnu"),
81+
clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd));
82+
7383
std::string Options;
7484

7585
// Provide additional help output explaining the operations and modifiers of
@@ -539,15 +549,27 @@ computeNewArchiveMembers(ArchiveOperation Operation,
539549
static void
540550
performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
541551
std::vector<NewArchiveIterator> *NewMembersP) {
552+
object::Archive::Kind Kind;
553+
switch (FormatOpt) {
554+
case Default:
555+
// FIXME: change as the support for other formats improve.
556+
Kind = object::Archive::K_GNU;
557+
case GNU:
558+
Kind = object::Archive::K_GNU;
559+
break;
560+
case BSD:
561+
Kind = object::Archive::K_BSD;
562+
break;
563+
}
542564
if (NewMembersP) {
543565
std::pair<StringRef, std::error_code> Result =
544-
writeArchive(ArchiveName, *NewMembersP, Symtab);
566+
writeArchive(ArchiveName, *NewMembersP, Symtab, Kind);
545567
failIfError(Result.second, Result.first);
546568
return;
547569
}
548570
std::vector<NewArchiveIterator> NewMembers =
549571
computeNewArchiveMembers(Operation, OldArchive);
550-
auto Result = writeArchive(ArchiveName, NewMembers, Symtab);
572+
auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind);
551573
failIfError(Result.second, Result.first);
552574
}
553575

0 commit comments

Comments
 (0)