diff options
author | Ian Lance Taylor <iant@google.com> | 2006-12-01 16:51:25 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2006-12-01 16:51:25 +0000 |
commit | 16649710df23ad9038e0057035882a92e783f7e6 (patch) | |
tree | 7d4db6bb5578f6c90193108bc525a39f09ab379d /gold | |
parent | 8a82f7e3921015b4cbadf29379d8af9d9f6af891 (diff) | |
download | binutils-gdb-16649710df23ad9038e0057035882a92e783f7e6.tar.gz |
Can now dynamically link hello, world.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/gold.cc | 7 | ||||
-rw-r--r-- | gold/i386.cc | 77 | ||||
-rw-r--r-- | gold/layout.cc | 77 | ||||
-rw-r--r-- | gold/layout.h | 50 | ||||
-rw-r--r-- | gold/output.cc | 121 | ||||
-rw-r--r-- | gold/output.h | 149 | ||||
-rw-r--r-- | gold/po/gold.pot | 40 | ||||
-rw-r--r-- | gold/reloc.cc | 2 | ||||
-rw-r--r-- | gold/resolve.cc | 4 | ||||
-rw-r--r-- | gold/symtab.cc | 141 | ||||
-rw-r--r-- | gold/symtab.h | 51 | ||||
-rw-r--r-- | gold/target.h | 6 |
12 files changed, 541 insertions, 184 deletions
diff --git a/gold/gold.cc b/gold/gold.cc index 5051a13a6aa..e7b7ae2939d 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -217,8 +217,11 @@ queue_final_tasks(const General_options& options, // Queue a task to write out the symbol table. final_blocker->add_blocker(); - workqueue->queue(new Write_symbols_task(symtab, input_objects->target(), - layout->sympool(), of, + workqueue->queue(new Write_symbols_task(symtab, + input_objects->target(), + layout->sympool(), + layout->dynpool(), + of, final_blocker)); // Queue a task to write out everything else. diff --git a/gold/i386.cc b/gold/i386.cc index 4cf90e99f9e..ee3654c5a05 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -51,7 +51,7 @@ class Target_i386 : public Sized_target<32, false> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(const General_options*, Layout*); // Relocate a section. void @@ -231,7 +231,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab, this->got_ = new Output_data_got<32, false>(options); layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, this->got_); + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->got_); // The old GNU linker creates a .got.plt section. We just // create another set of data in the .got section. Note that we @@ -239,7 +240,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab, // might be empty. this->got_plt_ = new Output_data_space(4); layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, this->got_plt_); + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->got_plt_); // The first three entries are reserved. this->got_plt_->set_space_size(3 * 4); @@ -248,7 +250,7 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab, symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_", this->got_plt_, 0, 0, elfcpp::STT_OBJECT, - elfcpp::STB_GLOBAL, + elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN, 0, false, false); } @@ -284,6 +286,15 @@ class Output_data_plt_i386 : public Output_section_data void add_entry(Symbol* gsym); + // Return the .rel.plt section data. + const Reloc_section* + rel_plt() const + { return this->rel_; } + + protected: + void + do_adjust_output_section(Output_section* os); + private: // The size of an entry in the PLT. static const int plt_entry_size = 16; @@ -333,6 +344,16 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout, elfcpp::SHF_ALLOC, this->rel_); } +// For some reason + +void +Output_data_plt_i386::do_adjust_output_section(Output_section* os) +{ + // UnixWare sets the entsize of .plt to 4, and so does the old GNU + // linker, and so do we. + os->set_entsize(4); +} + // Add an entry to the PLT. void @@ -354,6 +375,7 @@ Output_data_plt_i386::add_entry(Symbol* gsym) this->got_plt_->set_space_size(got_offset + 4); // Every PLT entry needs a reloc. + gsym->set_needs_dynsym_entry(); this->rel_->add_global(gsym, elfcpp::R_386_JUMP_SLOT, this->got_plt_, got_offset); @@ -503,6 +525,10 @@ Target_i386::make_plt_entry(const General_options* options, this->plt_ = new Output_data_plt_i386(layout, this->got_plt_, options->is_shared()); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR), + this->plt_); } this->plt_->add_entry(gsym); @@ -587,6 +613,7 @@ Target_i386::copy_reloc(const General_options* options, false, false); // Add the COPY reloc. + ssym->set_needs_dynsym_entry(); Reloc_section* rel_dyn = this->rel_dyn_section(layout); rel_dyn->add_global(ssym, elfcpp::R_386_COPY, dynbss, offset); } @@ -940,12 +967,46 @@ Target_i386::scan_relocs(const General_options& options, global_symbols); } -// Finalize the sections. This is where we emit any relocs we saved -// in an attempt to avoid generating extra COPY relocs. +// Finalize the sections. void -Target_i386::do_finalize_sections(Layout* layout) +Target_i386::do_finalize_sections(const General_options* options, + Layout* layout) { + // Fill in some more dynamic tags. + Output_data_dynamic* const odyn = layout->dynamic_data(); + if (odyn != NULL) + { + if (this->got_plt_ != NULL) + odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); + + if (this->plt_ != NULL) + { + const Output_data* od = this->plt_->rel_plt(); + odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); + odyn->add_section_address(elfcpp::DT_JMPREL, od); + odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); + } + + if (this->rel_dyn_ != NULL) + { + const Output_data* od = this->rel_dyn_; + odyn->add_section_address(elfcpp::DT_REL, od); + odyn->add_section_size(elfcpp::DT_RELSZ, od); + odyn->add_constant(elfcpp::DT_RELENT, + elfcpp::Elf_sizes<32>::rel_size); + } + + if (!options->is_shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } + } + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. if (this->copy_relocs_ == NULL) return; if (this->copy_relocs_->any_to_emit()) @@ -992,7 +1053,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, if (gsym != NULL && gsym->is_defined_in_dynobj()) { if (gsym->has_plt_offset()) - address = target->plt_section()->address() + gsym->plt_offset(); + value = target->plt_section()->address() + gsym->plt_offset(); else gold_unreachable(); } diff --git a/gold/layout.cc b/gold/layout.cc index 0de42c2f758..f424bb4438e 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -42,7 +42,8 @@ Layout::Layout(const General_options& options) : options_(options), namepool_(), sympool_(), dynpool_(), signatures_(), section_name_map_(), segment_list_(), section_list_(), unattached_section_list_(), special_output_list_(), - tls_segment_(NULL), symtab_section_(NULL), dynsym_section_(NULL) + tls_segment_(NULL), symtab_section_(NULL), dynsym_section_(NULL), + dynamic_section_(NULL), dynamic_data_(NULL) { // Make space for more than enough segments for a typical file. // This is just for efficiency--it's OK if we wind up needing more. @@ -325,6 +326,11 @@ Layout::create_initial_dynamic_sections(const Input_objects* input_objects, this->dynamic_section_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN, 0, false, false); + + this->dynamic_data_ = new Output_data_dynamic(input_objects->target(), + &this->dynpool_); + + this->dynamic_section_->add_output_section_data(this->dynamic_data_); } // Find the first read-only PT_LOAD segment, creating one if @@ -386,7 +392,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab) Target* const target = input_objects->target(); const int size = target->get_size(); - target->finalize_sections(this); + target->finalize_sections(&this->options_, this); Output_segment* phdr_seg = NULL; if (input_objects->any_dynamic()) @@ -399,14 +405,9 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab) phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R); this->segment_list_.push_back(phdr_seg); - // This holds the dynamic tags. - Output_data_dynamic* odyn; - odyn = new Output_data_dynamic(input_objects->target(), - &this->dynpool_); - // Create the dynamic symbol table, including the hash table, // the dynamic relocations, and the version sections. - this->create_dynamic_symtab(target, odyn, symtab); + this->create_dynamic_symtab(target, symtab); // Create the .interp section to hold the name of the // interpreter, and put it in a PT_INTERP segment. @@ -414,7 +415,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab) // Finish the .dynamic section to hold the dynamic data, and put // it in a PT_DYNAMIC segment. - this->finish_dynamic_section(input_objects, symtab, odyn); + this->finish_dynamic_section(input_objects, symtab); } // FIXME: Handle PT_GNU_STACK. @@ -452,9 +453,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab) // Create the symbol table sections. // FIXME: We don't need to do this if we are stripping symbols. - Output_section* ostrtab; - this->create_symtab_sections(size, input_objects, symtab, &off, - &ostrtab); + this->create_symtab_sections(size, input_objects, symtab, &off); // Create the .shstrtab section. Output_section* shstrtab_section = this->create_shstrtab(); @@ -463,9 +462,6 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab) // segments. off = this->set_section_offsets(off, &shndx); - // Now the section index of OSTRTAB is set. - this->symtab_section_->set_link(ostrtab->out_shndx()); - // Create the section table header. Output_section_headers* oshdrs = this->create_shdrs(size, big_endian, &off); @@ -685,8 +681,7 @@ Layout::set_section_offsets(off_t off, unsigned int* pshndx) void Layout::create_symtab_sections(int size, const Input_objects* input_objects, Symbol_table* symtab, - off_t* poff, - Output_section** postrtab) + off_t* poff) { int symsize; unsigned int align; @@ -742,7 +737,27 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects, unsigned int local_symcount = local_symbol_index; gold_assert(local_symcount * symsize == off - startoff); - off = symtab->finalize(local_symcount, off, &this->sympool_); + off_t dynoff; + size_t dyn_global_index; + size_t dyncount; + if (this->dynsym_section_ == NULL) + { + dynoff = 0; + dyn_global_index = 0; + dyncount = 0; + } + else + { + dyn_global_index = this->dynsym_section_->info(); + off_t locsize = dyn_global_index * this->dynsym_section_->entsize(); + dynoff = this->dynsym_section_->offset() + locsize; + dyncount = (this->dynsym_section_->data_size() - locsize) / symsize; + gold_assert(dyncount * symsize + == this->dynsym_section_->data_size() - locsize); + } + + off = symtab->finalize(local_symcount, off, dynoff, dyn_global_index, + dyncount, &this->sympool_); this->sympool_.set_string_offsets(); @@ -765,11 +780,11 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects, ostrtab->add_output_section_data(pstr); osymtab->set_address(0, startoff); + osymtab->set_link_section(ostrtab); osymtab->set_info(local_symcount); osymtab->set_entsize(symsize); *poff = off; - *postrtab = ostrtab; } // Create the .shstrtab section, which holds the names of the @@ -801,8 +816,9 @@ Output_section_headers* Layout::create_shdrs(int size, bool big_endian, off_t* poff) { Output_section_headers* oshdrs; - oshdrs = new Output_section_headers(size, big_endian, this->segment_list_, - this->unattached_section_list_, + oshdrs = new Output_section_headers(size, big_endian, this, + &this->segment_list_, + &this->unattached_section_list_, &this->namepool_); off_t off = align_address(*poff, oshdrs->addralign()); oshdrs->set_address(0, off); @@ -815,8 +831,7 @@ Layout::create_shdrs(int size, bool big_endian, off_t* poff) // Create the dynamic symbol table. void -Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn, - Symbol_table* symtab) +Layout::create_dynamic_symtab(const Target* target, Symbol_table* symtab) { // Count all the symbols in the dynamic symbol table, and set the // dynamic symbol indexes. @@ -883,6 +898,7 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn, this->dynsym_section_ = dynsym; + Output_data_dynamic* const odyn = this->dynamic_data_; odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym); odyn->add_constant(elfcpp::DT_SYMENT, symsize); @@ -894,6 +910,9 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn, Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); dynstr->add_output_section_data(strdata); + dynsym->set_link_section(dynstr); + this->dynamic_section_->set_link_section(dynstr); + odyn->add_section_address(elfcpp::DT_STRTAB, dynstr); odyn->add_section_size(elfcpp::DT_STRSZ, dynstr); @@ -914,8 +933,8 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn, align); hashsec->add_output_section_data(hashdata); + hashsec->set_link_section(dynsym); hashsec->set_entsize(4); - // FIXME: .hash should link to .dynsym. odyn->add_section_address(elfcpp::DT_HASH, hashsec); } @@ -951,17 +970,16 @@ Layout::create_interp(const Target* target) void Layout::finish_dynamic_section(const Input_objects* input_objects, - const Symbol_table* symtab, - Output_data_dynamic* odyn) + const Symbol_table* symtab) { - this->dynamic_section_->add_output_section_data(odyn); - Output_segment* oseg = new Output_segment(elfcpp::PT_DYNAMIC, elfcpp::PF_R | elfcpp::PF_W); this->segment_list_.push_back(oseg); oseg->add_initial_output_section(this->dynamic_section_, elfcpp::PF_R | elfcpp::PF_W); + Output_data_dynamic* const odyn = this->dynamic_data_; + for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin(); p != input_objects->dynobj_end(); ++p) @@ -1231,7 +1249,8 @@ Write_symbols_task::locks(Workqueue* workqueue) void Write_symbols_task::run(Workqueue*) { - this->symtab_->write_globals(this->target_, this->sympool_, this->of_); + this->symtab_->write_globals(this->target_, this->sympool_, this->dynpool_, + this->of_); } // Close_task_runner methods. diff --git a/gold/layout.h b/gold/layout.h index 26948bb356f..4c54e005554 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -89,6 +89,12 @@ class Layout sympool() const { return &this->sympool_; } + // Return the Stringpool used for dynamic symbol names and dynamic + // tags. + const Stringpool* + dynpool() const + { return &this->dynpool_; } + // Return whether a section is a .gnu.linkonce section, given the // section name. static inline bool @@ -106,11 +112,33 @@ class Layout off_t finalize(const Input_objects*, Symbol_table*); - // Return the TLS segment. + // Return the TLS segment. This will return NULL if there isn't + // one. Output_segment* tls_segment() const { return this->tls_segment_; } + // Return the normal symbol table. + Output_section* + symtab_section() const + { + gold_assert(this->symtab_section_ != NULL); + return this->symtab_section_; + } + + // Return the dynamic symbol table. + Output_section* + dynsym_section() const + { + gold_assert(this->dynsym_section_ != NULL); + return this->dynsym_section_; + } + + // Return the dynamic tags. + Output_data_dynamic* + dynamic_data() const + { return this->dynamic_data_; } + // Write out data not associated with an input file or the symbol // table. void @@ -160,8 +188,8 @@ class Layout // Create the output sections for the symbol table. void - create_symtab_sections(int size, const Input_objects*, Symbol_table*, off_t*, - Output_section** ostrtab); + create_symtab_sections(int size, const Input_objects*, Symbol_table*, + off_t*); // Create the .shstrtab section. Output_section* @@ -173,12 +201,11 @@ class Layout // Create the dynamic symbol table. void - create_dynamic_symtab(const Target*, Output_data_dynamic*, Symbol_table*); + create_dynamic_symtab(const Target*, Symbol_table*); // Finish the .dynamic section and PT_DYNAMIC segment. void - finish_dynamic_section(const Input_objects*, const Symbol_table*, - Output_data_dynamic*); + finish_dynamic_section(const Input_objects*, const Symbol_table*); // Create the .interp section and PT_INTERP segment. void @@ -284,6 +311,8 @@ class Layout Output_section* dynsym_section_; // The SHT_DYNAMIC output section if there is one. Output_section* dynamic_section_; + // The dynamic data which goes into dynamic_section_. + Output_data_dynamic* dynamic_data_; }; // This task handles writing out data which is not part of a section @@ -324,10 +353,10 @@ class Write_symbols_task : public Task { public: Write_symbols_task(const Symbol_table* symtab, const Target* target, - const Stringpool* sympool, Output_file* of, - Task_token* final_blocker) - : symtab_(symtab), target_(target), sympool_(sympool), of_(of), - final_blocker_(final_blocker) + const Stringpool* sympool, const Stringpool* dynpool, + Output_file* of, Task_token* final_blocker) + : symtab_(symtab), target_(target), sympool_(sympool), dynpool_(dynpool), + of_(of), final_blocker_(final_blocker) { } // The standard Task methods. @@ -345,6 +374,7 @@ class Write_symbols_task : public Task const Symbol_table* symtab_; const Target* target_; const Stringpool* sympool_; + const Stringpool* dynpool_; Output_file* of_; Task_token* final_blocker_; }; diff --git a/gold/output.cc b/gold/output.cc index 14938472751..f0d7985732d 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -58,23 +58,25 @@ Output_data::default_alignment(int size) Output_section_headers::Output_section_headers( int size, bool big_endian, - const Layout::Segment_list& segment_list, - const Layout::Section_list& unattached_section_list, + const Layout* layout, + const Layout::Segment_list* segment_list, + const Layout::Section_list* unattached_section_list, const Stringpool* secnamepool) : size_(size), big_endian_(big_endian), + layout_(layout), segment_list_(segment_list), unattached_section_list_(unattached_section_list), secnamepool_(secnamepool) { // Count all the sections. Start with 1 for the null section. off_t count = 1; - for (Layout::Segment_list::const_iterator p = segment_list.begin(); - p != segment_list.end(); + for (Layout::Segment_list::const_iterator p = segment_list->begin(); + p != segment_list->end(); ++p) if ((*p)->type() == elfcpp::PT_LOAD) count += (*p)->output_section_count(); - count += unattached_section_list.size(); + count += unattached_section_list->size(); int shdr_size; if (size == 32) @@ -137,20 +139,20 @@ Output_section_headers::do_sized_write(Output_file* of) v += shdr_size; unsigned shndx = 1; - for (Layout::Segment_list::const_iterator p = this->segment_list_.begin(); - p != this->segment_list_.end(); + for (Layout::Segment_list::const_iterator p = this->segment_list_->begin(); + p != this->segment_list_->end(); ++p) v = (*p)->write_section_headers SELECT_SIZE_ENDIAN_NAME(size, big_endian) ( - this->secnamepool_, v, &shndx + this->layout_, this->secnamepool_, v, &shndx SELECT_SIZE_ENDIAN(size, big_endian)); for (Layout::Section_list::const_iterator p = - this->unattached_section_list_.begin(); - p != this->unattached_section_list_.end(); + this->unattached_section_list_->begin(); + p != this->unattached_section_list_->end(); ++p) { gold_assert(shndx == (*p)->out_shndx()); elfcpp::Shdr_write<size, big_endian> oshdr(v); - (*p)->write_header(this->secnamepool_, &oshdr); + (*p)->write_header(this->layout_, this->secnamepool_, &oshdr); v += shdr_size; ++shndx; } @@ -372,6 +374,18 @@ Output_data_const_buffer::do_write(Output_file* of) // Output_section_data methods. +// Record the output section, and set the entry size and such. + +void +Output_section_data::set_output_section(Output_section* os) +{ + gold_assert(this->output_section_ == NULL); + this->output_section_ = os; + this->do_adjust_output_section(os); +} + +// Return the section index of the output section. + unsigned int Output_section_data::do_out_shndx() const { @@ -496,6 +510,25 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write( // Output_data_reloc_base methods. +// Adjust the output section. + +template<int sh_type, bool dynamic, int size, bool big_endian> +void +Output_data_reloc_base<sh_type, dynamic, size, big_endian> + ::do_adjust_output_section(Output_section* os) +{ + if (sh_type == elfcpp::SHT_REL) + os->set_entsize(elfcpp::Elf_sizes<size>::rel_size); + else if (sh_type == elfcpp::SHT_RELA) + os->set_entsize(elfcpp::Elf_sizes<size>::rela_size); + else + gold_unreachable(); + if (dynamic) + os->set_should_link_to_dynsym(); + else + os->set_should_link_to_symtab(); +} + // Write out relocation data. template<int sh_type, bool dynamic, int size, bool big_endian> @@ -636,16 +669,17 @@ Output_data_dynamic::Dynamic_entry::write( break; case DYNAMIC_SECTION_ADDRESS: - val = this->u_.os->address(); + val = this->u_.od->address(); break; case DYNAMIC_SECTION_SIZE: - val = this->u_.os->data_size(); + val = this->u_.od->data_size(); break; case DYNAMIC_SYMBOL: { - Sized_symbol<size>* s = static_cast<Sized_symbol<size>*>(this->u_.sym); + const Sized_symbol<size>* s = + static_cast<const Sized_symbol<size>*>(this->u_.sym); val = s->value(); } break; @@ -665,6 +699,19 @@ Output_data_dynamic::Dynamic_entry::write( // Output_data_dynamic methods. +// Adjust the output section to set the entry size. + +void +Output_data_dynamic::do_adjust_output_section(Output_section* os) +{ + if (this->target_->get_size() == 32) + os->set_entsize(elfcpp::Elf_sizes<32>::dyn_size); + else if (this->target_->get_size() == 64) + os->set_entsize(elfcpp::Elf_sizes<64>::dyn_size); + else + gold_unreachable(); +} + // Set the final data size. void @@ -780,7 +827,9 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, : name_(name), addralign_(0), entsize_(0), + link_section_(NULL), link_(0), + info_section_(NULL), info_(0), type_(type), flags_(flags), @@ -791,7 +840,9 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, first_input_offset_(0), may_add_data_(may_add_data), needs_symtab_index_(false), - needs_dynsym_index_(false) + needs_dynsym_index_(false), + should_link_to_symtab_(false), + should_link_to_dynsym_(false) { } @@ -799,6 +850,17 @@ Output_section::~Output_section() { } +// Set the entry size. + +void +Output_section::set_entsize(uint64_t v) +{ + if (this->entsize_ == 0) + this->entsize_ = v; + else + gold_assert(this->entsize_ == v); +} + // Add the input section SHNDX, with header SHDR, named SECNAME, in // OBJECT, to the Output_section. Return the offset of the input // section within the output section. We don't always keep track of @@ -885,7 +947,8 @@ Output_section::do_set_address(uint64_t address, off_t startoff) template<int size, bool big_endian> void -Output_section::write_header(const Stringpool* secnamepool, +Output_section::write_header(const Layout* layout, + const Stringpool* secnamepool, elfcpp::Shdr_write<size, big_endian>* oshdr) const { oshdr->put_sh_name(secnamepool->get_offset(this->name_)); @@ -894,8 +957,18 @@ Output_section::write_header(const Stringpool* secnamepool, oshdr->put_sh_addr(this->address()); oshdr->put_sh_offset(this->offset()); oshdr->put_sh_size(this->data_size()); - oshdr->put_sh_link(this->link_); - oshdr->put_sh_info(this->info_); + if (this->link_section_ != NULL) + oshdr->put_sh_link(this->link_section_->out_shndx()); + else if (this->should_link_to_symtab_) + oshdr->put_sh_link(layout->symtab_section()->out_shndx()); + else if (this->should_link_to_dynsym_) + oshdr->put_sh_link(layout->dynsym_section()->out_shndx()); + else + oshdr->put_sh_link(this->link_); + if (this->info_section_ != NULL) + oshdr->put_sh_info(this->info_section_->out_shndx()); + else + oshdr->put_sh_info(this->info_); oshdr->put_sh_addralign(this->addralign_); oshdr->put_sh_entsize(this->entsize_); } @@ -1245,7 +1318,8 @@ Output_segment::write_header(elfcpp::Phdr_write<size, big_endian>* ophdr) template<int size, bool big_endian> unsigned char* -Output_segment::write_section_headers(const Stringpool* secnamepool, +Output_segment::write_section_headers(const Layout* layout, + const Stringpool* secnamepool, unsigned char* v, unsigned int *pshndx ACCEPT_SIZE_ENDIAN) const @@ -1258,18 +1332,19 @@ Output_segment::write_section_headers(const Stringpool* secnamepool, v = this->write_section_headers_list SELECT_SIZE_ENDIAN_NAME(size, big_endian) ( - secnamepool, &this->output_data_, v, pshndx + layout, secnamepool, &this->output_data_, v, pshndx SELECT_SIZE_ENDIAN(size, big_endian)); v = this->write_section_headers_list SELECT_SIZE_ENDIAN_NAME(size, big_endian) ( - secnamepool, &this->output_bss_, v, pshndx + layout, secnamepool, &this->output_bss_, v, pshndx SELECT_SIZE_ENDIAN(size, big_endian)); return v; } template<int size, bool big_endian> unsigned char* -Output_segment::write_section_headers_list(const Stringpool* secnamepool, +Output_segment::write_section_headers_list(const Layout* layout, + const Stringpool* secnamepool, const Output_data_list* pdl, unsigned char* v, unsigned int* pshndx @@ -1285,7 +1360,7 @@ Output_segment::write_section_headers_list(const Stringpool* secnamepool, const Output_section* ps = static_cast<const Output_section*>(*p); gold_assert(*pshndx == ps->out_shndx()); elfcpp::Shdr_write<size, big_endian> oshdr(v); - ps->write_header(secnamepool, &oshdr); + ps->write_header(layout, secnamepool, &oshdr); v += shdr_size; ++*pshndx; } diff --git a/gold/output.h b/gold/output.h index f7efdba55dc..ceea87729f4 100644 --- a/gold/output.h +++ b/gold/output.h @@ -185,8 +185,9 @@ class Output_section_headers : public Output_data public: Output_section_headers(int size, bool big_endian, - const Layout::Segment_list&, - const Layout::Section_list&, + const Layout*, + const Layout::Segment_list*, + const Layout::Section_list*, const Stringpool*); // Write the data to the file. @@ -206,8 +207,9 @@ class Output_section_headers : public Output_data int size_; bool big_endian_; - const Layout::Segment_list& segment_list_; - const Layout::Section_list& unattached_section_list_; + const Layout* layout_; + const Layout::Segment_list* segment_list_; + const Layout::Section_list* unattached_section_list_; const Stringpool* secnamepool_; }; @@ -303,17 +305,24 @@ class Output_section_data : public Output_data : Output_data(0), output_section_(NULL), addralign_(addralign) { } + // Return the output section. + const Output_section* + output_section() const + { return this->output_section_; } + // Record the output section. void - set_output_section(Output_section* os) - { - gold_assert(this->output_section_ == NULL); - this->output_section_ = os; - } + set_output_section(Output_section* os); protected: // The child class must implement do_write. + // The child class may implement specific adjustments to the output + // section. + virtual void + do_adjust_output_section(Output_section*) + { } + // Return the required alignment. uint64_t do_addralign() const @@ -695,6 +704,10 @@ class Output_data_reloc_base : public Output_section_data do_write(Output_file*); protected: + // Set the entry size and the link. + void + do_adjust_output_section(Output_section *os); + // Add a relocation entry. void add(const Output_reloc_type& reloc) @@ -975,19 +988,19 @@ class Output_data_dynamic : public Output_section_data add_constant(elfcpp::DT tag, unsigned int val) { this->add_entry(Dynamic_entry(tag, val)); } - // Add a new dynamic entry with the address of a section. + // Add a new dynamic entry with the address of output data. void - add_section_address(elfcpp::DT tag, Output_section* os) - { this->add_entry(Dynamic_entry(tag, os, false)); } + add_section_address(elfcpp::DT tag, const Output_data* od) + { this->add_entry(Dynamic_entry(tag, od, false)); } - // Add a new dynamic entry with the size of a section. + // Add a new dynamic entry with the size of output data. void - add_section_size(elfcpp::DT tag, Output_section* os) - { this->add_entry(Dynamic_entry(tag, os, true)); } + add_section_size(elfcpp::DT tag, const Output_data* od) + { this->add_entry(Dynamic_entry(tag, od, true)); } // Add a new dynamic entry with the address of a symbol. void - add_symbol(elfcpp::DT tag, Symbol* sym) + add_symbol(elfcpp::DT tag, const Symbol* sym) { this->add_entry(Dynamic_entry(tag, sym)); } // Add a new dynamic entry with a string. @@ -1003,6 +1016,11 @@ class Output_data_dynamic : public Output_section_data void do_write(Output_file*); + protected: + // Adjust the output section to set the entry size. + void + do_adjust_output_section(Output_section*); + private: // This POD class holds a single dynamic entry. class Dynamic_entry @@ -1014,15 +1032,15 @@ class Output_data_dynamic : public Output_section_data { this->u_.val = val; } // Create an entry with the size or address of a section. - Dynamic_entry(elfcpp::DT tag, Output_section* os, bool section_size) + Dynamic_entry(elfcpp::DT tag, const Output_data* od, bool section_size) : tag_(tag), classification_(section_size ? DYNAMIC_SECTION_SIZE : DYNAMIC_SECTION_ADDRESS) - { this->u_.os = os; } + { this->u_.od = od; } // Create an entry with the address of a symbol. - Dynamic_entry(elfcpp::DT tag, Symbol* sym) + Dynamic_entry(elfcpp::DT tag, const Symbol* sym) : tag_(tag), classification_(DYNAMIC_SYMBOL) { this->u_.sym = sym; } @@ -1056,9 +1074,9 @@ class Output_data_dynamic : public Output_section_data // For DYNAMIC_NUMBER. unsigned int val; // For DYNAMIC_SECTION_ADDRESS and DYNAMIC_SECTION_SIZE. - Output_section* os; + const Output_data* od; // For DYNAMIC_SYMBOL. - Symbol* sym; + const Symbol* sym; // For DYNAMIC_STRING. const char* str; } u_; @@ -1143,18 +1161,71 @@ class Output_section : public Output_data // Set the entsize field. void - set_entsize(uint64_t v) - { this->entsize_ = v; } + set_entsize(uint64_t v); - // Set the link field. + // Set the link field to the output section index of a section. + void + set_link_section(Output_data* od) + { + gold_assert(this->link_ == 0 + && !this->should_link_to_symtab_ + && !this->should_link_to_dynsym_); + this->link_section_ = od; + } + + // Set the link field to a constant. void set_link(unsigned int v) - { this->link_ = v; } + { + gold_assert(this->link_section_ == NULL + && !this->should_link_to_symtab_ + && !this->should_link_to_dynsym_); + this->link_ = v; + } - // Set the info field. + // Record that this section should link to the normal symbol table. + void + set_should_link_to_symtab() + { + gold_assert(this->link_section_ == NULL + && this->link_ == 0 + && !this->should_link_to_dynsym_); + this->should_link_to_symtab_ = true; + } + + // Record that this section should link to the dynamic symbol table. + void + set_should_link_to_dynsym() + { + gold_assert(this->link_section_ == NULL + && this->link_ == 0 + && !this->should_link_to_symtab_); + this->should_link_to_dynsym_ = true; + } + + // Return the info field. + unsigned int + info() const + { + gold_assert(this->info_section_ == NULL); + return this->info_; + } + + // Set the info field to the output section index of a section. + void + set_info_section(Output_data* od) + { + gold_assert(this->info_ == 0); + this->info_section_ = od; + } + + // Set the info field to a constant. void set_info(unsigned int v) - { this->info_ = v; } + { + gold_assert(this->info_section_ == NULL); + this->info_ = v; + } // Set the addralign field. void @@ -1250,7 +1321,8 @@ class Output_section : public Output_data // Write the section header into *OPHDR. template<int size, bool big_endian> void - write_header(const Stringpool*, elfcpp::Shdr_write<size, big_endian>*) const; + write_header(const Layout*, const Stringpool*, + elfcpp::Shdr_write<size, big_endian>*) const; private: // In some cases we need to keep a list of the input sections @@ -1344,9 +1416,13 @@ class Output_section : public Output_data // The section entry size. uint64_t entsize_; // The file offset is in the parent class. - // The section link field. + // Set the section link field to the index of this section. + Output_data* link_section_; + // If link_section_ is NULL, this is the link field. unsigned int link_; - // The section info field. + // Set the section info field to the index of this section. + Output_data* info_section_; + // If info_section_ is NULL, this is the section info field. unsigned int info_; // The section type. elfcpp::Elf_Word type_; @@ -1379,6 +1455,12 @@ class Output_section : public Output_data // dynamic symbol table. This will be true if there is a dynamic // relocation which needs it. bool needs_dynsym_index_ : 1; + // Whether the link field of this output section should point to the + // normal symbol table. + bool should_link_to_symtab_ : 1; + // Whether the link field of this output section should point to the + // dynamic symbol table. + bool should_link_to_dynsym_ : 1; }; // An output segment. PT_LOAD segments are built from collections of @@ -1466,8 +1548,7 @@ class Output_segment // Write the section headers of associated sections into V. template<int size, bool big_endian> unsigned char* - write_section_headers(const Stringpool*, - unsigned char* v, + write_section_headers(const Layout*, const Stringpool*, unsigned char* v, unsigned int* pshndx ACCEPT_SIZE_ENDIAN) const; private: @@ -1497,8 +1578,8 @@ class Output_segment // Write the section headers in the list into V. template<int size, bool big_endian> unsigned char* - write_section_headers_list(const Stringpool*, const Output_data_list*, - unsigned char* v, + write_section_headers_list(const Layout*, const Stringpool*, + const Output_data_list*, unsigned char* v, unsigned int* pshdx ACCEPT_SIZE_ENDIAN) const; // The list of output data with contents attached to this segment. diff --git a/gold/po/gold.pot b/gold/po/gold.pot index 4a852a1e720..dbfa857cf1e 100644 --- a/gold/po/gold.pot +++ b/gold/po/gold.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-11-30 15:37-0800\n" +"POT-Creation-Date: 2006-12-01 08:46-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -240,52 +240,52 @@ msgstr "" msgid "%s: missing expected TLS relocation\n" msgstr "" -#: i386.cc:702 i386.cc:843 i386.cc:1064 +#: i386.cc:729 i386.cc:870 i386.cc:1125 #, c-format msgid "%s: %s: unexpected reloc %u in object file\n" msgstr "" -#: i386.cc:738 i386.cc:757 +#: i386.cc:765 i386.cc:784 #, c-format msgid "%s: %s: unsupported reloc %u against local symbol\n" msgstr "" -#: i386.cc:879 i386.cc:900 +#: i386.cc:906 i386.cc:927 #, c-format msgid "%s: %s: unsupported reloc %u against global symbol %s\n" msgstr "" -#: i386.cc:923 +#: i386.cc:950 #, c-format msgid "%s: %s: unsupported RELA reloc section\n" msgstr "" -#: i386.cc:980 +#: i386.cc:1041 #, c-format msgid "%s: %s: missing expected TLS relocation\n" msgstr "" -#: i386.cc:1096 i386.cc:1171 i386.cc:1182 +#: i386.cc:1157 i386.cc:1232 i386.cc:1243 #, c-format msgid "%s: %s: unsupported reloc %u\n" msgstr "" -#: i386.cc:1123 +#: i386.cc:1184 #, c-format msgid "%s: %s: TLS reloc but no TLS segment\n" msgstr "" -#: i386.cc:1156 +#: i386.cc:1217 #, c-format msgid "%s: %s: unsupported reloc type %u\n" msgstr "" -#: i386.cc:1365 +#: i386.cc:1426 #, c-format msgid "%s: %s: TLS relocation out of range\n" msgstr "" -#: i386.cc:1383 +#: i386.cc:1444 #, c-format msgid "%s: %s: TLS relocation against invalid instruction\n" msgstr "" @@ -496,37 +496,37 @@ msgstr "" msgid "%s: -%c: %s\n" msgstr "" -#: output.cc:817 +#: output.cc:881 #, c-format msgid "%s: %s: invalid alignment %lu for section \"%s\"\n" msgstr "" -#: output.cc:1316 +#: output.cc:1393 #, c-format msgid "%s: %s: open: %s\n" msgstr "" -#: output.cc:1325 +#: output.cc:1402 #, c-format msgid "%s: %s: lseek: %s\n" msgstr "" -#: output.cc:1332 +#: output.cc:1409 #, c-format msgid "%s: %s: write: %s\n" msgstr "" -#: output.cc:1342 +#: output.cc:1419 #, c-format msgid "%s: %s: mmap: %s\n" msgstr "" -#: output.cc:1356 +#: output.cc:1433 #, c-format msgid "%s: %s: munmap: %s\n" msgstr "" -#: output.cc:1364 +#: output.cc:1441 #, c-format msgid "%s: %s: close: %s\n" msgstr "" @@ -607,12 +607,12 @@ msgstr "" msgid "%s: %s: versym for symbol %zu has no name: %u\n" msgstr "" -#: symtab.cc:1050 symtab.cc:1201 +#: symtab.cc:1063 symtab.cc:1235 #, c-format msgid "%s: %s: unsupported symbol section 0x%x\n" msgstr "" -#: symtab.cc:1364 +#: symtab.cc:1423 #, c-format msgid "%s: %s: warning: %s\n" msgstr "" diff --git a/gold/reloc.cc b/gold/reloc.cc index 915656c374e..5b4db46ccb3 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -497,6 +497,7 @@ void Copy_relocs<size, big_endian>::Copy_reloc_entry::emit( Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>* reloc_data) { + this->sym_->set_needs_dynsym_entry(); reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_, this->shndx_, this->address_); } @@ -508,6 +509,7 @@ void Copy_relocs<size, big_endian>::Copy_reloc_entry::emit( Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>* reloc_data) { + this->sym_->set_needs_dynsym_entry(); reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_, this->shndx_, this->address_, this->addend_); } diff --git a/gold/resolve.cc b/gold/resolve.cc index 891de8c7c94..b8e5e701cb7 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -22,7 +22,7 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym, gold_assert(this->source_ == FROM_OBJECT); this->u_.from_object.object = object; // FIXME: Handle SHN_XINDEX. - this->u_.from_object.shnum = sym.get_st_shndx(); + this->u_.from_object.shndx = sym.get_st_shndx(); this->type_ = sym.get_st_type(); this->binding_ = sym.get_st_bind(); this->visibility_ = sym.get_st_visibility(); @@ -110,7 +110,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, && to->object()->is_dynamic()) tobits |= (1 << 1); - switch (to->shnum()) + switch (to->shndx()) { case elfcpp::SHN_UNDEF: tobits |= (1 << 2); diff --git a/gold/symtab.cc b/gold/symtab.cc index 4d2bb1afecb..21192c1ec43 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -55,7 +55,7 @@ Symbol::init_base(const char* name, const char* version, Object* object, sym.get_st_visibility(), sym.get_st_nonvis()); this->u_.from_object.object = object; // FIXME: Handle SHN_XINDEX. - this->u_.from_object.shnum = sym.get_st_shndx(); + this->u_.from_object.shndx = sym.get_st_shndx(); this->source_ = FROM_OBJECT; this->in_dyn_ = object->is_dynamic(); } @@ -258,7 +258,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from esym.put_st_size(from->symsize()); esym.put_st_info(from->binding(), from->type()); esym.put_st_other(from->visibility(), from->nonvis()); - esym.put_st_shndx(from->shnum()); + esym.put_st_shndx(from->shndx()); Symbol_table::resolve(to, esym.sym(), from->object()); } @@ -717,9 +717,9 @@ Symbol_table::define_special_symbol(Target* target, const char* name, sym = this->get_sized_symbol SELECT_SIZE_NAME(size) (oldsym SELECT_SIZE(size)); gold_assert(sym->source() == Symbol::FROM_OBJECT); - const int old_shnum = sym->shnum(); - if (old_shnum != elfcpp::SHN_UNDEF - && old_shnum != elfcpp::SHN_COMMON + const int old_shndx = sym->shndx(); + if (old_shndx != elfcpp::SHN_UNDEF + && old_shndx != elfcpp::SHN_COMMON && !sym->object()->is_dynamic()) { fprintf(stderr, "%s: linker defined: multiple definition of %s\n", @@ -969,7 +969,14 @@ Symbol_table::set_dynsym_indexes(unsigned int index, ++p) { Symbol* sym = p->second; - if (sym->needs_dynsym_entry()) + + // Note that SYM may already have a dynamic symbol index, since + // some symbols appear more than once in the symbol table, with + // and without a version. + + if (!sym->needs_dynsym_entry()) + sym->set_dynsym_index(-1U); + else if (!sym->has_dynsym_index()) { sym->set_dynsym_index(index); ++index; @@ -986,13 +993,19 @@ Symbol_table::set_dynsym_indexes(unsigned int index, // OFF. Add their names to POOL. Return the new file offset. off_t -Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool) +Symbol_table::finalize(unsigned int index, off_t off, off_t dynoff, + size_t dyn_global_index, size_t dyncount, + Stringpool* pool) { off_t ret; gold_assert(index != 0); this->first_global_index_ = index; + this->dynamic_offset_ = dynoff; + this->first_dynamic_global_index_ = dyn_global_index; + this->dynamic_count_ = dyncount; + if (this->size_ == 32) ret = this->sized_finalize<32>(index, off, pool); else if (this->size_ == 64) @@ -1041,14 +1054,14 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) { case Symbol::FROM_OBJECT: { - unsigned int shnum = sym->shnum(); + unsigned int shndx = sym->shndx(); // FIXME: We need some target specific support here. - if (shnum >= elfcpp::SHN_LORESERVE - && shnum != elfcpp::SHN_ABS) + if (shndx >= elfcpp::SHN_LORESERVE + && shndx != elfcpp::SHN_ABS) { fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"), - program_name, sym->name(), shnum); + program_name, sym->name(), shndx); gold_exit(false); } @@ -1056,21 +1069,22 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) if (symobj->is_dynamic()) { value = 0; - shnum = elfcpp::SHN_UNDEF; + shndx = elfcpp::SHN_UNDEF; } - else if (shnum == elfcpp::SHN_UNDEF) + else if (shndx == elfcpp::SHN_UNDEF) value = 0; - else if (shnum == elfcpp::SHN_ABS) + else if (shndx == elfcpp::SHN_ABS) value = sym->value(); else { Relobj* relobj = static_cast<Relobj*>(symobj); off_t secoff; - Output_section* os = relobj->output_section(shnum, &secoff); + Output_section* os = relobj->output_section(shndx, &secoff); if (os == NULL) { sym->set_symtab_index(-1U); + gold_assert(sym->dynsym_index() == -1U); continue; } @@ -1132,21 +1146,21 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) void Symbol_table::write_globals(const Target* target, const Stringpool* sympool, - Output_file* of) const + const Stringpool* dynpool, Output_file* of) const { if (this->size_ == 32) { if (target->is_big_endian()) - this->sized_write_globals<32, true>(target, sympool, of); + this->sized_write_globals<32, true>(target, sympool, dynpool, of); else - this->sized_write_globals<32, false>(target, sympool, of); + this->sized_write_globals<32, false>(target, sympool, dynpool, of); } else if (this->size_ == 64) { if (target->is_big_endian()) - this->sized_write_globals<64, true>(target, sympool, of); + this->sized_write_globals<64, true>(target, sympool, dynpool, of); else - this->sized_write_globals<64, false>(target, sympool, of); + this->sized_write_globals<64, false>(target, sympool, dynpool, of); } else gold_unreachable(); @@ -1158,12 +1172,22 @@ template<int size, bool big_endian> void Symbol_table::sized_write_globals(const Target*, const Stringpool* sympool, + const Stringpool* dynpool, Output_file* of) const { const int sym_size = elfcpp::Elf_sizes<size>::sym_size; unsigned int index = this->first_global_index_; const off_t oview_size = this->output_count_ * sym_size; - unsigned char* psyms = of->get_output_view(this->offset_, oview_size); + unsigned char* const psyms = of->get_output_view(this->offset_, oview_size); + + unsigned int dynamic_count = this->dynamic_count_; + off_t dynamic_size = dynamic_count * sym_size; + unsigned int first_dynamic_global_index = this->first_dynamic_global_index_; + unsigned char* dynamic_view; + if (this->dynamic_offset_ == 0) + dynamic_view = NULL; + else + dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size); unsigned char* ps = psyms; for (Symbol_table_type::const_iterator p = this->table_.begin(); @@ -1173,33 +1197,43 @@ Symbol_table::sized_write_globals(const Target*, Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second); unsigned int sym_index = sym->symtab_index(); - if (sym_index == -1U) + unsigned int dynsym_index; + if (dynamic_view == NULL) + dynsym_index = -1U; + else + dynsym_index = sym->dynsym_index(); + + if (sym_index == -1U && dynsym_index == -1U) { // This symbol is not included in the output file. continue; } - if (sym_index != index) + + if (sym_index == index) + ++index; + else if (sym_index != -1U) { // We have already seen this symbol, because it has a // default version. gold_assert(sym_index < index); - continue; + if (dynsym_index == -1U) + continue; + sym_index = -1U; } - ++index; unsigned int shndx; switch (sym->source()) { case Symbol::FROM_OBJECT: { - unsigned int shnum = sym->shnum(); + unsigned int in_shndx = sym->shndx(); // FIXME: We need some target specific support here. - if (shnum >= elfcpp::SHN_LORESERVE - && shnum != elfcpp::SHN_ABS) + if (in_shndx >= elfcpp::SHN_LORESERVE + && in_shndx != elfcpp::SHN_ABS) { fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"), - program_name, sym->name(), sym->shnum()); + program_name, sym->name(), in_shndx); gold_exit(false); } @@ -1209,13 +1243,14 @@ Symbol_table::sized_write_globals(const Target*, // FIXME. shndx = elfcpp::SHN_UNDEF; } - else if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS) - shndx = shnum; + else if (in_shndx == elfcpp::SHN_UNDEF + || in_shndx == elfcpp::SHN_ABS) + shndx = in_shndx; else { Relobj* relobj = static_cast<Relobj*>(symobj); off_t secoff; - Output_section* os = relobj->output_section(shnum, &secoff); + Output_section* os = relobj->output_section(in_shndx, &secoff); gold_assert(os != NULL); shndx = os->out_shndx(); } @@ -1238,21 +1273,45 @@ Symbol_table::sized_write_globals(const Target*, gold_unreachable(); } - elfcpp::Sym_write<size, big_endian> osym(ps); - osym.put_st_name(sympool->get_offset(sym->name())); - osym.put_st_value(sym->value()); - osym.put_st_size(sym->symsize()); - osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type())); - osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), - sym->nonvis())); - osym.put_st_shndx(shndx); + if (sym_index != -1U) + { + this->sized_write_symbol<size, big_endian>(sym, shndx, sympool, ps); + ps += sym_size; + } - ps += sym_size; + if (dynsym_index != -1U) + { + dynsym_index -= first_dynamic_global_index; + gold_assert(dynsym_index < dynamic_count); + unsigned char* pd = dynamic_view + (dynsym_index * sym_size); + this->sized_write_symbol<size, big_endian>(sym, shndx, dynpool, pd); + } } gold_assert(ps - psyms == oview_size); of->write_output_view(this->offset_, oview_size, psyms); + if (dynamic_view != NULL) + of->write_output_view(this->dynamic_offset_, dynamic_size, dynamic_view); +} + +// Write out the symbol SYM, in section SHNDX, to P. POOL is the +// strtab holding the name. + +template<int size, bool big_endian> +void +Symbol_table::sized_write_symbol(Sized_symbol<size>* sym, + unsigned int shndx, + const Stringpool* pool, + unsigned char* p) const +{ + elfcpp::Sym_write<size, big_endian> osym(p); + osym.put_st_name(pool->get_offset(sym->name())); + osym.put_st_value(sym->value()); + osym.put_st_size(sym->symsize()); + osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type())); + osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis())); + osym.put_st_shndx(shndx); } // Write out a section symbol. Return the update offset. diff --git a/gold/symtab.h b/gold/symtab.h index 1350bf11a0f..ee3b3a8e2d5 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -97,10 +97,10 @@ class Symbol // Return the index of the section in the input relocatable or // dynamic object file. unsigned int - shnum() const + shndx() const { gold_assert(this->source_ == FROM_OBJECT); - return this->u_.from_object.shnum; + return this->u_.from_object.shndx; } // Return the output data section with which this symbol is @@ -235,6 +235,12 @@ class Symbol this->dynsym_index_ = index; } + // Return whether this symbol already has an index in the dynamic + // symbol table. + bool + has_dynsym_index() const + { return this->dynsym_index_ != 0; } + // Return whether this symbol has an entry in the GOT section. bool has_got_offset() const @@ -293,8 +299,8 @@ class Symbol is_defined() const { return (this->source_ != FROM_OBJECT - || (this->shnum() != elfcpp::SHN_UNDEF - && this->shnum() != elfcpp::SHN_COMMON)); + || (this->shndx() != elfcpp::SHN_UNDEF + && this->shndx() != elfcpp::SHN_COMMON)); } // Return whether this symbol is defined in a dynamic object. @@ -310,7 +316,7 @@ class Symbol bool is_undefined() const { - return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_UNDEF; + return this->source_ == FROM_OBJECT && this->shndx() == elfcpp::SHN_UNDEF; } // Return whether this is a common symbol. @@ -318,7 +324,7 @@ class Symbol is_common() const { return (this->source_ == FROM_OBJECT - && (this->shnum() == elfcpp::SHN_COMMON + && (this->shndx() == elfcpp::SHN_COMMON || this->type_ == elfcpp::STT_COMMON)); } @@ -391,7 +397,7 @@ class Symbol // seen. Object* object; // Section number in object_ in which symbol is defined. - unsigned int shnum; + unsigned int shndx; } from_object; // This struct is used if SOURCE_ == IN_OUTPUT_DATA. @@ -824,14 +830,19 @@ class Symbol_table // Finalize the symbol table after we have set the final addresses // of all the input sections. This sets the final symbol indexes, // values and adds the names to *POOL. INDEX is the index of the - // first global symbol. This records the file offset OFF, and - // returns the new file offset. + // first global symbol. OFF is the file offset of the global symbol + // table, DYNOFF is the offset of the globals in the dynamic symbol + // table, DYN_GLOBAL_INDEX is the index of the first global dynamic + // symbol, and DYNCOUNT is the number of global dynamic symbols. + // This records the parameters, and returns the new file offset. off_t - finalize(unsigned int index, off_t off, Stringpool* pool); + finalize(unsigned int index, off_t off, off_t dynoff, + size_t dyn_global_index, size_t dyncount, Stringpool* pool); // Write out the global symbols. void - write_globals(const Target*, const Stringpool*, Output_file*) const; + write_globals(const Target*, const Stringpool*, const Stringpool*, + Output_file*) const; // Write out a section symbol. Return the updated offset. void @@ -915,7 +926,14 @@ class Symbol_table // Write globals specialized for size and endianness. template<int size, bool big_endian> void - sized_write_globals(const Target*, const Stringpool*, Output_file*) const; + sized_write_globals(const Target*, const Stringpool*, const Stringpool*, + Output_file*) const; + + // Write out a symbol to P. + template<int size, bool big_endian> + void + sized_write_symbol(Sized_symbol<size>*, unsigned int shndx, + const Stringpool*, unsigned char* p) const; // Write out a section symbol, specialized for size and endianness. template<int size, bool big_endian> @@ -962,6 +980,15 @@ class Symbol_table // The number of global symbols we want to write out. size_t output_count_; + // The file offset of the global dynamic symbols, or 0 if none. + off_t dynamic_offset_; + + // The index of the first global dynamic symbol. + unsigned int first_dynamic_global_index_; + + // The number of global dynamic symbols, or 0 if none. + off_t dynamic_count_; + // The symbol hash table. Symbol_table_type table_; diff --git a/gold/target.h b/gold/target.h index a031c403302..42bed9ed37d 100644 --- a/gold/target.h +++ b/gold/target.h @@ -86,8 +86,8 @@ class Target // This is called to tell the target to complete any sections it is // handling. After this all sections must have their final size. void - finalize_sections(Layout* layout) - { return this->do_finalize_sections(layout); } + finalize_sections(const General_options* options, Layout* layout) + { return this->do_finalize_sections(options, layout); } protected: // This struct holds the constant information for a child class. We @@ -121,7 +121,7 @@ class Target // Virtual function which may be implemented by the child class. virtual void - do_finalize_sections(Layout*) + do_finalize_sections(const General_options*, Layout*) { } private: |