Archive.cpp revision efd2d5e1c48e9e530d2323123d28120f50dfed76
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
22fe944e8cd03701b699c07590b4ec5203928b2b11Michael J. Spencerstatic const StringRef 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];
31a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  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) {
63aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  const char *internals[] = {
64aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    "/",
65aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    "//",
66aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    "#_LLVM_SYM_TAB_#"
67aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    };
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
77a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. SpencerArchive::Child Archive::Child::getNext() const {
78a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  size_t SpaceToSkip = sizeof(ArchiveMemberHeader) +
79a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    ToHeader(Data.data())->getSize();
80a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  // If it's odd, add 1 to make it even.
81a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (SpaceToSkip & 1)
82a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    ++SpaceToSkip;
83a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
84a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  const char *NextLoc = Data.data() + SpaceToSkip;
85a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
86a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  // Check to see if this is past the end of the archive.
87a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (NextLoc >= Parent->Data->getBufferEnd())
88a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    return Child(Parent, StringRef(0, 0));
89a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
90a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  size_t NextSize = sizeof(ArchiveMemberHeader) +
91a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    ToHeader(NextLoc)->getSize();
92a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
93a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  return Child(Parent, StringRef(NextLoc, NextSize));
94a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
95a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
96a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencererror_code Archive::Child::getName(StringRef &Result) const {
97a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  StringRef name = ToHeader(Data.data())->getName();
98a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  // Check if it's a special name.
99a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (name[0] == '/') {
100a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    if (name.size() == 1) { // Linker member.
101a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      Result = name;
102a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      return object_error::success;
103a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    }
104a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    if (name.size() == 2 && name[1] == '/') { // String table.
105a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      Result = name;
106a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      return object_error::success;
107a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    }
108a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    // It's a long name.
109a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    // Get the offset.
110a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    APInt offset;
111a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    name.substr(1).getAsInteger(10, offset);
112a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    const char *addr = Parent->StringTable->Data.begin()
113a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                       + sizeof(ArchiveMemberHeader)
114a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                       + offset.getZExtValue();
115a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    // Verify it.
116a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    if (Parent->StringTable == Parent->end_children()
117a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer        || addr < (Parent->StringTable->Data.begin()
118a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                   + sizeof(ArchiveMemberHeader))
119a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer        || addr > (Parent->StringTable->Data.begin()
120a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                   + sizeof(ArchiveMemberHeader)
121a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                   + Parent->StringTable->getSize()))
122a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      return object_error::parse_failed;
123a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    Result = addr;
124a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    return object_error::success;
125aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  } else if (name.startswith("#1/")) {
126aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    APInt name_size;
127aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    name.substr(3).getAsInteger(10, name_size);
128aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    Result = Data.substr(0, name_size.getZExtValue());
129aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    return object_error::success;
130a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  }
131a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  // It's a simple name.
132a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (name[name.size() - 1] == '/')
133a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    Result = name.substr(0, name.size() - 1);
134a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  else
135a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    Result = name;
136a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  return object_error::success;
137a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
138a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
139a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spenceruint64_t Archive::Child::getSize() const {
140aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  uint64_t size = ToHeader(Data.data())->getSize();
141aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  // Don't include attached name.
142aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  StringRef name =  ToHeader(Data.data())->getName();
143aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  if (name.startswith("#1/")) {
144aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    APInt name_size;
145aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    name.substr(3).getAsInteger(10, name_size);
146aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    size -= name_size.getZExtValue();
147aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  }
148aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  return size;
149a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
150a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
151a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. SpencerMemoryBuffer *Archive::Child::getBuffer() const {
152a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  StringRef name;
153a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (getName(name)) return NULL;
154aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  int size = sizeof(ArchiveMemberHeader);
155aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  if (name.startswith("#1/")) {
156aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    APInt name_size;
157aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    name.substr(3).getAsInteger(10, name_size);
158aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    size += name_size.getZExtValue();
159aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  }
160aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()),
161a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                                    name,
162a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                                    false);
163a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
164a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
165a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencererror_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
166a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  OwningPtr<Binary> ret;
167a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (error_code ec =
168a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    createBinary(getBuffer(), ret))
169a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    return ec;
170a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  Result.swap(ret);
171a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  return object_error::success;
172a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
173a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
174a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. SpencerArchive::Archive(MemoryBuffer *source, error_code &ec)
175c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  : Binary(Binary::isArchive, source) {
176a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  // Check for sufficient magic.
177a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  if (!source || source->getBufferSize()
178a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer                 < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive.
179a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer              || StringRef(source->getBufferStart(), 8) != Magic) {
180a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    ec = object_error::invalid_file_type;
181a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    return;
182a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  }
183a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
184c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  // Get the special members.
185c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  child_iterator i = begin_children(false);
186a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  child_iterator e = end_children();
187a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
188c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  if (i != e) ++i; // Nobody cares about the first member.
189c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  if (i != e) {
190c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    SymbolTable = i;
191c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    ++i;
192c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  }
193c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  if (i != e) {
194c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    StringTable = i;
195c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  }
196a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
197a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  ec = object_error::success;
198a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
199a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
200aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. SpencerArchive::child_iterator Archive::begin_children(bool skip_internal) const {
201a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  const char *Loc = Data->getBufferStart() + Magic.size();
202a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  size_t Size = sizeof(ArchiveMemberHeader) +
203a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    ToHeader(Loc)->getSize();
204aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  Child c(this, StringRef(Loc, Size));
205aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  // Skip internals at the beginning of an archive.
206aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  if (skip_internal && isInternalMember(*ToHeader(Loc)))
207aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer    return c.getNext();
208aaf98ead114bcd51cd2479badfe28b8d0e4895c2Michael J. Spencer  return c;
209a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
210a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer
2115861893c25ee9ee6bb2991057169c0cb1e1331e0Michael J. SpencerArchive::child_iterator Archive::end_children() const {
212a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer  return Child(this, StringRef(0, 0));
213a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer}
214c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
215c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencererror_code Archive::Symbol::getName(StringRef &Result) const {
216c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  Result =
217c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex);
218c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  return object_error::success;
219c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer}
220c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
221c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencererror_code Archive::Symbol::getMember(child_iterator &Result) const {
222c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
223c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
224c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  const char *offsets = buf + 4;
225c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  buf += 4 + (member_count * 4); // Skip offsets.
226c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  const char *indicies = buf + 4;
227c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
228c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint16_t offsetindex =
229c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    *(reinterpret_cast<const support::ulittle16_t*>(indicies)
230c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer      + SymbolIndex);
231c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
232c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t offset = *(reinterpret_cast<const support::ulittle32_t*>(offsets)
233c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer                      + (offsetindex - 1));
234c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
235c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  const char *Loc = Parent->getData().begin() + offset;
236c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  size_t Size = sizeof(ArchiveMemberHeader) +
237c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    ToHeader(Loc)->getSize();
238c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  Result = Child(Parent, StringRef(Loc, Size));
239c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
240c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  return object_error::success;
241c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer}
242c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
243c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. SpencerArchive::Symbol Archive::Symbol::getNext() const {
244c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  Symbol t(*this);
245efd2d5e1c48e9e530d2323123d28120f50dfed76Benjamin Kramer  // Go to one past next null.
246efd2d5e1c48e9e530d2323123d28120f50dfed76Benjamin Kramer  t.StringIndex =
247efd2d5e1c48e9e530d2323123d28120f50dfed76Benjamin Kramer    Parent->SymbolTable->getBuffer()->getBuffer().find('\0', t.StringIndex) + 1;
248c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  ++t.SymbolIndex;
249c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  return t;
250c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer}
251c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
252c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. SpencerArchive::symbol_iterator Archive::begin_symbols() const {
253c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  const char *buf = SymbolTable->getBuffer()->getBufferStart();
254c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
255c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  buf += 4 + (member_count * 4); // Skip offsets.
256c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
257c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  buf += 4 + (symbol_count * 2); // Skip indices.
258c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t string_start_offset =
259c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    buf - SymbolTable->getBuffer()->getBufferStart();
260c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  return symbol_iterator(Symbol(this, 0, string_start_offset));
261c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer}
262c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer
263c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. SpencerArchive::symbol_iterator Archive::end_symbols() const {
264c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  const char *buf = SymbolTable->getBuffer()->getBufferStart();
265c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
266c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  buf += 4 + (member_count * 4); // Skip offsets.
267c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
268c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer  return symbol_iterator(
269c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer    Symbol(this, symbol_count, 0));
270c8a55a660e93bb7a4854969b4c5814bf7bb0101bMichael J. Spencer}
271