FreeBSD/contrib/binutils/bfd/elflink.c
/* Looks for sections with SHF_LINK_ORDER set.  Rearranges them into the same
   order as their linked sections.  Returns false if this could not be done
   because an output section includes both ordered and unordered
   sections.  Ideally we'd do this in the linker proper.  */
Looks for sections with SHF_LINK_ORDER set.  Rearranges them into the same
order as their linked sections.  Returns false if this could not be done
because an output section includes both ordered and unordered
sections.  Ideally we'd do this in the linker proper.
Looks for sections with SHF_LINK_ORDER set . Rearranges them into the same order as their linked sections . Returns false if this could not be done because an output section includes both ordered and unordered sections . Ideally we ' d do this in the linker proper .
static bfd_boolean
elf_fixup_link_order (bfd *abfd, asection *o)
{
  int seen_linkorder;
  int seen_other;
  int n;
  struct bfd_link_order *p;
  bfd *sub;
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  unsigned elfsec;
  struct bfd_link_order **sections;
  asection *s, *other_sec, *linkorder_sec;
  bfd_vma offset;
  other_sec = NULL;
  linkorder_sec = NULL;
  seen_other = 0;
  seen_linkorder = 0;
  for (p = o->map_head.link_order; p != NULL; p = p->next)
    {
      if (p->type == bfd_indirect_link_order)
	{
	  s = p->u.indirect.section;
	  sub = s->owner;
	  if (bfd_get_flavour (sub) == bfd_target_elf_flavour
	      && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
	      && (elfsec = _bfd_elf_section_from_bfd_section (sub, s))
	      && elfsec < elf_numsections (sub)
	      && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER)
	    {
	      seen_linkorder++;
	      linkorder_sec = s;
	    }
	  else
	    {
	      seen_other++;
	      other_sec = s;
	    }
	}
      else
	seen_other++;
      if (seen_other && seen_linkorder)
	{
	  if (other_sec && linkorder_sec)
	    (*_bfd_error_handler) (_("%A has both ordered [`%A' in %B] and unordered [`%A' in %B] sections"),
				   o, linkorder_sec,
				   linkorder_sec->owner, other_sec,
				   other_sec->owner);
	  else
	    (*_bfd_error_handler) (_("%A has both ordered and unordered sections"),
				   o);
	  bfd_set_error (bfd_error_bad_value);
	  return FALSE;
	}
    }
  if (!seen_linkorder)
    return TRUE;
  sections = (struct bfd_link_order **)
    xmalloc (seen_linkorder * sizeof (struct bfd_link_order *));
  seen_linkorder = 0;
  for (p = o->map_head.link_order; p != NULL; p = p->next)
    {
      sections[seen_linkorder++] = p;
    }
  qsort (sections, seen_linkorder, sizeof (struct bfd_link_order *),
	 compare_link_order);
  offset = 0;
  for (n = 0; n < seen_linkorder; n++)
    {
      s = sections[n]->u.indirect.section;
      offset &= ~(bfd_vma)((1 << s->alignment_power) - 1);
      s->output_offset = offset;
      sections[n]->offset = offset;
      offset += sections[n]->size;
    }
  return TRUE;
}
static bfd_boolean elf_fixup_link_order ( bfd * abfd , asection * o ) { int seen_linkorder ; int seen_other ; int n ; struct bfd_link_order * p ; bfd * sub ; const struct elf_backend_data * bed = get_elf_backend_data ( abfd ) ; unsigned elfsec ; struct bfd_link_order * * sections ; asection * s , * other_sec , * linkorder_sec ; bfd_vma offset ; other_sec = NULL ; linkorder_sec = NULL ; seen_other = 0 ; seen_linkorder = 0 ; for ( p = o -> map_head . link_order ; p != NULL ; p = p -> next ) { if ( p -> type == bfd_indirect_link_order ) { s = p -> u . indirect . section ; sub = s -> owner ; if ( bfd_get_flavour ( sub ) == bfd_target_elf_flavour && elf_elfheader ( sub ) -> e_ident [ EI_CLASS ] == bed -> s -> elfclass && ( elfsec = _bfd_elf_section_from_bfd_section ( sub , s ) ) && elfsec < elf_numsections ( sub ) && elf_elfsections ( sub ) [ elfsec ] -> sh_flags & SHF_LINK_ORDER ) { seen_linkorder ++ ; linkorder_sec = s ; } else { seen_other ++ ; other_sec = s ; } } else seen_other ++ ; if ( seen_other && seen_linkorder ) { if ( other_sec && linkorder_sec ) ( * _bfd_error_handler ) ( _ ( " " ) , o , linkorder_sec , linkorder_sec -> owner , other_sec , other_sec -> owner ) ; else ( * _bfd_error_handler ) ( _ ( " " ) , o ) ; bfd_set_error ( bfd_error_bad_value ) ; return FALSE ; } } if ( ! seen_linkorder ) return TRUE ; sections = ( struct bfd_link_order * * ) xmalloc ( seen_linkorder * sizeof ( struct bfd_link_order * ) ) ; seen_linkorder = 0 ; for ( p = o -> map_head . link_order ; p != NULL ; p = p -> next ) { sections [ seen_linkorder ++ ] = p ; } qsort ( sections , seen_linkorder , sizeof ( struct bfd_link_order * ) , compare_link_order ) ; offset = 0 ; for ( n = 0 ; n < seen_linkorder ; n ++ ) { s = sections [ n ] -> u . indirect . section ; offset &= ~ ( bfd_vma ) ( ( 1 << s -> alignment_power ) - 1 ) ; s -> output_offset = offset ; sections [ n ] -> offset = offset ; offset += sections [ n ] -> size ; } return TRUE ; }
Looks for sections with SHF_LINK_ORDER set.
Looks for sections with SHF_LINK_ORDER set .
/* Sort the input sections in the order of their linked section.  */ /* Change the offsets of the sections.  */