1//===- MipsELFDynamic.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 <llvm/Support/ELF.h>
10#include <mcld/LinkerConfig.h>
11#include <mcld/LD/ELFFileFormat.h>
12#include <mcld/LD/ELFSegment.h>
13#include <mcld/LD/ELFSegmentFactory.h>
14#include <mcld/Target/GNULDBackend.h>
15#include "MipsELFDynamic.h"
16#include "MipsLDBackend.h"
17
18using namespace mcld;
19
20MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent,
21                               const LinkerConfig& pConfig)
22  : ELFDynamic(pParent, pConfig),
23    m_pParent(pParent),
24    m_pConfig(pConfig)
25{
26}
27
28void MipsELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
29{
30  if (pFormat.hasGOT())
31    reserveOne(llvm::ELF::DT_PLTGOT);
32
33  reserveOne(llvm::ELF::DT_MIPS_RLD_VERSION);
34  reserveOne(llvm::ELF::DT_MIPS_FLAGS);
35  reserveOne(llvm::ELF::DT_MIPS_BASE_ADDRESS);
36  reserveOne(llvm::ELF::DT_MIPS_LOCAL_GOTNO);
37  reserveOne(llvm::ELF::DT_MIPS_SYMTABNO);
38  reserveOne(llvm::ELF::DT_MIPS_GOTSYM);
39
40  if (pFormat.hasGOTPLT())
41    reserveOne(llvm::ELF::DT_MIPS_PLTGOT);
42}
43
44void MipsELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
45{
46  if (pFormat.hasGOT())
47    applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
48
49  applyOne(llvm::ELF::DT_MIPS_RLD_VERSION, 1);
50  applyOne(llvm::ELF::DT_MIPS_FLAGS, llvm::ELF::RHF_NOTPOT);
51  applyOne(llvm::ELF::DT_MIPS_BASE_ADDRESS, getBaseAddress());
52  applyOne(llvm::ELF::DT_MIPS_LOCAL_GOTNO, getLocalGotNum(pFormat));
53  applyOne(llvm::ELF::DT_MIPS_SYMTABNO, getSymTabNum(pFormat));
54  applyOne(llvm::ELF::DT_MIPS_GOTSYM, getGotSym(pFormat));
55
56  if (pFormat.hasGOTPLT())
57    applyOne(llvm::ELF::DT_MIPS_PLTGOT, pFormat.getGOTPLT().addr());
58}
59
60size_t MipsELFDynamic::getSymTabNum(const ELFFileFormat& pFormat) const
61{
62  if (!pFormat.hasDynSymTab())
63    return 0;
64
65  const LDSection& dynsym = pFormat.getDynSymTab();
66  return dynsym.size() / symbolSize();
67}
68
69size_t MipsELFDynamic::getGotSym(const ELFFileFormat& pFormat) const
70{
71  if (!pFormat.hasGOT())
72    return 0;
73
74  return getSymTabNum(pFormat) - m_pParent.getGOT().getGlobalNum();
75}
76
77size_t MipsELFDynamic::getLocalGotNum(const ELFFileFormat& pFormat) const
78{
79  if (!pFormat.hasGOT())
80    return 0;
81
82  return m_pParent.getGOT().getLocalNum();
83}
84
85uint64_t MipsELFDynamic::getBaseAddress()
86{
87  if (LinkerConfig::Exec != m_pConfig.codeGenType())
88    return 0;
89
90  ELFSegmentFactory::const_iterator baseSeg =
91    m_pParent.elfSegmentTable().find(llvm::ELF::PT_LOAD, 0x0, 0x0);
92
93  return m_pParent.elfSegmentTable().end() == baseSeg ? 0 : (*baseSeg)->vaddr();
94}
95