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