Archive.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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/InputBuilder.h>
11#include <mcld/MC/MCLDInput.h>
12#include <mcld/MC/AttributeSet.h>
13#include <mcld/MC/ContextFactory.h>
14#include <llvm/ADT/StringRef.h>
15#include <mcld/Support/MemoryAreaFactory.h>
16#include <mcld/Support/MsgHandling.h>
17
18using namespace mcld;
19
20//===----------------------------------------------------------------------===//
21// Archive
22const char   Archive::MAGIC[]            = "!<arch>\n";
23const char   Archive::THIN_MAGIC[]       = "!<thin>\n";
24const size_t Archive::MAGIC_LEN          = sizeof(Archive::MAGIC) - 1;
25const char   Archive::SVR4_SYMTAB_NAME[] = "/               ";
26const char   Archive::STRTAB_NAME[]      = "//              ";
27const char   Archive::PAD[]              = "\n";
28const char   Archive::MEMBER_MAGIC[]     = "`\n";
29
30Archive::Archive(Input& pInputFile, InputBuilder& pBuilder)
31 : m_ArchiveFile(pInputFile),
32   m_pInputTree(NULL),
33   m_SymbolFactory(32),
34   m_Builder(pBuilder)
35{
36  // FIXME: move creation of input tree out of Archive.
37  m_pInputTree = new InputTree();
38}
39
40Archive::~Archive()
41{
42  delete m_pInputTree;
43}
44
45/// getARFile - get the Input& of the archive file
46Input& Archive::getARFile()
47{
48  return m_ArchiveFile;
49}
50
51/// getARFile - get the Input& of the archive file
52const Input& Archive::getARFile() const
53{
54  return m_ArchiveFile;
55}
56
57/// inputs - get the input tree built from this archive
58InputTree& Archive::inputs()
59{
60  return *m_pInputTree;
61}
62
63/// inputs - get the input tree built from this archive
64const InputTree& Archive::inputs() const
65{
66  return *m_pInputTree;
67}
68
69/// getObjectMemberMap - get the map that contains the included object files
70Archive::ObjectMemberMapType& Archive::getObjectMemberMap()
71{
72  return m_ObjectMemberMap;
73}
74
75/// getObjectMemberMap - get the map that contains the included object files
76const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const
77{
78  return m_ObjectMemberMap;
79}
80
81/// numOfObjectMember - return the number of included object files
82size_t Archive::numOfObjectMember() const
83{
84  return m_ObjectMemberMap.numOfEntries();
85}
86
87/// addObjectMember - add a object in the object member map
88/// @param pFileOffset - file offset in symtab represents a object file
89/// @param pIter - the iterator in the input tree built from this archive
90bool Archive::addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter)
91{
92  bool exist;
93  ObjectMemberEntryType* entry = m_ObjectMemberMap.insert(pFileOffset, exist);
94  if (!exist)
95    entry->setValue(pIter);
96  return !exist;
97}
98
99/// hasObjectMember - check if a object file is included or not
100/// @param pFileOffset - file offset in symtab represents a object file
101bool Archive::hasObjectMember(uint32_t pFileOffset) const
102{
103  return (m_ObjectMemberMap.find(pFileOffset) != m_ObjectMemberMap.end());
104}
105
106/// getArchiveMemberMap - get the map that contains the included archive files
107Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap()
108{
109  return m_ArchiveMemberMap;
110}
111
112/// getArchiveMemberMap - get the map that contains the included archive files
113const Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() const
114{
115  return m_ArchiveMemberMap;
116}
117
118/// addArchiveMember - add an archive in the archive member map
119/// @param pName    - the name of the new archive member
120/// @param pLastPos - this records the point to insert the next node in the
121///                   subtree of this archive member
122/// @param pMove    - this records the direction to insert the next node in the
123///                   subtree of this archive member
124bool Archive::addArchiveMember(const llvm::StringRef& pName,
125                               InputTree::iterator pLastPos,
126                               InputTree::Mover* pMove)
127{
128  bool exist;
129  ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist);
130  if (!exist) {
131    ArchiveMember& ar = entry->value();
132    ar.file = *pLastPos;
133    ar.lastPos = pLastPos;
134    ar.move = pMove;
135  }
136  return !exist;
137}
138
139/// hasArchiveMember - check if an archive file is included or not
140bool Archive::hasArchiveMember(const llvm::StringRef& pName) const
141{
142  return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end());
143}
144
145/// getArchiveMember - get a archive member
146Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName)
147{
148  ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName);
149  if (it != m_ArchiveMemberMap.end())
150    return &(it.getEntry()->value());
151  return NULL;
152}
153
154/// getSymbolTable - get the symtab
155Archive::SymTabType& Archive::getSymbolTable()
156{
157  return m_SymTab;
158}
159
160/// getSymbolTable - get the symtab
161const Archive::SymTabType& Archive::getSymbolTable() const
162{
163  return m_SymTab;
164}
165
166/// setSymTabSize - set the memory size of symtab
167void Archive::setSymTabSize(size_t pSize)
168{
169  m_SymTabSize = pSize;
170}
171
172/// getSymTabSize - get the memory size of symtab
173size_t Archive::getSymTabSize() const
174{
175  return m_SymTabSize;
176}
177
178/// numOfSymbols - return the number of symbols in symtab
179size_t Archive::numOfSymbols() const
180{
181  return m_SymTab.size();
182}
183
184/// addSymbol - add a symtab entry to symtab
185/// @param pName - symbol name
186/// @param pFileOffset - file offset in symtab represents a object file
187void Archive::addSymbol(const char* pName,
188                        uint32_t pFileOffset,
189                        enum Archive::Symbol::Status pStatus)
190{
191  Symbol* entry = m_SymbolFactory.allocate();
192  new (entry) Symbol(pName, pFileOffset, pStatus);
193  m_SymTab.push_back(entry);
194}
195
196/// getSymbolName - get the symbol name with the given index
197const std::string& Archive::getSymbolName(size_t pSymIdx) const
198{
199  assert(pSymIdx < numOfSymbols());
200  return m_SymTab[pSymIdx]->name;
201}
202
203/// getObjFileOffset - get the file offset that represent a object file
204uint32_t Archive::getObjFileOffset(size_t pSymIdx) const
205{
206  assert(pSymIdx < numOfSymbols());
207  return m_SymTab[pSymIdx]->fileOffset;
208}
209
210/// getSymbolStatus - get the status of a symbol
211enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const
212{
213  assert(pSymIdx < numOfSymbols());
214  return m_SymTab[pSymIdx]->status;
215}
216
217/// setSymbolStatus - set the status of a symbol
218void Archive::setSymbolStatus(size_t pSymIdx,
219                              enum Archive::Symbol::Status pStatus)
220{
221  assert(pSymIdx < numOfSymbols());
222  m_SymTab[pSymIdx]->status = pStatus;
223}
224
225/// getStrTable - get the extended name table
226std::string& Archive::getStrTable()
227{
228  return m_StrTab;
229}
230
231/// getStrTable - get the extended name table
232const std::string& Archive::getStrTable() const
233{
234  return m_StrTab;
235}
236
237/// hasStrTable()
238bool Archive::hasStrTable() const
239{
240  return (m_StrTab.size() > 0);
241}
242
243/// getMemberFile - get the member file in an archive member
244/// @param pArchiveFile - Input reference of the archive member
245/// @param pIsThinAR    - denote the archive menber is a Thin Archive or not
246/// @param pName        - the name of the member file we want to get
247/// @param pPath        - the path of the member file
248/// @param pFileOffset  - the file offset of the member file in a regular AR
249/// FIXME: maybe we should not construct input file here
250Input* Archive::getMemberFile(Input& pArchiveFile,
251                              bool isThinAR,
252                              const std::string& pName,
253                              const sys::fs::Path& pPath,
254                              off_t pFileOffset)
255{
256  Input* member = NULL;
257  if (!isThinAR) {
258    member = m_Builder.createInput(pName, pPath, Input::Unknown, pFileOffset);
259    assert(member != NULL);
260    member->setMemArea(pArchiveFile.memArea());
261    m_Builder.setContext(*member);
262  }
263  else {
264    member = m_Builder.createInput(pName, pPath, Input::Unknown);
265    assert(member != NULL);
266    if (!m_Builder.setMemory(*member, FileHandle::ReadOnly)) {
267      error(diag::err_cannot_open_input) << member->name() << member->path();
268      return NULL;
269    }
270    m_Builder.setContext(*member);
271  }
272  return member;
273}
274
275