Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 7a6e343

Browse files
committed
Add support for reading members out of thin archives.
For now the Archive owns the buffers of the thin archive members. This makes for a simple API, but all the buffers are destructed only when the archive is destructed. This should be fine since we close the files after mmap so we should not hit an open file limit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242215 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d0838f8 commit 7a6e343

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

include/llvm/Object/Archive.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ class Archive : public Binary {
9494
/// \return the size in the archive header for this member.
9595
uint64_t getRawSize() const;
9696

97-
StringRef getBuffer() const {
98-
return StringRef(Data.data() + StartOfFile, getSize());
99-
}
97+
ErrorOr<StringRef> getBuffer() const;
10098
uint64_t getChildOffset() const;
10199

102100
ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
@@ -208,7 +206,11 @@ class Archive : public Binary {
208206

209207
bool hasSymbolTable() const;
210208
child_iterator getSymbolTableChild() const { return SymbolTable; }
211-
StringRef getSymbolTable() const { return SymbolTable->getBuffer(); }
209+
StringRef getSymbolTable() const {
210+
// We know that the symbol table is not an external file,
211+
// so we just assert there is no error.
212+
return *SymbolTable->getBuffer();
213+
}
212214
uint32_t getNumberOfSymbols() const;
213215

214216
private:
@@ -217,6 +219,7 @@ class Archive : public Binary {
217219
child_iterator FirstRegular;
218220
unsigned Format : 2;
219221
unsigned IsThin : 1;
222+
mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
220223
};
221224

222225
}

lib/Object/Archive.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/Twine.h"
1818
#include "llvm/Support/Endian.h"
1919
#include "llvm/Support/MemoryBuffer.h"
20+
#include "llvm/Support/Path.h"
2021

2122
using namespace llvm;
2223
using namespace object;
@@ -115,6 +116,23 @@ uint64_t Archive::Child::getRawSize() const {
115116
return getHeader()->getSize();
116117
}
117118

119+
ErrorOr<StringRef> Archive::Child::getBuffer() const {
120+
if (!Parent->IsThin)
121+
return StringRef(Data.data() + StartOfFile, getSize());
122+
ErrorOr<StringRef> Name = getName();
123+
if (std::error_code EC = Name.getError())
124+
return EC;
125+
SmallString<128> FullName =
126+
Parent->getMemoryBufferRef().getBufferIdentifier();
127+
sys::path::remove_filename(FullName);
128+
sys::path::append(FullName, *Name);
129+
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
130+
if (std::error_code EC = Buf.getError())
131+
return EC;
132+
Parent->ThinBuffers.push_back(std::move(*Buf));
133+
return Parent->ThinBuffers.back()->getBuffer();
134+
}
135+
118136
Archive::Child Archive::Child::getNext() const {
119137
size_t SpaceToSkip = Data.size();
120138
// If it's odd, add 1 to make it even.
@@ -186,7 +204,10 @@ ErrorOr<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
186204
if (std::error_code EC = NameOrErr.getError())
187205
return EC;
188206
StringRef Name = NameOrErr.get();
189-
return MemoryBufferRef(getBuffer(), Name);
207+
ErrorOr<StringRef> Buf = getBuffer();
208+
if (std::error_code EC = Buf.getError())
209+
return EC;
210+
return MemoryBufferRef(*Buf, Name);
190211
}
191212

192213
ErrorOr<std::unique_ptr<Binary>>

test/Object/archive-extract.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,9 @@ NOTFOUND: foo.o was not found
4848

4949
RUN: not llvm-ar x %p/Inputs/thin.a foo.o 2>&1 | FileCheck %s --check-prefix=THINEXTRACT
5050
THINEXTRACT: extracting from a thin archive is not supported
51+
52+
RUN: llvm-ar p %p/Inputs/thin.a evenlen | FileCheck %s --check-prefix=EVENLEN
53+
EVENLEN: evenlen
54+
55+
RUN: not llvm-ar p %p/Inputs/thin-path.a t/test2.o | FileCheck %s --check-prefix=MISSING
56+
MISSING: No such file or directory.

tools/llvm-ar/llvm-ar.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,9 @@ static void doPrint(StringRef Name, const object::Archive::Child &C) {
299299
if (Verbose)
300300
outs() << "Printing " << Name << "\n";
301301

302-
StringRef Data = C.getBuffer();
302+
ErrorOr<StringRef> DataOrErr = C.getBuffer();
303+
failIfError(DataOrErr.getError());
304+
StringRef Data = *DataOrErr;
303305
outs().write(Data.data(), Data.size());
304306
}
305307

@@ -355,7 +357,7 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
355357
raw_fd_ostream file(FD, false);
356358

357359
// Get the data and its length
358-
StringRef Data = C.getBuffer();
360+
StringRef Data = *C.getBuffer();
359361

360362
// Write the data.
361363
file.write(Data.data(), Data.size());

0 commit comments

Comments
 (0)