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//===----------------------------------------------------------------------===//
9affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/MC/MCLDInfo.h>
10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/MC/MCLDInput.h>
11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/MC/InputTree.h>
12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/GNUArchiveReader.h>
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/LD/ResolveInfo.h>
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/LD/ELFObjectReader.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/FileSystem.h>
16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Support/FileHandle.h>
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryArea.h>
18affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryRegion.h>
19affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryAreaFactory.h>
20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
21cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Support/Path.h>
22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/ADT/SizeTraits.h>
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
24cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/ADT/StringRef.h>
25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h>
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
27cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <cstring>
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstdlib>
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
32cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoGNUArchiveReader::GNUArchiveReader(MCLDInfo& pLDInfo,
33cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                   MemoryAreaFactory& pMemAreaFactory,
34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                   ELFObjectReader& pELFObjectReader)
35cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao : m_LDInfo(pLDInfo),
36cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao   m_MemAreaFactory(pMemAreaFactory),
37cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao   m_ELFObjectReader(pELFObjectReader)
38cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
39cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoGNUArchiveReader::~GNUArchiveReader()
42cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
43cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
45cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isMyFormat
46cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isMyFormat(Input& pInput) const
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
48cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pInput.hasMemArea());
49cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
50cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                                   Archive::MAGIC_LEN);
51cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const char* str = reinterpret_cast<const char*>(region->getBuffer());
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
53cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  bool result = false;
54cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(NULL != str);
55cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (isArchive(str) || isThinArchive(str))
56cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    result = true;
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
58cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pInput.memArea()->release(region);
59cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return result;
60cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
62cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isArchive
63cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isArchive(const char* pStr) const
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
65cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return (0 == memcmp(pStr, Archive::MAGIC, Archive::MAGIC_LEN));
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
68cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isThinArchive
69cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isThinArchive(const char* pStr) const
70cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
71cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return (0 == memcmp(pStr, Archive::THIN_MAGIC, Archive::MAGIC_LEN));
72cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
74cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isThinArchive
75cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isThinArchive(Input& pInput) const
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(pInput.hasMemArea());
78cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
79cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                                   Archive::MAGIC_LEN);
80cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const char* str = reinterpret_cast<const char*>(region->getBuffer());
81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
82cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  bool result = false;
83cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(NULL != str);
84cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (isThinArchive(str))
85cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    result = true;
86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
87cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pInput.memArea()->release(region);
88cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return result;
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
91cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::readArchive(Archive& pArchive)
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
93cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // read the symtab of the archive
94cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  readSymbolTable(pArchive);
95cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
96cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // read the strtab of the archive
97cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  readStringTable(pArchive);
98cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
99cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // add root archive to ArchiveMemberMap
100cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.addArchiveMember(pArchive.getARFile().name(),
101cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                            pArchive.inputs().root(),
102cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                            &InputTree::Downward);
103cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
104cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // include the needed members in the archive and build up the input tree
105cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  bool willSymResolved;
106cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  do {
107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    willSymResolved = false;
108cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    for (size_t idx = 0; idx < pArchive.numOfSymbols(); ++idx) {
109cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // bypass if we already decided to include this symbol or not
110cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (Archive::Symbol::Unknown != pArchive.getSymbolStatus(idx))
111cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        continue;
112cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
113cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // bypass if another symbol with the same object file offset is included
114cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (pArchive.hasObjectMember(pArchive.getObjFileOffset(idx))) {
115cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pArchive.setSymbolStatus(idx, Archive::Symbol::Include);
116cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        continue;
117cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      }
118cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // check if we should include this defined symbol
120cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      Archive::Symbol::Status status =
121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        shouldIncludeSymbol(pArchive.getSymbolName(idx));
122cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (Archive::Symbol::Unknown != status)
123cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pArchive.setSymbolStatus(idx, status);
124cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
125cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (Archive::Symbol::Include == status) {
126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        Input* cur_archive = &(pArchive.getARFile());
127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        Input* member = cur_archive;
128cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        uint32_t file_offset = pArchive.getObjFileOffset(idx);
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        while ((member != NULL) && (Input::Object != member->type())) {
130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          uint32_t nested_offset = 0;
131cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          // use the file offset in current archive to find out the member we
132cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          // want to include
133cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          member = readMemberHeader(pArchive,
134cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                    *cur_archive,
135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                    file_offset,
136cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                    nested_offset);
137cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          assert(member != NULL);
138cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          // bypass if we get an archive that is already in the map
139cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          if (Input::Archive == member->type()) {
140cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao              cur_archive = member;
141cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao              file_offset = nested_offset;
142cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao              continue;
143cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          }
144cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
145cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          // insert a node into the subtree of current archive.
146cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          Archive::ArchiveMember* parent =
147cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            pArchive.getArchiveMember(cur_archive->name());
148cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
149cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          assert(NULL != parent);
150cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
151cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
152cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          // move the iterator to new created node, and also adjust the
153cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          // direction to Afterward for next insertion in this subtree
154cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          parent->move->move(parent->lastPos);
155cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          parent->move = &InputTree::Afterward;
156cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
157cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          if (m_ELFObjectReader.isMyFormat(*member)) {
158cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            member->setType(Input::Object);
159cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            pArchive.addObjectMember(pArchive.getObjFileOffset(idx),
160cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                     parent->lastPos);
161cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            m_ELFObjectReader.readObject(*member);
162cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            m_ELFObjectReader.readSections(*member);
163cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            m_ELFObjectReader.readSymbols(*member);
164cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          }
165cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          else if (isMyFormat(*member)) {
166cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            member->setType(Input::Archive);
167cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            // when adding a new archive node, set the iterator to archive
168cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            // itself, and set the direction to Downward
169cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            pArchive.addArchiveMember(member->name(),
170cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                      parent->lastPos,
171cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                      &InputTree::Downward);
172cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            cur_archive = member;
173cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao            file_offset = nested_offset;
174cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao          }
175cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        } // end of while
176cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        willSymResolved = true;
177cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      } // end of if
178cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    } // end of for
179cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  } while (willSymResolved);
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
181cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return true;
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
184cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readMemberHeader - read the header of a member in a archive file and then
185cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// return the corresponding archive member (it may be an input object or
186cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// another archive)
187cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pArchiveRoot  - the archive root that holds the strtab (extended
188cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao///                        name table)
189cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pArchiveFile  - the archive that contains the needed object
190cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pFileOffset   - file offset of the member header in the archive
191cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pNestedOffset - used when we find a nested archive
192cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoInput* GNUArchiveReader::readMemberHeader(Archive& pArchiveRoot,
193cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                          Input& pArchiveFile,
194cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                          uint32_t pFileOffset,
195cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                          uint32_t& pNestedOffset)
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
197cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pArchiveFile.hasMemArea());
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
199cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* header_region =
200cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    pArchiveFile.memArea()->request((pArchiveFile.fileOffset() + pFileOffset),
201cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                    sizeof(Archive::MemberHeader));
202cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const Archive::MemberHeader* header =
203cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
205cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
206cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
207cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // int size = atoi(header->size);
208cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
209cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // parse the member name and nested offset if any
210cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  std::string member_name;
211cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::StringRef name_field(header->name, 16);
212cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if ('/' != header->name[0]) {
213cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is an object file in an archive
214cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    size_t pos = name_field.find_first_of('/');
215cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member_name.assign(name_field.substr(0, pos).str());
216cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
217cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  else {
218cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is an object/archive file in a thin archive
219cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    size_t begin = 1;
220cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    size_t end = name_field.find_first_of(" :");
221cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    uint32_t name_offset = 0;
222cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // parse the name offset
223cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    name_field.substr(begin, end - begin).getAsInteger(10, name_offset);
224cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
225cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (':' == name_field[end]) {
226cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // there is a nested offset
227cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      begin = end + 1;
228cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      end = name_field.find_first_of(' ', begin);
229cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      name_field.substr(begin, end - begin).getAsInteger(10, pNestedOffset);
230cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
231cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
232cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // get the member name from the extended name table
233cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    begin = name_offset;
234cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    end = pArchiveRoot.getStrTable().find_first_of('\n', begin);
235cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member_name.assign(pArchiveRoot.getStrTable().substr(begin, end - begin -1));
236cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
237affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
238cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  Input* member = NULL;
239cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (!isThinArchive(pArchiveFile)) {
240cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is an object file in an archive
241cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member =
242cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      m_LDInfo.inputFactory().produce(member_name,
243cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                      pArchiveFile.path(),
244cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                      Input::Unknown,
245cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                      (pFileOffset +
246cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                       sizeof(Archive::MemberHeader)));
247cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    assert(member != NULL);
248cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member->setMemArea(pArchiveFile.memArea());
249cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    LDContext *input_context = m_LDInfo.contextFactory().produce();
250cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member->setContext(input_context);
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
252cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  else {
253cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is a member in a thin archive
254cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // try to find if this is a archive already in the map first
255cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    Archive::ArchiveMember* ar_member =
256cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      pArchiveRoot.getArchiveMember(member_name);
257cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (NULL != ar_member) {
258cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return ar_member->file;
259cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
261cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // get nested file path, the nested file's member name is the relative
262cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // path to the archive containing it.
263cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    sys::fs::Path input_path(pArchiveFile.path().parent_path());
264cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (!input_path.empty())
265cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      input_path.append(member_name);
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else
267cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      input_path.assign(member_name);
268cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member =
269cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      m_LDInfo.inputFactory().produce(member_name, input_path, Input::Unknown);
270cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
271cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    assert(member != NULL);
272cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    MemoryArea* input_memory =
273cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      m_MemAreaFactory.produce(member->path(), FileHandle::ReadOnly);
274cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (input_memory->handler()->isGood()) {
275cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      member->setMemArea(input_memory);
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
277cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    else {
278cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      error(diag::err_cannot_open_input) << member->name() << member->path();
279cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return NULL;
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
281cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    LDContext *input_context = m_LDInfo.contextFactory().produce(input_path);
282cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member->setContext(input_context);
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
284cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
285cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchiveFile.memArea()->release(header_region);
286cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return member;
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
289cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readSymbolTable - read the archive symbol map (armap)
290cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::readSymbolTable(Archive& pArchive)
291cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
292cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pArchive.getARFile().hasMemArea());
293cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
294cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* header_region =
295cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
296cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                             Archive::MAGIC_LEN),
297cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                            sizeof(Archive::MemberHeader));
298cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const Archive::MemberHeader* header =
299cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
300cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
301cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
302cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  int symtab_size = atoi(header->size);
303cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.setSymTabSize(symtab_size);
304cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
305cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* symtab_region =
306cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
307cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                             Archive::MAGIC_LEN +
308cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                             sizeof(Archive::MemberHeader)),
309cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                            symtab_size);
310cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const uint32_t* data =
311cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    reinterpret_cast<const uint32_t*>(symtab_region->getBuffer());
312cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
313cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // read the number of symbols
314cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  uint32_t number = 0;
315cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (llvm::sys::isLittleEndianHost())
316cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    number = bswap32(*data);
317cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  else
318cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    number = *data;
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
320cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // set up the pointers for file offset and name offset
321cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  ++data;
322cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const char* name = reinterpret_cast<const char*>(data + number);
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
324cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // add the archive symbols
325cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  for (uint32_t i = 0; i < number; ++i) {
326cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (llvm::sys::isLittleEndianHost())
327cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      pArchive.addSymbol(name, bswap32(*data));
328cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    else
329cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      pArchive.addSymbol(name, *data);
330cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    name += strlen(name) + 1;
331cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    ++data;
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
334cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.getARFile().memArea()->release(header_region);
335cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.getARFile().memArea()->release(symtab_region);
336cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return true;
337cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
339cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readStringTable - read the strtab for long file name of the archive
340cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::readStringTable(Archive& pArchive)
341cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
342cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  size_t offset = Archive::MAGIC_LEN +
343cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                  sizeof(Archive::MemberHeader) +
344cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                  pArchive.getSymTabSize();
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
346cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (0x0 != (offset & 1))
347cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    ++offset;
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
349cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pArchive.getARFile().hasMemArea());
350cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
351cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* header_region =
352cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
353cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                             offset),
354cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                            sizeof(Archive::MemberHeader));
355cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const Archive::MemberHeader* header =
356cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
358cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
359cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
360cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  int strtab_size = atoi(header->size);
361cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
362cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  MemoryRegion* strtab_region =
363cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
364cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                             offset +
365cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                             sizeof(Archive::MemberHeader)),
366cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                            strtab_size);
367cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const char* strtab =
368cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    reinterpret_cast<const char*>(strtab_region->getBuffer());
369cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
370cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.getStrTable().assign(strtab, strtab_size);
371cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
372cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.getARFile().memArea()->release(header_region);
373cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.getARFile().memArea()->release(strtab_region);
374cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return true;
3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
377cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// shouldIncludeStatus - given a sym name from armap and check if including
378cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// the corresponding archive member, and then return the decision
379cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaoenum Archive::Symbol::Status
380cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoGNUArchiveReader::shouldIncludeSymbol(const llvm::StringRef& pSymName) const
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
382cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // TODO: handle symbol version issue and user defined symbols
383cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pSymName);
384cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL != info) {
385cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (!info->isUndef())
386cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return Archive::Symbol::Exclude;
387cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (info->isWeak())
388cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return Archive::Symbol::Unknown;
389cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return Archive::Symbol::Include;
3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
391cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return Archive::Symbol::Unknown;
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
393cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
394