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 14#include <mcld/ADT/BinTree.h> 15#include <mcld/CodeGen/SectLinker.h> 16#include <mcld/CodeGen/SectLinkerOption.h> 17#include <mcld/MC/MCLDInputTree.h> 18#include <mcld/MC/MCLDDriver.h> 19#include <mcld/Support/DerivedPositionDependentOptions.h> 20#include <mcld/Support/FileSystem.h> 21#include <mcld/Target/TargetLDBackend.h> 22 23#include <llvm/Module.h> 24#include <llvm/Support/ErrorHandling.h> 25#include <llvm/Support/raw_ostream.h> 26 27#include <algorithm> 28#include <stack> 29#include <string> 30 31using namespace mcld; 32using namespace llvm; 33 34//===----------------------------------------------------------------------===// 35// Forward declarations 36char SectLinker::m_ID = 0; 37static bool CompareOption(const PositionDependentOption* X, 38 const PositionDependentOption* Y); 39 40//===----------------------------------------------------------------------===// 41// SectLinker 42SectLinker::SectLinker(SectLinkerOption &pOption, 43 TargetLDBackend& pLDBackend) 44 : MachineFunctionPass(m_ID), 45 m_pOption(&pOption), 46 m_pLDBackend(&pLDBackend), 47 m_pLDDriver(NULL) { } 48 49SectLinker::~SectLinker() 50{ 51 delete m_pLDDriver; 52 // FIXME: current implementation can not change the order of delete. 53 // 54 // Instance of TargetLDBackend was created outside and is not managed by 55 // SectLinker. It should not be destroyed here and by SectLinker. However, in 56 // order to follow the LLVM convention - that is, the pass manages all the 57 // objects it used during the processing, we destroy the object of 58 // TargetLDBackend here. 59 delete m_pLDBackend; 60} 61 62bool SectLinker::doInitialization(Module &pM) 63{ 64 MCLDInfo &info = m_pOption->info(); 65 66 // setup the output 67 info.output().setContext(info.contextFactory().produce(info.output().path())); 68 69 int mode = (Output::Object == info.output().type())? 0544 : 0755; 70 info.output().setMemArea( 71 info.memAreaFactory().produce(info.output().path(), 72 O_RDWR | O_CREAT | O_TRUNC, 73 mode)); 74 75 // make sure output is openend successfully. 76 if (!info.output().hasMemArea()) 77 report_fatal_error("output is not given on the command line\n"); 78 79 if (!info.output().memArea()->isGood()) 80 report_fatal_error("can not open output file :"+info.output().path().native()); 81 82 // let the target override the target-specific parameters 83 addTargetOptions(pM, *m_pOption); 84 85 // ----- convert position dependent options into tree of input files ----- // 86 PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options(); 87 std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption); 88 initializeInputTree(PosDepOpts); 89 90 // Now, all input arguments are prepared well, send it into MCLDDriver 91 m_pLDDriver = new MCLDDriver(info, *m_pLDBackend); 92 93 return false; 94} 95 96bool SectLinker::doFinalization(Module &pM) 97{ 98 const MCLDInfo &info = m_pOption->info(); 99 100 // 3. - initialize output's standard segments and sections 101 if (!m_pLDDriver->initMCLinker()) 102 return true; 103 104 // 4. - normalize the input tree 105 m_pLDDriver->normalize(); 106 107 if (info.options().verbose()) { 108 outs() << "MCLinker (LLVM Sub-project) - "; 109 outs() << MCLDInfo::version(); 110 outs() << "\n"; 111 } 112 113 if (info.options().trace()) { 114 static int counter = 0; 115 outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n"; 116 InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end(); 117 for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) { 118 outs() << counter++ << " * " << (*input)->name(); 119 switch((*input)->type()) { 120 case Input::Archive: 121 outs() << "\tarchive\t("; 122 break; 123 case Input::Object: 124 outs() << "\tobject\t("; 125 break; 126 case Input::DynObj: 127 outs() << "\tshared\t("; 128 break; 129 case Input::Script: 130 outs() << "\tscript\t("; 131 break; 132 default: 133 report_fatal_error("** Trace a unsupported file. It must be an internal bug!"); 134 } 135 outs() << (*input)->path().c_str() << ")\n"; 136 } 137 } 138 139 // 5. - check if we can do static linking and if we use split-stack. 140 if (!m_pLDDriver->linkable()) 141 return true; 142 143 144 // 6. - read all sections 145 if (!m_pLDDriver->readSections() || 146 !m_pLDDriver->mergeSections()) 147 return true; 148 149 // 7. - read all symbol tables of input files and resolve them 150 if (!m_pLDDriver->readSymbolTables() || 151 !m_pLDDriver->mergeSymbolTables()) 152 return true; 153 154 // 7.a - add standard symbols and target-dependent symbols 155 // m_pLDDriver->addUndefSymbols(); 156 if (!m_pLDDriver->addStandardSymbols() || 157 !m_pLDDriver->addTargetSymbols()) 158 return true; 159 160 // 8. - read all relocation entries from input files 161 m_pLDDriver->readRelocations(); 162 163 // 9. - pre-layout 164 m_pLDDriver->prelayout(); 165 166 // 10. - linear layout 167 m_pLDDriver->layout(); 168 169 // 10.b - post-layout 170 m_pLDDriver->postlayout(); 171 172 // 11. - finalize symbol value 173 m_pLDDriver->finalizeSymbolValue(); 174 175 // 12. - apply relocations 176 m_pLDDriver->relocate(); 177 178 // 13. - write out output 179 m_pLDDriver->emitOutput(); 180 181 // 14. - post processing 182 m_pLDDriver->postProcessing(); 183 return false; 184} 185 186bool SectLinker::runOnMachineFunction(MachineFunction& pF) 187{ 188 // basically, linkers do nothing during function is generated. 189 return false; 190} 191 192void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const 193{ 194 if (pPosDepOptions.empty()) 195 return; 196 197 MCLDInfo &info = m_pOption->info(); 198 PositionDependentOptions::const_iterator cur_char = pPosDepOptions.begin(); 199 if (1 == pPosDepOptions.size() && 200 ((*cur_char)->type() != PositionDependentOption::INPUT_FILE && 201 (*cur_char)->type() != PositionDependentOption::NAMESPEC)) 202 return; 203 204 InputTree::Connector *prev_ward = &InputTree::Downward; 205 206 std::stack<InputTree::iterator> returnStack; 207 InputTree::iterator cur_node = info.inputs().root(); 208 209 PositionDependentOptions::const_iterator charEnd = pPosDepOptions.end(); 210 while (cur_char != charEnd ) { 211 switch ((*cur_char)->type()) { 212 case PositionDependentOption::BITCODE: { 213 // threat bitcode as a script in this version. 214 const BitcodeOption *bitcode_option = 215 static_cast<const BitcodeOption*>(*cur_char); 216 info.inputs().insert(cur_node, 217 *prev_ward, 218 bitcode_option->path()->native(), 219 *(bitcode_option->path()), 220 Input::Script); 221 info.setBitcode(**cur_node); 222 prev_ward->move(cur_node); 223 prev_ward = &InputTree::Afterward; 224 break; 225 } 226 case PositionDependentOption::INPUT_FILE: { 227 const InputFileOption *input_file_option = 228 static_cast<const InputFileOption*>(*cur_char); 229 info.inputs().insert(cur_node, 230 *prev_ward, 231 input_file_option->path()->native(), 232 *(input_file_option->path())); 233 prev_ward->move(cur_node); 234 prev_ward = &InputTree::Afterward; 235 break; 236 } 237 case PositionDependentOption::NAMESPEC: { 238 sys::fs::Path* path = 0; 239 const NamespecOption *namespec_option = 240 static_cast<const NamespecOption*>(*cur_char); 241 if (info.attrFactory().last().isStatic()) { 242 path = info.options().directories().find(namespec_option->namespec(), 243 Input::Archive); 244 } 245 else { 246 path = info.options().directories().find(namespec_option->namespec(), 247 Input::DynObj); 248 } 249 250 if (0 == path) { 251 llvm::report_fatal_error(std::string("Can't find namespec: ")+ 252 namespec_option->namespec()); 253 } 254 info.inputs().insert(cur_node, 255 *prev_ward, 256 namespec_option->namespec(), 257 *path); 258 prev_ward->move(cur_node); 259 prev_ward = &InputTree::Afterward; 260 break; 261 } 262 case PositionDependentOption::START_GROUP: 263 info.inputs().enterGroup(cur_node, *prev_ward); 264 prev_ward->move(cur_node); 265 returnStack.push(cur_node); 266 prev_ward = &InputTree::Downward; 267 break; 268 case PositionDependentOption::END_GROUP: 269 cur_node = returnStack.top(); 270 returnStack.pop(); 271 prev_ward = &InputTree::Afterward; 272 break; 273 case PositionDependentOption::WHOLE_ARCHIVE: 274 info.attrFactory().last().setWholeArchive(); 275 break; 276 case PositionDependentOption::NO_WHOLE_ARCHIVE: 277 info.attrFactory().last().unsetWholeArchive(); 278 break; 279 case PositionDependentOption::AS_NEEDED: 280 info.attrFactory().last().setAsNeeded(); 281 break; 282 case PositionDependentOption::NO_AS_NEEDED: 283 info.attrFactory().last().unsetAsNeeded(); 284 break; 285 case PositionDependentOption::ADD_NEEDED: 286 info.attrFactory().last().setAddNeeded(); 287 break; 288 case PositionDependentOption::NO_ADD_NEEDED: 289 info.attrFactory().last().unsetAddNeeded(); 290 break; 291 case PositionDependentOption::BSTATIC: 292 info.attrFactory().last().setStatic(); 293 break; 294 case PositionDependentOption::BDYNAMIC: 295 info.attrFactory().last().setDynamic(); 296 break; 297 default: 298 report_fatal_error("can not find the type of input file"); 299 } 300 ++cur_char; 301 } 302 303 if (!returnStack.empty()) { 304 report_fatal_error("no matched --start-group and --end-group"); 305 } 306} 307 308//===----------------------------------------------------------------------===// 309// Non-member functions 310static bool CompareOption(const PositionDependentOption* X, 311 const PositionDependentOption* Y) 312{ 313 return (X->position() < Y->position()); 314} 315 316