1 //===- MipsRelocator.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 "MipsRelocator.h"
10 #include "MipsRelocationFunctions.h"
11
12 #include "mcld/IRBuilder.h"
13 #include "mcld/LinkerConfig.h"
14 #include "mcld/Object/ObjectBuilder.h"
15 #include "mcld/Support/MsgHandling.h"
16 #include "mcld/Target/OutputRelocSection.h"
17 #include "mcld/LD/ELFFileFormat.h"
18
19 #include <llvm/ADT/Twine.h>
20 #include <llvm/Support/ELF.h>
21
22 namespace mcld {
23
24 //===----------------------------------------------------------------------===//
25 // MipsRelocationInfo
26 //===----------------------------------------------------------------------===//
27 class MipsRelocationInfo {
28 public:
HasSubType(const Relocation & pParent,Relocation::Type pType)29 static bool HasSubType(const Relocation& pParent, Relocation::Type pType) {
30 if (llvm::ELF::R_MIPS_NONE == pType)
31 return true;
32
33 for (Relocation::Type type = pParent.type();
34 llvm::ELF::R_MIPS_NONE != (type & 0xff);
35 type >>= 8) {
36 if ((type & 0xff) == pType)
37 return true;
38 }
39
40 return false;
41 }
42
MipsRelocationInfo(Relocation & pParent,bool pIsRel)43 MipsRelocationInfo(Relocation& pParent, bool pIsRel)
44 : m_Parent(&pParent),
45 m_Type(pParent.type()),
46 m_Addend(pIsRel ? pParent.target() : pParent.addend()),
47 m_Symbol(pParent.symValue()),
48 m_Result(pParent.target()) {}
49
isNone() const50 bool isNone() const { return llvm::ELF::R_MIPS_NONE == type(); }
isFirst() const51 bool isFirst() const { return type() == (parent().type() & 0xff); }
isLast() const52 bool isLast() const { return llvm::ELF::R_MIPS_NONE == (m_Type >> 8); }
53
next() const54 MipsRelocationInfo next() const {
55 return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result());
56 }
57
parent() const58 const Relocation& parent() const { return *m_Parent; }
59
parent()60 Relocation& parent() { return *m_Parent; }
61
type() const62 Relocation::Type type() const { return m_Type & 0xff; }
63
A() const64 Relocation::DWord A() const { return m_Addend; }
65
S() const66 Relocation::DWord S() const { return m_Symbol; }
67
P() const68 Relocation::DWord P() const { return parent().place(); }
69
result() const70 Relocation::DWord result() const { return m_Result; }
71
result()72 Relocation::DWord& result() { return m_Result; }
73
74 private:
75 Relocation* m_Parent;
76 Relocation::Type m_Type;
77 Relocation::DWord m_Addend;
78 Relocation::DWord m_Symbol;
79 Relocation::DWord m_Result;
80
MipsRelocationInfo(Relocation & pParent,Relocation::Type pType,Relocation::DWord pResult,Relocation::DWord pAddend)81 MipsRelocationInfo(Relocation& pParent, Relocation::Type pType,
82 Relocation::DWord pResult, Relocation::DWord pAddend)
83 : m_Parent(&pParent),
84 m_Type(pType),
85 m_Addend(pAddend),
86 m_Symbol(0),
87 m_Result(pResult) {}
88 };
89
helper_PLT_init(MipsRelocationInfo & pReloc,MipsRelocator & pParent)90 static void helper_PLT_init(MipsRelocationInfo& pReloc,
91 MipsRelocator& pParent) {
92 ResolveInfo* rsym = pReloc.parent().symInfo();
93 assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL && "PLT entry exists");
94
95 MipsGNULDBackend& backend = pParent.getTarget();
96 PLTEntryBase* pltEntry = backend.getPLT().create();
97 pParent.getSymPLTMap().record(*rsym, *pltEntry);
98
99 assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL &&
100 "PLT entry not exist, but DynRel entry exist!");
101 Fragment* gotpltEntry = backend.getGOTPLT().create();
102 pParent.getSymGOTPLTMap().record(*rsym, *gotpltEntry);
103
104 Relocation* relEntry = backend.getRelPLT().create();
105 relEntry->setType(llvm::ELF::R_MIPS_JUMP_SLOT);
106 relEntry->targetRef().assign(*gotpltEntry);
107 relEntry->setSymInfo(rsym);
108 }
109
helper_get_PLT_address(ResolveInfo & pSym,MipsRelocator & pParent)110 static Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
111 MipsRelocator& pParent) {
112 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
113 assert(plt_entry != NULL);
114 return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
115 }
116
117 //===----------------------------------------------------------------------===//
118 // Relocation Functions and Tables
119 //===----------------------------------------------------------------------===//
120 DECL_MIPS_APPLY_RELOC_FUNCS
121
122 /// the prototype of applying function
123 typedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&,
124 MipsRelocator& pParent);
125
126 // the table entry of applying functions
127 struct ApplyFunctionTriple {
128 ApplyFunctionType func;
129 unsigned int type;
130 const char* name;
131 unsigned int size;
132 };
133
134 // declare the table of applying functions
135 static const ApplyFunctionTriple ApplyFunctions[] = {
136 DECL_MIPS_APPLY_RELOC_FUNC_PTRS};
137
138 //===----------------------------------------------------------------------===//
139 // MipsRelocator
140 //===----------------------------------------------------------------------===//
MipsRelocator(MipsGNULDBackend & pParent,const LinkerConfig & pConfig)141 MipsRelocator::MipsRelocator(MipsGNULDBackend& pParent,
142 const LinkerConfig& pConfig)
143 : Relocator(pConfig),
144 m_Target(pParent),
145 m_pApplyingInput(NULL),
146 m_CurrentLo16Reloc(NULL) {
147 }
148
applyRelocation(Relocation & pReloc)149 Relocator::Result MipsRelocator::applyRelocation(Relocation& pReloc) {
150 // If m_CurrentLo16Reloc is not NULL we are processing
151 // postponed relocation. Otherwise check relocation type
152 // and postpone it for later handling.
153 if (m_CurrentLo16Reloc == NULL && isPostponed(pReloc)) {
154 postponeRelocation(pReloc);
155 return OK;
156 }
157
158 for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone();
159 info = info.next()) {
160 if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0]))
161 return Unknown;
162
163 const ApplyFunctionTriple& triple = ApplyFunctions[info.type()];
164
165 Result res = triple.func(info, *this);
166 if (OK != res)
167 return res;
168
169 if (info.isLast()) {
170 uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size);
171 pReloc.target() &= ~mask;
172 pReloc.target() |= info.result() & mask;
173 }
174 }
175
176 return OK;
177 }
178
getName(Relocation::Type pType) const179 const char* MipsRelocator::getName(Relocation::Type pType) const {
180 return ApplyFunctions[pType & 0xff].name;
181 }
182
scanRelocation(Relocation & pReloc,IRBuilder & pBuilder,Module & pModule,LDSection & pSection,Input & pInput)183 void MipsRelocator::scanRelocation(Relocation& pReloc,
184 IRBuilder& pBuilder,
185 Module& pModule,
186 LDSection& pSection,
187 Input& pInput) {
188 // rsym - The relocation target symbol
189 ResolveInfo* rsym = pReloc.symInfo();
190 assert(rsym != NULL &&
191 "ResolveInfo of relocation not set while scanRelocation");
192
193 // Skip relocation against _gp_disp
194 if (getTarget().getGpDispSymbol() != NULL &&
195 rsym == getTarget().getGpDispSymbol()->resolveInfo())
196 return;
197
198 assert(pSection.getLink() != NULL);
199 if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0)
200 return;
201
202 for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone();
203 info = info.next()) {
204 // We test isLocal or if pInputSym is not a dynamic symbol
205 // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
206 // Don't put undef symbols into local entries.
207 if (isLocalReloc(*rsym))
208 scanLocalReloc(info, pBuilder, pSection);
209 else
210 scanGlobalReloc(info, pBuilder, pSection);
211
212 if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo()))
213 getTarget().addNonPICBranchSym(pReloc.symInfo());
214 }
215
216 // Check if we should issue undefined reference
217 // for the relocation target symbol.
218 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
219 issueUndefRef(pReloc, pSection, pInput);
220 }
221
initializeScan(Input & pInput)222 bool MipsRelocator::initializeScan(Input& pInput) {
223 if (LinkerConfig::Object != config().codeGenType())
224 getTarget().getGOT().initializeScan(pInput);
225 return true;
226 }
227
finalizeScan(Input & pInput)228 bool MipsRelocator::finalizeScan(Input& pInput) {
229 if (LinkerConfig::Object != config().codeGenType())
230 getTarget().getGOT().finalizeScan(pInput);
231 return true;
232 }
233
initializeApply(Input & pInput)234 bool MipsRelocator::initializeApply(Input& pInput) {
235 m_pApplyingInput = &pInput;
236 return true;
237 }
238
finalizeApply(Input & pInput)239 bool MipsRelocator::finalizeApply(Input& pInput) {
240 m_pApplyingInput = NULL;
241 return true;
242 }
243
scanLocalReloc(MipsRelocationInfo & pReloc,IRBuilder & pBuilder,const LDSection & pSection)244 void MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc,
245 IRBuilder& pBuilder,
246 const LDSection& pSection) {
247 ResolveInfo* rsym = pReloc.parent().symInfo();
248
249 switch (pReloc.type()) {
250 case llvm::ELF::R_MIPS_NONE:
251 case llvm::ELF::R_MIPS_16:
252 break;
253 case llvm::ELF::R_MIPS_32:
254 case llvm::ELF::R_MIPS_64:
255 if (pReloc.isFirst() && LinkerConfig::DynObj == config().codeGenType()) {
256 // TODO: (simon) The gold linker does not create an entry in .rel.dyn
257 // section if the symbol section flags contains SHF_EXECINSTR.
258 // 1. Find the reason of this condition.
259 // 2. Check this condition here.
260 getTarget().getRelDyn().reserveEntry();
261 rsym->setReserved(rsym->reserved() | ReserveRel);
262 getTarget().checkAndSetHasTextRel(*pSection.getLink());
263 }
264 break;
265 case llvm::ELF::R_MIPS_REL32:
266 case llvm::ELF::R_MIPS_26:
267 case llvm::ELF::R_MIPS_HI16:
268 case llvm::ELF::R_MIPS_LO16:
269 case llvm::ELF::R_MIPS_SHIFT5:
270 case llvm::ELF::R_MIPS_SHIFT6:
271 case llvm::ELF::R_MIPS_SUB:
272 case llvm::ELF::R_MIPS_INSERT_A:
273 case llvm::ELF::R_MIPS_INSERT_B:
274 case llvm::ELF::R_MIPS_DELETE:
275 case llvm::ELF::R_MIPS_HIGHER:
276 case llvm::ELF::R_MIPS_HIGHEST:
277 case llvm::ELF::R_MIPS_SCN_DISP:
278 case llvm::ELF::R_MIPS_REL16:
279 case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
280 case llvm::ELF::R_MIPS_PJUMP:
281 case llvm::ELF::R_MIPS_RELGOT:
282 case llvm::ELF::R_MIPS_JALR:
283 case llvm::ELF::R_MIPS_GLOB_DAT:
284 case llvm::ELF::R_MIPS_COPY:
285 case llvm::ELF::R_MIPS_JUMP_SLOT:
286 break;
287 case llvm::ELF::R_MIPS_GOT16:
288 case llvm::ELF::R_MIPS_CALL16:
289 case llvm::ELF::R_MIPS_GOT_HI16:
290 case llvm::ELF::R_MIPS_CALL_HI16:
291 case llvm::ELF::R_MIPS_GOT_LO16:
292 case llvm::ELF::R_MIPS_CALL_LO16:
293 case llvm::ELF::R_MIPS_GOT_DISP:
294 case llvm::ELF::R_MIPS_GOT_PAGE:
295 case llvm::ELF::R_MIPS_GOT_OFST:
296 if (getTarget()
297 .getGOT()
298 .reserveLocalEntry(*rsym, pReloc.type(), pReloc.A())) {
299 if (getTarget().getGOT().hasMultipleGOT())
300 getTarget().checkAndSetHasTextRel(*pSection.getLink());
301 }
302 break;
303 case llvm::ELF::R_MIPS_GPREL32:
304 case llvm::ELF::R_MIPS_GPREL16:
305 case llvm::ELF::R_MIPS_LITERAL:
306 break;
307 case llvm::ELF::R_MIPS_TLS_GD:
308 getTarget().getGOT().reserveTLSGdEntry(*rsym);
309 getTarget().checkAndSetHasTextRel(*pSection.getLink());
310 break;
311 case llvm::ELF::R_MIPS_TLS_LDM:
312 getTarget().getGOT().reserveTLSLdmEntry();
313 getTarget().checkAndSetHasTextRel(*pSection.getLink());
314 break;
315 case llvm::ELF::R_MIPS_TLS_GOTTPREL:
316 getTarget().getGOT().reserveTLSGotEntry(*rsym);
317 getTarget().checkAndSetHasTextRel(*pSection.getLink());
318 break;
319 case llvm::ELF::R_MIPS_TLS_DTPMOD32:
320 case llvm::ELF::R_MIPS_TLS_DTPREL32:
321 case llvm::ELF::R_MIPS_TLS_DTPMOD64:
322 case llvm::ELF::R_MIPS_TLS_DTPREL64:
323 case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
324 case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
325 case llvm::ELF::R_MIPS_TLS_TPREL32:
326 case llvm::ELF::R_MIPS_TLS_TPREL64:
327 case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
328 case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
329 break;
330 case llvm::ELF::R_MIPS_PC16:
331 case llvm::ELF::R_MIPS_PC32:
332 case llvm::ELF::R_MIPS_PC18_S3:
333 case llvm::ELF::R_MIPS_PC19_S2:
334 case llvm::ELF::R_MIPS_PC21_S2:
335 case llvm::ELF::R_MIPS_PC26_S2:
336 case llvm::ELF::R_MIPS_PCHI16:
337 case llvm::ELF::R_MIPS_PCLO16:
338 break;
339 default:
340 fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type())
341 << rsym->name();
342 }
343 }
344
scanGlobalReloc(MipsRelocationInfo & pReloc,IRBuilder & pBuilder,const LDSection & pSection)345 void MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc,
346 IRBuilder& pBuilder,
347 const LDSection& pSection) {
348 ResolveInfo* rsym = pReloc.parent().symInfo();
349 bool hasPLT = rsym->reserved() & ReservePLT;
350
351 switch (pReloc.type()) {
352 case llvm::ELF::R_MIPS_NONE:
353 case llvm::ELF::R_MIPS_INSERT_A:
354 case llvm::ELF::R_MIPS_INSERT_B:
355 case llvm::ELF::R_MIPS_DELETE:
356 case llvm::ELF::R_MIPS_TLS_DTPMOD64:
357 case llvm::ELF::R_MIPS_TLS_DTPREL64:
358 case llvm::ELF::R_MIPS_REL16:
359 case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
360 case llvm::ELF::R_MIPS_PJUMP:
361 case llvm::ELF::R_MIPS_RELGOT:
362 case llvm::ELF::R_MIPS_TLS_TPREL64:
363 break;
364 case llvm::ELF::R_MIPS_32:
365 case llvm::ELF::R_MIPS_64:
366 if (pReloc.isFirst() &&
367 getTarget().symbolNeedsDynRel(*rsym, hasPLT, true)) {
368 getTarget().getRelDyn().reserveEntry();
369 rsym->setReserved(rsym->reserved() | ReserveRel);
370 getTarget().checkAndSetHasTextRel(*pSection.getLink());
371 if (!getTarget().symbolFinalValueIsKnown(*rsym))
372 getTarget().getGOT().reserveGlobalEntry(*rsym);
373 }
374 break;
375 case llvm::ELF::R_MIPS_HI16:
376 case llvm::ELF::R_MIPS_LO16:
377 if (getTarget().symbolNeedsDynRel(*rsym, hasPLT, true) ||
378 getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) {
379 getTarget().getRelDyn().reserveEntry();
380 LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym);
381 addCopyReloc(*cpySym.resolveInfo());
382 }
383 break;
384 case llvm::ELF::R_MIPS_GOT16:
385 case llvm::ELF::R_MIPS_CALL16:
386 case llvm::ELF::R_MIPS_GOT_DISP:
387 case llvm::ELF::R_MIPS_GOT_HI16:
388 case llvm::ELF::R_MIPS_CALL_HI16:
389 case llvm::ELF::R_MIPS_GOT_LO16:
390 case llvm::ELF::R_MIPS_CALL_LO16:
391 case llvm::ELF::R_MIPS_GOT_PAGE:
392 case llvm::ELF::R_MIPS_GOT_OFST:
393 if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
394 if (getTarget().getGOT().hasMultipleGOT())
395 getTarget().checkAndSetHasTextRel(*pSection.getLink());
396 }
397 break;
398 case llvm::ELF::R_MIPS_LITERAL:
399 case llvm::ELF::R_MIPS_GPREL32:
400 fatal(diag::invalid_global_relocation) << static_cast<int>(pReloc.type())
401 << rsym->name();
402 break;
403 case llvm::ELF::R_MIPS_GPREL16:
404 break;
405 case llvm::ELF::R_MIPS_26:
406 // Create a PLT entry if the symbol requires it and does not have it.
407 if (getTarget().symbolNeedsPLT(*rsym) && !hasPLT) {
408 helper_PLT_init(pReloc, *this);
409 rsym->setReserved(rsym->reserved() | ReservePLT);
410 }
411 break;
412 case llvm::ELF::R_MIPS_16:
413 case llvm::ELF::R_MIPS_SHIFT5:
414 case llvm::ELF::R_MIPS_SHIFT6:
415 case llvm::ELF::R_MIPS_SUB:
416 case llvm::ELF::R_MIPS_HIGHER:
417 case llvm::ELF::R_MIPS_HIGHEST:
418 case llvm::ELF::R_MIPS_SCN_DISP:
419 break;
420 case llvm::ELF::R_MIPS_TLS_GD:
421 getTarget().getGOT().reserveTLSGdEntry(*rsym);
422 getTarget().checkAndSetHasTextRel(*pSection.getLink());
423 break;
424 case llvm::ELF::R_MIPS_TLS_LDM:
425 getTarget().getGOT().reserveTLSLdmEntry();
426 getTarget().checkAndSetHasTextRel(*pSection.getLink());
427 break;
428 case llvm::ELF::R_MIPS_TLS_GOTTPREL:
429 getTarget().getGOT().reserveTLSGotEntry(*rsym);
430 getTarget().checkAndSetHasTextRel(*pSection.getLink());
431 break;
432 case llvm::ELF::R_MIPS_TLS_DTPREL32:
433 case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
434 case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
435 case llvm::ELF::R_MIPS_TLS_TPREL32:
436 case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
437 case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
438 break;
439 case llvm::ELF::R_MIPS_REL32:
440 case llvm::ELF::R_MIPS_JALR:
441 case llvm::ELF::R_MIPS_PC16:
442 case llvm::ELF::R_MIPS_PC32:
443 case llvm::ELF::R_MIPS_PC18_S3:
444 case llvm::ELF::R_MIPS_PC19_S2:
445 case llvm::ELF::R_MIPS_PC21_S2:
446 case llvm::ELF::R_MIPS_PC26_S2:
447 case llvm::ELF::R_MIPS_PCHI16:
448 case llvm::ELF::R_MIPS_PCLO16:
449 break;
450 case llvm::ELF::R_MIPS_COPY:
451 case llvm::ELF::R_MIPS_GLOB_DAT:
452 case llvm::ELF::R_MIPS_JUMP_SLOT:
453 fatal(diag::dynamic_relocation) << static_cast<int>(pReloc.type());
454 break;
455 default:
456 fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type())
457 << rsym->name();
458 }
459 }
460
isPostponed(const Relocation & pReloc) const461 bool MipsRelocator::isPostponed(const Relocation& pReloc) const {
462 if (isN64ABI())
463 return false;
464
465 if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16) ||
466 MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_PCHI16))
467 return true;
468
469 if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) &&
470 pReloc.symInfo()->isLocal())
471 return true;
472
473 return false;
474 }
475
addCopyReloc(ResolveInfo & pSym)476 void MipsRelocator::addCopyReloc(ResolveInfo& pSym) {
477 Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
478 relEntry.setType(llvm::ELF::R_MIPS_COPY);
479 assert(pSym.outSymbol()->hasFragRef());
480 relEntry.targetRef().assign(*pSym.outSymbol()->fragRef());
481 relEntry.setSymInfo(&pSym);
482 }
483
defineSymbolforCopyReloc(IRBuilder & pBuilder,const ResolveInfo & pSym)484 LDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
485 const ResolveInfo& pSym) {
486 // Get or create corresponding BSS LDSection
487 ELFFileFormat* fileFormat = getTarget().getOutputFormat();
488 LDSection* bssSectHdr = ResolveInfo::ThreadLocal == pSym.type()
489 ? &fileFormat->getTBSS()
490 : &fileFormat->getBSS();
491
492 // Get or create corresponding BSS SectionData
493 SectionData* bssData = bssSectHdr->hasSectionData()
494 ? bssSectHdr->getSectionData()
495 : IRBuilder::CreateSectionData(*bssSectHdr);
496
497 // Determine the alignment by the symbol value
498 // FIXME: here we use the largest alignment
499 uint32_t addrAlign = config().targets().bitclass() / 8;
500
501 // Allocate space in BSS for the copy symbol
502 Fragment* frag = new FillFragment(0x0, 1, pSym.size());
503 uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign);
504 bssSectHdr->setSize(bssSectHdr->size() + size);
505
506 // Change symbol binding to Global if it's a weak symbol
507 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
508 if (binding == ResolveInfo::Weak)
509 binding = ResolveInfo::Global;
510
511 // Define the copy symbol in the bss section and resolve it
512 LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
513 pSym.name(),
514 (ResolveInfo::Type)pSym.type(),
515 ResolveInfo::Define,
516 binding,
517 pSym.size(), // size
518 0x0, // value
519 FragmentRef::Create(*frag, 0x0),
520 (ResolveInfo::Visibility)pSym.other());
521
522 // Output all other alias symbols if any
523 Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym);
524 if (alias_list == NULL)
525 return *cpySym;
526
527 for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end();
528 it != ie;
529 ++it) {
530 const ResolveInfo* alias = *it;
531 if (alias == &pSym || !alias->isDyn())
532 continue;
533
534 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
535 alias->name(),
536 (ResolveInfo::Type)alias->type(),
537 ResolveInfo::Define,
538 binding,
539 alias->size(), // size
540 0x0, // value
541 FragmentRef::Create(*frag, 0x0),
542 (ResolveInfo::Visibility)alias->other());
543 }
544
545 return *cpySym;
546 }
547
postponeRelocation(Relocation & pReloc)548 void MipsRelocator::postponeRelocation(Relocation& pReloc) {
549 ResolveInfo* rsym = pReloc.symInfo();
550 m_PostponedRelocs[rsym].insert(&pReloc);
551 }
552
applyPostponedRelocations(MipsRelocationInfo & pLo16Reloc)553 void MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc) {
554 m_CurrentLo16Reloc = &pLo16Reloc;
555
556 ResolveInfo* rsym = pLo16Reloc.parent().symInfo();
557
558 RelocationSet& relocs = m_PostponedRelocs[rsym];
559 for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it)
560 (*it)->apply(*this);
561
562 m_PostponedRelocs.erase(rsym);
563
564 m_CurrentLo16Reloc = NULL;
565 }
566
isGpDisp(const Relocation & pReloc) const567 bool MipsRelocator::isGpDisp(const Relocation& pReloc) const {
568 return strcmp("_gp_disp", pReloc.symInfo()->name()) == 0;
569 }
570
isRel() const571 bool MipsRelocator::isRel() const {
572 return config().targets().is32Bits();
573 }
574
isLocalReloc(ResolveInfo & pSym) const575 bool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const {
576 if (pSym.isUndef())
577 return false;
578
579 return pSym.isLocal() || !getTarget().isDynamicSymbol(pSym) || !pSym.isDyn();
580 }
581
getGPAddress()582 Relocator::Address MipsRelocator::getGPAddress() {
583 return getTarget().getGOT().getGPAddr(getApplyingInput());
584 }
585
getTPOffset()586 Relocator::Address MipsRelocator::getTPOffset() {
587 return getTarget().getTPOffset(getApplyingInput());
588 }
589
getDTPOffset()590 Relocator::Address MipsRelocator::getDTPOffset() {
591 return getTarget().getDTPOffset(getApplyingInput());
592 }
593
getGP0()594 Relocator::Address MipsRelocator::getGP0() {
595 return getTarget().getGP0(getApplyingInput());
596 }
597
getLocalGOTEntry(MipsRelocationInfo & pReloc,Relocation::DWord entryValue)598 Fragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc,
599 Relocation::DWord entryValue) {
600 // rsym - The relocation target symbol
601 ResolveInfo* rsym = pReloc.parent().symInfo();
602 MipsGOT& got = getTarget().getGOT();
603
604 assert(isLocalReloc(*rsym) &&
605 "Attempt to get a global GOT entry for the local relocation");
606
607 Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue);
608
609 // Found a mapping, then return the mapped entry immediately.
610 if (got_entry != NULL)
611 return *got_entry;
612
613 // Not found.
614 got_entry = got.consumeLocal();
615
616 if (got.isPrimaryGOTConsumed())
617 setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), NULL);
618 else
619 got.setEntryValue(got_entry, entryValue);
620
621 got.recordLocalEntry(rsym, entryValue, got_entry);
622
623 return *got_entry;
624 }
625
getGlobalGOTEntry(MipsRelocationInfo & pReloc)626 Fragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc) {
627 // rsym - The relocation target symbol
628 ResolveInfo* rsym = pReloc.parent().symInfo();
629 MipsGOT& got = getTarget().getGOT();
630
631 assert(!isLocalReloc(*rsym) &&
632 "Attempt to get a local GOT entry for the global relocation");
633
634 Fragment* got_entry = got.lookupGlobalEntry(rsym);
635
636 // Found a mapping, then return the mapped entry immediately.
637 if (got_entry != NULL)
638 return *got_entry;
639
640 // Not found.
641 got_entry = got.consumeGlobal();
642
643 if (got.isPrimaryGOTConsumed())
644 setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), rsym);
645 else
646 got.setEntryValue(got_entry, pReloc.parent().symValue());
647
648 got.recordGlobalEntry(rsym, got_entry);
649
650 return *got_entry;
651 }
652
getTLSGOTEntry(MipsRelocationInfo & pReloc)653 Fragment& MipsRelocator::getTLSGOTEntry(MipsRelocationInfo& pReloc) {
654 // rsym - The relocation target symbol
655 ResolveInfo* rsym = pReloc.parent().symInfo();
656 MipsGOT& got = getTarget().getGOT();
657
658 Fragment* modEntry = got.lookupTLSEntry(rsym, pReloc.type());
659
660 // Found a mapping, then return the mapped entry immediately.
661 if (modEntry != NULL)
662 return *modEntry;
663
664 // Not found.
665 modEntry = got.consumeTLS(pReloc.type());
666 setupTLSDynEntry(*modEntry, rsym, pReloc.type());
667 got.recordTLSEntry(rsym, modEntry, pReloc.type());
668
669 return *modEntry;
670 }
671
getGOTOffset(MipsRelocationInfo & pReloc)672 Relocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc) {
673 ResolveInfo* rsym = pReloc.parent().symInfo();
674 MipsGOT& got = getTarget().getGOT();
675
676 if (isLocalReloc(*rsym)) {
677 uint64_t value = pReloc.S();
678
679 if (ResolveInfo::Section == rsym->type())
680 value += pReloc.A();
681
682 return got.getGPRelOffset(getApplyingInput(),
683 getLocalGOTEntry(pReloc, value));
684 } else {
685 return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc));
686 }
687 }
688
getTLSGOTOffset(MipsRelocationInfo & pReloc)689 Relocator::Address MipsRelocator::getTLSGOTOffset(MipsRelocationInfo& pReloc) {
690 MipsGOT& got = getTarget().getGOT();
691 return got.getGPRelOffset(getApplyingInput(), getTLSGOTEntry(pReloc));
692 }
693
createDynRel(MipsRelocationInfo & pReloc)694 void MipsRelocator::createDynRel(MipsRelocationInfo& pReloc) {
695 Relocator::DWord A = pReloc.A();
696 Relocator::DWord S = pReloc.S();
697
698 ResolveInfo* rsym = pReloc.parent().symInfo();
699
700 if (getTarget().isDynamicSymbol(*rsym)) {
701 setupRel32DynEntry(pReloc.parent().targetRef(), rsym);
702 // Don't add symbol value that will be resolved by the dynamic linker.
703 pReloc.result() = A;
704 } else {
705 setupRel32DynEntry(pReloc.parent().targetRef(), NULL);
706 pReloc.result() = A + S;
707 }
708
709 if (!isLocalReloc(*rsym) && !getTarget().symbolFinalValueIsKnown(*rsym))
710 getGlobalGOTEntry(pReloc);
711 }
712
calcAHL(const MipsRelocationInfo & pHiReloc)713 uint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc) {
714 if (isN64ABI())
715 return pHiReloc.A();
716
717 assert(m_CurrentLo16Reloc != NULL &&
718 "There is no saved R_MIPS_LO16 relocation");
719
720 uint64_t AHI = pHiReloc.A() & 0xFFFF;
721 uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF;
722 uint64_t AHL = (AHI << 16) + int16_t(ALO);
723
724 return AHL;
725 }
726
isN64ABI() const727 bool MipsRelocator::isN64ABI() const {
728 return config().targets().is64Bits();
729 }
730
getDebugStringOffset(Relocation & pReloc) const731 uint32_t MipsRelocator::getDebugStringOffset(Relocation& pReloc) const {
732 if (pReloc.type() != llvm::ELF::R_MIPS_32)
733 error(diag::unsupport_reloc_for_debug_string)
734 << getName(pReloc.type()) << "mclinker@googlegroups.com";
735 if (pReloc.symInfo()->type() == ResolveInfo::Section)
736 return pReloc.target() + pReloc.addend();
737 else
738 return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
739 pReloc.target() + pReloc.addend();
740 }
741
applyDebugStringOffset(Relocation & pReloc,uint32_t pOffset)742 void MipsRelocator::applyDebugStringOffset(Relocation& pReloc,
743 uint32_t pOffset) {
744 pReloc.target() = pOffset;
745 }
746
setupRelDynEntry(FragmentRef & pFragRef,ResolveInfo * pSym,Relocation::Type pType)747 void MipsRelocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym,
748 Relocation::Type pType) {
749 Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
750 relEntry.setType(pType);
751 relEntry.targetRef() = pFragRef;
752 relEntry.setSymInfo(pSym);
753 }
754
755 //===----------------------------------------------------------------------===//
756 // Mips32Relocator
757 //===----------------------------------------------------------------------===//
Mips32Relocator(Mips32GNULDBackend & pParent,const LinkerConfig & pConfig)758 Mips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent,
759 const LinkerConfig& pConfig)
760 : MipsRelocator(pParent, pConfig) {
761 }
762
setupRel32DynEntry(FragmentRef & pFragRef,ResolveInfo * pSym)763 void Mips32Relocator::setupRel32DynEntry(FragmentRef& pFragRef,
764 ResolveInfo* pSym) {
765 setupRelDynEntry(pFragRef, pSym, llvm::ELF::R_MIPS_REL32);
766 }
767
setupTLSDynEntry(Fragment & pFrag,ResolveInfo * pSym,Relocation::Type pType)768 void Mips32Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym,
769 Relocation::Type pType) {
770 pSym = pSym->isLocal() ? nullptr : pSym;
771 if (pType == llvm::ELF::R_MIPS_TLS_GD) {
772 FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
773 setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32);
774 FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0);
775 setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL32);
776 } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) {
777 FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
778 setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32);
779 } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) {
780 FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
781 setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL32);
782 } else {
783 llvm_unreachable("Unexpected relocation");
784 }
785 }
786
getSize(Relocation::Type pType) const787 Relocator::Size Mips32Relocator::getSize(Relocation::Type pType) const {
788 return ApplyFunctions[pType & 0xff].size;
789 }
790
791 //===----------------------------------------------------------------------===//
792 // Mips64Relocator
793 //===----------------------------------------------------------------------===//
Mips64Relocator(Mips64GNULDBackend & pParent,const LinkerConfig & pConfig)794 Mips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent,
795 const LinkerConfig& pConfig)
796 : MipsRelocator(pParent, pConfig) {
797 }
798
setupRel32DynEntry(FragmentRef & pFragRef,ResolveInfo * pSym)799 void Mips64Relocator::setupRel32DynEntry(FragmentRef& pFragRef,
800 ResolveInfo* pSym) {
801 Relocation::Type type = llvm::ELF::R_MIPS_REL32 | llvm::ELF::R_MIPS_64 << 8;
802 setupRelDynEntry(pFragRef, pSym, type);
803 }
804
setupTLSDynEntry(Fragment & pFrag,ResolveInfo * pSym,Relocation::Type pType)805 void Mips64Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym,
806 Relocation::Type pType) {
807 pSym = pSym->isLocal() ? nullptr : pSym;
808 if (pType == llvm::ELF::R_MIPS_TLS_GD) {
809 FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
810 setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64);
811 FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0);
812 setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL64);
813 } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) {
814 FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
815 setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64);
816 } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) {
817 FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
818 setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL64);
819 } else {
820 llvm_unreachable("Unexpected relocation");
821 }
822 }
823
getSize(Relocation::Type pType) const824 Relocator::Size Mips64Relocator::getSize(Relocation::Type pType) const {
825 if (((pType >> 16) & 0xff) != llvm::ELF::R_MIPS_NONE)
826 return ApplyFunctions[(pType >> 16) & 0xff].size;
827 if (((pType >> 8) & 0xff) != llvm::ELF::R_MIPS_NONE)
828 return ApplyFunctions[(pType >> 8) & 0xff].size;
829 return ApplyFunctions[pType & 0xff].size;
830 }
831
832 //=========================================//
833 // Relocation functions implementation //
834 //=========================================//
835
836 // R_MIPS_NONE and those unsupported/deprecated relocation type
none(MipsRelocationInfo & pReloc,MipsRelocator & pParent)837 static MipsRelocator::Result none(MipsRelocationInfo& pReloc,
838 MipsRelocator& pParent) {
839 return Relocator::OK;
840 }
841
842 // R_MIPS_32: S + A
abs32(MipsRelocationInfo & pReloc,MipsRelocator & pParent)843 static MipsRelocator::Result abs32(MipsRelocationInfo& pReloc,
844 MipsRelocator& pParent) {
845 ResolveInfo* rsym = pReloc.parent().symInfo();
846
847 Relocator::DWord A = pReloc.A();
848 Relocator::DWord S = pReloc.S();
849
850 LDSection& target_sect =
851 pReloc.parent().targetRef().frag()->getParent()->getSection();
852
853 // If the flag of target section is not ALLOC, we will not scan this
854 // relocation
855 // but perform static relocation. (e.g., applying .debug section)
856 if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
857 pReloc.result() = S + A;
858 return Relocator::OK;
859 }
860
861 if (rsym->reserved() & MipsRelocator::ReserveRel) {
862 pParent.createDynRel(pReloc);
863 return Relocator::OK;
864 }
865
866 pReloc.result() = S + A;
867
868 return Relocator::OK;
869 }
870
871 // R_MIPS_26:
872 // local : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
873 // external: (sign–extend(A) + S) >> 2
rel26(MipsRelocationInfo & pReloc,MipsRelocator & pParent)874 static MipsRelocator::Result rel26(MipsRelocationInfo& pReloc,
875 MipsRelocator& pParent) {
876 ResolveInfo* rsym = pReloc.parent().symInfo();
877
878 int32_t A = pParent.isN64ABI() ? pReloc.A() : (pReloc.A() & 0x03FFFFFF) << 2;
879 int32_t P = pReloc.P();
880 int32_t S = rsym->reserved() & MipsRelocator::ReservePLT
881 ? helper_get_PLT_address(*rsym, pParent)
882 : pReloc.S();
883
884 if (rsym->isLocal())
885 pReloc.result() = A | ((P + 4) & 0x3F000000);
886 else
887 pReloc.result() = signExtend<28>(A);
888
889 pReloc.result() = (pReloc.result() + S) >> 2;
890
891 return Relocator::OK;
892 }
893
894 // R_MIPS_HI16:
895 // local/external: ((AHL + S) - (short)(AHL + S)) >> 16
896 // _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
hi16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)897 static MipsRelocator::Result hi16(MipsRelocationInfo& pReloc,
898 MipsRelocator& pParent) {
899 uint64_t AHL = pParent.calcAHL(pReloc);
900
901 if (pParent.isGpDisp(pReloc.parent())) {
902 int32_t P = pReloc.P();
903 int32_t GP = pParent.getGPAddress();
904 pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
905 } else {
906 int32_t S = pReloc.S();
907 if (pParent.isN64ABI())
908 pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16;
909 else
910 pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
911 }
912
913 return Relocator::OK;
914 }
915
916 // R_MIPS_LO16:
917 // local/external: AHL + S
918 // _gp_disp : AHL + GP - P + 4
lo16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)919 static MipsRelocator::Result lo16(MipsRelocationInfo& pReloc,
920 MipsRelocator& pParent) {
921 // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16
922 // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16
923 // addend here.
924 int32_t AHL = (pReloc.A() & 0xFFFF);
925
926 if (pParent.isGpDisp(pReloc.parent())) {
927 int32_t P = pReloc.P();
928 int32_t GP = pParent.getGPAddress();
929 pReloc.result() = AHL + GP - P + 4;
930 } else {
931 int32_t S = pReloc.S();
932 pReloc.result() = AHL + S;
933 }
934
935 pParent.applyPostponedRelocations(pReloc);
936
937 return Relocator::OK;
938 }
939
940 // R_MIPS_GPREL16:
941 // external: sign–extend(A) + S - GP
942 // local : sign–extend(A) + S + GP0 – GP
gprel16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)943 static MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc,
944 MipsRelocator& pParent) {
945 // Remember to add the section offset to A.
946 uint64_t A = pReloc.A();
947 uint64_t S = pReloc.S();
948 uint64_t GP0 = pParent.getGP0();
949 uint64_t GP = pParent.getGPAddress();
950
951 ResolveInfo* rsym = pReloc.parent().symInfo();
952 if (rsym->isLocal())
953 pReloc.result() = A + S + GP0 - GP;
954 else
955 pReloc.result() = A + S - GP;
956
957 return Relocator::OK;
958 }
959
960 // R_MIPS_GOT16:
961 // local : G (calculate AHL and put high 16 bit to GOT)
962 // external: G
got16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)963 static MipsRelocator::Result got16(MipsRelocationInfo& pReloc,
964 MipsRelocator& pParent) {
965 if (pReloc.parent().symInfo()->isLocal()) {
966 int32_t AHL = pParent.calcAHL(pReloc);
967 int32_t S = pReloc.S();
968 int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
969
970 MipsGOT& got = pParent.getTarget().getGOT();
971
972 Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res);
973
974 pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
975 } else {
976 pReloc.result() = pParent.getGOTOffset(pReloc);
977 }
978
979 return Relocator::OK;
980 }
981
982 // R_MIPS_GOTHI16:
983 // external: (G - (short)G) >> 16 + A
gothi16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)984 static MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc,
985 MipsRelocator& pParent) {
986 Relocator::Address G = pParent.getGOTOffset(pReloc);
987 int32_t A = pReloc.A();
988
989 pReloc.result() = (G - (int16_t)G) >> (16 + A);
990
991 return Relocator::OK;
992 }
993
994 // R_MIPS_GOTLO16:
995 // external: G & 0xffff
gotlo16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)996 static MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc,
997 MipsRelocator& pParent) {
998 pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff;
999
1000 return Relocator::OK;
1001 }
1002
1003 // R_MIPS_SUB:
1004 // external/local: S - A
sub(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1005 static MipsRelocator::Result sub(MipsRelocationInfo& pReloc,
1006 MipsRelocator& pParent) {
1007 uint64_t S = pReloc.S();
1008 uint64_t A = pReloc.A();
1009
1010 pReloc.result() = S - A;
1011
1012 return Relocator::OK;
1013 }
1014
1015 // R_MIPS_CALL16: G
call16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1016 static MipsRelocator::Result call16(MipsRelocationInfo& pReloc,
1017 MipsRelocator& pParent) {
1018 pReloc.result() = pParent.getGOTOffset(pReloc);
1019
1020 return Relocator::OK;
1021 }
1022
1023 // R_MIPS_GPREL32: A + S + GP0 - GP
gprel32(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1024 static MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc,
1025 MipsRelocator& pParent) {
1026 // Remember to add the section offset to A.
1027 uint64_t A = pReloc.A();
1028 uint64_t S = pReloc.S();
1029 uint64_t GP0 = pParent.getGP0();
1030 uint64_t GP = pParent.getGPAddress();
1031
1032 pReloc.result() = A + S + GP0 - GP;
1033
1034 return Relocator::OK;
1035 }
1036
1037 // R_MIPS_64: S + A
abs64(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1038 static MipsRelocator::Result abs64(MipsRelocationInfo& pReloc,
1039 MipsRelocator& pParent) {
1040 // FIXME (simon): Consider to merge with abs32() or use the same function
1041 // but with another mask size.
1042 ResolveInfo* rsym = pReloc.parent().symInfo();
1043
1044 Relocator::DWord A = pReloc.A();
1045 Relocator::DWord S = pReloc.S();
1046
1047 LDSection& target_sect =
1048 pReloc.parent().targetRef().frag()->getParent()->getSection();
1049
1050 // If the flag of target section is not ALLOC, we will not scan this
1051 // relocation
1052 // but perform static relocation. (e.g., applying .debug section)
1053 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1054 pReloc.result() = S + A;
1055 return Relocator::OK;
1056 }
1057
1058 if (rsym->reserved() & MipsRelocator::ReserveRel) {
1059 pParent.createDynRel(pReloc);
1060 return Relocator::OK;
1061 }
1062
1063 pReloc.result() = S + A;
1064
1065 return Relocator::OK;
1066 }
1067
1068 // R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G
gotdisp(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1069 static MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc,
1070 MipsRelocator& pParent) {
1071 pReloc.result() = pParent.getGOTOffset(pReloc);
1072
1073 return Relocator::OK;
1074 }
1075
1076 // R_MIPS_GOT_OFST:
gotoff(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1077 static MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc,
1078 MipsRelocator& pParent) {
1079 // FIXME (simon): Needs to be implemented.
1080 return Relocator::OK;
1081 }
1082
1083 // R_MIPS_JALR:
jalr(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1084 static MipsRelocator::Result jalr(MipsRelocationInfo& pReloc,
1085 MipsRelocator& pParent) {
1086 return Relocator::OK;
1087 }
1088
1089 // R_MIPS_PC16
pc16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1090 static MipsRelocator::Result pc16(MipsRelocationInfo& pReloc,
1091 MipsRelocator& pParent) {
1092 int64_t A = signExtend<18>(pReloc.A() << 2);
1093 int64_t S = pReloc.S();
1094 int64_t P = pReloc.P();
1095 pReloc.result() = (A + S - P) >> 2;
1096 return Relocator::OK;
1097 }
1098
1099 // R_MIPS_PC32
pc32(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1100 static MipsRelocator::Result pc32(MipsRelocationInfo& pReloc,
1101 MipsRelocator& pParent) {
1102 int64_t A = pReloc.A();
1103 int64_t S = pReloc.S();
1104 int64_t P = pReloc.P();
1105 pReloc.result() = A + S - P;
1106 return Relocator::OK;
1107 }
1108
1109 // R_MIPS_PC18_S3
pc18_s3(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1110 static MipsRelocator::Result pc18_s3(MipsRelocationInfo& pReloc,
1111 MipsRelocator& pParent) {
1112 int64_t A = signExtend<21>(pReloc.A() << 3);
1113 int64_t S = pReloc.S();
1114 int64_t P = pReloc.P();
1115 pReloc.result() = (S + A - ((P | 7) ^ 7)) >> 3;
1116 return Relocator::OK;
1117 }
1118
1119 // R_MIPS_PC19_S2
pc19_s2(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1120 static MipsRelocator::Result pc19_s2(MipsRelocationInfo& pReloc,
1121 MipsRelocator& pParent) {
1122 int64_t A = signExtend<21>(pReloc.A() << 2);
1123 int64_t S = pReloc.S();
1124 int64_t P = pReloc.P();
1125 pReloc.result() = (A + S - P) >> 2;
1126 return Relocator::OK;
1127 }
1128
1129 // R_MIPS_PC21_S2
pc21_s2(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1130 static MipsRelocator::Result pc21_s2(MipsRelocationInfo& pReloc,
1131 MipsRelocator& pParent) {
1132 int32_t A = signExtend<23>(pReloc.A() << 2);
1133 int32_t S = pReloc.S();
1134 int32_t P = pReloc.P();
1135 pReloc.result() = (A + S - P) >> 2;
1136 return Relocator::OK;
1137 }
1138
1139 // R_MIPS_PC26_S2
pc26_s2(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1140 static MipsRelocator::Result pc26_s2(MipsRelocationInfo& pReloc,
1141 MipsRelocator& pParent) {
1142 int64_t A = signExtend<28>(pReloc.A() << 2);
1143 int64_t S = pReloc.S();
1144 int64_t P = pReloc.P();
1145 pReloc.result() = (A + S - P) >> 2;
1146 return Relocator::OK;
1147 }
1148
1149 // R_MIPS_PCHI16
pchi16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1150 static MipsRelocator::Result pchi16(MipsRelocationInfo& pReloc,
1151 MipsRelocator& pParent) {
1152 uint64_t AHL = pParent.calcAHL(pReloc);
1153 int64_t S = pReloc.S();
1154 int64_t P = pReloc.P();
1155 pReloc.result() = (S + AHL - P + 0x8000) >> 16;
1156 return Relocator::OK;
1157 }
1158
1159 // R_MIPS_PCLO16
pclo16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1160 static MipsRelocator::Result pclo16(MipsRelocationInfo& pReloc,
1161 MipsRelocator& pParent) {
1162 int32_t AHL = pReloc.A() & 0xFFFF;
1163 int64_t S = pReloc.S();
1164 int64_t P = pReloc.P();
1165 pReloc.result() = S + AHL - P;
1166 pParent.applyPostponedRelocations(pReloc);
1167 return Relocator::OK;
1168 }
1169
1170 // R_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_DTPREL_HI16
1171 // local/external: (A + S - TP Offset) >> 16
1172 // _gp_disp : (A + GP - P - TP Offset) >> 16
tlshi16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1173 static MipsRelocator::Result tlshi16(MipsRelocationInfo& pReloc,
1174 MipsRelocator& pParent) {
1175 uint64_t A = pReloc.A() & 0xFFFF;
1176 if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_HI16)
1177 A -= pParent.getTPOffset();
1178 else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_HI16)
1179 A -= pParent.getDTPOffset();
1180 else
1181 llvm_unreachable("Unexpected relocation");
1182
1183 if (pParent.isGpDisp(pReloc.parent()))
1184 pReloc.result() = (A + pReloc.S() - pReloc.P() + 0x8000) >> 16;
1185 else
1186 pReloc.result() = (A + pReloc.S() + 0x8000) >> 16;
1187
1188 return Relocator::OK;
1189 }
1190
1191 // R_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_DTPREL_LO16
1192 // local/external: A + S - TP Offset
1193 // _gp_disp : A + GP - P + 4 - TP Offset
tlslo16(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1194 static MipsRelocator::Result tlslo16(MipsRelocationInfo& pReloc,
1195 MipsRelocator& pParent) {
1196 uint64_t A = pReloc.A() & 0xFFFF;
1197 if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_LO16)
1198 A -= pParent.getTPOffset();
1199 else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_LO16)
1200 A -= pParent.getDTPOffset();
1201 else
1202 llvm_unreachable("Unexpected relocation");
1203
1204 if (pParent.isGpDisp(pReloc.parent()))
1205 pReloc.result() = A + pReloc.S() - pReloc.P() + 4;
1206 else
1207 pReloc.result() = A + pReloc.S();
1208
1209 return Relocator::OK;
1210 }
1211
1212 // R_MIPS_TLS_GD, R_MIPS_TLS_LDM
tlsgot(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1213 static MipsRelocator::Result tlsgot(MipsRelocationInfo& pReloc,
1214 MipsRelocator& pParent) {
1215 pReloc.result() = pParent.getTLSGOTOffset(pReloc);
1216 return Relocator::OK;
1217 }
1218
unsupported(MipsRelocationInfo & pReloc,MipsRelocator & pParent)1219 static MipsRelocator::Result unsupported(MipsRelocationInfo& pReloc,
1220 MipsRelocator& pParent) {
1221 return Relocator::Unsupported;
1222 }
1223
1224 } // namespace mcld
1225