2010-02-01 Doug Kwan <dougkwan@google.com>
[deliverable/binutils-gdb.git] / gold / object.h
index e7d05c72c880c2616f441c20c440ed09f73daf6b..fb3caefcdb8465cc97b28fabf2f786dc40ffbb60 100644 (file)
@@ -1,6 +1,6 @@
 // object.h -- support for an object file for linking in gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -188,6 +188,8 @@ class Xindex
 class Object
 {
  public:
+  typedef std::vector<Symbol*> Symbols;
+
   // NAME is the name of the object as we would report it to the user
   // (e.g., libfoo.a(bar.o) if this is in an archive.  INPUT_FILE is
   // used to read the file.  OFFSET is the offset within the input
@@ -195,7 +197,8 @@ class Object
   Object(const std::string& name, Input_file* input_file, bool is_dynamic,
         off_t offset = 0)
     : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
-      is_dynamic_(is_dynamic), xindex_(NULL), no_export_(false)
+      is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
+      has_no_split_stack_(false), no_export_(false), xindex_(NULL)
   { input_file->file().add_object(); }
 
   virtual ~Object()
@@ -216,6 +219,30 @@ class Object
   is_dynamic() const
   { return this->is_dynamic_; }
 
+  // Return whether this object is needed--true if it is a dynamic
+  // object which defines some symbol referenced by a regular object.
+  // We keep the flag here rather than in Dynobj for convenience when
+  // setting it.
+  bool
+  is_needed() const
+  { return this->is_needed_; }
+
+  // Record that this object is needed.
+  void
+  set_is_needed()
+  { this->is_needed_ = true; }
+
+  // Return whether this object was compiled with -fsplit-stack.
+  bool
+  uses_split_stack() const
+  { return this->uses_split_stack_; }
+
+  // Return whether this object contains any functions compiled with
+  // the no_split_stack attribute.
+  bool
+  has_no_split_stack() const
+  { return this->has_no_split_stack_; }
+
   // Returns NULL for Objects that are not plugin objects.  This method
   // is overridden in the Pluginobj class.
   Pluginobj*
@@ -441,6 +468,11 @@ class Object
                           size_t* used) const
   { this->do_get_global_symbol_counts(symtab, defined, used); }
 
+  // Get the symbols defined in this object.
+  const Symbols*
+  get_global_symbols() const
+  { return this->do_get_global_symbols(); }
+
   // Return whether this object was found in a system directory.
   bool
   is_in_system_directory() const
@@ -528,6 +560,9 @@ class Object
   virtual void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;
 
+  virtual const Symbols*
+  do_get_global_symbols() const = 0;
+
   // Set the number of sections.
   void
   set_shnum(int shnum)
@@ -556,6 +591,12 @@ class Object
   handle_gnu_warning_section(const char* name, unsigned int shndx,
                             Symbol_table*);
 
+  // If NAME is the name of the special section which indicates that
+  // this object was compiled with -fstack-split, mark it accordingly,
+  // and return true.  Otherwise return false.
+  bool
+  handle_split_stack_section(const char* name);
+
  private:
   // This class may not be copied.
   Object(const Object&);
@@ -571,12 +612,21 @@ class Object
   // Number of input sections.
   unsigned int shnum_;
   // Whether this is a dynamic object.
-  bool is_dynamic_;
-  // Many sections for objects with more than SHN_LORESERVE sections.
-  Xindex* xindex_;
+  bool is_dynamic_ : 1;
+  // Whether this object is needed.  This is only set for dynamic
+  // objects, and means that the object defined a symbol which was
+  // used by a reference from a regular object.
+  bool is_needed_ : 1;
+  // Whether this object was compiled with -fsplit-stack.
+  bool uses_split_stack_ : 1;
+  // Whether this object contains any functions compiled with the
+  // no_split_stack attribute.
+  bool has_no_split_stack_ : 1;
   // True if exclude this object from automatic symbol export.
   // This is used only for archive objects.
-  bool no_export_;
+  bool no_export_ : 1;
+  // Many sections for objects with more than SHN_LORESERVE sections.
+  Xindex* xindex_;
 };
 
 // A regular object (ET_REL).  This is an abstract base class itself.
@@ -636,15 +686,13 @@ class Relobj : public Object
 
   // Process the relocs, during garbage collection only.
   void
-  gc_process_relocs(const General_options& options, Symbol_table* symtab,
-                   Layout* layout, Read_relocs_data* rd)
-  { return this->do_gc_process_relocs(options, symtab, layout, rd); }
+  gc_process_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
+  { return this->do_gc_process_relocs(symtab, layout, rd); }
 
   // Scan the relocs and adjust the symbol table.
   void
-  scan_relocs(const General_options& options, Symbol_table* symtab,
-             Layout* layout, Read_relocs_data* rd)
-  { return this->do_scan_relocs(options, symtab, layout, rd); }
+  scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
+  { return this->do_scan_relocs(symtab, layout, rd); }
 
   // The number of local symbols in the input symbol table.
   virtual unsigned int
@@ -678,9 +726,8 @@ class Relobj : public Object
 
   // Relocate the input sections and write out the local symbols.
   void
-  relocate(const General_options& options, const Symbol_table* symtab,
-          const Layout* layout, Output_file* of)
-  { return this->do_relocate(options, symtab, layout, of); }
+  relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of)
+  { return this->do_relocate(symtab, layout, of); }
 
   // Return whether an input section is being included in the link.
   bool
@@ -700,6 +747,16 @@ class Relobj : public Object
     return this->output_sections_[shndx];
   }
 
+  // The the output section of the input section with index SHNDX.
+  // This is only used currently to remove a section from the link in
+  // relaxation.
+  void
+  set_output_section(unsigned int shndx, Output_section* os)
+  {
+    gold_assert(shndx < this->output_sections_.size());
+    this->output_sections_[shndx] = os;
+  }
+  
   // Given a section index, return the offset in the Output_section.
   // The return value will be -1U if the section is specially mapped,
   // such as a merge section.
@@ -767,13 +824,11 @@ class Relobj : public Object
 
   // Process the relocs--implemented by child class.
   virtual void
-  do_gc_process_relocs(const General_options&, Symbol_table*, Layout*,
-                Read_relocs_data*) = 0;
+  do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
 
   // Scan the relocs--implemented by child class.
   virtual void
-  do_scan_relocs(const General_options&, Symbol_table*, Layout*,
-                Read_relocs_data*) = 0;
+  do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
 
   // Return the number of local symbols--implemented by child class.
   virtual unsigned int
@@ -801,8 +856,7 @@ class Relobj : public Object
   // Relocate the input sections and write out the local
   // symbols--implemented by child class.
   virtual void
-  do_relocate(const General_options& options, const Symbol_table* symtab,
-             const Layout*, Output_file* of) = 0;
+  do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of) = 0;
 
   // Get the offset of a section--implemented by child class.
   virtual uint64_t
@@ -1252,6 +1306,30 @@ class Got_offset_list
   Got_offset_list* got_next_;
 };
 
+// This type is used to modify relocations for -fsplit-stack.  It is
+// indexed by relocation index, and means that the relocation at that
+// index should use the symbol from the vector, rather than the one
+// indicated by the relocation.
+
+class Reloc_symbol_changes
+{
+ public:
+  Reloc_symbol_changes(size_t count)
+    : vec_(count, NULL)
+  { }
+
+  void
+  set(size_t i, Symbol* sym)
+  { this->vec_[i] = sym; }
+
+  const Symbol*
+  operator[](size_t i) const
+  { return this->vec_[i]; }
+
+ private:
+  std::vector<Symbol*> vec_;
+};
+
 // A regular object file.  This is size and endian specific.
 
 template<int size, bool big_endian>
@@ -1277,7 +1355,8 @@ class Sized_relobj : public Relobj
 
   // Set up the object file based on TARGET.
   void
-  setup();
+  setup()
+  { this->do_setup(); }
 
   // Return the number of symbols.  This is only valid after
   // Object::add_symbols has been called.
@@ -1416,6 +1495,10 @@ class Sized_relobj : public Relobj
   map_to_kept_section(unsigned int shndx, bool* found) const;
 
  protected:
+  // Set up.
+  virtual void
+  do_setup();
+
   // Read the symbols.
   void
   do_read_symbols(Read_symbols_data*);
@@ -1445,13 +1528,11 @@ class Sized_relobj : public Relobj
   // Process the relocs to find list of referenced sections. Used only
   // during garbage collection.
   void
-  do_gc_process_relocs(const General_options&, Symbol_table*, Layout*,
-                      Read_relocs_data*);
+  do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*);
 
   // Scan the relocs and adjust the symbol table.
   void
-  do_scan_relocs(const General_options&, Symbol_table*, Layout*,
-                Read_relocs_data*);
+  do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*);
 
   // Count the local symbols.
   void
@@ -1472,8 +1553,7 @@ class Sized_relobj : public Relobj
 
   // Relocate the input sections and write out the local symbols.
   void
-  do_relocate(const General_options& options, const Symbol_table* symtab,
-             const Layout*, Output_file* of);
+  do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of);
 
   // Get the size of a section.
   uint64_t
@@ -1531,6 +1611,11 @@ class Sized_relobj : public Relobj
   void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
 
+  // Get the global symbols.
+  const Symbols*
+  do_get_global_symbols() const
+  { return &this->symbols_; }
+
   // Get the offset of a section.
   uint64_t
   do_output_section_offset(unsigned int shndx) const
@@ -1546,9 +1631,69 @@ class Sized_relobj : public Relobj
   do_set_section_offset(unsigned int shndx, uint64_t off)
   {
     gold_assert(shndx < this->section_offsets_.size());
-    this->section_offsets_[shndx] = convert_types<Address, uint64_t>(off);
+    this->section_offsets_[shndx] =
+      (off == static_cast<uint64_t>(-1)
+       ? invalid_address
+       : convert_types<Address, uint64_t>(off));
   }
 
+  // Adjust a section index if necessary.
+  unsigned int
+  adjust_shndx(unsigned int shndx)
+  {
+    if (shndx >= elfcpp::SHN_LORESERVE)
+      shndx += this->elf_file_.large_shndx_offset();
+    return shndx;
+  }
+
+  // Initialize input to output maps for section symbols in merged
+  // sections.
+  void
+  initialize_input_to_output_maps();
+
+  // Free the input to output maps for section symbols in merged
+  // sections.
+  void
+  free_input_to_output_maps();
+
+  // Return symbol table section index.
+  unsigned int
+  symtab_shndx() const
+  { return this->symtab_shndx_; }
+
+  // Allow a child class to access the ELF file.
+  elfcpp::Elf_file<size, big_endian, Object>*
+  elf_file()
+  { return &this->elf_file_; }
+  
+  // Allow a child class to access the local values.
+  Local_values*
+  local_values()
+  { return &this->local_values_; }
+
+  // Views and sizes when relocating.
+  struct View_size
+  {
+    unsigned char* view;
+    typename elfcpp::Elf_types<size>::Elf_Addr address;
+    off_t offset;
+    section_size_type view_size;
+    bool is_input_output_view;
+    bool is_postprocessing_view;
+  };
+
+  typedef std::vector<View_size> Views;
+
+  // This may be overriden by a child class.
+  virtual void
+  do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
+                      const unsigned char* pshdrs, Views* pviews);
+
+  // Allow a child to set output local symbol count.
+  void
+  set_output_local_symbol_count(unsigned int value)
+  { this->output_local_symbol_count_ = value; }
+   
  private:
   // For convenience.
   typedef Sized_relobj<size, big_endian> This;
@@ -1571,15 +1716,6 @@ class Sized_relobj : public Relobj
   typedef std::map<unsigned int, Kept_comdat_section>
       Kept_comdat_section_table;
 
-  // Adjust a section index if necessary.
-  unsigned int
-  adjust_shndx(unsigned int shndx)
-  {
-    if (shndx >= elfcpp::SHN_LORESERVE)
-      shndx += this->elf_file_.large_shndx_offset();
-    return shndx;
-  }
-
   // Find the SHT_SYMTAB section, given the section headers.
   void
   find_symtab(const unsigned char* pshdrs);
@@ -1612,19 +1748,6 @@ class Sized_relobj : public Relobj
                  typename This::Shdr& shdr, unsigned int reloc_shndx,
                  unsigned int reloc_type);
 
-  // Views and sizes when relocating.
-  struct View_size
-  {
-    unsigned char* view;
-    typename elfcpp::Elf_types<size>::Elf_Addr address;
-    off_t offset;
-    section_size_type view_size;
-    bool is_input_output_view;
-    bool is_postprocessing_view;
-  };
-
-  typedef std::vector<View_size> Views;
-
   // Write section data to the output file.  Record the views and
   // sizes in VIEWS for use when relocating.
   void
@@ -1632,20 +1755,20 @@ class Sized_relobj : public Relobj
 
   // Relocate the sections in the output file.
   void
-  relocate_sections(const General_options& options, const Symbol_table*,
-                   const Layout*, const unsigned char* pshdrs, Views*);
+  relocate_sections(const Symbol_table* symtab, const Layout* layout,
+                   const unsigned char* pshdrs, Views* pviews)
+  { this->do_relocate_sections(symtab, layout, pshdrs, pviews); }
 
   // Scan the input relocations for --emit-relocs.
   void
-  emit_relocs_scan(const General_options&, Symbol_table*, Layout*,
-                  const unsigned char* plocal_syms,
+  emit_relocs_scan(Symbol_table*, Layout*, const unsigned char* plocal_syms,
                   const Read_relocs_data::Relocs_list::iterator&);
 
   // Scan the input relocations for --emit-relocs, templatized on the
   // type of the relocation section.
   template<int sh_type>
   void
-  emit_relocs_scan_reltype(const General_options&, Symbol_table*, Layout*,
+  emit_relocs_scan_reltype(Symbol_table*, Layout*,
                           const unsigned char* plocal_syms,
                           const Read_relocs_data::Relocs_list::iterator&,
                           Relocatable_relocs*);
@@ -1671,15 +1794,29 @@ class Sized_relobj : public Relobj
                      unsigned char* reloc_view,
                      section_size_type reloc_view_size);
 
-  // Initialize input to output maps for section symbols in merged
-  // sections.
+  // A type shared by split_stack_adjust_reltype and find_functions.
+  typedef std::map<section_offset_type, section_size_type> Function_offsets;
+
+  // Check for -fsplit-stack routines calling non-split-stack routines.
   void
-  initialize_input_to_output_maps();
+  split_stack_adjust(const Symbol_table*, const unsigned char* pshdrs,
+                    unsigned int sh_type, unsigned int shndx,
+                    const unsigned char* prelocs, size_t reloc_count,
+                    unsigned char* view, section_size_type view_size,
+                    Reloc_symbol_changes** reloc_map);
 
-  // Free the input to output maps for section symbols in merged
-  // sections.
+  template<int sh_type>
   void
-  free_input_to_output_maps();
+  split_stack_adjust_reltype(const Symbol_table*, const unsigned char* pshdrs,
+                            unsigned int shndx, const unsigned char* prelocs,
+                            size_t reloc_count, unsigned char* view,
+                            section_size_type view_size,
+                            Reloc_symbol_changes** reloc_map);
+
+  // Find all functions in a section.
+  void
+  find_functions(const unsigned char* pshdrs, unsigned int shndx,
+                Function_offsets*);
 
   // Write out the local symbols.
   void
@@ -1843,6 +1980,10 @@ class Input_objects
   void
   print_symbol_counts(const Symbol_table*) const;
 
+  // Print a cross reference table.
+  void
+  print_cref(const Symbol_table*, FILE*) const;
+
   // Iterate over all regular objects.
 
   Relobj_iterator
@@ -1893,8 +2034,6 @@ class Input_objects
 template<int size, bool big_endian>
 struct Relocate_info
 {
-  // Command line options.
-  const General_options* options;
   // Symbol table.
   const Symbol_table* symtab;
   // Layout.
@@ -1903,8 +2042,12 @@ struct Relocate_info
   Sized_relobj<size, big_endian>* object;
   // Section index of relocation section.
   unsigned int reloc_shndx;
+  // Section header of relocation section.
+  const unsigned char* reloc_shdr;
   // Section index of section being relocated.
   unsigned int data_shndx;
+  // Section header of data section.
+  const unsigned char* data_shdr;
 
   // Return a string showing the location of a relocation.  This is
   // only used for error messages.
@@ -1912,6 +2055,31 @@ struct Relocate_info
   location(size_t relnum, off_t reloffset) const;
 };
 
+// This is used to represent a section in an object and is used as the
+// key type for various section maps.
+typedef std::pair<Object*, unsigned int> Section_id;
+
+// This is similar to Section_id but is used when the section
+// pointers are const.
+typedef std::pair<const Object*, unsigned int> Const_section_id;
+
+// The hash value is based on the address of an object in memory during
+// linking.  It is okay to use this for looking up sections but never use
+// this in an unordered container that we want to traverse in a repeatable
+// manner.
+
+struct Section_id_hash
+{
+  size_t operator()(const Section_id& loc) const
+  { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
+};
+
+struct Const_section_id_hash
+{
+  size_t operator()(const Const_section_id& loc) const
+  { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
+};
+
 // Return whether INPUT_FILE contains an ELF object start at file
 // offset OFFSET.  This sets *START to point to a view of the start of
 // the file.  It sets *READ_SIZE to the number of bytes in the view.
This page took 0.027869 seconds and 4 git commands to generate.