Home | History | Annotate | Download | only in Object
      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/ADT/SmallString.h"
     17 #include "llvm/ADT/Twine.h"
     18 #include "llvm/Support/Endian.h"
     19 #include "llvm/Support/MemoryBuffer.h"
     20 
     21 using namespace llvm;
     22 using namespace object;
     23 
     24 static const char *const Magic = "!<arch>\n";
     25 
     26 void Archive::anchor() { }
     27 
     28 StringRef ArchiveMemberHeader::getName() const {
     29   char EndCond;
     30   if (Name[0] == '/' || Name[0] == '#')
     31     EndCond = ' ';
     32   else
     33     EndCond = '/';
     34   llvm::StringRef::size_type end =
     35       llvm::StringRef(Name, sizeof(Name)).find(EndCond);
     36   if (end == llvm::StringRef::npos)
     37     end = sizeof(Name);
     38   assert(end <= sizeof(Name) && end > 0);
     39   // Don't include the EndCond if there is one.
     40   return llvm::StringRef(Name, end);
     41 }
     42 
     43 uint32_t ArchiveMemberHeader::getSize() const {
     44   uint32_t Ret;
     45   if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret))
     46     llvm_unreachable("Size is not a decimal number.");
     47   return Ret;
     48 }
     49 
     50 sys::fs::perms ArchiveMemberHeader::getAccessMode() const {
     51   unsigned Ret;
     52   if (StringRef(AccessMode, sizeof(AccessMode)).rtrim(" ").getAsInteger(8, Ret))
     53     llvm_unreachable("Access mode is not an octal number.");
     54   return static_cast<sys::fs::perms>(Ret);
     55 }
     56 
     57 sys::TimeValue ArchiveMemberHeader::getLastModified() const {
     58   unsigned Seconds;
     59   if (StringRef(LastModified, sizeof(LastModified)).rtrim(" ")
     60           .getAsInteger(10, Seconds))
     61     llvm_unreachable("Last modified time not a decimal number.");
     62 
     63   sys::TimeValue Ret;
     64   Ret.fromEpochTime(Seconds);
     65   return Ret;
     66 }
     67 
     68 unsigned ArchiveMemberHeader::getUID() const {
     69   unsigned Ret;
     70   if (StringRef(UID, sizeof(UID)).rtrim(" ").getAsInteger(10, Ret))
     71     llvm_unreachable("UID time not a decimal number.");
     72   return Ret;
     73 }
     74 
     75 unsigned ArchiveMemberHeader::getGID() const {
     76   unsigned Ret;
     77   if (StringRef(GID, sizeof(GID)).rtrim(" ").getAsInteger(10, Ret))
     78     llvm_unreachable("GID time not a decimal number.");
     79   return Ret;
     80 }
     81 
     82 Archive::Child::Child(const Archive *Parent, const char *Start)
     83     : Parent(Parent) {
     84   if (!Start)
     85     return;
     86 
     87   const ArchiveMemberHeader *Header =
     88       reinterpret_cast<const ArchiveMemberHeader *>(Start);
     89   Data = StringRef(Start, sizeof(ArchiveMemberHeader) + Header->getSize());
     90 
     91   // Setup StartOfFile and PaddingBytes.
     92   StartOfFile = sizeof(ArchiveMemberHeader);
     93   // Don't include attached name.
     94   StringRef Name = Header->getName();
     95   if (Name.startswith("#1/")) {
     96     uint64_t NameSize;
     97     if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize))
     98       llvm_unreachable("Long name length is not an integer");
     99     StartOfFile += NameSize;
    100   }
    101 }
    102 
    103 Archive::Child Archive::Child::getNext() const {
    104   size_t SpaceToSkip = Data.size();
    105   // If it's odd, add 1 to make it even.
    106   if (SpaceToSkip & 1)
    107     ++SpaceToSkip;
    108 
    109   const char *NextLoc = Data.data() + SpaceToSkip;
    110 
    111   // Check to see if this is past the end of the archive.
    112   if (NextLoc >= Parent->Data->getBufferEnd())
    113     return Child(Parent, NULL);
    114 
    115   return Child(Parent, NextLoc);
    116 }
    117 
    118 error_code Archive::Child::getName(StringRef &Result) const {
    119   StringRef name = getRawName();
    120   // Check if it's a special name.
    121   if (name[0] == '/') {
    122     if (name.size() == 1) { // Linker member.
    123       Result = name;
    124       return object_error::success;
    125     }
    126     if (name.size() == 2 && name[1] == '/') { // String table.
    127       Result = name;
    128       return object_error::success;
    129     }
    130     // It's a long name.
    131     // Get the offset.
    132     std::size_t offset;
    133     if (name.substr(1).rtrim(" ").getAsInteger(10, offset))
    134       llvm_unreachable("Long name offset is not an integer");
    135     const char *addr = Parent->StringTable->Data.begin()
    136                        + sizeof(ArchiveMemberHeader)
    137                        + offset;
    138     // Verify it.
    139     if (Parent->StringTable == Parent->end_children()
    140         || addr < (Parent->StringTable->Data.begin()
    141                    + sizeof(ArchiveMemberHeader))
    142         || addr > (Parent->StringTable->Data.begin()
    143                    + sizeof(ArchiveMemberHeader)
    144                    + Parent->StringTable->getSize()))
    145       return object_error::parse_failed;
    146 
    147     // GNU long file names end with a /.
    148     if (Parent->kind() == K_GNU) {
    149       StringRef::size_type End = StringRef(addr).find('/');
    150       Result = StringRef(addr, End);
    151     } else {
    152       Result = addr;
    153     }
    154     return object_error::success;
    155   } else if (name.startswith("#1/")) {
    156     uint64_t name_size;
    157     if (name.substr(3).rtrim(" ").getAsInteger(10, name_size))
    158       llvm_unreachable("Long name length is not an ingeter");
    159     Result = Data.substr(sizeof(ArchiveMemberHeader), name_size)
    160         .rtrim(StringRef("\0", 1));
    161     return object_error::success;
    162   }
    163   // It's a simple name.
    164   if (name[name.size() - 1] == '/')
    165     Result = name.substr(0, name.size() - 1);
    166   else
    167     Result = name;
    168   return object_error::success;
    169 }
    170 
    171 error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result,
    172                                            bool FullPath) const {
    173   StringRef Name;
    174   if (error_code ec = getName(Name))
    175     return ec;
    176   SmallString<128> Path;
    177   Result.reset(MemoryBuffer::getMemBuffer(
    178       getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + ")")
    179                                   .toStringRef(Path)
    180                             : Name,
    181       false));
    182   return error_code::success();
    183 }
    184 
    185 error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
    186   OwningPtr<Binary> ret;
    187   OwningPtr<MemoryBuffer> Buff;
    188   if (error_code ec = getMemoryBuffer(Buff))
    189     return ec;
    190   if (error_code ec = createBinary(Buff.take(), ret))
    191     return ec;
    192   Result.swap(ret);
    193   return object_error::success;
    194 }
    195 
    196 Archive::Archive(MemoryBuffer *source, error_code &ec)
    197   : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) {
    198   // Check for sufficient magic.
    199   assert(source);
    200   if (source->getBufferSize() < 8 ||
    201       StringRef(source->getBufferStart(), 8) != Magic) {
    202     ec = object_error::invalid_file_type;
    203     return;
    204   }
    205 
    206   // Get the special members.
    207   child_iterator i = begin_children(false);
    208   child_iterator e = end_children();
    209 
    210   if (i == e) {
    211     ec = object_error::success;
    212     return;
    213   }
    214 
    215   StringRef Name = i->getRawName();
    216 
    217   // Below is the pattern that is used to figure out the archive format
    218   // GNU archive format
    219   //  First member : / (may exist, if it exists, points to the symbol table )
    220   //  Second member : // (may exist, if it exists, points to the string table)
    221   //  Note : The string table is used if the filename exceeds 15 characters
    222   // BSD archive format
    223   //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
    224   //  There is no string table, if the filename exceeds 15 characters or has a
    225   //  embedded space, the filename has #1/<size>, The size represents the size
    226   //  of the filename that needs to be read after the archive header
    227   // COFF archive format
    228   //  First member : /
    229   //  Second member : / (provides a directory of symbols)
    230   //  Third member : // (may exist, if it exists, contains the string table)
    231   //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
    232   //  even if the string table is empty. However, lib.exe does not in fact
    233   //  seem to create the third member if there's no member whose filename
    234   //  exceeds 15 characters. So the third member is optional.
    235 
    236   if (Name == "__.SYMDEF") {
    237     Format = K_BSD;
    238     SymbolTable = i;
    239     ++i;
    240     FirstRegular = i;
    241     ec = object_error::success;
    242     return;
    243   }
    244 
    245   if (Name.startswith("#1/")) {
    246     Format = K_BSD;
    247     // We know this is BSD, so getName will work since there is no string table.
    248     ec = i->getName(Name);
    249     if (ec)
    250       return;
    251     if (Name == "__.SYMDEF SORTED") {
    252       SymbolTable = i;
    253       ++i;
    254     }
    255     FirstRegular = i;
    256     return;
    257   }
    258 
    259   if (Name == "/") {
    260     SymbolTable = i;
    261 
    262     ++i;
    263     if (i == e) {
    264       ec = object_error::parse_failed;
    265       return;
    266     }
    267     Name = i->getRawName();
    268   }
    269 
    270   if (Name == "//") {
    271     Format = K_GNU;
    272     StringTable = i;
    273     ++i;
    274     FirstRegular = i;
    275     ec = object_error::success;
    276     return;
    277   }
    278 
    279   if (Name[0] != '/') {
    280     Format = K_GNU;
    281     FirstRegular = i;
    282     ec = object_error::success;
    283     return;
    284   }
    285 
    286   if (Name != "/") {
    287     ec = object_error::parse_failed;
    288     return;
    289   }
    290 
    291   Format = K_COFF;
    292   SymbolTable = i;
    293 
    294   ++i;
    295   if (i == e) {
    296     FirstRegular = i;
    297     ec = object_error::success;
    298     return;
    299   }
    300 
    301   Name = i->getRawName();
    302 
    303   if (Name == "//") {
    304     StringTable = i;
    305     ++i;
    306   }
    307 
    308   FirstRegular = i;
    309   ec = object_error::success;
    310 }
    311 
    312 Archive::child_iterator Archive::begin_children(bool SkipInternal) const {
    313   if (Data->getBufferSize() == 8) // empty archive.
    314     return end_children();
    315 
    316   if (SkipInternal)
    317     return FirstRegular;
    318 
    319   const char *Loc = Data->getBufferStart() + strlen(Magic);
    320   Child c(this, Loc);
    321   return c;
    322 }
    323 
    324 Archive::child_iterator Archive::end_children() const {
    325   return Child(this, NULL);
    326 }
    327 
    328 error_code Archive::Symbol::getName(StringRef &Result) const {
    329   Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex);
    330   return object_error::success;
    331 }
    332 
    333 error_code Archive::Symbol::getMember(child_iterator &Result) const {
    334   const char *Buf = Parent->SymbolTable->getBuffer().begin();
    335   const char *Offsets = Buf + 4;
    336   uint32_t Offset = 0;
    337   if (Parent->kind() == K_GNU) {
    338     Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets)
    339                + SymbolIndex);
    340   } else if (Parent->kind() == K_BSD) {
    341     llvm_unreachable("BSD format is not supported");
    342   } else {
    343     uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf);
    344 
    345     // Skip offsets.
    346     Buf += sizeof(support::ulittle32_t)
    347            + (MemberCount * sizeof(support::ulittle32_t));
    348 
    349     uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf);
    350 
    351     if (SymbolIndex >= SymbolCount)
    352       return object_error::parse_failed;
    353 
    354     // Skip SymbolCount to get to the indices table.
    355     const char *Indices = Buf + sizeof(support::ulittle32_t);
    356 
    357     // Get the index of the offset in the file member offset table for this
    358     // symbol.
    359     uint16_t OffsetIndex =
    360       *(reinterpret_cast<const support::ulittle16_t*>(Indices)
    361         + SymbolIndex);
    362     // Subtract 1 since OffsetIndex is 1 based.
    363     --OffsetIndex;
    364 
    365     if (OffsetIndex >= MemberCount)
    366       return object_error::parse_failed;
    367 
    368     Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets)
    369                + OffsetIndex);
    370   }
    371 
    372   const char *Loc = Parent->getData().begin() + Offset;
    373   Result = Child(Parent, Loc);
    374 
    375   return object_error::success;
    376 }
    377 
    378 Archive::Symbol Archive::Symbol::getNext() const {
    379   Symbol t(*this);
    380   // Go to one past next null.
    381   t.StringIndex =
    382       Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1;
    383   ++t.SymbolIndex;
    384   return t;
    385 }
    386 
    387 Archive::symbol_iterator Archive::begin_symbols() const {
    388   if (!hasSymbolTable())
    389     return symbol_iterator(Symbol(this, 0, 0));
    390 
    391   const char *buf = SymbolTable->getBuffer().begin();
    392   if (kind() == K_GNU) {
    393     uint32_t symbol_count = 0;
    394     symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
    395     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
    396   } else if (kind() == K_BSD) {
    397     llvm_unreachable("BSD archive format is not supported");
    398   } else {
    399     uint32_t member_count = 0;
    400     uint32_t symbol_count = 0;
    401     member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
    402     buf += 4 + (member_count * 4); // Skip offsets.
    403     symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
    404     buf += 4 + (symbol_count * 2); // Skip indices.
    405   }
    406   uint32_t string_start_offset = buf - SymbolTable->getBuffer().begin();
    407   return symbol_iterator(Symbol(this, 0, string_start_offset));
    408 }
    409 
    410 Archive::symbol_iterator Archive::end_symbols() const {
    411   if (!hasSymbolTable())
    412     return symbol_iterator(Symbol(this, 0, 0));
    413 
    414   const char *buf = SymbolTable->getBuffer().begin();
    415   uint32_t symbol_count = 0;
    416   if (kind() == K_GNU) {
    417     symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);
    418   } else if (kind() == K_BSD) {
    419     llvm_unreachable("BSD archive format is not supported");
    420   } else {
    421     uint32_t member_count = 0;
    422     member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
    423     buf += 4 + (member_count * 4); // Skip offsets.
    424     symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
    425   }
    426   return symbol_iterator(
    427     Symbol(this, symbol_count, 0));
    428 }
    429 
    430 Archive::child_iterator Archive::findSym(StringRef name) const {
    431   Archive::symbol_iterator bs = begin_symbols();
    432   Archive::symbol_iterator es = end_symbols();
    433   Archive::child_iterator result;
    434 
    435   StringRef symname;
    436   for (; bs != es; ++bs) {
    437     if (bs->getName(symname))
    438         return end_children();
    439     if (symname == name) {
    440       if (bs->getMember(result))
    441         return end_children();
    442       return result;
    443     }
    444   }
    445   return end_children();
    446 }
    447 
    448 bool Archive::hasSymbolTable() const {
    449   return SymbolTable != end_children();
    450 }
    451