Archive.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. //===- Archive.h - ar archive file format -----------------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file declares the ar archive file format class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_OBJECT_ARCHIVE_H
  14. #define LLVM_OBJECT_ARCHIVE_H
  15. #include "llvm/ADT/StringRef.h"
  16. #include "llvm/ADT/iterator_range.h"
  17. #include "llvm/Object/Binary.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #include "llvm/Support/ErrorOr.h"
  20. #include "llvm/Support/FileSystem.h"
  21. #include "llvm/Support/MemoryBuffer.h"
  22. namespace llvm {
  23. namespace object {
  24. struct ArchiveMemberHeader {
  25. char Name[16];
  26. char LastModified[12];
  27. char UID[6];
  28. char GID[6];
  29. char AccessMode[8];
  30. char Size[10]; ///< Size of data, not including header or padding.
  31. char Terminator[2];
  32. /// Get the name without looking up long names.
  33. llvm::StringRef getName() const;
  34. /// Members are not larger than 4GB.
  35. uint32_t getSize() const;
  36. sys::fs::perms getAccessMode() const;
  37. sys::TimeValue getLastModified() const;
  38. llvm::StringRef getRawLastModified() const {
  39. return StringRef(LastModified, sizeof(LastModified)).rtrim(" ");
  40. }
  41. unsigned getUID() const;
  42. unsigned getGID() const;
  43. };
  44. class Archive : public Binary {
  45. virtual void anchor();
  46. public:
  47. class Child {
  48. const Archive *Parent;
  49. /// \brief Includes header but not padding byte.
  50. StringRef Data;
  51. /// \brief Offset from Data to the start of the file.
  52. uint16_t StartOfFile;
  53. const ArchiveMemberHeader *getHeader() const {
  54. return reinterpret_cast<const ArchiveMemberHeader *>(Data.data());
  55. }
  56. public:
  57. Child(const Archive *Parent, const char *Start);
  58. bool operator ==(const Child &other) const {
  59. assert(Parent == other.Parent);
  60. return Data.begin() == other.Data.begin();
  61. }
  62. bool operator <(const Child &other) const {
  63. return Data.begin() < other.Data.begin();
  64. }
  65. Child getNext() const;
  66. ErrorOr<StringRef> getName() const;
  67. StringRef getRawName() const { return getHeader()->getName(); }
  68. sys::TimeValue getLastModified() const {
  69. return getHeader()->getLastModified();
  70. }
  71. StringRef getRawLastModified() const {
  72. return getHeader()->getRawLastModified();
  73. }
  74. unsigned getUID() const { return getHeader()->getUID(); }
  75. unsigned getGID() const { return getHeader()->getGID(); }
  76. sys::fs::perms getAccessMode() const {
  77. return getHeader()->getAccessMode();
  78. }
  79. /// \return the size of the archive member without the header or padding.
  80. uint64_t getSize() const;
  81. /// \return the size in the archive header for this member.
  82. uint64_t getRawSize() const;
  83. ErrorOr<StringRef> getBuffer() const;
  84. uint64_t getChildOffset() const;
  85. ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
  86. ErrorOr<std::unique_ptr<Binary>>
  87. getAsBinary(LLVMContext *Context = nullptr) const;
  88. };
  89. class child_iterator {
  90. Child child;
  91. public:
  92. child_iterator() : child(Child(nullptr, nullptr)) {}
  93. child_iterator(const Child &c) : child(c) {}
  94. const Child *operator->() const { return &child; }
  95. const Child &operator*() const { return child; }
  96. bool operator==(const child_iterator &other) const {
  97. return child == other.child;
  98. }
  99. bool operator!=(const child_iterator &other) const {
  100. return !(*this == other);
  101. }
  102. bool operator<(const child_iterator &other) const {
  103. return child < other.child;
  104. }
  105. child_iterator &operator++() { // Preincrement
  106. child = child.getNext();
  107. return *this;
  108. }
  109. };
  110. class Symbol {
  111. const Archive *Parent;
  112. uint32_t SymbolIndex;
  113. uint32_t StringIndex; // Extra index to the string.
  114. public:
  115. bool operator ==(const Symbol &other) const {
  116. return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
  117. }
  118. Symbol(const Archive *p, uint32_t symi, uint32_t stri)
  119. : Parent(p)
  120. , SymbolIndex(symi)
  121. , StringIndex(stri) {}
  122. StringRef getName() const;
  123. ErrorOr<child_iterator> getMember() const;
  124. Symbol getNext() const;
  125. };
  126. class symbol_iterator {
  127. Symbol symbol;
  128. public:
  129. symbol_iterator(const Symbol &s) : symbol(s) {}
  130. const Symbol *operator->() const { return &symbol; }
  131. const Symbol &operator*() const { return symbol; }
  132. bool operator==(const symbol_iterator &other) const {
  133. return symbol == other.symbol;
  134. }
  135. bool operator!=(const symbol_iterator &other) const {
  136. return !(*this == other);
  137. }
  138. symbol_iterator& operator++() { // Preincrement
  139. symbol = symbol.getNext();
  140. return *this;
  141. }
  142. };
  143. Archive(MemoryBufferRef Source, std::error_code &EC);
  144. static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
  145. enum Kind {
  146. K_GNU,
  147. K_MIPS64,
  148. K_BSD,
  149. K_COFF
  150. };
  151. Kind kind() const { return (Kind)Format; }
  152. bool isThin() const { return IsThin; }
  153. child_iterator child_begin(bool SkipInternal = true) const;
  154. child_iterator child_end() const;
  155. iterator_range<child_iterator> children(bool SkipInternal = true) const {
  156. return iterator_range<child_iterator>(child_begin(SkipInternal),
  157. child_end());
  158. }
  159. symbol_iterator symbol_begin() const;
  160. symbol_iterator symbol_end() const;
  161. iterator_range<symbol_iterator> symbols() const {
  162. return iterator_range<symbol_iterator>(symbol_begin(), symbol_end());
  163. }
  164. // Cast methods.
  165. static inline bool classof(Binary const *v) {
  166. return v->isArchive();
  167. }
  168. // check if a symbol is in the archive
  169. child_iterator findSym(StringRef name) const;
  170. bool hasSymbolTable() const;
  171. child_iterator getSymbolTableChild() const { return SymbolTable; }
  172. StringRef getSymbolTable() const {
  173. // We know that the symbol table is not an external file,
  174. // so we just assert there is no error.
  175. return *SymbolTable->getBuffer();
  176. }
  177. uint32_t getNumberOfSymbols() const;
  178. private:
  179. child_iterator SymbolTable;
  180. child_iterator StringTable;
  181. child_iterator FirstRegular;
  182. unsigned Format : 2;
  183. unsigned IsThin : 1;
  184. mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
  185. };
  186. }
  187. }
  188. #endif