1//===- Archive.cpp - ar File Format implementation --------------*- 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 defines the ArchiveObjectFile class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Object/Archive.h"
15#include "llvm/ADT/APInt.h"
16#include "llvm/Support/Endian.h"
17#include "llvm/Support/MemoryBuffer.h"
18
19using namespace llvm;
20using namespace object;
21
22static const char *Magic = "!<arch>\n";
23
24namespace {
25struct ArchiveMemberHeader {
26  char Name[16];
27  char LastModified[12];
28  char UID[6];
29  char GID[6];
30  char AccessMode[8];
31  char Size[10]; ///< Size of data, not including header or padding.
32  char Terminator[2];
33
34  ///! Get the name without looking up long names.
35  StringRef getName() const {
36    char EndCond;
37    if (Name[0] == '/' || Name[0] == '#')
38      EndCond = ' ';
39    else
40      EndCond = '/';
41    StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond);
42    if (end == StringRef::npos)
43      end = sizeof(Name);
44    assert(end <= sizeof(Name) && end > 0);
45    // Don't include the EndCond if there is one.
46    return StringRef(Name, end);
47  }
48
49  uint64_t getSize() const {
50    APInt ret;
51    StringRef(Size, sizeof(Size)).getAsInteger(10, ret);
52    return ret.getZExtValue();
53  }
54};
55}
56
57static const ArchiveMemberHeader *ToHeader(const char *base) {
58  return reinterpret_cast<const ArchiveMemberHeader *>(base);
59}
60
61
62static bool isInternalMember(const ArchiveMemberHeader &amh) {
63  static const char *const internals[] = {
64    "/",
65    "//",
66    "#_LLVM_SYM_TAB_#"
67  };
68
69  StringRef name = amh.getName();
70  for (std::size_t i = 0; i < sizeof(internals) / sizeof(*internals); ++i) {
71    if (name == internals[i])
72      return true;
73  }
74  return false;
75}
76
77void Archive::anchor() { }
78
79Archive::Child Archive::Child::getNext() const {
80  size_t SpaceToSkip = sizeof(ArchiveMemberHeader) +
81    ToHeader(Data.data())->getSize();
82  // If it's odd, add 1 to make it even.
83  if (SpaceToSkip & 1)
84    ++SpaceToSkip;
85
86  const char *NextLoc = Data.data() + SpaceToSkip;
87
88  // Check to see if this is past the end of the archive.
89  if (NextLoc >= Parent->Data->getBufferEnd())
90    return Child(Parent, StringRef(0, 0));
91
92  size_t NextSize = sizeof(ArchiveMemberHeader) +
93    ToHeader(NextLoc)->getSize();
94
95  return Child(Parent, StringRef(NextLoc, NextSize));
96}
97
98error_code Archive::Child::getName(StringRef &Result) const {
99  StringRef name = ToHeader(Data.data())->getName();
100  // Check if it's a special name.
101  if (name[0] == '/') {
102    if (name.size() == 1) { // Linker member.
103      Result = name;
104      return object_error::success;
105    }
106    if (name.size() == 2 && name[1] == '/') { // String table.
107      Result = name;
108      return object_error::success;
109    }
110    // It's a long name.
111    // Get the offset.
112    APInt offset;
113    name.substr(1).getAsInteger(10, offset);
114    const char *addr = Parent->StringTable->Data.begin()
115                       + sizeof(ArchiveMemberHeader)
116                       + offset.getZExtValue();
117    // Verify it.
118    if (Parent->StringTable == Parent->end_children()
119        || addr < (Parent->StringTable->Data.begin()
120                   + sizeof(ArchiveMemberHeader))
121        || addr > (Parent->StringTable->Data.begin()
122                   + sizeof(ArchiveMemberHeader)
123                   + Parent->StringTable->getSize()))
124      return object_error::parse_failed;
125    Result = addr;
126    return object_error::success;
127  } else if (name.startswith("#1/")) {
128    APInt name_size;
129    name.substr(3).getAsInteger(10, name_size);
130    Result = Data.substr(0, name_size.getZExtValue());
131    return object_error::success;
132  }
133  // It's a simple name.
134  if (name[name.size() - 1] == '/')
135    Result = name.substr(0, name.size() - 1);
136  else
137    Result = name;
138  return object_error::success;
139}
140
141uint64_t Archive::Child::getSize() const {
142  uint64_t size = ToHeader(Data.data())->getSize();
143  // Don't include attached name.
144  StringRef name =  ToHeader(Data.data())->getName();
145  if (name.startswith("#1/")) {
146    APInt name_size;
147    name.substr(3).getAsInteger(10, name_size);
148    size -= name_size.getZExtValue();
149  }
150  return size;
151}
152
153MemoryBuffer *Archive::Child::getBuffer() const {
154  StringRef name;
155  if (getName(name)) return NULL;
156  int size = sizeof(ArchiveMemberHeader);
157  if (name.startswith("#1/")) {
158    APInt name_size;
159    name.substr(3).getAsInteger(10, name_size);
160    size += name_size.getZExtValue();
161  }
162  return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()),
163                                    name,
164                                    false);
165}
166
167error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
168  OwningPtr<Binary> ret;
169  if (error_code ec =
170    createBinary(getBuffer(), ret))
171    return ec;
172  Result.swap(ret);
173  return object_error::success;
174}
175
176Archive::Archive(MemoryBuffer *source, error_code &ec)
177  : Binary(Binary::ID_Archive, source) {
178  // Check for sufficient magic.
179  if (!source || source->getBufferSize()
180                 < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive.
181              || StringRef(source->getBufferStart(), 8) != Magic) {
182    ec = object_error::invalid_file_type;
183    return;
184  }
185
186  // Get the special members.
187  child_iterator i = begin_children(false);
188  child_iterator e = end_children();
189
190  if (i != e) ++i; // Nobody cares about the first member.
191  if (i != e) {
192    SymbolTable = i;
193    ++i;
194  }
195  if (i != e) {
196    StringTable = i;
197  }
198
199  ec = object_error::success;
200}
201
202Archive::child_iterator Archive::begin_children(bool skip_internal) const {
203  const char *Loc = Data->getBufferStart() + strlen(Magic);
204  size_t Size = sizeof(ArchiveMemberHeader) +
205    ToHeader(Loc)->getSize();
206  Child c(this, StringRef(Loc, Size));
207  // Skip internals at the beginning of an archive.
208  if (skip_internal && isInternalMember(*ToHeader(Loc)))
209    return c.getNext();
210  return c;
211}
212
213Archive::child_iterator Archive::end_children() const {
214  return Child(this, StringRef(0, 0));
215}
216
217error_code Archive::Symbol::getName(StringRef &Result) const {
218  Result =
219    StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex);
220  return object_error::success;
221}
222
223error_code Archive::Symbol::getMember(child_iterator &Result) const {
224  const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
225  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
226  const char *offsets = buf + 4;
227  buf += 4 + (member_count * 4); // Skip offsets.
228  const char *indicies = buf + 4;
229
230  uint16_t offsetindex =
231    *(reinterpret_cast<const support::ulittle16_t*>(indicies)
232      + SymbolIndex);
233
234  uint32_t offset = *(reinterpret_cast<const support::ulittle32_t*>(offsets)
235                      + (offsetindex - 1));
236
237  const char *Loc = Parent->getData().begin() + offset;
238  size_t Size = sizeof(ArchiveMemberHeader) +
239    ToHeader(Loc)->getSize();
240  Result = Child(Parent, StringRef(Loc, Size));
241
242  return object_error::success;
243}
244
245Archive::Symbol Archive::Symbol::getNext() const {
246  Symbol t(*this);
247  // Go to one past next null.
248  t.StringIndex =
249    Parent->SymbolTable->getBuffer()->getBuffer().find('\0', t.StringIndex) + 1;
250  ++t.SymbolIndex;
251  return t;
252}
253
254Archive::symbol_iterator Archive::begin_symbols() const {
255  const char *buf = SymbolTable->getBuffer()->getBufferStart();
256  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
257  buf += 4 + (member_count * 4); // Skip offsets.
258  uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
259  buf += 4 + (symbol_count * 2); // Skip indices.
260  uint32_t string_start_offset =
261    buf - SymbolTable->getBuffer()->getBufferStart();
262  return symbol_iterator(Symbol(this, 0, string_start_offset));
263}
264
265Archive::symbol_iterator Archive::end_symbols() const {
266  const char *buf = SymbolTable->getBuffer()->getBufferStart();
267  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
268  buf += 4 + (member_count * 4); // Skip offsets.
269  uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
270  return symbol_iterator(
271    Symbol(this, symbol_count, 0));
272}
273