diff options
author | Sriraman Tallam <tmsriram@google.com> | 2009-01-28 02:25:33 +0000 |
---|---|---|
committer | Sriraman Tallam <tmsriram@google.com> | 2009-01-28 02:25:33 +0000 |
commit | 6d03d481a0827abf92804f8ffaf9ab00593943be (patch) | |
tree | 617f1054036bd3cca35f897b225b37b4ce1a3b0c /gold/symtab.cc | |
parent | 7df3ce47694f5c804a9468d4c098825b5901216e (diff) | |
download | gdb-6d03d481a0827abf92804f8ffaf9ab00593943be.zip gdb-6d03d481a0827abf92804f8ffaf9ab00593943be.tar.gz gdb-6d03d481a0827abf92804f8ffaf9ab00593943be.tar.bz2 |
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.cc | 104 |
1 files changed, 101 insertions, 3 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc index 90ddfae..11feb03 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; } |