Linker.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
1//===- Linker.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/Linker.h> 10#include <mcld/LinkerConfig.h> 11#include <mcld/Module.h> 12#include <mcld/IRBuilder.h> 13 14#include <mcld/Support/MsgHandling.h> 15#include <mcld/Support/TargetRegistry.h> 16#include <mcld/Support/FileHandle.h> 17#include <mcld/Support/MemoryArea.h> 18#include <mcld/Support/raw_ostream.h> 19 20#include <mcld/Object/ObjectLinker.h> 21#include <mcld/MC/InputBuilder.h> 22#include <mcld/Target/TargetLDBackend.h> 23#include <mcld/LD/LDSection.h> 24#include <mcld/LD/LDSymbol.h> 25#include <mcld/Fragment/FragmentRef.h> 26 27#include <cassert> 28 29using namespace mcld; 30 31Linker::Linker() 32 : m_pConfig(NULL), m_pModule(NULL), m_pIRBuilder(NULL), 33 m_pTarget(NULL), m_pBackend(NULL), m_pObjLinker(NULL) { 34} 35 36Linker::~Linker() 37{ 38 reset(); 39} 40 41bool Linker::config(LinkerConfig& pConfig) 42{ 43 m_pConfig = &pConfig; 44 45 if (!initTarget()) 46 return false; 47 48 if (!initBackend()) 49 return false; 50 51 if (!initEmulator()) 52 return false; 53 54 if (!initOStream()) 55 return false; 56 57 return true; 58} 59 60bool Linker::link(Module& pModule, IRBuilder& pBuilder) 61{ 62 assert(NULL != m_pConfig); 63 64 m_pIRBuilder = &pBuilder; 65 m_pObjLinker = new ObjectLinker(*m_pConfig, 66 pModule, 67 m_pIRBuilder->getInputBuilder(), 68 *m_pBackend); 69 70 // 2. - initialize FragmentLinker 71 if (!m_pObjLinker->initFragmentLinker()) 72 return false; 73 74 // 3. - initialize output's standard sections 75 if (!m_pObjLinker->initStdSections()) 76 return false; 77 78 // 4. - normalize the input tree 79 m_pObjLinker->normalize(); 80 81 if (m_pConfig->options().trace()) { 82 static int counter = 0; 83 mcld::outs() << "** name\ttype\tpath\tsize (" << pModule.getInputTree().size() << ")\n"; 84 InputTree::const_dfs_iterator input, inEnd = pModule.getInputTree().dfs_end(); 85 for (input=pModule.getInputTree().dfs_begin(); input!=inEnd; ++input) { 86 mcld::outs() << counter++ << " * " << (*input)->name(); 87 switch((*input)->type()) { 88 case Input::Archive: 89 mcld::outs() << "\tarchive\t("; 90 break; 91 case Input::Object: 92 mcld::outs() << "\tobject\t("; 93 break; 94 case Input::DynObj: 95 mcld::outs() << "\tshared\t("; 96 break; 97 case Input::Script: 98 mcld::outs() << "\tscript\t("; 99 break; 100 case Input::External: 101 mcld::outs() << "\textern\t("; 102 break; 103 default: 104 unreachable(diag::err_cannot_trace_file) << (*input)->type() 105 << (*input)->name() 106 << (*input)->path(); 107 } 108 mcld::outs() << (*input)->path() << ")\n"; 109 } 110 } 111 112 // 5. - check if we can do static linking and if we use split-stack. 113 if (!m_pObjLinker->linkable()) 114 return Diagnose(); 115 116 // 6. - read all relocation entries from input files 117 m_pObjLinker->readRelocations(); 118 119 // 7. - merge all sections 120 if (!m_pObjLinker->mergeSections()) 121 return false; 122 123 // 8. - add standard symbols and target-dependent symbols 124 // m_pObjLinker->addUndefSymbols(); 125 if (!m_pObjLinker->addStandardSymbols() || 126 !m_pObjLinker->addTargetSymbols()) 127 return false; 128 129 // 9. - scan all relocation entries by output symbols. 130 m_pObjLinker->scanRelocations(); 131 132 // 10.a - pre-layout 133 m_pObjLinker->prelayout(); 134 135 // 10.b - linear layout 136 m_pObjLinker->layout(); 137 138 // 10.c - post-layout (create segment, instruction relaxing) 139 m_pObjLinker->postlayout(); 140 141 // 11. - finalize symbol value 142 m_pObjLinker->finalizeSymbolValue(); 143 144 // 12. - apply relocations 145 m_pObjLinker->relocation(); 146 147 if (!Diagnose()) 148 return false; 149 return true; 150} 151 152bool Linker::emit(MemoryArea& pOutput) 153{ 154 // 13. - write out output 155 m_pObjLinker->emitOutput(pOutput); 156 157 // 14. - post processing 158 m_pObjLinker->postProcessing(pOutput); 159 160 if (!Diagnose()) 161 return false; 162 163 return true; 164} 165 166bool Linker::emit(const std::string& pPath) 167{ 168 FileHandle file; 169 FileHandle::Permission perm = 0755; 170 if (!file.open(pPath, 171 FileHandle::ReadWrite | FileHandle::Truncate | FileHandle::Create, 172 perm)) { 173 error(diag::err_cannot_open_output_file) << "Linker::emit()" << pPath; 174 return false; 175 } 176 177 MemoryArea* output = new MemoryArea(file); 178 179 bool result = emit(*output); 180 181 delete output; 182 file.close(); 183 return result; 184} 185 186bool Linker::emit(int pFileDescriptor) 187{ 188 FileHandle file; 189 file.delegate(pFileDescriptor); 190 MemoryArea* output = new MemoryArea(file); 191 192 bool result = emit(*output); 193 194 delete output; 195 file.close(); 196 return result; 197} 198 199bool Linker::reset() 200{ 201 m_pConfig = NULL; 202 m_pModule = NULL; 203 m_pIRBuilder = NULL; 204 m_pTarget = NULL; 205 206 delete m_pBackend; 207 m_pBackend = NULL; 208 209 delete m_pObjLinker; 210 m_pObjLinker = NULL; 211 212 LDSection::Clear(); 213 LDSymbol::Clear(); 214 FragmentRef::Clear(); 215 return true; 216} 217 218bool Linker::initTarget() 219{ 220 assert(NULL != m_pConfig); 221 222 std::string error; 223 m_pTarget = TargetRegistry::lookupTarget(m_pConfig->triple().str(), error); 224 if (NULL == m_pTarget) { 225 fatal(diag::fatal_cannot_init_target) << m_pConfig->triple().str() << error; 226 return false; 227 } 228 return true; 229} 230 231bool Linker::initBackend() 232{ 233 assert(NULL != m_pTarget); 234 m_pBackend = m_pTarget->createLDBackend(*m_pConfig); 235 if (NULL == m_pBackend) { 236 fatal(diag::fatal_cannot_init_backend) << m_pConfig->triple().str(); 237 return false; 238 } 239 return true; 240} 241 242bool Linker::initEmulator() 243{ 244 assert(NULL != m_pTarget && NULL != m_pConfig); 245 return m_pTarget->emulate(m_pConfig->triple().str(), *m_pConfig); 246} 247 248bool Linker::initOStream() 249{ 250 assert(NULL != m_pConfig); 251 252 mcld::outs().setColor(m_pConfig->options().color()); 253 mcld::errs().setColor(m_pConfig->options().color()); 254 255 return true; 256} 257 258