Linker.cpp revision d0fbbb227051be16931a1aa9b4a7722ac039c698
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/LD/SectionData.h> 26#include <mcld/LD/RelocData.h> 27#include <mcld/Fragment/Relocation.h> 28#include <mcld/Fragment/FragmentRef.h> 29 30#include <cassert> 31 32using namespace mcld; 33 34Linker::Linker() 35 : m_pConfig(NULL), m_pModule(NULL), m_pIRBuilder(NULL), 36 m_pTarget(NULL), m_pBackend(NULL), m_pObjLinker(NULL) { 37} 38 39Linker::~Linker() 40{ 41 reset(); 42} 43 44bool Linker::config(LinkerConfig& pConfig) 45{ 46 m_pConfig = &pConfig; 47 48 if (!initTarget()) 49 return false; 50 51 if (!initBackend()) 52 return false; 53 54 if (!initEmulator()) 55 return false; 56 57 if (!initOStream()) 58 return false; 59 60 return true; 61} 62 63bool Linker::link(Module& pModule, IRBuilder& pBuilder) 64{ 65 assert(NULL != m_pConfig); 66 67 m_pIRBuilder = &pBuilder; 68 m_pObjLinker = new ObjectLinker(*m_pConfig, 69 pModule, 70 *m_pIRBuilder, 71 *m_pBackend); 72 73 // 2. - initialize FragmentLinker 74 if (!m_pObjLinker->initFragmentLinker()) 75 return false; 76 77 // 3. - initialize output's standard sections 78 if (!m_pObjLinker->initStdSections()) 79 return false; 80 81 // 4. - normalize the input tree 82 m_pObjLinker->normalize(); 83 84 if (m_pConfig->options().trace()) { 85 static int counter = 0; 86 mcld::outs() << "** name\ttype\tpath\tsize (" << pModule.getInputTree().size() << ")\n"; 87 InputTree::const_dfs_iterator input, inEnd = pModule.getInputTree().dfs_end(); 88 for (input=pModule.getInputTree().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 115 // 5. - check if we can do static linking and if we use split-stack. 116 if (!m_pObjLinker->linkable()) 117 return Diagnose(); 118 119 // 6. - read all relocation entries from input files 120 m_pObjLinker->readRelocations(); 121 122 // 7. - merge all sections 123 if (!m_pObjLinker->mergeSections()) 124 return false; 125 126 // 8. - add standard symbols and target-dependent symbols 127 // m_pObjLinker->addUndefSymbols(); 128 if (!m_pObjLinker->addStandardSymbols() || 129 !m_pObjLinker->addTargetSymbols()) 130 return false; 131 132 // 9. - scan all relocation entries by output symbols. 133 m_pObjLinker->scanRelocations(); 134 135 // 10.a - pre-layout 136 m_pObjLinker->prelayout(); 137 138 // 10.b - linear layout 139 m_pObjLinker->layout(); 140 141 // 10.c - post-layout (create segment, instruction relaxing) 142 m_pObjLinker->postlayout(); 143 144 // 11. - finalize symbol value 145 m_pObjLinker->finalizeSymbolValue(); 146 147 // 12. - apply relocations 148 m_pObjLinker->relocation(); 149 150 if (!Diagnose()) 151 return false; 152 return true; 153} 154 155bool Linker::emit(MemoryArea& pOutput) 156{ 157 // 13. - write out output 158 m_pObjLinker->emitOutput(pOutput); 159 160 // 14. - post processing 161 m_pObjLinker->postProcessing(pOutput); 162 163 if (!Diagnose()) 164 return false; 165 166 return true; 167} 168 169bool Linker::emit(const std::string& pPath) 170{ 171 FileHandle file; 172 FileHandle::Permission perm = 0755; 173 if (!file.open(pPath, 174 FileHandle::ReadWrite | FileHandle::Truncate | FileHandle::Create, 175 perm)) { 176 error(diag::err_cannot_open_output_file) << "Linker::emit()" << pPath; 177 return false; 178 } 179 180 MemoryArea* output = new MemoryArea(file); 181 182 bool result = emit(*output); 183 184 delete output; 185 file.close(); 186 return result; 187} 188 189bool Linker::emit(int pFileDescriptor) 190{ 191 FileHandle file; 192 file.delegate(pFileDescriptor); 193 MemoryArea* output = new MemoryArea(file); 194 195 bool result = emit(*output); 196 197 delete output; 198 file.close(); 199 return result; 200} 201 202bool Linker::reset() 203{ 204 m_pConfig = NULL; 205 m_pModule = NULL; 206 m_pIRBuilder = NULL; 207 m_pTarget = NULL; 208 209 // Because llvm::iplist will touch the removed node, we must clear 210 // RelocData before deleting target backend. 211 RelocData::Clear(); 212 SectionData::Clear(); 213 214 delete m_pBackend; 215 m_pBackend = NULL; 216 217 delete m_pObjLinker; 218 m_pObjLinker = NULL; 219 220 LDSection::Clear(); 221 LDSymbol::Clear(); 222 FragmentRef::Clear(); 223 Relocation::Clear(); 224 return true; 225} 226 227bool Linker::initTarget() 228{ 229 assert(NULL != m_pConfig); 230 231 std::string error; 232 m_pTarget = mcld::TargetRegistry::lookupTarget(m_pConfig->targets().triple().str(), error); 233 if (NULL == m_pTarget) { 234 fatal(diag::fatal_cannot_init_target) << m_pConfig->targets().triple().str() << error; 235 return false; 236 } 237 return true; 238} 239 240bool Linker::initBackend() 241{ 242 assert(NULL != m_pTarget); 243 m_pBackend = m_pTarget->createLDBackend(*m_pConfig); 244 if (NULL == m_pBackend) { 245 fatal(diag::fatal_cannot_init_backend) << m_pConfig->targets().triple().str(); 246 return false; 247 } 248 return true; 249} 250 251bool Linker::initEmulator() 252{ 253 assert(NULL != m_pTarget && NULL != m_pConfig); 254 bool result = m_pTarget->emulate(m_pConfig->targets().triple().str(), 255 *m_pConfig); 256 257 // Relocation should be set up after emulation. 258 Relocation::SetUp(*m_pConfig); 259 return result; 260} 261 262bool Linker::initOStream() 263{ 264 assert(NULL != m_pConfig); 265 266 mcld::outs().setColor(m_pConfig->options().color()); 267 mcld::errs().setColor(m_pConfig->options().color()); 268 269 return true; 270} 271 272