1 //===- ScriptFile.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/Script/ScriptFile.h"
10 
11 #include "mcld/ADT/HashEntry.h"
12 #include "mcld/ADT/HashTable.h"
13 #include "mcld/ADT/StringHash.h"
14 #include "mcld/Script/AssertCmd.h"
15 #include "mcld/Script/EntryCmd.h"
16 #include "mcld/Script/GroupCmd.h"
17 #include "mcld/Script/InputCmd.h"
18 #include "mcld/Script/Operand.h"
19 #include "mcld/Script/OutputArchCmd.h"
20 #include "mcld/Script/OutputCmd.h"
21 #include "mcld/Script/OutputFormatCmd.h"
22 #include "mcld/Script/RpnExpr.h"
23 #include "mcld/Script/ScriptCommand.h"
24 #include "mcld/Script/SearchDirCmd.h"
25 #include "mcld/Script/SectionsCmd.h"
26 #include "mcld/Script/StringList.h"
27 #include "mcld/Script/StrToken.h"
28 #include "mcld/MC/Input.h"
29 #include "mcld/MC/InputBuilder.h"
30 #include "mcld/Support/MemoryArea.h"
31 #include "mcld/InputTree.h"
32 
33 #include <llvm/Support/Casting.h>
34 #include <llvm/Support/ManagedStatic.h>
35 
36 #include <cassert>
37 
38 namespace mcld {
39 
40 typedef HashEntry<std::string, void*, hash::StringCompare<std::string> >
41     ParserStrEntry;
42 typedef HashTable<ParserStrEntry,
43                   hash::StringHash<hash::DJB>,
44                   EntryFactory<ParserStrEntry> > ParserStrPool;
45 static llvm::ManagedStatic<ParserStrPool> g_ParserStrPool;
46 
47 //===----------------------------------------------------------------------===//
48 // ScriptFile
49 //===----------------------------------------------------------------------===//
ScriptFile(Kind pKind,Input & pInput,InputBuilder & pBuilder)50 ScriptFile::ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder)
51     : m_Kind(pKind),
52       m_Input(pInput),
53       m_Name(pInput.path().native()),
54       m_pInputTree(NULL),
55       m_Builder(pBuilder),
56       m_bHasSectionsCmd(false),
57       m_bInSectionsCmd(false),
58       m_bInOutputSectDesc(false),
59       m_pRpnExpr(NULL),
60       m_pStringList(NULL),
61       m_bAsNeeded(false) {
62   // FIXME: move creation of input tree out of ScriptFile.
63   m_pInputTree = new InputTree();
64 }
65 
~ScriptFile()66 ScriptFile::~ScriptFile() {
67   for (iterator it = begin(), ie = end(); it != ie; ++it) {
68     if (*it != NULL)
69       delete *it;
70   }
71   if (m_pInputTree != NULL)
72     delete m_pInputTree;
73 }
74 
dump() const75 void ScriptFile::dump() const {
76   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
77     (*it)->dump();
78 }
79 
activate(Module & pModule)80 void ScriptFile::activate(Module& pModule) {
81   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
82     (*it)->activate(pModule);
83 }
84 
addEntryPoint(const std::string & pSymbol)85 void ScriptFile::addEntryPoint(const std::string& pSymbol) {
86   EntryCmd* entry = new EntryCmd(pSymbol);
87 
88   if (m_bInSectionsCmd) {
89     assert(!m_CommandQueue.empty());
90     SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
91     sections->push_back(entry);
92   } else {
93     m_CommandQueue.push_back(entry);
94   }
95 }
96 
addOutputFormatCmd(const std::string & pName)97 void ScriptFile::addOutputFormatCmd(const std::string& pName) {
98   m_CommandQueue.push_back(new OutputFormatCmd(pName));
99 }
100 
addOutputFormatCmd(const std::string & pDefault,const std::string & pBig,const std::string & pLittle)101 void ScriptFile::addOutputFormatCmd(const std::string& pDefault,
102                                     const std::string& pBig,
103                                     const std::string& pLittle) {
104   m_CommandQueue.push_back(new OutputFormatCmd(pDefault, pBig, pLittle));
105 }
106 
addInputCmd(StringList & pStringList,ObjectReader & pObjectReader,ArchiveReader & pArchiveReader,DynObjReader & pDynObjReader,const LinkerConfig & pConfig)107 void ScriptFile::addInputCmd(StringList& pStringList,
108                              ObjectReader& pObjectReader,
109                              ArchiveReader& pArchiveReader,
110                              DynObjReader& pDynObjReader,
111                              const LinkerConfig& pConfig) {
112   m_CommandQueue.push_back(new InputCmd(pStringList,
113                                         *m_pInputTree,
114                                         m_Builder,
115                                         pObjectReader,
116                                         pArchiveReader,
117                                         pDynObjReader,
118                                         pConfig));
119 }
120 
addGroupCmd(StringList & pStringList,GroupReader & pGroupReader,const LinkerConfig & pConfig)121 void ScriptFile::addGroupCmd(StringList& pStringList,
122                              GroupReader& pGroupReader,
123                              const LinkerConfig& pConfig) {
124   m_CommandQueue.push_back(new GroupCmd(
125       pStringList, *m_pInputTree, m_Builder, pGroupReader, pConfig));
126 }
127 
addOutputCmd(const std::string & pFileName)128 void ScriptFile::addOutputCmd(const std::string& pFileName) {
129   m_CommandQueue.push_back(new OutputCmd(pFileName));
130 }
131 
addSearchDirCmd(const std::string & pPath)132 void ScriptFile::addSearchDirCmd(const std::string& pPath) {
133   m_CommandQueue.push_back(new SearchDirCmd(pPath));
134 }
135 
addOutputArchCmd(const std::string & pArch)136 void ScriptFile::addOutputArchCmd(const std::string& pArch) {
137   m_CommandQueue.push_back(new OutputArchCmd(pArch));
138 }
139 
addAssertCmd(RpnExpr & pRpnExpr,const std::string & pMessage)140 void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage) {
141   m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage));
142 }
143 
addAssignment(const std::string & pSymbolName,RpnExpr & pRpnExpr,Assignment::Type pType)144 void ScriptFile::addAssignment(const std::string& pSymbolName,
145                                RpnExpr& pRpnExpr,
146                                Assignment::Type pType) {
147   if (m_bInSectionsCmd) {
148     assert(!m_CommandQueue.empty());
149     SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
150     if (m_bInOutputSectDesc) {
151       assert(!sections->empty());
152       OutputSectDesc* output_desc =
153           llvm::cast<OutputSectDesc>(sections->back());
154       output_desc->push_back(new Assignment(Assignment::INPUT_SECTION,
155                                             pType,
156                                             *(SymOperand::create(pSymbolName)),
157                                             pRpnExpr));
158     } else {
159       sections->push_back(new Assignment(Assignment::OUTPUT_SECTION,
160                                          pType,
161                                          *(SymOperand::create(pSymbolName)),
162                                          pRpnExpr));
163     }
164   } else {
165     m_CommandQueue.push_back(new Assignment(Assignment::OUTSIDE_SECTIONS,
166                                             pType,
167                                             *(SymOperand::create(pSymbolName)),
168                                             pRpnExpr));
169   }
170 }
171 
hasSectionsCmd() const172 bool ScriptFile::hasSectionsCmd() const {
173   return m_bHasSectionsCmd;
174 }
175 
enterSectionsCmd()176 void ScriptFile::enterSectionsCmd() {
177   m_bHasSectionsCmd = true;
178   m_bInSectionsCmd = true;
179   m_CommandQueue.push_back(new SectionsCmd());
180 }
181 
leaveSectionsCmd()182 void ScriptFile::leaveSectionsCmd() {
183   m_bInSectionsCmd = false;
184 }
185 
enterOutputSectDesc(const std::string & pName,const OutputSectDesc::Prolog & pProlog)186 void ScriptFile::enterOutputSectDesc(const std::string& pName,
187                                      const OutputSectDesc::Prolog& pProlog) {
188   assert(!m_CommandQueue.empty());
189   assert(m_bInSectionsCmd);
190   SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
191   sections->push_back(new OutputSectDesc(pName, pProlog));
192 
193   m_bInOutputSectDesc = true;
194 }
195 
leaveOutputSectDesc(const OutputSectDesc::Epilog & pEpilog)196 void ScriptFile::leaveOutputSectDesc(const OutputSectDesc::Epilog& pEpilog) {
197   assert(!m_CommandQueue.empty());
198   assert(m_bInSectionsCmd);
199   SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
200 
201   assert(!sections->empty() && m_bInOutputSectDesc);
202   OutputSectDesc* output_desc = llvm::cast<OutputSectDesc>(sections->back());
203   output_desc->setEpilog(pEpilog);
204 
205   m_bInOutputSectDesc = false;
206 }
207 
addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,const InputSectDesc::Spec & pSpec)208 void ScriptFile::addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,
209                                   const InputSectDesc::Spec& pSpec) {
210   assert(!m_CommandQueue.empty());
211   assert(m_bInSectionsCmd);
212   SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
213 
214   assert(!sections->empty() && m_bInOutputSectDesc);
215   OutputSectDesc* output_sect = llvm::cast<OutputSectDesc>(sections->back());
216 
217   output_sect->push_back(new InputSectDesc(pPolicy, pSpec, *output_sect));
218 }
219 
createRpnExpr()220 RpnExpr* ScriptFile::createRpnExpr() {
221   m_pRpnExpr = RpnExpr::create();
222   return m_pRpnExpr;
223 }
224 
createStringList()225 StringList* ScriptFile::createStringList() {
226   m_pStringList = StringList::create();
227   return m_pStringList;
228 }
229 
setAsNeeded(bool pEnable)230 void ScriptFile::setAsNeeded(bool pEnable) {
231   m_bAsNeeded = pEnable;
232 }
233 
createParserStr(const char * pText,size_t pLength)234 const std::string& ScriptFile::createParserStr(const char* pText,
235                                                size_t pLength) {
236   bool exist = false;
237   ParserStrEntry* entry =
238       g_ParserStrPool->insert(std::string(pText, pLength), exist);
239   return entry->key();
240 }
241 
clearParserStrPool()242 void ScriptFile::clearParserStrPool() {
243   g_ParserStrPool->clear();
244 }
245 
246 }  // namespace mcld
247