OSDN Git Service

[Object][Archive] Apparently StringRef::getAsInteger for APInt accepts spaces.
[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/Endian.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/MemoryBuffer.h"
19
20 using namespace llvm;
21 using namespace object;
22
23 static const char *Magic = "!<arch>\n";
24
25 namespace {
26 struct ArchiveMemberHeader {
27   char Name[16];
28   char LastModified[12];
29   char UID[6];
30   char GID[6];
31   char AccessMode[8];
32   char Size[10]; ///< Size of data, not including header or padding.
33   char Terminator[2];
34
35   ///! Get the name without looking up long names.
36   StringRef getName() const {
37     char EndCond;
38     if (Name[0] == '/' || Name[0] == '#')
39       EndCond = ' ';
40     else
41       EndCond = '/';
42     StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond);
43     if (end == StringRef::npos)
44       end = sizeof(Name);
45     assert(end <= sizeof(Name) && end > 0);
46     // Don't include the EndCond if there is one.
47     return StringRef(Name, end);
48   }
49
50   uint64_t getSize() const {
51     uint64_t ret;
52     StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret);
53     return ret;
54   }
55 };
56 }
57
58 static const ArchiveMemberHeader *ToHeader(const char *base) {
59   return reinterpret_cast<const ArchiveMemberHeader *>(base);
60 }
61
62
63 static bool isInternalMember(const ArchiveMemberHeader &amh) {
64   static const char *const internals[] = {
65     "/",
66     "//",
67     "#_LLVM_SYM_TAB_#"
68   };
69
70   StringRef name = amh.getName();
71   for (std::size_t i = 0; i < sizeof(internals) / sizeof(*internals); ++i) {
72     if (name == internals[i])
73       return true;
74   }
75   return false;
76 }
77
78 void Archive::anchor() { }
79
80 Archive::Child Archive::Child::getNext() const {
81   size_t SpaceToSkip = sizeof(ArchiveMemberHeader) +
82     ToHeader(Data.data())->getSize();
83   // If it's odd, add 1 to make it even.
84   if (SpaceToSkip & 1)
85     ++SpaceToSkip;
86
87   const char *NextLoc = Data.data() + SpaceToSkip;
88
89   // Check to see if this is past the end of the archive.
90   if (NextLoc >= Parent->Data->getBufferEnd())
91     return Child(Parent, StringRef(0, 0));
92
93   size_t NextSize = sizeof(ArchiveMemberHeader) +
94     ToHeader(NextLoc)->getSize();
95
96   return Child(Parent, StringRef(NextLoc, NextSize));
97 }
98
99 error_code Archive::Child::getName(StringRef &Result) const {
100   StringRef name = ToHeader(Data.data())->getName();
101   // Check if it's a special name.
102   if (name[0] == '/') {
103     if (name.size() == 1) { // Linker member.
104       Result = name;
105       return object_error::success;
106     }
107     if (name.size() == 2 && name[1] == '/') { // String table.
108       Result = name;
109       return object_error::success;
110     }
111     // It's a long name.
112     // Get the offset.
113     std::size_t offset;
114     name.substr(1).getAsInteger(10, offset);
115     const char *addr = Parent->StringTable->Data.begin()
116                        + sizeof(ArchiveMemberHeader)
117                        + offset;
118     // Verify it.
119     if (Parent->StringTable == Parent->end_children()
120         || addr < (Parent->StringTable->Data.begin()
121                    + sizeof(ArchiveMemberHeader))
122         || addr > (Parent->StringTable->Data.begin()
123                    + sizeof(ArchiveMemberHeader)
124                    + Parent->StringTable->getSize()))
125       return object_error::parse_failed;
126
127     // GNU long file names end with a /.
128     if (Parent->kind() == K_GNU) {
129       StringRef::size_type End = StringRef(addr).find('/');
130       Result = StringRef(addr, End);
131     } else {
132       Result = addr;
133     }
134     return object_error::success;
135   } else if (name.startswith("#1/")) {
136     uint64_t name_size;
137     name.substr(3).getAsInteger(10, name_size);
138     Result = Data.substr(0, name_size);
139     return object_error::success;
140   }
141   // It's a simple name.
142   if (name[name.size() - 1] == '/')
143     Result = name.substr(0, name.size() - 1);
144   else
145     Result = name;
146   return object_error::success;
147 }
148
149 uint64_t Archive::Child::getSize() const {
150   uint64_t size = ToHeader(Data.data())->getSize();
151   // Don't include attached name.
152   StringRef name =  ToHeader(Data.data())->getName();
153   if (name.startswith("#1/")) {
154     uint64_t name_size;
155     name.substr(3).getAsInteger(10, name_size);
156     size -= name_size;
157   }
158   return size;
159 }
160
161 MemoryBuffer *Archive::Child::getBuffer() const {
162   StringRef name;
163   if (getName(name)) return NULL;
164   int size = sizeof(ArchiveMemberHeader);
165   if (name.startswith("#1/")) {
166     uint64_t name_size;
167     name.substr(3).getAsInteger(10, name_size);
168     size += name_size;
169   }
170   return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()),
171                                     name,
172                                     false);
173 }
174
175 error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
176   OwningPtr<Binary> ret;
177   if (error_code ec =
178     createBinary(getBuffer(), ret))
179     return ec;
180   Result.swap(ret);
181   return object_error::success;
182 }
183
184 Archive::Archive(MemoryBuffer *source, error_code &ec)
185   : Binary(Binary::ID_Archive, source) {
186   // Check for sufficient magic.
187   if (!source || source->getBufferSize()
188                  < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive.
189               || StringRef(source->getBufferStart(), 8) != Magic) {
190     ec = object_error::invalid_file_type;
191     return;
192   }
193
194   // Get the special members.
195   child_iterator i = begin_children(false);
196   child_iterator e = end_children();
197
198   StringRef name;
199   if ((ec = i->getName(name)))
200     return;
201
202   // Below is the pattern that is used to figure out the archive format
203   // GNU archive format
204   //  First member : / (points to the symbol table )
205   //  Second member : // (may exist, if it exists, points to the string table)
206   //  Note : The string table is used if the filename exceeds 15 characters
207   // BSD archive format
208   //  First member : __.SYMDEF (points to the symbol table)
209   //  There is no string table, if the filename exceeds 15 characters or has a 
210   //  embedded space, the filename has #1/<size>, The size represents the size 
211   //  of the filename that needs to be read after the archive header
212   // COFF archive format
213   //  First member : /
214   //  Second member : / (provides a directory of symbols)
215   //  Third member : // contains the string table, this is present even if the
216   //                    string table is empty
217   if (name == "/") {
218     SymbolTable = i;
219     StringTable = e;
220     if (i != e) ++i;
221     if (i == e) {
222       ec = object_error::parse_failed;
223       return;
224     }
225     if ((ec = i->getName(name)))
226       return;
227     if (name[0] != '/') {
228       Format = K_GNU;
229     } else if ((name.size() > 1) && (name == "//")) { 
230       Format = K_GNU;
231       StringTable = i;
232       ++i;
233     } else  { 
234       Format = K_COFF;
235       if (i != e) {
236         SymbolTable = i;
237         ++i;
238       }
239       if (i != e) {
240         StringTable = i;
241       }
242     }
243   } else if (name == "__.SYMDEF") {
244     Format = K_BSD;
245     SymbolTable = i;
246     StringTable = e;
247   } 
248   ec = object_error::success;
249 }
250
251 Archive::child_iterator Archive::begin_children(bool skip_internal) const {
252   const char *Loc = Data->getBufferStart() + strlen(Magic);
253   size_t Size = sizeof(ArchiveMemberHeader) +
254     ToHeader(Loc)->getSize();
255   Child c(this, StringRef(Loc, Size));
256   // Skip internals at the beginning of an archive.
257   if (skip_internal && isInternalMember(*ToHeader(Loc)))
258     return c.getNext();
259   return c;
260 }
261
262 Archive::child_iterator Archive::end_children() const {
263   return Child(this, StringRef(0, 0));
264 }
265
266 error_code Archive::Symbol::getName(StringRef &Result) const {
267   Result =
268     StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex);
269   return object_error::success;
270 }
271
272 error_code Archive::Symbol::getMember(child_iterator &Result) const {
273   const char *Buf = Parent->SymbolTable->getBuffer()->getBufferStart();
274   const char *Offsets = Buf + 4;
275   uint32_t Offset = 0;
276   if (Parent->kind() == K_GNU) {
277     Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets)
278                + SymbolIndex);
279   } else if (Parent->kind() == K_BSD) {
280     llvm_unreachable("BSD format is not supported");
281   } else {
282     uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf);
283     
284     // Skip offsets.
285     Buf += sizeof(support::ulittle32_t)
286            + (MemberCount * sizeof(support::ulittle32_t));
287
288     uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf);
289
290     if (SymbolIndex >= SymbolCount)
291       return object_error::parse_failed;
292
293     // Skip SymbolCount to get to the indices table.
294     const char *Indices = Buf + sizeof(support::ulittle32_t);
295
296     // Get the index of the offset in the file member offset table for this
297     // symbol.
298     uint16_t OffsetIndex =
299       *(reinterpret_cast<const support::ulittle16_t*>(Indices)
300         + SymbolIndex);
301     // Subtract 1 since OffsetIndex is 1 based.
302     --OffsetIndex;
303
304     if (OffsetIndex >= MemberCount)
305       return object_error::parse_failed;
306
307     Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets)
308                + OffsetIndex);
309   }
310
311   const char *Loc = Parent->getData().begin() + Offset;
312   size_t Size = sizeof(ArchiveMemberHeader) +
313     ToHeader(Loc)->getSize();
314   Result = Child(Parent, StringRef(Loc, Size));
315
316   return object_error::success;
317 }
318
319 Archive::Symbol Archive::Symbol::getNext() const {
320   Symbol t(*this);
321   // Go to one past next null.
322   t.StringIndex =
323     Parent->SymbolTable->getBuffer()->getBuffer().find('\0', t.StringIndex) + 1;
324   ++t.SymbolIndex;
325   return t;
326 }
327
328 Archive::symbol_iterator Archive::begin_symbols() const {
329   const char *buf = SymbolTable->getBuffer()->getBufferStart();
330   if (kind() == K_GNU) {
331     uint32_t symbol_count = 0;
332     symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
333     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
334   } else if (kind() == K_BSD) {
335     llvm_unreachable("BSD archive format is not supported");
336   } else {
337     uint32_t member_count = 0;
338     uint32_t symbol_count = 0;
339     member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
340     buf += 4 + (member_count * 4); // Skip offsets.
341     symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
342     buf += 4 + (symbol_count * 2); // Skip indices.
343   }
344   uint32_t string_start_offset =
345     buf - SymbolTable->getBuffer()->getBufferStart();
346   return symbol_iterator(Symbol(this, 0, string_start_offset));
347 }
348
349 Archive::symbol_iterator Archive::end_symbols() const {
350   const char *buf = SymbolTable->getBuffer()->getBufferStart();
351   uint32_t symbol_count = 0;
352   if (kind() == K_GNU) {
353     symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
354     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
355   } else if (kind() == K_BSD) {
356     llvm_unreachable("BSD archive format is not supported");
357   } else {
358     uint32_t member_count = 0;
359     member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
360     buf += 4 + (member_count * 4); // Skip offsets.
361     symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
362   }
363   return symbol_iterator(
364     Symbol(this, symbol_count, 0));
365 }
366
367 Archive::child_iterator Archive::findSym(StringRef name) const {
368   Archive::symbol_iterator bs = begin_symbols();
369   Archive::symbol_iterator es = end_symbols();
370   Archive::child_iterator result;
371   
372   StringRef symname;
373   for (; bs != es; ++bs) {
374     if (bs->getName(symname))
375         return end_children();
376     if (symname == name) {
377       if (bs->getMember(result))
378         return end_children();
379       return result;
380     }
381   }
382   return end_children();
383 }