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
18 using namespace mcld;
19
MipsELFDynamic(const MipsGNULDBackend & pParent,const LinkerConfig & pConfig)20 MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent,
21 const LinkerConfig& pConfig)
22 : ELFDynamic(pParent, pConfig),
23 m_pParent(pParent),
24 m_pConfig(pConfig)
25 {
26 }
27
reserveTargetEntries(const ELFFileFormat & pFormat)28 void 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
applyTargetEntries(const ELFFileFormat & pFormat)44 void 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
getSymTabNum(const ELFFileFormat & pFormat) const60 size_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
getGotSym(const ELFFileFormat & pFormat) const69 size_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
getLocalGotNum(const ELFFileFormat & pFormat) const77 size_t MipsELFDynamic::getLocalGotNum(const ELFFileFormat& pFormat) const
78 {
79 if (!pFormat.hasGOT())
80 return 0;
81
82 return m_pParent.getGOT().getLocalNum();
83 }
84
getBaseAddress()85 uint64_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