• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- MipsPLT.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/Casting.h>
10 #include <llvm/Support/ELF.h>
11 #include "mcld/Support/MsgHandling.h"
12 #include "MipsGOTPLT.h"
13 #include "MipsPLT.h"
14 
15 namespace {
16 
17 const uint32_t PLT0[] = {
18     0x3c1c0000,  // lui $28, %hi(&GOTPLT[0])
19     0x8f990000,  // lw $25, %lo(&GOTPLT[0])($28)
20     0x279c0000,  // addiu $28, $28, %lo(&GOTPLT[0])
21     0x031cc023,  // subu $24, $24, $28
22     0x03e07821,  // move $15, $31
23     0x0018c082,  // srl $24, $24, 2
24     0x0320f809,  // jalr $25
25     0x2718fffe   // subu $24, $24, 2
26 };
27 
28 const uint32_t PLTA[] = {
29     0x3c0f0000,  // lui $15, %hi(.got.plt entry)
30     0x8df90000,  // l[wd] $25, %lo(.got.plt entry)($15)
31     0x03200008,  // jr $25
32     0x25f80000   // addiu $24, $15, %lo(.got.plt entry)
33 };
34 
35 }  // anonymous namespace
36 
37 namespace mcld {
38 
39 //===----------------------------------------------------------------------===//
40 // MipsPLT0 Entry
41 //===----------------------------------------------------------------------===//
42 class MipsPLT0 : public PLT::Entry<sizeof(PLT0)> {
43  public:
MipsPLT0(SectionData & pParent)44   MipsPLT0(SectionData& pParent) : PLT::Entry<sizeof(PLT0)>(pParent) {}
45 };
46 
47 //===----------------------------------------------------------------------===//
48 // MipsPLTA Entry
49 //===----------------------------------------------------------------------===//
50 class MipsPLTA : public PLT::Entry<sizeof(PLTA)> {
51  public:
MipsPLTA(SectionData & pParent)52   MipsPLTA(SectionData& pParent) : PLT::Entry<sizeof(PLTA)>(pParent) {}
53 };
54 
55 //===----------------------------------------------------------------------===//
56 // MipsPLT
57 //===----------------------------------------------------------------------===//
MipsPLT(LDSection & pSection)58 MipsPLT::MipsPLT(LDSection& pSection) : PLT(pSection) {
59   new MipsPLT0(*m_pSectionData);
60   m_Last = m_pSectionData->begin();
61 }
62 
finalizeSectionSize()63 void MipsPLT::finalizeSectionSize() {
64   uint64_t size = sizeof(PLT0) + (m_pSectionData->size() - 1) * sizeof(PLTA);
65   m_Section.setSize(size);
66 
67   uint32_t offset = 0;
68   SectionData::iterator frag, fragEnd = m_pSectionData->end();
69   for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) {
70     frag->setOffset(offset);
71     offset += frag->size();
72   }
73 }
74 
hasPLT1() const75 bool MipsPLT::hasPLT1() const {
76   return m_pSectionData->size() > 1;
77 }
78 
emit(MemoryRegion & pRegion)79 uint64_t MipsPLT::emit(MemoryRegion& pRegion) {
80   uint64_t result = 0x0;
81   iterator it = begin();
82 
83   unsigned char* buffer = pRegion.begin();
84   memcpy(buffer, llvm::cast<MipsPLT0>((*it)).getValue(), MipsPLT0::EntrySize);
85   result += MipsPLT0::EntrySize;
86   ++it;
87 
88   MipsPLTA* plta = 0;
89   for (iterator ie = end(); it != ie; ++it) {
90     plta = &(llvm::cast<MipsPLTA>(*it));
91     memcpy(buffer + result, plta->getValue(), MipsPLTA::EntrySize);
92     result += MipsPLTA::EntrySize;
93   }
94   return result;
95 }
96 
reserveEntry(size_t pNum)97 void MipsPLT::reserveEntry(size_t pNum) {
98   for (size_t i = 0; i < pNum; ++i) {
99     Fragment* entry = new (std::nothrow) MipsPLTA(*m_pSectionData);
100 
101     if (entry == NULL)
102       fatal(diag::fail_allocate_memory_plt);
103   }
104 }
105 
consume()106 Fragment* MipsPLT::consume() {
107   ++m_Last;
108   assert(m_Last != m_pSectionData->end() &&
109          "The number of PLT Entries and ResolveInfo doesn't match");
110   return &(*m_Last);
111 }
112 
applyAllPLT(MipsGOTPLT & pGOTPLT)113 void MipsPLT::applyAllPLT(MipsGOTPLT& pGOTPLT) {
114   assert(m_Section.addr() && ".plt base address is NULL!");
115 
116   size_t count = 0;
117   for (iterator it = m_pSectionData->begin(); it != m_pSectionData->end();
118        ++it) {
119     PLTEntryBase* plt = &(llvm::cast<PLTEntryBase>(*it));
120 
121     if (it == m_pSectionData->begin()) {
122       uint32_t* data = static_cast<uint32_t*>(malloc(plt->size()));
123 
124       if (!data)
125         fatal(diag::fail_allocate_memory_plt);
126 
127       memcpy(data, PLT0, plt->size());
128 
129       uint64_t gotAddr = pGOTPLT.addr();
130 
131       data[0] |= ((gotAddr + 0x8000) >> 16) & 0xffff;
132       data[1] |= gotAddr & 0xffff;
133       data[2] |= gotAddr & 0xffff;
134 
135       plt->setValue(reinterpret_cast<unsigned char*>(data));
136     } else {
137       uint32_t* data = static_cast<uint32_t*>(malloc(plt->size()));
138 
139       if (!data)
140         fatal(diag::fail_allocate_memory_plt);
141 
142       memcpy(data, PLTA, plt->size());
143 
144       uint64_t gotEntryAddr = pGOTPLT.getEntryAddr(count++);
145 
146       data[0] |= ((gotEntryAddr + 0x8000) >> 16) & 0xffff;
147       data[1] |= gotEntryAddr & 0xffff;
148       data[3] |= gotEntryAddr & 0xffff;
149 
150       plt->setValue(reinterpret_cast<unsigned char*>(data));
151     }
152   }
153 }
154 
155 }  // namespace mcld
156