Indent labels
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index 79e68ff47674220a1d8e9a6840b5a671e1f0cb40..90e27023343a7140c88959d899a2ccaa73789239 100644 (file)
@@ -1223,7 +1223,8 @@ elf_x86_64_check_tls_transition (bfd *abfd,
 
     case R_X86_64_GOTPC32_TLSDESC:
       /* Check transition from GDesc access model:
-               leaq x@tlsdesc(%rip), %rax
+               leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
+               rex leal x@tlsdesc(%rip), %eax <--- X32 mode.
 
         Make sure it's a leaq adding rip to a 32-bit offset
         into any register, although it's probably almost always
@@ -1233,7 +1234,8 @@ elf_x86_64_check_tls_transition (bfd *abfd,
        return FALSE;
 
       val = bfd_get_8 (abfd, contents + offset - 3);
-      if ((val & 0xfb) != 0x48)
+      val &= 0xfb;
+      if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40))
        return FALSE;
 
       if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
@@ -1244,13 +1246,26 @@ elf_x86_64_check_tls_transition (bfd *abfd,
 
     case R_X86_64_TLSDESC_CALL:
       /* Check transition from GDesc access model:
-               call *x@tlsdesc(%rax)
+               call *x@tlsdesc(%rax) <--- LP64 mode.
+               call *x@tlsdesc(%eax) <--- X32 mode.
        */
       if (offset + 2 <= sec->size)
        {
-         /* Make sure that it's a call *x@tlsdesc(%rax).  */
+         unsigned int prefix;
          call = contents + offset;
-         return call[0] == 0xff && call[1] == 0x10;
+         prefix = 0;
+         if (!ABI_64_P (abfd))
+           {
+             /* Check for call *x@tlsdesc(%eax).  */
+             if (call[0] == 0x67)
+               {
+                 prefix = 1;
+                 if (offset + 3 > sec->size)
+                   return FALSE;
+               }
+           }
+         /* Make sure that it's a call *x@tlsdesc(%rax).  */
+         return call[prefix] == 0xff && call[1 + prefix] == 0x10;
        }
 
       return FALSE;
@@ -1647,7 +1662,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
   if (no_overflow)
     return TRUE;
 
-convert:
+ convert:
   if (opcode == 0xff)
     {
       /* We have "call/jmp *foo@GOTPCREL(%rip)".  */
@@ -1772,7 +1787,7 @@ convert:
             overflow when sign-extending imm32 to imm64.  */
          r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32;
 
-rewrite_modrm_rex:
+       rewrite_modrm_rex:
          bfd_put_8 (abfd, modrm, contents + roff - 1);
 
          if (rex)
@@ -2164,7 +2179,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_PC32_BND:
        case R_X86_64_PC64:
        case R_X86_64_64:
-pointer:
+       pointer:
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->zero_undefweak |= 0x2;
          /* We are called after all symbols have been resolved.  Only
@@ -2229,7 +2244,7 @@ pointer:
            }
 
          size_reloc = FALSE;
-do_size:
+       do_size:
          if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
                                         htab->pointer_r_type))
            {
@@ -2279,7 +2294,7 @@ do_size:
              p = *head;
              if (p == NULL || p->sec != sec)
                {
-                 bfd_size_type amt = sizeof *p;
+                 size_t amt = sizeof *p;
 
                  p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
@@ -2336,7 +2351,7 @@ do_size:
 
   return TRUE;
 
-error_return:
+ error_return:
   if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
   sec->check_relocs_failed = 1;
@@ -2663,7 +2678,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
          switch (r_type)
            {
            default:
-bad_ifunc_reloc:
+           bad_ifunc_reloc:
              if (h->root.root.string)
                name = h->root.root.string;
              else
@@ -2687,7 +2702,7 @@ bad_ifunc_reloc:
                goto do_relocation;
              /* FALLTHROUGH */
            case R_X86_64_64:
-do_ifunc_pointer:
+           do_ifunc_pointer:
              if (rel->r_addend != 0)
                {
                  if (h->root.root.string)
@@ -2773,7 +2788,7 @@ do_ifunc_pointer:
            }
        }
 
-skip_ifunc:
+    skip_ifunc:
       resolved_to_zero = (eh != NULL
                          && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
 
@@ -3032,7 +3047,7 @@ skip_ifunc:
              break;
            }
 
-use_plt:
+       use_plt:
          if (h->plt.offset != (bfd_vma) -1)
            {
              if (htab->plt_second != NULL)
@@ -3147,7 +3162,7 @@ use_plt:
          /* FIXME: The ABI says the linker should make sure the value is
             the same when it's zeroextended to 64 bit.  */
 
-direct:
+       direct:
          if ((input_section->flags & SEC_ALLOC) == 0)
            break;
 
@@ -3358,7 +3373,7 @@ direct:
                          if (roff < 3
                              || (roff - 3 + 22) > input_section->size)
                            {
-corrupt_input:
+                           corrupt_input:
                              info->callbacks->einfo
                                (_("%F%P: corrupt input: %pB\n"),
                                 input_bfd);
@@ -3401,10 +3416,13 @@ corrupt_input:
                {
                  /* GDesc -> LE transition.
                     It's originally something like:
-                    leaq x@tlsdesc(%rip), %rax
+                    leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
+                    rex leal x@tlsdesc(%rip), %eax <--- X32 mode.
 
                     Change it to:
-                    movl $x@tpoff, %rax.  */
+                    movq $x@tpoff, %rax <--- LP64 mode.
+                    rex movl $x@tpoff, %eax <--- X32 mode.
+                  */
 
                  unsigned int val, type;
 
@@ -3412,7 +3430,8 @@ corrupt_input:
                    goto corrupt_input;
                  type = bfd_get_8 (input_bfd, contents + roff - 3);
                  val = bfd_get_8 (input_bfd, contents + roff - 1);
-                 bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
+                 bfd_put_8 (output_bfd,
+                            (type & 0x48) | ((type >> 2) & 1),
                             contents + roff - 3);
                  bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
                  bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
@@ -3426,11 +3445,30 @@ corrupt_input:
                {
                  /* GDesc -> LE transition.
                     It's originally:
-                    call *(%rax)
+                    call *(%rax) <--- LP64 mode.
+                    call *(%eax) <--- X32 mode.
                     Turn it into:
-                    xchg %ax,%ax.  */
-                 bfd_put_8 (output_bfd, 0x66, contents + roff);
-                 bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                    xchg %ax,%ax <-- LP64 mode.
+                    nopl (%rax)  <-- X32 mode.
+                  */
+                 unsigned int prefix = 0;
+                 if (!ABI_64_P (input_bfd))
+                   {
+                     /* Check for call *x@tlsdesc(%eax).  */
+                     if (contents[roff] == 0x67)
+                       prefix = 1;
+                   }
+                 if (prefix)
+                   {
+                     bfd_put_8 (output_bfd, 0x0f, contents + roff);
+                     bfd_put_8 (output_bfd, 0x1f, contents + roff + 1);
+                     bfd_put_8 (output_bfd, 0x00, contents + roff + 2);
+                   }
+                 else
+                   {
+                     bfd_put_8 (output_bfd, 0x66, contents + roff);
+                     bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                   }
                  continue;
                }
              else if (r_type == R_X86_64_GOTTPOFF)
@@ -3741,13 +3779,18 @@ corrupt_input:
                {
                  /* GDesc -> IE transition.
                     It's originally something like:
-                    leaq x@tlsdesc(%rip), %rax
+                    leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
+                    rex leal x@tlsdesc(%rip), %eax <--- X32 mode.
 
                     Change it to:
-                    movq x@gottpoff(%rip), %rax # before xchg %ax,%ax.  */
+                    # before xchg %ax,%ax in LP64 mode.
+                    movq x@gottpoff(%rip), %rax
+                    # before nopl (%rax) in X32 mode.
+                    rex movl x@gottpoff(%rip), %eax
+                 */
 
                  /* Now modify the instruction as appropriate. To
-                    turn a leaq into a movq in the form we use it, it
+                    turn a lea into a mov in the form we use it, it
                     suffices to change the second byte from 0x8d to
                     0x8b.  */
                  if (roff < 2)
@@ -3768,13 +3811,32 @@ corrupt_input:
                {
                  /* GDesc -> IE transition.
                     It's originally:
-                    call *(%rax)
+                    call *(%rax) <--- LP64 mode.
+                    call *(%eax) <--- X32 mode.
 
                     Change it to:
-                    xchg %ax, %ax.  */
+                    xchg %ax, %ax <-- LP64 mode.
+                    nopl (%rax)  <-- X32 mode.
+                  */
 
-                 bfd_put_8 (output_bfd, 0x66, contents + roff);
-                 bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                 unsigned int prefix = 0;
+                 if (!ABI_64_P (input_bfd))
+                   {
+                     /* Check for call *x@tlsdesc(%eax).  */
+                     if (contents[roff] == 0x67)
+                       prefix = 1;
+                   }
+                 if (prefix)
+                   {
+                     bfd_put_8 (output_bfd, 0x0f, contents + roff);
+                     bfd_put_8 (output_bfd, 0x1f, contents + roff + 1);
+                     bfd_put_8 (output_bfd, 0x00, contents + roff + 2);
+                   }
+                 else
+                   {
+                     bfd_put_8 (output_bfd, 0x66, contents + roff);
+                     bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                   }
                  continue;
                }
              else
@@ -3969,12 +4031,12 @@ corrupt_input:
            }
        }
 
-do_relocation:
+    do_relocation:
       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset,
                                    relocation, rel->r_addend);
 
-check_relocation_error:
+    check_relocation_error:
       if (r != bfd_reloc_ok)
        {
          const char *name;
@@ -4397,7 +4459,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       else
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
-do_glob_dat:
+       do_glob_dat:
          bfd_put_64 (output_bfd, (bfd_vma) 0,
                      htab->elf.sgot->contents + h->got.offset);
          rela.r_info = htab->r_info (h->dynindx, R_X86_64_GLOB_DAT);
This page took 0.027702 seconds and 4 git commands to generate.