PageRenderTime 401ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/frameworks/compile/mclinker/lib/CodeGen/SectLinker.cpp

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
C++ | 404 lines | 260 code | 64 blank | 80 comment | 34 complexity | e133149e5cc8e548b50e544aa72da032 MD5 | raw file
  1. //===- SectLinker.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. //
  10. // This file implements the SectLinker class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include <mcld/Support/FileHandle.h>
  14. #include <mcld/MC/InputTree.h>
  15. #include <mcld/MC/MCLDDriver.h>
  16. #include <mcld/Support/FileSystem.h>
  17. #include <mcld/Support/MsgHandling.h>
  18. #include <mcld/Support/FileHandle.h>
  19. #include <mcld/Support/raw_ostream.h>
  20. #include <mcld/Support/MemoryAreaFactory.h>
  21. #include <mcld/Support/DerivedPositionDependentOptions.h>
  22. #include <mcld/Target/TargetLDBackend.h>
  23. #include <mcld/CodeGen/SectLinker.h>
  24. #include <mcld/CodeGen/SectLinkerOption.h>
  25. #include <llvm/Module.h>
  26. #include <algorithm>
  27. #include <stack>
  28. #include <string>
  29. using namespace mcld;
  30. using namespace llvm;
  31. //===----------------------------------------------------------------------===//
  32. // Forward declarations
  33. char SectLinker::m_ID = 0;
  34. static bool CompareOption(const PositionDependentOption* X,
  35. const PositionDependentOption* Y);
  36. //===----------------------------------------------------------------------===//
  37. // SectLinker
  38. SectLinker::SectLinker(SectLinkerOption &pOption,
  39. TargetLDBackend& pLDBackend)
  40. : MachineFunctionPass(m_ID),
  41. m_pOption(&pOption),
  42. m_pLDBackend(&pLDBackend),
  43. m_pLDDriver(NULL),
  44. m_pMemAreaFactory(NULL)
  45. {
  46. m_pMemAreaFactory = new MemoryAreaFactory(32);
  47. }
  48. SectLinker::~SectLinker()
  49. {
  50. delete m_pLDDriver;
  51. // FIXME: current implementation can not change the order of delete.
  52. //
  53. // Instance of TargetLDBackend was created outside and is not managed by
  54. // SectLinker. It should not be destroyed here and by SectLinker. However, in
  55. // order to follow the LLVM convention - that is, the pass manages all the
  56. // objects it used during the processing, we destroy the object of
  57. // TargetLDBackend here.
  58. delete m_pLDBackend;
  59. delete m_pMemAreaFactory;
  60. }
  61. bool SectLinker::doInitialization(Module &pM)
  62. {
  63. MCLDInfo &info = m_pOption->info();
  64. // ----- convert position dependent options into tree of input files ----- //
  65. PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
  66. std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
  67. initializeInputTree(PosDepOpts);
  68. initializeInputOutput(info);
  69. // Now, all input arguments are prepared well, send it into MCLDDriver
  70. m_pLDDriver = new MCLDDriver(info, *m_pLDBackend, *memAreaFactory());
  71. return false;
  72. }
  73. bool SectLinker::doFinalization(Module &pM)
  74. {
  75. const MCLDInfo &info = m_pOption->info();
  76. // 2. - initialize MCLinker
  77. if (!m_pLDDriver->initMCLinker())
  78. return true;
  79. // 3. - initialize output's standard sections
  80. if (!m_pLDDriver->initStdSections())
  81. return true;
  82. // 4. - normalize the input tree
  83. m_pLDDriver->normalize();
  84. if (info.options().trace()) {
  85. static int counter = 0;
  86. mcld::outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
  87. InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
  88. for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
  89. mcld::outs() << counter++ << " * " << (*input)->name();
  90. switch((*input)->type()) {
  91. case Input::Archive:
  92. mcld::outs() << "\tarchive\t(";
  93. break;
  94. case Input::Object:
  95. mcld::outs() << "\tobject\t(";
  96. break;
  97. case Input::DynObj:
  98. mcld::outs() << "\tshared\t(";
  99. break;
  100. case Input::Script:
  101. mcld::outs() << "\tscript\t(";
  102. break;
  103. case Input::External:
  104. mcld::outs() << "\textern\t(";
  105. break;
  106. default:
  107. unreachable(diag::err_cannot_trace_file) << (*input)->type()
  108. << (*input)->name()
  109. << (*input)->path();
  110. }
  111. mcld::outs() << (*input)->path() << ")\n";
  112. }
  113. }
  114. // 5. - check if we can do static linking and if we use split-stack.
  115. if (!m_pLDDriver->linkable())
  116. return true;
  117. // 6. - merge all sections
  118. if (!m_pLDDriver->mergeSections())
  119. return true;
  120. // 7. - add standard symbols and target-dependent symbols
  121. // m_pLDDriver->addUndefSymbols();
  122. if (!m_pLDDriver->addStandardSymbols() ||
  123. !m_pLDDriver->addTargetSymbols())
  124. return true;
  125. // 8. - read all relocation entries from input files
  126. m_pLDDriver->readRelocations();
  127. // 9. - pre-layout
  128. m_pLDDriver->prelayout();
  129. // 10. - linear layout
  130. m_pLDDriver->layout();
  131. // 10.b - post-layout (create segment, instruction relaxing)
  132. m_pLDDriver->postlayout();
  133. // 11. - finalize symbol value
  134. m_pLDDriver->finalizeSymbolValue();
  135. // 12. - apply relocations
  136. m_pLDDriver->relocation();
  137. // 13. - write out output
  138. m_pLDDriver->emitOutput();
  139. // 14. - post processing
  140. m_pLDDriver->postProcessing();
  141. return false;
  142. }
  143. bool SectLinker::runOnMachineFunction(MachineFunction& pF)
  144. {
  145. // basically, linkers do nothing during function is generated.
  146. return false;
  147. }
  148. void SectLinker::initializeInputOutput(MCLDInfo &pLDInfo)
  149. {
  150. // ----- initialize output file ----- //
  151. FileHandle::Permission perm;
  152. if (Output::Object == pLDInfo.output().type())
  153. perm = 0544;
  154. else
  155. perm = 0755;
  156. MemoryArea* out_area = memAreaFactory()->produce(pLDInfo.output().path(),
  157. FileHandle::ReadWrite,
  158. perm);
  159. if (!out_area->handler()->isGood()) {
  160. // make sure output is openend successfully.
  161. fatal(diag::err_cannot_open_output_file) << pLDInfo.output().name()
  162. << pLDInfo.output().path();
  163. }
  164. pLDInfo.output().setMemArea(out_area);
  165. pLDInfo.output().setContext(pLDInfo.contextFactory().produce());
  166. // ----- initialize input files ----- //
  167. InputTree::dfs_iterator input, inEnd = pLDInfo.inputs().dfs_end();
  168. for (input = pLDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
  169. // already got type - for example, bitcode
  170. if ((*input)->type() == Input::Script ||
  171. (*input)->type() == Input::Object ||
  172. (*input)->type() == Input::DynObj ||
  173. (*input)->type() == Input::Archive)
  174. continue;
  175. MemoryArea *input_memory =
  176. memAreaFactory()->produce((*input)->path(), FileHandle::ReadOnly);
  177. if (input_memory->handler()->isGood()) {
  178. (*input)->setMemArea(input_memory);
  179. }
  180. else {
  181. error(diag::err_cannot_open_input) << (*input)->name() << (*input)->path();
  182. return;
  183. }
  184. LDContext *input_context =
  185. pLDInfo.contextFactory().produce((*input)->path());
  186. (*input)->setContext(input_context);
  187. }
  188. }
  189. void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
  190. {
  191. if (pPosDepOptions.empty())
  192. fatal(diag::err_no_inputs);
  193. MCLDInfo &info = m_pOption->info();
  194. PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
  195. if (1 == pPosDepOptions.size() &&
  196. ((*option)->type() != PositionDependentOption::INPUT_FILE &&
  197. (*option)->type() != PositionDependentOption::NAMESPEC) &&
  198. (*option)->type() != PositionDependentOption::BITCODE) {
  199. // if we only have one positional options, and the option is
  200. // not an input file, then emit error message.
  201. fatal(diag::err_no_inputs);
  202. }
  203. // ----- Input tree insertion algorithm ----- //
  204. // The type of the previsou node indicates the direction of the current
  205. // insertion.
  206. //
  207. // root : the parent node who being inserted.
  208. // mover : the direcion of current movement.
  209. //
  210. // for each positional options:
  211. // insert the options in current root.
  212. // calculate the next movement
  213. // Initialization
  214. InputTree::Mover *move = &InputTree::Downward;
  215. InputTree::iterator root = info.inputs().root();
  216. PositionDependentOptions::const_iterator optionEnd = pPosDepOptions.end();
  217. std::stack<InputTree::iterator> returnStack;
  218. while (option != optionEnd ) {
  219. switch ((*option)->type()) {
  220. /** bitcode **/
  221. case PositionDependentOption::BITCODE: {
  222. const BitcodeOption *bitcode_option =
  223. static_cast<const BitcodeOption*>(*option);
  224. // threat bitcode as an external IR in this version.
  225. info.inputs().insert(root, *move,
  226. bitcode_option->path()->native(),
  227. *(bitcode_option->path()),
  228. Input::External);
  229. info.setBitcode(**root);
  230. // move root on the new created node.
  231. move->move(root);
  232. // the next file is appended after bitcode file.
  233. move = &InputTree::Afterward;
  234. break;
  235. }
  236. /** input object file **/
  237. case PositionDependentOption::INPUT_FILE: {
  238. const InputFileOption *input_file_option =
  239. static_cast<const InputFileOption*>(*option);
  240. info.inputs().insert(root, *move,
  241. input_file_option->path()->native(),
  242. *(input_file_option->path()));
  243. // move root on the new created node.
  244. move->move(root);
  245. // the next file is appended after object file.
  246. move = &InputTree::Afterward;
  247. break;
  248. }
  249. /** -lnamespec **/
  250. case PositionDependentOption::NAMESPEC: {
  251. sys::fs::Path* path = NULL;
  252. const NamespecOption *namespec_option =
  253. static_cast<const NamespecOption*>(*option);
  254. // find out the real path of the namespec.
  255. if (info.attrFactory().constraint().isSharedSystem()) {
  256. // In the system with shared object support, we can find both archive
  257. // and shared object.
  258. if (info.attrFactory().last().isStatic()) {
  259. // with --static, we must search an archive.
  260. path = info.options().directories().find(namespec_option->namespec(),
  261. Input::Archive);
  262. }
  263. else {
  264. // otherwise, with --Bdynamic, we can find either an archive or a
  265. // shared object.
  266. path = info.options().directories().find(namespec_option->namespec(),
  267. Input::DynObj);
  268. }
  269. }
  270. else {
  271. // In the system without shared object support, we only look for an
  272. // archive.
  273. path = info.options().directories().find(namespec_option->namespec(),
  274. Input::Archive);
  275. }
  276. if (NULL == path)
  277. fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();
  278. info.inputs().insert(root, *move,
  279. namespec_option->namespec(),
  280. *path);
  281. // iterate root on the new created node.
  282. move->move(root);
  283. // the file after a namespec must be appended afterward.
  284. move = &InputTree::Afterward;
  285. break;
  286. }
  287. /** start group **/
  288. case PositionDependentOption::START_GROUP:
  289. info.inputs().enterGroup(root, *move);
  290. move->move(root);
  291. returnStack.push(root);
  292. move = &InputTree::Downward;
  293. break;
  294. /** end group **/
  295. case PositionDependentOption::END_GROUP:
  296. root = returnStack.top();
  297. returnStack.pop();
  298. move = &InputTree::Afterward;
  299. break;
  300. case PositionDependentOption::WHOLE_ARCHIVE:
  301. info.attrFactory().last().setWholeArchive();
  302. break;
  303. case PositionDependentOption::NO_WHOLE_ARCHIVE:
  304. info.attrFactory().last().unsetWholeArchive();
  305. break;
  306. case PositionDependentOption::AS_NEEDED:
  307. info.attrFactory().last().setAsNeeded();
  308. break;
  309. case PositionDependentOption::NO_AS_NEEDED:
  310. info.attrFactory().last().unsetAsNeeded();
  311. break;
  312. case PositionDependentOption::ADD_NEEDED:
  313. info.attrFactory().last().setAddNeeded();
  314. break;
  315. case PositionDependentOption::NO_ADD_NEEDED:
  316. info.attrFactory().last().unsetAddNeeded();
  317. break;
  318. case PositionDependentOption::BSTATIC:
  319. info.attrFactory().last().setStatic();
  320. break;
  321. case PositionDependentOption::BDYNAMIC:
  322. info.attrFactory().last().setDynamic();
  323. break;
  324. default:
  325. fatal(diag::err_cannot_identify_option) << (*option)->position()
  326. << (uint32_t)(*option)->type();
  327. } // end of switch
  328. ++option;
  329. } // end of while
  330. if (!returnStack.empty()) {
  331. report_fatal_error("no matched --start-group and --end-group");
  332. }
  333. }
  334. //===----------------------------------------------------------------------===//
  335. // Non-member functions
  336. static bool CompareOption(const PositionDependentOption* X,
  337. const PositionDependentOption* Y)
  338. {
  339. return (X->position() < Y->position());
  340. }