]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/reloc.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / bfd / reloc.c
index 76c309bc9035f57dc504e6203ca37f3e7bf35edf..fbc67ac72805005ef7fa6da916d91e38456f480b 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD support for handling relocation entries.
-   Copyright (C) 1990-2022 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -62,8 +62,7 @@ SUBSECTION
 
        This is the structure of a relocation entry:
 
-CODE_FRAGMENT
-.
+EXTERNAL
 .typedef enum bfd_reloc_status
 .{
 .  {* No errors detected.  Note - the value 2 is used so that it
@@ -82,7 +81,7 @@ CODE_FRAGMENT
 .  {* Unsupported relocation size requested.  *}
 .  bfd_reloc_notsupported,
 .
-.  {* Unused.  *}
+.  {* Target specific meaning.  *}
 .  bfd_reloc_other,
 .
 .  {* The symbol to relocate against was undefined.  *}
@@ -97,7 +96,9 @@ CODE_FRAGMENT
 .
 .typedef const struct reloc_howto_struct reloc_howto_type;
 .
-.typedef struct reloc_cache_entry
+
+CODE_FRAGMENT
+.struct reloc_cache_entry
 .{
 .  {* A pointer into the canonical table of pointers.  *}
 .  struct bfd_symbol **sym_ptr_ptr;
@@ -111,8 +112,7 @@ CODE_FRAGMENT
 .  {* Pointer to how to perform the required relocation.  *}
 .  reloc_howto_type *howto;
 .
-.}
-.arelent;
+.};
 .
 */
 
@@ -251,7 +251,6 @@ SUBSUBSECTION
        performing a relocation.
 
 CODE_FRAGMENT
-.
 .enum complain_overflow
 .{
 .  {* Do not complain on overflow.  *}
@@ -270,7 +269,7 @@ CODE_FRAGMENT
 .     unsigned number.  *}
 .  complain_overflow_unsigned
 .};
-
+.
 */
 
 /*
@@ -338,6 +337,11 @@ CODE_FRAGMENT
 .     empty (e.g., ELF); this flag signals the fact.  *}
 .  unsigned int pcrel_offset:1;
 .
+.  {* Whether bfd_install_relocation should just install the addend,
+.     or should follow the practice of some older object formats and
+.     install a value including the symbol.  *}
+.  unsigned int install_addend:1;
+.
 .  {* src_mask selects the part of the instruction (or data) to be used
 .     in the relocation sum.  If the target relocations don't have an
 .     addend in the reloc, eg. ELF USE_REL, src_mask will normally equal
@@ -373,11 +377,13 @@ DESCRIPTION
        The HOWTO macro fills in a reloc_howto_type (a typedef for
        const struct reloc_howto_struct).
 
+.#define HOWTO_INSTALL_ADDEND 0
 .#define HOWTO_RSIZE(sz) ((sz) < 0 ? -(sz) : (sz))
 .#define HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,  \
 .              inplace, src_mask, dst_mask, pcrel_off)                 \
 .  { (unsigned) type, HOWTO_RSIZE (size), bits, right, left, ovf,      \
-.    size < 0, pcrel, inplace, pcrel_off, src_mask, dst_mask, func, name }
+.    size < 0, pcrel, inplace, pcrel_off, HOWTO_INSTALL_ADDEND,                \
+.    src_mask, dst_mask, func, name }
 
 DESCRIPTION
        This is used to fill in an empty howto entry in an array.
@@ -395,11 +401,10 @@ DESCRIPTION
 */
 
 /*
-TYPEDEF
+DEFINITION
        arelent_chain
 
 DESCRIPTION
-
        How relocs are tied together in an <<asection>>:
 
 .typedef struct relent_chain
@@ -801,9 +806,7 @@ bfd_perform_relocation (bfd *abfd,
          reloc_entry->address += input_section->output_offset;
 
          /* WTF?? */
-         if (abfd->xvec->flavour == bfd_target_coff_flavour
-             && strcmp (abfd->xvec->name, "coff-Intel-little") != 0
-             && strcmp (abfd->xvec->name, "coff-Intel-big") != 0)
+         if (abfd->xvec->flavour == bfd_target_coff_flavour)
            {
              /* For m68k-coff, the addend was being subtracted twice during
                 relocation with -r.  Removing the line below this comment
@@ -1021,8 +1024,6 @@ bfd_install_relocation (bfd *abfd,
         reloc_entry->address field might actually be valid for the
         backend concerned.  It is up to the special_function itself
         to call bfd_reloc_offset_in_range if needed.  */
-      /* XXX - The special_function calls haven't been fixed up to deal
-        with creating new relocations and section contents.  */
       cont = howto->special_function (abfd, reloc_entry, symbol,
                                      /* XXX - Non-portable! */
                                      ((bfd_byte *) data_start
@@ -1032,199 +1033,81 @@ bfd_install_relocation (bfd *abfd,
        return cont;
     }
 
-  if (bfd_is_abs_section (symbol->section))
-    {
-      reloc_entry->address += input_section->output_offset;
-      return bfd_reloc_ok;
-    }
-
-  /* No need to check for howto != NULL if !bfd_is_abs_section as
-     it will have been checked in `bfd_perform_relocation already'.  */
-
-  /* Is the address of the relocation really within the section?  */
-  octets = reloc_entry->address * bfd_octets_per_byte (abfd, input_section);
-  if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
-    return bfd_reloc_outofrange;
-
-  /* Work out which section the relocation is targeted at and the
-     initial relocation command value.  */
-
-  /* Get symbol value.  (Common symbols are special.)  */
-  if (bfd_is_com_section (symbol->section))
-    relocation = 0;
+  if (howto->install_addend)
+    relocation = reloc_entry->addend;
   else
-    relocation = symbol->value;
-
-  reloc_target_output_section = symbol->section->output_section;
-
-  /* Convert input-section-relative symbol value to absolute.  */
-  if (! howto->partial_inplace)
-    output_base = 0;
-  else
-    output_base = reloc_target_output_section->vma;
-
-  output_base += symbol->section->output_offset;
-
-  /* If symbol addresses are in octets, convert to bytes.  */
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-      && (symbol->section->flags & SEC_ELF_OCTETS))
-    output_base *= bfd_octets_per_byte (abfd, input_section);
+    {
+      if (bfd_is_abs_section (symbol->section))
+       return bfd_reloc_ok;
 
-  relocation += output_base;
+      /* Work out which section the relocation is targeted at and the
+        initial relocation command value.  */
 
-  /* Add in supplied addend.  */
-  relocation += reloc_entry->addend;
+      /* Get symbol value.  (Common symbols are special.)  */
+      if (bfd_is_com_section (symbol->section))
+       relocation = 0;
+      else
+       relocation = symbol->value;
 
-  /* Here the variable relocation holds the final address of the
-     symbol we are relocating against, plus any addend.  */
+      reloc_target_output_section = symbol->section;
 
-  if (howto->pc_relative)
-    {
-      /* This is a PC relative relocation.  We want to set RELOCATION
-        to the distance between the address of the symbol and the
-        location.  RELOCATION is already the address of the symbol.
+      /* Convert input-section-relative symbol value to absolute.  */
+      if (! howto->partial_inplace)
+       output_base = 0;
+      else
+       output_base = reloc_target_output_section->vma;
 
-        We start by subtracting the address of the section containing
-        the location.
+      /* If symbol addresses are in octets, convert to bytes.  */
+      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+         && (symbol->section->flags & SEC_ELF_OCTETS))
+       output_base *= bfd_octets_per_byte (abfd, input_section);
 
-        If pcrel_offset is set, we must further subtract the position
-        of the location within the section.  Some targets arrange for
-        the addend to be the negative of the position of the location
-        within the section; for example, i386-aout does this.  For
-        i386-aout, pcrel_offset is FALSE.  Some other targets do not
-        include the position of the location; for example, ELF.
-        For those targets, pcrel_offset is TRUE.
+      relocation += output_base;
 
-        If we are producing relocatable output, then we must ensure
-        that this reloc will be correctly computed when the final
-        relocation is done.  If pcrel_offset is FALSE we want to wind
-        up with the negative of the location within the section,
-        which means we must adjust the existing addend by the change
-        in the location within the section.  If pcrel_offset is TRUE
-        we do not want to adjust the existing addend at all.
+      /* Add in supplied addend.  */
+      relocation += reloc_entry->addend;
 
-        FIXME: This seems logical to me, but for the case of
-        producing relocatable output it is not what the code
-        actually does.  I don't want to change it, because it seems
-        far too likely that something will break.  */
+      /* Here the variable relocation holds the final address of the
+        symbol we are relocating against, plus any addend.  */
 
-      relocation -=
-       input_section->output_section->vma + input_section->output_offset;
+      if (howto->pc_relative)
+       {
+         relocation -= input_section->vma;
 
-      if (howto->pcrel_offset && howto->partial_inplace)
-       relocation -= reloc_entry->address;
+         if (howto->pcrel_offset && howto->partial_inplace)
+           relocation -= reloc_entry->address;
+       }
     }
 
-  if (! howto->partial_inplace)
+  if (!howto->partial_inplace)
     {
-      /* 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;
 
-      /* WTF?? */
-      if (abfd->xvec->flavour == bfd_target_coff_flavour
-         && strcmp (abfd->xvec->name, "coff-Intel-little") != 0
-         && strcmp (abfd->xvec->name, "coff-Intel-big") != 0)
-       {
-
-         /* For m68k-coff, the addend was being subtracted twice during
-            relocation with -r.  Removing the line below this comment
-            fixes that problem; see PR 2953.
-
-However, Ian wrote the following, regarding removing the line below,
-which explains why it is still enabled:  --djm
-
-If you put a patch like that into BFD you need to check all the COFF
-linkers.  I am fairly certain that patch will break coff-i386 (e.g.,
-SCO); see coff_i386_reloc in coff-i386.c where I worked around the
-problem in a different way.  There may very well be a reason that the
-code works as it does.
-
-Hmmm.  The first obvious point is that bfd_install_relocation should
-not have any tests that depend upon the flavour.  It's seem like
-entirely the wrong place for such a thing.  The second obvious point
-is that the current code ignores the reloc addend when producing
-relocatable output for COFF.  That's peculiar.  In fact, I really
-have no idea what the point of the line you want to remove is.
-
-A typical COFF reloc subtracts the old value of the symbol and adds in
-the new value to the location in the object file (if it's a pc
-relative reloc it adds the difference between the symbol value and the
-location).  When relocating we need to preserve that property.
-
-BFD handles this by setting the addend to the negative of the old
-value of the symbol.  Unfortunately it handles common symbols in a
-non-standard way (it doesn't subtract the old value) but that's a
-different story (we can't change it without losing backward
-compatibility with old object files) (coff-i386 does subtract the old
-value, to be compatible with existing coff-i386 targets, like SCO).
-
-So everything works fine when not producing relocatable output.  When
-we are producing relocatable output, logically we should do exactly
-what we do when not producing relocatable output.  Therefore, your
-patch is correct.  In fact, it should probably always just set
-reloc_entry->addend to 0 for all cases, since it is, in fact, going to
-add the value into the object file.  This won't hurt the COFF code,
-which doesn't use the addend; I'm not sure what it will do to other
-formats (the thing to check for would be whether any formats both use
-the addend and set partial_inplace).
-
-When I wanted to make coff-i386 produce relocatable output, I ran
-into the problem that you are running into: I wanted to remove that
-line.  Rather than risk it, I made the coff-i386 relocs use a special
-function; it's coff_i386_reloc in coff-i386.c.  The function
-specifically adds the addend field into the object file, knowing that
-bfd_install_relocation is not going to.  If you remove that line, then
-coff-i386.c will wind up adding the addend field in twice.  It's
-trivial to fix; it just needs to be done.
-
-The problem with removing the line is just that it may break some
-working code.  With BFD it's hard to be sure of anything.  The right
-way to deal with this is simply to build and test at least all the
-supported COFF targets.  It should be straightforward if time and disk
-space consuming.  For each target:
-    1) build the linker
-    2) generate some executable, and link it using -r (I would
-       probably use paranoia.o and link against newlib/libc.a, which
-       for all the supported targets would be available in
-       /usr/cygnus/progressive/H-host/target/lib/libc.a).
-    3) make the change to reloc.c
-    4) rebuild the linker
-    5) repeat step 2
-    6) if the resulting object files are the same, you have at least
-       made it no worse
-    7) if they are different you have to figure out which version is
-       right.  */
-         relocation -= reloc_entry->addend;
-         /* FIXME: There should be no target specific code here...  */
-         if (strcmp (abfd->xvec->name, "coff-z8k") != 0)
-           reloc_entry->addend = 0;
-       }
-      else
-       {
-         reloc_entry->addend = relocation;
-       }
+  if (!howto->install_addend
+      && abfd->xvec->flavour == bfd_target_coff_flavour)
+    {
+      /* This is just weird.  We're subtracting out the original
+        addend, so that for COFF the addend is ignored???  */
+      relocation -= reloc_entry->addend;
+      /* FIXME: There should be no target specific code here...  */
+      if (strcmp (abfd->xvec->name, "coff-z8k") != 0)
+       reloc_entry->addend = 0;
     }
+  else
+    reloc_entry->addend = relocation;
+
+  /* Is the address of the relocation really within the section?  */
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, input_section);
+  if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
+    return bfd_reloc_outofrange;
 
   /* FIXME: This overflow checking is incomplete, because the value
      might have overflowed before we get here.  For a correct check we
      need to compute the value in a size larger than bitsize, but we
      can't reasonably do that for a reloc the same size as a host
-     machine word.
-     FIXME: We should also do overflow checking on the result after
-     adding in the value contained in the object file.  */
+     machine word.  */
   if (howto->complain_on_overflow != complain_overflow_dont)
     flag = bfd_check_overflow (howto->complain_on_overflow,
                               howto->bitsize,
@@ -1232,71 +1115,11 @@ space consuming.  For each target:
                               bfd_arch_bits_per_address (abfd),
                               relocation);
 
-  /* 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
-     any room in the output format to describe addends to relocs).  */
-
-  /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
-     (OSF version 1.3, compiler version 3.11).  It miscompiles the
-     following program:
-
-     struct str
-     {
-       unsigned int i0;
-     } s = { 0 };
-
-     int
-     main ()
-     {
-       unsigned long x;
-
-       x = 0x100000000;
-       x <<= (unsigned long) s.i0;
-       if (x == 0)
-        printf ("failed\n");
-       else
-        printf ("succeeded (%lx)\n", x);
-     }
-     */
-
   relocation >>= (bfd_vma) howto->rightshift;
 
   /* Shift everything up to where it's going to be used.  */
   relocation <<= (bfd_vma) howto->bitpos;
 
-  /* Wait for the day when all have the mask in them.  */
-
-  /* What we do:
-     i instruction to be left alone
-     o offset within instruction
-     r relocation offset to apply
-     S src mask
-     D dst mask
-     N ~dst mask
-     A part 1
-     B part 2
-     R result
-
-     Do this:
-     ((         i i i i i o o o o o  from bfd_get<size>
-     and          S S S S S) to get the size offset we want
-     +  r r r r r r r r r r) to get the final value to place
-     and          D D D D D  to chop to right size
-     -----------------------
-     =            A A A A A
-     And this:
-     (  i i i i i o o o o o  from bfd_get<size>
-     and N N N N N         ) get instruction
-     -----------------------
-     =  B B B B B
-
-     And then:
-     (  B B B B B
-     or                   A A A A A)
-     -----------------------
-     =  R R R R R R R R R R  put into bfd_put<size>
-     */
-
   data = (bfd_byte *) data_start + (octets - data_start_offset);
   apply_reloc (abfd, data, howto, relocation);
   return flag;
@@ -1547,8 +1370,8 @@ SUBSECTION
 */
 
 /*
-TYPEDEF
-       bfd_reloc_code_type
+DEFINITION
+       bfd_reloc_code_real_type
 
 DESCRIPTION
        The insides of a reloc code.  The idea is that, eventually, there
@@ -2293,7 +2116,7 @@ ENUMX
 ENUMX
   BFD_RELOC_MICROMIPS_SCN_DISP
 ENUMX
-  BFD_RELOC_MIPS_REL16
+  BFD_RELOC_MIPS_16
 ENUMX
   BFD_RELOC_MIPS_RELGOT
 ENUMX
@@ -5225,6 +5048,10 @@ ENUMX
   BFD_RELOC_RISCV_SET32
 ENUMX
   BFD_RELOC_RISCV_32_PCREL
+ENUMX
+  BFD_RELOC_RISCV_SET_ULEB128
+ENUMX
+  BFD_RELOC_RISCV_SUB_ULEB128
 ENUMDOC
   RISC-V relocations.
 
@@ -6289,17 +6116,6 @@ ENUMDOC
   Self-describing complex relocations.
 COMMENT
 
-ENUM
-  BFD_RELOC_XC16X_PAG
-ENUMX
-  BFD_RELOC_XC16X_POF
-ENUMX
-  BFD_RELOC_XC16X_SEG
-ENUMX
-  BFD_RELOC_XC16X_SOF
-ENUMDOC
-  Infineon Relocations.
-
 ENUM
   BFD_RELOC_VAX_GLOB_DAT
 ENUMX
@@ -7935,12 +7751,6 @@ ENUMDOC
 
 ENUM
   BFD_RELOC_BPF_64
-ENUMX
-  BFD_RELOC_BPF_32
-ENUMX
-  BFD_RELOC_BPF_16
-ENUMX
-  BFD_RELOC_BPF_DISP16
 ENUMX
   BFD_RELOC_BPF_DISP32
 ENUMDOC
@@ -8239,14 +8049,122 @@ ENUMX
   BFD_RELOC_LARCH_SUB32
 ENUMX
   BFD_RELOC_LARCH_SUB64
+
+ENUMX
+  BFD_RELOC_LARCH_B16
+ENUMX
+  BFD_RELOC_LARCH_B21
+ENUMX
+  BFD_RELOC_LARCH_B26
+
+ENUMX
+  BFD_RELOC_LARCH_ABS_HI20
+ENUMX
+  BFD_RELOC_LARCH_ABS_LO12
+ENUMX
+  BFD_RELOC_LARCH_ABS64_LO20
+ENUMX
+  BFD_RELOC_LARCH_ABS64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_PCALA_HI20
+ENUMX
+  BFD_RELOC_LARCH_PCALA_LO12
+ENUMX
+  BFD_RELOC_LARCH_PCALA64_LO20
+ENUMX
+  BFD_RELOC_LARCH_PCALA64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_GOT_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_GOT_PC_LO12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_PC_HI12
+ENUMX
+  BFD_RELOC_LARCH_GOT_HI20
+ENUMX
+  BFD_RELOC_LARCH_GOT_LO12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_LO20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE64_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_PC_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_PC_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD_HI20
+
+ENUMX
+  BFD_RELOC_LARCH_32_PCREL
+
+ENUMX
+  BFD_RELOC_LARCH_RELAX
+
+ENUMX
+  BFD_RELOC_LARCH_DELETE
+
+ENUMX
+  BFD_RELOC_LARCH_ALIGN
+
+ENUMX
+  BFD_RELOC_LARCH_PCREL20_S2
+
+ENUMX
+  BFD_RELOC_LARCH_CFA
+
+ENUMX
+  BFD_RELOC_LARCH_ADD6
+ENUMX
+  BFD_RELOC_LARCH_SUB6
+
+ENUMX
+  BFD_RELOC_LARCH_ADD_ULEB128
+ENUMX
+  BFD_RELOC_LARCH_SUB_ULEB128
+
+ENUMX
+  BFD_RELOC_LARCH_64_PCREL
+
 ENUMDOC
   LARCH relocations.
 
 ENDSENUM
   BFD_RELOC_UNUSED
+
 CODE_FRAGMENT
-.
 .typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+.
 */
 
 /*
@@ -8264,7 +8182,6 @@ DESCRIPTION
        Return a pointer to a howto structure which, when
        invoked, will perform the relocation @var{code} on data from the
        architecture noted.
-
 */
 
 reloc_howto_type *
@@ -8292,7 +8209,6 @@ SYNOPSIS
 
 DESCRIPTION
        Provides a default relocation lookup routine for any architecture.
-
 */
 
 reloc_howto_type *
@@ -8439,7 +8355,6 @@ SYNOPSIS
 DESCRIPTION
        Provides default handling of relocation effort for back ends
        which can't be bothered to do it efficiently.
-
 */
 
 bfd_byte *
@@ -8461,6 +8376,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
     return NULL;
 
   /* Read in the section.  */
+  bfd_byte *orig_data = data;
   if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
     return NULL;
 
@@ -8472,7 +8388,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
 
   reloc_vector = (arelent **) bfd_malloc (reloc_size);
   if (reloc_vector == NULL)
-    return NULL;
+    goto error_return;
 
   reloc_count = bfd_canonicalize_reloc (input_bfd,
                                        input_section,
@@ -8609,6 +8525,8 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
 
  error_return:
   free (reloc_vector);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
@@ -8635,6 +8553,10 @@ _bfd_generic_set_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 {
   section->orelocation = relptr;
   section->reloc_count = count;
+  if (count != 0)
+    section->flags |= SEC_RELOC;
+  else
+    section->flags &= ~SEC_RELOC;
 }
 
 /*