• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- TestLinker.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 "TestLinker.h"
10 
11 #include <iostream>
12 
13 #include <llvm/Support/TargetSelect.h>
14 
15 #include <mcld/LD/TextDiagnosticPrinter.h>
16 #include <mcld/MC/InputTree.h>
17 #include <mcld/MC/MCLDDirectory.h>
18 #include <mcld/Target/TargetLDBackend.h>
19 #include <mcld/Support/RegionFactory.h>
20 #include <mcld/Support/TargetSelect.h>
21 #include <mcld/Support/MsgHandling.h>
22 #include <mcld/Support/raw_ostream.h>
23 #include <mcld/Support/SystemUtils.h>
24 #include <mcld/Support/MemoryAreaFactory.h>
25 
26 using namespace std;
27 using namespace mcld;
28 using namespace mcld::sys::fs;
29 using namespace mcld::test;
30 
31 //===----------------------------------------------------------------------===//
32 // TestLinker
33 //===----------------------------------------------------------------------===//
TestLinker()34 TestLinker::TestLinker()
35   : m_pTarget(NULL), m_pDriver(NULL), m_pInfo(NULL), m_pDiagLineInfo(NULL),
36     m_pDiagPrinter(NULL), m_pBackend(NULL), m_pRegionFactory(NULL),
37     m_pMemAreaFactory(NULL) {
38 }
39 
~TestLinker()40 TestLinker::~TestLinker()
41 {
42   std::list<mcld::FileHandle*>::iterator file, fEnd = m_FileHandleList.end();
43   for (file = m_FileHandleList.begin(); file != fEnd; ++file)
44     delete (*file);
45 
46   std::list<mcld::MemoryArea*>::iterator mem, mEnd = m_MemAreaList.end() ;
47   for (mem = m_MemAreaList.begin(); mem != mEnd; ++mem)
48     delete (*mem);
49 
50   delete m_pDriver;
51   delete m_pInfo;
52   delete m_pDiagLineInfo;
53   delete m_pDiagPrinter;
54   delete m_pBackend;
55   delete m_pRegionFactory;
56   delete m_pMemAreaFactory;
57 }
58 
initialize(const std::string & pTriple)59 bool TestLinker::initialize(const std::string &pTriple)
60 {
61   bool is_initialized = false;
62 
63   if (is_initialized)
64     return false;
65 
66   // initilaize all llvm::Target and mcld::Target
67   llvm::InitializeAllTargets();
68   llvm::InitializeAllAsmPrinters();
69   llvm::InitializeAllAsmParsers();
70   llvm::InitializeAllTargetMCs();
71   mcld::InitializeAllTargets();
72   mcld::InitializeAllDiagnostics();
73 
74   // create mcld::MCLDInfo
75   m_pInfo = new MCLDInfo(pTriple, 1, 32);
76   m_Root = m_pInfo->inputs().root();
77 
78   // create mcld::RegionFactory
79   m_pRegionFactory = new mcld::RegionFactory(32);
80 
81   // specify mcld::Target
82   std::string error;
83   m_pTarget = mcld::TargetRegistry::lookupTarget(pTriple, error);
84   if (NULL == m_pTarget) {
85     fatal(diag::fatal_cannot_init_target) << pTriple << error;
86     return false;
87   }
88 
89   // create mcld::DiagnosticEngine
90   m_pDiagLineInfo = m_pTarget->createDiagnosticLineInfo(*m_pTarget, pTriple);
91   if (NULL == m_pDiagLineInfo) {
92     fatal(diag::fatal_cannot_init_lineinfo) << pTriple;
93     return false;
94   }
95 
96   m_pDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *m_pInfo);
97 
98   mcld::InitializeDiagnosticEngine(*m_pInfo, m_pDiagLineInfo, m_pDiagPrinter);
99 
100   // create mcld::TargetLDBackend
101   m_pBackend = m_pTarget->createLDBackend(pTriple);
102   if (NULL == m_pBackend) {
103     fatal(diag::fatal_cannot_init_backend) << pTriple;
104     return false;
105   }
106 
107   m_pMemAreaFactory = new MemoryAreaFactory(32);
108 
109   m_pDriver = new mcld::MCLDDriver(*m_pInfo, *m_pBackend, *m_pMemAreaFactory);
110   m_pDriver->initMCLinker();
111 
112   is_initialized = true;
113   return true;
114 }
115 
addSearchDir(const std::string & pDirPath)116 void TestLinker::addSearchDir(const std::string &pDirPath)
117 {
118   assert(NULL != m_pInfo && "initialize() must be called before addSearchDir");
119   assert(!m_pInfo->options().sysroot().empty() &&
120          "must setSysRoot before addSearchDir");
121 
122   mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
123 
124   if (sd->isInSysroot()) {
125     sd->setSysroot(m_pInfo->options().sysroot());
126   }
127 
128   if (exists(sd->path()) && is_directory(sd->path())) {
129     m_pInfo->options().directories().add(*sd);
130   } else {
131     mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
132   }
133 }
134 
setSysRoot(const mcld::sys::fs::Path & pPath)135 void TestLinker::setSysRoot(const mcld::sys::fs::Path &pPath)
136 {
137   assert(NULL != m_pInfo && "initialize() must be called before setSysRoot");
138   m_pInfo->options().setSysroot(pPath);
139 }
140 
addObject(const std::string & pPath)141 void TestLinker::addObject(const std::string &pPath)
142 {
143   mcld::Input* input = m_pInfo->inputFactory().produce(pPath, pPath,
144                                                        mcld::Input::Unknown);
145 
146   m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
147 
148   advanceRoot();
149 
150   mcld::FileHandle* handler = new mcld::FileHandle();
151   m_FileHandleList.push_back(handler);
152   if (!handler->open(pPath, mcld::FileHandle::ReadOnly)) {
153     mcld::error(mcld::diag::err_cannot_open_file)
154                                       << pPath
155                                       << mcld::sys::strerror(handler->error());
156   }
157 
158   mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
159   input->setMemArea(input_memory);
160   m_MemAreaList.push_back(input_memory);
161 
162   mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
163   input->setContext(context);
164 }
165 
addObject(void * pMemBuffer,size_t pSize)166 void TestLinker::addObject(void* pMemBuffer, size_t pSize)
167 {
168   mcld::Input* input = m_pInfo->inputFactory().produce("memory object", "NAN",
169                                                        mcld::Input::Unknown);
170 
171   m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
172 
173   advanceRoot();
174 
175   mcld::Space* space = new mcld::Space(mcld::Space::EXTERNAL, pMemBuffer, pSize);
176   mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *space);
177   input->setMemArea(input_memory);
178   m_MemAreaList.push_back(input_memory);
179 
180   mcld::LDContext* context = m_pInfo->contextFactory().produce();
181   input->setContext(context);
182 }
183 
addObject(int pFileHandler)184 void TestLinker::addObject(int pFileHandler)
185 {
186   mcld::Input* input = m_pInfo->inputFactory().produce("handler object", "NAN",
187                                                        mcld::Input::Unknown);
188 
189   m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
190 
191   advanceRoot();
192 
193   mcld::FileHandle* handler = new mcld::FileHandle();
194   m_FileHandleList.push_back(handler);
195   handler->delegate(pFileHandler);
196 
197   mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
198   input->setMemArea(input_memory);
199   m_MemAreaList.push_back(input_memory);
200 
201   mcld::LDContext* context = m_pInfo->contextFactory().produce();
202   input->setContext(context);
203 }
204 
addNameSpec(const std::string & pNameSpec)205 void TestLinker::addNameSpec(const std::string &pNameSpec)
206 {
207   mcld::sys::fs::Path* path = NULL;
208   // find out the real path of the namespec.
209   if (m_pInfo->attrFactory().constraint().isSharedSystem()) {
210     // In the system with shared object support, we can find both archive
211     // and shared object.
212 
213     if (m_pInfo->attrFactory().last().isStatic()) {
214       // with --static, we must search an archive.
215       path = m_pInfo->options().directories().find(pNameSpec,
216                                                    mcld::Input::Archive);
217     }
218     else {
219       // otherwise, with --Bdynamic, we can find either an archive or a
220       // shared object.
221       path = m_pInfo->options().directories().find(pNameSpec,
222                                                    mcld::Input::DynObj);
223     }
224   }
225   else {
226     // In the system without shared object support, we only look for an
227     // archive.
228     path = m_pInfo->options().directories().find(pNameSpec,
229                                                  mcld::Input::Archive);
230   }
231 
232   if (NULL == path) {
233     mcld::fatal(diag::err_cannot_find_namespec) << pNameSpec;
234     return;
235   }
236 
237   mcld::Input* input = m_pInfo->inputFactory().produce(pNameSpec, *path,
238                                                        mcld::Input::Unknown);
239 
240   m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
241 
242   advanceRoot();
243 
244   mcld::FileHandle* handler = new mcld::FileHandle();
245   m_FileHandleList.push_back(handler);
246   if (!handler->open(*path, mcld::FileHandle::ReadOnly)) {
247     mcld::error(mcld::diag::err_cannot_open_file)
248                                       << *path
249                                       << mcld::sys::strerror(handler->error());
250   }
251 
252   mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
253   input->setMemArea(input_memory);
254   m_MemAreaList.push_back(input_memory);
255 
256   mcld::LDContext* context = m_pInfo->contextFactory().produce(*path);
257   input->setContext(context);
258 }
259 
setOutput(const std::string & pPath)260 bool TestLinker::setOutput(const std::string &pPath)
261 {
262   if (m_pInfo->output().hasContext())
263     return false;
264 
265   mcld::FileHandle* handler = new mcld::FileHandle();
266   m_FileHandleList.push_back(handler);
267   bool open_res = handler->open(pPath, mcld::FileHandle::ReadWrite |
268                                        mcld::FileHandle::Truncate |
269                                        mcld::FileHandle::Create,
270                                 mcld::FileHandle::Permission(0755));
271   if (!open_res) {
272     mcld::error(mcld::diag::err_cannot_open_file)
273                                       << pPath
274                                       << mcld::sys::strerror(handler->error());
275   }
276 
277   mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
278   m_pInfo->output().setMemArea(output_memory);
279   m_MemAreaList.push_back(output_memory);
280 
281   mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
282   m_pInfo->output().setContext(context);
283 
284   // FIXME: remove the initStdSections().
285   m_pDriver->initStdSections();
286   return true;
287 }
288 
setOutput(const sys::fs::Path & pPath)289 bool TestLinker::setOutput(const sys::fs::Path &pPath)
290 {
291   return setOutput(pPath.native());
292 }
293 
setOutput(int pFileHandler)294 bool TestLinker::setOutput(int pFileHandler)
295 {
296   if (m_pInfo->output().hasContext())
297     return false;
298 
299   mcld::FileHandle* handler = new mcld::FileHandle();
300   handler->delegate(pFileHandler);
301   m_FileHandleList.push_back(handler);
302 
303   mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
304   m_pInfo->output().setMemArea(output_memory);
305   m_MemAreaList.push_back(output_memory);
306 
307   mcld::LDContext* context = m_pInfo->contextFactory().produce();
308   m_pInfo->output().setContext(context);
309 
310   // FIXME: remove the initStdSections().
311   m_pDriver->initStdSections();
312   return true;
313 }
314 
advanceRoot()315 void TestLinker::advanceRoot()
316 {
317     if (m_Root.isRoot())
318       --m_Root;
319     else
320       ++m_Root;
321 }
322