blob: dcd5c9415cea094630a5fa6cf148285cc7b50ff6 [file] [log] [blame]
Stephen Hines6f757552013-03-04 19:51:03 -08001//===- HexagonPLT.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 "HexagonPLT.h"
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070010#include "HexagonRelocationFunctions.h"
Stephen Hines6f757552013-03-04 19:51:03 -080011
Stephen Hines37b74a32014-11-26 18:48:20 -080012#include "mcld/LD/LDSection.h"
13#include "mcld/LinkerConfig.h"
14#include "mcld/Support/MsgHandling.h"
15
Stephen Hines6f757552013-03-04 19:51:03 -080016#include <llvm/Support/ELF.h>
17#include <llvm/Support/Casting.h>
18
Stephen Hines37b74a32014-11-26 18:48:20 -080019namespace mcld {
Stephen Hines6f757552013-03-04 19:51:03 -080020
21//===----------------------------------------------------------------------===//
22// PLT entry data
23//===----------------------------------------------------------------------===//
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070024HexagonPLT0::HexagonPLT0(SectionData& pParent)
Stephen Hines37b74a32014-11-26 18:48:20 -080025 : PLT::Entry<sizeof(hexagon_plt0)>(pParent) {
Stephen Hines6f757552013-03-04 19:51:03 -080026}
27
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070028HexagonPLT1::HexagonPLT1(SectionData& pParent)
Stephen Hines37b74a32014-11-26 18:48:20 -080029 : PLT::Entry<sizeof(hexagon_plt1)>(pParent) {
Stephen Hines6f757552013-03-04 19:51:03 -080030}
31
32//===----------------------------------------------------------------------===//
33// HexagonPLT
34//===----------------------------------------------------------------------===//
35HexagonPLT::HexagonPLT(LDSection& pSection,
Stephen Hines37b74a32014-11-26 18:48:20 -080036 HexagonGOTPLT& pGOTPLT,
37 const LinkerConfig& pConfig)
Stephen Hinescfcb2242016-03-08 00:18:09 -080038 : PLT(pSection), m_GOTPLT(pGOTPLT) {
39 assert(LinkerConfig::DynObj == pConfig.codeGenType() ||
40 LinkerConfig::Exec == pConfig.codeGenType() ||
41 LinkerConfig::Binary == pConfig.codeGenType());
Stephen Hines6f757552013-03-04 19:51:03 -080042
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070043 m_PLT0 = hexagon_plt0;
Stephen Hines37b74a32014-11-26 18:48:20 -080044 m_PLT0Size = sizeof(hexagon_plt0);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070045 // create PLT0
Stephen Hines551ae4e2014-04-24 14:41:24 -070046 new HexagonPLT0(*m_pSectionData);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070047 pSection.setAlign(16);
Stephen Hines6f757552013-03-04 19:51:03 -080048}
49
Stephen Hines37b74a32014-11-26 18:48:20 -080050HexagonPLT::~HexagonPLT() {
Stephen Hines6f757552013-03-04 19:51:03 -080051}
52
Stephen Hines37b74a32014-11-26 18:48:20 -080053PLTEntryBase* HexagonPLT::getPLT0() const {
Stephen Hines551ae4e2014-04-24 14:41:24 -070054 iterator first = m_pSectionData->getFragmentList().begin();
Stephen Hines6f757552013-03-04 19:51:03 -080055
Stephen Hines551ae4e2014-04-24 14:41:24 -070056 assert(first != m_pSectionData->getFragmentList().end() &&
Stephen Hines6f757552013-03-04 19:51:03 -080057 "FragmentList is empty, getPLT0 failed!");
58
59 PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
60
61 return plt0;
62}
63
Stephen Hines37b74a32014-11-26 18:48:20 -080064void HexagonPLT::finalizeSectionSize() {
Stephen Hines6f757552013-03-04 19:51:03 -080065 uint64_t size = 0;
66 // plt0 size
67 size = getPLT0()->size();
68
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070069 // get first plt1 entry
70 HexagonPLT::iterator it = begin();
71 ++it;
72 if (end() != it) {
73 // plt1 size
74 PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it));
Stephen Hines551ae4e2014-04-24 14:41:24 -070075 size += (m_pSectionData->size() - 1) * plt1->size();
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070076 }
Stephen Hines6f757552013-03-04 19:51:03 -080077 m_Section.setSize(size);
78
79 uint32_t offset = 0;
Stephen Hines551ae4e2014-04-24 14:41:24 -070080 SectionData::iterator frag, fragEnd = m_pSectionData->end();
81 for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) {
Stephen Hines6f757552013-03-04 19:51:03 -080082 frag->setOffset(offset);
83 offset += frag->size();
84 }
85}
86
Stephen Hines37b74a32014-11-26 18:48:20 -080087bool HexagonPLT::hasPLT1() const {
Stephen Hines551ae4e2014-04-24 14:41:24 -070088 return (m_pSectionData->size() > 1);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070089}
90
Stephen Hines37b74a32014-11-26 18:48:20 -080091HexagonPLT1* HexagonPLT::create() {
Stephen Hines551ae4e2014-04-24 14:41:24 -070092 return new HexagonPLT1(*m_pSectionData);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070093}
94
Stephen Hines37b74a32014-11-26 18:48:20 -080095void HexagonPLT::applyPLT0() {
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070096 PLTEntryBase* plt0 = getPLT0();
97 uint64_t pltBase = m_Section.addr();
98
99 unsigned char* data = 0;
100 data = static_cast<unsigned char*>(malloc(plt0->size()));
101
102 if (!data)
103 fatal(diag::fail_allocate_memory_plt);
104
105 memcpy(data, m_PLT0, plt0->size());
106 uint32_t gotpltAddr = m_GOTPLT.addr();
107
Stephen Hines37b74a32014-11-26 18:48:20 -0800108 int32_t* dest = reinterpret_cast<int32_t*>(data);
109 int32_t result = ((gotpltAddr - pltBase) >> 6);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700110 *dest |= ApplyMask<int32_t>(0xfff3fff, result);
111 dest = dest + 1;
112 // Already calculated using pltBase
113 result = (gotpltAddr - pltBase);
114 *(dest) |= ApplyMask<int32_t>(0x1f80, result);
115
116 plt0->setValue(data);
117}
118
119void HexagonPLT::applyPLT1() {
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700120 uint64_t plt_base = m_Section.addr();
121 assert(plt_base && ".plt base address is NULL!");
122
123 uint64_t got_base = m_GOTPLT.addr();
124 assert(got_base && ".got base address is NULL!");
125
Stephen Hines551ae4e2014-04-24 14:41:24 -0700126 HexagonPLT::iterator it = m_pSectionData->begin();
127 HexagonPLT::iterator ie = m_pSectionData->end();
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700128 assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
129
130 uint32_t GOTEntrySize = HexagonGOTEntry::EntrySize;
Stephen Hines37b74a32014-11-26 18:48:20 -0800131 uint32_t GOTEntryAddress = got_base + GOTEntrySize * 4;
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700132
133 uint64_t PLTEntryAddress =
Stephen Hines37b74a32014-11-26 18:48:20 -0800134 plt_base + HexagonPLT0::EntrySize; // Offset of PLT0
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700135
Stephen Hines37b74a32014-11-26 18:48:20 -0800136 ++it; // skip PLT0
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700137 uint64_t PLT1EntrySize = HexagonPLT1::EntrySize;
138 HexagonPLT1* plt1 = NULL;
139
140 uint32_t* Out = NULL;
141 while (it != ie) {
142 plt1 = &(llvm::cast<HexagonPLT1>(*it));
143 Out = static_cast<uint32_t*>(malloc(HexagonPLT1::EntrySize));
144
145 if (!Out)
146 fatal(diag::fail_allocate_memory_plt);
147
148 memcpy(Out, hexagon_plt1, plt1->size());
149
Stephen Hines37b74a32014-11-26 18:48:20 -0800150 int32_t* dest = reinterpret_cast<int32_t*>(Out);
151 int32_t result = ((GOTEntryAddress - PLTEntryAddress) >> 6);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700152 *dest |= ApplyMask<int32_t>(0xfff3fff, result);
153 dest = dest + 1;
154 result = (GOTEntryAddress - PLTEntryAddress);
155 *(dest) |= ApplyMask<int32_t>(0x1f80, result);
156
157 // Address in the PLT entries point to the corresponding GOT entries
158 // TODO: Fixup plt to point to the corresponding GOTEntryAddress
159 // We need to borrow the same relocation code to fix the relocation
160 plt1->setValue(reinterpret_cast<unsigned char*>(Out));
161 ++it;
162
163 GOTEntryAddress += GOTEntrySize;
164 PLTEntryAddress += PLT1EntrySize;
165 }
166}
167
Stephen Hines37b74a32014-11-26 18:48:20 -0800168uint64_t HexagonPLT::emit(MemoryRegion& pRegion) {
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700169 uint64_t result = 0x0;
170 iterator it = begin();
171
Stephen Hines87f34652014-02-14 18:00:16 -0800172 unsigned char* buffer = pRegion.begin();
Stephen Hines37b74a32014-11-26 18:48:20 -0800173 memcpy(buffer,
174 llvm::cast<HexagonPLT0>((*it)).getValue(),
175 HexagonPLT0::EntrySize);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700176 result += HexagonPLT0::EntrySize;
177 ++it;
178
179 HexagonPLT1* plt1 = 0;
180 HexagonPLT::iterator ie = end();
181 while (it != ie) {
182 plt1 = &(llvm::cast<HexagonPLT1>(*it));
183 memcpy(buffer + result, plt1->getValue(), HexagonPLT1::EntrySize);
184 result += HexagonPLT1::EntrySize;
185 ++it;
186 }
187 return result;
Stephen Hines6f757552013-03-04 19:51:03 -0800188}
189
Stephen Hines37b74a32014-11-26 18:48:20 -0800190} // namespace mcld