1//===- Archive.cpp --------------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include <mcld/LD/Archive.h>
10#include <mcld/MC/InputFactory.h>
11#include <llvm/ADT/StringRef.h>
12
13using namespace mcld;
14
15//===----------------------------------------------------------------------===//
16// Archive
17const char   Archive::MAGIC[]            = "!<arch>\n";
18const char   Archive::THIN_MAGIC[]       = "!<thin>\n";
19const size_t Archive::MAGIC_LEN          = sizeof(Archive::MAGIC) - 1;
20const char   Archive::SVR4_SYMTAB_NAME[] = "/               ";
21const char   Archive::STRTAB_NAME[]      = "//              ";
22const char   Archive::PAD[]              = "\n";
23const char   Archive::MEMBER_MAGIC[]     = "`\n";
24
25Archive::Archive(Input& pInputFile, InputFactory& pInputFactory)
26 : m_ArchiveFile(pInputFile),
27   m_pInputTree(NULL),
28   m_SymbolFactory(32)
29{
30  m_pInputTree = new InputTree(pInputFactory);
31}
32
33Archive::~Archive()
34{
35  delete m_pInputTree;
36}
37
38/// getARFile - get the Input& of the archive file
39Input& Archive::getARFile()
40{
41  return m_ArchiveFile;
42}
43
44/// getARFile - get the Input& of the archive file
45const Input& Archive::getARFile() const
46{
47  return m_ArchiveFile;
48}
49
50/// inputs - get the input tree built from this archive
51InputTree& Archive::inputs()
52{
53  return *m_pInputTree;
54}
55
56/// inputs - get the input tree built from this archive
57const InputTree& Archive::inputs() const
58{
59  return *m_pInputTree;
60}
61
62/// getObjectMemberMap - get the map that contains the included object files
63Archive::ObjectMemberMapType& Archive::getObjectMemberMap()
64{
65  return m_ObjectMemberMap;
66}
67
68/// getObjectMemberMap - get the map that contains the included object files
69const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const
70{
71  return m_ObjectMemberMap;
72}
73
74/// numOfObjectMember - return the number of included object files
75size_t Archive::numOfObjectMember() const
76{
77  return m_ObjectMemberMap.numOfEntries();
78}
79
80/// addObjectMember - add a object in the object member map
81/// @param pFileOffset - file offset in symtab represents a object file
82/// @param pIter - the iterator in the input tree built from this archive
83bool Archive::addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter)
84{
85  bool exist;
86  ObjectMemberEntryType* entry = m_ObjectMemberMap.insert(pFileOffset, exist);
87  if (!exist)
88    entry->setValue(pIter);
89  return !exist;
90}
91
92/// hasObjectMember - check if a object file is included or not
93/// @param pFileOffset - file offset in symtab represents a object file
94bool Archive::hasObjectMember(uint32_t pFileOffset) const
95{
96  return (m_ObjectMemberMap.find(pFileOffset) != m_ObjectMemberMap.end());
97}
98
99/// getArchiveMemberMap - get the map that contains the included archive files
100Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap()
101{
102  return m_ArchiveMemberMap;
103}
104
105/// getArchiveMemberMap - get the map that contains the included archive files
106const Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() const
107{
108  return m_ArchiveMemberMap;
109}
110
111/// addArchiveMember - add an archive in the archive member map
112/// @param pName    - the name of the new archive member
113/// @param pLastPos - this records the point to insert the next node in the
114///                   subtree of this archive member
115/// @param pMove    - this records the direction to insert the next node in the
116///                   subtree of this archive member
117bool Archive::addArchiveMember(const llvm::StringRef& pName,
118                               InputTree::iterator pLastPos,
119                               InputTree::Mover* pMove)
120{
121  bool exist;
122  ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist);
123  if (!exist) {
124    ArchiveMember& ar = entry->value();
125    ar.file = *pLastPos;
126    ar.lastPos = pLastPos;
127    ar.move = pMove;
128  }
129  return !exist;
130}
131
132/// hasArchiveMember - check if an archive file is included or not
133bool Archive::hasArchiveMember(const llvm::StringRef& pName) const
134{
135  return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end());
136}
137
138/// getArchiveMember - get a archive member
139Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName)
140{
141  ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName);
142  if (it != m_ArchiveMemberMap.end())
143    return &(it.getEntry()->value());
144  return NULL;
145}
146
147/// getSymbolTable - get the symtab
148Archive::SymTabType& Archive::getSymbolTable()
149{
150  return m_SymTab;
151}
152
153/// getSymbolTable - get the symtab
154const Archive::SymTabType& Archive::getSymbolTable() const
155{
156  return m_SymTab;
157}
158
159/// setSymTabSize - set the memory size of symtab
160void Archive::setSymTabSize(size_t pSize)
161{
162  m_SymTabSize = pSize;
163}
164
165/// getSymTabSize - get the memory size of symtab
166size_t Archive::getSymTabSize() const
167{
168  return m_SymTabSize;
169}
170
171/// numOfSymbols - return the number of symbols in symtab
172size_t Archive::numOfSymbols() const
173{
174  return m_SymTab.size();
175}
176
177/// addSymbol - add a symtab entry to symtab
178/// @param pName - symbol name
179/// @param pFileOffset - file offset in symtab represents a object file
180void Archive::addSymbol(const char* pName,
181                        uint32_t pFileOffset,
182                        enum Archive::Symbol::Status pStatus)
183{
184  Symbol* entry = m_SymbolFactory.allocate();
185  new (entry) Symbol(pName, pFileOffset, pStatus);
186  m_SymTab.push_back(entry);
187}
188
189/// getSymbolName - get the symbol name with the given index
190const std::string& Archive::getSymbolName(size_t pSymIdx) const
191{
192  assert(pSymIdx < numOfSymbols());
193  return m_SymTab[pSymIdx]->name;
194}
195
196/// getObjFileOffset - get the file offset that represent a object file
197uint32_t Archive::getObjFileOffset(size_t pSymIdx) const
198{
199  assert(pSymIdx < numOfSymbols());
200  return m_SymTab[pSymIdx]->fileOffset;
201}
202
203/// getSymbolStatus - get the status of a symbol
204enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const
205{
206  assert(pSymIdx < numOfSymbols());
207  return m_SymTab[pSymIdx]->status;
208}
209
210/// setSymbolStatus - set the status of a symbol
211void Archive::setSymbolStatus(size_t pSymIdx,
212                              enum Archive::Symbol::Status pStatus)
213{
214  assert(pSymIdx < numOfSymbols());
215  m_SymTab[pSymIdx]->status = pStatus;
216}
217
218/// getStrTable - get the extended name table
219std::string& Archive::getStrTable()
220{
221  return m_StrTab;
222}
223
224/// getStrTable - get the extended name table
225const std::string& Archive::getStrTable() const
226{
227  return m_StrTab;
228}
229
230