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//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/GNUArchiveReader.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/InputTree.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Module.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/ADT/SizeTraits.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Attribute.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFObjectReader.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/FileHandle.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/FileSystem.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Path.h"
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
25cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/ADT/StringRef.h>
26affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h>
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstdlib>
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <cstring>
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoGNUArchiveReader::GNUArchiveReader(Module& pModule,
34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                   ELFObjectReader& pELFObjectReader)
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_Module(pModule), m_ELFObjectReader(pELFObjectReader) {
36cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3837b74a387bb3993387029859c2d9d051c41c724eStephen HinesGNUArchiveReader::~GNUArchiveReader() {
39cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isMyFormat
4237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool GNUArchiveReader::isMyFormat(Input& pInput, bool& pContinue) const {
43cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pInput.hasMemArea());
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pInput.memArea()->size() < Archive::MAGIC_LEN)
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef region =
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pInput.memArea()->request(pInput.fileOffset(), Archive::MAGIC_LEN);
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char* str = region.begin();
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
51cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  bool result = false;
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(str != NULL);
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pContinue = true;
54cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (isArchive(str) || isThinArchive(str))
55cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    result = true;
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
57cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return result;
58cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
60cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isArchive
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool GNUArchiveReader::isArchive(const char* pStr) const {
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return (memcmp(pStr, Archive::MAGIC, Archive::MAGIC_LEN) == 0);
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isThinArchive
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool GNUArchiveReader::isThinArchive(const char* pStr) const {
6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return (memcmp(pStr, Archive::THIN_MAGIC, Archive::MAGIC_LEN) == 0);
68cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
70cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isThinArchive
7137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool GNUArchiveReader::isThinArchive(Input& pInput) const {
72affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(pInput.hasMemArea());
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef region =
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pInput.memArea()->request(pInput.fileOffset(), Archive::MAGIC_LEN);
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char* str = region.begin();
76affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
77cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  bool result = false;
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(str != NULL);
79cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (isThinArchive(str))
80cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    result = true;
81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
82cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return result;
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool GNUArchiveReader::readArchive(const LinkerConfig& pConfig,
8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   Archive& pArchive) {
876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // bypass the empty archive
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (Archive::MAGIC_LEN == pArchive.getARFile().memArea()->size())
896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pArchive.getARFile().attribute()->isWholeArchive())
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return includeAllMembers(pConfig, pArchive);
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // if this is the first time read this archive, setup symtab and strtab
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pArchive.getSymbolTable().empty()) {
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    // read the symtab of the archive
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    readSymbolTable(pArchive);
98cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    // read the strtab of the archive
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    readStringTable(pArchive);
101cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    // add root archive to ArchiveMemberMap
10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    pArchive.addArchiveMember(pArchive.getARFile().name(),
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              pArchive.inputs().root(),
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              &InputTree::Downward);
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
108cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // include the needed members in the archive and build up the input tree
109cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  bool willSymResolved;
110cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  do {
111cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    willSymResolved = false;
112cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    for (size_t idx = 0; idx < pArchive.numOfSymbols(); ++idx) {
113cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // bypass if we already decided to include this symbol or not
114cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (Archive::Symbol::Unknown != pArchive.getSymbolStatus(idx))
115cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        continue;
116cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
117cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // bypass if another symbol with the same object file offset is included
118cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (pArchive.hasObjectMember(pArchive.getObjFileOffset(idx))) {
119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pArchive.setSymbolStatus(idx, Archive::Symbol::Include);
120cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        continue;
121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      }
122cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
123cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // check if we should include this defined symbol
124cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      Archive::Symbol::Status status =
12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          shouldIncludeSymbol(pArchive.getSymbolName(idx));
126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (Archive::Symbol::Unknown != status)
127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pArchive.setSymbolStatus(idx, status);
128cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (Archive::Symbol::Include == status) {
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // include the object member from the given offset
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        includeMember(pConfig, pArchive, pArchive.getObjFileOffset(idx));
132cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        willSymResolved = true;
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }  // end of if
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }    // end of for
135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  } while (willSymResolved);
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
137cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return true;
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
140cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readMemberHeader - read the header of a member in a archive file and then
141cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// return the corresponding archive member (it may be an input object or
142cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// another archive)
143cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pArchiveRoot  - the archive root that holds the strtab (extended
144cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao///                        name table)
145cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pArchiveFile  - the archive that contains the needed object
146cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pFileOffset   - file offset of the member header in the archive
147cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pNestedOffset - used when we find a nested archive
14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pMemberSize   - the file size of this member
149cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoInput* GNUArchiveReader::readMemberHeader(Archive& pArchiveRoot,
150cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                          Input& pArchiveFile,
151cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                          uint32_t pFileOffset,
15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                          uint32_t& pNestedOffset,
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                          size_t& pMemberSize) {
154cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pArchiveFile.hasMemArea());
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::StringRef header_region = pArchiveFile.memArea()->request(
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (pArchiveFile.fileOffset() + pFileOffset), sizeof(Archive::MemberHeader));
158cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const Archive::MemberHeader* header =
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      reinterpret_cast<const Archive::MemberHeader*>(header_region.begin());
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)) ==
16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines         0);
163cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pMemberSize = atoi(header->size);
165cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
166cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // parse the member name and nested offset if any
167cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  std::string member_name;
16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::StringRef name_field(header->name, sizeof(header->name));
16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (header->name[0] != '/') {
170cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is an object file in an archive
171cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    size_t pos = name_field.find_first_of('/');
172cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    member_name.assign(name_field.substr(0, pos).str());
17337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
174cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is an object/archive file in a thin archive
175cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    size_t begin = 1;
176cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    size_t end = name_field.find_first_of(" :");
177cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    uint32_t name_offset = 0;
178cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // parse the name offset
179cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    name_field.substr(begin, end - begin).getAsInteger(10, name_offset);
180cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
18137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (name_field[end] == ':') {
182cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // there is a nested offset
183cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      begin = end + 1;
184cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      end = name_field.find_first_of(' ', begin);
185cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      name_field.substr(begin, end - begin).getAsInteger(10, pNestedOffset);
186cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
187cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
188cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // get the member name from the extended name table
18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(pArchiveRoot.hasStrTable());
190cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    begin = name_offset;
191cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    end = pArchiveRoot.getStrTable().find_first_of('\n', begin);
19237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    member_name.assign(
19337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchiveRoot.getStrTable().substr(begin, end - begin - 1));
194cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
196cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  Input* member = NULL;
19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool isThinAR = isThinArchive(pArchiveFile);
19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!isThinAR) {
199cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is an object file in an archive
20037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    member = pArchiveRoot.getMemberFile(
20137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchiveFile,
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        isThinAR,
20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        member_name,
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchiveFile.path(),
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        (pFileOffset + sizeof(Archive::MemberHeader)));
20637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
207cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // this is a member in a thin archive
208cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // try to find if this is a archive already in the map first
209cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    Archive::ArchiveMember* ar_member =
21037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchiveRoot.getArchiveMember(member_name);
21137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (ar_member != NULL) {
212cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return ar_member->file;
213cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
215cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // get nested file path, the nested file's member name is the relative
216cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    // path to the archive containing it.
217cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    sys::fs::Path input_path(pArchiveFile.path().parent_path());
218cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (!input_path.empty())
21937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      input_path.append(sys::fs::Path(member_name));
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else
221cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      input_path.assign(member_name);
222cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
22337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    member = pArchiveRoot.getMemberFile(
22437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchiveFile, isThinAR, member_name, input_path);
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
226cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
227cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return member;
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinestemplate <size_t SIZE>
23137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic void readSymbolTableEntries(Archive& pArchive,
23237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   llvm::StringRef pMemRegion) {
23387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  typedef typename SizeTraits<SIZE>::Offset Offset;
23487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const Offset* data = reinterpret_cast<const Offset*>(pMemRegion.begin());
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // read the number of symbols
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Offset number = 0;
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::sys::IsLittleEndianHost)
24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    number = mcld::bswap<SIZE>(*data);
24187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    number = *data;
24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set up the pointers for file offset and name offset
24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ++data;
24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char* name = reinterpret_cast<const char*>(data + number);
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // add the archive symbols
24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (Offset i = 0; i < number; ++i) {
25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (llvm::sys::IsLittleEndianHost)
25187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pArchive.addSymbol(name, mcld::bswap<SIZE>(*data));
25287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
25387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pArchive.addSymbol(name, *data);
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    name += strlen(name) + 1;
25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ++data;
25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
25887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
259cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readSymbolTable - read the archive symbol map (armap)
26037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool GNUArchiveReader::readSymbolTable(Archive& pArchive) {
261cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pArchive.getARFile().hasMemArea());
26237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  MemoryArea* memory_area = pArchive.getARFile().memArea();
263cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
26437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::StringRef header_region = memory_area->request(
26537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (pArchive.getARFile().fileOffset() + Archive::MAGIC_LEN),
26637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sizeof(Archive::MemberHeader));
267cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const Archive::MemberHeader* header =
26837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      reinterpret_cast<const Archive::MemberHeader*>(header_region.begin());
26937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)) ==
27037b74a387bb3993387029859c2d9d051c41c724eStephen Hines         0);
271cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
272cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  int symtab_size = atoi(header->size);
273cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pArchive.setSymTabSize(symtab_size);
274cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
27522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!pArchive.getARFile().attribute()->isWholeArchive()) {
27637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    llvm::StringRef symtab_region = memory_area->request(
27737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        (pArchive.getARFile().fileOffset() + Archive::MAGIC_LEN +
27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         sizeof(Archive::MemberHeader)),
27987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        symtab_size);
28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
28137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (strncmp(header->name,
28237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                Archive::SVR4_SYMTAB_NAME,
28337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                strlen(Archive::SVR4_SYMTAB_NAME)) == 0)
28487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      readSymbolTableEntries<32>(pArchive, symtab_region);
28537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    else if (strncmp(header->name,
28637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                     Archive::IRIX6_SYMTAB_NAME,
28737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                     strlen(Archive::IRIX6_SYMTAB_NAME)) == 0)
28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      readSymbolTableEntries<64>(pArchive, symtab_region);
289cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    else
29087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      unreachable(diag::err_unsupported_archive);
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
292cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return true;
293cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
295cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readStringTable - read the strtab for long file name of the archive
29637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool GNUArchiveReader::readStringTable(Archive& pArchive) {
29737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  size_t offset = Archive::MAGIC_LEN + sizeof(Archive::MemberHeader) +
298cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                  pArchive.getSymTabSize();
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
30037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((offset & 1) != 0x0)
301cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    ++offset;
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
303cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  assert(pArchive.getARFile().hasMemArea());
30437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  MemoryArea* memory_area = pArchive.getARFile().memArea();
305cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef header_region =
30737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      memory_area->request((pArchive.getARFile().fileOffset() + offset),
30837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           sizeof(Archive::MemberHeader));
309cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  const Archive::MemberHeader* header =
31037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      reinterpret_cast<const Archive::MemberHeader*>(header_region.begin());
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
31237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)) ==
31337b74a387bb3993387029859c2d9d051c41c724eStephen Hines         0);
31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
31537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (memcmp(header->name, Archive::STRTAB_NAME, sizeof(header->name)) == 0) {
31622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // read the extended name table
31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int strtab_size = atoi(header->size);
31887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    llvm::StringRef strtab_region =
31937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        memory_area->request((pArchive.getARFile().fileOffset() + offset +
32037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              sizeof(Archive::MemberHeader)),
32137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             strtab_size);
32287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const char* strtab = strtab_region.begin();
32322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pArchive.getStrTable().assign(strtab, strtab_size);
32422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
325cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return true;
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
328cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// shouldIncludeStatus - given a sym name from armap and check if including
329cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// the corresponding archive member, and then return the decision
33037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesenum Archive::Symbol::Status GNUArchiveReader::shouldIncludeSymbol(
33137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const llvm::StringRef& pSymName) const {
332cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // TODO: handle symbol version issue and user defined symbols
33322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ResolveInfo* info = m_Module.getNamePool().findInfo(pSymName);
33437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (info != NULL) {
335cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (!info->isUndef())
336cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return Archive::Symbol::Exclude;
337cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (info->isWeak())
338cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return Archive::Symbol::Unknown;
339cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return Archive::Symbol::Include;
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
341cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return Archive::Symbol::Unknown;
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
343cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
34422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// includeMember - include the object member in the given file offset, and
34522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// return the size of the object
34687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// @param pConfig - LinkerConfig
34722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pArchiveRoot - the archive root
34822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pFileOffset  - file offset of the member header in the archive
34987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinessize_t GNUArchiveReader::includeMember(const LinkerConfig& pConfig,
35087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       Archive& pArchive,
35137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       uint32_t pFileOffset) {
35222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Input* cur_archive = &(pArchive.getARFile());
35322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Input* member = NULL;
35422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t file_offset = pFileOffset;
35522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t size = 0;
35622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  do {
35722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t nested_offset = 0;
35822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // use the file offset in current archive to find out the member we
35922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // want to include
36037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    member = readMemberHeader(
36137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchive, *cur_archive, file_offset, nested_offset, size);
36222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(member != NULL);
36322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // bypass if we get an archive that is already in the map
36422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (Input::Archive == member->type()) {
36537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      cur_archive = member;
36637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      file_offset = nested_offset;
36737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      continue;
36822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
36922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
37022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // insert a node into the subtree of current archive.
37122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Archive::ArchiveMember* parent =
37237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pArchive.getArchiveMember(cur_archive->name());
37322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert(parent != NULL);
37522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
37622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
37722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // move the iterator to new created node, and also adjust the
37822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // direction to Afterward for next insertion in this subtree
37922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    parent->move->move(parent->lastPos);
38022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    parent->move = &InputTree::Afterward;
38187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bool doContinue = false;
38222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
38387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (m_ELFObjectReader.isMyFormat(*member, doContinue)) {
38422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      member->setType(Input::Object);
3850dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      // Set this object as no export if the archive is in the exclude libs.
3860dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      if (pArchive.getARFile().noExport()) {
3870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        member->setNoExport();
3880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      }
38922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pArchive.addObjectMember(pFileOffset, parent->lastPos);
39022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_ELFObjectReader.readHeader(*member);
39122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_ELFObjectReader.readSections(*member);
39222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_ELFObjectReader.readSymbols(*member);
39322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_Module.getObjectList().push_back(member);
39437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else if (doContinue && isMyFormat(*member, doContinue)) {
39522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      member->setType(Input::Archive);
39622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // when adding a new archive node, set the iterator to archive
39722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // itself, and set the direction to Downward
39837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pArchive.addArchiveMember(
39937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          member->name(), parent->lastPos, &InputTree::Downward);
40022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      cur_archive = member;
40122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      file_offset = nested_offset;
40237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
40337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      warning(diag::warn_unrecognized_input_file)
40437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          << member->path() << pConfig.targets().triple().str();
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
40622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } while (Input::Object != member->type());
40722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return size;
40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// includeAllMembers - include all object members. This is called if
41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// --whole-archive is the attribute for this archive file.
41287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool GNUArchiveReader::includeAllMembers(const LinkerConfig& pConfig,
41337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         Archive& pArchive) {
41422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // read the symtab of the archive
41522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  readSymbolTable(pArchive);
41622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // read the strtab of the archive
41822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  readStringTable(pArchive);
41922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // add root archive to ArchiveMemberMap
42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pArchive.addArchiveMember(pArchive.getARFile().name(),
42222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                            pArchive.inputs().root(),
42322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                            &InputTree::Downward);
42422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool isThinAR = isThinArchive(pArchive.getARFile());
42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t begin_offset = pArchive.getARFile().fileOffset() +
42737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                          Archive::MAGIC_LEN + sizeof(Archive::MemberHeader) +
42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          pArchive.getSymTabSize();
42922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pArchive.hasStrTable()) {
43037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if ((begin_offset & 1) != 0x0)
43122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      ++begin_offset;
43237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    begin_offset +=
43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        sizeof(Archive::MemberHeader) + pArchive.getStrTable().size();
43422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
43587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t end_offset = pArchive.getARFile().memArea()->size();
43637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (uint32_t offset = begin_offset; offset < end_offset;
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao       offset += sizeof(Archive::MemberHeader)) {
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    size_t size = includeMember(pConfig, pArchive, offset);
43922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (!isThinAR) {
44122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      offset += size;
44222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
44322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if ((offset & 1) != 0x0)
44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      ++offset;
44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
44937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
45037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
451