122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===- FragmentLinker.cpp -------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
1022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// This file implements the FragmentLinker class
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentLinker.h>
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Host.h>
16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/raw_ostream.h>
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/Casting.h>
18cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LinkerConfig.h>
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Module.h>
21f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LD/LDSection.h>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLDInput.h>
23f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LD/LDSection.h>
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/BranchIslandFactory.h>
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Resolver.h>
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/LDContext.h>
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/RelocationFactory.h>
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/RelocData.h>
29f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LD/Relocator.h>
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MemoryArea.h>
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/FileHandle.h>
33affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/TargetLDBackend.h>
35d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/Fragment/Relocation.h>
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
39d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
40d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// FragmentLinker
41d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Constructor
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentLinker::FragmentLinker(const LinkerConfig& pConfig,
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               Module& pModule,
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               TargetLDBackend& pBackend)
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : m_Config(pConfig),
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Module(pModule),
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Backend(pBackend) {
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Destructor
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentLinker::~FragmentLinker()
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool FragmentLinker::finalizeSymbols()
58cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Module::sym_iterator symbol, symEnd = m_Module.sym_end();
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (symbol = m_Module.sym_begin(); symbol != symEnd; ++symbol) {
61cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
62cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if ((*symbol)->resolveInfo()->isAbsolute() ||
63cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
64cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // absolute symbols or symbols with function type should have
65cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // zero value
66cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      (*symbol)->setValue(0x0);
67cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      continue;
68cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
69cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_Backend.finalizeTLSSymbol(**symbol);
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      continue;
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
75cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if ((*symbol)->hasFragRef()) {
76cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // set the virtual address of the symbol. If the output file is
77cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // relocatable object file, the section's virtual address becomes zero.
78cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      // And the symbol's value become section relative offset.
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      uint64_t value = (*symbol)->fragRef()->getOutputOffset();
80cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      assert(NULL != (*symbol)->fragRef()->frag());
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      uint64_t addr = (*symbol)->fragRef()->frag()->getParent()->getSection().addr();
82cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      (*symbol)->setValue(value + addr);
83cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      continue;
84cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
85cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
86cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
88cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
89cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
90cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
91cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// Relocation Operations
92cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool FragmentLinker::applyRelocations()
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // when producing relocatables, no need to apply relocation
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object == m_Config.codeGenType())
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // apply all relocations of all inputs
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Module::obj_iterator input, inEnd = m_Module.obj_end();
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_Backend.getRelocator()->initializeApply(**input);
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // bypass the reloc section if
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // 1. its section kind is changed to Ignore. (The target section is a
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // discarded group section.)
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // 2. it has no reloc data. (All symbols in the input relocs are in the
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // discarded group sections)
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        continue;
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        Relocation* relocation = llvm::cast<Relocation>(reloc);
115d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        relocation->apply(*m_Backend.getRelocator());
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      } // for all relocations
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    } // for all relocation section
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_Backend.getRelocator()->finalizeApply(**input);
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // for all inputs
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // apply relocations created by relaxation
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    BranchIsland& island = *facIter;
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      (*iter)->apply(*m_Backend.getRelocator());
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid FragmentLinker::syncRelocationResult(MemoryArea& pOutput)
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != m_Config.codeGenType())
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    normalSyncRelocationResult(pOutput);
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    partialSyncRelocationResult(pOutput);
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return;
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid FragmentLinker::normalSyncRelocationResult(MemoryArea& pOutput)
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint8_t* data = region->getBuffer();
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // sync all relocations of all inputs
15022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Module::obj_iterator input, inEnd = m_Module.obj_end();
15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // bypass the reloc section if
15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // 1. its section kind is changed to Ignore. (The target section is a
15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // discarded group section.)
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // 2. it has no reloc data. (All symbols in the input relocs are in the
15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // discarded group sections)
15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        continue;
16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        Relocation* relocation = llvm::cast<Relocation>(reloc);
16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
16522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // bypass the relocation with NONE type. This is to avoid overwrite the
16622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // target result by NONE type relocation if there is a place which has
16722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // two relocations to apply to, and one of it is NONE type. The result
16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // we want is the value of the other relocation result. For example,
16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // the same place
17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        if (0x0 == relocation->type())
17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          continue;
17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        writeRelocationResult(*relocation, data);
17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      } // for all relocations
17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    } // for all relocation section
17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // for all inputs
17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // sync relocations created by relaxation
17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    BranchIsland& island = *facIter;
18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Relocation* reloc = *iter;
18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      writeRelocationResult(*reloc, data);
18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pOutput.clear();
19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid FragmentLinker::partialSyncRelocationResult(MemoryArea& pOutput)
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t* data = region->getBuffer();
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // traverse outputs' LDSection to get RelocData
20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Module::iterator sectIter, sectEnd = m_Module.end();
20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (sectIter = m_Module.begin(); sectIter != sectEnd; ++sectIter) {
20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LDFileFormat::Relocation != (*sectIter)->kind())
20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      continue;
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    RelocData* reloc_data = (*sectIter)->getRelocData();
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    RelocData::iterator relocIter, relocEnd = reloc_data->end();
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Relocation* reloc = llvm::cast<Relocation>(relocIter);
20922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
21022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // bypass the relocation with NONE type. This is to avoid overwrite the
21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // target result by NONE type relocation if there is a place which has
21222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // two relocations to apply to, and one of it is NONE type. The result
21322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // we want is the value of the other relocation result. For example,
21422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
21522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // the same place
21622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (0x0 == reloc->type())
21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        continue;
21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      writeRelocationResult(*reloc, data);
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
22022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pOutput.clear();
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid FragmentLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
22722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get output file offset
2286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t out_offset =
2296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                 pReloc.targetRef().frag()->getParent()->getSection().offset() +
2306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                 pReloc.targetRef().getOutputOffset();
23122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t* target_addr = pOutput + out_offset;
23322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // byte swapping if target and host has different endian, and then write back
23421433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian()) {
23522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     uint64_t tmp_data = 0;
23622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines     switch(pReloc.size(*m_Backend.getRelocator())) {
2386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       case 8u:
2396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines         std::memcpy(target_addr, &pReloc.target(), 1);
2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines         break;
2416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       case 16u:
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines         tmp_data = mcld::bswap16(pReloc.target());
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines         std::memcpy(target_addr, &tmp_data, 2);
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines         break;
2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
24722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao       case 32u:
248d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         tmp_data = mcld::bswap32(pReloc.target());
24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         std::memcpy(target_addr, &tmp_data, 4);
25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         break;
25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao       case 64u:
253d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         tmp_data = mcld::bswap64(pReloc.target());
25422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         std::memcpy(target_addr, &tmp_data, 8);
25522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         break;
25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao       default:
25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         break;
259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
26122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    std::memcpy(target_addr, &pReloc.target(),
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      pReloc.size(*m_Backend.getRelocator())/8);
264affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
265affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
266