]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/Elf64Convert.c
BaseTools/GenFw AARCH64: Convert more types of explicit GOT references
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf64Convert.c
index 35e96dd05bc26f7212d0f80af1ecb998bcb993dd..ca3c8f8bee8c346825dc5003572a3a8fd4a7b495 100644 (file)
@@ -1305,6 +1305,22 @@ WriteSections64 (
         Elf_Shdr *SymShdr;\r
         UINT8    *Targ;\r
 \r
+        //\r
+        // The _GLOBAL_OFFSET_TABLE_ symbol is not actually an absolute symbol,\r
+        // but carries the SHN_ABS section index for historical reasons.\r
+        // It must be accompanied by a R_*_GOT_* type relocation on a\r
+        // subsequent instruction, which we handle below, specifically to avoid\r
+        // the GOT indirection, and to refer to the symbol directly. This means\r
+        // we can simply disregard direct references to the GOT symbol itself,\r
+        // as the resulting value will never be used.\r
+        //\r
+        if (Sym->st_shndx == SHN_ABS) {\r
+          const UINT8 *SymName = GetSymName (Sym);\r
+          if (strcmp ((CHAR8 *)SymName, "_GLOBAL_OFFSET_TABLE_") == 0) {\r
+            continue;\r
+          }\r
+        }\r
+\r
         //\r
         // Check section header index found in symbol table and get the section\r
         // header location.\r
@@ -1448,6 +1464,23 @@ WriteSections64 (
           switch (ELF_R_TYPE(Rel->r_info)) {\r
             INT64 Offset;\r
 \r
+          case R_AARCH64_LD64_GOTOFF_LO15:\r
+          case R_AARCH64_LD64_GOTPAGE_LO15:\r
+            //\r
+            // Convert into an ADR instruction that refers to the symbol directly.\r
+            //\r
+            Offset = Sym->st_value - Rel->r_offset;\r
+\r
+            *(UINT32 *)Targ &= 0x1000001f;\r
+            *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29);\r
+\r
+            if (Offset < -0x100000 || Offset > 0xfffff) {\r
+              Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s failed to relax GOT based symbol reference - image is too big (>1 MiB).",\r
+                mInImageName);\r
+              break;\r
+            }\r
+            break;\r
+\r
           case R_AARCH64_LD64_GOT_LO12_NC:\r
             //\r
             // Convert into an ADD instruction - see R_AARCH64_ADR_GOT_PAGE below.\r
@@ -1686,6 +1719,8 @@ WriteRelocations64 (
             case R_AARCH64_LDST128_ABS_LO12_NC:\r
             case R_AARCH64_ADR_GOT_PAGE:\r
             case R_AARCH64_LD64_GOT_LO12_NC:\r
+            case R_AARCH64_LD64_GOTOFF_LO15:\r
+            case R_AARCH64_LD64_GOTPAGE_LO15:\r
               //\r
               // No fixups are required for relative relocations, provided that\r
               // the relative offsets between sections have been preserved in\r