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

Commit

Permalink
Start adding support for writing archives in BSD format.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
espindola committed Jul 8, 2015
1 parent 31512fe commit b13e877
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 16 deletions.
3 changes: 1 addition & 2 deletions include/llvm/Object/ArchiveWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ class NewArchiveIterator {

std::pair<StringRef, std::error_code>
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab);

bool WriteSymtab, object::Archive::Kind Kind);
}

#endif
6 changes: 4 additions & 2 deletions lib/LibDriver/LibDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,10 @@ int llvm::libDriverMain(llvm::ArrayRef<const char*> ArgsArr) {
llvm::sys::path::filename(Arg->getValue()));
}

std::pair<StringRef, std::error_code> Result = llvm::writeArchive(
getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true);
std::pair<StringRef, std::error_code> Result =
llvm::writeArchive(getOutputPath(&Args, Members[0]), Members,
/*WriteSymtab=*/true, object::Archive::K_GNU);

if (Result.second) {
if (Result.first.empty())
Result.first = ArgsArr[0];
Expand Down
40 changes: 30 additions & 10 deletions lib/Object/ArchiveWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,25 @@ static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
}

static void
printMemberHeader(raw_fd_ostream &Out, StringRef Name,
printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
StringRef Name,
std::vector<unsigned>::iterator &StringMapIndexIter,
const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
unsigned Perms, unsigned Size) {
if (Kind == object::Archive::K_BSD) {
uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
// Pad so that even 64 bit object files are aligned.
unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
unsigned NameWithPadding = Name.size() + Pad;
printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
NameWithPadding + Size);
Out << Name;
assert(PosAfterHeader == Out.tell());
while (Pad--)
Out.write(uint8_t(0));
return;
}
if (Name.size() < 16) {
printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
return;
Expand Down Expand Up @@ -160,9 +175,13 @@ static void writeStringTable(raw_fd_ostream &Out,

// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
ArrayRef<NewArchiveIterator> Members,
ArrayRef<MemoryBufferRef> Buffers,
std::vector<unsigned> &MemberOffsetRefs) {
if (Kind != object::Archive::K_GNU)
return 0;

unsigned StartOffset = 0;
unsigned MemberNum = 0;
std::string NameBuf;
Expand Down Expand Up @@ -222,7 +241,7 @@ writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab) {
bool WriteSymtab, object::Archive::Kind Kind) {
SmallString<128> TmpArchive;
int TmpArchiveFD;
if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
Expand Down Expand Up @@ -274,14 +293,15 @@ llvm::writeArchive(StringRef ArcName,
unsigned MemberReferenceOffset = 0;
if (WriteSymtab) {
ErrorOr<unsigned> MemberReferenceOffsetOrErr =
writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs);
if (auto EC = MemberReferenceOffsetOrErr.getError())
return std::make_pair(ArcName, EC);
MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
}

std::vector<unsigned> StringMapIndexes;
writeStringTable(Out, NewMembers, StringMapIndexes);
if (Kind != object::Archive::K_BSD)
writeStringTable(Out, NewMembers, StringMapIndexes);

unsigned MemberNum = 0;
unsigned NewMemberNum = 0;
Expand All @@ -296,13 +316,13 @@ llvm::writeArchive(StringRef ArcName,
if (I.isNewMember()) {
StringRef FileName = I.getNew();
const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
printMemberHeader(Out, sys::path::filename(FileName), StringMapIndexIter,
Status.getLastModificationTime(), Status.getUser(),
Status.getGroup(), Status.permissions(),
Status.getSize());
printMemberHeader(Out, Kind, sys::path::filename(FileName),
StringMapIndexIter, Status.getLastModificationTime(),
Status.getUser(), Status.getGroup(),
Status.permissions(), Status.getSize());
} else {
object::Archive::child_iterator OldMember = I.getOld();
printMemberHeader(Out, I.getName(), StringMapIndexIter,
printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter,
OldMember->getLastModified(), OldMember->getUID(),
OldMember->getGID(), OldMember->getAccessMode(),
OldMember->getSize());
Expand Down
10 changes: 10 additions & 0 deletions test/Object/archive-format.test
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ CHECK-NEXT: 0123456789abcdef/
CHECK-NEXT: 0123456789abcde/{{................................}}4 `
CHECK-NEXT: bar./0 {{................................}}4 `
CHECK-NEXT: zed.

RUN: rm -f test-bsd.a
RUN: llvm-ar --format=bsd rc test-bsd.a 0123456789abcde 0123456789abcdef
RUN: cat test-bsd.a | FileCheck -strict-whitespace --check-prefix=BSD %s

BSD: !<arch>
BSD-NEXT: #1/20 {{..............................}} 24 `
BSD-NEXT: 0123456789abcde{{.....}}bar.
BSD-SAME: #1/16 {{..............................}} 20 `
BSD-NEXT: 0123456789abcdefzed.
26 changes: 24 additions & 2 deletions tools/llvm-ar/llvm-ar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ static cl::list<std::string>

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

namespace {
enum Format { Default, GNU, BSD };
}

static cl::opt<Format>
FormatOpt("format", cl::desc("Archive format to create"),
cl::values(clEnumValN(Default, "defalut", "default"),
clEnumValN(GNU, "gnu", "gnu"),
clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd));

std::string Options;

// Provide additional help output explaining the operations and modifiers of
Expand Down Expand Up @@ -539,15 +549,27 @@ computeNewArchiveMembers(ArchiveOperation Operation,
static void
performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
std::vector<NewArchiveIterator> *NewMembersP) {
object::Archive::Kind Kind;
switch (FormatOpt) {
case Default:
// FIXME: change as the support for other formats improve.
Kind = object::Archive::K_GNU;
case GNU:
Kind = object::Archive::K_GNU;
break;
case BSD:
Kind = object::Archive::K_BSD;
break;
}
if (NewMembersP) {
std::pair<StringRef, std::error_code> Result =
writeArchive(ArchiveName, *NewMembersP, Symtab);
writeArchive(ArchiveName, *NewMembersP, Symtab, Kind);
failIfError(Result.second, Result.first);
return;
}
std::vector<NewArchiveIterator> NewMembers =
computeNewArchiveMembers(Operation, OldArchive);
auto Result = writeArchive(ArchiveName, NewMembers, Symtab);
auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind);
failIfError(Result.second, Result.first);
}

Expand Down

0 comments on commit b13e877

Please sign in to comment.