From f15f61a7f344161a8e23cd995d15d7382f738b9d Mon Sep 17 00:00:00 2001
From: Doug Kwan <dougkwan@google.com>
Date: Thu, 15 Oct 2009 18:17:48 +0000
Subject: [PATCH] 2009-10-15  Doug Kwan  <dougkwan@google.com>

	* layout.cc (Layout::finish_dynamic_section): Generate tags
	DT_FINI_ARRAY, DT_FINI_ARRAYSZ, DT_INIT_ARRAY, DT_INIT_ARRAYSZ,
	DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ as needed. If -Bsymbolic is
	used, add DT_SYMBOLIC and set DF_SYMBOLIC in DT_FLAGS.
---
 gold/ChangeLog |  7 +++++++
 gold/layout.cc | 31 +++++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index f5b1fd56427..b69da9f2a9a 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,10 @@
+2009-10-15  Doug Kwan  <dougkwan@google.com>
+
+	* layout.cc (Layout::finish_dynamic_section): Generate tags
+	DT_FINI_ARRAY, DT_FINI_ARRAYSZ, DT_INIT_ARRAY, DT_INIT_ARRAYSZ,
+	DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ as needed. If -Bsymbolic is
+	used, add DT_SYMBOLIC and set DF_SYMBOLIC in DT_FLAGS.
+
 2009-10-14  Ian Lance Taylor  <iant@google.com>
 
 	* object.h (class Relocate_info): Add reloc_shdr and data_shdr
diff --git a/gold/layout.cc b/gold/layout.cc
index 24965309d01..ad3ee1b45b4 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -3104,8 +3104,29 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
   if (sym != NULL && sym->is_defined() && !sym->is_from_dynobj())
     odyn->add_symbol(elfcpp::DT_FINI, sym);
 
-  // FIXME: Support DT_INIT_ARRAY and DT_FINI_ARRAY.
-
+  // Look for .init_array, .preinit_array and .fini_array by checking
+  // section types.
+  for(Layout::Section_list::const_iterator p = this->section_list_.begin();
+      p != this->section_list_.end();
+      ++p)
+    switch((*p)->type())
+      {
+      case elfcpp::SHT_FINI_ARRAY:
+	odyn->add_section_address(elfcpp::DT_FINI_ARRAY, *p);
+	odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p); 
+	break;
+      case elfcpp::SHT_INIT_ARRAY:
+	odyn->add_section_address(elfcpp::DT_INIT_ARRAY, *p);
+	odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p); 
+	break;
+      case elfcpp::SHT_PREINIT_ARRAY:
+	odyn->add_section_address(elfcpp::DT_PREINIT_ARRAY, *p);
+	odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p); 
+	break;
+      default:
+	break;
+      }
+  
   // Add a DT_RPATH entry if needed.
   const General_options::Dir_list& rpath(parameters->options().rpath());
   if (!rpath.empty())
@@ -3186,6 +3207,12 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
     flags |= elfcpp::DF_STATIC_TLS;
   if (parameters->options().origin())
     flags |= elfcpp::DF_ORIGIN;
+  if (parameters->options().Bsymbolic())
+    {
+      flags |= elfcpp::DF_SYMBOLIC;
+      // Add DT_SYMBOLIC for compatibility with older loaders.
+      odyn->add_constant(elfcpp::DT_SYMBOLIC, 0);
+    }
   if (parameters->options().now())
     flags |= elfcpp::DF_BIND_NOW;
   odyn->add_constant(elfcpp::DT_FLAGS, flags);