Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
6.5 KiB

  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/SmallString.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/ADT/Twine.h"
  18. #include "llvm/Object/Binary.h"
  19. #include "llvm/Support/DataTypes.h"
  20. #include "llvm/Support/ErrorHandling.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. char EndCond;
  35. if (Name[0] == '/' || Name[0] == '#')
  36. EndCond = ' ';
  37. else
  38. EndCond = '/';
  39. llvm::StringRef::size_type end =
  40. llvm::StringRef(Name, sizeof(Name)).find(EndCond);
  41. if (end == llvm::StringRef::npos)
  42. end = sizeof(Name);
  43. assert(end <= sizeof(Name) && end > 0);
  44. // Don't include the EndCond if there is one.
  45. return llvm::StringRef(Name, end);
  46. }
  47. uint64_t getSize() const {
  48. uint64_t ret;
  49. if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret))
  50. llvm_unreachable("Size is not an integer.");
  51. return ret;
  52. }
  53. };
  54. static const ArchiveMemberHeader *ToHeader(const char *base) {
  55. return reinterpret_cast<const ArchiveMemberHeader *>(base);
  56. }
  57. class Archive : public Binary {
  58. virtual void anchor();
  59. public:
  60. class Child {
  61. const Archive *Parent;
  62. /// \brief Includes header but not padding byte.
  63. StringRef Data;
  64. /// \brief Offset from Data to the start of the file.
  65. uint16_t StartOfFile;
  66. public:
  67. Child(const Archive *p, StringRef d) : Parent(p), Data(d) {
  68. if (!p || d.empty())
  69. return;
  70. // Setup StartOfFile and PaddingBytes.
  71. StartOfFile = sizeof(ArchiveMemberHeader);
  72. // Don't include attached name.
  73. StringRef Name = ToHeader(Data.data())->getName();
  74. if (Name.startswith("#1/")) {
  75. uint64_t NameSize;
  76. if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize))
  77. llvm_unreachable("Long name length is not an integer");
  78. StartOfFile += NameSize;
  79. }
  80. }
  81. bool operator ==(const Child &other) const {
  82. return (Parent == other.Parent) && (Data.begin() == other.Data.begin());
  83. }
  84. bool operator <(const Child &other) const {
  85. return Data.begin() < other.Data.begin();
  86. }
  87. Child getNext() const {
  88. size_t SpaceToSkip = Data.size();
  89. // If it's odd, add 1 to make it even.
  90. if (SpaceToSkip & 1)
  91. ++SpaceToSkip;
  92. const char *NextLoc = Data.data() + SpaceToSkip;
  93. // Check to see if this is past the end of the archive.
  94. if (NextLoc >= Parent->Data->getBufferEnd())
  95. return Child(Parent, StringRef(0, 0));
  96. size_t NextSize =
  97. sizeof(ArchiveMemberHeader) + ToHeader(NextLoc)->getSize();
  98. return Child(Parent, StringRef(NextLoc, NextSize));
  99. }
  100. error_code getName(StringRef &Result) const;
  101. int getLastModified() const;
  102. int getUID() const;
  103. int getGID() const;
  104. int getAccessMode() const;
  105. /// \return the size of the archive member without the header or padding.
  106. uint64_t getSize() const { return Data.size() - StartOfFile; }
  107. StringRef getBuffer() const {
  108. return StringRef(Data.data() + StartOfFile, getSize());
  109. }
  110. error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result,
  111. bool FullPath = false) const {
  112. StringRef Name;
  113. if (error_code ec = getName(Name))
  114. return ec;
  115. SmallString<128> Path;
  116. Result.reset(MemoryBuffer::getMemBuffer(
  117. getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name +
  118. ")").toStringRef(Path) : Name, false));
  119. return error_code::success();
  120. }
  121. error_code getAsBinary(OwningPtr<Binary> &Result) const;
  122. };
  123. class child_iterator {
  124. Child child;
  125. public:
  126. child_iterator() : child(Child(0, StringRef())) {}
  127. child_iterator(const Child &c) : child(c) {}
  128. const Child* operator->() const {
  129. return &child;
  130. }
  131. bool operator==(const child_iterator &other) const {
  132. return child == other.child;
  133. }
  134. bool operator!=(const child_iterator &other) const {
  135. return !(*this == other);
  136. }
  137. bool operator <(const child_iterator &other) const {
  138. return child < other.child;
  139. }
  140. child_iterator& operator++() { // Preincrement
  141. child = child.getNext();
  142. return *this;
  143. }
  144. };
  145. class Symbol {
  146. const Archive *Parent;
  147. uint32_t SymbolIndex;
  148. uint32_t StringIndex; // Extra index to the string.
  149. public:
  150. bool operator ==(const Symbol &other) const {
  151. return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
  152. }
  153. Symbol(const Archive *p, uint32_t symi, uint32_t stri)
  154. : Parent(p)
  155. , SymbolIndex(symi)
  156. , StringIndex(stri) {}
  157. error_code getName(StringRef &Result) const;
  158. error_code getMember(child_iterator &Result) const;
  159. Symbol getNext() const;
  160. };
  161. class symbol_iterator {
  162. Symbol symbol;
  163. public:
  164. symbol_iterator(const Symbol &s) : symbol(s) {}
  165. const Symbol *operator->() const {
  166. return &symbol;
  167. }
  168. bool operator==(const symbol_iterator &other) const {
  169. return symbol == other.symbol;
  170. }
  171. bool operator!=(const symbol_iterator &other) const {
  172. return !(*this == other);
  173. }
  174. symbol_iterator& operator++() { // Preincrement
  175. symbol = symbol.getNext();
  176. return *this;
  177. }
  178. };
  179. Archive(MemoryBuffer *source, error_code &ec);
  180. enum Kind {
  181. K_GNU,
  182. K_BSD,
  183. K_COFF
  184. };
  185. Kind kind() const {
  186. return Format;
  187. }
  188. child_iterator begin_children(bool skip_internal = true) const;
  189. child_iterator end_children() const;
  190. symbol_iterator begin_symbols() const;
  191. symbol_iterator end_symbols() const;
  192. // Cast methods.
  193. static inline bool classof(Binary const *v) {
  194. return v->isArchive();
  195. }
  196. // check if a symbol is in the archive
  197. child_iterator findSym(StringRef name) const;
  198. private:
  199. child_iterator SymbolTable;
  200. child_iterator StringTable;
  201. Kind Format;
  202. };
  203. }
  204. }
  205. #endif