OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [layout.cc] - Diff between revs 148 and 159

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 148 Rev 159
Line 44... Line 44...
#include "symtab.h"
#include "symtab.h"
#include "dynobj.h"
#include "dynobj.h"
#include "ehframe.h"
#include "ehframe.h"
#include "compressed_output.h"
#include "compressed_output.h"
#include "reduced_debug_output.h"
#include "reduced_debug_output.h"
 
#include "object.h"
#include "reloc.h"
#include "reloc.h"
#include "descriptors.h"
#include "descriptors.h"
#include "plugin.h"
#include "plugin.h"
#include "incremental.h"
#include "incremental.h"
#include "layout.h"
#include "layout.h"
Line 159... Line 160...
  if (len == 0)
  if (len == 0)
    return align_address(minoff, align);
    return align_address(minoff, align);
 
 
  ++Free_list::num_allocates;
  ++Free_list::num_allocates;
 
 
 
  // We usually want to drop free chunks smaller than 4 bytes.
 
  // If we need to guarantee a minimum hole size, though, we need
 
  // to keep track of all free chunks.
 
  const int fuzz = this->min_hole_ > 0 ? 0 : 3;
 
 
  for (Iterator p = this->list_.begin(); p != this->list_.end(); ++p)
  for (Iterator p = this->list_.begin(); p != this->list_.end(); ++p)
    {
    {
      ++Free_list::num_allocate_visits;
      ++Free_list::num_allocate_visits;
      off_t start = p->start_ > minoff ? p->start_ : minoff;
      off_t start = p->start_ > minoff ? p->start_ : minoff;
      start = align_address(start, align);
      start = align_address(start, align);
      off_t end = start + len;
      off_t end = start + len;
      if (end <= p->end_)
      if (end > p->end_ && p->end_ == this->length_ && this->extend_)
        {
        {
          if (p->start_ + 3 >= start && p->end_ <= end + 3)
          this->length_ = end;
 
          p->end_ = end;
 
        }
 
      if (end == p->end_ || (end <= p->end_ - this->min_hole_))
 
        {
 
          if (p->start_ + fuzz >= start && p->end_ <= end + fuzz)
            this->list_.erase(p);
            this->list_.erase(p);
          else if (p->start_ + 3 >= start)
          else if (p->start_ + fuzz >= start)
            p->start_ = end;
            p->start_ = end;
          else if (p->end_ <= end + 3)
          else if (p->end_ <= end + fuzz)
            p->end_ = start;
            p->end_ = start;
          else
          else
            {
            {
              Free_list_node newnode(p->start_, start);
              Free_list_node newnode(p->start_, start);
              p->start_ = end;
              p->start_ = end;
Line 183... Line 194...
              ++Free_list::num_nodes;
              ++Free_list::num_nodes;
            }
            }
          return start;
          return start;
        }
        }
    }
    }
 
  if (this->extend_)
 
    {
 
      off_t start = align_address(this->length_, align);
 
      this->length_ = start + len;
 
      return start;
 
    }
  return -1;
  return -1;
}
}
 
 
// Dump the free list (for debugging).
// Dump the free list (for debugging).
void
void
Line 358... Line 375...
    unattached_section_list_(),
    unattached_section_list_(),
    special_output_list_(),
    special_output_list_(),
    section_headers_(NULL),
    section_headers_(NULL),
    tls_segment_(NULL),
    tls_segment_(NULL),
    relro_segment_(NULL),
    relro_segment_(NULL),
 
    interp_segment_(NULL),
    increase_relro_(0),
    increase_relro_(0),
    symtab_section_(NULL),
    symtab_section_(NULL),
    symtab_xindex_(NULL),
    symtab_xindex_(NULL),
    dynsym_section_(NULL),
    dynsym_section_(NULL),
    dynsym_xindex_(NULL),
    dynsym_xindex_(NULL),
Line 384... Line 402...
    input_without_gnu_stack_note_(false),
    input_without_gnu_stack_note_(false),
    has_static_tls_(false),
    has_static_tls_(false),
    any_postprocessing_sections_(false),
    any_postprocessing_sections_(false),
    resized_signatures_(false),
    resized_signatures_(false),
    have_stabstr_section_(false),
    have_stabstr_section_(false),
 
    section_ordering_specified_(false),
    incremental_inputs_(NULL),
    incremental_inputs_(NULL),
    record_output_section_data_from_script_(false),
    record_output_section_data_from_script_(false),
    script_output_section_data_list_(),
    script_output_section_data_list_(),
    segment_states_(NULL),
    segment_states_(NULL),
    relaxation_debug_check_(NULL),
    relaxation_debug_check_(NULL),
 
    input_section_position_(),
 
    input_section_glob_(),
    incremental_base_(NULL),
    incremental_base_(NULL),
    free_list_()
    free_list_()
{
{
  // Make space for more than enough segments for a typical file.
  // Make space for more than enough segments for a typical file.
  // This is just for efficiency--it's OK if we wind up needing more.
  // This is just for efficiency--it's OK if we wind up needing more.
Line 614... Line 635...
        && ((*p)->flags() & clear) == 0)
        && ((*p)->flags() & clear) == 0)
      return *p;
      return *p;
  return NULL;
  return NULL;
}
}
 
 
 
// When we put a .ctors or .dtors section with more than one word into
 
// a .init_array or .fini_array section, we need to reverse the words
 
// in the .ctors/.dtors section.  This is because .init_array executes
 
// constructors front to back, where .ctors executes them back to
 
// front, and vice-versa for .fini_array/.dtors.  Although we do want
 
// to remap .ctors/.dtors into .init_array/.fini_array because it can
 
// be more efficient, we don't want to change the order in which
 
// constructors/destructors are run.  This set just keeps track of
 
// these sections which need to be reversed.  It is only changed by
 
// Layout::layout.  It should be a private member of Layout, but that
 
// would require layout.h to #include object.h to get the definition
 
// of Section_id.
 
static Unordered_set<Section_id, Section_id_hash> ctors_sections_in_init_array;
 
 
 
// Return whether OBJECT/SHNDX is a .ctors/.dtors section mapped to a
 
// .init_array/.fini_array section.
 
 
 
bool
 
Layout::is_ctors_in_init_array(Relobj* relobj, unsigned int shndx) const
 
{
 
  return (ctors_sections_in_init_array.find(Section_id(relobj, shndx))
 
          != ctors_sections_in_init_array.end());
 
}
 
 
// Return the output section to use for section NAME with type TYPE
// Return the output section to use for section NAME with type TYPE
// and section flags FLAGS.  NAME must be canonicalized in the string
// and section flags FLAGS.  NAME must be canonicalized in the string
// pool, and NAME_KEY is the key.  IS_INTERP is true if this is the
// pool, and NAME_KEY is the key.  ORDER is where this should appear
// .interp section.  IS_DYNAMIC_LINKER_SECTION is true if this section
// in the output sections.  IS_RELRO is true for a relro section.
// is used by the dynamic linker.  IS_RELRO is true for a relro
 
// section.  IS_LAST_RELRO is true for the last relro section.
 
// IS_FIRST_NON_RELRO is true for the first non-relro section.
 
 
 
Output_section*
Output_section*
Layout::get_output_section(const char* name, Stringpool::Key name_key,
Layout::get_output_section(const char* name, Stringpool::Key name_key,
                           elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
                           elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
                           Output_section_order order, bool is_relro)
                           Output_section_order order, bool is_relro)
{
{
 
  elfcpp::Elf_Word lookup_type = type;
 
 
 
  // For lookup purposes, treat INIT_ARRAY, FINI_ARRAY, and
 
  // PREINIT_ARRAY like PROGBITS.  This ensures that we combine
 
  // .init_array, .fini_array, and .preinit_array sections by name
 
  // whatever their type in the input file.  We do this because the
 
  // types are not always right in the input files.
 
  if (lookup_type == elfcpp::SHT_INIT_ARRAY
 
      || lookup_type == elfcpp::SHT_FINI_ARRAY
 
      || lookup_type == elfcpp::SHT_PREINIT_ARRAY)
 
    lookup_type = elfcpp::SHT_PROGBITS;
 
 
  elfcpp::Elf_Xword lookup_flags = flags;
  elfcpp::Elf_Xword lookup_flags = flags;
 
 
  // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine
  // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine
  // read-write with read-only sections.  Some other ELF linkers do
  // read-write with read-only sections.  Some other ELF linkers do
  // not do this.  FIXME: Perhaps there should be an option
  // not do this.  FIXME: Perhaps there should be an option
  // controlling this.
  // controlling this.
  lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR);
  lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR);
 
 
  const Key key(name_key, std::make_pair(type, lookup_flags));
  const Key key(name_key, std::make_pair(lookup_type, lookup_flags));
  const std::pair<Key, Output_section*> v(key, NULL);
  const std::pair<Key, Output_section*> v(key, NULL);
  std::pair<Section_name_map::iterator, bool> ins(
  std::pair<Section_name_map::iterator, bool> ins(
    this->section_name_map_.insert(v));
    this->section_name_map_.insert(v));
 
 
  if (!ins.second)
  if (!ins.second)
Line 652... Line 706...
      // with non-zero flags.  This is a workaround for cases where
      // with non-zero flags.  This is a workaround for cases where
      // assembler code forgets to set section flags.  FIXME: Perhaps
      // assembler code forgets to set section flags.  FIXME: Perhaps
      // there should be an option to control this.
      // there should be an option to control this.
      Output_section* os = NULL;
      Output_section* os = NULL;
 
 
      if (type == elfcpp::SHT_PROGBITS)
      if (lookup_type == elfcpp::SHT_PROGBITS)
        {
        {
          if (flags == 0)
          if (flags == 0)
            {
            {
              Output_section* same_name = this->find_output_section(name);
              Output_section* same_name = this->find_output_section(name);
              if (same_name != NULL
              if (same_name != NULL
                  && same_name->type() == elfcpp::SHT_PROGBITS
                  && (same_name->type() == elfcpp::SHT_PROGBITS
 
                      || same_name->type() == elfcpp::SHT_INIT_ARRAY
 
                      || same_name->type() == elfcpp::SHT_FINI_ARRAY
 
                      || same_name->type() == elfcpp::SHT_PREINIT_ARRAY)
                  && (same_name->flags() & elfcpp::SHF_TLS) == 0)
                  && (same_name->flags() & elfcpp::SHF_TLS) == 0)
                os = same_name;
                os = same_name;
            }
            }
          else if ((flags & elfcpp::SHF_TLS) == 0)
          else if ((flags & elfcpp::SHF_TLS) == 0)
            {
            {
              elfcpp::Elf_Xword zero_flags = 0;
              elfcpp::Elf_Xword zero_flags = 0;
              const Key zero_key(name_key, std::make_pair(type, zero_flags));
              const Key zero_key(name_key, std::make_pair(lookup_type,
 
                                                          zero_flags));
              Section_name_map::iterator p =
              Section_name_map::iterator p =
                  this->section_name_map_.find(zero_key);
                  this->section_name_map_.find(zero_key);
              if (p != this->section_name_map_.end())
              if (p != this->section_name_map_.end())
                os = p->second;
                os = p->second;
            }
            }
Line 685... Line 743...
 
 
// Pick the output section to use for section NAME, in input file
// Pick the output section to use for section NAME, in input file
// RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
// RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
// linker created section.  IS_INPUT_SECTION is true if we are
// linker created section.  IS_INPUT_SECTION is true if we are
// choosing an output section for an input section found in a input
// choosing an output section for an input section found in a input
// file.  IS_INTERP is true if this is the .interp section.
// file.  ORDER is where this section should appear in the output
// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
// sections.  IS_RELRO is true for a relro section.  This will return
// dynamic linker.  IS_RELRO is true for a relro section.
// NULL if the input section should be discarded.
// IS_LAST_RELRO is true for the last relro section.
 
// IS_FIRST_NON_RELRO is true for the first non-relro section.  This
 
// will return NULL if the input section should be discarded.
 
 
 
Output_section*
Output_section*
Layout::choose_output_section(const Relobj* relobj, const char* name,
Layout::choose_output_section(const Relobj* relobj, const char* name,
                              elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
                              elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
                              bool is_input_section, Output_section_order order,
                              bool is_input_section, Output_section_order order,
Line 818... Line 873...
  // Turn NAME from the name of the input section into the name of the
  // Turn NAME from the name of the input section into the name of the
  // output section.
  // output section.
  if (is_input_section
  if (is_input_section
      && !this->script_options_->saw_sections_clause()
      && !this->script_options_->saw_sections_clause()
      && !parameters->options().relocatable())
      && !parameters->options().relocatable())
    name = Layout::output_section_name(name, &len);
    name = Layout::output_section_name(relobj, name, &len);
 
 
  Stringpool::Key name_key;
  Stringpool::Key name_key;
  name = this->namepool_.add_with_length(name, len, true, &name_key);
  name = this->namepool_.add_with_length(name, len, true, &name_key);
 
 
  if (uncompressed_name != NULL)
  if (uncompressed_name != NULL)
Line 887... Line 942...
  *off = 0;
  *off = 0;
 
 
  if (!this->include_section(object, name, shdr))
  if (!this->include_section(object, name, shdr))
    return NULL;
    return NULL;
 
 
  Output_section* os;
 
 
 
  // Sometimes .init_array*, .preinit_array* and .fini_array* do not have
 
  // correct section types.  Force them here.
 
  elfcpp::Elf_Word sh_type = shdr.get_sh_type();
  elfcpp::Elf_Word sh_type = shdr.get_sh_type();
  if (sh_type == elfcpp::SHT_PROGBITS)
 
    {
 
      static const char init_array_prefix[] = ".init_array";
 
      static const char preinit_array_prefix[] = ".preinit_array";
 
      static const char fini_array_prefix[] = ".fini_array";
 
      static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1;
 
      static size_t preinit_array_prefix_size =
 
        sizeof(preinit_array_prefix) - 1;
 
      static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1;
 
 
 
      if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0)
 
        sh_type = elfcpp::SHT_INIT_ARRAY;
 
      else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size)
 
               == 0)
 
        sh_type = elfcpp::SHT_PREINIT_ARRAY;
 
      else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0)
 
        sh_type = elfcpp::SHT_FINI_ARRAY;
 
    }
 
 
 
  // In a relocatable link a grouped section must not be combined with
  // In a relocatable link a grouped section must not be combined with
  // any other sections.
  // any other sections.
 
  Output_section* os;
  if (parameters->options().relocatable()
  if (parameters->options().relocatable()
      && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
      && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
    {
    {
      name = this->namepool_.add(name, true, NULL);
      name = this->namepool_.add(name, true, NULL);
      os = this->make_output_section(name, sh_type, shdr.get_sh_flags(),
      os = this->make_output_section(name, sh_type, shdr.get_sh_flags(),
Line 930... Line 964...
      if (os == NULL)
      if (os == NULL)
        return NULL;
        return NULL;
    }
    }
 
 
  // By default the GNU linker sorts input sections whose names match
  // By default the GNU linker sorts input sections whose names match
  // .ctor.*, .dtor.*, .init_array.*, or .fini_array.*.  The sections
  // .ctors.*, .dtors.*, .init_array.*, or .fini_array.*.  The
  // are sorted by name.  This is used to implement constructor
  // sections are sorted by name.  This is used to implement
  // priority ordering.  We are compatible.
  // constructor priority ordering.  We are compatible.  When we put
 
  // .ctor sections in .init_array and .dtor sections in .fini_array,
 
  // we must also sort plain .ctor and .dtor sections.
  if (!this->script_options_->saw_sections_clause()
  if (!this->script_options_->saw_sections_clause()
 
      && !parameters->options().relocatable()
      && (is_prefix_of(".ctors.", name)
      && (is_prefix_of(".ctors.", name)
          || is_prefix_of(".dtors.", name)
          || is_prefix_of(".dtors.", name)
          || is_prefix_of(".init_array.", name)
          || is_prefix_of(".init_array.", name)
          || is_prefix_of(".fini_array.", name)))
          || is_prefix_of(".fini_array.", name)
 
          || (parameters->options().ctors_in_init_array()
 
              && (strcmp(name, ".ctors") == 0
 
                  || strcmp(name, ".dtors") == 0))))
    os->set_must_sort_attached_input_sections();
    os->set_must_sort_attached_input_sections();
 
 
 
  // If this is a .ctors or .ctors.* section being mapped to a
 
  // .init_array section, or a .dtors or .dtors.* section being mapped
 
  // to a .fini_array section, we will need to reverse the words if
 
  // there is more than one.  Record this section for later.  See
 
  // ctors_sections_in_init_array above.
 
  if (!this->script_options_->saw_sections_clause()
 
      && !parameters->options().relocatable()
 
      && shdr.get_sh_size() > size / 8
 
      && (((strcmp(name, ".ctors") == 0
 
            || is_prefix_of(".ctors.", name))
 
           && strcmp(os->name(), ".init_array") == 0)
 
          || ((strcmp(name, ".dtors") == 0
 
               || is_prefix_of(".dtors.", name))
 
              && strcmp(os->name(), ".fini_array") == 0)))
 
    ctors_sections_in_init_array.insert(Section_id(object, shndx));
 
 
  // FIXME: Handle SHF_LINK_ORDER somewhere.
  // FIXME: Handle SHF_LINK_ORDER somewhere.
 
 
  elfcpp::Elf_Xword orig_flags = os->flags();
  elfcpp::Elf_Xword orig_flags = os->flags();
 
 
  *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx,
  *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx,
Line 1093... Line 1149...
                        unsigned int shndx,
                        unsigned int shndx,
                        const elfcpp::Shdr<size, big_endian>& shdr,
                        const elfcpp::Shdr<size, big_endian>& shdr,
                        unsigned int reloc_shndx, unsigned int reloc_type,
                        unsigned int reloc_shndx, unsigned int reloc_type,
                        off_t* off)
                        off_t* off)
{
{
  gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS);
  gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS
 
              || shdr.get_sh_type() == elfcpp::SHT_X86_64_UNWIND);
  gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
  gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
 
 
  const char* const name = ".eh_frame";
  Output_section* os = this->make_eh_frame_section(object);
  Output_section* os = this->choose_output_section(object, name,
  if (os == NULL)
 
    return NULL;
 
 
 
  gold_assert(this->eh_frame_section_ == os);
 
 
 
  elfcpp::Elf_Xword orig_flags = os->flags();
 
 
 
  if (!parameters->incremental()
 
      && this->eh_frame_data_->add_ehframe_input_section(object,
 
                                                         symbols,
 
                                                         symbols_size,
 
                                                         symbol_names,
 
                                                         symbol_names_size,
 
                                                         shndx,
 
                                                         reloc_shndx,
 
                                                         reloc_type))
 
    {
 
      os->update_flags_for_input_section(shdr.get_sh_flags());
 
 
 
      // A writable .eh_frame section is a RELRO section.
 
      if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
 
          != (os->flags() & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR)))
 
        {
 
          os->set_is_relro();
 
          os->set_order(ORDER_RELRO);
 
        }
 
 
 
      // We found a .eh_frame section we are going to optimize, so now
 
      // we can add the set of optimized sections to the output
 
      // section.  We need to postpone adding this until we've found a
 
      // section we can optimize so that the .eh_frame section in
 
      // crtbegin.o winds up at the start of the output section.
 
      if (!this->added_eh_frame_data_)
 
        {
 
          os->add_output_section_data(this->eh_frame_data_);
 
          this->added_eh_frame_data_ = true;
 
        }
 
      *off = -1;
 
    }
 
  else
 
    {
 
      // We couldn't handle this .eh_frame section for some reason.
 
      // Add it as a normal section.
 
      bool saw_sections_clause = this->script_options_->saw_sections_clause();
 
      *off = os->add_input_section(this, object, shndx, ".eh_frame", shdr,
 
                                   reloc_shndx, saw_sections_clause);
 
      this->have_added_input_section_ = true;
 
 
 
      if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
 
          != (os->flags() & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR)))
 
        os->set_order(this->default_section_order(os, false));
 
    }
 
 
 
  return os;
 
}
 
 
 
// Create and return the magic .eh_frame section.  Create
 
// .eh_frame_hdr also if appropriate.  OBJECT is the object with the
 
// input .eh_frame section; it may be NULL.
 
 
 
Output_section*
 
Layout::make_eh_frame_section(const Relobj* object)
 
{
 
  // FIXME: On x86_64, this could use SHT_X86_64_UNWIND rather than
 
  // SHT_PROGBITS.
 
  Output_section* os = this->choose_output_section(object, ".eh_frame",
                                                   elfcpp::SHT_PROGBITS,
                                                   elfcpp::SHT_PROGBITS,
                                                   elfcpp::SHF_ALLOC, false,
                                                   elfcpp::SHF_ALLOC, false,
                                                   ORDER_EHFRAME, false);
                                                   ORDER_EHFRAME, false);
  if (os == NULL)
  if (os == NULL)
    return NULL;
    return NULL;
Line 1141... Line 1263...
              this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
              this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
            }
            }
        }
        }
    }
    }
 
 
  gold_assert(this->eh_frame_section_ == os);
  return os;
 
}
  if (!parameters->incremental()
 
      && this->eh_frame_data_->add_ehframe_input_section(object,
 
                                                         symbols,
 
                                                         symbols_size,
 
                                                         symbol_names,
 
                                                         symbol_names_size,
 
                                                         shndx,
 
                                                         reloc_shndx,
 
                                                         reloc_type))
 
    {
 
      os->update_flags_for_input_section(shdr.get_sh_flags());
 
 
 
      // A writable .eh_frame section is a RELRO section.
// Add an exception frame for a PLT.  This is called from target code.
      if ((shdr.get_sh_flags() & elfcpp::SHF_WRITE) != 0)
 
        os->set_is_relro();
 
 
 
      // We found a .eh_frame section we are going to optimize, so now
void
      // we can add the set of optimized sections to the output
Layout::add_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
      // section.  We need to postpone adding this until we've found a
                             size_t cie_length, const unsigned char* fde_data,
      // section we can optimize so that the .eh_frame section in
                             size_t fde_length)
      // crtbegin.o winds up at the start of the output section.
{
 
  if (parameters->incremental())
 
    {
 
      // FIXME: Maybe this could work some day....
 
      return;
 
    }
 
  Output_section* os = this->make_eh_frame_section(NULL);
 
  if (os == NULL)
 
    return;
 
  this->eh_frame_data_->add_ehframe_for_plt(plt, cie_data, cie_length,
 
                                            fde_data, fde_length);
      if (!this->added_eh_frame_data_)
      if (!this->added_eh_frame_data_)
        {
        {
          os->add_output_section_data(this->eh_frame_data_);
          os->add_output_section_data(this->eh_frame_data_);
          this->added_eh_frame_data_ = true;
          this->added_eh_frame_data_ = true;
        }
        }
      *off = -1;
 
    }
 
  else
 
    {
 
      // We couldn't handle this .eh_frame section for some reason.
 
      // Add it as a normal section.
 
      bool saw_sections_clause = this->script_options_->saw_sections_clause();
 
      *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx,
 
                                   saw_sections_clause);
 
      this->have_added_input_section_ = true;
 
    }
 
 
 
  return os;
 
}
}
 
 
// Add POSD to an output section using NAME, TYPE, and FLAGS.  Return
// Add POSD to an output section using NAME, TYPE, and FLAGS.  Return
// the output section.
// the output section.
 
 
Line 1249... Line 1355...
      if (this->debug_abbrev_)
      if (this->debug_abbrev_)
        this->debug_info_->set_abbreviations(this->debug_abbrev_);
        this->debug_info_->set_abbreviations(this->debug_abbrev_);
    }
    }
  else
  else
    {
    {
 
      // Sometimes .init_array*, .preinit_array* and .fini_array* do
 
      // not have correct section types.  Force them here.
 
      if (type == elfcpp::SHT_PROGBITS)
 
        {
 
          if (is_prefix_of(".init_array", name))
 
            type = elfcpp::SHT_INIT_ARRAY;
 
          else if (is_prefix_of(".preinit_array", name))
 
            type = elfcpp::SHT_PREINIT_ARRAY;
 
          else if (is_prefix_of(".fini_array", name))
 
            type = elfcpp::SHT_FINI_ARRAY;
 
        }
 
 
      // FIXME: const_cast is ugly.
      // FIXME: const_cast is ugly.
      Target* target = const_cast<Target*>(&parameters->target());
      Target* target = const_cast<Target*>(&parameters->target());
      os = target->make_output_section(name, type, flags);
      os = target->make_output_section(name, type, flags);
    }
    }
 
 
Line 1296... Line 1414...
 
 
  // The GNU linker by default sorts some sections by priority, so we
  // The GNU linker by default sorts some sections by priority, so we
  // do the same.  We need to know that this might happen before we
  // do the same.  We need to know that this might happen before we
  // attach any input sections.
  // attach any input sections.
  if (!this->script_options_->saw_sections_clause()
  if (!this->script_options_->saw_sections_clause()
 
      && !parameters->options().relocatable()
 
      && (strcmp(name, ".init_array") == 0
 
          || strcmp(name, ".fini_array") == 0
 
          || (!parameters->options().ctors_in_init_array()
      && (strcmp(name, ".ctors") == 0
      && (strcmp(name, ".ctors") == 0
          || strcmp(name, ".dtors") == 0
                  || strcmp(name, ".dtors") == 0))))
          || strcmp(name, ".init_array") == 0
 
          || strcmp(name, ".fini_array") == 0))
 
    os->set_may_sort_attached_input_sections();
    os->set_may_sort_attached_input_sections();
 
 
  // Check for .stab*str sections, as .stab* sections need to link to
  // Check for .stab*str sections, as .stab* sections need to link to
  // them.
  // them.
  if (type == elfcpp::SHT_STRTAB
  if (type == elfcpp::SHT_STRTAB
      && !this->have_stabstr_section_
      && !this->have_stabstr_section_
      && strncmp(name, ".stab", 5) == 0
      && strncmp(name, ".stab", 5) == 0
      && strcmp(name + strlen(name) - 3, "str") == 0)
      && strcmp(name + strlen(name) - 3, "str") == 0)
    this->have_stabstr_section_ = true;
    this->have_stabstr_section_ = true;
 
 
 
  // During a full incremental link, we add patch space to most
 
  // PROGBITS and NOBITS sections.  Flag those that may be
 
  // arbitrarily padded.
 
  if ((type == elfcpp::SHT_PROGBITS || type == elfcpp::SHT_NOBITS)
 
      && order != ORDER_INTERP
 
      && order != ORDER_INIT
 
      && order != ORDER_PLT
 
      && order != ORDER_FINI
 
      && order != ORDER_RELRO_LAST
 
      && order != ORDER_NON_RELRO_FIRST
 
      && strcmp(name, ".ctors") != 0
 
      && strcmp(name, ".dtors") != 0
 
      && strcmp(name, ".jcr") != 0)
 
    {
 
      os->set_is_patch_space_allowed();
 
 
 
      // Certain sections require "holes" to be filled with
 
      // specific fill patterns.  These fill patterns may have
 
      // a minimum size, so we must prevent allocations from the
 
      // free list that leave a hole smaller than the minimum.
 
      if (strcmp(name, ".debug_info") == 0)
 
        os->set_free_space_fill(new Output_fill_debug_info(false));
 
      else if (strcmp(name, ".debug_types") == 0)
 
        os->set_free_space_fill(new Output_fill_debug_info(true));
 
      else if (strcmp(name, ".debug_line") == 0)
 
        os->set_free_space_fill(new Output_fill_debug_line());
 
    }
 
 
  // If we have already attached the sections to segments, then we
  // If we have already attached the sections to segments, then we
  // need to attach this one now.  This happens for sections created
  // need to attach this one now.  This happens for sections created
  // directly by the linker.
  // directly by the linker.
  if (this->sections_are_attached_)
  if (this->sections_are_attached_)
    this->attach_section_to_segment(os);
    this->attach_section_to_segment(os);
Line 1539... Line 1687...
      gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
      gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
      if (this->relro_segment_ == NULL)
      if (this->relro_segment_ == NULL)
        this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
        this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
      this->relro_segment_->add_output_section_to_nonload(os, seg_flags);
      this->relro_segment_->add_output_section_to_nonload(os, seg_flags);
    }
    }
 
 
 
  // If we see a section named .interp, put it into a PT_INTERP
 
  // segment.  This seems broken to me, but this is what GNU ld does,
 
  // and glibc expects it.
 
  if (strcmp(os->name(), ".interp") == 0
 
      && !this->script_options_->saw_phdrs_clause())
 
    {
 
      if (this->interp_segment_ == NULL)
 
        this->make_output_segment(elfcpp::PT_INTERP, seg_flags);
 
      else
 
        gold_warning(_("multiple '.interp' sections in input files "
 
                       "may cause confusing PT_INTERP segment"));
 
      this->interp_segment_->add_output_section_to_nonload(os, seg_flags);
 
    }
}
}
 
 
// Make an output section for a script.
// Make an output section for a script.
 
 
Output_section*
Output_section*
Line 1643... Line 1805...
                                                       (elfcpp::SHF_ALLOC
                                                       (elfcpp::SHF_ALLOC
                                                        | elfcpp::SHF_WRITE),
                                                        | elfcpp::SHF_WRITE),
                                                       false, ORDER_RELRO,
                                                       false, ORDER_RELRO,
                                                       true);
                                                       true);
 
 
 
  // A linker script may discard .dynamic, so check for NULL.
 
  if (this->dynamic_section_ != NULL)
 
    {
  this->dynamic_symbol_ =
  this->dynamic_symbol_ =
    symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED,
        symtab->define_in_output_data("_DYNAMIC", NULL,
 
                                      Symbol_table::PREDEFINED,
                                  this->dynamic_section_, 0, 0,
                                  this->dynamic_section_, 0, 0,
                                  elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
                                  elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
                                  elfcpp::STV_HIDDEN, 0, false, false);
                                  elfcpp::STV_HIDDEN, 0, false, false);
 
 
  this->dynamic_data_ =  new Output_data_dynamic(&this->dynpool_);
  this->dynamic_data_ =  new Output_data_dynamic(&this->dynpool_);
 
 
  this->dynamic_section_->add_output_section_data(this->dynamic_data_);
  this->dynamic_section_->add_output_section_data(this->dynamic_data_);
}
}
 
}
 
 
// For each output section whose name can be represented as C symbol,
// For each output section whose name can be represented as C symbol,
// define __start and __stop symbols for the section.  This is a GNU
// define __start and __stop symbols for the section.  This is a GNU
// extension.
// extension.
 
 
Line 1944... Line 2111...
    load_seg = NULL;
    load_seg = NULL;
 
 
  // If the user set the address of the text segment, that may not be
  // If the user set the address of the text segment, that may not be
  // compatible with putting the segment headers and file headers into
  // compatible with putting the segment headers and file headers into
  // that segment.
  // that segment.
  if (parameters->options().user_set_Ttext())
  if (parameters->options().user_set_Ttext()
 
      && parameters->options().Ttext() % target->common_pagesize() != 0)
 
    {
    load_seg = NULL;
    load_seg = NULL;
 
      phdr_seg = NULL;
 
    }
 
 
  gold_assert(phdr_seg == NULL
  gold_assert(phdr_seg == NULL
              || load_seg != NULL
              || load_seg != NULL
              || this->script_options_->saw_sections_clause());
              || this->script_options_->saw_sections_clause());
 
 
Line 2061... Line 2232...
    }
    }
  return 0;
  return 0;
}
}
 
 
// Read the sequence of input sections from the file specified with
// Read the sequence of input sections from the file specified with
// --section-ordering-file.
// option --section-ordering-file.
 
 
void
void
Layout::read_layout_from_file()
Layout::read_layout_from_file()
{
{
  const char* filename = parameters->options().section_ordering_file();
  const char* filename = parameters->options().section_ordering_file();
Line 2077... Line 2248...
    gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
    gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
               filename, strerror(errno));
               filename, strerror(errno));
 
 
  std::getline(in, line);   // this chops off the trailing \n, if any
  std::getline(in, line);   // this chops off the trailing \n, if any
  unsigned int position = 1;
  unsigned int position = 1;
 
  this->set_section_ordering_specified();
 
 
  while (in)
  while (in)
    {
    {
      if (!line.empty() && line[line.length() - 1] == '\r')   // Windows
      if (!line.empty() && line[line.length() - 1] == '\r')   // Windows
        line.resize(line.length() - 1);
        line.resize(line.length() - 1);
Line 2161... Line 2333...
      this->create_dynamic_symtab(input_objects, symtab, &dynstr,
      this->create_dynamic_symtab(input_objects, symtab, &dynstr,
                                  &local_dynamic_count, &dynamic_symbols,
                                  &local_dynamic_count, &dynamic_symbols,
                                  &versions);
                                  &versions);
 
 
      // Create the .interp section to hold the name of the
      // Create the .interp section to hold the name of the
      // interpreter, and put it in a PT_INTERP segment.
      // interpreter, and put it in a PT_INTERP segment.  Don't do it
      if (!parameters->options().shared())
      // if we saw a .interp section in an input file.
 
      if ((!parameters->options().shared()
 
           || parameters->options().dynamic_linker() != NULL)
 
          && this->interp_segment_ == NULL)
        this->create_interp(target);
        this->create_interp(target);
 
 
      // Finish the .dynamic section to hold the dynamic data, and put
      // Finish the .dynamic section to hold the dynamic data, and put
      // it in a PT_DYNAMIC segment.
      // it in a PT_DYNAMIC segment.
      this->finish_dynamic_section(input_objects, symtab);
      this->finish_dynamic_section(input_objects, symtab);
Line 2671... Line 2846...
  incremental_got_plt_os->set_link_section(incremental_inputs_os);
  incremental_got_plt_os->set_link_section(incremental_inputs_os);
}
}
 
 
// Return whether SEG1 should be before SEG2 in the output file.  This
// Return whether SEG1 should be before SEG2 in the output file.  This
// is based entirely on the segment type and flags.  When this is
// is based entirely on the segment type and flags.  When this is
// called the segment addresses has normally not yet been set.
// called the segment addresses have normally not yet been set.
 
 
bool
bool
Layout::segment_precedes(const Output_segment* seg1,
Layout::segment_precedes(const Output_segment* seg1,
                         const Output_segment* seg2)
                         const Output_segment* seg2)
{
{
Line 2797... Line 2972...
    return (flags1 & elfcpp::PF_X) != 0;
    return (flags1 & elfcpp::PF_X) != 0;
  if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
  if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
    return (flags1 & elfcpp::PF_R) == 0;
    return (flags1 & elfcpp::PF_R) == 0;
 
 
  // We shouldn't get here--we shouldn't create segments which we
  // We shouldn't get here--we shouldn't create segments which we
  // can't distinguish.
  // can't distinguish.  Unless of course we are using a weird linker
  gold_unreachable();
  // script.
 
  gold_assert(this->script_options_->saw_phdrs_clause());
 
  return false;
}
}
 
 
// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE.
// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE.
 
 
static off_t
static off_t
Line 2822... Line 2999...
 
 
off_t
off_t
Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
                            unsigned int* pshndx)
                            unsigned int* pshndx)
{
{
  // Sort them into the final order.
  // Sort them into the final order.  We use a stable sort so that we
  std::sort(this->segment_list_.begin(), this->segment_list_.end(),
  // don't randomize the order of indistinguishable segments created
            Layout::Compare_segments());
  // by linker scripts.
 
  std::stable_sort(this->segment_list_.begin(), this->segment_list_.end(),
 
                   Layout::Compare_segments(this));
 
 
  // Find the PT_LOAD segments, and set their addresses and offsets
  // Find the PT_LOAD segments, and set their addresses and offsets
  // and their section's addresses and offsets.
  // and their section's addresses and offsets.
  uint64_t addr;
  uint64_t addr;
  if (parameters->options().user_set_Ttext())
  if (parameters->options().user_set_Ttext())
Line 2876... Line 3055...
            {
            {
              // When it comes to setting file offsets, we care about
              // When it comes to setting file offsets, we care about
              // the physical address.
              // the physical address.
              addr = (*p)->paddr();
              addr = (*p)->paddr();
            }
            }
 
          else if (parameters->options().user_set_Ttext()
 
                   && ((*p)->flags() & elfcpp::PF_W) == 0)
 
            {
 
              are_addresses_set = true;
 
            }
          else if (parameters->options().user_set_Tdata()
          else if (parameters->options().user_set_Tdata()
                   && ((*p)->flags() & elfcpp::PF_W) != 0
                   && ((*p)->flags() & elfcpp::PF_W) != 0
                   && (!parameters->options().user_set_Tbss()
                   && (!parameters->options().user_set_Tbss()
                       || (*p)->has_any_data_sections()))
                       || (*p)->has_any_data_sections()))
            {
            {
Line 3558... Line 3742...
                                                       elfcpp::SHF_ALLOC,
                                                       elfcpp::SHF_ALLOC,
                                                       false,
                                                       false,
                                                       ORDER_DYNAMIC_LINKER,
                                                       ORDER_DYNAMIC_LINKER,
                                                       false);
                                                       false);
 
 
 
  // Check for NULL as a linker script may discard .dynsym.
 
  if (dynsym != NULL)
 
    {
  Output_section_data* odata = new Output_data_fixed_space(index * symsize,
  Output_section_data* odata = new Output_data_fixed_space(index * symsize,
                                                           align,
                                                           align,
                                                           "** dynsym");
                                                           "** dynsym");
  dynsym->add_output_section_data(odata);
  dynsym->add_output_section_data(odata);
 
 
  dynsym->set_info(local_symcount);
  dynsym->set_info(local_symcount);
  dynsym->set_entsize(symsize);
  dynsym->set_entsize(symsize);
  dynsym->set_addralign(align);
  dynsym->set_addralign(align);
 
 
  this->dynsym_section_ = dynsym;
  this->dynsym_section_ = dynsym;
 
    }
 
 
  Output_data_dynamic* const odyn = this->dynamic_data_;
  Output_data_dynamic* const odyn = this->dynamic_data_;
 
  if (odyn != NULL)
 
    {
  odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
  odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
  odyn->add_constant(elfcpp::DT_SYMENT, symsize);
  odyn->add_constant(elfcpp::DT_SYMENT, symsize);
 
    }
 
 
  // If there are more than SHN_LORESERVE allocated sections, we
  // If there are more than SHN_LORESERVE allocated sections, we
  // create a .dynsym_shndx section.  It is possible that we don't
  // create a .dynsym_shndx section.  It is possible that we don't
  // need one, because it is possible that there are no dynamic
  // need one, because it is possible that there are no dynamic
  // symbols in any of the sections with indexes larger than
  // symbols in any of the sections with indexes larger than
Line 3588... Line 3779...
        this->choose_output_section(NULL, ".dynsym_shndx",
        this->choose_output_section(NULL, ".dynsym_shndx",
                                    elfcpp::SHT_SYMTAB_SHNDX,
                                    elfcpp::SHT_SYMTAB_SHNDX,
                                    elfcpp::SHF_ALLOC,
                                    elfcpp::SHF_ALLOC,
                                    false, ORDER_DYNAMIC_LINKER, false);
                                    false, ORDER_DYNAMIC_LINKER, false);
 
 
 
      if (dynsym_xindex != NULL)
 
        {
      this->dynsym_xindex_ = new Output_symtab_xindex(index);
      this->dynsym_xindex_ = new Output_symtab_xindex(index);
 
 
      dynsym_xindex->add_output_section_data(this->dynsym_xindex_);
      dynsym_xindex->add_output_section_data(this->dynsym_xindex_);
 
 
      dynsym_xindex->set_link_section(dynsym);
      dynsym_xindex->set_link_section(dynsym);
      dynsym_xindex->set_addralign(4);
      dynsym_xindex->set_addralign(4);
      dynsym_xindex->set_entsize(4);
      dynsym_xindex->set_entsize(4);
 
 
      dynsym_xindex->set_after_input_sections();
      dynsym_xindex->set_after_input_sections();
 
 
      // This tells the driver code to wait until the symbol table has
          // This tells the driver code to wait until the symbol table
      // written out before writing out the postprocessing sections,
          // has written out before writing out the postprocessing
      // including the .dynsym_shndx section.
          // sections, including the .dynsym_shndx section.
      this->any_postprocessing_sections_ = true;
      this->any_postprocessing_sections_ = true;
    }
    }
 
    }
 
 
  // Create the dynamic string table section.
  // Create the dynamic string table section.
 
 
  Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
  Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
                                                       elfcpp::SHT_STRTAB,
                                                       elfcpp::SHT_STRTAB,
                                                       elfcpp::SHF_ALLOC,
                                                       elfcpp::SHF_ALLOC,
                                                       false,
                                                       false,
                                                       ORDER_DYNAMIC_LINKER,
                                                       ORDER_DYNAMIC_LINKER,
                                                       false);
                                                       false);
 
 
 
  if (dynstr != NULL)
 
    {
  Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
  Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
  dynstr->add_output_section_data(strdata);
  dynstr->add_output_section_data(strdata);
 
 
 
      if (dynsym != NULL)
  dynsym->set_link_section(dynstr);
  dynsym->set_link_section(dynstr);
 
      if (this->dynamic_section_ != NULL)
  this->dynamic_section_->set_link_section(dynstr);
  this->dynamic_section_->set_link_section(dynstr);
 
 
 
      if (odyn != NULL)
 
        {
  odyn->add_section_address(elfcpp::DT_STRTAB, dynstr);
  odyn->add_section_address(elfcpp::DT_STRTAB, dynstr);
  odyn->add_section_size(elfcpp::DT_STRSZ, dynstr);
  odyn->add_section_size(elfcpp::DT_STRSZ, dynstr);
 
        }
 
 
  *pdynstr = dynstr;
  *pdynstr = dynstr;
 
    }
 
 
  // Create the hash tables.
  // Create the hash tables.
 
 
  if (strcmp(parameters->options().hash_style(), "sysv") == 0
  if (strcmp(parameters->options().hash_style(), "sysv") == 0
      || strcmp(parameters->options().hash_style(), "both") == 0)
      || strcmp(parameters->options().hash_style(), "both") == 0)
Line 3643... Line 3845...
 
 
      Output_section_data* hashdata = new Output_data_const_buffer(phash,
      Output_section_data* hashdata = new Output_data_const_buffer(phash,
                                                                   hashlen,
                                                                   hashlen,
                                                                   align,
                                                                   align,
                                                                   "** hash");
                                                                   "** hash");
 
      if (hashsec != NULL && hashdata != NULL)
      hashsec->add_output_section_data(hashdata);
      hashsec->add_output_section_data(hashdata);
 
 
 
      if (hashsec != NULL)
 
        {
 
          if (dynsym != NULL)
      hashsec->set_link_section(dynsym);
      hashsec->set_link_section(dynsym);
      hashsec->set_entsize(4);
      hashsec->set_entsize(4);
 
        }
 
 
 
      if (odyn != NULL)
      odyn->add_section_address(elfcpp::DT_HASH, hashsec);
      odyn->add_section_address(elfcpp::DT_HASH, hashsec);
    }
    }
 
 
  if (strcmp(parameters->options().hash_style(), "gnu") == 0
  if (strcmp(parameters->options().hash_style(), "gnu") == 0
      || strcmp(parameters->options().hash_style(), "both") == 0)
      || strcmp(parameters->options().hash_style(), "both") == 0)
Line 3668... Line 3876...
 
 
      Output_section_data* hashdata = new Output_data_const_buffer(phash,
      Output_section_data* hashdata = new Output_data_const_buffer(phash,
                                                                   hashlen,
                                                                   hashlen,
                                                                   align,
                                                                   align,
                                                                   "** hash");
                                                                   "** hash");
 
      if (hashsec != NULL && hashdata != NULL)
      hashsec->add_output_section_data(hashdata);
      hashsec->add_output_section_data(hashdata);
 
 
 
      if (hashsec != NULL)
 
        {
 
          if (dynsym != NULL)
      hashsec->set_link_section(dynsym);
      hashsec->set_link_section(dynsym);
 
 
      // For a 64-bit target, the entries in .gnu.hash do not have a
          // For a 64-bit target, the entries in .gnu.hash do not have
      // uniform size, so we only set the entry size for a 32-bit
          // a uniform size, so we only set the entry size for a
      // target.
          // 32-bit target.
      if (parameters->target().get_size() == 32)
      if (parameters->target().get_size() == 32)
        hashsec->set_entsize(4);
        hashsec->set_entsize(4);
 
 
 
          if (odyn != NULL)
      odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec);
      odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec);
    }
    }
}
}
 
}
 
 
// Assign offsets to each local portion of the dynamic symbol table.
// Assign offsets to each local portion of the dynamic symbol table.
 
 
void
void
Layout::assign_local_dynsym_offsets(const Input_objects* input_objects)
Layout::assign_local_dynsym_offsets(const Input_objects* input_objects)
{
{
  Output_section* dynsym = this->dynsym_section_;
  Output_section* dynsym = this->dynsym_section_;
  gold_assert(dynsym != NULL);
  if (dynsym == NULL)
 
    return;
 
 
  off_t off = dynsym->offset();
  off_t off = dynsym->offset();
 
 
  // Skip the dummy symbol at the start of the section.
  // Skip the dummy symbol at the start of the section.
  off += dynsym->entsize();
  off += dynsym->entsize();
Line 3769... Line 3984...
                                                     elfcpp::SHF_ALLOC,
                                                     elfcpp::SHF_ALLOC,
                                                     false,
                                                     false,
                                                     ORDER_DYNAMIC_LINKER,
                                                     ORDER_DYNAMIC_LINKER,
                                                     false);
                                                     false);
 
 
 
  // Check for NULL since a linker script may discard this section.
 
  if (vsec != NULL)
 
    {
  unsigned char* vbuf;
  unsigned char* vbuf;
  unsigned int vsize;
  unsigned int vsize;
  versions->symbol_section_contents<size, big_endian>(symtab, &this->dynpool_,
      versions->symbol_section_contents<size, big_endian>(symtab,
 
                                                          &this->dynpool_,
                                                      local_symcount,
                                                      local_symcount,
                                                      dynamic_symbols,
                                                      dynamic_symbols,
                                                      &vbuf, &vsize);
                                                      &vbuf, &vsize);
 
 
  Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2,
  Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2,
                                                            "** versions");
                                                            "** versions");
 
 
  vsec->add_output_section_data(vdata);
  vsec->add_output_section_data(vdata);
  vsec->set_entsize(2);
  vsec->set_entsize(2);
  vsec->set_link_section(this->dynsym_section_);
  vsec->set_link_section(this->dynsym_section_);
 
    }
 
 
  Output_data_dynamic* const odyn = this->dynamic_data_;
  Output_data_dynamic* const odyn = this->dynamic_data_;
 
  if (odyn != NULL && vsec != NULL)
  odyn->add_section_address(elfcpp::DT_VERSYM, vsec);
  odyn->add_section_address(elfcpp::DT_VERSYM, vsec);
 
 
  if (versions->any_defs())
  if (versions->any_defs())
    {
    {
      Output_section* vdsec;
      Output_section* vdsec;
      vdsec= this->choose_output_section(NULL, ".gnu.version_d",
      vdsec= this->choose_output_section(NULL, ".gnu.version_d",
                                         elfcpp::SHT_GNU_verdef,
                                         elfcpp::SHT_GNU_verdef,
                                         elfcpp::SHF_ALLOC,
                                         elfcpp::SHF_ALLOC,
                                         false, ORDER_DYNAMIC_LINKER, false);
                                         false, ORDER_DYNAMIC_LINKER, false);
 
 
 
      if (vdsec != NULL)
 
        {
      unsigned char* vdbuf;
      unsigned char* vdbuf;
      unsigned int vdsize;
      unsigned int vdsize;
      unsigned int vdentries;
      unsigned int vdentries;
      versions->def_section_contents<size, big_endian>(&this->dynpool_, &vdbuf,
          versions->def_section_contents<size, big_endian>(&this->dynpool_,
                                                       &vdsize, &vdentries);
                                                           &vdbuf, &vdsize,
 
                                                           &vdentries);
 
 
      Output_section_data* vddata =
      Output_section_data* vddata =
        new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs");
        new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs");
 
 
      vdsec->add_output_section_data(vddata);
      vdsec->add_output_section_data(vddata);
      vdsec->set_link_section(dynstr);
      vdsec->set_link_section(dynstr);
      vdsec->set_info(vdentries);
      vdsec->set_info(vdentries);
 
 
 
          if (odyn != NULL)
 
            {
      odyn->add_section_address(elfcpp::DT_VERDEF, vdsec);
      odyn->add_section_address(elfcpp::DT_VERDEF, vdsec);
      odyn->add_constant(elfcpp::DT_VERDEFNUM, vdentries);
      odyn->add_constant(elfcpp::DT_VERDEFNUM, vdentries);
    }
    }
 
        }
 
    }
 
 
  if (versions->any_needs())
  if (versions->any_needs())
    {
    {
      Output_section* vnsec;
      Output_section* vnsec;
      vnsec = this->choose_output_section(NULL, ".gnu.version_r",
      vnsec = this->choose_output_section(NULL, ".gnu.version_r",
                                          elfcpp::SHT_GNU_verneed,
                                          elfcpp::SHT_GNU_verneed,
                                          elfcpp::SHF_ALLOC,
                                          elfcpp::SHF_ALLOC,
                                          false, ORDER_DYNAMIC_LINKER, false);
                                          false, ORDER_DYNAMIC_LINKER, false);
 
 
 
      if (vnsec != NULL)
 
        {
      unsigned char* vnbuf;
      unsigned char* vnbuf;
      unsigned int vnsize;
      unsigned int vnsize;
      unsigned int vnentries;
      unsigned int vnentries;
      versions->need_section_contents<size, big_endian>(&this->dynpool_,
      versions->need_section_contents<size, big_endian>(&this->dynpool_,
                                                        &vnbuf, &vnsize,
                                                        &vnbuf, &vnsize,
Line 3833... Line 4063...
 
 
      vnsec->add_output_section_data(vndata);
      vnsec->add_output_section_data(vndata);
      vnsec->set_link_section(dynstr);
      vnsec->set_link_section(dynstr);
      vnsec->set_info(vnentries);
      vnsec->set_info(vnentries);
 
 
 
          if (odyn != NULL)
 
            {
      odyn->add_section_address(elfcpp::DT_VERNEED, vnsec);
      odyn->add_section_address(elfcpp::DT_VERNEED, vnsec);
      odyn->add_constant(elfcpp::DT_VERNEEDNUM, vnentries);
      odyn->add_constant(elfcpp::DT_VERNEEDNUM, vnentries);
    }
    }
}
}
 
    }
 
}
 
 
// Create the .interp section and PT_INTERP segment.
// Create the .interp section and PT_INTERP segment.
 
 
void
void
Layout::create_interp(const Target* target)
Layout::create_interp(const Target* target)
{
{
 
  gold_assert(this->interp_segment_ == NULL);
 
 
  const char* interp = parameters->options().dynamic_linker();
  const char* interp = parameters->options().dynamic_linker();
  if (interp == NULL)
  if (interp == NULL)
    {
    {
      interp = target->dynamic_linker();
      interp = target->dynamic_linker();
      gold_assert(interp != NULL);
      gold_assert(interp != NULL);
Line 3859... Line 4095...
  Output_section* osec = this->choose_output_section(NULL, ".interp",
  Output_section* osec = this->choose_output_section(NULL, ".interp",
                                                     elfcpp::SHT_PROGBITS,
                                                     elfcpp::SHT_PROGBITS,
                                                     elfcpp::SHF_ALLOC,
                                                     elfcpp::SHF_ALLOC,
                                                     false, ORDER_INTERP,
                                                     false, ORDER_INTERP,
                                                     false);
                                                     false);
 
  if (osec != NULL)
  osec->add_output_section_data(odata);
  osec->add_output_section_data(odata);
 
 
  if (!this->script_options_->saw_phdrs_clause())
 
    {
 
      Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
 
                                                       elfcpp::PF_R);
 
      oseg->add_output_section_to_nonload(osec, elfcpp::PF_R);
 
    }
 
}
}
 
 
// Add dynamic tags for the PLT and the dynamic relocs.  This is
// Add dynamic tags for the PLT and the dynamic relocs.  This is
// called by the target-specific code.  This does nothing if not doing
// called by the target-specific code.  This does nothing if not doing
// a dynamic link.
// a dynamic link.
Line 3882... Line 4112...
// If PLT_REL is not NULL, it is used for DT_PLTRELSZ, and DT_JMPREL,
// If PLT_REL is not NULL, it is used for DT_PLTRELSZ, and DT_JMPREL,
// and we also set DT_PLTREL.  We use PLT_REL's output section, since
// and we also set DT_PLTREL.  We use PLT_REL's output section, since
// some targets have multiple reloc sections in PLT_REL.
// some targets have multiple reloc sections in PLT_REL.
 
 
// If DYN_REL is not NULL, it is used for DT_REL/DT_RELA,
// If DYN_REL is not NULL, it is used for DT_REL/DT_RELA,
// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT.
// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT.  Again we use the output
 
// section.
 
 
// If ADD_DEBUG is true, we add a DT_DEBUG entry when generating an
// If ADD_DEBUG is true, we add a DT_DEBUG entry when generating an
// executable.
// executable.
 
 
void
void
Line 3911... Line 4142...
    }
    }
 
 
  if (dyn_rel != NULL && dyn_rel->output_section() != NULL)
  if (dyn_rel != NULL && dyn_rel->output_section() != NULL)
    {
    {
      odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA,
      odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA,
                                dyn_rel);
                                dyn_rel->output_section());
      if (plt_rel != NULL && dynrel_includes_plt)
      if (plt_rel != NULL
 
          && plt_rel->output_section() != NULL
 
          && dynrel_includes_plt)
        odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
        odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
                               dyn_rel, plt_rel);
                               dyn_rel->output_section(),
 
                               plt_rel->output_section());
      else
      else
        odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
        odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
                               dyn_rel);
                               dyn_rel->output_section());
      const int size = parameters->target().get_size();
      const int size = parameters->target().get_size();
      elfcpp::DT rel_tag;
      elfcpp::DT rel_tag;
      int rel_size;
      int rel_size;
      if (use_rel)
      if (use_rel)
        {
        {
Line 3968... Line 4202...
 
 
void
void
Layout::finish_dynamic_section(const Input_objects* input_objects,
Layout::finish_dynamic_section(const Input_objects* input_objects,
                               const Symbol_table* symtab)
                               const Symbol_table* symtab)
{
{
  if (!this->script_options_->saw_phdrs_clause())
  if (!this->script_options_->saw_phdrs_clause()
 
      && this->dynamic_section_ != NULL)
    {
    {
      Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
      Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
                                                       (elfcpp::PF_R
                                                       (elfcpp::PF_R
                                                        | elfcpp::PF_W));
                                                        | elfcpp::PF_W));
      oseg->add_output_section_to_nonload(this->dynamic_section_,
      oseg->add_output_section_to_nonload(this->dynamic_section_,
                                          elfcpp::PF_R | elfcpp::PF_W);
                                          elfcpp::PF_R | elfcpp::PF_W);
    }
    }
 
 
  Output_data_dynamic* const odyn = this->dynamic_data_;
  Output_data_dynamic* const odyn = this->dynamic_data_;
 
  if (odyn == NULL)
 
    return;
 
 
  for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
  for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
       p != input_objects->dynobj_end();
       p != input_objects->dynobj_end();
       ++p)
       ++p)
    {
    {
Line 4070... Line 4307...
    {
    {
      for (Segment_list::const_iterator p = this->segment_list_.begin();
      for (Segment_list::const_iterator p = this->segment_list_.begin();
           p != this->segment_list_.end();
           p != this->segment_list_.end();
           ++p)
           ++p)
        {
        {
          if (((*p)->flags() & elfcpp::PF_W) == 0
          if ((*p)->type() == elfcpp::PT_LOAD
 
              && ((*p)->flags() & elfcpp::PF_W) == 0
              && (*p)->has_dynamic_reloc())
              && (*p)->has_dynamic_reloc())
            {
            {
              have_textrel = true;
              have_textrel = true;
              break;
              break;
            }
            }
Line 4090... Line 4328...
           p != this->section_list_.end();
           p != this->section_list_.end();
           ++p)
           ++p)
        {
        {
          if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
          if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
              && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
              && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
              && ((*p)->has_dynamic_reloc()))
              && (*p)->has_dynamic_reloc())
            {
            {
              have_textrel = true;
              have_textrel = true;
              break;
              break;
            }
            }
        }
        }
    }
    }
 
 
  // Add a DT_FLAGS entry. We add it even if no flags are set so that
  if (parameters->options().filter() != NULL)
  // post-link tools can easily modify these flags if desired.
    odyn->add_string(elfcpp::DT_FILTER, parameters->options().filter());
 
  if (parameters->options().any_auxiliary())
 
    {
 
      for (options::String_set::const_iterator p =
 
             parameters->options().auxiliary_begin();
 
           p != parameters->options().auxiliary_end();
 
           ++p)
 
        odyn->add_string(elfcpp::DT_AUXILIARY, *p);
 
    }
 
 
 
  // Add a DT_FLAGS entry if necessary.
  unsigned int flags = 0;
  unsigned int flags = 0;
  if (have_textrel)
  if (have_textrel)
    {
    {
      // Add a DT_TEXTREL for compatibility with older loaders.
      // Add a DT_TEXTREL for compatibility with older loaders.
      odyn->add_constant(elfcpp::DT_TEXTREL, 0);
      odyn->add_constant(elfcpp::DT_TEXTREL, 0);
Line 4125... Line 4373...
      // Add DT_SYMBOLIC for compatibility with older loaders.
      // Add DT_SYMBOLIC for compatibility with older loaders.
      odyn->add_constant(elfcpp::DT_SYMBOLIC, 0);
      odyn->add_constant(elfcpp::DT_SYMBOLIC, 0);
    }
    }
  if (parameters->options().now())
  if (parameters->options().now())
    flags |= elfcpp::DF_BIND_NOW;
    flags |= elfcpp::DF_BIND_NOW;
 
  if (flags != 0)
  odyn->add_constant(elfcpp::DT_FLAGS, flags);
  odyn->add_constant(elfcpp::DT_FLAGS, flags);
 
 
  flags = 0;
  flags = 0;
  if (parameters->options().initfirst())
  if (parameters->options().initfirst())
    flags |= elfcpp::DF_1_INITFIRST;
    flags |= elfcpp::DF_1_INITFIRST;
Line 4150... Line 4399...
               | elfcpp::DF_1_NOOPEN);
               | elfcpp::DF_1_NOOPEN);
  if (parameters->options().origin())
  if (parameters->options().origin())
    flags |= elfcpp::DF_1_ORIGIN;
    flags |= elfcpp::DF_1_ORIGIN;
  if (parameters->options().now())
  if (parameters->options().now())
    flags |= elfcpp::DF_1_NOW;
    flags |= elfcpp::DF_1_NOW;
  if (flags)
  if (parameters->options().Bgroup())
 
    flags |= elfcpp::DF_1_GROUP;
 
  if (flags != 0)
    odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
    odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
}
}
 
 
// Set the size of the _DYNAMIC symbol table to be the size of the
// Set the size of the _DYNAMIC symbol table to be the size of the
// dynamic data.
// dynamic data.
 
 
void
void
Layout::set_dynamic_symbol_size(const Symbol_table* symtab)
Layout::set_dynamic_symbol_size(const Symbol_table* symtab)
{
{
  Output_data_dynamic* const odyn = this->dynamic_data_;
  Output_data_dynamic* const odyn = this->dynamic_data_;
 
  if (odyn == NULL)
 
    return;
  odyn->finalize_data_size();
  odyn->finalize_data_size();
 
  if (this->dynamic_symbol_ == NULL)
 
    return;
  off_t data_size = odyn->data_size();
  off_t data_size = odyn->data_size();
  const int size = parameters->target().get_size();
  const int size = parameters->target().get_size();
  if (size == 32)
  if (size == 32)
    symtab->get_sized_symbol<32>(this->dynamic_symbol_)->set_symsize(data_size);
    symtab->get_sized_symbol<32>(this->dynamic_symbol_)->set_symsize(data_size);
  else if (size == 64)
  else if (size == 64)
Line 4181... Line 4436...
 
 
#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
const Layout::Section_name_mapping Layout::section_name_mapping[] =
const Layout::Section_name_mapping Layout::section_name_mapping[] =
{
{
  MAPPING_INIT(".text.", ".text"),
  MAPPING_INIT(".text.", ".text"),
  MAPPING_INIT(".ctors.", ".ctors"),
 
  MAPPING_INIT(".dtors.", ".dtors"),
 
  MAPPING_INIT(".rodata.", ".rodata"),
  MAPPING_INIT(".rodata.", ".rodata"),
  MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"),
  MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"),
  MAPPING_INIT(".data.rel.ro", ".data.rel.ro"),
  MAPPING_INIT(".data.rel.ro", ".data.rel.ro"),
  MAPPING_INIT(".data.", ".data"),
  MAPPING_INIT(".data.", ".data"),
  MAPPING_INIT(".bss.", ".bss"),
  MAPPING_INIT(".bss.", ".bss"),
Line 4234... Line 4487...
// Choose the output section name to use given an input section name.
// Choose the output section name to use given an input section name.
// Set *PLEN to the length of the name.  *PLEN is initialized to the
// Set *PLEN to the length of the name.  *PLEN is initialized to the
// length of NAME.
// length of NAME.
 
 
const char*
const char*
Layout::output_section_name(const char* name, size_t* plen)
Layout::output_section_name(const Relobj* relobj, const char* name,
 
                            size_t* plen)
{
{
  // gcc 4.3 generates the following sorts of section names when it
  // gcc 4.3 generates the following sorts of section names when it
  // needs a section name specific to a function:
  // needs a section name specific to a function:
  //   .text.FN
  //   .text.FN
  //   .rodata.FN
  //   .rodata.FN
Line 4281... Line 4535...
          *plen = psnm->tolen;
          *plen = psnm->tolen;
          return psnm->to;
          return psnm->to;
        }
        }
    }
    }
 
 
 
  // As an additional complication, .ctors sections are output in
 
  // either .ctors or .init_array sections, and .dtors sections are
 
  // output in either .dtors or .fini_array sections.
 
  if (is_prefix_of(".ctors.", name) || is_prefix_of(".dtors.", name))
 
    {
 
      if (parameters->options().ctors_in_init_array())
 
        {
 
          *plen = 11;
 
          return name[1] == 'c' ? ".init_array" : ".fini_array";
 
        }
 
      else
 
        {
 
          *plen = 6;
 
          return name[1] == 'c' ? ".ctors" : ".dtors";
 
        }
 
    }
 
  if (parameters->options().ctors_in_init_array()
 
      && (strcmp(name, ".ctors") == 0 || strcmp(name, ".dtors") == 0))
 
    {
 
      // To make .init_array/.fini_array work with gcc we must exclude
 
      // .ctors and .dtors sections from the crtbegin and crtend
 
      // files.
 
      if (relobj == NULL
 
          || (!Layout::match_file_name(relobj, "crtbegin")
 
              && !Layout::match_file_name(relobj, "crtend")))
 
        {
 
          *plen = 11;
 
          return name[1] == 'c' ? ".init_array" : ".fini_array";
 
        }
 
    }
 
 
  return name;
  return name;
}
}
 
 
 
// Return true if RELOBJ is an input file whose base name matches
 
// FILE_NAME.  The base name must have an extension of ".o", and must
 
// be exactly FILE_NAME.o or FILE_NAME, one character, ".o".  This is
 
// to match crtbegin.o as well as crtbeginS.o without getting confused
 
// by other possibilities.  Overall matching the file name this way is
 
// a dreadful hack, but the GNU linker does it in order to better
 
// support gcc, and we need to be compatible.
 
 
 
bool
 
Layout::match_file_name(const Relobj* relobj, const char* match)
 
{
 
  const std::string& file_name(relobj->name());
 
  const char* base_name = lbasename(file_name.c_str());
 
  size_t match_len = strlen(match);
 
  if (strncmp(base_name, match, match_len) != 0)
 
    return false;
 
  size_t base_len = strlen(base_name);
 
  if (base_len != match_len + 2 && base_len != match_len + 3)
 
    return false;
 
  return memcmp(base_name + base_len - 2, ".o", 2) == 0;
 
}
 
 
// Check if a comdat group or .gnu.linkonce section with the given
// Check if a comdat group or .gnu.linkonce section with the given
// NAME is selected for the link.  If there is already a section,
// NAME is selected for the link.  If there is already a section,
// *KEPT_SECTION is set to point to the existing section and the
// *KEPT_SECTION is set to point to the existing section and the
// function returns false.  Otherwise, OBJECT, SHNDX, IS_COMDAT, and
// function returns false.  Otherwise, OBJECT, SHNDX, IS_COMDAT, and
// IS_GROUP_NAME are recorded for this NAME in the layout object,
// IS_GROUP_NAME are recorded for this NAME in the layout object,
Line 4387... Line 4694...
 
 
  if (type == elfcpp::PT_TLS)
  if (type == elfcpp::PT_TLS)
    this->tls_segment_ = oseg;
    this->tls_segment_ = oseg;
  else if (type == elfcpp::PT_GNU_RELRO)
  else if (type == elfcpp::PT_GNU_RELRO)
    this->relro_segment_ = oseg;
    this->relro_segment_ = oseg;
 
  else if (type == elfcpp::PT_INTERP)
 
    this->interp_segment_ = oseg;
 
 
  return oseg;
  return oseg;
}
}
 
 
// Return the file offset of the normal symbol table.
// Return the file offset of the normal symbol table.
Line 4401... Line 4710...
  if (this->symtab_section_ != NULL)
  if (this->symtab_section_ != NULL)
    return this->symtab_section_->offset();
    return this->symtab_section_->offset();
  return 0;
  return 0;
}
}
 
 
 
// Return the section index of the normal symbol table.  It may have
 
// been stripped by the -s/--strip-all option.
 
 
 
unsigned int
 
Layout::symtab_section_shndx() const
 
{
 
  if (this->symtab_section_ != NULL)
 
    return this->symtab_section_->out_shndx();
 
  return 0;
 
}
 
 
// Write out the Output_sections.  Most won't have anything to write,
// Write out the Output_sections.  Most won't have anything to write,
// since most of the data will come from input sections which are
// since most of the data will come from input sections which are
// handled elsewhere.  But some Output_sections do have Output_data.
// handled elsewhere.  But some Output_sections do have Output_data.
 
 
void
void

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.