]> Git Repo - binutils.git/blobdiff - bfd/reloc.c
* bout.c (aout32_slurp_extended_name_table): Define to be
[binutils.git] / bfd / reloc.c
index 89a92b43c1a15ad10444b916ec7c01884f8632c8..327a7eb40468408707d2c1ff86e77b2cb8233c5f 100644 (file)
@@ -45,7 +45,8 @@ SECTION
 #include "sysdep.h"
 #include "libbfd.h"
 #include "seclet.h"
-/*doc*
+/*
+DOCDD
 INODE
        typedef arelent, howto manager, Relocations, Relocations
 
@@ -131,10 +132,13 @@ DESCRIPTION
         will be relative to this point - for example, a relocation
         type which modifies the bottom two bytes of a four byte word
         would not touch the first byte pointed to in a big endian
-        world. @item addend The addend is a value provided by the back
-        end to be added (!) to the relocation offset. Its
-        interpretation is dependent upon the howto. For example, on
-        the 68k the code:
+        world.
+       
+       o addend
+
+       The addend is a value provided by the back end to be added (!)
+       to the relocation offset. Its interpretation is dependent upon
+       the howto. For example, on the 68k the code:
 
 
 |        char foo[];
@@ -247,6 +251,7 @@ SUBSUBSECTION
         information that BFD needs to know to tie up a back end's data.
 
 CODE_FRAGMENT
+.struct symbol_cache_entry;            {* Forward declaration *}
 .
 .typedef CONST struct reloc_howto_struct 
 .{ 
@@ -263,8 +268,9 @@ CODE_FRAGMENT
 .  unsigned int rightshift;
 .
 .       {*  The size of the item to be relocated - 0, is one byte, 1 is 2
-.           bytes, 3 is four bytes. *}
-.  unsigned int size;
+.           bytes, 3 is four bytes.  A -ve value indicates that the
+.          result is to be subtracted from the data*}
+.  int size;
 .
 .       {*  Now obsolete *}
 .  unsigned int bitsize;
@@ -289,7 +295,13 @@ CODE_FRAGMENT
 .          called rather than the normal function. This allows really
 .          strange relocation methods to be accomodated (eg, i960 callj
 .          instructions). *}
-.  bfd_reloc_status_type (*special_function)();
+.  bfd_reloc_status_type (*special_function) 
+.                                  PARAMS ((bfd *abfd,
+.                                           arelent *reloc_entry,
+.                                            struct symbol_cache_entry *symbol,
+.                                            PTR data,
+.                                            asection *input_section, 
+.                                            bfd *output_bfd));
 .
 .       {* The textual name of the relocation type. *}
 .  char *name;
@@ -431,19 +443,29 @@ DEFUN(bfd_perform_relocation,(abfd,
   asymbol *symbol;
 
   symbol = *( reloc_entry->sym_ptr_ptr);
+  if ((symbol->section == &bfd_abs_section) 
+      && output_bfd != (bfd *)NULL) 
+  {
+    reloc_entry->address += input_section->output_offset;
+       
+    return bfd_reloc_ok;
+       
+  }
+
   if ((symbol->section == &bfd_und_section) && output_bfd == (bfd *)NULL) {
-      flag = bfd_reloc_undefined;
-    }
+    flag = bfd_reloc_undefined;
+  }
 
-  if (howto->special_function){
-      bfd_reloc_status_type cont;
-      cont = howto->special_function(abfd,
-                                    reloc_entry,
-                                    symbol,
-                                    data,
-                                    input_section);
-      if (cont != bfd_reloc_continue) return cont;
-    }
+  if (howto->special_function) {
+    bfd_reloc_status_type cont;
+    cont = howto->special_function(abfd,
+                                  reloc_entry,
+                                  symbol,
+                                  data,
+                                  input_section,
+                                  output_bfd);
+    if (cont != bfd_reloc_continue) return cont;
+  }
 
   /* 
     Work out which section the relocation is targetted at and the
@@ -452,22 +474,22 @@ DEFUN(bfd_perform_relocation,(abfd,
 
 
   if (symbol->section == &bfd_com_section) {
-      relocation = 0;
-    }
+    relocation = 0;
+  }
   else {
-      relocation = symbol->value;
-    }
+    relocation = symbol->value;
+  }
 
 
   reloc_target_output_section = symbol->section->output_section;
 
   if (output_bfd && howto->partial_inplace==false) {
-      output_base = 0;
-    }
+    output_base = 0;
+  }
   else {
-      output_base = reloc_target_output_section->vma;
+    output_base = reloc_target_output_section->vma;
 
-    }
+  }
 
   relocation += output_base +   symbol->section->output_offset;
   
@@ -499,44 +521,52 @@ DEFUN(bfd_perform_relocation,(abfd,
      input_section->output_section->vma + input_section->output_offset;
 
     if (howto->pcrel_offset == true) {
-       relocation -= reloc_entry->address;
-      }
+      relocation -= reloc_entry->address;
+    }
 
   }
 
-  if (output_bfd!= (bfd *)NULL) {
-      if ( howto->partial_inplace == false)  {
-         /*
-           This is a partial relocation, and we want to apply the relocation
-           to the reloc entry rather than the raw data. Modify the reloc
-           inplace to reflect what we now know.
-           */
-         reloc_entry->addend = relocation  ;
-         reloc_entry->address +=  input_section->output_offset;
-         return flag;
-       }
-      else 
-      {
-       /* This is a partial relocation, but inplace, so modify the
-          reloc record a bit. 
-          
-          If we've relocated with a symbol with a section, change
-          into a ref to  the section belonging to the symbol
-          */
-         reloc_entry->addend = relocation  ;
-         reloc_entry->address +=  input_section->output_offset;
+  if (output_bfd!= (bfd *)NULL) 
+  {
+    if ( howto->partial_inplace == false)  
+    {
+      /*
+       This is a partial relocation, and we want to apply the relocation
+       to the reloc entry rather than the raw data. Modify the reloc
+       inplace to reflect what we now know.
+       */
+      reloc_entry->addend = relocation  ;
+      reloc_entry->address +=  input_section->output_offset;
+      return flag;
+    }
+    else 
+    {
+      /* This is a partial relocation, but inplace, so modify the
+        reloc record a bit. 
+        
+        If we've relocated with a symbol with a section, change
+        into a ref to  the section belonging to the symbol
+        */
 
+      reloc_entry->address += input_section->output_offset;
 
+      if (abfd->xvec->flavour == bfd_target_coff_flavour) 
+      {
+       relocation -= reloc_entry->addend;
+       reloc_entry->addend = 0;
+      }
+      else
+      {
+       reloc_entry->addend = relocation  ;
       }
     }
+  }
   else 
   {
-    
-  reloc_entry->addend = 0;
-}
+    reloc_entry->addend = 0;
+  }
   
 
-
   /* 
     Either we are relocating all the way, or we don't want to apply
     the relocation to the reloc entry (probably because there isn't
@@ -586,33 +616,42 @@ DEFUN(bfd_perform_relocation,(abfd,
 
    switch (howto->size)
    {
-   case 0:
-   {
-     char x = bfd_get_8(abfd, (char *)data + addr);
-     DOIT(x);
-     bfd_put_8(abfd,x, (unsigned char *) data + addr);
-   }
+    case 0:
+    {
+      char x = bfd_get_8(abfd, (char *)data + addr);
+      DOIT(x);
+      bfd_put_8(abfd,x, (unsigned char *) data + addr);
+    }
      break;
 
-   case 1:
-   { 
-     short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
-     DOIT(x);
-     bfd_put_16(abfd, x,   (unsigned char *)data + addr);
-   }
+    case 1:
+    
+      short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
+      DOIT(x);
+      bfd_put_16(abfd, x,   (unsigned char *)data + addr);
+    }
      break;
-   case 2:
-   {
-     long  x = bfd_get_32(abfd, (bfd_byte *) data + addr);
-     DOIT(x);
-     bfd_put_32(abfd,x,    (bfd_byte *)data + addr);
-   }      
+    case 2:
+    {
+      long  x = bfd_get_32(abfd, (bfd_byte *) data + addr);
+      DOIT(x);
+      bfd_put_32(abfd,x,    (bfd_byte *)data + addr);
+    }      
+     break;
+    case -2:
+    {
+      long  x = bfd_get_32(abfd, (bfd_byte *) data + addr);
+      relocation = -relocation;
+      DOIT(x);
+      bfd_put_32(abfd,x,    (bfd_byte *)data + addr);
+    }      
      break;
-   case 3:
+
+    case 3:
 
      /* Do nothing */
      break;
-   default:
+    default:
      return bfd_reloc_other;
    }
 
@@ -622,6 +661,7 @@ DEFUN(bfd_perform_relocation,(abfd,
 
 
 /*
+DOCDD
 INODE
        howto manager,  , typedef arelent, Relocations
 
@@ -644,6 +684,7 @@ DESCRIPTION
 CODE_FRAGMENT
 .
 .typedef enum bfd_reloc_code_real 
+.
 .{
 .       {* 16 bits wide, simple reloc *}
 .  BFD_RELOC_16,        
@@ -661,7 +702,50 @@ CODE_FRAGMENT
 .          moment probably a 32 bit wide abs address, but the cpu can
 .          choose. *}
 .
-.  BFD_RELOC_CTOR
+.  BFD_RELOC_CTOR,
+.
+.       {* 32 bits wide, simple reloc *}
+.  BFD_RELOC_32,
+.      {* 32 bits, PC-relative *}
+.  BFD_RELOC_32_PCREL,
+.
+.      {* High 22 bits of 32-bit value; simple reloc.  *}
+.  BFD_RELOC_HI22,
+.      {* Low 10 bits.  *}
+.  BFD_RELOC_LO10,
+.
+.      {* Reloc types used for i960/b.out.  *}
+.  BFD_RELOC_24_PCREL,
+.  BFD_RELOC_I960_CALLJ,
+.
+.  BFD_RELOC_16_PCREL,
+.      {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit
+.         word displacement, e.g. for SPARC) *}
+.  BFD_RELOC_32_PCREL_S2,
+.
+.  {* now for the sparc/elf codes *}
+.  BFD_RELOC_NONE,             {* actually used *}
+.  BFD_RELOC_SPARC_WDISP22,
+.  BFD_RELOC_SPARC22,
+.  BFD_RELOC_SPARC13,
+.  BFD_RELOC_SPARC_BASE13,
+.  BFD_RELOC_SPARC_GOT10,
+.  BFD_RELOC_SPARC_GOT13,
+.  BFD_RELOC_SPARC_GOT22,
+.  BFD_RELOC_SPARC_PC10,
+.  BFD_RELOC_SPARC_PC22,
+.  BFD_RELOC_SPARC_WPLT30,
+.  BFD_RELOC_SPARC_COPY,
+.  BFD_RELOC_SPARC_GLOB_DAT,
+.  BFD_RELOC_SPARC_JMP_SLOT,
+.  BFD_RELOC_SPARC_RELATIVE,
+.  BFD_RELOC_SPARC_UA32,
+.
+.  {* this one is a.out specific? *}
+.  BFD_RELOC_SPARC_BASE22,
+.
+.  {* this must be the highest numeric value *}
+.  BFD_RELOC_UNUSED
 . } bfd_reloc_code_real_type;
 */
 
@@ -673,8 +757,7 @@ SECTION
 
 SYNOPSIS
        CONST struct reloc_howto_struct *
-       bfd_reloc_type_lookup
-       (CONST bfd_arch_info_type *arch, bfd_reloc_code_type code);
+       bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
 
 DESCRIPTION
        This routine returns a pointer to a howto struct which when
@@ -685,11 +768,11 @@ DESCRIPTION
 
 
 CONST struct reloc_howto_struct *
-DEFUN(bfd_reloc_type_lookup,(arch, code),
-       CONST bfd_arch_info_type *arch  AND
-       bfd_reloc_code_type code)
+DEFUN(bfd_reloc_type_lookup,(abfd, code),
+      bfd *abfd AND
+      bfd_reloc_code_real_type code)
 {
-  return arch->reloc_type_lookup(arch, code);
+  return BFD_SEND (abfd, reloc_type_lookup, (abfd, code));
 }
 
 static reloc_howto_type bfd_howto_32 =
@@ -703,7 +786,7 @@ INTERNAL_FUNCTION
 SYNOPSIS
        CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup
        (CONST struct bfd_arch_info *,
-         bfd_reloc_code_type  code);
+         bfd_reloc_code_real_type  code);
 
 DESCRIPTION
        Provides a default relocation lookuperer for any architectue 
@@ -713,7 +796,7 @@ DESCRIPTION
 CONST struct reloc_howto_struct *
 DEFUN(bfd_default_reloc_type_lookup,(arch,  code),
      CONST struct bfd_arch_info *arch AND
-      bfd_reloc_code_type  code)
+      bfd_reloc_code_real_type  code)
 {
     switch (code) 
     {
@@ -733,7 +816,7 @@ DEFUN(bfd_default_reloc_type_lookup,(arch,  code),
        default:
        BFD_FAIL();
     }
-return (struct reloc_howto_struct *)NULL;
+return (CONST struct reloc_howto_struct *)NULL;
 }
 
 
@@ -745,20 +828,18 @@ SYNOPSIS
        boolean bfd_generic_relax_section
         (bfd *abfd,
          asection *section,
-         asymbol **symbols,
-         struct bfd_seclet_struct *seclet);
+         asymbol **symbols);
 
 DESCRIPTION
        Provides default handling for relaxing for back ends which
-       don't do relaxing - ie does nothing 
+       don't do relaxing -- i.e., does nothing.
 */
 
 boolean
-DEFUN(bfd_generic_relax_section,(abfd, section, symbols, seclet),
+DEFUN(bfd_generic_relax_section,(abfd, section, symbols),
       bfd *abfd AND
       asection *section AND
-      asymbol **symbols AND
-      struct bfd_seclet_struct *seclet)
+      asymbol **symbols)
 {
   
   return false;
@@ -773,7 +854,8 @@ INTERNAL_FUNCTION
 SYNOPSIS
        bfd_byte *
           bfd_generic_get_relocated_section_contents(bfd *abfd,
-            struct bfd_seclet_struct  *seclet)
+            struct bfd_seclet_struct  *seclet,
+            bfd_byte *data)
 
 DESCRIPTION
        Provides default handling of relocation effort for back ends
@@ -782,27 +864,22 @@ DESCRIPTION
 */
 
 bfd_byte *
-DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet),
+DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet, data),
       bfd *abfd AND
-      struct bfd_seclet_struct *seclet)
+      struct bfd_seclet_struct *seclet AND
+      bfd_byte *data)
 {
   extern bfd_error_vector_type bfd_error_vector;
-  
-
-  asymbol **symbols = 0;
 
   /* Get enough memory to hold the stuff */
   bfd *input_bfd = seclet->u.indirect.section->owner;
   asection *input_section = seclet->u.indirect.section;
 
-  bfd_byte *data = (bfd_byte *)malloc(input_section->_raw_size);
-  bfd_byte *dst = data;
-  bfd_byte *prev_dst = data;
-  unsigned int gap = 0;
+
 
   bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
                                                       input_section);
-  arelent **reloc_vector = (arelent **)malloc(reloc_size);
+  arelent **reloc_vector = (arelent **) alloca(reloc_size);
   
   /* read in the section */
   bfd_get_section_contents(input_bfd,
@@ -834,8 +911,6 @@ DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet),
 
       if (r != bfd_reloc_ok) 
       {
-       asymbol *s;
-
        switch (r)
        {
        case bfd_reloc_undefined:
@@ -857,7 +932,7 @@ DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet),
     }    
   }
 
-  free((char *)reloc_vector);
+
   return data;
 
   
This page took 0.037914 seconds and 4 git commands to generate.