summaryrefslogtreecommitdiff
path: root/gold/symtab.cc
diff options
context:
space:
mode:
authorSriraman Tallam <tmsriram@google.com>2009-01-28 02:25:33 +0000
committerSriraman Tallam <tmsriram@google.com>2009-01-28 02:25:33 +0000
commit6d03d481a0827abf92804f8ffaf9ab00593943be (patch)
tree617f1054036bd3cca35f897b225b37b4ce1a3b0c /gold/symtab.cc
parent7df3ce47694f5c804a9468d4c098825b5901216e (diff)
downloadbinutils-gdb-6d03d481a0827abf92804f8ffaf9ab00593943be.tar.gz
2009-01-20 Sriraman Tallam <tmsriram@google.com>
* Makefile.am (CCFILES): Add gc.cc. (HFILES): Add gc.h. * Makefile.in: Regenerate. * gold.cc (Gc_runner): New class. (queue_initial_tasks): Call garbage collection related tasks when corresponding options are invoked. (queue_middle_gc_tasks): New function. (queue_middle_tasks): Reorder tasks to allow relocs to be read and processed early before laying out sections during garbage collection. * gold.h (queue_middle_gc_tasks): New function. (is_prefix_of): Move from "layout.cc". * i386.cc (Target_i386::gc_process_relocs): New function. * layout.cc (is_prefix_of): Remove. Move to "gold.h" * main.cc (main): Create object of class "Garbage_collection". * object.cc (Relobj::copy_symbols_data): New function. (Relobj::is_section_name_included): New function. (Sized_relobj::do_layout): Allow this function to be called twice during garbage collection and defer layout of section during the first call. * object.h (Relobj::get_symbols_data): New function. (Relobj::is_section_name_included): New function. (Relobj::copy_symbols_data): New function. (Relobj::set_symbols_data): New function. (Relobj::get_relocs_data): New function. (Relobj::set_relocs_data): New function. (Relobj::is_output_section_offset_invalid): New pure virtual function. (Relobj::gc_process_relocs): New function. (Relobj::do_gc_process_relocs): New pure virtual function. (Relobj::sd_): New data member. (Sized_relobj::is_output_section_offset_invalid): New function. (Sized_relobj::do_gc_process_relocs): New function. * options.h (General_options::gc_sections): Modify to not be a no-op. (General_options::print_gc_sections): New option. * plugin.cc (Plugin_finish::run): Remove function call to Plugin_manager::layout_deferred_objects. Move it to "gold.cc". * powerpc.cc (Target_powerpc::gc_process_relocs): New function. * reloc.cc (Read_relocs::run): Add task to process relocs and determine unreferenced sections when doing garbage collection. (Gc_process_relocs): New class. (Sized_relobj::do_gc_process_relocs): New function. (Sized_relobj::do_scan_relocs): Don't try to scan the relocs for sections that are garbage collected. * reloc.h (Gc_process_relocs): New class. * sparc.cc (Target_sparc::gc_process_relocs): New function. * symtab.cc (Symbol::should_add_dynsym_entry): Do not add entries for symbols whose corresponding sections are garbage collected. (Symbol_table::Symbol_table): Add new parameter for the garbage collection object. (Symbol_table::gc_mark_undef_symbols): New function. (Symbol_table::gc_mark_symbol_for_shlib): New function. (Symbol_table::gc_mark_dyn_syms): New function. (Symbol_table::resolve): Do not treat symbols seen in dynamic objects as garbage. (Symbol_table::add_from_object): Likewise. (Symbol_table::add_from_relobj): When building shared objects, do not treat externally visible symbols as garbage. (Symbol_table::sized_finalize_symbol): Do not check dynamic symbol table information for static and relocatable links. * symtab.h (Symbol_table::set_gc): New function. (Symbol_table::gc): New function. (Symbol_table::gc_mark_undef_symbols): New function. (Symbol_table::gc_mark_symbol_for_shlib): New function. (Symbol_table::gc_mark_dyn_syms): New function. (Symbol_table::gc_): New data member. * target.h (Sized_target::gc_process_relocs): New pure virtual function. * x86_64.cc (Target_x86_64::gc_process_relocs): New function. * testsuite/testfile.cc (Target_test::gc_process_relocs): New function.
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r--gold/symtab.cc104
1 files changed, 101 insertions, 3 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 90ddfaea077..11feb03072c 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -1,6 +1,6 @@
// symtab.cc -- the gold symbol table
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -30,6 +30,7 @@
#include <utility>
#include "demangle.h"
+#include "gc.h"
#include "object.h"
#include "dwarf_reader.h"
#include "dynobj.h"
@@ -302,6 +303,22 @@ Symbol::should_add_dynsym_entry() const
if (this->needs_dynsym_entry())
return true;
+ // If this symbol's section is not added, the symbol need not be added.
+ // The section may have been GCed. Note that export_dynamic is being
+ // overridden here. This should not be done for shared objects.
+ if (parameters->options().gc_sections()
+ && !parameters->options().shared()
+ && this->source() == Symbol::FROM_OBJECT
+ && !this->object()->is_dynamic())
+ {
+ Relobj* relobj = static_cast<Relobj*>(this->object());
+ bool is_ordinary;
+ unsigned int shndx = this->shndx(&is_ordinary);
+ if (is_ordinary && shndx != elfcpp::SHN_UNDEF
+ && !relobj->is_section_included(shndx))
+ return false;
+ }
+
// If the symbol was forced local in a version script, do not add it.
if (this->is_forced_local())
return false;
@@ -461,7 +478,7 @@ 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_(),
- version_script_(version_script)
+ version_script_(version_script), gc_(NULL)
{
namepool_.reserve(count);
}
@@ -488,6 +505,72 @@ Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1,
return k1.first == k2.first && k1.second == k2.second;
}
+// For symbols that have been listed with -u option, add them to the
+// work list to avoid gc'ing them.
+
+void
+Symbol_table::gc_mark_undef_symbols()
+{
+ for (options::String_set::const_iterator p =
+ parameters->options().undefined_begin();
+ p != parameters->options().undefined_end();
+ ++p)
+ {
+ const char* name = p->c_str();
+ Symbol* sym = this->lookup(name);
+ gold_assert (sym != NULL);
+ if (sym->source() == Symbol::FROM_OBJECT
+ && !sym->object()->is_dynamic())
+ {
+ Relobj* obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary)
+ {
+ gold_assert(this->gc_ != NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
+ }
+ }
+ }
+}
+
+void
+Symbol_table::gc_mark_symbol_for_shlib(Symbol* sym)
+{
+ if (!sym->is_from_dynobj()
+ && sym->is_externally_visible())
+ {
+ //Add the object and section to the work list.
+ Relobj* obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
+ {
+ gold_assert(this->gc_!= NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
+ }
+ }
+}
+
+// When doing garbage collection, keep symbols that have been seen in
+// dynamic objects.
+inline void
+Symbol_table::gc_mark_dyn_syms(Symbol* sym)
+{
+ if (sym->in_dyn() && sym->source() == Symbol::FROM_OBJECT
+ && !sym->object()->is_dynamic())
+ {
+ Relobj *obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
+ {
+ gold_assert(this->gc_ != NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
+ }
+ }
+}
+
// Make TO a symbol which forwards to FROM.
void
@@ -561,6 +644,8 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
to->set_in_reg();
if (from->in_dyn())
to->set_in_dyn();
+ if (parameters->options().gc_sections())
+ this->gc_mark_dyn_syms(to);
}
// Record that a symbol is forced to be local by a version script.
@@ -732,6 +817,8 @@ Symbol_table::add_from_object(Object* object,
this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
version);
+ if (parameters->options().gc_sections())
+ this->gc_mark_dyn_syms(ret);
if (def)
{
@@ -814,6 +901,8 @@ Symbol_table::add_from_object(Object* object,
this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
version);
+ if (parameters->options().gc_sections())
+ this->gc_mark_dyn_syms(ret);
ins.first->second = ret;
}
else
@@ -1019,6 +1108,12 @@ Symbol_table::add_from_relobj(
res = this->add_from_object(relobj, name, name_key, ver, ver_key,
def, *psym, st_shndx, is_ordinary,
orig_st_shndx);
+
+ // If building a shared library using garbage collection, do not
+ // treat externally visible symbols as garbage.
+ if (parameters->options().gc_sections()
+ && parameters->options().shared())
+ this->gc_mark_symbol_for_shlib(res);
if (local)
this->force_local(res);
@@ -2177,7 +2272,10 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
if (os == NULL)
{
sym->set_symtab_index(-1U);
- gold_assert(sym->dynsym_index() == -1U);
+ bool static_or_reloc = (parameters->doing_static_link() ||
+ parameters->options().relocatable());
+ gold_assert(static_or_reloc || sym->dynsym_index() == -1U);
+
return false;
}