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