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