* layout.cc (Layout::make_output_section): Call
authorIan Lance Taylor <ian@airs.com>
Mon, 22 Jun 2009 06:51:53 +0000 (06:51 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 22 Jun 2009 06:51:53 +0000 (06:51 +0000)
Target::new_output_section.
(Layout::attach_allocated_section_to_segment): Put large section
sections in a separate load segment with the large segment flag
set.
(Layout::segment_precedes): Sort large data segments after other
load segments.
(align_file_offset): New static function.
(Layout::set_segment_offsets): Use align_file_offset.
* output.h (class Output_section): Add is_small_section_ and
is_large_section_ fields.
(Output_section::is_small_section): New function.
(Output_section::set_is_small_section):  New function.
(Output_section::is_large_section): New function.
(Output_section::set_is_large_section): New function.
(Output_section::is_large_data_section): New function.
(class Output_segment): Add is_large_data_segment_ field.
(Output_segment::is_large_data_segment): New function.
(Output_segment::set_is_large_data_segment): New function.
* output.cc (Output_section::Output_section): Initialize new
fields.
(Output_segment::Output_segment): Likewise.
(Output_segment::add_output_section): Add assertion that large
data sections always go in large data segments.  Force small data
sections to the end of the list of data sections.  Force small BSS
sections to the start of the list of BSS sections.  For large BSS
sections to the end of the list of BSS sections.
* symtab.h (class Symbol): Declare is_common_shndx.
(Symbol::is_defined): Check Symbol::is_common_shndx.
(Symbol::is_common): Likewise.
(class Symbol_table): Define enum Commons_section_type.  Update
declarations.  Add small_commons_ and large_commons_ fields.
* symtab.cc (Symbol::is_common_shndx): New function.
(Symbol_table::Symbol_table): Initialize new fields.
(Symbol_table::add_from_object): Put small and large common
symbols in the right list.
(Symbol_table::sized_finalized_symbol): Check
Symbol::is_common_shndx.
(Symbol_table::sized_write_globals): Likewise.
* common.cc (Symbol_table::do_allocate_commons): Allocate new
common symbol lists.  Don't call do_allocate_commons_list if the
list is empty.
(Symbol_table::do_allocate_commons_list): Remove is_tls
parameter.  Add comons_section_type parameter.  Change all
callers.  Handle small and large common symbols.
* object.cc (Sized_relobj::do_finalize_local_symbols): Check
Symbol::is_common_shndx.
* resolve.cc (symbol_to_bits): Likewise.
* target.h (Target::small_common_shndx): New function.
(Target::small_common_section_flags): New function.
(Target::large_common_shndx): New function.
(Target::large_common_section_flags): New function.
(Target::new_output_section): New function.
(Target::Target_info): Add small_common_shndx, large_common_shndx,
small_common_section_flags, and large_common_section_flags
fields.
(Target::do_new_output_section): New virtual function.
* arm.cc (Target_arm::arm_info): Initialize new fields.
* i386.cc (Target_i386::i386_info): Likewise.
* powerpc.cc (Target_powerpc::powerpc_info) [all versions]:
Likewise.
* sparc.c (Target_sparc::sparc_info) [all versions]: Likewise.
* x86_64.cc (Target_x86_64::x86_64_info): Likewise.
(Target_x86_64::do_new_output_section): New function.
* configure.ac: Define conditional MCMODEL_MEDIUM.
* testsuite/Makefile.am (check_PROGRAMS): Add large.
(large_SOURCES, large_CFLAGS, large_DEPENDENCIES): Define.
(large_LDFLAGS): Define.
* testsuite/large.c: New file.
* testsuite/testfile.cc (Target_test::test_target_info):
Initialize new fields.
* configure, testsuite/Makefile.in: Rebuild.

22 files changed:
gold/ChangeLog
gold/Makefile.in
gold/arm.cc
gold/common.cc
gold/configure
gold/configure.ac
gold/i386.cc
gold/layout.cc
gold/object.cc
gold/output.cc
gold/output.h
gold/powerpc.cc
gold/resolve.cc
gold/sparc.cc
gold/symtab.cc
gold/symtab.h
gold/target.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/large.c [new file with mode: 0644]
gold/testsuite/testfile.cc
gold/x86_64.cc

index 02ee8facc629bcbb760309c8216c44ef8b41ec4f..308441a3a83e6c7625dd3e3ecaaa54b5ada94b68 100644 (file)
@@ -1,3 +1,78 @@
+2009-06-21  Ian Lance Taylor  <ian@airs.com>
+
+       * layout.cc (Layout::make_output_section): Call
+       Target::new_output_section.
+       (Layout::attach_allocated_section_to_segment): Put large section
+       sections in a separate load segment with the large segment flag
+       set.
+       (Layout::segment_precedes): Sort large data segments after other
+       load segments.
+       (align_file_offset): New static function.
+       (Layout::set_segment_offsets): Use align_file_offset.
+       * output.h (class Output_section): Add is_small_section_ and
+       is_large_section_ fields.
+       (Output_section::is_small_section): New function.
+       (Output_section::set_is_small_section):  New function.
+       (Output_section::is_large_section): New function.
+       (Output_section::set_is_large_section): New function.
+       (Output_section::is_large_data_section): New function.
+       (class Output_segment): Add is_large_data_segment_ field.
+       (Output_segment::is_large_data_segment): New function.
+       (Output_segment::set_is_large_data_segment): New function.
+       * output.cc (Output_section::Output_section): Initialize new
+       fields.
+       (Output_segment::Output_segment): Likewise.
+       (Output_segment::add_output_section): Add assertion that large
+       data sections always go in large data segments.  Force small data
+       sections to the end of the list of data sections.  Force small BSS
+       sections to the start of the list of BSS sections.  For large BSS
+       sections to the end of the list of BSS sections.
+       * symtab.h (class Symbol): Declare is_common_shndx.
+       (Symbol::is_defined): Check Symbol::is_common_shndx.
+       (Symbol::is_common): Likewise.
+       (class Symbol_table): Define enum Commons_section_type.  Update
+       declarations.  Add small_commons_ and large_commons_ fields.
+       * symtab.cc (Symbol::is_common_shndx): New function.
+       (Symbol_table::Symbol_table): Initialize new fields.
+       (Symbol_table::add_from_object): Put small and large common
+       symbols in the right list.
+       (Symbol_table::sized_finalized_symbol): Check
+       Symbol::is_common_shndx.
+       (Symbol_table::sized_write_globals): Likewise.
+       * common.cc (Symbol_table::do_allocate_commons): Allocate new
+       common symbol lists.  Don't call do_allocate_commons_list if the
+       list is empty.
+       (Symbol_table::do_allocate_commons_list): Remove is_tls
+       parameter.  Add comons_section_type parameter.  Change all
+       callers.  Handle small and large common symbols.
+       * object.cc (Sized_relobj::do_finalize_local_symbols): Check
+       Symbol::is_common_shndx.
+       * resolve.cc (symbol_to_bits): Likewise.
+       * target.h (Target::small_common_shndx): New function.
+       (Target::small_common_section_flags): New function.
+       (Target::large_common_shndx): New function.
+       (Target::large_common_section_flags): New function.
+       (Target::new_output_section): New function.
+       (Target::Target_info): Add small_common_shndx, large_common_shndx,
+       small_common_section_flags, and large_common_section_flags
+       fields.
+       (Target::do_new_output_section): New virtual function.
+       * arm.cc (Target_arm::arm_info): Initialize new fields.
+       * i386.cc (Target_i386::i386_info): Likewise.
+       * powerpc.cc (Target_powerpc::powerpc_info) [all versions]:
+       Likewise.
+       * sparc.c (Target_sparc::sparc_info) [all versions]: Likewise.
+       * x86_64.cc (Target_x86_64::x86_64_info): Likewise.
+       (Target_x86_64::do_new_output_section): New function.
+       * configure.ac: Define conditional MCMODEL_MEDIUM.
+       * testsuite/Makefile.am (check_PROGRAMS): Add large.
+       (large_SOURCES, large_CFLAGS, large_DEPENDENCIES): Define.
+       (large_LDFLAGS): Define.
+       * testsuite/large.c: New file.
+       * testsuite/testfile.cc (Target_test::test_target_info):
+       Initialize new fields.
+       * configure, testsuite/Makefile.in: Rebuild.
+
 2009-06-05  Doug Kwan  <dougkwan@google.com>
 
        * Makefile.am (CCFILES): Add target.cc.
index 0a3245ff1051df77c3fc190fa550b67559c4a3f8..a32de6b67826fc5eeae59eead23e2ab2b6b14a8c 100644 (file)
@@ -213,6 +213,8 @@ MAINT = @MAINT@
 MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
 MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
 MAKEINFO = @MAKEINFO@
+MCMODEL_MEDIUM_FALSE = @MCMODEL_MEDIUM_FALSE@
+MCMODEL_MEDIUM_TRUE = @MCMODEL_MEDIUM_TRUE@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MSGFMT = @MSGFMT@
 MSGMERGE = @MSGMERGE@
index 76538de789dbe7498a7debab3d3992d2d8432379..491f254d1042a0d26cf6ebe3539e360c75e541e9 100644 (file)
@@ -449,7 +449,11 @@ const Target::Target_info Target_arm<big_endian>::arm_info =
   "/usr/lib/libc.so.1",        // dynamic_linker
   0x8000,              // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
-  0x1000               // common_pagesize (overridable by -z common-page-size)
+  0x1000,              // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 // Arm relocate functions class
index 632a20b6c9906469f516cc1d595bf795a3e38759..f90ae40e1b56d826819629d6f84d163210fce20e 100644 (file)
@@ -146,10 +146,18 @@ template<int size>
 void
 Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile)
 {
-  this->do_allocate_commons_list<size>(layout, false, &this->commons_,
-                                      mapfile);
-  this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_,
-                                      mapfile);
+  if (!this->commons_.empty())
+    this->do_allocate_commons_list<size>(layout, COMMONS_NORMAL,
+                                        &this->commons_, mapfile);
+  if (!this->tls_commons_.empty())
+    this->do_allocate_commons_list<size>(layout, COMMONS_TLS,
+                                        &this->tls_commons_, mapfile);
+  if (!this->small_commons_.empty())
+    this->do_allocate_commons_list<size>(layout, COMMONS_SMALL,
+                                        &this->small_commons_, mapfile);
+  if (!this->large_commons_.empty())
+    this->do_allocate_commons_list<size>(layout, COMMONS_LARGE,
+                                        &this->large_commons_, mapfile);
 }
 
 // Allocate the common symbols in a list.  IS_TLS indicates whether
@@ -157,9 +165,11 @@ Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile)
 
 template<int size>
 void
-Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
-                                      Commons_type* commons,
-                                      Mapfile* mapfile)
+Symbol_table::do_allocate_commons_list(
+    Layout* layout,
+    Commons_section_type commons_section_type,
+    Commons_type* commons,
+    Mapfile* mapfile)
 {
   typedef typename Sized_symbol<size>::Value_type Value_type;
   typedef typename Sized_symbol<size>::Size_type Size_type;
@@ -198,20 +208,45 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
            Sort_commons<size>(this));
 
   // Place them in a newly allocated BSS section.
-
-  Output_data_space *poc = new Output_data_space(addralign,
-                                                (is_tls
-                                                 ? "** tls common"
-                                                 : "** common"));
-
-  const char* name = ".bss";
   elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
-  if (is_tls)
+  const char* name;
+  const char* ds_name;
+  switch (commons_section_type)
     {
-      name = ".tbss";
+    case COMMONS_NORMAL:
+      name = ".bss";
+      ds_name = "** common";
+      break;
+    case COMMONS_TLS:
       flags |= elfcpp::SHF_TLS;
+      name = ".tbss";
+      ds_name = "** tls common";
+      break;
+    case COMMONS_SMALL:
+      flags |= parameters->target().small_common_section_flags();
+      name = ".sbss";
+      ds_name = "** small common";
+      break;
+    case COMMONS_LARGE:
+      flags |= parameters->target().large_common_section_flags();
+      name = ".lbss";
+      ds_name = "** large common";
+      break;
+    default:
+      gold_unreachable();
+    }
+
+  Output_data_space *poc = new Output_data_space(addralign, ds_name);
+  Output_section *os = layout->add_output_section_data(name,
+                                                      elfcpp::SHT_NOBITS,
+                                                      flags, poc);
+  if (os != NULL)
+    {
+      if (commons_section_type == COMMONS_SMALL)
+       os->set_is_small_section();
+      else if (commons_section_type == COMMONS_LARGE)
+       os->set_is_large_section();
     }
-  layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags, poc);
 
   // Allocate them all.
 
index 8a6e728afc810dd06dacf05f10addbc3abb6c904..0ada4cfddb093e0d0da2bc5b304686d68a73a196 100755 (executable)
@@ -309,7 +309,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar THREADS_TRUE THREADS_FALSE PLUGINS_TRUE PLUGINS_FALSE TARGETOBJS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE OMP_SUPPORT_TRUE OMP_SUPPORT_FALSE TLS_GNU2_DIALECT_TRUE TLS_GNU2_DIALECT_FALSE TLS_DESCRIPTORS_TRUE TLS_DESCRIPTORS_FALSE CONSTRUCTOR_PRIORITY_TRUE CONSTRUCTOR_PRIORITY_FALSE RANDOM_SEED_CFLAGS WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CFLAGS LIBOBJS CPP EGREP HAVE_ZLIB_TRUE HAVE_ZLIB_FALSE CXXCPP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar THREADS_TRUE THREADS_FALSE PLUGINS_TRUE PLUGINS_FALSE TARGETOBJS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE MCMODEL_MEDIUM_TRUE MCMODEL_MEDIUM_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE OMP_SUPPORT_TRUE OMP_SUPPORT_FALSE TLS_GNU2_DIALECT_TRUE TLS_GNU2_DIALECT_FALSE TLS_DESCRIPTORS_TRUE TLS_DESCRIPTORS_FALSE CONSTRUCTOR_PRIORITY_TRUE CONSTRUCTOR_PRIORITY_FALSE RANDOM_SEED_CFLAGS WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CFLAGS LIBOBJS CPP EGREP HAVE_ZLIB_TRUE HAVE_ZLIB_FALSE CXXCPP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS'
 ac_subst_files=''
 ac_pwd=`pwd`
 
@@ -4603,6 +4603,17 @@ else
 fi
 
 
+
+
+if test "$target_cpu" = "x86_64"; then
+  MCMODEL_MEDIUM_TRUE=
+  MCMODEL_MEDIUM_FALSE='#'
+else
+  MCMODEL_MEDIUM_TRUE='#'
+  MCMODEL_MEDIUM_FALSE=
+fi
+
+
 echo "$as_me:$LINENO: checking for thread support" >&5
 echo $ECHO_N "checking for thread support... $ECHO_C" >&6
 if test "${gold_cv_c_thread+set}" = set; then
@@ -7651,6 +7662,13 @@ echo "$as_me: error: conditional \"FN_PTRS_IN_SO_WITHOUT_PIC\" was never defined
 Usually this means the macro was only invoked conditionally." >&2;}
    { (exit 1); exit 1; }; }
 fi
+if test -z "${MCMODEL_MEDIUM_TRUE}" && test -z "${MCMODEL_MEDIUM_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"MCMODEL_MEDIUM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MCMODEL_MEDIUM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
 if test -z "${TLS_TRUE}" && test -z "${TLS_FALSE}"; then
   { { echo "$as_me:$LINENO: error: conditional \"TLS\" was never defined.
 Usually this means the macro was only invoked conditionally." >&5
@@ -8335,6 +8353,8 @@ s,@GCC_TRUE@,$GCC_TRUE,;t t
 s,@GCC_FALSE@,$GCC_FALSE,;t t
 s,@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@,$FN_PTRS_IN_SO_WITHOUT_PIC_TRUE,;t t
 s,@FN_PTRS_IN_SO_WITHOUT_PIC_FALSE@,$FN_PTRS_IN_SO_WITHOUT_PIC_FALSE,;t t
+s,@MCMODEL_MEDIUM_TRUE@,$MCMODEL_MEDIUM_TRUE,;t t
+s,@MCMODEL_MEDIUM_FALSE@,$MCMODEL_MEDIUM_FALSE,;t t
 s,@TLS_TRUE@,$TLS_TRUE,;t t
 s,@TLS_FALSE@,$TLS_FALSE,;t t
 s,@STATIC_TLS_TRUE@,$STATIC_TLS_TRUE,;t t
index cf59a6a6bcfa03709e51e67d7bef590005141f5d..c249ae4005bdaa69360a569d75227b45e2864774 100644 (file)
@@ -221,6 +221,9 @@ AM_CONDITIONAL(FN_PTRS_IN_SO_WITHOUT_PIC, [
     *) true;;
   esac])
 
+dnl Whether we can test -mcmodel=medium.
+AM_CONDITIONAL(MCMODEL_MEDIUM, [test "$target_cpu" = "x86_64"])
+
 dnl Test for __thread support.
 AC_CACHE_CHECK([for thread support], [gold_cv_c_thread],
 [AC_COMPILE_IFELSE([__thread int i = 1;],
index 11204f48b319f6e55e34a485960f2956a87bf025..0b68613d4dca1027b758a551b01b8f957869220d 100644 (file)
@@ -444,7 +444,11 @@ const Target::Target_info Target_i386::i386_info =
   "/usr/lib/libc.so.1",        // dynamic_linker
   0x08048000,          // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
-  0x1000               // common_pagesize (overridable by -z common-page-size)
+  0x1000,              // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 // Get the GOT section, creating it if necessary.
index 9dbcedc8fe0d7a809b1d2f35294cd3e002eb91dd..c3020cd843b7e6ca24c8df31909b029c32d96d9a 100644 (file)
@@ -788,6 +788,8 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
  else
     os = new Output_section(name, type, flags);
 
+  parameters->target().new_output_section(os);
+
   this->section_list_.push_back(os);
 
   // The GNU linker by default sorts some sections by priority, so we
@@ -875,7 +877,8 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
 
   // In general the only thing we really care about for PT_LOAD
   // segments is whether or not they are writable, so that is how we
-  // search for them.  People who need segments sorted on some other
+  // search for them.  Large data sections also go into their own
+  // PT_LOAD segment.  People who need segments sorted on some other
   // basis will have to use a linker script.
 
   Segment_list::const_iterator p;
@@ -883,28 +886,32 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
        p != this->segment_list_.end();
        ++p)
     {
-      if ((*p)->type() == elfcpp::PT_LOAD
-         && (parameters->options().omagic()
-             || ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W)))
-        {
-          // If -Tbss was specified, we need to separate the data
-          // and BSS segments.
-          if (parameters->options().user_set_Tbss())
-            {
-              if ((os->type() == elfcpp::SHT_NOBITS)
-                  == (*p)->has_any_data_sections())
-                continue;
-            }
+      if ((*p)->type() != elfcpp::PT_LOAD)
+       continue;
+      if (!parameters->options().omagic()
+         && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
+       continue;
+      // If -Tbss was specified, we need to separate the data and BSS
+      // segments.
+      if (parameters->options().user_set_Tbss())
+       {
+         if ((os->type() == elfcpp::SHT_NOBITS)
+             == (*p)->has_any_data_sections())
+           continue;
+       }
+      if (os->is_large_data_section() && !(*p)->is_large_data_segment())
+       continue;
 
-          (*p)->add_output_section(os, seg_flags);
-          break;
-        }
+      (*p)->add_output_section(os, seg_flags);
+      break;
     }
 
   if (p == this->segment_list_.end())
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
                                                        seg_flags);
+      if (os->is_large_data_section())
+       oseg->set_is_large_data_segment();
       oseg->add_output_section(os, seg_flags);
     }
 
@@ -1729,14 +1736,25 @@ Layout::segment_precedes(const Output_segment* seg1,
   else if (seg2->are_addresses_set())
     return false;
 
-  // We sort PT_LOAD segments based on the flags.  Readonly segments
-  // come before writable segments.  Then writable segments with data
-  // come before writable segments without data.  Then executable
-  // segments come before non-executable segments.  Then the unlikely
-  // case of a non-readable segment comes before the normal case of a
-  // readable segment.  If there are multiple segments with the same
-  // type and flags, we require that the address be set, and we sort
-  // by virtual address and then physical address.
+  // A segment which holds large data comes after a segment which does
+  // not hold large data.
+  if (seg1->is_large_data_segment())
+    {
+      if (!seg2->is_large_data_segment())
+       return false;
+    }
+  else if (seg2->is_large_data_segment())
+    return true;
+
+  // Otherwise, we sort PT_LOAD segments based on the flags.  Readonly
+  // segments come before writable segments.  Then writable segments
+  // with data come before writable segments without data.  Then
+  // executable segments come before non-executable segments.  Then
+  // the unlikely case of a non-readable segment comes before the
+  // normal case of a readable segment.  If there are multiple
+  // segments with the same type and flags, we require that the
+  // address be set, and we sort by virtual address and then physical
+  // address.
   if ((flags1 & elfcpp::PF_W) != (flags2 & elfcpp::PF_W))
     return (flags1 & elfcpp::PF_W) == 0;
   if ((flags1 & elfcpp::PF_W) != 0
@@ -1752,6 +1770,19 @@ Layout::segment_precedes(const Output_segment* seg1,
   gold_unreachable();
 }
 
+// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE.
+
+static off_t
+align_file_offset(off_t off, uint64_t addr, uint64_t abi_pagesize)
+{
+  uint64_t unsigned_off = off;
+  uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1))
+                         | (addr & (abi_pagesize - 1)));
+  if (aligned_off < unsigned_off)
+    aligned_off += abi_pagesize;
+  return aligned_off;
+}
+
 // Set the file offsets of all the segments, and all the sections they
 // contain.  They have all been created.  LOAD_SEG must be be laid out
 // first.  Return the offset of the data to follow.
@@ -1838,22 +1869,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
              && !parameters->options().omagic())
            (*p)->set_minimum_p_align(common_pagesize);
 
-         if (are_addresses_set)
-           {
-             if (!parameters->options().nmagic()
-                 && !parameters->options().omagic())
-               {
-                 // Adjust the file offset to the same address modulo
-                 // the page size.
-                 uint64_t unsigned_off = off;
-                 uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1))
-                                         | (addr & (abi_pagesize - 1)));
-                 if (aligned_off < unsigned_off)
-                   aligned_off += abi_pagesize;
-                 off = aligned_off;
-               }
-           }
-         else
+         if (!are_addresses_set)
            {
              // If the last segment was readonly, and this one is
              // not, then skip the address forward one page,
@@ -1874,6 +1890,10 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
              off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
            }
 
+         if (!parameters->options().nmagic()
+             && !parameters->options().omagic())
+           off = align_file_offset(off, addr, abi_pagesize);
+
          unsigned int shndx_hold = *pshndx;
          uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
                                                           &off, pshndx);
@@ -1900,6 +1920,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
                  addr = align_address(aligned_addr, common_pagesize);
                  addr = align_address(addr, (*p)->maximum_alignment());
                  off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+                 off = align_file_offset(off, addr, abi_pagesize);
                  new_addr = (*p)->set_section_addresses(this, true, addr,
                                                          &off, pshndx);
                }
index 88b6028287ee339a63735d897b756d31ce56582a..c3c9c7bcf4542341693a68e342e4834b4f9c35d6 100644 (file)
@@ -1554,7 +1554,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
 
       if (!is_ordinary)
        {
-         if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON)
+         if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx))
            lv.set_output_value(lv.input_value());
          else
            {
index b5321369a35920839d63b7d989f98466d76f0905..911a49ade2ca666e62544f9635c4542034462348 100644 (file)
@@ -1764,6 +1764,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     attached_input_sections_are_sorted_(false),
     is_relro_(false),
     is_relro_local_(false),
+    is_small_section_(false),
+    is_large_section_(false),
     tls_offset_(0)
 {
   // An unallocated section has no address.  Forcing this means that
@@ -2613,7 +2615,8 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
     type_(type),
     flags_(flags),
     is_max_align_known_(false),
-    are_addresses_set_(false)
+    are_addresses_set_(false),
+    is_large_data_segment_(false)
 {
 }
 
@@ -2625,6 +2628,7 @@ Output_segment::add_output_section(Output_section* os,
 {
   gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
   gold_assert(!this->is_max_align_known_);
+  gold_assert(os->is_large_data_section() == this->is_large_data_segment());
 
   // Update the segment flags.
   this->flags_ |= seg_flags;
@@ -2732,6 +2736,69 @@ Output_segment::add_output_section(Output_section* os,
       return;
     }
 
+  // Small data sections go at the end of the list of data sections.
+  // If OS is not small, and there are small sections, we have to
+  // insert it before the first small section.
+  if (os->type() != elfcpp::SHT_NOBITS
+      && !os->is_small_section()
+      && !pdl->empty()
+      && pdl->back()->is_section()
+      && pdl->back()->output_section()->is_small_section())
+    {
+      for (Output_segment::Output_data_list::iterator p = pdl->begin();
+          p != pdl->end();
+          ++p)
+       {
+         if ((*p)->is_section()
+             && (*p)->output_section()->is_small_section())
+           {
+             pdl->insert(p, os);
+             return;
+           }
+       }
+      gold_unreachable();
+    }
+
+  // A small BSS section goes at the start of the BSS sections, after
+  // other small BSS sections.
+  if (os->type() == elfcpp::SHT_NOBITS && os->is_small_section())
+    {
+      for (Output_segment::Output_data_list::iterator p = pdl->begin();
+          p != pdl->end();
+          ++p)
+       {
+         if (!(*p)->is_section()
+             || !(*p)->output_section()->is_small_section())
+           {
+             pdl->insert(p, os);
+             return;
+           }
+       }
+    }
+
+  // A large BSS section goes at the end of the BSS sections, which
+  // means that one that is not large must come before the first large
+  // one.
+  if (os->type() == elfcpp::SHT_NOBITS
+      && !os->is_large_section()
+      && !pdl->empty()
+      && pdl->back()->is_section()
+      && pdl->back()->output_section()->is_large_section())
+    {
+      for (Output_segment::Output_data_list::iterator p = pdl->begin();
+          p != pdl->end();
+          ++p)
+       {
+         if ((*p)->is_section()
+             && (*p)->output_section()->is_large_section())
+           {
+             pdl->insert(p, os);
+             return;
+           }
+       }
+      gold_unreachable();
+    }
+
   pdl->push_back(os);
 }
 
index 5d2c62f3e3c28a0aba9095c14bc670ee5166c519..3e46ad8487c1647ed02cca790de748378be1396a 100644 (file)
@@ -2195,6 +2195,33 @@ class Output_section : public Output_data
   set_is_relro_local()
   { this->is_relro_local_ = true; }
 
+  // True if this is a small section: a section which holds small
+  // variables.
+  bool
+  is_small_section() const
+  { return this->is_small_section_; }
+
+  // Record that this is a small section.
+  void
+  set_is_small_section()
+  { this->is_small_section_ = true; }
+
+  // True if this is a large section: a section which holds large
+  // variables.
+  bool
+  is_large_section() const
+  { return this->is_large_section_; }
+
+  // Record that this is a large section.
+  void
+  set_is_large_section()
+  { this->is_large_section_ = true; }
+
+  // True if this is a large data (not BSS) section.
+  bool
+  is_large_data_section()
+  { return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; }
+
   // Return whether this section should be written after all the input
   // sections are complete.
   bool
@@ -2808,6 +2835,10 @@ class Output_section : public Output_data
   bool is_relro_ : 1;
   // True if this section holds relro local data.
   bool is_relro_local_ : 1;
+  // True if this is a small section.
+  bool is_small_section_ : 1;
+  // True if this is a large section.
+  bool is_large_section_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
@@ -2858,6 +2889,17 @@ class Output_segment
   offset() const
   { return this->offset_; }
 
+  // Whether this is a segment created to hold large data sections.
+  bool
+  is_large_data_segment() const
+  { return this->is_large_data_segment_; }
+
+  // Record that this is a segment created to hold large data
+  // sections.
+  void
+  set_is_large_data_segment()
+  { this->is_large_data_segment_ = true; }
+
   // Return the maximum alignment of the Output_data.
   uint64_t
   maximum_alignment();
@@ -3040,6 +3082,8 @@ class Output_segment
   bool is_max_align_known_ : 1;
   // Whether vaddr and paddr were set by a linker script.
   bool are_addresses_set_ : 1;
+  // Whether this segment holds large data sections.
+  bool is_large_data_segment_ : 1;
 };
 
 // This class represents the output file.
index 9e3d327d01a396dc6947405fd04d039eaadcbfd2..a940fd853fd422fa934871f59dba356e98e3c9cc 100644 (file)
@@ -352,7 +352,11 @@ Target::Target_info Target_powerpc<32, true>::powerpc_info =
   "/usr/lib/ld.so.1",  // dynamic_linker
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
-  4 * 1024             // common_pagesize (overridable by -z common-page-size)
+  4 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 template<>
@@ -369,7 +373,11 @@ Target::Target_info Target_powerpc<32, false>::powerpc_info =
   "/usr/lib/ld.so.1",  // dynamic_linker
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
-  4 * 1024             // common_pagesize (overridable by -z common-page-size)
+  4 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 template<>
@@ -386,7 +394,11 @@ Target::Target_info Target_powerpc<64, true>::powerpc_info =
   "/usr/lib/ld.so.1",  // dynamic_linker
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
-  8 * 1024             // common_pagesize (overridable by -z common-page-size)
+  8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 template<>
@@ -403,7 +415,11 @@ Target::Target_info Target_powerpc<64, false>::powerpc_info =
   "/usr/lib/ld.so.1",  // dynamic_linker
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
-  8 * 1024             // common_pagesize (overridable by -z common-page-size)
+  8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 template<int size, bool big_endian>
index bd327e88a58466f8d8b53fdd0cbd470eae937640..9da963f0abb9de1cbc10de57d302d41f6d980bfd 100644 (file)
@@ -217,6 +217,8 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic,
     default:
       if (type == elfcpp::STT_COMMON)
        bits |= common_flag;
+      else if (!is_ordinary && Symbol::is_common_shndx(shndx))
+       bits |= common_flag;
       else
         bits |= def_flag;
       break;
index d15b8339f693da3c0ddcc161653164ffcb9272b5..34288dea66d71a3de213551d12a9c56a8feaeb18 100644 (file)
@@ -371,7 +371,11 @@ Target::Target_info Target_sparc<32, true>::sparc_info =
   "/usr/lib/ld.so.1",  // dynamic_linker
   0x00010000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
-  8 * 1024             // common_pagesize (overridable by -z common-page-size)
+  8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 template<>
@@ -388,7 +392,11 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
   "/usr/lib/sparcv9/ld.so.1",  // dynamic_linker
   0x100000,            // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
-  8 * 1024             // common_pagesize (overridable by -z common-page-size)
+  8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0                    // large_common_section_flags
 };
 
 // We have to take care here, even when operating in little-endian
index 3d179ef035dbafa2959756d9e8eb0934525a2dca..daf9daf453a218a4921e650a393e194892624443 100644 (file)
@@ -280,6 +280,16 @@ Sized_symbol<size>::init_undefined(const char* name, const char* version,
   this->symsize_ = 0;
 }
 
+// Return true if SHNDX represents a common symbol.
+
+bool
+Symbol::is_common_shndx(unsigned int shndx)
+{
+  return (shndx == elfcpp::SHN_COMMON
+         || shndx == parameters->target().small_common_shndx()
+         || shndx == parameters->target().large_common_shndx());
+}
+
 // Allocate a common symbol.
 
 template<int size>
@@ -477,7 +487,8 @@ Symbol::set_output_section(Output_section* os)
 Symbol_table::Symbol_table(unsigned int count,
                            const Version_script_info& version_script)
   : saw_undefined_(0), offset_(0), table_(count), namepool_(),
-    forwarders_(), commons_(), tls_commons_(), forced_locals_(), warnings_(),
+    forwarders_(), commons_(), tls_commons_(), small_commons_(),
+    large_commons_(), forced_locals_(), warnings_(),
     version_script_(version_script), gc_(NULL)
 {
   namepool_.reserve(count);
@@ -975,10 +986,16 @@ Symbol_table::add_from_object(Object* object,
   // allocation.
   if (!was_common && ret->is_common())
     {
-      if (ret->type() != elfcpp::STT_TLS)
-       this->commons_.push_back(ret);
-      else
+      if (ret->type() == elfcpp::STT_TLS)
        this->tls_commons_.push_back(ret);
+      else if (!is_ordinary
+              && st_shndx == parameters->target().small_common_shndx())
+       this->small_commons_.push_back(ret);
+      else if (!is_ordinary
+              && st_shndx == parameters->target().large_common_shndx())
+       this->large_commons_.push_back(ret);
+      else
+       this->commons_.push_back(ret);
     }
 
   // If we're not doing a relocatable link, then any symbol with
@@ -2370,10 +2387,9 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
        bool is_ordinary;
        unsigned int shndx = sym->shndx(&is_ordinary);
 
-       // FIXME: We need some target specific support here.
        if (!is_ordinary
            && shndx != elfcpp::SHN_ABS
-           && shndx != elfcpp::SHN_COMMON)
+           && !Symbol::is_common_shndx(shndx))
          {
            gold_error(_("%s: unsupported symbol section 0x%x"),
                       sym->demangled_name().c_str(), shndx);
@@ -2394,7 +2410,8 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
        else if (shndx == elfcpp::SHN_UNDEF)
          value = 0;
        else if (!is_ordinary
-                && (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON))
+                && (shndx == elfcpp::SHN_ABS
+                    || Symbol::is_common_shndx(shndx)))
          value = sym->value();
        else
          {
@@ -2597,10 +2614,9 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
            bool is_ordinary;
            unsigned int in_shndx = sym->shndx(&is_ordinary);
 
-           // FIXME: We need some target specific support here.
            if (!is_ordinary
                && in_shndx != elfcpp::SHN_ABS
-               && in_shndx != elfcpp::SHN_COMMON)
+               && !Symbol::is_common_shndx(in_shndx))
              {
                gold_error(_("%s: unsupported symbol section 0x%x"),
                           sym->demangled_name().c_str(), in_shndx);
@@ -2620,7 +2636,7 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
                else if (in_shndx == elfcpp::SHN_UNDEF
                         || (!is_ordinary
                             && (in_shndx == elfcpp::SHN_ABS
-                                || in_shndx == elfcpp::SHN_COMMON)))
+                                || Symbol::is_common_shndx(in_shndx))))
                  shndx = in_shndx;
                else
                  {
index 660fc4d45776e5f13ea698b8964655de61c101a1..be6bc12242b6ff436ee0e61a31390b338ff9bc42 100644 (file)
@@ -411,6 +411,11 @@ class Symbol
   bool
   final_value_is_known() const;
 
+  // Return true if SHNDX represents a common symbol.  This depends on
+  // the target.
+  static bool
+  is_common_shndx(unsigned int shndx);
+
   // Return whether this is a defined symbol (not undefined or
   // common).
   bool
@@ -422,7 +427,7 @@ class Symbol
     unsigned int shndx = this->shndx(&is_ordinary);
     return (is_ordinary
            ? shndx != elfcpp::SHN_UNDEF
-           : shndx != elfcpp::SHN_COMMON);
+           : !Symbol::is_common_shndx(shndx));
   }
 
   // Return true if this symbol is from a dynamic object.
@@ -463,11 +468,13 @@ class Symbol
   bool
   is_common() const
   {
+    if (this->type_ == elfcpp::STT_COMMON)
+      return true;
+    if (this->source_ != FROM_OBJECT)
+      return false;
     bool is_ordinary;
-    return (this->source_ == FROM_OBJECT
-           && ((this->shndx(&is_ordinary) == elfcpp::SHN_COMMON
-                && !is_ordinary)
-               || this->type_ == elfcpp::STT_COMMON));
+    unsigned int shndx = this->shndx(&is_ordinary);
+    return !is_ordinary && Symbol::is_common_shndx(shndx);
   }
 
   // Return whether this symbol can be seen outside this object.
@@ -1505,6 +1512,16 @@ class Symbol_table
   void
   do_add_undefined_symbols_from_command_line();
 
+  // Types of common symbols.
+
+  enum Commons_section_type
+  {
+    COMMONS_NORMAL,
+    COMMONS_TLS,
+    COMMONS_SMALL,
+    COMMONS_LARGE
+  };
+
   // Allocate the common symbols, sized version.
   template<int size>
   void
@@ -1513,7 +1530,8 @@ class Symbol_table
   // Allocate the common symbols from one list.
   template<int size>
   void
-  do_allocate_commons_list(Layout*, bool is_tls, Commons_type*, Mapfile*);
+  do_allocate_commons_list(Layout*, Commons_section_type, Commons_type*,
+                          Mapfile*);
 
   // Implement detect_odr_violations.
   template<int size, bool big_endian>
@@ -1630,6 +1648,10 @@ class Symbol_table
   // This is like the commons_ field, except that it holds TLS common
   // symbols.
   Commons_type tls_commons_;
+  // This is for small common symbols.
+  Commons_type small_commons_;
+  // This is for large common symbols.
+  Commons_type large_commons_;
   // A list of symbols which have been forced to be local.  We don't
   // expect there to be very many of them, so we keep a list of them
   // rather than walking the whole table to find them.
index 2a281050a8b071663356991b2536f2ab20d3720a..597a4f93d07d3f70f82ad52962865fe5d555b7f6 100644 (file)
@@ -141,6 +141,43 @@ class Target
   wrap_char() const
   { return this->pti_->wrap_char; }
 
+  // Return the special section index which indicates a small common
+  // symbol.  This will return SHN_UNDEF if there are no small common
+  // symbols.
+  elfcpp::Elf_Half
+  small_common_shndx() const
+  { return this->pti_->small_common_shndx; }
+
+  // Return values to add to the section flags for the section holding
+  // small common symbols.
+  elfcpp::Elf_Xword
+  small_common_section_flags() const
+  {
+    gold_assert(this->pti_->small_common_shndx != elfcpp::SHN_UNDEF);
+    return this->pti_->small_common_section_flags;
+  }
+
+  // Return the special section index which indicates a large common
+  // symbol.  This will return SHN_UNDEF if there are no large common
+  // symbols.
+  elfcpp::Elf_Half
+  large_common_shndx() const
+  { return this->pti_->large_common_shndx; }
+
+  // Return values to add to the section flags for the section holding
+  // large common symbols.
+  elfcpp::Elf_Xword
+  large_common_section_flags() const
+  {
+    gold_assert(this->pti_->large_common_shndx != elfcpp::SHN_UNDEF);
+    return this->pti_->large_common_section_flags;
+  }
+
+  // This hook is called when an output section is created.
+  void
+  new_output_section(Output_section* os) const
+  { this->do_new_output_section(os); }
+
   // This is called to tell the target to complete any sections it is
   // handling.  After this all sections must have their final size.
   void
@@ -210,12 +247,27 @@ class Target
     uint64_t abi_pagesize;
     // The common page size used by actual implementations.
     uint64_t common_pagesize;
+    // The special section index for small common symbols; SHN_UNDEF
+    // if none.
+    elfcpp::Elf_Half small_common_shndx;
+    // The special section index for large common symbols; SHN_UNDEF
+    // if none.
+    elfcpp::Elf_Half large_common_shndx;
+    // Section flags for small common section.
+    elfcpp::Elf_Xword small_common_section_flags;
+    // Section flags for large common section.
+    elfcpp::Elf_Xword large_common_section_flags;
   };
 
   Target(const Target_info* pti)
     : pti_(pti)
   { }
 
+  // Virtual function which may be implemented by the child class.
+  virtual void
+  do_new_output_section(Output_section*) const
+  { }
+
   // Virtual function which may be implemented by the child class.
   virtual void
   do_finalize_sections(Layout*)
index 3bb5bd3a5f86acbc9f48702cbea4bf6a0cd54ed5..5afd4b0a58241210cd6e1d82c473880cfa25ab92 100644 (file)
@@ -1092,5 +1092,13 @@ discard_locals_test.syms: discard_locals_test
 discard_locals_test.o: discard_locals_test.c
        $(COMPILE) -c -Wa,-L -o $@ $<
 
+if MCMODEL_MEDIUM
+check_PROGRAMS += large
+large_SOURCES = large.c
+large_CFLAGS = -mcmodel=medium
+large_DEPENDENCIES = gcctestdir/ld
+large_LDFLAGS = -Bgcctestdir/
+endif MCMODEL_MEDIUM
+
 endif GCC
 endif NATIVE_LINKER
index 1bc579e76f7d90b39e3153c1b064c2adbd98a5d5..c10827486251a5c5b77d9c305248c78405781253 100644 (file)
@@ -48,7 +48,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
        $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \
        $(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \
        $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) \
-       $(am__EXEEXT_16) $(am__EXEEXT_17)
+       $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__EXEEXT_18)
 
 # Test --detect-odr-violations
 
@@ -330,6 +330,20 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_2.a \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libexclude_libs_test_3.a \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.syms
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__append_28 = large
+@GCC_FALSE@large_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@GCC_FALSE@    ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
+@GCC_FALSE@    $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+@MCMODEL_MEDIUM_FALSE@large_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@MCMODEL_MEDIUM_FALSE@ ../../libiberty/libiberty.a \
+@MCMODEL_MEDIUM_FALSE@ $(am__DEPENDENCIES_1) \
+@MCMODEL_MEDIUM_FALSE@ $(am__DEPENDENCIES_1) \
+@MCMODEL_MEDIUM_FALSE@ $(am__DEPENDENCIES_1)
+@NATIVE_LINKER_FALSE@large_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@NATIVE_LINKER_FALSE@  ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1) \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1) \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1)
 subdir = testsuite
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -438,6 +452,7 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ exclude_libs_test$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ local_labels_test$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test$(EXEEXT)
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_18 = large$(EXEEXT)
 basic_pic_test_SOURCES = basic_pic_test.c
 basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT)
 basic_pic_test_LDADD = $(LDADD)
@@ -589,6 +604,10 @@ am__justsyms_SOURCES_DIST = justsyms_1.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT)
 justsyms_OBJECTS = $(am_justsyms_OBJECTS)
 justsyms_LDADD = $(LDADD)
+am__large_SOURCES_DIST = large.c
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am_large_OBJECTS = large-large.$(OBJEXT)
+large_OBJECTS = $(am_large_OBJECTS)
+large_LDADD = $(LDADD)
 local_labels_test_SOURCES = local_labels_test.c
 local_labels_test_OBJECTS = local_labels_test.$(OBJEXT)
 local_labels_test_LDADD = $(LDADD)
@@ -923,15 +942,16 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
        $(exclude_libs_test_SOURCES) \
        flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
        flagstest_o_specialfile_and_compress_debug_sections.c \
-       $(initpri1_SOURCES) $(justsyms_SOURCES) local_labels_test.c \
-       many_sections_r_test.c $(many_sections_test_SOURCES) \
-       $(object_unittest_SOURCES) plugin_test_1.c plugin_test_2.c \
-       plugin_test_3.c plugin_test_4.c $(protected_1_SOURCES) \
-       $(protected_2_SOURCES) $(relro_script_test_SOURCES) \
-       $(relro_test_SOURCES) $(script_test_1_SOURCES) \
-       $(script_test_2_SOURCES) script_test_3.c \
-       $(thin_archive_test_1_SOURCES) $(thin_archive_test_2_SOURCES) \
-       $(tls_pic_test_SOURCES) $(tls_shared_gd_to_ie_test_SOURCES) \
+       $(initpri1_SOURCES) $(justsyms_SOURCES) $(large_SOURCES) \
+       local_labels_test.c many_sections_r_test.c \
+       $(many_sections_test_SOURCES) $(object_unittest_SOURCES) \
+       plugin_test_1.c plugin_test_2.c plugin_test_3.c \
+       plugin_test_4.c $(protected_1_SOURCES) $(protected_2_SOURCES) \
+       $(relro_script_test_SOURCES) $(relro_test_SOURCES) \
+       $(script_test_1_SOURCES) $(script_test_2_SOURCES) \
+       script_test_3.c $(thin_archive_test_1_SOURCES) \
+       $(thin_archive_test_2_SOURCES) $(tls_pic_test_SOURCES) \
+       $(tls_shared_gd_to_ie_test_SOURCES) \
        $(tls_shared_gnu2_gd_to_ie_test_SOURCES) \
        $(tls_shared_gnu2_test_SOURCES) $(tls_shared_ie_test_SOURCES) \
        $(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \
@@ -979,8 +999,8 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
        flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
        flagstest_o_specialfile_and_compress_debug_sections.c \
        $(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \
-       local_labels_test.c many_sections_r_test.c \
-       $(am__many_sections_test_SOURCES_DIST) \
+       $(am__large_SOURCES_DIST) local_labels_test.c \
+       many_sections_r_test.c $(am__many_sections_test_SOURCES_DIST) \
        $(object_unittest_SOURCES) plugin_test_1.c plugin_test_2.c \
        plugin_test_3.c plugin_test_4.c \
        $(am__protected_1_SOURCES_DIST) \
@@ -1086,6 +1106,8 @@ MAINT = @MAINT@
 MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
 MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
 MAKEINFO = @MAKEINFO@
+MCMODEL_MEDIUM_FALSE = @MCMODEL_MEDIUM_FALSE@
+MCMODEL_MEDIUM_TRUE = @MCMODEL_MEDIUM_TRUE@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MSGFMT = @MSGFMT@
 MSGMERGE = @MSGMERGE@
@@ -1546,6 +1568,10 @@ binary_unittest_SOURCES = binary_unittest.cc
 
 @GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test_SOURCES = discard_locals_test.c
 @GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test_LDFLAGS = -Bgcctestdir/ -Wl,--discard-locals
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_SOURCES = large.c
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_CFLAGS = -mcmodel=medium
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_DEPENDENCIES = gcctestdir/ld
+@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_LDFLAGS = -Bgcctestdir/
 all: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) all-am
 
@@ -1689,6 +1715,9 @@ initpri1$(EXEEXT): $(initpri1_OBJECTS) $(initpri1_DEPENDENCIES)
 justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES) 
        @rm -f justsyms$(EXEEXT)
        $(CXXLINK) $(justsyms_LDFLAGS) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS)
+large$(EXEEXT): $(large_OBJECTS) $(large_DEPENDENCIES) 
+       @rm -f large$(EXEEXT)
+       $(LINK) $(large_LDFLAGS) $(large_OBJECTS) $(large_LDADD) $(LIBS)
 @GCC_FALSE@local_labels_test$(EXEEXT): $(local_labels_test_OBJECTS) $(local_labels_test_DEPENDENCIES) 
 @GCC_FALSE@    @rm -f local_labels_test$(EXEEXT)
 @GCC_FALSE@    $(LINK) $(local_labels_test_LDFLAGS) $(local_labels_test_OBJECTS) $(local_labels_test_LDADD) $(LIBS)
@@ -1928,6 +1957,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri1.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/large-large.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_labels_test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_r_test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_test.Po@am__quote@
@@ -1980,6 +2010,20 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
 
+large-large.o: large.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -MT large-large.o -MD -MP -MF "$(DEPDIR)/large-large.Tpo" -c -o large-large.o `test -f 'large.c' || echo '$(srcdir)/'`large.c; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/large-large.Tpo" "$(DEPDIR)/large-large.Po"; else rm -f "$(DEPDIR)/large-large.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='large.c' object='large-large.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -c -o large-large.o `test -f 'large.c' || echo '$(srcdir)/'`large.c
+
+large-large.obj: large.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -MT large-large.obj -MD -MP -MF "$(DEPDIR)/large-large.Tpo" -c -o large-large.obj `if test -f 'large.c'; then $(CYGPATH_W) 'large.c'; else $(CYGPATH_W) '$(srcdir)/large.c'; fi`; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/large-large.Tpo" "$(DEPDIR)/large-large.Po"; else rm -f "$(DEPDIR)/large-large.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='large.c' object='large-large.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -c -o large-large.obj `if test -f 'large.c'; then $(CYGPATH_W) 'large.c'; else $(CYGPATH_W) '$(srcdir)/large.c'; fi`
+
 .cc.o:
 @am__fastdepCXX_TRUE@  if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
diff --git a/gold/testsuite/large.c b/gold/testsuite/large.c
new file mode 100644 (file)
index 0000000..796242a
--- /dev/null
@@ -0,0 +1,59 @@
+/* large.c -- a test case for gold
+
+   Copyright 2009 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <iant@google.com>.
+
+   This file is part of gold.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include <assert.h>
+
+/* Test large sections in gold.  */
+
+int v1;
+int v2 = 1;
+int v3[0x10000];
+int v4[0x10000] = { 1 };
+const int v5[0x10000] = { 2 };
+int v6;
+int v7 = 1;
+
+int
+main (int argc __attribute__ ((unused)), char** argv __attribute ((unused)))
+{
+  assert (v1 == 0);
+  assert (v2 == 1);
+  assert (v3[0] == 0 && v3[0xffff] == 0);
+  assert (v4[0] == 1 && v4[0xffff] == 0);
+  assert (v5[0] == 2 && v5[0xffff] == 0);
+  assert (v6 == 0);
+  assert (v7 == 1);
+
+  /* The large symbols must follow the small ones.  */
+  assert (&v1 < v3 && &v1 < v4 && &v1 < v5);
+  assert (&v2 < v3 && &v2 < v4 && &v2 < v5);
+  assert (&v6 < v3 && &v6 < v4 && &v6 < v5);
+  assert (&v7 < v3 && &v7 < v4 && &v7 < v5);
+
+  /* Large symbols should be BSS followed by read-only followed by
+     read-write.  */
+  assert (v3 < v4);
+  assert (v3 < v5);
+  assert (v5 < v4);
+
+  return 0;
+}
index a2a45bec23aae719d7adc5198c27a7552960a03d..2532307994f5c9c981ed964164e02da965f22108 100644 (file)
@@ -99,7 +99,11 @@ const Target::Target_info Target_test<size, big_endian>::test_target_info =
   "/dummy",                            // dynamic_linker
   0x08000000,                          // default_text_segment_address
   0x1000,                              // abi_pagesize
-  0x1000                               // common_pagesize
+  0x1000,                              // common_pagesize
+  elfcpp::SHN_UNDEF,                   // small_common_shndx
+  elfcpp::SHN_UNDEF,                   // large_common_shndx
+  0,                                   // small_common_section_flags
+  0                                    // large_common_section_flags
 };
 
 // The test targets.
index 611c37ed8d4fc7c225fe6682dc511164250f3d98..91b542eef4687ad4151119708c737145324634b7 100644 (file)
@@ -67,6 +67,10 @@ class Target_x86_64 : public Target_freebsd<64, false>
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
   { }
 
+  // Hook for a new output section.
+  void
+  do_new_output_section(Output_section*) const;
+
   // Scan the relocations to look for symbol adjustments.
   void
   gc_process_relocs(const General_options& options,
@@ -438,9 +442,23 @@ const Target::Target_info Target_x86_64::x86_64_info =
   "/lib/ld64.so.1",     // program interpreter
   0x400000,            // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
-  0x1000               // common_pagesize (overridable by -z common-page-size)
+  0x1000,              // common_pagesize (overridable by -z common-page-size)
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_X86_64_LCOMMON,  // large_common_shndx
+  0,                   // small_common_section_flags
+  elfcpp::SHF_X86_64_LARGE     // large_common_section_flags
 };
 
+// This is called when a new output section is created.  This is where
+// we handle the SHF_X86_64_LARGE.
+
+void
+Target_x86_64::do_new_output_section(Output_section *os) const
+{
+  if ((os->flags() & elfcpp::SHF_X86_64_LARGE) != 0)
+    os->set_is_large_section();
+}
+
 // Get the GOT section, creating it if necessary.
 
 Output_data_got<64, false>*
This page took 0.057468 seconds and 4 git commands to generate.