1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

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.

llvm-svn: 241721
This commit is contained in:
Rafael Espindola 2015-07-08 20:47:32 +00:00
parent 8b999fafb7
commit 116995db75
5 changed files with 69 additions and 16 deletions

View File

@ -44,8 +44,7 @@ public:
std::pair<StringRef, std::error_code> std::pair<StringRef, std::error_code>
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers, writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab); bool WriteSymtab, object::Archive::Kind Kind);
} }
#endif #endif

View File

@ -139,8 +139,10 @@ int llvm::libDriverMain(llvm::ArrayRef<const char*> ArgsArr) {
llvm::sys::path::filename(Arg->getValue())); llvm::sys::path::filename(Arg->getValue()));
} }
std::pair<StringRef, std::error_code> Result = llvm::writeArchive( std::pair<StringRef, std::error_code> Result =
getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true); llvm::writeArchive(getOutputPath(&Args, Members[0]), Members,
/*WriteSymtab=*/true, object::Archive::K_GNU);
if (Result.second) { if (Result.second) {
if (Result.first.empty()) if (Result.first.empty())
Result.first = ArgsArr[0]; Result.first = ArgsArr[0];

View File

@ -117,10 +117,25 @@ static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
} }
static void 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, std::vector<unsigned>::iterator &StringMapIndexIter,
const sys::TimeValue &ModTime, unsigned UID, unsigned GID, const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
unsigned Perms, unsigned Size) { 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) { if (Name.size() < 16) {
printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size); printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
return; return;
@ -160,9 +175,13 @@ static void writeStringTable(raw_fd_ostream &Out,
// Returns the offset of the first reference to a member offset. // Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned> 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, ArrayRef<MemoryBufferRef> Buffers,
std::vector<unsigned> &MemberOffsetRefs) { std::vector<unsigned> &MemberOffsetRefs) {
if (Kind != object::Archive::K_GNU)
return 0;
unsigned StartOffset = 0; unsigned StartOffset = 0;
unsigned MemberNum = 0; unsigned MemberNum = 0;
std::string NameBuf; std::string NameBuf;
@ -222,7 +241,7 @@ writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
std::pair<StringRef, std::error_code> std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName, llvm::writeArchive(StringRef ArcName,
std::vector<NewArchiveIterator> &NewMembers, std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab) { bool WriteSymtab, object::Archive::Kind Kind) {
SmallString<128> TmpArchive; SmallString<128> TmpArchive;
int TmpArchiveFD; int TmpArchiveFD;
if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a", if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
@ -274,14 +293,15 @@ llvm::writeArchive(StringRef ArcName,
unsigned MemberReferenceOffset = 0; unsigned MemberReferenceOffset = 0;
if (WriteSymtab) { if (WriteSymtab) {
ErrorOr<unsigned> MemberReferenceOffsetOrErr = ErrorOr<unsigned> MemberReferenceOffsetOrErr =
writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs); writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs);
if (auto EC = MemberReferenceOffsetOrErr.getError()) if (auto EC = MemberReferenceOffsetOrErr.getError())
return std::make_pair(ArcName, EC); return std::make_pair(ArcName, EC);
MemberReferenceOffset = MemberReferenceOffsetOrErr.get(); MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
} }
std::vector<unsigned> StringMapIndexes; std::vector<unsigned> StringMapIndexes;
writeStringTable(Out, NewMembers, StringMapIndexes); if (Kind != object::Archive::K_BSD)
writeStringTable(Out, NewMembers, StringMapIndexes);
unsigned MemberNum = 0; unsigned MemberNum = 0;
unsigned NewMemberNum = 0; unsigned NewMemberNum = 0;
@ -296,13 +316,13 @@ llvm::writeArchive(StringRef ArcName,
if (I.isNewMember()) { if (I.isNewMember()) {
StringRef FileName = I.getNew(); StringRef FileName = I.getNew();
const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++]; const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
printMemberHeader(Out, sys::path::filename(FileName), StringMapIndexIter, printMemberHeader(Out, Kind, sys::path::filename(FileName),
Status.getLastModificationTime(), Status.getUser(), StringMapIndexIter, Status.getLastModificationTime(),
Status.getGroup(), Status.permissions(), Status.getUser(), Status.getGroup(),
Status.getSize()); Status.permissions(), Status.getSize());
} else { } else {
object::Archive::child_iterator OldMember = I.getOld(); object::Archive::child_iterator OldMember = I.getOld();
printMemberHeader(Out, I.getName(), StringMapIndexIter, printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter,
OldMember->getLastModified(), OldMember->getUID(), OldMember->getLastModified(), OldMember->getUID(),
OldMember->getGID(), OldMember->getAccessMode(), OldMember->getGID(), OldMember->getAccessMode(),
OldMember->getSize()); OldMember->getSize());

View File

@ -17,3 +17,13 @@ CHECK-NEXT: 0123456789abcdef/
CHECK-NEXT: 0123456789abcde/{{................................}}4 ` CHECK-NEXT: 0123456789abcde/{{................................}}4 `
CHECK-NEXT: bar./0 {{................................}}4 ` CHECK-NEXT: bar./0 {{................................}}4 `
CHECK-NEXT: zed. 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.

View File

@ -70,6 +70,16 @@ static cl::list<std::string>
static cl::opt<bool> MRI("M", cl::desc("")); 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; std::string Options;
// Provide additional help output explaining the operations and modifiers of // Provide additional help output explaining the operations and modifiers of
@ -539,15 +549,27 @@ computeNewArchiveMembers(ArchiveOperation Operation,
static void static void
performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
std::vector<NewArchiveIterator> *NewMembersP) { 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) { if (NewMembersP) {
std::pair<StringRef, std::error_code> Result = std::pair<StringRef, std::error_code> Result =
writeArchive(ArchiveName, *NewMembersP, Symtab); writeArchive(ArchiveName, *NewMembersP, Symtab, Kind);
failIfError(Result.second, Result.first); failIfError(Result.second, Result.first);
return; return;
} }
std::vector<NewArchiveIterator> NewMembers = std::vector<NewArchiveIterator> NewMembers =
computeNewArchiveMembers(Operation, OldArchive); computeNewArchiveMembers(Operation, OldArchive);
auto Result = writeArchive(ArchiveName, NewMembers, Symtab); auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind);
failIfError(Result.second, Result.first); failIfError(Result.second, Result.first);
} }