From 0f1c85a62235edfbe68c78b197dcdbbe94b0b160 Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Tue, 24 May 2011 21:57:28 +0000 Subject: * dynobj.h (Dynobj::do_dynobj): New function. * incremental-dump.cc (dump_incremental_inputs): Print as_needed flag and soname for shared objects. * incremental.cc (Incremental_inputs::report_object): Make either Incremental_object_entry or Incremental_dynobj_entry; add soname to string table. (Incremental_inputs::report_input_section): Add assertion. (Output_section_incremental_inputs::set_final_data_size): Adjust type of input file entry for shared libraries; adjust size of shared library info entry. (Output_section_incremental_inputs::write_input_files): Write as_needed flag for shared libraries. (Output_section_incremental_inputs::write_info_blocks): Adjust type of input file entry for shared libraries; write soname. (Sized_incr_dynobj::Sized_incr_dynobj): Read as_needed flag and soname from incremental info. * incremental.h (enum Incremental_input_flags): Add INCREMENTAL_INPUT_AS_NEEDED. (Incremental_input_entry::Incremental_input_entry): Initialize new data member. (Incremental_input_entry::set_as_needed): New function. (Incremental_input_entry::as_needed): New function. (Incremental_input_entry::do_dynobj_entry): New function. (Incremental_input_entry::as_needed_): New data member. (Incremental_object_entry::Incremental_object_entry): Don't check for shared library. (Incremental_object_entry::do_type): Likewise. (class Incremental_dynobj_entry): New class. (Incremental_input_entry_reader::as_needed): New function. (Incremental_input_entry_reader::get_soname): New function. (Incremental_input_entry_reader::get_global_symbol_count): Rewrite. (Incremental_input_entry_reader::get_output_symbol_index): Adjust size of shared library info entry. * layout.cc (Layout::finish_dynamic_section): Don't test for incremental link when adding DT_NEEDED entries. * object.h (Object::Object): Initialize new data member. (Object::dynobj): New function. (Object::set_as_needed): New function. (Object::as_needed): New function. (Object::do_dynobj): New function. (Object::as_needed_): New data member. --- gold/ChangeLog | 44 +++++++++++++++++++ gold/dynobj.h | 5 +++ gold/incremental-dump.cc | 4 ++ gold/incremental.cc | 66 +++++++++++++++++++++------- gold/incremental.h | 112 ++++++++++++++++++++++++++++++++++++++--------- gold/layout.cc | 4 +- gold/object.h | 27 +++++++++++- 7 files changed, 221 insertions(+), 41 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 2cdc273..67e7e9a 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,49 @@ 2011-05-24 Cary Coutant + * dynobj.h (Dynobj::do_dynobj): New function. + * incremental-dump.cc (dump_incremental_inputs): Print as_needed + flag and soname for shared objects. + * incremental.cc (Incremental_inputs::report_object): Make + either Incremental_object_entry or Incremental_dynobj_entry; add + soname to string table. + (Incremental_inputs::report_input_section): Add assertion. + (Output_section_incremental_inputs::set_final_data_size): Adjust + type of input file entry for shared libraries; adjust size of + shared library info entry. + (Output_section_incremental_inputs::write_input_files): Write + as_needed flag for shared libraries. + (Output_section_incremental_inputs::write_info_blocks): Adjust type + of input file entry for shared libraries; write soname. + (Sized_incr_dynobj::Sized_incr_dynobj): Read as_needed flag and + soname from incremental info. + * incremental.h (enum Incremental_input_flags): Add + INCREMENTAL_INPUT_AS_NEEDED. + (Incremental_input_entry::Incremental_input_entry): Initialize new + data member. + (Incremental_input_entry::set_as_needed): New function. + (Incremental_input_entry::as_needed): New function. + (Incremental_input_entry::do_dynobj_entry): New function. + (Incremental_input_entry::as_needed_): New data member. + (Incremental_object_entry::Incremental_object_entry): Don't check + for shared library. + (Incremental_object_entry::do_type): Likewise. + (class Incremental_dynobj_entry): New class. + (Incremental_input_entry_reader::as_needed): New function. + (Incremental_input_entry_reader::get_soname): New function. + (Incremental_input_entry_reader::get_global_symbol_count): Rewrite. + (Incremental_input_entry_reader::get_output_symbol_index): Adjust + size of shared library info entry. + * layout.cc (Layout::finish_dynamic_section): Don't test for + incremental link when adding DT_NEEDED entries. + * object.h (Object::Object): Initialize new data member. + (Object::dynobj): New function. + (Object::set_as_needed): New function. + (Object::as_needed): New function. + (Object::do_dynobj): New function. + (Object::as_needed_): New data member. + +2011-05-24 Cary Coutant + * incremental-dump.cc (dump_incremental_inputs): Print dynamic reloc info; adjust display of GOT entries. * incremental.cc (Sized_incremental_binary::setup_readers): Allocate diff --git a/gold/dynobj.h b/gold/dynobj.h index c96ee2c..d26b8a7 100644 --- a/gold/dynobj.h +++ b/gold/dynobj.h @@ -96,6 +96,11 @@ class Dynobj : public Object unsigned char** pphash, unsigned int* phashlen); protected: + // Return a pointer to this object. + virtual Dynobj* + do_dynobj() + { return this; } + // Set the DT_SONAME string. void set_soname_string(const char* s) diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc index c1e2530..1887db8 100644 --- a/gold/incremental-dump.cc +++ b/gold/incremental-dump.cc @@ -162,6 +162,10 @@ dump_incremental_inputs(const char* argv0, const char* filename, break; case INCREMENTAL_INPUT_SHARED_LIBRARY: printf("Shared library\n"); + printf(" As needed: %s\n", + input_file.as_needed() ? "true" : "false"); + printf(" soname: %s\n", + input_file.get_soname()); printf(" Symbol count: %d\n", input_file.get_global_symbol_count()); break; diff --git a/gold/incremental.cc b/gold/incremental.cc index d49c8a5..0a89940 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -975,28 +975,48 @@ Incremental_inputs::report_object(Object* obj, unsigned int arg_serial, arg_serial = 0; this->strtab_->add(obj->name().c_str(), false, &filename_key); - Incremental_object_entry* obj_entry = - new Incremental_object_entry(filename_key, obj, arg_serial, mtime); - if (obj->is_in_system_directory()) - obj_entry->set_is_in_system_directory(); - this->inputs_.push_back(obj_entry); - if (arch != NULL) + Incremental_input_entry* input_entry; + + this->current_object_ = obj; + + if (!obj->is_dynamic()) { - Incremental_archive_entry* arch_entry = arch->incremental_info(); - gold_assert(arch_entry != NULL); - arch_entry->add_object(obj_entry); + this->current_object_entry_ = + new Incremental_object_entry(filename_key, obj, arg_serial, mtime); + input_entry = this->current_object_entry_; + if (arch != NULL) + { + Incremental_archive_entry* arch_entry = arch->incremental_info(); + gold_assert(arch_entry != NULL); + arch_entry->add_object(this->current_object_entry_); + } } + else + { + this->current_object_entry_ = NULL; + Stringpool::Key soname_key; + Dynobj* dynobj = obj->dynobj(); + gold_assert(dynobj != NULL); + this->strtab_->add(dynobj->soname(), false, &soname_key); + input_entry = new Incremental_dynobj_entry(filename_key, soname_key, obj, + arg_serial, mtime); + } + + if (obj->is_in_system_directory()) + input_entry->set_is_in_system_directory(); + + if (obj->as_needed()) + input_entry->set_as_needed(); + + this->inputs_.push_back(input_entry); if (script_info != NULL) { Incremental_script_entry* script_entry = script_info->incremental_info(); gold_assert(script_entry != NULL); - script_entry->add_object(obj_entry); + script_entry->add_object(input_entry); } - - this->current_object_ = obj; - this->current_object_entry_ = obj_entry; } // Record the input object file OBJ. If ARCH is not NULL, attach @@ -1013,6 +1033,7 @@ Incremental_inputs::report_input_section(Object* obj, unsigned int shndx, this->strtab_->add(name, true, &key); gold_assert(obj == this->current_object_); + gold_assert(this->current_object_entry_ != NULL); this->current_object_entry_->add_input_section(shndx, key, sh_size); } @@ -1155,11 +1176,11 @@ Output_section_incremental_inputs::set_final_data_size() break; case INCREMENTAL_INPUT_SHARED_LIBRARY: { - Incremental_object_entry* entry = (*p)->object_entry(); + Incremental_dynobj_entry* entry = (*p)->dynobj_entry(); gold_assert(entry != NULL); (*p)->set_info_offset(info_offset); - // Global symbol count. - info_offset += 4; + // Global symbol count, soname index. + info_offset += 8; // Each global symbol. const Object::Symbols* syms = entry->object()->get_global_symbols(); gold_assert(syms != NULL); @@ -1321,6 +1342,8 @@ Output_section_incremental_inputs::write_input_files( unsigned int flags = (*p)->type(); if ((*p)->is_in_system_directory()) flags |= INCREMENTAL_INPUT_IN_SYSTEM_DIR; + if ((*p)->as_needed()) + flags |= INCREMENTAL_INPUT_AS_NEEDED; Swap32::writeval(pov, filename_offset); Swap32::writeval(pov + 4, (*p)->get_info_offset()); Swap64::writeval(pov + 8, mtime.seconds); @@ -1483,11 +1506,17 @@ Output_section_incremental_inputs::write_info_blocks( { gold_assert(static_cast(pov - oview) == (*p)->get_info_offset()); - Incremental_object_entry* entry = (*p)->object_entry(); + Incremental_dynobj_entry* entry = (*p)->dynobj_entry(); gold_assert(entry != NULL); const Object* obj = entry->object(); const Object::Symbols* syms = obj->get_global_symbols(); + // Write the soname string table index. + section_offset_type soname_offset = + strtab->get_offset_from_key(entry->get_soname_key()); + Swap32::writeval(pov, soname_offset); + pov += 4; + // Skip the global symbol count for now. unsigned char* orig_pov = pov; pov += 4; @@ -2347,6 +2376,9 @@ Sized_incr_dynobj::Sized_incr_dynobj( { if (this->input_reader_.is_in_system_directory()) this->set_is_in_system_directory(); + if (this->input_reader_.as_needed()) + this->set_as_needed(); + this->set_soname_string(this->input_reader_.get_soname()); this->set_shnum(0); } diff --git a/gold/incremental.h b/gold/incremental.h index 3935186..dc8ef33 100644 --- a/gold/incremental.h +++ b/gold/incremental.h @@ -40,6 +40,7 @@ class Input_argument; class Incremental_inputs_checker; class Incremental_script_entry; class Incremental_object_entry; +class Incremental_dynobj_entry; class Incremental_archive_entry; class Incremental_inputs; class Incremental_binary; @@ -63,7 +64,8 @@ enum Incremental_input_type enum Incremental_input_flags { - INCREMENTAL_INPUT_IN_SYSTEM_DIR = 0x0800 + INCREMENTAL_INPUT_IN_SYSTEM_DIR = 0x8000, + INCREMENTAL_INPUT_AS_NEEDED = 0x4000 }; // Create an Incremental_binary object for FILE. Returns NULL is this is not @@ -80,7 +82,8 @@ class Incremental_input_entry Incremental_input_entry(Stringpool::Key filename_key, unsigned int arg_serial, Timespec mtime) : filename_key_(filename_key), file_index_(0), offset_(0), info_offset_(0), - arg_serial_(arg_serial), mtime_(mtime), is_in_system_directory_(false) + arg_serial_(arg_serial), mtime_(mtime), is_in_system_directory_(false), + as_needed_(false) { } virtual @@ -145,6 +148,16 @@ class Incremental_input_entry is_in_system_directory() const { return this->is_in_system_directory_; } + // Record that the file was linked with --as-needed. + void + set_as_needed() + { this->as_needed_ = true; } + + // Return TRUE if the file was linked with --as-needed. + bool + as_needed() const + { return this->as_needed_; } + // Return a pointer to the derived Incremental_script_entry object. // Return NULL for input entries that are not script files. Incremental_script_entry* @@ -157,6 +170,12 @@ class Incremental_input_entry object_entry() { return this->do_object_entry(); } + // Return a pointer to the derived Incremental_dynobj_entry object. + // Return NULL for input entries that are not shared object files. + Incremental_dynobj_entry* + dynobj_entry() + { return this->do_dynobj_entry(); } + // Return a pointer to the derived Incremental_archive_entry object. // Return NULL for input entries that are not archive files. Incremental_archive_entry* @@ -180,6 +199,12 @@ class Incremental_input_entry do_object_entry() { return NULL; } + // Return a pointer to the derived Incremental_dynobj_entry object. + // Return NULL for input entries that are not shared object files. + virtual Incremental_dynobj_entry* + do_dynobj_entry() + { return NULL; } + // Return a pointer to the derived Incremental_archive_entry object. // Return NULL for input entries that are not archive files. virtual Incremental_archive_entry* @@ -207,6 +232,9 @@ class Incremental_input_entry // TRUE if the file was found in a system directory. bool is_in_system_directory_; + + // TRUE if the file was linked with --as-needed. + bool as_needed_; }; // Information about a script input that will persist during the whole linker @@ -298,10 +326,7 @@ class Incremental_object_entry : public Incremental_input_entry unsigned int arg_serial, Timespec mtime) : Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj), is_member_(false), sections_() - { - if (!obj_->is_dynamic()) - this->sections_.reserve(obj->shnum()); - } + { this->sections_.reserve(obj->shnum()); } // Get the object. Object* @@ -349,9 +374,7 @@ class Incremental_object_entry : public Incremental_input_entry { return (this->is_member_ ? INCREMENTAL_INPUT_ARCHIVE_MEMBER - : (this->obj_->is_dynamic() - ? INCREMENTAL_INPUT_SHARED_LIBRARY - : INCREMENTAL_INPUT_OBJECT)); + : INCREMENTAL_INPUT_OBJECT); } // Return a pointer to the derived Incremental_object_entry object. @@ -379,6 +402,46 @@ class Incremental_object_entry : public Incremental_input_entry std::vector sections_; }; +// Class for recording shared library input files. + +class Incremental_dynobj_entry : public Incremental_input_entry +{ + public: + Incremental_dynobj_entry(Stringpool::Key filename_key, + Stringpool::Key soname_key, Object* obj, + unsigned int arg_serial, Timespec mtime) + : Incremental_input_entry(filename_key, arg_serial, mtime), + soname_key_(soname_key), obj_(obj) + { } + + // Get the object. + Object* + object() const + { return this->obj_; } + + // Get the stringpool key for the soname. + Stringpool::Key + get_soname_key() const + { return this->soname_key_; } + + protected: + virtual Incremental_input_type + do_type() const + { return INCREMENTAL_INPUT_SHARED_LIBRARY; } + + // Return a pointer to the derived Incremental_dynobj_entry object. + virtual Incremental_dynobj_entry* + do_dynobj_entry() + { return this; } + + private: + // Key of the soname string in the section stringtable. + Stringpool::Key soname_key_; + + // The object file itself. + Object* obj_; +}; + // Class for recording archive library input files. class Incremental_archive_entry : public Incremental_input_entry @@ -718,6 +781,11 @@ class Incremental_inputs_reader is_in_system_directory() const { return (this->flags_ & INCREMENTAL_INPUT_IN_SYSTEM_DIR) != 0; } + // Return TRUE if the file was linked with --as-needed. + bool + as_needed() const + { return (this->flags_ & INCREMENTAL_INPUT_AS_NEEDED) != 0; } + // Return the input section count -- for objects only. unsigned int get_input_section_count() const @@ -727,6 +795,16 @@ class Incremental_inputs_reader return Swap32::readval(this->inputs_->p_ + this->info_offset_); } + // Return the soname -- for shared libraries only. + const char* + get_soname() const + { + gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY); + unsigned int offset = Swap32::readval(this->inputs_->p_ + + this->info_offset_); + return this->inputs_->get_string(offset); + } + // Return the offset of the supplemental info for symbol SYMNDX -- // for objects only. unsigned int @@ -745,16 +823,10 @@ class Incremental_inputs_reader unsigned int get_global_symbol_count() const { - switch (this->type()) - { - case INCREMENTAL_INPUT_OBJECT: - case INCREMENTAL_INPUT_ARCHIVE_MEMBER: - return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 4); - case INCREMENTAL_INPUT_SHARED_LIBRARY: - return Swap32::readval(this->inputs_->p_ + this->info_offset_); - default: - gold_unreachable(); - } + gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT + || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER + || this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY); + return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 4); } // Return the offset of the first local symbol -- for objects only. @@ -899,7 +971,7 @@ class Incremental_inputs_reader { gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY); const unsigned char* p = (this->inputs_->p_ - + this->info_offset_ + 4 + + this->info_offset_ + 8 + n * 4); unsigned int output_symndx = Swap32::readval(p); *is_def = (output_symndx & (1U << 31)) != 0; diff --git a/gold/layout.cc b/gold/layout.cc index d4b9f18..356a664 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -3986,9 +3986,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, p != input_objects->dynobj_end(); ++p) { - if (!(*p)->is_needed() - && !(*p)->is_incremental() - && (*p)->input_file()->options().as_needed()) + if (!(*p)->is_needed() && (*p)->as_needed()) { // This dynamic object was linked with --as-needed, but it // is not needed. diff --git a/gold/object.h b/gold/object.h index d9be4b5..1031833 100644 --- a/gold/object.h +++ b/gold/object.h @@ -332,12 +332,13 @@ class Object : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U), is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false), has_no_split_stack_(false), no_export_(false), - is_in_system_directory_(false), xindex_(NULL) + is_in_system_directory_(false), as_needed_(false), xindex_(NULL) { if (input_file != NULL) { input_file->file().add_object(); this->is_in_system_directory_ = input_file->is_in_system_directory(); + this->as_needed_ = input_file->options().as_needed(); } } @@ -386,6 +387,12 @@ class Object has_no_split_stack() const { return this->has_no_split_stack_; } + // Returns NULL for Objects that are not dynamic objects. This method + // is overridden in the Dynobj class. + Dynobj* + dynobj() + { return this->do_dynobj(); } + // Returns NULL for Objects that are not plugin objects. This method // is overridden in the Pluginobj class. Pluginobj* @@ -688,6 +695,16 @@ class Object is_in_system_directory() const { return this->is_in_system_directory_; } + // Set flag that this object was linked with --as-needed. + void + set_as_needed() + { this->as_needed_ = true; } + + // Return whether this object was linked with --as-needed. + bool + as_needed() const + { return this->as_needed_; } + // Return whether we found this object by searching a directory. bool searched_for() const @@ -719,6 +736,12 @@ class Object { return this->do_get_incremental_reloc_count(symndx); } protected: + // Returns NULL for Objects that are not dynamic objects. This method + // is overridden in the Dynobj class. + virtual Dynobj* + do_dynobj() + { return NULL; } + // Returns NULL for Objects that are not plugin objects. This method // is overridden in the Pluginobj class. virtual Pluginobj* @@ -911,6 +934,8 @@ class Object bool no_export_ : 1; // True if the object was found in a system directory. bool is_in_system_directory_ : 1; + // True if the object was linked with --as-needed. + bool as_needed_ : 1; // Many sections for objects with more than SHN_LORESERVE sections. Xindex* xindex_; }; -- cgit v1.1