GNUArchiveReader.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- GNUArchiveReader.cpp -----------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/MC/MCLDInfo.h"
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/MC/MCLDInput.h"
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/MC/MCLDInputTree.h"
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/LD/GNUArchiveReader.h"
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/MemoryBuffer.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/system_error.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sstream>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <vector>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstdlib>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace std;
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotypedef size_t sectionSizeTy;
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotypedef uint32_t elfWord;
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Archive Header, Magic number, etc..
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst unsigned archiveMagicSize = 8;
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst char archiveMagic[archiveMagicSize] = { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' };
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst char thinArchiveMagic[archiveMagicSize] = { '!', '<', 't', 'h', 'i', 'n', '>', '\n' };
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst char archiveFinalMagic[2] = { '`', '\n' };
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct GNUArchiveReader::ArchiveMemberHeader
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char name[16];
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char date[12];
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char uid[6];
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char gid[6];
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char mode[8];
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char size[10];
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char finalMagic[2];
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao};
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct GNUArchiveReader::SymbolTableEntry
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  off_t fileOffset;
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::string name;
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao};
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoinline void endian_swap(unsigned int& x)
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  x = (x>>24) |
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      ((x<<8) & 0x00FF0000) |
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      ((x>>8) & 0x0000FF00) |
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      (x<<24);
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// convert string to size_t
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<class Type>
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoType stringToType(const std::string &str)
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Type n;
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::stringstream ss(str);
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ss >> n;
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return n;
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// GNUArchiveReader Operations
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Public API
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool GNUArchiveReader::isMyFormat(Input &pInput) const
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  llvm::OwningPtr<llvm::MemoryBuffer> mapFile;
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile);
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const char* pFile = mapFile->getBufferStart();
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// check archive format.
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(mapFile->getBufferSize() <= archiveMagicSize)
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0;
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0)
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoLDReader::Endian GNUArchiveReader::endian(Input& pFile) const
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_endian;
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoInputTree *GNUArchiveReader::readArchive(Input &pInput)
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return setupNewArchive(pInput, 0);
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Read Input as archive. First create a null InputTree.
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Then Construct Input object for corresponding member of this archive
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// and insert the Input object into the InputTree.
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Finally, return the InputTree.
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoInputTree *GNUArchiveReader::setupNewArchive(Input &pInput,
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                            size_t off)
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  llvm::OwningPtr<llvm::MemoryBuffer> mapFile;
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile))
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "GNUArchiveReader:can't map a file to MemoryBuffer\n");
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return NULL;
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  InputTree *resultTree = new InputTree(m_pLDInfo.inputFactory());
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::vector<SymbolTableEntry> symbolTable;
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::string archiveMemberName;
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::string extendedName;
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool isThinArchive;
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const char *pFile = mapFile->getBufferStart();
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// check archive format.
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(mapFile->getBufferSize() <= archiveMagicSize)
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return NULL;
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0;
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0)
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return NULL;
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  off += archiveMagicSize ;
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t symbolTableSize = parseMemberHeader(mapFile, off, &archiveMemberName,
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                            NULL, extendedName);
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// read archive symbol table
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(archiveMemberName.empty())
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    readSymbolTable(mapFile, symbolTable,
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                    off+sizeof(GNUArchiveReader::ArchiveMemberHeader), symbolTableSize);
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    off = off + sizeof(GNUArchiveReader::ArchiveMemberHeader) + symbolTableSize;
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "fatal error : need symbol table\n");
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return NULL;
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if((off&1) != 0)
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++off;
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t extendedSize = parseMemberHeader(mapFile, off, &archiveMemberName,
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                          NULL, extendedName);
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// read long Name table if exist
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(archiveMemberName == "/")
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    off += sizeof(GNUArchiveReader::ArchiveMemberHeader);
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pFile += off;
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    extendedName.assign(pFile,extendedSize);
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// traverse all the archive members
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  InputTree::iterator node = resultTree->root();
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  set<string> haveSeen;
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for(unsigned i=0 ; i<symbolTable.size() ; ++i)
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// We shall get each member at this archive.
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// Construct a corresponding mcld::Input, and insert it into
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// the original InputTree, resultTree.
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    off_t nestedOff = 0;
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    parseMemberHeader(mapFile, symbolTable[i].fileOffset, &archiveMemberName,
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                      &nestedOff, extendedName);
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(haveSeen.find(archiveMemberName)==haveSeen.end())
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      haveSeen.insert(archiveMemberName);
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      continue;
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(!isThinArchive)
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    {
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      /// New a Input object and assign fileOffset in MCLDFile.
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      /// Insert the object to resultTree and move ahead.
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      off_t fileOffset = symbolTable[i].fileOffset + sizeof(ArchiveMemberHeader);
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      Input *insertObjectFile = m_pLDInfo.inputFactory().produce(archiveMemberName,
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                                 pInput.path(),
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                                 MCLDFile::Object,
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                                 fileOffset);
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      resultTree->insert<InputTree::Positional>(node, *insertObjectFile);
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if(i==0)
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        node.move<InputTree::Inclusive>();
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        node.move<InputTree::Positional>();
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      continue;
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// create the real path
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    sys::fs::RealPath realPath(archiveMemberName);
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(nestedOff > 0)
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    {
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      /// This is a member of a nested archive.
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      /// Create an Input for this archive ,and recursive call setupNewArchive
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      /// Finally, merge the new InputTree with the old one
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      Input *newArchive = m_pLDInfo.inputFactory().produce(archiveMemberName,
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                           realPath,
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                           MCLDFile::Archive,
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                           0);
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      resultTree->insert<InputTree::Positional>(node, *newArchive);
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if(i==0)
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        node.move<InputTree::Inclusive>();
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        node.move<InputTree::Positional>();
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      InputTree *newArchiveTree = setupNewArchive(*newArchive, 0);
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      resultTree->merge<InputTree::Inclusive>(node, *newArchiveTree);
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      continue;
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// External member , open it as normal object file
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// add new Input to InputTree
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Input *insertObjectFile = m_pLDInfo.inputFactory().produce(archiveMemberName,
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                               realPath,
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                               MCLDFile::Object,
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                               0);
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    resultTree->insert<InputTree::Positional>(node, *insertObjectFile);
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(i==0)
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      node.move<InputTree::Inclusive>();
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      node.move<InputTree::Positional>();
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return resultTree;
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Parse the member header and return the size of member
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Archive member names in System 5 style :
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "/                  " - symbol table, must be the first member
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "//                 " - long name table
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "filename.o/        " - regular file with short name
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "/5566              " - name at offset 5566 at long name table
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t GNUArchiveReader::parseMemberHeader(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           off_t off,
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           std::string *p_Name,
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           off_t *p_NestedOff,
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           std::string &p_ExtendedName)
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const char *pFile = mapFile->getBufferStart();
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pFile += off;
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const ArchiveMemberHeader *header = reinterpret_cast<const ArchiveMemberHeader *>(pFile);
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// check magic number of member header
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(memcmp(header->finalMagic, archiveFinalMagic, sizeof archiveFinalMagic))
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "archive member header magic number false");
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return 0;
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// evaluate member size
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  std::string sizeString(header->size, sizeof(header->size)+1);
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t memberSize = stringToType<size_t>(sizeString);
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(memberSize == 0)
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "member Size Error");
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return 0;
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(header->name[0] != '/')
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// This is a regular file with short name
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    const char* nameEnd = strchr(header->name, '/');
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    size_t nameLen = ((nameEnd == NULL) ? 0 : (nameEnd - header->name));
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if((nameLen <= 0) || (nameLen >= sizeof(header->name)))
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    {
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(0 && "header name format error\n");
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return 0;
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    p_Name->assign(header->name, nameLen);
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(!p_NestedOff)
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      p_NestedOff = 0;
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else if(header->name[1] == ' ')
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// This is symbol table
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(!p_Name->empty())
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      p_Name->clear();
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else if(header->name[1] == '/')
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// This is long name table
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    p_Name->assign(1,'/');
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// This is regular file with long name
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    char *end;
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    long extendedNameOff = strtol(header->name+1, &end, 10);
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    long nestedOff = 0;
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(*end == ':')
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      nestedOff = strtol(end+1, &end, 10);
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(*end != ' '
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       || extendedNameOff < 0
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       || static_cast<size_t>(extendedNameOff) >= p_ExtendedName.size())
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    {
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(0 && "extended name");
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return 0;
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    const char *name = p_ExtendedName.data() + extendedNameOff;
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    const char *nameEnd = strchr(name, '\n');
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(nameEnd[-1] != '/'
3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       || static_cast<size_t>(nameEnd-name) > p_ExtendedName.size())
3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    {
3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(0 && "p_ExtendedName substring is not end with / \n");
3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return 0;
3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    p_Name->assign(name, nameEnd-name-1);
3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if(p_NestedOff)
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao     *p_NestedOff = nestedOff;
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return memberSize;
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid GNUArchiveReader::readSymbolTable(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       std::vector<SymbolTableEntry> &pSymbolTable,
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       off_t start,
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       size_t size)
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const char *startPtr = mapFile->getBufferStart() + start;
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const elfWord *p_Word = reinterpret_cast<const elfWord *>(startPtr);
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  unsigned int symbolNum = *p_Word;
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// Portable Issue on Sparc platform
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// Intel, ARM and Mips are littel-endian , Sparc is little-endian after verion 9
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// symbolNum in symbol table is always big-endian
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if(m_endian == LDReader::LittleEndian)
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    endian_swap(symbolNum);
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++p_Word;
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const char *p_Name = reinterpret_cast<const char *>(p_Word + symbolNum);
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pSymbolTable.resize(symbolNum);
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for(unsigned int i=0 ; i<symbolNum ; ++i)
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// assign member offset
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    unsigned int memberOffset = *p_Word;
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    endian_swap(memberOffset);
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pSymbolTable[i].fileOffset = static_cast<off_t>(memberOffset);
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++p_Word;
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /// assign member name
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    off_t nameEnd = strlen(p_Name) + 1;
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pSymbolTable[i].name.assign(p_Name, nameEnd);
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    p_Name += nameEnd;
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
357