1//===- FragmentLinker.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 FragmentLinker class 11// 12//===----------------------------------------------------------------------===// 13#include <mcld/Fragment/FragmentLinker.h> 14 15#include <llvm/Support/Host.h> 16#include <llvm/Support/raw_ostream.h> 17#include <llvm/Support/Casting.h> 18 19#include <mcld/LinkerConfig.h> 20#include <mcld/Module.h> 21#include <mcld/LD/LDSection.h> 22#include <mcld/MC/MCLDInput.h> 23#include <mcld/LD/LDSection.h> 24#include <mcld/LD/BranchIslandFactory.h> 25#include <mcld/LD/Resolver.h> 26#include <mcld/LD/LDContext.h> 27#include <mcld/LD/RelocationFactory.h> 28#include <mcld/LD/RelocData.h> 29#include <mcld/LD/Relocator.h> 30#include <mcld/Support/MemoryRegion.h> 31#include <mcld/Support/MemoryArea.h> 32#include <mcld/Support/FileHandle.h> 33#include <mcld/Support/MsgHandling.h> 34#include <mcld/Target/TargetLDBackend.h> 35#include <mcld/Fragment/Relocation.h> 36 37using namespace mcld; 38 39//===----------------------------------------------------------------------===// 40// FragmentLinker 41//===----------------------------------------------------------------------===// 42/// Constructor 43FragmentLinker::FragmentLinker(const LinkerConfig& pConfig, 44 Module& pModule, 45 TargetLDBackend& pBackend) 46 47 : m_Config(pConfig), 48 m_Module(pModule), 49 m_Backend(pBackend) { 50} 51 52/// Destructor 53FragmentLinker::~FragmentLinker() 54{ 55} 56 57bool FragmentLinker::finalizeSymbols() 58{ 59 Module::sym_iterator symbol, symEnd = m_Module.sym_end(); 60 for (symbol = m_Module.sym_begin(); symbol != symEnd; ++symbol) { 61 62 if ((*symbol)->resolveInfo()->isAbsolute() || 63 (*symbol)->resolveInfo()->type() == ResolveInfo::File) { 64 // absolute symbols or symbols with function type should have 65 // zero value 66 (*symbol)->setValue(0x0); 67 continue; 68 } 69 70 if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) { 71 m_Backend.finalizeTLSSymbol(**symbol); 72 continue; 73 } 74 75 if ((*symbol)->hasFragRef()) { 76 // set the virtual address of the symbol. If the output file is 77 // relocatable object file, the section's virtual address becomes zero. 78 // And the symbol's value become section relative offset. 79 uint64_t value = (*symbol)->fragRef()->getOutputOffset(); 80 assert(NULL != (*symbol)->fragRef()->frag()); 81 uint64_t addr = (*symbol)->fragRef()->frag()->getParent()->getSection().addr(); 82 (*symbol)->setValue(value + addr); 83 continue; 84 } 85 } 86 87 return true; 88} 89 90//===----------------------------------------------------------------------===// 91// Relocation Operations 92//===----------------------------------------------------------------------===// 93bool FragmentLinker::applyRelocations() 94{ 95 // when producing relocatables, no need to apply relocation 96 if (LinkerConfig::Object == m_Config.codeGenType()) 97 return true; 98 99 // apply all relocations of all inputs 100 Module::obj_iterator input, inEnd = m_Module.obj_end(); 101 for (input = m_Module.obj_begin(); input != inEnd; ++input) { 102 m_Backend.getRelocator()->initializeApply(**input); 103 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); 104 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 105 // bypass the reloc section if 106 // 1. its section kind is changed to Ignore. (The target section is a 107 // discarded group section.) 108 // 2. it has no reloc data. (All symbols in the input relocs are in the 109 // discarded group sections) 110 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) 111 continue; 112 RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); 113 for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { 114 Relocation* relocation = llvm::cast<Relocation>(reloc); 115 relocation->apply(*m_Backend.getRelocator()); 116 } // for all relocations 117 } // for all relocation section 118 m_Backend.getRelocator()->finalizeApply(**input); 119 } // for all inputs 120 121 // apply relocations created by relaxation 122 BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory(); 123 BranchIslandFactory::iterator facIter, facEnd = br_factory->end(); 124 for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) { 125 BranchIsland& island = *facIter; 126 BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end(); 127 for (iter = island.reloc_begin(); iter != iterEnd; ++iter) 128 (*iter)->apply(*m_Backend.getRelocator()); 129 } 130 return true; 131} 132 133 134void FragmentLinker::syncRelocationResult(MemoryArea& pOutput) 135{ 136 if (LinkerConfig::Object != m_Config.codeGenType()) 137 normalSyncRelocationResult(pOutput); 138 else 139 partialSyncRelocationResult(pOutput); 140 return; 141} 142 143void FragmentLinker::normalSyncRelocationResult(MemoryArea& pOutput) 144{ 145 MemoryRegion* region = pOutput.request(0, pOutput.handler()->size()); 146 147 uint8_t* data = region->getBuffer(); 148 149 // sync all relocations of all inputs 150 Module::obj_iterator input, inEnd = m_Module.obj_end(); 151 for (input = m_Module.obj_begin(); input != inEnd; ++input) { 152 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); 153 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 154 // bypass the reloc section if 155 // 1. its section kind is changed to Ignore. (The target section is a 156 // discarded group section.) 157 // 2. it has no reloc data. (All symbols in the input relocs are in the 158 // discarded group sections) 159 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) 160 continue; 161 RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); 162 for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { 163 Relocation* relocation = llvm::cast<Relocation>(reloc); 164 165 // bypass the relocation with NONE type. This is to avoid overwrite the 166 // target result by NONE type relocation if there is a place which has 167 // two relocations to apply to, and one of it is NONE type. The result 168 // we want is the value of the other relocation result. For example, 169 // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to 170 // the same place 171 if (0x0 == relocation->type()) 172 continue; 173 writeRelocationResult(*relocation, data); 174 } // for all relocations 175 } // for all relocation section 176 } // for all inputs 177 178 // sync relocations created by relaxation 179 BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory(); 180 BranchIslandFactory::iterator facIter, facEnd = br_factory->end(); 181 for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) { 182 BranchIsland& island = *facIter; 183 BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end(); 184 for (iter = island.reloc_begin(); iter != iterEnd; ++iter) { 185 Relocation* reloc = *iter; 186 writeRelocationResult(*reloc, data); 187 } 188 } 189 190 pOutput.clear(); 191} 192 193void FragmentLinker::partialSyncRelocationResult(MemoryArea& pOutput) 194{ 195 MemoryRegion* region = pOutput.request(0, pOutput.handler()->size()); 196 197 uint8_t* data = region->getBuffer(); 198 199 // traverse outputs' LDSection to get RelocData 200 Module::iterator sectIter, sectEnd = m_Module.end(); 201 for (sectIter = m_Module.begin(); sectIter != sectEnd; ++sectIter) { 202 if (LDFileFormat::Relocation != (*sectIter)->kind()) 203 continue; 204 205 RelocData* reloc_data = (*sectIter)->getRelocData(); 206 RelocData::iterator relocIter, relocEnd = reloc_data->end(); 207 for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) { 208 Relocation* reloc = llvm::cast<Relocation>(relocIter); 209 210 // bypass the relocation with NONE type. This is to avoid overwrite the 211 // target result by NONE type relocation if there is a place which has 212 // two relocations to apply to, and one of it is NONE type. The result 213 // we want is the value of the other relocation result. For example, 214 // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to 215 // the same place 216 if (0x0 == reloc->type()) 217 continue; 218 writeRelocationResult(*reloc, data); 219 } 220 } 221 222 pOutput.clear(); 223} 224 225void FragmentLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput) 226{ 227 // get output file offset 228 size_t out_offset = 229 pReloc.targetRef().frag()->getParent()->getSection().offset() + 230 pReloc.targetRef().getOutputOffset(); 231 232 uint8_t* target_addr = pOutput + out_offset; 233 // byte swapping if target and host has different endian, and then write back 234 if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian()) { 235 uint64_t tmp_data = 0; 236 237 switch(pReloc.size(*m_Backend.getRelocator())) { 238 case 8u: 239 std::memcpy(target_addr, &pReloc.target(), 1); 240 break; 241 242 case 16u: 243 tmp_data = mcld::bswap16(pReloc.target()); 244 std::memcpy(target_addr, &tmp_data, 2); 245 break; 246 247 case 32u: 248 tmp_data = mcld::bswap32(pReloc.target()); 249 std::memcpy(target_addr, &tmp_data, 4); 250 break; 251 252 case 64u: 253 tmp_data = mcld::bswap64(pReloc.target()); 254 std::memcpy(target_addr, &tmp_data, 8); 255 break; 256 257 default: 258 break; 259 } 260 } 261 else 262 std::memcpy(target_addr, &pReloc.target(), 263 pReloc.size(*m_Backend.getRelocator())/8); 264} 265 266