LoongArch: binutils: Add support for linker relaxation.
authormengqinggang <mengqinggang@loongson.cn>
Thu, 1 Dec 2022 08:06:42 +0000 (16:06 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Tue, 30 May 2023 11:56:45 +0000 (19:56 +0800)
Add support for relocs related to relax to readelf.

binutils/ChangeLog:

* readelf.c (target_specific_reloc_handling): Handle ULEB128 reloc.
(is_32bit_inplace_add_reloc): Handle new reloc.
(is_32bit_inplace_sub_reloc): Likewise.
(is_64bit_inplace_add_reloc): Likewise.
(is_64bit_inplace_sub_reloc): Likewise.
(is_16bit_inplace_add_reloc): Likewise.
(is_16bit_inplace_sub_reloc): Likewise.
(is_8bit_inplace_add_reloc): Likewise.
(is_8bit_inplace_sub_reloc): Likewise.
(is_6bit_inplace_sub_reloc): Likewise.
(is_6bit_inplace_add_reloc): New function.
(apply_relocations): Handle new reloc.
* testsuite/binutils-all/readelf.exp: Add -mno-relax option
for LoongArch.

binutils/readelf.c
binutils/testsuite/binutils-all/readelf.exp

index d8ad58b15dc2f52e689f903694f88505ba4d8f86..7292dd0941a855e4c75aa7b5ab238343ec645944 100644 (file)
@@ -14008,6 +14008,51 @@ target_specific_reloc_handling (Filedata *filedata,
 
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      {
+       switch (reloc_type)
+         {
+           /* For .uleb128 .LFE1-.LFB1, loongarch write 0 to object file
+              at assembly time.  */
+           case 107: /* R_LARCH_ADD_ULEB128.  */
+           case 108: /* R_LARCH_SUB_ULEB128.  */
+             {
+               uint64_t value;
+               unsigned int reloc_size = 0;
+               int leb_ret = 0;
+
+               value = read_leb128 (start + reloc->r_offset, end, false,
+                             &reloc_size, &leb_ret);
+               if (leb_ret != 0 || reloc_size == 0 || reloc_size > 8)
+                 error (_("LoongArch ULEB128 field at 0x%lx contains invalid "
+                          "ULEB128 value\n"),
+                        (long) reloc->r_offset);
+
+               if (107 == reloc_type)
+                 value += (reloc->r_addend + symtab[sym_index].st_value);
+               else if (108 == reloc_type)
+                 value -= (reloc->r_addend + symtab[sym_index].st_value);
+
+               /* Write uleb128 value to p.  */
+               bfd_byte c;
+               bfd_byte *p = start + reloc->r_offset;
+               do
+                 {
+                   c = value & 0x7f;
+                   if (reloc_size > 1)
+                     c |= 0x80;
+                   *(p++) = c;
+                   value >>= 7;
+                   reloc_size--;
+                 }
+               while (reloc_size);
+
+               return true;
+             }
+         }
+       break;
+      }
+
     case EM_MSP430:
     case EM_MSP430_OLD:
       {
@@ -14734,6 +14779,8 @@ is_32bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 50; /* R_LARCH_ADD32.  */
     case EM_RISCV:
       return reloc_type == 35; /* R_RISCV_ADD32.  */
     default:
@@ -14750,6 +14797,8 @@ is_32bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 55; /* R_LARCH_SUB32.  */
     case EM_RISCV:
       return reloc_type == 39; /* R_RISCV_SUB32.  */
     default:
@@ -14766,6 +14815,8 @@ is_64bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 51; /* R_LARCH_ADD64.  */
     case EM_RISCV:
       return reloc_type == 36; /* R_RISCV_ADD64.  */
     default:
@@ -14782,6 +14833,8 @@ is_64bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 56; /* R_LARCH_SUB64.  */
     case EM_RISCV:
       return reloc_type == 40; /* R_RISCV_SUB64.  */
     default:
@@ -14798,6 +14851,8 @@ is_16bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 48; /* R_LARCH_ADD16.  */
     case EM_RISCV:
       return reloc_type == 34; /* R_RISCV_ADD16.  */
     default:
@@ -14814,6 +14869,8 @@ is_16bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 53; /* R_LARCH_SUB16.  */
     case EM_RISCV:
       return reloc_type == 38; /* R_RISCV_SUB16.  */
     default:
@@ -14830,6 +14887,8 @@ is_8bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 47; /* R_LARCH_ADD8.  */
     case EM_RISCV:
       return reloc_type == 33; /* R_RISCV_ADD8.  */
     default:
@@ -14846,6 +14905,8 @@ is_8bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 52; /* R_LARCH_SUB8.  */
     case EM_RISCV:
       return reloc_type == 37; /* R_RISCV_SUB8.  */
     default:
@@ -14853,6 +14914,21 @@ is_8bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
     }
 }
 
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+   a 6-bit inplace add RELA relocation used in DWARF debug sections.  */
+
+static bool
+is_6bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
+{
+  switch (filedata->file_header.e_machine)
+    {
+    case EM_LOONGARCH:
+      return reloc_type == 105; /* R_LARCH_ADD6.  */
+    default:
+      return false;
+    }
+}
+
 /* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
    a 6-bit inplace sub RELA relocation used in DWARF debug sections.  */
 
@@ -14861,6 +14937,8 @@ is_6bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
 {
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 106; /* R_LARCH_SUB6.  */
     case EM_RISCV:
       return reloc_type == 52; /* R_RISCV_SUB6.  */
     default:
@@ -15108,7 +15186,8 @@ apply_relocations (Filedata *filedata,
              reloc_inplace = true;
            }
          else if ((reloc_subtract = is_6bit_inplace_sub_reloc (filedata,
-                                                               reloc_type)))
+                                                               reloc_type))
+                  || is_6bit_inplace_add_reloc (filedata, reloc_type))
            {
              reloc_size = 1;
              reloc_inplace = true;
@@ -15200,7 +15279,8 @@ apply_relocations (Filedata *filedata,
                        reloc_size);
            }
          else if (is_6bit_abs_reloc (filedata, reloc_type)
-                  || is_6bit_inplace_sub_reloc (filedata, reloc_type))
+                  || is_6bit_inplace_sub_reloc (filedata, reloc_type)
+                  || is_6bit_inplace_add_reloc (filedata, reloc_type))
            {
              if (reloc_subtract)
                addend -= sym->st_value;
index 2a785c6e3dfe84d884c18b5b21273362c0b74b1b..f963c6bee248d570bbf70b6d4ca93ceb264f2145 100644 (file)
@@ -489,18 +489,23 @@ if {![binutils_assemble $srcdir/$subdir/z.s tmpdir/z.o]} then {
     readelf_test {--decompress --hex-dump .debug_loc} $tempfile readelf.z
 }
 
-set hpux ""
+set flags ""
 
 # Skip the next test for the RISCV architectures because they
 # do not support .ULEB128 pseudo-ops with non-constant values.
 if ![istarget "riscv*-*-*"] then {
 
     if [istarget "hppa*64*-*-hpux*"] {
-       set hpux "--defsym HPUX=1"
+       set flags "--defsym HPUX=1"
     }
 
+    # LoongArch relax align add nops, so label subtractions will increase
+    if [istarget "loongarch*-*-*"] {
+       set flags "-mno-relax"
+     }
+
     # Assemble the DWARF-5 test file.
-    if {![binutils_assemble_flags $srcdir/$subdir/dw5.S tmpdir/dw5.o $hpux]} then {
+    if {![binutils_assemble_flags $srcdir/$subdir/dw5.S tmpdir/dw5.o $flags]} then {
        unsupported "readelf -wiaoRlL dw5 (failed to assemble)"
     } else {
 
@@ -612,7 +617,7 @@ if ![is_remote host] {
 }
 
 # Check dwarf-5 support for DW_OP_addrx.
-if {![binutils_assemble_flags $srcdir/$subdir/dw5-op.S tmpdir/dw5-op.o $hpux]} then {
+if {![binutils_assemble_flags $srcdir/$subdir/dw5-op.S tmpdir/dw5-op.o $flags]} then {
     unsupported "readelf -wi dw5-op (failed to assemble)"
 } else {