llvm.org GIT mirror llvm / 7a6e343
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 Rafael Espindola 4 years ago
4 changed file(s) with 39 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
9393 /// \return the size in the archive header for this member.
9494 uint64_t getRawSize() const;
9595
96 StringRef getBuffer() const {
97 return StringRef(Data.data() + StartOfFile, getSize());
98 }
96 ErrorOr getBuffer() const;
9997 uint64_t getChildOffset() const;
10098
10199 ErrorOr getMemoryBufferRef() const;
207205
208206 bool hasSymbolTable() const;
209207 child_iterator getSymbolTableChild() const { return SymbolTable; }
210 StringRef getSymbolTable() const { return SymbolTable->getBuffer(); }
208 StringRef getSymbolTable() const {
209 // We know that the symbol table is not an external file,
210 // so we just assert there is no error.
211 return *SymbolTable->getBuffer();
212 }
211213 uint32_t getNumberOfSymbols() const;
212214
213215 private:
216218 child_iterator FirstRegular;
217219 unsigned Format : 2;
218220 unsigned IsThin : 1;
221 mutable std::vector> ThinBuffers;
219222 };
220223
221224 }
1616 #include "llvm/ADT/Twine.h"
1717 #include "llvm/Support/Endian.h"
1818 #include "llvm/Support/MemoryBuffer.h"
19 #include "llvm/Support/Path.h"
1920
2021 using namespace llvm;
2122 using namespace object;
112113
113114 uint64_t Archive::Child::getRawSize() const {
114115 return getHeader()->getSize();
116 }
117
118 ErrorOr Archive::Child::getBuffer() const {
119 if (!Parent->IsThin)
120 return StringRef(Data.data() + StartOfFile, getSize());
121 ErrorOr Name = getName();
122 if (std::error_code EC = Name.getError())
123 return EC;
124 SmallString<128> FullName =
125 Parent->getMemoryBufferRef().getBufferIdentifier();
126 sys::path::remove_filename(FullName);
127 sys::path::append(FullName, *Name);
128 ErrorOr> Buf = MemoryBuffer::getFile(FullName);
129 if (std::error_code EC = Buf.getError())
130 return EC;
131 Parent->ThinBuffers.push_back(std::move(*Buf));
132 return Parent->ThinBuffers.back()->getBuffer();
115133 }
116134
117135 Archive::Child Archive::Child::getNext() const {
185203 if (std::error_code EC = NameOrErr.getError())
186204 return EC;
187205 StringRef Name = NameOrErr.get();
188 return MemoryBufferRef(getBuffer(), Name);
206 ErrorOr Buf = getBuffer();
207 if (std::error_code EC = Buf.getError())
208 return EC;
209 return MemoryBufferRef(*Buf, Name);
189210 }
190211
191212 ErrorOr>
4747
4848 RUN: not llvm-ar x %p/Inputs/thin.a foo.o 2>&1 | FileCheck %s --check-prefix=THINEXTRACT
4949 THINEXTRACT: extracting from a thin archive is not supported
50
51 RUN: llvm-ar p %p/Inputs/thin.a evenlen | FileCheck %s --check-prefix=EVENLEN
52 EVENLEN: evenlen
53
54 RUN: not llvm-ar p %p/Inputs/thin-path.a t/test2.o | FileCheck %s --check-prefix=MISSING
55 MISSING: No such file or directory.
298298 if (Verbose)
299299 outs() << "Printing " << Name << "\n";
300300
301 StringRef Data = C.getBuffer();
301 ErrorOr DataOrErr = C.getBuffer();
302 failIfError(DataOrErr.getError());
303 StringRef Data = *DataOrErr;
302304 outs().write(Data.data(), Data.size());
303305 }
304306
354356 raw_fd_ostream file(FD, false);
355357
356358 // Get the data and its length
357 StringRef Data = C.getBuffer();
359 StringRef Data = *C.getBuffer();
358360
359361 // Write the data.
360362 file.write(Data.data(), Data.size());