[ELF][MIPS] Implement R_MIPS_GPREL16/R_MIPS_GPREL32 relocations

The R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations use the following
expressions for calculations:
```
local symbol:  S + A + GP0 - GP
global symbol: S + A - GP

GP  - Represents the final gp value, i.e. _gp symbol
GP0 - Represents the gp value used to create the relocatable object
```
The GP0 value is taken from the .reginfo data section defined by an object
file. To implement that I keep a reference to `MipsReginfoInputSection`
in the `ObjectFile` class. This reference is used by the
`ObjectFile::getMipsGp0` method to return the GP0 value.

Differential Revision: http://reviews.llvm.org/D15760

llvm-svn: 256416
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 1b45ec7..2548200 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -187,6 +187,12 @@
     uintX_t A = getAddend<ELFT>(RI);
     if (!Body) {
       uintX_t SymVA = getLocalRelTarget(*File, RI, A);
+      // We need to adjust SymVA value in case of R_MIPS_GPREL16/32 relocations
+      // because they use the following expression to calculate the relocation's
+      // result for local symbol: S + A + GP0 - G.
+      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;
@@ -351,6 +357,13 @@
   return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gprmask;
 }
 
+template <class ELFT> uint32_t MipsReginfoInputSection<ELFT>::getGp0() const {
+  ArrayRef<uint8_t> D = this->getSectionData();
+  if (D.size() != sizeof(Elf_Mips_RegInfo))
+    error("Invalid size of .reginfo section");
+  return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gp_value;
+}
+
 template <class ELFT>
 bool MipsReginfoInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
   return S->SectionKind == InputSectionBase<ELFT>::MipsReginfo;