Fixed xgettext invocation in .Sanitize files
[binutils-gdb.git] / bfd / coff-a29k.c
index 46730419578bb73cde244792d42e2622a8447371..bbf23eed981a4643477fc1f6bc2729b8f32625e8 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for AMD 29000 COFF binaries.
-   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
    Contributed by David Wood at New York University 7/8/91.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
-#include "obstack.h"
 #include "coff/a29k.h"
 #include "coff/internal.h"
 #include "libcoff.h"
@@ -45,7 +44,7 @@ static boolean coff_a29k_adjust_symndx
 #define EXTRACT_HWORD(WORD) \
     ((((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff))
 #define SIGN_EXTEND_HWORD(HWORD) \
-    ((HWORD) & 0x8000 ? (HWORD)|0xffff0000 : (HWORD))
+    ((HWORD) & 0x8000 ? (HWORD)|(~0xffffL) : (HWORD))
 
 /* Provided the symbol, returns the value reffed */
 static long
@@ -119,7 +118,7 @@ a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
   if ((part1_consth_active) && (r_type != R_IHCONST)) 
   {
     part1_consth_active = false;
-    *error_message = (char *) "Missing IHCONST";
+    *error_message = (char *) _("Missing IHCONST");
     return(bfd_reloc_dangerous);
   }
 
@@ -134,18 +133,23 @@ a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
     signed_value = EXTRACT_HWORD(insn);
     signed_value = SIGN_EXTEND_HWORD(signed_value);
     signed_value <<= 2;
-    signed_value +=  sym_value + reloc_entry->addend;
-    if (((signed_value + reloc_entry->address) & ~0x3ffff) == 0)
+
+    /* See the note on the R_IREL reloc in coff_a29k_relocate_section.  */
+    if (signed_value == - (long) reloc_entry->address)
+      signed_value = 0;
+
+    signed_value += sym_value + reloc_entry->addend;
+    if ((signed_value & ~0x3ffff) == 0)
     {                          /* Absolute jmp/call */
       insn |= (1<<24);         /* Make it absolute */
-      signed_value += reloc_entry->address;
       /* FIXME: Should we change r_type to R_IABS */
     } 
     else 
     {
       /* Relative jmp/call, so subtract from the value the
         address of the place we're coming from */
-      signed_value -= (input_section->output_section->vma
+      signed_value -= (reloc_entry->address
+                      + input_section->output_section->vma
                       + input_section->output_offset);
       if (signed_value>0x1ffff || signed_value<-0x20000) 
        return(bfd_reloc_overflow);
@@ -174,7 +178,7 @@ a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
     /* consth, part 2 
        Now relocate the reference */
     if (part1_consth_active == false) {
-      *error_message = (char *) "Missing IHIHALF";
+      *error_message = (char *) _("Missing IHIHALF");
       return(bfd_reloc_dangerous);
     }
     /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */
@@ -206,7 +210,7 @@ a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
     bfd_put_32(abfd, insn, hit_data);
     break;
    default:
-    *error_message = "Unrecognized reloc";
+    *error_message = _("Unrecognized reloc");
     return (bfd_reloc_dangerous);
   }
 
@@ -349,7 +353,7 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
       symndx = rel->r_symndx;
       loc = contents + rel->r_vaddr - input_section->vma;
 
-      if (symndx == -1)
+      if (symndx == -1 || rel->r_type == R_IHCONST)
        h = NULL;
       else
        h = obj_coff_sym_hashes (input_bfd)[symndx];
@@ -399,7 +403,7 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
          if (hihalf)
            {
              if (! ((*info->callbacks->reloc_dangerous)
-                    (info, "missing IHCONST reloc", input_bfd,
+                    (info, _("missing IHCONST reloc"), input_bfd,
                      input_section, rel->r_vaddr - input_section->vma)))
                return false;
              hihalf = false;
@@ -422,8 +426,29 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
          signed_value = SIGN_EXTEND_HWORD (signed_value);
          signed_value <<= 2;
 
+         /* Unfortunately, there are two different versions of COFF
+            a29k.  In the original AMD version, the value stored in
+            the field for the R_IREL reloc is a simple addend.  In
+            the GNU version, the value is the negative of the address
+            of the reloc within section.  We try to cope here by
+            assuming the AMD version, unless the addend is exactly
+            the negative of the address; in the latter case we assume
+            the GNU version.  This means that something like
+                .text
+                nop
+                jmp i-4
+            will fail, because the addend of -4 will happen to equal
+            the negative of the address within the section.  The
+            compiler will never generate code like this.
+
+            At some point in the future we may want to take out this
+            check.  */
+
+         if (signed_value == - (long) (rel->r_vaddr - input_section->vma))
+           signed_value = 0;
+
          /* Determine the destination of the jump.  */
-         signed_value += val + rel->r_vaddr - input_section->vma;
+         signed_value += val;
 
          if ((signed_value & ~0x3ffff) == 0)
            {
@@ -469,7 +494,7 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
          if (! hihalf)
            {
              if (! ((*info->callbacks->reloc_dangerous)
-                    (info, "missing IHIHALF reloc", input_bfd,
+                    (info, _("missing IHIHALF reloc"), input_bfd,
                      input_section, rel->r_vaddr - input_section->vma)))
                return false;
              hihalf_val = 0;
@@ -559,8 +584,8 @@ const bfd_target a29kcoff_big_vec =
 {
   "coff-a29k-big",             /* name */
   bfd_target_coff_flavour,
-  true,                                /* data byte order is big */
-  true,                                /* header byte order is big */
+  BFD_ENDIAN_BIG,              /* data byte order is big */
+  BFD_ENDIAN_BIG,              /* header byte order is big */
 
   (HAS_RELOC | EXEC_P |                /* object flags */
    HAS_LINENO | HAS_DEBUG |