Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -121,6 +121,10 @@ const Elf_Shdr *getSymbolTable() const { return this->Symtab; }; + // Get MIPS GP0 value defined by this file. + // This value represents the gp value used to create the relocatable object. + uint32_t getMipsGp0() const; + private: void initializeSections(llvm::DenseSet &Comdats); void initializeSymbols(); @@ -133,6 +137,9 @@ // List of all symbols referenced or defined by this file. std::vector SymbolBodies; + // MIPS .reginfo section defined by this file. + MipsReginfoInputSection *MipsReginfo = nullptr; + llvm::BumpPtrAllocator Alloc; llvm::SpecificBumpPtrAllocator> MAlloc; llvm::SpecificBumpPtrAllocator> EHAlloc; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -96,6 +96,10 @@ return this->getSymbolsHelper(true); } +template uint32_t ObjectFile::getMipsGp0() const { + return MipsReginfo ? MipsReginfo->getGp0() : 0; +} + template const typename ObjectFile::Elf_Sym * ObjectFile::getLocalSymbol(uintX_t SymIndex) { @@ -233,10 +237,11 @@ else if (Name == ".eh_frame") Sections[I] = new (this->EHAlloc.Allocate()) EHInputSection(this, &Sec); - else if (Name == ".reginfo") - Sections[I] = + else if (Name == ".reginfo") { + MipsReginfo = new (this->Alloc) MipsReginfoInputSection(this, &Sec); - else if (shouldMerge(Sec)) + Sections[I] = MipsReginfo; + } else if (shouldMerge(Sec)) Sections[I] = new (this->MAlloc.Allocate()) MergeInputSection(this, &Sec); else Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -176,6 +176,7 @@ MipsReginfoInputSection(ObjectFile *F, const Elf_Shdr *Header); uint32_t getGeneralMask() const; + uint32_t getGp0() const; static bool classof(const InputSectionBase *S); }; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -187,6 +187,9 @@ uintX_t A = getAddend(RI); if (!Body) { uintX_t SymVA = getLocalRelTarget(*File, RI, A); + if (Config->EMachine == EM_MIPS && + (Type == R_MIPS_GPREL16 || Type == R_MIPS_GPREL32)) + SymVA += File->getMipsGp0(); Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0, findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs)); continue; @@ -341,6 +344,13 @@ return reinterpret_cast(D.data())->ri_gprmask; } +template uint32_t MipsReginfoInputSection::getGp0() const { + ArrayRef D = this->getSectionData(); + if (D.size() != sizeof(Elf_Mips_RegInfo)) + error("Invalid size of .reginfo section"); + return reinterpret_cast(D.data())->ri_gp_value; +} + template bool MipsReginfoInputSection::classof(const InputSectionBase *S) { return S->SectionKind == InputSectionBase::MipsReginfo; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -1382,6 +1382,18 @@ write32(Loc, (read32(Loc) & 0xffff0000) | (V & 0xffff)); break; } + case R_MIPS_GPREL16: { + uint32_t Instr = read32(Loc); + int64_t V = SA + SignExtend64<16>(Instr & 0xffff) - getMipsGpAddr(); + checkInt<16>(V, Type); + write32(Loc, (Instr & 0xffff0000) | (V & 0xffff)); + break; + } + case R_MIPS_GPREL32: { + int64_t V = SA + int32_t(read32(Loc)) - getMipsGpAddr(); + write32(Loc, V); + break; + } case R_MIPS_HI16: { uint32_t Instr = read32(Loc); if (PairedLoc) { Index: test/ELF/mips-gprel32-relocs.test =================================================================== --- /dev/null +++ test/ELF/mips-gprel32-relocs.test @@ -0,0 +1,31 @@ +# Check R_MIPS_GPREL32 relocation calculation. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: ld.lld -shared -o %t.so %t.o +# RUN: llvm-objdump -s -section=.rodata -t %t.so | FileCheck %s + +# REQUIRES: mips + + .text + .globl __start +__start: + lw $t0,%call16(__start)($gp) +foo: + nop +bar: + nop + + .section .rodata, "a" +v1: + .gpword foo + .gpword bar + +# CHECK: Contents of section .rodata: +# CHECK: 0114 fffe8014 fffe8018 +# ^ 0x10004 - 0x27ff0 +# ^ 0x10008 - 0x27ff0 + +# CHECK: SYMBOL TABLE: +# CHECK: 00010008 .text 00000000 bar +# CHECK: 00010004 .text 00000000 foo +# CHECK: 00027ff0 *ABS* 00000000 _gp