blob: d4e8145ba2f1aa2a81e90d17313ae838204aa7a5 [file] [log] [blame]
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001//===- MipsLDBackend.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//===----------------------------------------------------------------------===//
Shih-wei Liaocedee4b2012-08-02 23:13:03 -07009#include "Mips.h"
Shih-wei Liaod0fbbb22013-01-03 06:23:31 -080010#include "MipsGNUInfo.h"
Shih-wei Liaocedee4b2012-08-02 23:13:03 -070011#include "MipsELFDynamic.h"
Stephen Hines87f34652014-02-14 18:00:16 -080012#include "MipsLA25Stub.h"
Shih-wei Liaocedee4b2012-08-02 23:13:03 -070013#include "MipsLDBackend.h"
Shih-wei Liaod0fbbb22013-01-03 06:23:31 -080014#include "MipsRelocator.h"
Shih-wei Liaocedee4b2012-08-02 23:13:03 -070015
Stephen Hines37b74a32014-11-26 18:48:20 -080016#include "mcld/IRBuilder.h"
17#include "mcld/LinkerConfig.h"
18#include "mcld/Module.h"
Stephen Hinescfcb2242016-03-08 00:18:09 -080019#include "mcld/Fragment/AlignFragment.h"
Stephen Hines37b74a32014-11-26 18:48:20 -080020#include "mcld/Fragment/FillFragment.h"
21#include "mcld/LD/BranchIslandFactory.h"
22#include "mcld/LD/LDContext.h"
23#include "mcld/LD/StubFactory.h"
24#include "mcld/LD/ELFFileFormat.h"
Stephen Hinescfcb2242016-03-08 00:18:09 -080025#include "mcld/LD/ELFSegment.h"
26#include "mcld/LD/ELFSegmentFactory.h"
Stephen Hines37b74a32014-11-26 18:48:20 -080027#include "mcld/MC/Attribute.h"
28#include "mcld/Object/ObjectBuilder.h"
29#include "mcld/Support/MemoryRegion.h"
30#include "mcld/Support/MemoryArea.h"
31#include "mcld/Support/MsgHandling.h"
32#include "mcld/Support/TargetRegistry.h"
33#include "mcld/Target/OutputRelocSection.h"
34
Shih-wei Liao5460a1f2012-03-16 22:41:16 -070035#include <llvm/ADT/Triple.h>
Stephen Hinescfcb2242016-03-08 00:18:09 -080036#include <llvm/Object/ELFTypes.h>
Stephen Hines87f34652014-02-14 18:00:16 -080037#include <llvm/Support/Casting.h>
Shih-wei Liao5460a1f2012-03-16 22:41:16 -070038#include <llvm/Support/ELF.h>
Stephen Hines87f34652014-02-14 18:00:16 -080039#include <llvm/Support/Host.h>
Stephen Hinescfcb2242016-03-08 00:18:09 -080040#include <llvm/Support/MipsABIFlags.h>
41
42#include <vector>
Shih-wei Liao5460a1f2012-03-16 22:41:16 -070043
Stephen Hines37b74a32014-11-26 18:48:20 -080044namespace mcld {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -070045
Shih-wei Liao22add6f2012-12-15 17:21:00 -080046//===----------------------------------------------------------------------===//
47// MipsGNULDBackend
48//===----------------------------------------------------------------------===//
Shih-wei Liaod0fbbb22013-01-03 06:23:31 -080049MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig,
50 MipsGNUInfo* pInfo)
Stephen Hines37b74a32014-11-26 18:48:20 -080051 : GNULDBackend(pConfig, pInfo),
52 m_pRelocator(NULL),
53 m_pGOT(NULL),
54 m_pPLT(NULL),
55 m_pGOTPLT(NULL),
56 m_pInfo(*pInfo),
57 m_pRelPlt(NULL),
58 m_pRelDyn(NULL),
59 m_pDynamic(NULL),
Stephen Hinescfcb2242016-03-08 00:18:09 -080060 m_pAbiFlags(NULL),
Stephen Hines37b74a32014-11-26 18:48:20 -080061 m_pGOTSymbol(NULL),
62 m_pPLTSymbol(NULL),
63 m_pGpDispSymbol(NULL) {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -070064}
65
Stephen Hines37b74a32014-11-26 18:48:20 -080066MipsGNULDBackend::~MipsGNULDBackend() {
Shih-wei Liaod0fbbb22013-01-03 06:23:31 -080067 delete m_pRelocator;
Stephen Hines87f34652014-02-14 18:00:16 -080068 delete m_pPLT;
69 delete m_pRelPlt;
Shih-wei Liao22add6f2012-12-15 17:21:00 -080070 delete m_pRelDyn;
71 delete m_pDynamic;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -070072}
73
Stephen Hines87f34652014-02-14 18:00:16 -080074bool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType,
Stephen Hines37b74a32014-11-26 18:48:20 -080075 const mcld::ResolveInfo* pSym) {
Stephen Hines87f34652014-02-14 18:00:16 -080076 if (config().isCodeIndep())
77 return false;
Shih-wei Liao22add6f2012-12-15 17:21:00 -080078
Stephen Hines87f34652014-02-14 18:00:16 -080079 if (llvm::ELF::R_MIPS_26 != pType)
80 return false;
Shih-wei Liao22add6f2012-12-15 17:21:00 -080081
Stephen Hines87f34652014-02-14 18:00:16 -080082 if (pSym->isLocal())
83 return false;
84
85 return true;
86}
87
Stephen Hines37b74a32014-11-26 18:48:20 -080088void MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym) {
Stephen Hines87f34652014-02-14 18:00:16 -080089 m_HasNonPICBranchSyms.insert(rsym);
90}
91
Stephen Hines37b74a32014-11-26 18:48:20 -080092bool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const {
Stephen Hines87f34652014-02-14 18:00:16 -080093 return m_HasNonPICBranchSyms.count(rsym);
94}
95
96void MipsGNULDBackend::initTargetSections(Module& pModule,
Stephen Hines37b74a32014-11-26 18:48:20 -080097 ObjectBuilder& pBuilder) {
Stephen Hines87f34652014-02-14 18:00:16 -080098 if (LinkerConfig::Object == config().codeGenType())
99 return;
100
101 ELFFileFormat* file_format = getOutputFormat();
102
103 // initialize .rel.plt
104 LDSection& relplt = file_format->getRelPlt();
105 m_pRelPlt = new OutputRelocSection(pModule, relplt);
106
107 // initialize .rel.dyn
108 LDSection& reldyn = file_format->getRelDyn();
109 m_pRelDyn = new OutputRelocSection(pModule, reldyn);
Stephen Hinescfcb2242016-03-08 00:18:09 -0800110
111 // initialize .sdata
112 m_psdata = pBuilder.CreateSection(
113 ".sdata", LDFileFormat::Target, llvm::ELF::SHT_PROGBITS,
114 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_MIPS_GPREL,
115 4);
116
117 // initialize .MIPS.abiflags
118 m_pAbiFlags = pBuilder.CreateSection(".MIPS.abiflags", LDFileFormat::Target,
119 llvm::ELF::SHT_MIPS_ABIFLAGS,
120 llvm::ELF::SHF_ALLOC, 4);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700121}
122
Stephen Hines37b74a32014-11-26 18:48:20 -0800123void MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700124 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
125 // same name in input
Stephen Hines6f757552013-03-04 19:51:03 -0800126 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
Stephen Hines37b74a32014-11-26 18:48:20 -0800127 "_GLOBAL_OFFSET_TABLE_",
128 ResolveInfo::Object,
129 ResolveInfo::Define,
130 ResolveInfo::Local,
131 0x0, // size
132 0x0, // value
133 FragmentRef::Null(), // FragRef
134 ResolveInfo::Hidden);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700135
Stephen Hines87f34652014-02-14 18:00:16 -0800136 // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the
137 // same name in input
Stephen Hines37b74a32014-11-26 18:48:20 -0800138 m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
139 "_PROCEDURE_LINKAGE_TABLE_",
140 ResolveInfo::Object,
141 ResolveInfo::Define,
142 ResolveInfo::Local,
143 0x0, // size
144 0x0, // value
145 FragmentRef::Null(), // FragRef
146 ResolveInfo::Hidden);
Stephen Hines87f34652014-02-14 18:00:16 -0800147
Stephen Hines37b74a32014-11-26 18:48:20 -0800148 m_pGpDispSymbol =
149 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
150 "_gp_disp",
151 ResolveInfo::Section,
152 ResolveInfo::Define,
153 ResolveInfo::Absolute,
154 0x0, // size
155 0x0, // value
156 FragmentRef::Null(), // FragRef
157 ResolveInfo::Default);
158
Stephen Hines0dea6bc2014-07-15 18:33:32 -0700159 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
Stephen Hines37b74a32014-11-26 18:48:20 -0800160 "_gp",
161 ResolveInfo::NoType,
162 ResolveInfo::Define,
163 ResolveInfo::Absolute,
164 0x0, // size
165 0x0, // value
166 FragmentRef::Null(), // FragRef
167 ResolveInfo::Default);
Stephen Hines0dea6bc2014-07-15 18:33:32 -0700168}
169
Stephen Hines37b74a32014-11-26 18:48:20 -0800170const Relocator* MipsGNULDBackend::getRelocator() const {
171 assert(m_pRelocator != NULL);
Stephen Hines0dea6bc2014-07-15 18:33:32 -0700172 return m_pRelocator;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700173}
174
Stephen Hines37b74a32014-11-26 18:48:20 -0800175Relocator* MipsGNULDBackend::getRelocator() {
176 assert(m_pRelocator != NULL);
Shih-wei Liaod0fbbb22013-01-03 06:23:31 -0800177 return m_pRelocator;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700178}
179
Stephen Hines37b74a32014-11-26 18:48:20 -0800180void MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder) {
Stephen Hines6f757552013-03-04 19:51:03 -0800181 // initialize .dynamic data
Stephen Hines37b74a32014-11-26 18:48:20 -0800182 if (!config().isCodeStatic() && m_pDynamic == NULL)
Stephen Hines6f757552013-03-04 19:51:03 -0800183 m_pDynamic = new MipsELFDynamic(*this, config());
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700184
Stephen Hinescfcb2242016-03-08 00:18:09 -0800185 if (m_pAbiInfo.hasValue())
186 m_pAbiFlags->setSize(m_pAbiInfo->size());
187
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800188 // set .got size
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700189 // when building shared object, the .got section is must.
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800190 if (LinkerConfig::Object != config().codeGenType()) {
Stephen Hines37b74a32014-11-26 18:48:20 -0800191 if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
192 m_pGOTSymbol != NULL) {
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700193 m_pGOT->finalizeScanning(*m_pRelDyn);
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800194 m_pGOT->finalizeSectionSize();
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700195
Stephen Hines6f757552013-03-04 19:51:03 -0800196 defineGOTSymbol(pBuilder);
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800197 }
198
Stephen Hines87f34652014-02-14 18:00:16 -0800199 if (m_pGOTPLT->hasGOT1()) {
200 m_pGOTPLT->finalizeSectionSize();
201
202 defineGOTPLTSymbol(pBuilder);
203 }
204
205 if (m_pPLT->hasPLT1())
206 m_pPLT->finalizeSectionSize();
207
Shih-wei Liaod0fbbb22013-01-03 06:23:31 -0800208 ELFFileFormat* file_format = getOutputFormat();
Stephen Hines87f34652014-02-14 18:00:16 -0800209
210 // set .rel.plt size
211 if (!m_pRelPlt->empty()) {
Stephen Hines37b74a32014-11-26 18:48:20 -0800212 assert(
213 !config().isCodeStatic() &&
214 "static linkage should not result in a dynamic relocation section");
215 file_format->getRelPlt().setSize(m_pRelPlt->numOfRelocs() *
216 getRelEntrySize());
Stephen Hines87f34652014-02-14 18:00:16 -0800217 }
218
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800219 // set .rel.dyn size
Stephen Hines6f757552013-03-04 19:51:03 -0800220 if (!m_pRelDyn->empty()) {
Stephen Hines37b74a32014-11-26 18:48:20 -0800221 assert(
222 !config().isCodeStatic() &&
223 "static linkage should not result in a dynamic relocation section");
224 file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
225 getRelEntrySize());
Stephen Hines6f757552013-03-04 19:51:03 -0800226 }
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700227 }
228}
Stephen Hines6f757552013-03-04 19:51:03 -0800229
Stephen Hines37b74a32014-11-26 18:48:20 -0800230void MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
231 const ELFFileFormat* format = getOutputFormat();
Stephen Hines87f34652014-02-14 18:00:16 -0800232
233 if (format->hasGOTPLT()) {
Stephen Hines37b74a32014-11-26 18:48:20 -0800234 assert(m_pGOTPLT != NULL && "doPostLayout failed, m_pGOTPLT is NULL!");
Stephen Hines87f34652014-02-14 18:00:16 -0800235 m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr());
236 }
237
238 if (format->hasPLT()) {
Stephen Hines37b74a32014-11-26 18:48:20 -0800239 assert(m_pPLT != NULL && "doPostLayout failed, m_pPLT is NULL!");
Stephen Hines87f34652014-02-14 18:00:16 -0800240 m_pPLT->applyAllPLT(*m_pGOTPLT);
241 }
242
243 m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700244}
245
246/// dynamic - the dynamic section of the target machine.
247/// Use co-variant return type to return its own dynamic section.
Stephen Hines37b74a32014-11-26 18:48:20 -0800248MipsELFDynamic& MipsGNULDBackend::dynamic() {
249 assert(m_pDynamic != NULL);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700250 return *m_pDynamic;
251}
252
253/// dynamic - the dynamic section of the target machine.
254/// Use co-variant return type to return its own dynamic section.
Stephen Hines37b74a32014-11-26 18:48:20 -0800255const MipsELFDynamic& MipsGNULDBackend::dynamic() const {
256 assert(m_pDynamic != NULL);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700257 return *m_pDynamic;
258}
259
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800260uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
Stephen Hines37b74a32014-11-26 18:48:20 -0800261 MemoryRegion& pRegion) const {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700262 assert(pRegion.size() && "Size of MemoryRegion is zero!");
263
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800264 const ELFFileFormat* file_format = getOutputFormat();
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700265
Stephen Hines87f34652014-02-14 18:00:16 -0800266 if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
267 return m_pGOT->emit(pRegion);
268 }
269
270 if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
271 return m_pPLT->emit(pRegion);
272 }
273
274 if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
275 return m_pGOTPLT->emit(pRegion);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700276 }
277
Stephen Hinescfcb2242016-03-08 00:18:09 -0800278 if (&pSection == m_pAbiFlags && m_pAbiInfo.hasValue())
279 return MipsAbiFlags::emit(*m_pAbiInfo, pRegion);
280
281 if (&pSection == m_psdata && m_psdata->hasSectionData()) {
282 const SectionData* sect_data = pSection.getSectionData();
283 SectionData::const_iterator frag_iter, frag_end = sect_data->end();
284 uint8_t* out_offset = pRegion.begin();
285 for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
286 size_t size = frag_iter->size();
287 switch (frag_iter->getKind()) {
288 case Fragment::Fillment: {
289 const FillFragment& fill_frag = llvm::cast<FillFragment>(*frag_iter);
290 if (fill_frag.getValueSize() == 0) {
291 // virtual fillment, ignore it.
292 break;
293 }
294 memset(out_offset, fill_frag.getValue(), fill_frag.size());
295 break;
296 }
297 case Fragment::Region: {
298 const RegionFragment& region_frag =
299 llvm::cast<RegionFragment>(*frag_iter);
300 const char* start = region_frag.getRegion().begin();
301 memcpy(out_offset, start, size);
302 break;
303 }
304 case Fragment::Alignment: {
305 const AlignFragment& align_frag =
306 llvm::cast<AlignFragment>(*frag_iter);
307 uint64_t count = size / align_frag.getValueSize();
308 switch (align_frag.getValueSize()) {
309 case 1u:
310 std::memset(out_offset, align_frag.getValue(), count);
311 break;
312 default:
313 llvm::report_fatal_error(
314 "unsupported value size for align fragment emission yet.\n");
315 break;
316 } // end switch
317 break;
318 }
319 case Fragment::Null: {
320 assert(0x0 == size);
321 break;
322 }
323 default:
324 llvm::report_fatal_error("unsupported fragment type.\n");
325 break;
326 } // end switch
327 out_offset += size;
328 }
329 return pRegion.size();
330 }
331
Stephen Hines37b74a32014-11-26 18:48:20 -0800332 fatal(diag::unrecognized_output_sectoin) << pSection.name()
333 << "mclinker@googlegroups.com";
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700334 return 0;
335}
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700336
Stephen Hines37b74a32014-11-26 18:48:20 -0800337bool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const {
338 return ResolveInfo::Section != pSym.type() || m_pGpDispSymbol == &pSym;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700339}
340
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700341namespace {
Stephen Hines37b74a32014-11-26 18:48:20 -0800342struct DynsymGOTCompare {
343 const MipsGOT& m_pGOT;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700344
Stephen Hines37b74a32014-11-26 18:48:20 -0800345 explicit DynsymGOTCompare(const MipsGOT& pGOT) : m_pGOT(pGOT) {}
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800346
Stephen Hines37b74a32014-11-26 18:48:20 -0800347 bool operator()(const LDSymbol* X, const LDSymbol* Y) const {
348 return m_pGOT.dynSymOrderCompare(X, Y);
349 }
350};
351} // anonymous namespace
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800352
Stephen Hines37b74a32014-11-26 18:48:20 -0800353void MipsGNULDBackend::orderSymbolTable(Module& pModule) {
Pirama Arumuga Nainar2bf3f882015-04-21 10:33:13 -0700354 if (config().options().hasGNUHash()) {
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700355 // The MIPS ABI and .gnu.hash require .dynsym to be sorted
356 // in different ways. The MIPS ABI requires a mapping between
357 // the GOT and the symbol table. At the same time .gnu.hash
358 // needs symbols to be grouped by hash code.
359 llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n";
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700360 }
361
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700362 Module::SymbolTable& symbols = pModule.getSymbolTable();
Zonr Changaffc1502012-07-16 14:28:23 +0800363
Stephen Hines37b74a32014-11-26 18:48:20 -0800364 std::stable_sort(
365 symbols.dynamicBegin(), symbols.dynamicEnd(), DynsymGOTCompare(*m_pGOT));
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700366}
367
Stephen Hines37b74a32014-11-26 18:48:20 -0800368} // namespace mcld
369
Stephen Hines87f34652014-02-14 18:00:16 -0800370namespace llvm {
371namespace ELF {
372// SHT_MIPS_OPTIONS section's block descriptor.
373struct Elf_Options {
Stephen Hines37b74a32014-11-26 18:48:20 -0800374 unsigned char kind; // Determines interpretation of variable
375 // part of descriptor. See ODK_xxx enumeration.
376 unsigned char size; // Byte size of descriptor, including this header.
377 Elf64_Half section; // Section header index of section affected,
378 // or 0 for global options.
379 Elf64_Word info; // Kind-specific information.
Stephen Hines87f34652014-02-14 18:00:16 -0800380};
381
Stephen Hines87f34652014-02-14 18:00:16 -0800382// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
383struct Elf32_RegInfo {
Stephen Hines37b74a32014-11-26 18:48:20 -0800384 Elf32_Word ri_gprmask; // Mask of general purpose registers used.
385 Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
386 Elf32_Addr ri_gp_value; // GP register value for this object file.
Stephen Hines87f34652014-02-14 18:00:16 -0800387};
388
389// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
390struct Elf64_RegInfo {
Stephen Hines37b74a32014-11-26 18:48:20 -0800391 Elf32_Word ri_gprmask; // Mask of general purpose registers used.
392 Elf32_Word ri_pad; // Padding.
393 Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
394 Elf64_Addr ri_gp_value; // GP register value for this object file.
Stephen Hines87f34652014-02-14 18:00:16 -0800395};
396
Stephen Hines37b74a32014-11-26 18:48:20 -0800397} // namespace ELF
398} // namespace llvm
Stephen Hines87f34652014-02-14 18:00:16 -0800399
Stephen Hines37b74a32014-11-26 18:48:20 -0800400namespace mcld {
401
Stephen Hinescfcb2242016-03-08 00:18:09 -0800402static const char* ArchName(uint64_t flagBits) {
403 switch (flagBits) {
404 case llvm::ELF::EF_MIPS_ARCH_1:
405 return "mips1";
406 case llvm::ELF::EF_MIPS_ARCH_2:
407 return "mips2";
408 case llvm::ELF::EF_MIPS_ARCH_3:
409 return "mips3";
410 case llvm::ELF::EF_MIPS_ARCH_4:
411 return "mips4";
412 case llvm::ELF::EF_MIPS_ARCH_5:
413 return "mips5";
414 case llvm::ELF::EF_MIPS_ARCH_32:
415 return "mips32";
416 case llvm::ELF::EF_MIPS_ARCH_64:
417 return "mips64";
418 case llvm::ELF::EF_MIPS_ARCH_32R2:
419 return "mips32r2";
420 case llvm::ELF::EF_MIPS_ARCH_64R2:
421 return "mips64r2";
422 case llvm::ELF::EF_MIPS_ARCH_32R6:
423 return "mips32r6";
424 case llvm::ELF::EF_MIPS_ARCH_64R6:
425 return "mips64r6";
426 default:
427 return "Unknown Arch";
428 }
429}
Stephen Hines87f34652014-02-14 18:00:16 -0800430
Stephen Hinescfcb2242016-03-08 00:18:09 -0800431void MipsGNULDBackend::mergeFlags(Input& pInput, const char* ELF_hdr) {
432 bool isTarget64Bit = config().targets().triple().isArch64Bit();
433 bool isInput64Bit = ELF_hdr[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64;
434
435 if (isTarget64Bit != isInput64Bit) {
436 fatal(diag::error_Mips_incompatible_class)
437 << (isTarget64Bit ? "ELFCLASS64" : "ELFCLASS32")
438 << (isInput64Bit ? "ELFCLASS64" : "ELFCLASS32") << pInput.name();
439 return;
440 }
441
442 m_ElfFlagsMap[&pInput] =
443 isInput64Bit ?
444 reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(ELF_hdr)->e_flags :
445 reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(ELF_hdr)->e_flags;
446}
447
448bool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
449 if ((pSD.getSection().flag() & llvm::ELF::SHF_MIPS_GPREL) ||
450 (pSD.getSection().type() == llvm::ELF::SHT_MIPS_ABIFLAGS)) {
Stephen Hines87f34652014-02-14 18:00:16 -0800451 uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
452 uint64_t size = pSD.getSection().size();
453
454 Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
455 ObjectBuilder::AppendFragment(*frag, pSD);
456 return true;
457 }
458
459 if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
460 uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
461 uint32_t size = pSD.getSection().size();
462
463 llvm::StringRef region = pInput.memArea()->request(offset, size);
464 if (region.size() > 0) {
465 const llvm::ELF::Elf_Options* optb =
Stephen Hines37b74a32014-11-26 18:48:20 -0800466 reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
Stephen Hines87f34652014-02-14 18:00:16 -0800467 const llvm::ELF::Elf_Options* opte =
Stephen Hines37b74a32014-11-26 18:48:20 -0800468 reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() +
469 size);
Stephen Hines87f34652014-02-14 18:00:16 -0800470
Stephen Hines37b74a32014-11-26 18:48:20 -0800471 for (const llvm::ELF::Elf_Options* opt = optb; opt < opte;
472 opt += opt->size) {
Stephen Hines87f34652014-02-14 18:00:16 -0800473 switch (opt->kind) {
474 default:
475 // Nothing to do.
476 break;
477 case llvm::ELF::ODK_REGINFO:
478 if (config().targets().triple().isArch32Bit()) {
479 const llvm::ELF::Elf32_RegInfo* reg =
Stephen Hines37b74a32014-11-26 18:48:20 -0800480 reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
Stephen Hines87f34652014-02-14 18:00:16 -0800481 m_GP0Map[&pInput] = reg->ri_gp_value;
Stephen Hines37b74a32014-11-26 18:48:20 -0800482 } else {
Stephen Hines87f34652014-02-14 18:00:16 -0800483 const llvm::ELF::Elf64_RegInfo* reg =
Stephen Hines37b74a32014-11-26 18:48:20 -0800484 reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
Stephen Hines87f34652014-02-14 18:00:16 -0800485 m_GP0Map[&pInput] = reg->ri_gp_value;
486 }
487 break;
488 }
489 }
490 }
491
492 return true;
493 }
494
495 return GNULDBackend::readSection(pInput, pSD);
496}
497
Stephen Hines37b74a32014-11-26 18:48:20 -0800498MipsGOT& MipsGNULDBackend::getGOT() {
499 assert(m_pGOT != NULL);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700500 return *m_pGOT;
501}
502
Stephen Hines37b74a32014-11-26 18:48:20 -0800503const MipsGOT& MipsGNULDBackend::getGOT() const {
504 assert(m_pGOT != NULL);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700505 return *m_pGOT;
506}
507
Stephen Hines37b74a32014-11-26 18:48:20 -0800508MipsPLT& MipsGNULDBackend::getPLT() {
509 assert(m_pPLT != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800510 return *m_pPLT;
511}
512
Stephen Hines37b74a32014-11-26 18:48:20 -0800513const MipsPLT& MipsGNULDBackend::getPLT() const {
514 assert(m_pPLT != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800515 return *m_pPLT;
516}
517
Stephen Hines37b74a32014-11-26 18:48:20 -0800518MipsGOTPLT& MipsGNULDBackend::getGOTPLT() {
519 assert(m_pGOTPLT != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800520 return *m_pGOTPLT;
521}
522
Stephen Hines37b74a32014-11-26 18:48:20 -0800523const MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const {
524 assert(m_pGOTPLT != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800525 return *m_pGOTPLT;
526}
527
Stephen Hines37b74a32014-11-26 18:48:20 -0800528OutputRelocSection& MipsGNULDBackend::getRelPLT() {
529 assert(m_pRelPlt != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800530 return *m_pRelPlt;
531}
532
Stephen Hines37b74a32014-11-26 18:48:20 -0800533const OutputRelocSection& MipsGNULDBackend::getRelPLT() const {
534 assert(m_pRelPlt != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800535 return *m_pRelPlt;
536}
537
Stephen Hines37b74a32014-11-26 18:48:20 -0800538OutputRelocSection& MipsGNULDBackend::getRelDyn() {
539 assert(m_pRelDyn != NULL);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700540 return *m_pRelDyn;
541}
542
Stephen Hines37b74a32014-11-26 18:48:20 -0800543const OutputRelocSection& MipsGNULDBackend::getRelDyn() const {
544 assert(m_pRelDyn != NULL);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700545 return *m_pRelDyn;
546}
547
Stephen Hines37b74a32014-11-26 18:48:20 -0800548unsigned int MipsGNULDBackend::getTargetSectionOrder(
549 const LDSection& pSectHdr) const {
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800550 const ELFFileFormat* file_format = getOutputFormat();
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700551
Stephen Hines87f34652014-02-14 18:00:16 -0800552 if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700553 return SHO_DATA;
554
Stephen Hines87f34652014-02-14 18:00:16 -0800555 if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
556 return SHO_DATA;
557
558 if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
559 return SHO_PLT;
560
Stephen Hinescfcb2242016-03-08 00:18:09 -0800561 if (&pSectHdr == m_psdata)
562 return SHO_SMALL_DATA;
563
564 if (&pSectHdr == m_pAbiFlags)
565 return SHO_RO_NOTE;
566
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700567 return SHO_UNDEFINED;
568}
569
570/// finalizeSymbol - finalize the symbol value
Stephen Hines37b74a32014-11-26 18:48:20 -0800571bool MipsGNULDBackend::finalizeTargetSymbols() {
572 if (m_pGpDispSymbol != NULL)
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700573 m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress());
574
Zonr Changaffc1502012-07-16 14:28:23 +0800575 return true;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700576}
577
578/// allocateCommonSymbols - allocate common symbols in the corresponding
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800579/// sections. This is called at pre-layout stage.
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700580/// FIXME: Mips needs to allocate small common symbol
Stephen Hines37b74a32014-11-26 18:48:20 -0800581bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule) {
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800582 SymbolCategory& symbol_list = pModule.getSymbolTable();
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700583
Stephen Hines6f757552013-03-04 19:51:03 -0800584 if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
585 symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700586 return true;
587
Zonr Changaffc1502012-07-16 14:28:23 +0800588 SymbolCategory::iterator com_sym, com_end;
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700589
590 // FIXME: If the order of common symbols is defined, then sort common symbols
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700591 // std::sort(com_sym, com_end, some kind of order);
592
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800593 // get corresponding BSS LDSection
594 ELFFileFormat* file_format = getOutputFormat();
595 LDSection& bss_sect = file_format->getBSS();
596 LDSection& tbss_sect = file_format->getTBSS();
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700597
Shih-wei Liaocedee4b2012-08-02 23:13:03 -0700598 // get or create corresponding BSS SectionData
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800599 SectionData* bss_sect_data = NULL;
600 if (bss_sect.hasSectionData())
601 bss_sect_data = bss_sect.getSectionData();
602 else
603 bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
604
605 SectionData* tbss_sect_data = NULL;
606 if (tbss_sect.hasSectionData())
607 tbss_sect_data = tbss_sect.getSectionData();
608 else
609 tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700610
Zonr Changaffc1502012-07-16 14:28:23 +0800611 // remember original BSS size
Stephen Hines37b74a32014-11-26 18:48:20 -0800612 uint64_t bss_offset = bss_sect.size();
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800613 uint64_t tbss_offset = tbss_sect.size();
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700614
615 // allocate all local common symbols
616 com_end = symbol_list.localEnd();
Zonr Changaffc1502012-07-16 14:28:23 +0800617
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700618 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
619 if (ResolveInfo::Common == (*com_sym)->desc()) {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700620 // We have to reset the description of the symbol here. When doing
621 // incremental linking, the output relocatable object may have common
622 // symbols. Therefore, we can not treat common symbols as normal symbols
623 // when emitting the regular name pools. We must change the symbols'
624 // description here.
625 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
Shih-wei Liaocedee4b2012-08-02 23:13:03 -0700626 Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
Zonr Changaffc1502012-07-16 14:28:23 +0800627
628 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
629 // allocate TLS common symbol in tbss section
Stephen Hines37b74a32014-11-26 18:48:20 -0800630 tbss_offset += ObjectBuilder::AppendFragment(
631 *frag, *tbss_sect_data, (*com_sym)->value());
Stephen Hines551ae4e2014-04-24 14:41:24 -0700632 ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
Stephen Hines87f34652014-02-14 18:00:16 -0800633 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
Stephen Hines37b74a32014-11-26 18:48:20 -0800634 } else {
635 // FIXME: how to identify small and large common symbols?
636 bss_offset += ObjectBuilder::AppendFragment(
637 *frag, *bss_sect_data, (*com_sym)->value());
Stephen Hines551ae4e2014-04-24 14:41:24 -0700638 ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
Stephen Hines87f34652014-02-14 18:00:16 -0800639 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
Zonr Changaffc1502012-07-16 14:28:23 +0800640 }
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700641 }
642 }
643
644 // allocate all global common symbols
645 com_end = symbol_list.commonEnd();
646 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700647 // We have to reset the description of the symbol here. When doing
648 // incremental linking, the output relocatable object may have common
649 // symbols. Therefore, we can not treat common symbols as normal symbols
650 // when emitting the regular name pools. We must change the symbols'
651 // description here.
652 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
Shih-wei Liaocedee4b2012-08-02 23:13:03 -0700653 Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
Zonr Changaffc1502012-07-16 14:28:23 +0800654
655 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
656 // allocate TLS common symbol in tbss section
Stephen Hines37b74a32014-11-26 18:48:20 -0800657 tbss_offset += ObjectBuilder::AppendFragment(
658 *frag, *tbss_sect_data, (*com_sym)->value());
Stephen Hines551ae4e2014-04-24 14:41:24 -0700659 ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
Stephen Hines87f34652014-02-14 18:00:16 -0800660 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
Stephen Hines37b74a32014-11-26 18:48:20 -0800661 } else {
662 // FIXME: how to identify small and large common symbols?
663 bss_offset += ObjectBuilder::AppendFragment(
664 *frag, *bss_sect_data, (*com_sym)->value());
Stephen Hines551ae4e2014-04-24 14:41:24 -0700665 ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
Stephen Hines87f34652014-02-14 18:00:16 -0800666 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
Zonr Changaffc1502012-07-16 14:28:23 +0800667 }
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700668 }
669
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800670 bss_sect.setSize(bss_offset);
671 tbss_sect.setSize(tbss_offset);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700672 symbol_list.changeCommonsToGlobal();
673 return true;
674}
675
Stephen Hinescfcb2242016-03-08 00:18:09 -0800676uint64_t MipsGNULDBackend::getTPOffset(const Input& pInput) const {
677 return m_TpOffsetMap.lookup(&pInput);
678}
679
680uint64_t MipsGNULDBackend::getDTPOffset(const Input& pInput) const {
681 return m_DtpOffsetMap.lookup(&pInput);
682}
683
Stephen Hines37b74a32014-11-26 18:48:20 -0800684uint64_t MipsGNULDBackend::getGP0(const Input& pInput) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800685 return m_GP0Map.lookup(&pInput);
686}
687
Stephen Hines37b74a32014-11-26 18:48:20 -0800688void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
Stephen Hinesf7ac0f12013-05-03 19:09:24 -0700689 // If we do not reserve any GOT entries, we do not need to re-define GOT
690 // symbol.
691 if (!m_pGOT->hasGOT1())
692 return;
693
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800694 // define symbol _GLOBAL_OFFSET_TABLE_
Stephen Hines37b74a32014-11-26 18:48:20 -0800695 if (m_pGOTSymbol != NULL) {
Stephen Hines6f757552013-03-04 19:51:03 -0800696 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
Stephen Hines37b74a32014-11-26 18:48:20 -0800697 "_GLOBAL_OFFSET_TABLE_",
698 ResolveInfo::Object,
699 ResolveInfo::Define,
700 ResolveInfo::Local,
701 0x0, // size
702 0x0, // value
703 FragmentRef::Create(*(m_pGOT->begin()), 0x0),
704 ResolveInfo::Hidden);
705 } else {
Stephen Hines6f757552013-03-04 19:51:03 -0800706 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
Stephen Hines37b74a32014-11-26 18:48:20 -0800707 "_GLOBAL_OFFSET_TABLE_",
708 ResolveInfo::Object,
709 ResolveInfo::Define,
710 ResolveInfo::Local,
711 0x0, // size
712 0x0, // value
713 FragmentRef::Create(*(m_pGOT->begin()), 0x0),
714 ResolveInfo::Hidden);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700715 }
716}
717
Stephen Hines37b74a32014-11-26 18:48:20 -0800718void MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder) {
Stephen Hines87f34652014-02-14 18:00:16 -0800719 // define symbol _PROCEDURE_LINKAGE_TABLE_
Stephen Hines37b74a32014-11-26 18:48:20 -0800720 if (m_pPLTSymbol != NULL) {
Stephen Hines87f34652014-02-14 18:00:16 -0800721 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
Stephen Hines37b74a32014-11-26 18:48:20 -0800722 "_PROCEDURE_LINKAGE_TABLE_",
723 ResolveInfo::Object,
724 ResolveInfo::Define,
725 ResolveInfo::Local,
726 0x0, // size
727 0x0, // value
728 FragmentRef::Create(*(m_pPLT->begin()), 0x0),
729 ResolveInfo::Hidden);
730 } else {
Stephen Hines87f34652014-02-14 18:00:16 -0800731 m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
Stephen Hines37b74a32014-11-26 18:48:20 -0800732 "_PROCEDURE_LINKAGE_TABLE_",
733 ResolveInfo::Object,
734 ResolveInfo::Define,
735 ResolveInfo::Local,
736 0x0, // size
737 0x0, // value
738 FragmentRef::Create(*(m_pPLT->begin()), 0x0),
739 ResolveInfo::Hidden);
Stephen Hines87f34652014-02-14 18:00:16 -0800740 }
741}
742
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800743/// doCreateProgramHdrs - backend can implement this function to create the
744/// target-dependent segments
Stephen Hines37b74a32014-11-26 18:48:20 -0800745void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule) {
Stephen Hinescfcb2242016-03-08 00:18:09 -0800746 if (!m_pAbiFlags || m_pAbiFlags->size() == 0)
747 return;
748
749 // create PT_MIPS_ABIFLAGS segment
750 ELFSegmentFactory::iterator sit =
751 elfSegmentTable().find(llvm::ELF::PT_INTERP, 0x0, 0x0);
752 if (sit == elfSegmentTable().end())
753 sit = elfSegmentTable().find(llvm::ELF::PT_PHDR, 0x0, 0x0);
754 if (sit == elfSegmentTable().end())
755 sit = elfSegmentTable().begin();
756 else
757 ++sit;
758
759 ELFSegment* abiSeg = elfSegmentTable().insert(sit,
760 llvm::ELF::PT_MIPS_ABIFLAGS,
761 llvm::ELF::PF_R);
762 abiSeg->setAlign(8);
763 abiSeg->append(m_pAbiFlags);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -0700764}
765
Stephen Hines37b74a32014-11-26 18:48:20 -0800766bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) {
Stephen Hines87f34652014-02-14 18:00:16 -0800767 uint64_t sym_value = 0x0;
768
769 LDSymbol* symbol = pRel.symInfo()->outSymbol();
770 if (symbol->hasFragRef()) {
771 uint64_t value = symbol->fragRef()->getOutputOffset();
772 uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
773 sym_value = addr + value;
774 }
775
Stephen Hines37b74a32014-11-26 18:48:20 -0800776 Stub* stub = getStubFactory()->create(
777 pRel, sym_value, pBuilder, *getBRIslandFactory());
Stephen Hines87f34652014-02-14 18:00:16 -0800778
Stephen Hines37b74a32014-11-26 18:48:20 -0800779 if (stub == NULL)
Stephen Hines87f34652014-02-14 18:00:16 -0800780 return false;
781
Stephen Hines37b74a32014-11-26 18:48:20 -0800782 assert(stub->symInfo() != NULL);
Stephen Hinescfcb2242016-03-08 00:18:09 -0800783 // reset the branch target of the reloc to this stub instead
784 pRel.setSymInfo(stub->symInfo());
785
Stephen Hines87f34652014-02-14 18:00:16 -0800786 // increase the size of .symtab and .strtab
787 LDSection& symtab = getOutputFormat()->getSymTab();
788 LDSection& strtab = getOutputFormat()->getStrTab();
789 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
790 strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
791
792 return true;
793}
794
Stephen Hines37b74a32014-11-26 18:48:20 -0800795bool MipsGNULDBackend::doRelax(Module& pModule,
796 IRBuilder& pBuilder,
797 bool& pFinished) {
798 assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
Stephen Hines87f34652014-02-14 18:00:16 -0800799
800 bool isRelaxed = false;
801
802 for (Module::obj_iterator input = pModule.obj_begin();
Stephen Hines37b74a32014-11-26 18:48:20 -0800803 input != pModule.obj_end();
804 ++input) {
Stephen Hines87f34652014-02-14 18:00:16 -0800805 LDContext* context = (*input)->context();
806
807 for (LDContext::sect_iterator rs = context->relocSectBegin();
Stephen Hines37b74a32014-11-26 18:48:20 -0800808 rs != context->relocSectEnd();
809 ++rs) {
Stephen Hines87f34652014-02-14 18:00:16 -0800810 LDSection* sec = *rs;
811
812 if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
813 continue;
814
815 for (RelocData::iterator reloc = sec->getRelocData()->begin();
Stephen Hines37b74a32014-11-26 18:48:20 -0800816 reloc != sec->getRelocData()->end();
817 ++reloc) {
Stephen Hines87f34652014-02-14 18:00:16 -0800818 if (llvm::ELF::R_MIPS_26 != reloc->type())
819 continue;
820
821 if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
822 isRelaxed = true;
823 }
824 }
825 }
826
Stephen Hines87f34652014-02-14 18:00:16 -0800827 // find the first fragment w/ invalid offset due to stub insertion
Stephen Hinescfcb2242016-03-08 00:18:09 -0800828 std::vector<Fragment*> invalid_frags;
Stephen Hines87f34652014-02-14 18:00:16 -0800829 pFinished = true;
830 for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
831 ie = getBRIslandFactory()->end();
Stephen Hines37b74a32014-11-26 18:48:20 -0800832 ii != ie;
833 ++ii) {
Stephen Hines87f34652014-02-14 18:00:16 -0800834 BranchIsland& island = *ii;
Stephen Hinescfcb2242016-03-08 00:18:09 -0800835 if (island.size() > stubGroupSize()) {
836 error(diag::err_no_space_to_place_stubs) << stubGroupSize();
837 return false;
838 }
Stephen Hines87f34652014-02-14 18:00:16 -0800839
Stephen Hinescfcb2242016-03-08 00:18:09 -0800840 if (island.numOfStubs() == 0) {
841 continue;
842 }
843
844 Fragment* exit = &*island.end();
845 if (exit == island.begin()->getParent()->end()) {
846 continue;
847 }
848
Stephen Hines87f34652014-02-14 18:00:16 -0800849 if ((island.offset() + island.size()) > exit->getOffset()) {
Stephen Hinescfcb2242016-03-08 00:18:09 -0800850 if (invalid_frags.empty() ||
851 (invalid_frags.back()->getParent() != island.getParent())) {
852 invalid_frags.push_back(exit);
853 pFinished = false;
854 }
855 continue;
Stephen Hines87f34652014-02-14 18:00:16 -0800856 }
857 }
858
859 // reset the offset of invalid fragments
Stephen Hinescfcb2242016-03-08 00:18:09 -0800860 for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie;
861 ++it) {
862 Fragment* invalid = *it;
863 while (invalid != NULL) {
864 invalid->setOffset(invalid->getPrevNode()->getOffset() +
865 invalid->getPrevNode()->size());
866 invalid = invalid->getNextNode();
867 }
Stephen Hines87f34652014-02-14 18:00:16 -0800868 }
869
Stephen Hinescfcb2242016-03-08 00:18:09 -0800870 // reset the size of section that has stubs inserted.
871 if (isRelaxed) {
872 SectionData* prev = NULL;
873 for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
874 island_end = getBRIslandFactory()->end();
875 island != island_end;
876 ++island) {
877 SectionData* sd = (*island).begin()->getParent();
878 if ((*island).numOfStubs() != 0) {
879 if (sd != prev) {
880 sd->getSection().setSize(sd->back().getOffset() + sd->back().size());
881 }
882 }
883 prev = sd;
884 }
885 }
Stephen Hines87f34652014-02-14 18:00:16 -0800886
887 return isRelaxed;
888}
889
Stephen Hines37b74a32014-11-26 18:48:20 -0800890bool MipsGNULDBackend::initTargetStubs() {
891 if (getStubFactory() == NULL)
Stephen Hines87f34652014-02-14 18:00:16 -0800892 return false;
893
894 getStubFactory()->addPrototype(new MipsLA25Stub(*this));
895 return true;
896}
897
898bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
899 Relocation::Type& pType,
900 uint32_t& pSymIdx,
Stephen Hines37b74a32014-11-26 18:48:20 -0800901 uint32_t& pOffset) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800902 return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
903}
904
905bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
906 Relocation::Type& pType,
907 uint32_t& pSymIdx,
908 uint32_t& pOffset,
Stephen Hines37b74a32014-11-26 18:48:20 -0800909 int32_t& pAddend) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800910 return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
911}
912
913bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
914 Relocation::Type& pType,
915 uint32_t& pSymIdx,
Stephen Hines37b74a32014-11-26 18:48:20 -0800916 uint64_t& pOffset) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800917 uint64_t r_info = 0x0;
918 if (llvm::sys::IsLittleEndianHost) {
919 pOffset = pRel.r_offset;
Stephen Hines37b74a32014-11-26 18:48:20 -0800920 r_info = pRel.r_info;
921 } else {
Stephen Hines87f34652014-02-14 18:00:16 -0800922 pOffset = mcld::bswap64(pRel.r_offset);
Stephen Hines37b74a32014-11-26 18:48:20 -0800923 r_info = mcld::bswap64(pRel.r_info);
Stephen Hines87f34652014-02-14 18:00:16 -0800924 }
925
926 // MIPS 64 little endian (we do not support big endian now)
927 // has a "special" encoding of r_info relocation
928 // field. Instead of one 64 bit little endian number, it is a little
929 // endian 32 bit number followed by a 32 bit big endian number.
930 pType = mcld::bswap32(r_info >> 32);
931 pSymIdx = r_info & 0xffffffff;
932 return true;
933}
934
935bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
936 Relocation::Type& pType,
937 uint32_t& pSymIdx,
938 uint64_t& pOffset,
Stephen Hines37b74a32014-11-26 18:48:20 -0800939 int64_t& pAddend) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800940 uint64_t r_info = 0x0;
941 if (llvm::sys::IsLittleEndianHost) {
942 pOffset = pRel.r_offset;
Stephen Hines37b74a32014-11-26 18:48:20 -0800943 r_info = pRel.r_info;
Stephen Hines87f34652014-02-14 18:00:16 -0800944 pAddend = pRel.r_addend;
Stephen Hines37b74a32014-11-26 18:48:20 -0800945 } else {
Stephen Hines87f34652014-02-14 18:00:16 -0800946 pOffset = mcld::bswap64(pRel.r_offset);
Stephen Hines37b74a32014-11-26 18:48:20 -0800947 r_info = mcld::bswap64(pRel.r_info);
Stephen Hines87f34652014-02-14 18:00:16 -0800948 pAddend = mcld::bswap64(pRel.r_addend);
949 }
950
951 pType = mcld::bswap32(r_info >> 32);
952 pSymIdx = r_info & 0xffffffff;
953 return true;
954}
955
956void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
957 Relocation::Type pType,
958 uint32_t pSymIdx,
Stephen Hines37b74a32014-11-26 18:48:20 -0800959 uint32_t pOffset) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800960 GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
961}
962
963void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
964 Relocation::Type pType,
965 uint32_t pSymIdx,
966 uint32_t pOffset,
Stephen Hines37b74a32014-11-26 18:48:20 -0800967 int32_t pAddend) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800968 GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
969}
970
971void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
972 Relocation::Type pType,
973 uint32_t pSymIdx,
Stephen Hines37b74a32014-11-26 18:48:20 -0800974 uint64_t pOffset) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800975 uint64_t r_info = mcld::bswap32(pType);
976 r_info <<= 32;
977 r_info |= pSymIdx;
978
979 pRel.r_info = r_info;
980 pRel.r_offset = pOffset;
981}
982
983void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
984 Relocation::Type pType,
985 uint32_t pSymIdx,
986 uint64_t pOffset,
Stephen Hines37b74a32014-11-26 18:48:20 -0800987 int64_t pAddend) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800988 uint64_t r_info = mcld::bswap32(pType);
989 r_info <<= 32;
990 r_info |= pSymIdx;
991
992 pRel.r_info = r_info;
993 pRel.r_offset = pOffset;
994 pRel.r_addend = pAddend;
995}
996
Stephen Hinescfcb2242016-03-08 00:18:09 -0800997namespace {
998struct ISATreeEdge {
999 unsigned child;
1000 unsigned parent;
1001};
1002}
1003
1004static ISATreeEdge isaTree[] = {
1005 // MIPS32R6 and MIPS64R6 are not compatible with other extensions
1006
1007 // MIPS64 extensions.
1008 {llvm::ELF::EF_MIPS_ARCH_64R2, llvm::ELF::EF_MIPS_ARCH_64},
1009 // MIPS V extensions.
1010 {llvm::ELF::EF_MIPS_ARCH_64, llvm::ELF::EF_MIPS_ARCH_5},
1011 // MIPS IV extensions.
1012 {llvm::ELF::EF_MIPS_ARCH_5, llvm::ELF::EF_MIPS_ARCH_4},
1013 // MIPS III extensions.
1014 {llvm::ELF::EF_MIPS_ARCH_4, llvm::ELF::EF_MIPS_ARCH_3},
1015 // MIPS32 extensions.
1016 {llvm::ELF::EF_MIPS_ARCH_32R2, llvm::ELF::EF_MIPS_ARCH_32},
1017 // MIPS II extensions.
1018 {llvm::ELF::EF_MIPS_ARCH_3, llvm::ELF::EF_MIPS_ARCH_2},
1019 {llvm::ELF::EF_MIPS_ARCH_32, llvm::ELF::EF_MIPS_ARCH_2},
1020 // MIPS I extensions.
1021 {llvm::ELF::EF_MIPS_ARCH_2, llvm::ELF::EF_MIPS_ARCH_1},
1022};
1023
1024static bool isIsaMatched(uint32_t base, uint32_t ext) {
1025 if (base == ext)
1026 return true;
1027 if (base == llvm::ELF::EF_MIPS_ARCH_32 &&
1028 isIsaMatched(llvm::ELF::EF_MIPS_ARCH_64, ext))
1029 return true;
1030 if (base == llvm::ELF::EF_MIPS_ARCH_32R2 &&
1031 isIsaMatched(llvm::ELF::EF_MIPS_ARCH_64R2, ext))
1032 return true;
1033 for (const auto &edge : isaTree) {
1034 if (ext == edge.child) {
1035 ext = edge.parent;
1036 if (ext == base)
1037 return true;
1038 }
1039 }
1040 return false;
1041}
1042
1043static bool getAbiFlags(const Input& pInput, uint64_t elfFlags, bool& hasFlags,
1044 MipsAbiFlags& pFlags) {
1045 MipsAbiFlags pElfFlags = {};
1046 if (!MipsAbiFlags::fillByElfFlags(pInput, elfFlags, pElfFlags))
1047 return false;
1048
1049 const LDContext* ctx = pInput.context();
1050 for (auto it = ctx->sectBegin(), ie = ctx->sectEnd(); it != ie; ++it)
1051 if ((*it)->type() == llvm::ELF::SHT_MIPS_ABIFLAGS) {
1052 if (!MipsAbiFlags::fillBySection(pInput, **it, pFlags))
1053 return false;
1054 if (!MipsAbiFlags::isCompatible(pInput, pElfFlags, pFlags))
1055 return false;
1056 hasFlags = true;
1057 return true;
1058 }
1059
1060 pFlags = pElfFlags;
1061 return true;
1062}
1063
1064static const char* getNanName(uint64_t flags) {
1065 return flags & llvm::ELF::EF_MIPS_NAN2008 ? "2008" : "legacy";
1066}
1067
1068static bool mergeElfFlags(const Input& pInput, uint64_t& oldElfFlags,
1069 uint64_t newElfFlags) {
1070 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
1071 // Ensure that this flag will exist in the linked file.
1072 if (newElfFlags & llvm::ELF::EF_MIPS_PIC)
1073 newElfFlags |= llvm::ELF::EF_MIPS_CPIC;
1074
1075 if (newElfFlags & llvm::ELF::EF_MIPS_ARCH_ASE_M16) {
1076 error(diag::error_Mips_m16_unsupported) << pInput.name();
1077 return false;
1078 }
1079
1080 if (!oldElfFlags) {
1081 oldElfFlags = newElfFlags;
1082 return true;
1083 }
1084
1085 uint64_t newPic =
1086 newElfFlags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
1087 uint64_t oldPic =
1088 oldElfFlags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
1089
1090 // Check PIC / CPIC flags compatibility.
1091 if ((newPic != 0) != (oldPic != 0))
1092 warning(diag::warn_Mips_abicalls_linking) << pInput.name();
1093
1094 if (!(newPic & llvm::ELF::EF_MIPS_PIC))
1095 oldElfFlags &= ~llvm::ELF::EF_MIPS_PIC;
1096 if (newPic)
1097 oldElfFlags |= llvm::ELF::EF_MIPS_CPIC;
1098
1099 // Check ISA compatibility.
1100 uint64_t newArch = newElfFlags & llvm::ELF::EF_MIPS_ARCH;
1101 uint64_t oldArch = oldElfFlags & llvm::ELF::EF_MIPS_ARCH;
1102 if (!isIsaMatched(newArch, oldArch)) {
1103 if (!isIsaMatched(oldArch, newArch)) {
1104 error(diag::error_Mips_inconsistent_arch)
1105 << ArchName(oldArch) << ArchName(newArch) << pInput.name();
1106 return false;
1107 }
1108 oldElfFlags &= ~llvm::ELF::EF_MIPS_ARCH;
1109 oldElfFlags |= newArch;
1110 }
1111
1112 // Check ABI compatibility.
1113 uint32_t newAbi = newElfFlags & llvm::ELF::EF_MIPS_ABI;
1114 uint32_t oldAbi = oldElfFlags & llvm::ELF::EF_MIPS_ABI;
1115 if (newAbi != oldAbi && newAbi && oldAbi) {
1116 error(diag::error_Mips_inconsistent_abi) << pInput.name();
1117 return false;
1118 }
1119
1120 // Check -mnan flags compatibility.
1121 if ((newElfFlags & llvm::ELF::EF_MIPS_NAN2008) !=
1122 (oldElfFlags & llvm::ELF::EF_MIPS_NAN2008)) {
1123 // Linking -mnan=2008 and -mnan=legacy modules
1124 error(diag::error_Mips_inconsistent_mnan)
1125 << getNanName(oldElfFlags) << getNanName(newElfFlags) << pInput.name();
1126 return false;
1127 }
1128
1129 // Check ASE compatibility.
1130 uint64_t newAse = newElfFlags & llvm::ELF::EF_MIPS_ARCH_ASE;
1131 uint64_t oldAse = oldElfFlags & llvm::ELF::EF_MIPS_ARCH_ASE;
1132 if (newAse != oldAse)
1133 oldElfFlags |= newAse;
1134
1135 // Check FP64 compatibility.
1136 if ((newElfFlags & llvm::ELF::EF_MIPS_FP64) !=
1137 (oldElfFlags & llvm::ELF::EF_MIPS_FP64)) {
1138 // Linking -mnan=2008 and -mnan=legacy modules
1139 error(diag::error_Mips_inconsistent_fp64) << pInput.name();
1140 return false;
1141 }
1142
1143 oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_NOREORDER;
1144 oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_MICROMIPS;
1145 oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_NAN2008;
1146 oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_32BITMODE;
1147
1148 return true;
1149}
1150
1151void MipsGNULDBackend::saveTPOffset(const Input& pInput) {
1152 const LDContext* ctx = pInput.context();
1153 for (auto it = ctx->sectBegin(), ie = ctx->sectEnd(); it != ie; ++it) {
1154 LDSection* sect = *it;
1155 if (sect->flag() & llvm::ELF::SHF_TLS) {
1156 m_TpOffsetMap[&pInput] = sect->addr() + 0x7000;
1157 m_DtpOffsetMap[&pInput] = sect->addr() + 0x8000;
1158 break;
1159 }
1160 }
1161}
1162
1163void MipsGNULDBackend::preMergeSections(Module& pModule) {
1164 uint64_t elfFlags = 0;
1165 bool hasAbiFlags = false;
1166 MipsAbiFlags abiFlags = {};
1167 for (const Input *input : pModule.getObjectList()) {
1168 if (input->type() != Input::Object)
1169 continue;
1170
1171 uint64_t newElfFlags = m_ElfFlagsMap[input];
1172
1173 MipsAbiFlags newAbiFlags = {};
1174 if (!getAbiFlags(*input, newElfFlags, hasAbiFlags, newAbiFlags))
1175 continue;
1176
1177 if (!mergeElfFlags(*input, elfFlags, newElfFlags))
1178 continue;
1179
1180 if (!MipsAbiFlags::merge(*input, abiFlags, newAbiFlags))
1181 continue;
1182
1183 saveTPOffset(*input);
1184 }
1185
1186 m_pInfo.setElfFlags(elfFlags);
1187 if (hasAbiFlags)
1188 m_pAbiInfo = abiFlags;
1189}
1190
1191bool MipsGNULDBackend::mergeSection(Module& pModule, const Input& pInput,
1192 LDSection& pSection) {
1193 if (pSection.flag() & llvm::ELF::SHF_MIPS_GPREL) {
1194 SectionData* sd = NULL;
1195 if (!m_psdata->hasSectionData()) {
1196 sd = IRBuilder::CreateSectionData(*m_psdata);
1197 m_psdata->setSectionData(sd);
1198 }
1199 sd = m_psdata->getSectionData();
1200 moveSectionData(*pSection.getSectionData(), *sd);
1201 } else if (pSection.type() == llvm::ELF::SHT_MIPS_ABIFLAGS) {
1202 // Nothing to do because we handle all .MIPS.abiflags sections
1203 // in the preMergeSections method.
1204 } else {
1205 ObjectBuilder builder(pModule);
1206 builder.MergeSection(pInput, pSection);
1207 }
1208 return true;
1209}
1210
1211void MipsGNULDBackend::moveSectionData(SectionData& pFrom, SectionData& pTo) {
1212 assert(&pFrom != &pTo && "Cannot move section data to itself!");
1213
1214 uint64_t offset = pTo.getSection().size();
1215 AlignFragment* align = NULL;
1216 if (pFrom.getSection().align() > 1) {
1217 // if the align constraint is larger than 1, append an alignment
1218 unsigned int alignment = pFrom.getSection().align();
1219 align = new AlignFragment(/*alignment*/ alignment,
1220 /*the filled value*/ 0x0,
1221 /*the size of filled value*/ 1u,
1222 /*max bytes to emit*/ alignment - 1);
1223 align->setOffset(offset);
1224 align->setParent(&pTo);
1225 pTo.getFragmentList().push_back(align);
1226 offset += align->size();
1227 }
1228
1229 // move fragments from pFrom to pTO
1230 SectionData::FragmentListType& from_list = pFrom.getFragmentList();
1231 SectionData::FragmentListType& to_list = pTo.getFragmentList();
1232 SectionData::FragmentListType::iterator frag, fragEnd = from_list.end();
1233 for (frag = from_list.begin(); frag != fragEnd; ++frag) {
1234 frag->setParent(&pTo);
1235 frag->setOffset(offset);
1236 offset += frag->size();
1237 }
1238 to_list.splice(to_list.end(), from_list);
1239
1240 // set up pTo's header
1241 pTo.getSection().setSize(offset);
1242}
1243
Stephen Hines87f34652014-02-14 18:00:16 -08001244//===----------------------------------------------------------------------===//
1245// Mips32GNULDBackend
1246//===----------------------------------------------------------------------===//
1247Mips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
1248 MipsGNUInfo* pInfo)
Stephen Hines37b74a32014-11-26 18:48:20 -08001249 : MipsGNULDBackend(pConfig, pInfo) {
1250}
Stephen Hines87f34652014-02-14 18:00:16 -08001251
Stephen Hines37b74a32014-11-26 18:48:20 -08001252bool Mips32GNULDBackend::initRelocator() {
1253 if (m_pRelocator == NULL)
Stephen Hines87f34652014-02-14 18:00:16 -08001254 m_pRelocator = new Mips32Relocator(*this, config());
1255
1256 return true;
1257}
1258
1259void Mips32GNULDBackend::initTargetSections(Module& pModule,
Stephen Hines37b74a32014-11-26 18:48:20 -08001260 ObjectBuilder& pBuilder) {
Stephen Hines87f34652014-02-14 18:00:16 -08001261 MipsGNULDBackend::initTargetSections(pModule, pBuilder);
1262
1263 if (LinkerConfig::Object == config().codeGenType())
1264 return;
1265
1266 ELFFileFormat* fileFormat = getOutputFormat();
1267
1268 // initialize .got
1269 LDSection& got = fileFormat->getGOT();
1270 m_pGOT = new Mips32GOT(got);
1271
1272 // initialize .got.plt
1273 LDSection& gotplt = fileFormat->getGOTPLT();
1274 m_pGOTPLT = new MipsGOTPLT(gotplt);
1275
1276 // initialize .plt
1277 LDSection& plt = fileFormat->getPLT();
1278 m_pPLT = new MipsPLT(plt);
1279}
1280
Stephen Hines37b74a32014-11-26 18:48:20 -08001281size_t Mips32GNULDBackend::getRelEntrySize() {
Stephen Hines87f34652014-02-14 18:00:16 -08001282 return 8;
1283}
1284
Stephen Hines37b74a32014-11-26 18:48:20 -08001285size_t Mips32GNULDBackend::getRelaEntrySize() {
Stephen Hines87f34652014-02-14 18:00:16 -08001286 return 12;
1287}
1288
1289//===----------------------------------------------------------------------===//
1290// Mips64GNULDBackend
1291//===----------------------------------------------------------------------===//
1292Mips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
1293 MipsGNUInfo* pInfo)
Stephen Hines37b74a32014-11-26 18:48:20 -08001294 : MipsGNULDBackend(pConfig, pInfo) {
1295}
Stephen Hines87f34652014-02-14 18:00:16 -08001296
Stephen Hines37b74a32014-11-26 18:48:20 -08001297bool Mips64GNULDBackend::initRelocator() {
1298 if (m_pRelocator == NULL)
Stephen Hines87f34652014-02-14 18:00:16 -08001299 m_pRelocator = new Mips64Relocator(*this, config());
1300
1301 return true;
1302}
1303
1304void Mips64GNULDBackend::initTargetSections(Module& pModule,
Stephen Hines37b74a32014-11-26 18:48:20 -08001305 ObjectBuilder& pBuilder) {
Stephen Hines87f34652014-02-14 18:00:16 -08001306 MipsGNULDBackend::initTargetSections(pModule, pBuilder);
1307
1308 if (LinkerConfig::Object == config().codeGenType())
1309 return;
1310
1311 ELFFileFormat* fileFormat = getOutputFormat();
1312
1313 // initialize .got
1314 LDSection& got = fileFormat->getGOT();
1315 m_pGOT = new Mips64GOT(got);
1316
1317 // initialize .got.plt
1318 LDSection& gotplt = fileFormat->getGOTPLT();
1319 m_pGOTPLT = new MipsGOTPLT(gotplt);
1320
1321 // initialize .plt
1322 LDSection& plt = fileFormat->getPLT();
1323 m_pPLT = new MipsPLT(plt);
1324}
1325
Stephen Hines37b74a32014-11-26 18:48:20 -08001326size_t Mips64GNULDBackend::getRelEntrySize() {
Stephen Hines87f34652014-02-14 18:00:16 -08001327 return 16;
1328}
1329
Stephen Hines37b74a32014-11-26 18:48:20 -08001330size_t Mips64GNULDBackend::getRelaEntrySize() {
Stephen Hines87f34652014-02-14 18:00:16 -08001331 return 24;
1332}
1333
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001334//===----------------------------------------------------------------------===//
1335/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
1336///
Stephen Hines37b74a32014-11-26 18:48:20 -08001337static TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig) {
Stephen Hines87f34652014-02-14 18:00:16 -08001338 const llvm::Triple& triple = pConfig.targets().triple();
1339
1340 if (triple.isOSDarwin()) {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001341 assert(0 && "MachO linker is not supported yet");
1342 }
Stephen Hines87f34652014-02-14 18:00:16 -08001343 if (triple.isOSWindows()) {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001344 assert(0 && "COFF linker is not supported yet");
1345 }
Stephen Hines87f34652014-02-14 18:00:16 -08001346
1347 llvm::Triple::ArchType arch = triple.getArch();
1348
1349 if (llvm::Triple::mips64el == arch)
1350 return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
1351
Stephen Hines37b74a32014-11-26 18:48:20 -08001352 assert(arch == llvm::Triple::mipsel);
Stephen Hines87f34652014-02-14 18:00:16 -08001353 return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001354}
1355
Stephen Hines37b74a32014-11-26 18:48:20 -08001356} // namespace mcld
1357
Shih-wei Liao22add6f2012-12-15 17:21:00 -08001358//===----------------------------------------------------------------------===//
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001359// Force static initialization.
Shih-wei Liao22add6f2012-12-15 17:21:00 -08001360//===----------------------------------------------------------------------===//
1361extern "C" void MCLDInitializeMipsLDBackend() {
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001362 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
Stephen Hines37b74a32014-11-26 18:48:20 -08001363 mcld::createMipsLDBackend);
Stephen Hines87f34652014-02-14 18:00:16 -08001364 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
Stephen Hines37b74a32014-11-26 18:48:20 -08001365 mcld::createMipsLDBackend);
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001366}