OSDN Git Service

Object/Archive: Cleanup anon namespace.
[android-x86/external-llvm.git] / lib / Object / Archive.cpp
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/MemoryBuffer.h"
17
18 using namespace llvm;
19 using namespace object;
20
21 static const StringRef Magic = "!<arch>\n";
22
23 namespace {
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
33   ///! Get the name without looking up long names.
34   StringRef getName() const {
35     char EndCond;
36     if (Name[0] == '/' || Name[0] == '#')
37       EndCond = ' ';
38     else
39       EndCond = '/';
40     StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond);
41     if (end == 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 StringRef(Name, end);
46   }
47
48   uint64_t getSize() const {
49     APInt ret;
50     StringRef(Size, sizeof(Size)).getAsInteger(10, ret);
51     return ret.getZExtValue();
52   }
53 };
54 }
55
56 static const ArchiveMemberHeader *ToHeader(const char *base) {
57   return reinterpret_cast<const ArchiveMemberHeader *>(base);
58 }
59
60
61 static bool isInternalMember(const ArchiveMemberHeader &amh) {
62   const char *internals[] = {
63     "/",
64     "//",
65     "#_LLVM_SYM_TAB_#"
66     };
67
68   StringRef name = amh.getName();
69   for (std::size_t i = 0; i < sizeof(internals) / sizeof(*internals); ++i) {
70     if (name == internals[i])
71       return true;
72   }
73   return false;
74 }
75
76 Archive::Child Archive::Child::getNext() const {
77   size_t SpaceToSkip = sizeof(ArchiveMemberHeader) +
78     ToHeader(Data.data())->getSize();
79   // If it's odd, add 1 to make it even.
80   if (SpaceToSkip & 1)
81     ++SpaceToSkip;
82
83   const char *NextLoc = Data.data() + SpaceToSkip;
84
85   // Check to see if this is past the end of the archive.
86   if (NextLoc >= Parent->Data->getBufferEnd())
87     return Child(Parent, StringRef(0, 0));
88
89   size_t NextSize = sizeof(ArchiveMemberHeader) +
90     ToHeader(NextLoc)->getSize();
91
92   return Child(Parent, StringRef(NextLoc, NextSize));
93 }
94
95 error_code Archive::Child::getName(StringRef &Result) const {
96   StringRef name = ToHeader(Data.data())->getName();
97   // Check if it's a special name.
98   if (name[0] == '/') {
99     if (name.size() == 1) { // Linker member.
100       Result = name;
101       return object_error::success;
102     }
103     if (name.size() == 2 && name[1] == '/') { // String table.
104       Result = name;
105       return object_error::success;
106     }
107     // It's a long name.
108     // Get the offset.
109     APInt offset;
110     name.substr(1).getAsInteger(10, offset);
111     const char *addr = Parent->StringTable->Data.begin()
112                        + sizeof(ArchiveMemberHeader)
113                        + offset.getZExtValue();
114     // Verify it.
115     if (Parent->StringTable == Parent->end_children()
116         || addr < (Parent->StringTable->Data.begin()
117                    + sizeof(ArchiveMemberHeader))
118         || addr > (Parent->StringTable->Data.begin()
119                    + sizeof(ArchiveMemberHeader)
120                    + Parent->StringTable->getSize()))
121       return object_error::parse_failed;
122     Result = addr;
123     return object_error::success;
124   } else if (name.startswith("#1/")) {
125     APInt name_size;
126     name.substr(3).getAsInteger(10, name_size);
127     Result = Data.substr(0, name_size.getZExtValue());
128     return object_error::success;
129   }
130   // It's a simple name.
131   if (name[name.size() - 1] == '/')
132     Result = name.substr(0, name.size() - 1);
133   else
134     Result = name;
135   return object_error::success;
136 }
137
138 uint64_t Archive::Child::getSize() const {
139   uint64_t size = ToHeader(Data.data())->getSize();
140   // Don't include attached name.
141   StringRef name =  ToHeader(Data.data())->getName();
142   if (name.startswith("#1/")) {
143     APInt name_size;
144     name.substr(3).getAsInteger(10, name_size);
145     size -= name_size.getZExtValue();
146   }
147   return size;
148 }
149
150 MemoryBuffer *Archive::Child::getBuffer() const {
151   StringRef name;
152   if (getName(name)) return NULL;
153   int size = sizeof(ArchiveMemberHeader);
154   if (name.startswith("#1/")) {
155     APInt name_size;
156     name.substr(3).getAsInteger(10, name_size);
157     size += name_size.getZExtValue();
158   }
159   return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()),
160                                     name,
161                                     false);
162 }
163
164 error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
165   OwningPtr<Binary> ret;
166   if (error_code ec =
167     createBinary(getBuffer(), ret))
168     return ec;
169   Result.swap(ret);
170   return object_error::success;
171 }
172
173 Archive::Archive(MemoryBuffer *source, error_code &ec)
174   : Binary(Binary::isArchive, source)
175   , StringTable(Child(this, StringRef(0, 0))) {
176   // Check for sufficient magic.
177   if (!source || source->getBufferSize()
178                  < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive.
179               || StringRef(source->getBufferStart(), 8) != Magic) {
180     ec = object_error::invalid_file_type;
181     return;
182   }
183
184   // Get the string table. It's the 3rd member.
185   child_iterator StrTable = begin_children(false);
186   child_iterator e = end_children();
187   for (int i = 0; StrTable != e && i < 2; ++StrTable, ++i) {}
188
189   // Check to see if there were 3 members, or the 3rd member wasn't named "//".
190   StringRef name;
191   if (StrTable != e && !StrTable->getName(name) && name == "//")
192     StringTable = StrTable;
193
194   ec = object_error::success;
195 }
196
197 Archive::child_iterator Archive::begin_children(bool skip_internal) const {
198   const char *Loc = Data->getBufferStart() + Magic.size();
199   size_t Size = sizeof(ArchiveMemberHeader) +
200     ToHeader(Loc)->getSize();
201   Child c(this, StringRef(Loc, Size));
202   // Skip internals at the beginning of an archive.
203   if (skip_internal && isInternalMember(*ToHeader(Loc)))
204     return c.getNext();
205   return c;
206 }
207
208 Archive::child_iterator Archive::end_children() const {
209   return Child(this, StringRef(0, 0));
210 }