From f6ce93d6e999d1a0c450c5e71c5b3468e6217f0a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 6 Nov 2006 22:46:08 +0000 Subject: [PATCH] Split Object into Dynobj and Relobj, incorporate elfcpp swapping changes. --- gold/archive.cc | 19 +-- gold/archive.h | 19 ++- gold/common.cc | 1 + gold/defstd.cc | 116 ++++++++++++++- gold/dynobj.h | 56 +++++++ gold/fileread.cc | 10 +- gold/gold.cc | 8 +- gold/i386.cc | 12 +- gold/layout.cc | 15 +- gold/layout.h | 2 +- gold/object.cc | 121 +++++++++------ gold/object.h | 276 +++++++++++++++++++--------------- gold/output.cc | 12 +- gold/output.h | 6 +- gold/po/gold.pot | 63 ++++---- gold/readsyms.cc | 15 +- gold/readsyms.h | 24 +-- gold/reloc.cc | 34 ++--- gold/reloc.h | 352 +++----------------------------------------- gold/symtab.cc | 130 ++++++++++++---- gold/symtab.h | 151 ++++++++++++++++--- gold/target-reloc.h | 5 +- gold/target.h | 9 +- 23 files changed, 807 insertions(+), 649 deletions(-) create mode 100644 gold/dynobj.h diff --git a/gold/archive.cc b/gold/archive.cc index 031ead09a4..d0854036a6 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -70,7 +70,7 @@ Archive::setup() // Numbers in the armap are always big-endian. const elfcpp::Elf_Word* pword = reinterpret_cast(p); - unsigned int nsyms = elfcpp::read_elf_word(pword); + unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword); ++pword; // Note that the addition is in units of sizeof(elfcpp::Elf_Word). @@ -81,7 +81,7 @@ Archive::setup() for (unsigned int i = 0; i < nsyms; ++i) { this->armap_[i].name = pnames; - this->armap_[i].offset = elfcpp::read_elf_word(pword); + this->armap_[i].offset = elfcpp::Swap<32, true>::readval(pword); pnames += strlen(pnames) + 1; ++pword; } @@ -215,8 +215,8 @@ Archive::read_header(off_t off, std::string* pname) // may be satisfied by other objects in the archive. void -Archive::add_symbols(Symbol_table* symtab, Layout* layout, - Input_objects* input_objects) +Archive::add_symbols(const General_options& options, Symbol_table* symtab, + Layout* layout, Input_objects* input_objects) { const size_t armap_size = this->armap_.size(); @@ -248,7 +248,7 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, // We want to include this object in the link. last = this->armap_[i].offset; - this->include_member(symtab, layout, input_objects, last); + this->include_member(options, symtab, layout, input_objects, last); this->seen_[i] = true; added_new_object = true; } @@ -260,8 +260,9 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, // the member header. void -Archive::include_member(Symbol_table* symtab, Layout* layout, - Input_objects* input_objects, off_t off) +Archive::include_member(const General_options& options, Symbol_table* symtab, + Layout* layout, Input_objects* input_objects, + off_t off) { std::string n; this->read_header(off, &n); @@ -303,7 +304,7 @@ Archive::include_member(Symbol_table* symtab, Layout* layout, Read_symbols_data sd; obj->read_symbols(&sd); - obj->layout(layout, &sd); + obj->layout(options, symtab, layout, &sd); obj->add_symbols(symtab, &sd); } @@ -352,7 +353,7 @@ Add_archive_symbols::locks(Workqueue* workqueue) void Add_archive_symbols::run(Workqueue*) { - this->archive_->add_symbols(this->symtab_, this->layout_, + this->archive_->add_symbols(this->options_, this->symtab_, this->layout_, this->input_objects_); if (this->input_group_ != NULL) diff --git a/gold/archive.h b/gold/archive.h index f0edfcb7ff..193a9e2de8 100644 --- a/gold/archive.h +++ b/gold/archive.h @@ -11,6 +11,7 @@ namespace gold { +class General_options; class Input_file; class Input_objects; class Input_group; @@ -68,14 +69,13 @@ class Archive // Select members from the archive as needed and add them to the // link. void - add_symbols(Symbol_table*, Layout*, Input_objects*); + add_symbols(const General_options&, Symbol_table*, Layout*, Input_objects*); private: Archive(const Archive&); Archive& operator=(const Archive&); struct Archive_header; - class Add_archive_symbols_locker; // Get a view into the underlying file. const unsigned char* @@ -89,7 +89,8 @@ class Archive // Include an archive member in the link. void - include_member(Symbol_table*, Layout*, Input_objects*, off_t off); + include_member(const General_options&, Symbol_table*, Layout*, + Input_objects*, off_t off); // An entry in the archive map of symbols to object files. struct Armap_entry @@ -119,14 +120,15 @@ class Archive class Add_archive_symbols : public Task { public: - Add_archive_symbols(Symbol_table* symtab, Layout* layout, - Input_objects* input_objects, + Add_archive_symbols(const General_options& options, Symbol_table* symtab, + Layout* layout, Input_objects* input_objects, Archive* archive, Input_group* input_group, Task_token* this_blocker, Task_token* next_blocker) - : symtab_(symtab), layout_(layout), input_objects_(input_objects), - archive_(archive), input_group_(input_group), - this_blocker_(this_blocker), next_blocker_(next_blocker) + : options_(options), symtab_(symtab), layout_(layout), + input_objects_(input_objects), archive_(archive), + input_group_(input_group), this_blocker_(this_blocker), + next_blocker_(next_blocker) { } ~Add_archive_symbols(); @@ -145,6 +147,7 @@ class Add_archive_symbols : public Task private: class Add_archive_symbols_locker; + const General_options& options_; Symbol_table* symtab_; Layout* layout_; Input_objects* input_objects_; diff --git a/gold/common.cc b/gold/common.cc index 28ca2f6dab..358ed8d0d9 100644 --- a/gold/common.cc +++ b/gold/common.cc @@ -7,6 +7,7 @@ #include "workqueue.h" #include "layout.h" #include "output.h" +#include "symtab.h" #include "common.h" namespace gold diff --git a/gold/defstd.cc b/gold/defstd.cc index 29fd2cd8cf..50a977a3b9 100644 --- a/gold/defstd.cc +++ b/gold/defstd.cc @@ -93,10 +93,122 @@ const int in_section_count = sizeof in_section / sizeof in_section[0]; const Define_symbol_in_segment in_segment[] = { + { + "__executable_start", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF(0), // segment_flags_set + elfcpp::PF(0), // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_START, // offset_from_base + true // only_if_ref + }, + { + "etext", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set + elfcpp::PF_W, // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_END, // offset_from_base + true // only_if_ref + }, + { + "_etext", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set + elfcpp::PF_W, // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_END, // offset_from_base + true // only_if_ref + }, + { + "__etext", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set + elfcpp::PF_W, // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_END, // offset_from_base + true // only_if_ref + }, + { + "_edata", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set + elfcpp::PF(0), // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_BSS, // offset_from_base + false // only_if_ref + }, + { + "edata", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set + elfcpp::PF(0), // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_BSS, // offset_from_base + true // only_if_ref + }, + { + "__bss_start", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set + elfcpp::PF(0), // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_BSS, // offset_from_base + false // only_if_ref + }, { "_end", // name elfcpp::PT_LOAD, // segment_type - elfcpp::PF_W, // segment_flags_set + elfcpp::PF_X, // segment_flags_set + elfcpp::PF(0), // segment_flags_clear + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + Symbol::SEGMENT_START, // offset_from_base + false // only_if_ref + }, + { + "end", // name + elfcpp::PT_LOAD, // segment_type + elfcpp::PF_X, // segment_flags_set elfcpp::PF(0), // segment_flags_clear 0, // value 0, // size @@ -104,7 +216,7 @@ const Define_symbol_in_segment in_segment[] = elfcpp::STB_GLOBAL, // binding elfcpp::STV_DEFAULT, // visibility 0, // nonvis - Symbol::SEGMENT_START, // offset_from_bas + Symbol::SEGMENT_START, // offset_from_base false // only_if_ref } }; diff --git a/gold/dynobj.h b/gold/dynobj.h new file mode 100644 index 0000000000..99e78830d1 --- /dev/null +++ b/gold/dynobj.h @@ -0,0 +1,56 @@ +// dynobj.h -- dynamic object support for gold -*- C++ -*- + +#ifndef GOLD_DYNOBJ_H +#define GOLD_DYNOBJ_H + +#include "object.h" + +namespace gold +{ + +// A dynamic object (ET_DYN). This is an abstract base class itself. +// The implementations is the template class Sized_dynobj. + +class Dynobj : public Object +{ + public: + Dynobj(const std::string& name, Input_file* input_file, off_t offset = 0) + : Object(name, input_file, true, offset) + { } +}; + +// A dynamic object, size and endian specific version. + +template +class Sized_dynobj : public Dynobj +{ + public: + Sized_dynobj(const std::string& name, Input_file* input_file, off_t offset, + const typename elfcpp::Ehdr&); + + // Read the symbols. + void + do_read_symbols(Read_symbols_data*); + + // Lay out the input sections. + void + do_layout(const General_options&, Symbol_table*, Layout*, + Read_symbols_data*); + + // Add the symbols to the symbol table. + void + do_add_symbols(Symbol_table*, Read_symbols_data*); + + // Return a view of the contents of a section. Set *PLEN to the + // size. + const unsigned char* + do_section_contents(unsigned int shnum, off_t* plen) = 0; + + // Get the name of a section. + std::string + do_section_name(unsigned int shnum); +}; + +} // End namespace gold. + +#endif // !defined(GOLD_DYNOBJ_H) diff --git a/gold/fileread.cc b/gold/fileread.cc index 00971a76ca..43c69b3cf4 100644 --- a/gold/fileread.cc +++ b/gold/fileread.cc @@ -314,9 +314,13 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath) std::string n1("lib"); n1 += this->input_argument_.name(); std::string n2; - if (!options.is_static()) - n2 = n1 + ".so"; - n1 += ".a"; + if (options.is_static()) + n1 += ".a"; + else + { + n2 = n1 + ".a"; + n1 += ".so"; + } name = dirpath.find(n1, n2); if (name.empty()) { diff --git a/gold/gold.cc b/gold/gold.cc index 31598dc9e6..c2372adf52 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -153,8 +153,8 @@ queue_middle_tasks(const General_options& options, // of references made to the symbols. Task_token* blocker = new Task_token(); Task_token* symtab_lock = new Task_token(); - for (Input_objects::Object_list::const_iterator p = input_objects->begin(); - p != input_objects->end(); + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); ++p) { // We can read and process the relocations in any order. But we @@ -198,8 +198,8 @@ queue_final_tasks(const General_options& options, // Queue a task for each input object to relocate the sections and // write out the local symbols. - for (Input_objects::Object_list::const_iterator p = input_objects->begin(); - p != input_objects->end(); + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); ++p) { final_blocker->add_blocker(); diff --git a/gold/i386.cc b/gold/i386.cc index 53af5eeae6..15376f9598 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -35,7 +35,7 @@ class Target_i386 : public Sized_target<32, false> scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, - Sized_object<32, false>* object, + Sized_relobj<32, false>* object, unsigned int sh_type, const unsigned char* prelocs, size_t reloc_count, @@ -60,14 +60,14 @@ class Target_i386 : public Sized_target<32, false> inline void local(const General_options& options, Symbol_table* symtab, Layout* layout, Target_i386* target, - Sized_object<32, false>* object, + Sized_relobj<32, false>* object, const elfcpp::Rel<32, false>& reloc, unsigned int r_type, const elfcpp::Sym<32, false>& lsym); inline void global(const General_options& options, Symbol_table* symtab, Layout* layout, Target_i386* target, - Sized_object<32, false>* object, + Sized_relobj<32, false>* object, const elfcpp::Rel<32, false>& reloc, unsigned int r_type, Symbol* gsym); }; @@ -265,7 +265,7 @@ Target_i386::Scan::local(const General_options& options, Symbol_table* symtab, Layout* layout, Target_i386* target, - Sized_object<32, false>* object, + Sized_relobj<32, false>* object, const elfcpp::Rel<32, false>&, unsigned int r_type, const elfcpp::Sym<32, false>&) { @@ -368,7 +368,7 @@ Target_i386::Scan::global(const General_options& options, Symbol_table* symtab, Layout* layout, Target_i386* target, - Sized_object<32, false>* object, + Sized_relobj<32, false>* object, const elfcpp::Rel<32, false>&, unsigned int r_type, Symbol* gsym) { @@ -496,7 +496,7 @@ void Target_i386::scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, - Sized_object<32, false>* object, + Sized_relobj<32, false>* object, unsigned int sh_type, const unsigned char* prelocs, size_t reloc_count, diff --git a/gold/layout.cc b/gold/layout.cc index 9e85f192a4..2bdd11b477 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -9,6 +9,7 @@ #include #include "output.h" +#include "symtab.h" #include "layout.h" namespace gold @@ -151,7 +152,7 @@ Layout::get_output_section(const char* name, elfcpp::Elf_Word type, template Output_section* -Layout::layout(Object* object, unsigned int shndx, const char* name, +Layout::layout(Relobj* object, unsigned int shndx, const char* name, const elfcpp::Shdr& shdr, off_t* off) { if (!this->include_section(object, name, shdr)) @@ -656,8 +657,8 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects, // never bother to write this out--it will just be left as zero. off += symsize; - for (Input_objects::Object_list::const_iterator p = input_objects->begin(); - p != input_objects->end(); + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); ++p) { Task_lock_obj tlo(**p); @@ -956,22 +957,22 @@ Close_task_runner::run(Workqueue*) template Output_section* -Layout::layout<32, false>(Object* object, unsigned int shndx, const char* name, +Layout::layout<32, false>(Relobj* object, unsigned int shndx, const char* name, const elfcpp::Shdr<32, false>& shdr, off_t*); template Output_section* -Layout::layout<32, true>(Object* object, unsigned int shndx, const char* name, +Layout::layout<32, true>(Relobj* object, unsigned int shndx, const char* name, const elfcpp::Shdr<32, true>& shdr, off_t*); template Output_section* -Layout::layout<64, false>(Object* object, unsigned int shndx, const char* name, +Layout::layout<64, false>(Relobj* object, unsigned int shndx, const char* name, const elfcpp::Shdr<64, false>& shdr, off_t*); template Output_section* -Layout::layout<64, true>(Object* object, unsigned int shndx, const char* name, +Layout::layout<64, true>(Relobj* object, unsigned int shndx, const char* name, const elfcpp::Shdr<64, true>& shdr, off_t*); diff --git a/gold/layout.h b/gold/layout.h index c96d47da10..bb2b644bd6 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -70,7 +70,7 @@ class Layout // output section. template Output_section* - layout(Object *object, unsigned int shndx, const char* name, + layout(Relobj *object, unsigned int shndx, const char* name, const elfcpp::Shdr& shdr, off_t* offset); // Add an Output_section_data to the layout. This is used for diff --git a/gold/object.cc b/gold/object.cc index 4e7f04c1dd..22e89a9604 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -6,25 +6,25 @@ #include #include -#include "object.h" #include "target-select.h" #include "layout.h" #include "output.h" +#include "symtab.h" +#include "object.h" +#include "dynobj.h" namespace gold { -// Class Object. - -// Class Sized_object. +// Class Sized_relobj. template -Sized_object::Sized_object( +Sized_relobj::Sized_relobj( const std::string& name, Input_file* input_file, off_t offset, const elfcpp::Ehdr& ehdr) - : Object(name, input_file, false, offset), + : Relobj(name, input_file, offset), section_headers_(NULL), flags_(ehdr.get_e_flags()), shoff_(ehdr.get_e_shoff()), @@ -53,7 +53,7 @@ Sized_object::Sized_object( } template -Sized_object::~Sized_object() +Sized_relobj::~Sized_relobj() { } @@ -61,21 +61,20 @@ Sized_object::~Sized_object() template inline const unsigned char* -Sized_object::section_header(unsigned int shnum) +Sized_relobj::section_header(unsigned int shnum) { assert(shnum < this->shnum()); off_t symtabshdroff = this->shoff_ + shnum * This::shdr_size; return this->get_view(symtabshdroff, This::shdr_size); } -// Return the name of section SHNUM. +// Return the name of section SHNUM. The object must already be +// locked. template std::string -Sized_object::do_section_name(unsigned int shnum) +Sized_relobj::do_section_name(unsigned int shnum) { - Task_lock_obj tl(*this); - // Read the section names. typename This::Shdr shdrnames(this->section_header(this->shstrndx_)); const unsigned char* pnamesu = this->get_view(shdrnames.get_sh_offset(), @@ -95,12 +94,27 @@ Sized_object::do_section_name(unsigned int shnum) return std::string(pnames + shdr.get_sh_name()); } +// Return a view of the contents of section SHNUM. The object does +// not have to be locked. + +template +const unsigned char* +Sized_relobj::do_section_contents(unsigned int shnum, + off_t* plen) +{ + Task_locker_obj tl(*this); + + typename This::Shdr shdr(this->section_header(shnum)); + *plen = shdr.get_sh_size(); + return this->get_view(shdr.get_sh_offset(), shdr.get_sh_size()); +} + // Set up an object file bsaed on the file header. This sets up the // target and reads the section information. template void -Sized_object::setup( +Sized_relobj::setup( const elfcpp::Ehdr& ehdr) { int machine = ehdr.get_e_machine(); @@ -159,7 +173,7 @@ Sized_object::setup( template void -Sized_object::do_read_symbols(Read_symbols_data* sd) +Sized_relobj::do_read_symbols(Read_symbols_data* sd) { // Transfer our view of the section headers to SD. sd->section_headers = this->section_headers_; @@ -236,7 +250,7 @@ Sized_object::do_read_symbols(Read_symbols_data* sd) template bool -Sized_object::include_section_group( +Sized_relobj::include_section_group( Layout* layout, unsigned int index, const elfcpp::Shdr& shdr, @@ -251,7 +265,7 @@ Sized_object::include_section_group( // The first word contains flags. We only care about COMDAT section // groups. Other section groups are always included in the link // just like ordinary sections. - elfcpp::Elf_Word flags = elfcpp::read_elf_word(pword); + elfcpp::Elf_Word flags = elfcpp::Swap<32, big_endian>::readval(pword); if ((flags & elfcpp::GRP_COMDAT) == 0) return true; @@ -345,7 +359,8 @@ Sized_object::include_section_group( size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word); for (size_t i = 1; i < count; ++i) { - elfcpp::Elf_Word secnum = elfcpp::read_elf_word(pword + i); + elfcpp::Elf_Word secnum = + elfcpp::Swap<32, big_endian>::readval(pword + i); if (secnum >= this->shnum()) { fprintf(stderr, @@ -377,7 +392,7 @@ Sized_object::include_section_group( template bool -Sized_object::include_linkonce_section( +Sized_relobj::include_linkonce_section( Layout* layout, const char* name, const elfcpp::Shdr&) @@ -395,7 +410,9 @@ Sized_object::include_linkonce_section( template void -Sized_object::do_layout(Layout* layout, +Sized_relobj::do_layout(const General_options& options, + Symbol_table* symtab, + Layout* layout, Read_symbols_data* sd) { unsigned int shnum = this->shnum(); @@ -415,7 +432,12 @@ Sized_object::do_layout(Layout* layout, // Keep track of which sections to omit. std::vector omit(shnum, false); - for (unsigned int i = 0; i < shnum; ++i, pshdrs += This::shdr_size) + const char warn_prefix[] = ".gnu.warning."; + const int warn_prefix_len = sizeof warn_prefix - 1; + + // Skip the first, dummy, section. + pshdrs += This::shdr_size; + for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size) { typename This::Shdr shdr(pshdrs); @@ -430,6 +452,13 @@ Sized_object::do_layout(Layout* layout, const char* name = pnames + shdr.get_sh_name(); + if (strncmp(name, warn_prefix, warn_prefix_len) == 0) + { + symtab->add_warning(name + warn_prefix_len, this, i); + if (!options.is_relocatable()) + omit[i] = true; + } + bool discard = omit[i]; if (!discard) { @@ -469,7 +498,7 @@ Sized_object::do_layout(Layout* layout, template void -Sized_object::do_add_symbols(Symbol_table* symtab, +Sized_relobj::do_add_symbols(Symbol_table* symtab, Read_symbols_data* sd) { if (sd->symbols == NULL) @@ -490,13 +519,12 @@ Sized_object::do_add_symbols(Symbol_table* symtab, this->symbols_ = new Symbol*[symcount]; - const unsigned char* psyms = sd->symbols->data(); - const elfcpp::Sym* syms = - reinterpret_cast*>(psyms); const char* sym_names = reinterpret_cast(sd->symbol_names->data()); - symtab->add_from_object(this, syms, symcount, sym_names, - sd->symbol_names_size, this->symbols_); + symtab->add_from_object(this, sd->symbols->data(), + symcount, sym_names, + sd->symbol_names_size, + this->symbols_); delete sd->symbols; sd->symbols = NULL; @@ -512,7 +540,7 @@ Sized_object::do_add_symbols(Symbol_table* symtab, template off_t -Sized_object::do_finalize_local_symbols(off_t off, +Sized_relobj::do_finalize_local_symbols(off_t off, Stringpool* pool) { if (this->symtab_shnum_ == 0) @@ -598,9 +626,12 @@ Sized_object::do_finalize_local_symbols(off_t off, + sym.get_st_value()); } - pool->add(pnames + sym.get_st_name()); - off += sym_size; - ++count; + if (sym.get_st_type() != elfcpp::STT_SECTION) + { + pool->add(pnames + sym.get_st_name()); + off += sym_size; + ++count; + } } this->output_local_symbol_count_ = count; @@ -612,7 +643,7 @@ Sized_object::do_finalize_local_symbols(off_t off, template void -Sized_object::write_local_symbols(Output_file* of, +Sized_relobj::write_local_symbols(Output_file* of, const Stringpool* sympool) { if (this->symtab_shnum_ == 0) @@ -655,7 +686,9 @@ Sized_object::write_local_symbols(Output_file* of, for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) { elfcpp::Sym isym(psyms); - elfcpp::Sym_write osym(ov); + + if (isym.get_st_type() == elfcpp::STT_SECTION) + continue; unsigned int st_shndx = isym.get_st_shndx(); if (st_shndx < elfcpp::SHN_LORESERVE) @@ -666,6 +699,8 @@ Sized_object::write_local_symbols(Output_file* of, st_shndx = mo[st_shndx].output_section->out_shndx(); } + elfcpp::Sym_write osym(ov); + osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name())); osym.put_st_value(this->values_[i]); osym.put_st_size(isym.get_st_size()); @@ -683,10 +718,15 @@ Sized_object::write_local_symbols(Output_file* of, // Input_objects methods. +// Add a regular relocatable object to the list. + void Input_objects::add_object(Object* obj) { - this->object_list_.push_back(obj); + if (obj->is_dynamic()) + this->dynobj_list_.push_back(static_cast(obj)); + else + this->relobj_list_.push_back(static_cast(obj)); Target* target = obj->target(); if (this->target_ == NULL) @@ -697,9 +737,6 @@ Input_objects::add_object(Object* obj) program_name, obj->name().c_str()); gold_exit(false); } - - if (obj->is_dynamic()) - this->any_dynamic_ = true; } // Relocate_info methods. @@ -752,8 +789,8 @@ make_elf_sized_object(const std::string& name, Input_file* input_file, if (et == elfcpp::ET_REL) { - Sized_object* obj = - new Sized_object(name, input_file, offset, ehdr); + Sized_relobj* obj = + new Sized_relobj(name, input_file, offset, ehdr); obj->setup(ehdr); return obj; } @@ -881,16 +918,16 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset, // script to restrict this to only the ones for implemented targets. template -class Sized_object<32, false>; +class Sized_relobj<32, false>; template -class Sized_object<32, true>; +class Sized_relobj<32, true>; template -class Sized_object<64, false>; +class Sized_relobj<64, false>; template -class Sized_object<64, true>; +class Sized_relobj<64, true>; template struct Relocate_info<32, false>; diff --git a/gold/object.h b/gold/object.h index 9b23de9000..e1f56d26f6 100644 --- a/gold/object.h +++ b/gold/object.h @@ -4,14 +4,12 @@ #define GOLD_OBJECT_H #include -#include #include #include #include "elfcpp.h" #include "fileread.h" #include "target.h" -#include "symtab.h" namespace gold { @@ -21,6 +19,7 @@ class Stringpool; class Layout; class Output_section; class Output_file; +class Dynobj; // Data to pass from read_symbols() to add_symbols(). @@ -71,10 +70,9 @@ struct Read_relocs_data File_view* local_symbols; }; -// Object is an interface which represents either a 32-bit or a 64-bit -// input object. This can be a regular object file (ET_REL) or a -// shared object (ET_DYN). The actual instantiations are -// Sized_object<32> and Sized_object<64> +// Object is an abstract base class which represents either a 32-bit +// or a 64-bit input object. This can be a regular object file +// (ET_REL) or a shared object (ET_DYN). class Object { @@ -86,8 +84,7 @@ class Object Object(const std::string& name, Input_file* input_file, bool is_dynamic, off_t offset = 0) : name_(name), input_file_(input_file), offset_(offset), - shnum_(0), is_dynamic_(is_dynamic), target_(NULL), - map_to_output_() + is_dynamic_(is_dynamic), target_(NULL) { } virtual ~Object() @@ -138,14 +135,124 @@ class Object // Pass sections which should be included in the link to the Layout // object, and record where the sections go in the output file. void - layout(Layout* lay, Read_symbols_data* sd) - { this->do_layout(lay, sd); } + layout(const General_options& options, Symbol_table* symtab, + Layout* layout, Read_symbols_data* sd) + { this->do_layout(options, symtab, layout, sd); } // Add symbol information to the global symbol table. void add_symbols(Symbol_table* symtab, Read_symbols_data* sd) { this->do_add_symbols(symtab, sd); } + // Return a view of the contents of a section. Set *PLEN to the + // size. + const unsigned char* + section_contents(unsigned int shnum, off_t* plen) + { return this->do_section_contents(shnum, plen); } + + // Return the name of a section given a section index. This is only + // used for error messages. + std::string + section_name(unsigned int shnum) + { return this->do_section_name(shnum); } + + protected: + // Read the symbols--implemented by child class. + virtual void + do_read_symbols(Read_symbols_data*) = 0; + + // Lay out sections--implemented by child class. + virtual void + do_layout(const General_options&, Symbol_table*, Layout*, + Read_symbols_data*) = 0; + + // Add symbol information to the global symbol table--implemented by + // child class. + virtual void + do_add_symbols(Symbol_table*, Read_symbols_data*) = 0; + + // Return a view of the contents of a section. Set *PLEN to the + // size. Implemented by child class. + virtual const unsigned char* + do_section_contents(unsigned int shnum, off_t* plen) = 0; + + // Get the name of a section--implemented by child class. + virtual std::string + do_section_name(unsigned int shnum) = 0; + + // Get the file. + Input_file* + input_file() const + { return this->input_file_; } + + // Get the offset into the file. + off_t + offset() const + { return this->offset_; } + + // Get a view into the underlying file. + const unsigned char* + get_view(off_t start, off_t size) + { return this->input_file_->file().get_view(start + this->offset_, size); } + + // Get a lasting view into the underlying file. + File_view* + get_lasting_view(off_t start, off_t size) + { + return this->input_file_->file().get_lasting_view(start + this->offset_, + size); + } + + // Read data from the underlying file. + void + read(off_t start, off_t size, void* p) + { this->input_file_->file().read(start + this->offset_, size, p); } + + // Set the target. + void + set_target(Target* target) + { this->target_ = target; } + + private: + // This class may not be copied. + Object(const Object&); + Object& operator=(const Object&); + + // Name of object as printed to user. + std::string name_; + // For reading the file. + Input_file* input_file_; + // Offset within the file--0 for an object file, non-0 for an + // archive. + off_t offset_; + // Whether this is a dynamic object. + bool is_dynamic_; + // Target functions--may be NULL if the target is not known. + Target* target_; +}; + +// Implement sized_target inline for efficiency. This approach breaks +// static type checking, but is made safe using asserts. + +template +inline Sized_target* +Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY) +{ + assert(this->target_->get_size() == size); + assert(this->target_->is_big_endian() ? big_endian : !big_endian); + return static_cast*>(this->target_); +} + +// A regular object (ET_REL). This is an abstract base class itself. +// The implementations is the template class Sized_relobj. + +class Relobj : public Object +{ + public: + Relobj(const std::string& name, Input_file* input_file, off_t offset = 0) + : Object(name, input_file, false, offset) + { } + // Read the relocs. void read_relocs(Read_relocs_data* rd) @@ -192,12 +299,6 @@ class Object this->map_to_output_[shndx].offset = off; } - // Return the name of a section given a section index. This is only - // used for error messages. - std::string - section_name(unsigned int shnum) - { return this->do_section_name(shnum); } - protected: // What we need to know to map an input section to an output // section. We keep an array of these, one for each input section, @@ -211,15 +312,6 @@ class Object off_t offset; }; - // Read the symbols--implemented by child class. - virtual void - do_read_symbols(Read_symbols_data*) = 0; - - // Add symbol information to the global symbol table--implemented by - // child class. - virtual void - do_add_symbols(Symbol_table*, Read_symbols_data*) = 0; - // Read the relocs--implemented by child class. virtual void do_read_relocs(Read_relocs_data*) = 0; @@ -229,10 +321,6 @@ class Object do_scan_relocs(const General_options&, Symbol_table*, Layout*, Read_relocs_data*) = 0; - // Lay out sections--implemented by child class. - virtual void - do_layout(Layout*, Read_symbols_data*) = 0; - // Finalize local symbols--implemented by child class. virtual off_t do_finalize_local_symbols(off_t, Stringpool*) = 0; @@ -243,25 +331,6 @@ class Object do_relocate(const General_options& options, const Symbol_table* symtab, const Layout*, Output_file* of) = 0; - // Get the name of a section--implemented by child class. - virtual std::string - do_section_name(unsigned int shnum) = 0; - - // Get the file. - Input_file* - input_file() const - { return this->input_file_; } - - // Get the offset into the file. - off_t - offset() const - { return this->offset_; } - - // Get a view into the underlying file. - const unsigned char* - get_view(off_t start, off_t size) - { return this->input_file_->file().get_view(start + this->offset_, size); } - // Get the number of sections. unsigned int shnum() const @@ -272,66 +341,21 @@ class Object set_shnum(int shnum) { this->shnum_ = shnum; } - // Set the target. - void - set_target(Target* target) - { this->target_ = target; } - - // Read data from the underlying file. - void - read(off_t start, off_t size, void* p) - { this->input_file_->file().read(start + this->offset_, size, p); } - - // Get a lasting view into the underlying file. - File_view* - get_lasting_view(off_t start, off_t size) - { - return this->input_file_->file().get_lasting_view(start + this->offset_, - size); - } - // Return the vector mapping input sections to output sections. std::vector& map_to_output() { return this->map_to_output_; } private: - // This class may not be copied. - Object(const Object&); - Object& operator=(const Object&); - - // Name of object as printed to user. - std::string name_; - // For reading the file. - Input_file* input_file_; - // Offset within the file--0 for an object file, non-0 for an - // archive. - off_t offset_; // Number of input sections. unsigned int shnum_; - // Whether this is a dynamic object. - bool is_dynamic_; - // Target functions--may be NULL if the target is not known. - Target* target_; // Mapping from input sections to output section. std::vector map_to_output_; }; -// Implement sized_target inline for efficiency. This approach breaks -// static type checking, but is made safe using asserts. - -template -inline Sized_target* -Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY) -{ - assert(this->target_->get_size() == size); - assert(this->target_->is_big_endian() ? big_endian : !big_endian); - return static_cast*>(this->target_); -} - // Implement Object::output_section inline for efficiency. inline Output_section* -Object::output_section(unsigned int shnum, off_t* poff) +Relobj::output_section(unsigned int shnum, off_t* poff) { assert(shnum < this->map_to_output_.size()); const Map_to_output& mo(this->map_to_output_[shnum]); @@ -342,13 +366,13 @@ Object::output_section(unsigned int shnum, off_t* poff) // A regular object file. This is size and endian specific. template -class Sized_object : public Object +class Sized_relobj : public Relobj { public: - Sized_object(const std::string& name, Input_file* input_file, off_t offset, + Sized_relobj(const std::string& name, Input_file* input_file, off_t offset, const typename elfcpp::Ehdr&); - ~Sized_object(); + ~Sized_relobj(); // Set up the object file based on the ELF header. void @@ -373,7 +397,8 @@ class Sized_object : public Object // Lay out the input sections. void - do_layout(Layout*, Read_symbols_data*); + do_layout(const General_options&, Symbol_table*, Layout*, + Read_symbols_data*); // Finalize the local symbols. off_t @@ -388,6 +413,11 @@ class Sized_object : public Object std::string do_section_name(unsigned int shnum); + // Return a view of the contents of a section. Set *PLEN to the + // size. + const unsigned char* + do_section_contents(unsigned int shnum, off_t* plen); + // Return the appropriate Sized_target structure. Sized_target* sized_target() @@ -398,12 +428,8 @@ class Sized_object : public Object } private: - // This object may not be copied. - Sized_object(const Sized_object&); - Sized_object& operator=(const Sized_object&); - // For convenience. - typedef Sized_object This; + typedef Sized_relobj This; static const int ehdr_size = elfcpp::Elf_sizes::ehdr_size; static const int shdr_size = elfcpp::Elf_sizes::shdr_size; static const int sym_size = elfcpp::Elf_sizes::sym_size; @@ -477,11 +503,16 @@ class Input_objects { public: Input_objects() - : object_list_(), target_(NULL), any_dynamic_(false) + : relobj_list_(), target_(NULL) { } - // The type of the list of input objects. - typedef std::list Object_list; + // The type of the list of input relocateable objects. + typedef std::vector Relobj_list; + typedef Relobj_list::const_iterator Relobj_iterator; + + // The type of the list of input dynamic objects. + typedef std::vector Dynobj_list; + typedef Dynobj_list::const_iterator Dynobj_iterator; // Add an object to the list. void @@ -492,27 +523,38 @@ class Input_objects target() const { return this->target_; } - // Iterate over all objects. - Object_list::const_iterator - begin() const - { return this->object_list_.begin(); } + // Iterate over all regular objects. + + Relobj_iterator + relobj_begin() const + { return this->relobj_list_.begin(); } + + Relobj_iterator + relobj_end() const + { return this->relobj_list_.end(); } + + // Iterate over all dynamic objects. + + Dynobj_iterator + dynobj_begin() const + { return this->dynobj_list_.begin(); } - Object_list::const_iterator - end() const - { return this->object_list_.end(); } + Dynobj_iterator + dynobj_end() const + { return this->dynobj_list_.end(); } // Return whether we have seen any dynamic objects. bool any_dynamic() const - { return this->any_dynamic_; } + { return !this->dynobj_list_.empty(); } private: Input_objects(const Input_objects&); Input_objects& operator=(const Input_objects&); - Object_list object_list_; + Relobj_list relobj_list_; + Dynobj_list dynobj_list_; Target* target_; - bool any_dynamic_; }; // Some of the information we pass to the relocation routines. We @@ -528,7 +570,7 @@ struct Relocate_info // Layout. const Layout* layout; // Object being relocated. - Sized_object* object; + Sized_relobj* object; // Number of local symbols. unsigned int local_symbol_count; // Values of local symbols. diff --git a/gold/output.cc b/gold/output.cc index 220a4f6b9e..40d58668c0 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -399,7 +399,7 @@ Output_section_got::Got_entry::write(unsigned char* pov) } Valtype* povv = reinterpret_cast(pov); - Swap::writeval(povv, val); + elfcpp::Swap::writeval(povv, val); } // Output_section_data methods. @@ -509,7 +509,7 @@ Output_section::~Output_section() template off_t -Output_section::add_input_section(Object* object, unsigned int shndx, +Output_section::add_input_section(Relobj* object, unsigned int shndx, const char* secname, const elfcpp::Shdr& shdr) { @@ -1091,7 +1091,7 @@ Output_file::close() template off_t Output_section::add_input_section<32, false>( - Object* object, + Relobj* object, unsigned int shndx, const char* secname, const elfcpp::Shdr<32, false>& shdr); @@ -1099,7 +1099,7 @@ Output_section::add_input_section<32, false>( template off_t Output_section::add_input_section<32, true>( - Object* object, + Relobj* object, unsigned int shndx, const char* secname, const elfcpp::Shdr<32, true>& shdr); @@ -1107,7 +1107,7 @@ Output_section::add_input_section<32, true>( template off_t Output_section::add_input_section<64, false>( - Object* object, + Relobj* object, unsigned int shndx, const char* secname, const elfcpp::Shdr<64, false>& shdr); @@ -1115,7 +1115,7 @@ Output_section::add_input_section<64, false>( template off_t Output_section::add_input_section<64, true>( - Object* object, + Relobj* object, unsigned int shndx, const char* secname, const elfcpp::Shdr<64, true>& shdr); diff --git a/gold/output.h b/gold/output.h index 5c72c02608..dc1653a987 100644 --- a/gold/output.h +++ b/gold/output.h @@ -504,7 +504,7 @@ class Output_section : public Output_data // object OBJECT. Return the offset within the output section. template off_t - add_input_section(Object* object, unsigned int shndx, const char *name, + add_input_section(Relobj* object, unsigned int shndx, const char *name, const elfcpp::Shdr& shdr); // Add generated data ODATA to this output section. @@ -613,7 +613,7 @@ class Output_section : public Output_data : shndx_(0), p2align_(0), data_size_(0) { this->u_.object = NULL; } - Input_section(Object* object, unsigned int shndx, off_t data_size, + Input_section(Relobj* object, unsigned int shndx, off_t data_size, uint64_t addralign) : shndx_(shndx), p2align_(ffsll(static_cast(addralign))), @@ -665,7 +665,7 @@ class Output_section : public Output_data { // If shndx_ != -1U, this points to the object which holds the // input section. - Object* object; + Relobj* object; // If shndx_ == -1U, this is the data to write out. Output_section_data* posd; } u_; diff --git a/gold/po/gold.pot b/gold/po/gold.pot index 522e25a5e2..4f00da433c 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-03 10:45-0800\n" +"POT-Creation-Date: 2006-11-06 13:40-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -51,7 +51,7 @@ msgstr "" msgid "%s: %s: bad extended name entry at header %ld\n" msgstr "" -#: archive.cc:279 archive.cc:292 +#: archive.cc:280 archive.cc:293 #, c-format msgid "%s: %s: member at %ld is not an ELF object" msgstr "" @@ -81,12 +81,12 @@ msgstr "" msgid "%s: %s: file too short: read only %lld of %lld bytes at %lld\n" msgstr "" -#: fileread.cc:323 +#: fileread.cc:327 #, c-format msgid "%s: cannot find %s\n" msgstr "" -#: fileread.cc:331 +#: fileread.cc:335 #, c-format msgid "%s: cannot open %s: %s\n" msgstr "" @@ -205,103 +205,103 @@ msgstr "" msgid "%s: %s: bad e_shentsize field (%d != %d)\n" msgstr "" -#: object.cc:89 object.cc:329 object.cc:425 +#: object.cc:88 object.cc:343 object.cc:447 #, c-format msgid "%s: %s: bad section name offset for section %u: %lu\n" msgstr "" -#: object.cc:112 +#: object.cc:126 #, c-format msgid "%s: %s: unsupported ELF machine number %d\n" msgstr "" -#: object.cc:207 +#: object.cc:221 #, c-format msgid "%s: %s: invalid symbol table name index: %u\n" msgstr "" -#: object.cc:215 +#: object.cc:229 #, c-format msgid "%s: %s: symbol table name section has wrong type: %u\n" msgstr "" -#: object.cc:267 +#: object.cc:281 #, c-format msgid "%s: %s: section group %u link %u out of range\n" msgstr "" -#: object.cc:277 +#: object.cc:291 #, c-format msgid "%s: %s: section group %u info %u out of range\n" msgstr "" -#: object.cc:288 +#: object.cc:302 #, c-format msgid "%s; %s: symtab section %u link %u out of range\n" msgstr "" -#: object.cc:304 +#: object.cc:318 #, c-format msgid "%s: %s: symbol %u name offset %u out of range\n" msgstr "" -#: object.cc:352 +#: object.cc:367 #, c-format msgid "%s: %s: section %u in section group %u out of range" msgstr "" -#: object.cc:486 +#: object.cc:515 #, c-format msgid "%s: %s: size of symbols is not multiple of symbol size\n" msgstr "" -#: object.cc:573 +#: object.cc:601 #, c-format msgid "%s: %s: unknown section index %u for local symbol %u\n" msgstr "" -#: object.cc:584 +#: object.cc:612 #, c-format msgid "%s: %s: local symbol %u section index %u out of range\n" msgstr "" #. elfcpp::ET_DYN -#: object.cc:763 +#: object.cc:800 #, c-format msgid "%s: %s: dynamic objects are not yet supported\n" msgstr "" -#: object.cc:787 object.cc:840 object.cc:861 +#: object.cc:824 object.cc:877 object.cc:898 #, c-format msgid "%s: %s: ELF file too short\n" msgstr "" -#: object.cc:796 +#: object.cc:833 #, c-format msgid "%s: %s: invalid ELF version 0\n" msgstr "" -#: object.cc:799 +#: object.cc:836 #, c-format msgid "%s: %s: unsupported ELF version %d\n" msgstr "" -#: object.cc:807 +#: object.cc:844 #, c-format msgid "%s: %s: invalid ELF class 0\n" msgstr "" -#: object.cc:814 +#: object.cc:851 #, c-format msgid "%s: %s: unsupported ELF class %d\n" msgstr "" -#: object.cc:822 +#: object.cc:859 #, c-format msgid "%s: %s: invalid ELF data encoding\n" msgstr "" -#: object.cc:829 +#: object.cc:866 #, c-format msgid "%s: %s: unsupported ELF data encoding %d\n" msgstr "" @@ -436,13 +436,13 @@ msgstr "" msgid "%s: %s: close: %s\n" msgstr "" -#: readsyms.cc:84 +#: readsyms.cc:85 #, c-format msgid "%s: %s: ordinary object found in input group\n" msgstr "" #. Here we have to handle any other input file types we need. -#: readsyms.cc:126 +#: readsyms.cc:129 #, c-format msgid "%s: %s: not an object or archive\n" msgstr "" @@ -477,21 +477,26 @@ msgstr "" msgid "%s: %s: unsupported symbol binding %d for symbol %s\n" msgstr "" -#: symtab.cc:429 +#: symtab.cc:432 #, c-format msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n" msgstr "" -#: symtab.cc:446 +#: symtab.cc:449 #, c-format msgid "%s: %s: bad global symbol name offset %u at %lu\n" msgstr "" -#: symtab.cc:854 symtab.cc:989 +#: symtab.cc:865 symtab.cc:1004 #, c-format msgid "%s: %s: unsupported symbol section 0x%x\n" msgstr "" +#: symtab.cc:1114 +#, c-format +msgid "%s: %s: warning: %s\n" +msgstr "" + #: target-reloc.h:181 #, c-format msgid "%s: %s: reloc has bad offset %zu\n" diff --git a/gold/readsyms.cc b/gold/readsyms.cc index 9ff7ab7d2b..c120fcb7cc 100644 --- a/gold/readsyms.cc +++ b/gold/readsyms.cc @@ -7,6 +7,7 @@ #include "elfcpp.h" #include "options.h" #include "dirsearch.h" +#include "symtab.h" #include "object.h" #include "archive.h" #include "readsyms.h" @@ -91,7 +92,8 @@ Read_symbols::run(Workqueue* workqueue) Read_symbols_data* sd = new Read_symbols_data; obj->read_symbols(sd); - workqueue->queue_front(new Add_symbols(this->input_objects_, + workqueue->queue_front(new Add_symbols(this->options_, + this->input_objects_, this->symtab_, this->layout_, obj, sd, this->this_blocker_, @@ -111,7 +113,8 @@ Read_symbols::run(Workqueue* workqueue) // This is an archive. Archive* arch = new Archive(this->input_.file().name(), input_file); arch->setup(); - workqueue->queue(new Add_archive_symbols(this->symtab_, + workqueue->queue(new Add_archive_symbols(this->options_, + this->symtab_, this->layout_, this->input_objects_, arch, @@ -159,7 +162,8 @@ Read_symbols::do_group(Workqueue* workqueue) } const int saw_undefined = this->symtab_->saw_undefined(); - workqueue->queue(new Finish_group(this->input_objects_, + workqueue->queue(new Finish_group(this->options_, + this->input_objects_, this->symtab_, this->layout_, input_group, @@ -217,7 +221,8 @@ void Add_symbols::run(Workqueue*) { this->input_objects_->add_object(this->object_); - this->object_->layout(this->layout_, this->sd_); + this->object_->layout(this->options_, this->symtab_, this->layout_, + this->sd_); this->object_->add_symbols(this->symtab_, this->sd_); delete this->sd_; this->sd_ = NULL; @@ -265,7 +270,7 @@ Finish_group::run(Workqueue*) { Task_lock_obj tl(**p); - (*p)->add_symbols(this->symtab_, this->layout_, + (*p)->add_symbols(this->options_, this->symtab_, this->layout_, this->input_objects_); } } diff --git a/gold/readsyms.h b/gold/readsyms.h index 2348c3237c..6631011eb4 100644 --- a/gold/readsyms.h +++ b/gold/readsyms.h @@ -83,11 +83,12 @@ class Add_symbols : public Task // THIS_BLOCKER is used to prevent this task from running before the // one for the previous input file. NEXT_BLOCKER is used to prevent // the next task from running. - Add_symbols(Input_objects* input_objects, Symbol_table* symtab, - Layout* layout, Object* object, Read_symbols_data* sd, - Task_token* this_blocker, Task_token* next_blocker) - : input_objects_(input_objects), symtab_(symtab), layout_(layout), - object_(object), sd_(sd), this_blocker_(this_blocker), + Add_symbols(const General_options& options, Input_objects* input_objects, + Symbol_table* symtab, Layout* layout, Object* object, + Read_symbols_data* sd, Task_token* this_blocker, + Task_token* next_blocker) + : options_(options), input_objects_(input_objects), symtab_(symtab), + layout_(layout), object_(object), sd_(sd), this_blocker_(this_blocker), next_blocker_(next_blocker) { } @@ -107,6 +108,7 @@ class Add_symbols : public Task private: class Add_symbols_locker; + const General_options& options_; Input_objects* input_objects_; Symbol_table* symtab_; Layout* layout_; @@ -153,13 +155,14 @@ class Input_group class Finish_group : public Task { public: - Finish_group(Input_objects* input_objects, Symbol_table* symtab, - Layout* layout, Input_group* input_group, + Finish_group(const General_options& options, Input_objects* input_objects, + Symbol_table* symtab, Layout* layout, Input_group* input_group, int saw_undefined, Task_token* this_blocker, Task_token* next_blocker) - : input_objects_(input_objects), symtab_(symtab), layout_(layout), - input_group_(input_group), saw_undefined_(saw_undefined), - this_blocker_(this_blocker), next_blocker_(next_blocker) + : options_(options), input_objects_(input_objects), symtab_(symtab), + layout_(layout), input_group_(input_group), + saw_undefined_(saw_undefined), this_blocker_(this_blocker), + next_blocker_(next_blocker) { } ~Finish_group(); @@ -176,6 +179,7 @@ class Finish_group : public Task run(Workqueue*); private: + const General_options& options_; Input_objects* input_objects_; Symbol_table* symtab_; Layout* layout_; diff --git a/gold/reloc.cc b/gold/reloc.cc index ca5e380dd9..7233266fa3 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -140,7 +140,7 @@ Relocate_task::run(Workqueue*) template void -Sized_object::do_read_relocs(Read_relocs_data* rd) +Sized_relobj::do_read_relocs(Read_relocs_data* rd) { rd->relocs.clear(); @@ -248,7 +248,7 @@ Sized_object::do_read_relocs(Read_relocs_data* rd) template void -Sized_object::do_scan_relocs(const General_options& options, +Sized_relobj::do_scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, Read_relocs_data* rd) @@ -285,7 +285,7 @@ Sized_object::do_scan_relocs(const General_options& options, template void -Sized_object::do_relocate(const General_options& options, +Sized_relobj::do_relocate(const General_options& options, const Symbol_table* symtab, const Layout* layout, Output_file* of) @@ -327,7 +327,7 @@ Sized_object::do_relocate(const General_options& options, template void -Sized_object::write_sections(const unsigned char* pshdrs, +Sized_relobj::write_sections(const unsigned char* pshdrs, Output_file* of, Views* pviews) { @@ -374,7 +374,7 @@ Sized_object::write_sections(const unsigned char* pshdrs, template void -Sized_object::relocate_sections( +Sized_relobj::relocate_sections( const General_options& options, const Symbol_table* symtab, const Layout* layout, @@ -475,72 +475,72 @@ Sized_object::relocate_sections( template void -Sized_object<32, false>::do_read_relocs(Read_relocs_data* rd); +Sized_relobj<32, false>::do_read_relocs(Read_relocs_data* rd); template void -Sized_object<32, true>::do_read_relocs(Read_relocs_data* rd); +Sized_relobj<32, true>::do_read_relocs(Read_relocs_data* rd); template void -Sized_object<64, false>::do_read_relocs(Read_relocs_data* rd); +Sized_relobj<64, false>::do_read_relocs(Read_relocs_data* rd); template void -Sized_object<64, true>::do_read_relocs(Read_relocs_data* rd); +Sized_relobj<64, true>::do_read_relocs(Read_relocs_data* rd); template void -Sized_object<32, false>::do_scan_relocs(const General_options& options, +Sized_relobj<32, false>::do_scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); template void -Sized_object<32, true>::do_scan_relocs(const General_options& options, +Sized_relobj<32, true>::do_scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); template void -Sized_object<64, false>::do_scan_relocs(const General_options& options, +Sized_relobj<64, false>::do_scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); template void -Sized_object<64, true>::do_scan_relocs(const General_options& options, +Sized_relobj<64, true>::do_scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); template void -Sized_object<32, false>::do_relocate(const General_options& options, +Sized_relobj<32, false>::do_relocate(const General_options& options, const Symbol_table* symtab, const Layout* layout, Output_file* of); template void -Sized_object<32, true>::do_relocate(const General_options& options, +Sized_relobj<32, true>::do_relocate(const General_options& options, const Symbol_table* symtab, const Layout* layout, Output_file* of); template void -Sized_object<64, false>::do_relocate(const General_options& options, +Sized_relobj<64, false>::do_relocate(const General_options& options, const Symbol_table* symtab, const Layout* layout, Output_file* of); template void -Sized_object<64, true>::do_relocate(const General_options& options, +Sized_relobj<64, true>::do_relocate(const General_options& options, const Symbol_table* symtab, const Layout* layout, Output_file* of); diff --git a/gold/reloc.h b/gold/reloc.h index f8f07b8b19..9b0518e5d9 100644 --- a/gold/reloc.h +++ b/gold/reloc.h @@ -10,7 +10,7 @@ namespace gold { -class Object; +class Relobj; class Read_relocs_data; class Stringpool; class Layout; @@ -25,7 +25,7 @@ class Read_relocs : public Task // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be // unblocked when the Scan_relocs task completes. Read_relocs(const General_options& options, Symbol_table* symtab, - Layout* layout, Object* object, Task_token* symtab_lock, + Layout* layout, Relobj* object, Task_token* symtab_lock, Task_token* blocker) : options_(options), symtab_(symtab), layout_(layout), object_(object), symtab_lock_(symtab_lock), blocker_(blocker) @@ -46,7 +46,7 @@ class Read_relocs : public Task const General_options& options_; Symbol_table* symtab_; Layout* layout_; - Object* object_; + Relobj* object_; Task_token* symtab_lock_; Task_token* blocker_; }; @@ -60,7 +60,7 @@ class Scan_relocs : public Task // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be // unblocked when the task completes. Scan_relocs(const General_options& options, Symbol_table* symtab, - Layout* layout, Object* object, Read_relocs_data* rd, + Layout* layout, Relobj* object, Read_relocs_data* rd, Task_token* symtab_lock, Task_token* blocker) : options_(options), symtab_(symtab), layout_(layout), object_(object), rd_(rd), symtab_lock_(symtab_lock), blocker_(blocker) @@ -83,7 +83,7 @@ class Scan_relocs : public Task const General_options& options_; Symbol_table* symtab_; Layout* layout_; - Object* object_; + Relobj* object_; Read_relocs_data* rd_; Task_token* symtab_lock_; Task_token* blocker_; @@ -95,7 +95,7 @@ class Relocate_task : public Task { public: Relocate_task(const General_options& options, const Symbol_table* symtab, - const Layout* layout, Object* object, Output_file* of, + const Layout* layout, Relobj* object, Output_file* of, Task_token* final_blocker) : options_(options), symtab_(symtab), layout_(layout), object_(object), of_(of), final_blocker_(final_blocker) @@ -118,327 +118,11 @@ class Relocate_task : public Task const General_options& options_; const Symbol_table* symtab_; const Layout* layout_; - Object* object_; + Relobj* object_; Output_file* of_; Task_token* final_blocker_; }; -// Integer swapping routines used by relocation functions. FIXME: -// Maybe these should be more general, and/or shared with elfcpp. - -// Endian simply indicates whether the host is big endian or not, -// based on the results of the configure script. - -struct Endian -{ - public: - // Used for template specializations. -#ifdef WORDS_BIGENDIAN - static const bool host_big_endian = true; -#else - static const bool host_big_endian = false; -#endif -}; - -// Valtype_base is a template based on size (8, 16, 32, 64) which -// defines a typedef Valtype for the unsigned integer of the specified -// size. - -template -struct Valtype_base; - -template<> -struct Valtype_base<8> -{ - typedef unsigned char Valtype; -}; - -template<> -struct Valtype_base<16> -{ - typedef uint16_t Valtype; -}; - -template<> -struct Valtype_base<32> -{ - typedef uint32_t Valtype; -}; - -template<> -struct Valtype_base<64> -{ - typedef uint64_t Valtype; -}; - -// Convert_host is a template based on size and on whether the host -// and target have the same endianness. It defines the type Valtype, -// and defines a function convert_host which takes an argument of type -// Valtype and swaps it if the host and target have different -// endianness. - -template -struct Convert_host; - -template -struct Convert_host -{ - typedef typename Valtype_base::Valtype Valtype; - - static inline Valtype - convert_host(Valtype v) - { return v; } -}; - -template<> -struct Convert_host<8, false> -{ - typedef Valtype_base<8>::Valtype Valtype; - - static inline Valtype - convert_host(Valtype v) - { return v; } -}; - -template<> -struct Convert_host<16, false> -{ - typedef Valtype_base<16>::Valtype Valtype; - - static inline Valtype - convert_host(Valtype v) - { return bswap_16(v); } -}; - -template<> -struct Convert_host<32, false> -{ - typedef Valtype_base<32>::Valtype Valtype; - - static inline Valtype - convert_host(Valtype v) - { return bswap_32(v); } -}; - -template<> -struct Convert_host<64, false> -{ - typedef Valtype_base<64>::Valtype Valtype; - - static inline Valtype - convert_host(Valtype v) - { return bswap_64(v); } -}; - -// Convert is a template based on size and on whether we have a big -// endian target. It defines Valtype and convert_host like -// Convert_host. That is, it is just like Convert_host except in the -// meaning of the second template parameter. - -template -struct Convert -{ - typedef typename Valtype_base::Valtype Valtype; - - static inline Valtype - convert_host(Valtype v) - { return Convert_host - ::convert_host(v); } -}; - -// Swap is a template based on size and on whether the target is big -// endian. It defines the type Valtype and the functions readval and -// writeval. The functions read and write values of the appropriate -// size out of buffers, swapping them if necessary. - -template -struct Swap -{ - typedef typename Valtype_base::Valtype Valtype; - - static inline Valtype - readval(const Valtype* wv) - { return Convert::convert_host(*wv); } - - static inline void - writeval(Valtype* wv, Valtype v) - { *wv = Convert::convert_host(v); } -}; - -// Swap_unaligned is a template based on size and on whether the -// target is big endian. It defines the type Valtype and the -// functions readval_unaligned and writeval_unaligned. The functions -// read and write values of the appropriate size out of buffers which -// may be misaligned. - -template -class Swap_unaligned; - -template -class Swap_unaligned<8, big_endian> -{ -public: - typedef typename Valtype_base<8>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { return *wv; } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { *wv = v; } -}; - -template<> -class Swap_unaligned<16, false> -{ -public: - typedef Valtype_base<16>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { - return (wv[1] << 8) | wv[0]; - } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { - wv[1] = v >> 8; - wv[0] = v; - } -}; - -template<> -class Swap_unaligned<16, true> -{ -public: - typedef Valtype_base<16>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { - return (wv[0] << 8) | wv[1]; - } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { - wv[0] = v >> 8; - wv[1] = v; - } -}; - -template<> -class Swap_unaligned<32, false> -{ -public: - typedef Valtype_base<32>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { - return (wv[3] << 24) | (wv[2] << 16) | (wv[1] << 8) | wv[0]; - } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { - wv[3] = v >> 24; - wv[2] = v >> 16; - wv[1] = v >> 8; - wv[0] = v; - } -}; - -template<> -class Swap_unaligned<32, true> -{ -public: - typedef Valtype_base<32>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { - return (wv[0] << 24) | (wv[1] << 16) | (wv[2] << 8) | wv[3]; - } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { - wv[0] = v >> 24; - wv[1] = v >> 16; - wv[2] = v >> 8; - wv[3] = v; - } -}; - -template<> -class Swap_unaligned<64, false> -{ -public: - typedef Valtype_base<64>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { - return ((static_cast(wv[7]) << 56) - | (static_cast(wv[6]) << 48) - | (static_cast(wv[5]) << 40) - | (static_cast(wv[4]) << 32) - | (static_cast(wv[3]) << 24) - | (static_cast(wv[2]) << 16) - | (static_cast(wv[1]) << 8) - | static_cast(wv[0])); - } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { - wv[7] = v >> 56; - wv[6] = v >> 48; - wv[5] = v >> 40; - wv[4] = v >> 32; - wv[3] = v >> 24; - wv[2] = v >> 16; - wv[1] = v >> 8; - wv[0] = v; - } -}; - -template<> -class Swap_unaligned<64, true> -{ -public: - typedef Valtype_base<64>::Valtype Valtype; - - static inline Valtype - readval_unaligned(const unsigned char* wv) - { - return ((static_cast(wv[0]) << 56) - | (static_cast(wv[1]) << 48) - | (static_cast(wv[2]) << 40) - | (static_cast(wv[3]) << 32) - | (static_cast(wv[4]) << 24) - | (static_cast(wv[5]) << 16) - | (static_cast(wv[6]) << 8) - | static_cast(wv[7])); - } - - static inline void - writeval_unaligned(unsigned char* wv, Valtype v) - { - wv[7] = v >> 56; - wv[6] = v >> 48; - wv[5] = v >> 40; - wv[4] = v >> 32; - wv[3] = v >> 24; - wv[2] = v >> 16; - wv[1] = v >> 8; - wv[0] = v; - } -}; - // Standard relocation routines which are used on many targets. Here // SIZE and BIG_ENDIAN refer to the target, not the relocation type. @@ -450,25 +134,27 @@ private: // VALSIZE is the size of the value. template static inline void - rel(unsigned char* view, typename Swap::Valtype value) + rel(unsigned char* view, + typename elfcpp::Swap::Valtype value) { - typedef typename Swap::Valtype Valtype; + typedef typename elfcpp::Swap::Valtype Valtype; Valtype* wv = reinterpret_cast(view); - Valtype x = Swap::readval(wv); - Swap::writeval(wv, x + value); + Valtype x = elfcpp::Swap::readval(wv); + elfcpp::Swap::writeval(wv, x + value); } // Do a simple PC relative relocation with the addend in the section // contents. VALSIZE is the size of the value. template static inline void - pcrel(unsigned char* view, typename Swap::Valtype value, + pcrel(unsigned char* view, + typename elfcpp::Swap::Valtype value, typename elfcpp::Elf_types::Elf_Addr address) { - typedef typename Swap::Valtype Valtype; + typedef typename elfcpp::Swap::Valtype Valtype; Valtype* wv = reinterpret_cast(view); - Valtype x = Swap::readval(wv); - Swap::writeval(wv, x + value - address); + Valtype x = elfcpp::Swap::readval(wv); + elfcpp::Swap::writeval(wv, x + value - address); } typedef Relocate_functions This; @@ -528,7 +214,7 @@ public: // Do a simple 64-bit REL relocation with the addend in the section // contents. static inline void - rel64(unsigned char* view, elfcpp::Elf_Word value) + rel64(unsigned char* view, elfcpp::Elf_Xword value) { This::template rel<64>(view, value); } @@ -536,7 +222,7 @@ public: // Do a simple 64-bit PC relative REL relocation with the addend in // the section contents. static inline void - pcrel64(unsigned char* view, elfcpp::Elf_Word value, + pcrel64(unsigned char* view, elfcpp::Elf_Xword value, typename elfcpp::Elf_types::Elf_Addr address) { This::template pcrel<64>(view, value, address); diff --git a/gold/symtab.cc b/gold/symtab.cc index 9adb9defc5..091144a75c 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -37,6 +37,7 @@ Symbol::init_fields(const char* name, const char* version, this->is_forwarder_ = false; this->in_dyn_ = false; this->has_got_offset_ = false; + this->has_warning_ = false; } // Initialize the fields in the base class Symbol for SYM in OBJECT. @@ -159,7 +160,7 @@ Sized_symbol::init(const char* name, Value_type value, Size_type symsize, Symbol_table::Symbol_table() : size_(0), saw_undefined_(0), offset_(0), table_(), namepool_(), - forwarders_(), commons_() + forwarders_(), commons_(), warnings_() { } @@ -279,7 +280,7 @@ Symbol_table::resolve(Sized_symbol* to, const Sized_symbol* from template Symbol* -Symbol_table::add_from_object(Sized_object* object, +Symbol_table::add_from_object(Object* object, const char *name, const char *version, bool def, const elfcpp::Sym& sym) @@ -360,7 +361,9 @@ Symbol_table::add_from_object(Sized_object* object, } else { - Sized_target* target = object->sized_target(); + Sized_target* target = + object->sized_target SELECT_SIZE_ENDIAN_NAME(size, big_endian) ( + SELECT_SIZE_ENDIAN_ONLY(size, big_endian)); if (!target->has_make_symbol()) ret = new Sized_symbol(); else @@ -408,13 +411,13 @@ Symbol_table::add_from_object(Sized_object* object, return ret; } -// Add all the symbols in an object to the hash table. +// Add all the symbols in a relocatable object to the hash table. template void Symbol_table::add_from_object( - Sized_object* object, - const elfcpp::Sym* syms, + Relobj* object, + const unsigned char* syms, size_t count, const char* sym_names, size_t sym_name_size, @@ -433,7 +436,7 @@ Symbol_table::add_from_object( const int sym_size = elfcpp::Elf_sizes::sym_size; - const unsigned char* p = reinterpret_cast(syms); + const unsigned char* p = syms; for (size_t i = 0; i < count; ++i, p += sym_size) { elfcpp::Sym sym(p); @@ -512,7 +515,7 @@ Symbol_table::define_special_symbol(Target* target, const char* name, if (only_if_ref) { oldsym = this->lookup(name, NULL); - if (oldsym == NULL) + if (oldsym == NULL || !oldsym->is_undefined()) return NULL; sym = NULL; @@ -810,12 +813,20 @@ Symbol_table::define_symbols(const Layout* layout, Target* target, int count, off_t Symbol_table::finalize(off_t off, Stringpool* pool) { + off_t ret; + if (this->size_ == 32) - return this->sized_finalize<32>(off, pool); + ret = this->sized_finalize<32>(off, pool); else if (this->size_ == 64) - return this->sized_finalize<64>(off, pool); + ret = this->sized_finalize<64>(off, pool); else abort(); + + // Now that we have the final symbol table, we can reliably note + // which symbols should get warnings. + this->warnings_.note_warnings(this); + + return ret; } // Set the final value for all the symbols. This is called after @@ -856,15 +867,21 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool) gold_exit(false); } - if (shnum == elfcpp::SHN_UNDEF) + Object* symobj = sym->object(); + if (symobj->is_dynamic()) + { + value = 0; + shnum = elfcpp::SHN_UNDEF; + } + else if (shnum == elfcpp::SHN_UNDEF) value = 0; else if (shnum == elfcpp::SHN_ABS) value = sym->value(); else { + Relobj* relobj = static_cast(symobj); off_t secoff; - Output_section* os = sym->object()->output_section(shnum, - &secoff); + Output_section* os = relobj->output_section(shnum, &secoff); if (os == NULL) { @@ -973,8 +990,6 @@ Symbol_table::sized_write_globals(const Target*, { Sized_symbol* sym = static_cast*>(p->second); - // FIXME: This repeats sized_finalize(). - unsigned int shndx; switch (sym->source()) { @@ -991,13 +1006,19 @@ Symbol_table::sized_write_globals(const Target*, gold_exit(false); } - if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS) + Object* symobj = sym->object(); + if (symobj->is_dynamic()) + { + // FIXME. + shndx = elfcpp::SHN_UNDEF; + } + else if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS) shndx = shnum; else { + Relobj* relobj = static_cast(symobj); off_t secoff; - Output_section* os = sym->object()->output_section(shnum, - &secoff); + Output_section* os = relobj->output_section(shnum, &secoff); if (os == NULL) continue; @@ -1037,6 +1058,63 @@ Symbol_table::sized_write_globals(const Target*, of->write_output_view(this->offset_, this->output_count_ * sym_size, psyms); } +// Warnings functions. + +// Add a new warning. + +void +Warnings::add_warning(Symbol_table* symtab, const char* name, Object* obj, + unsigned int shndx) +{ + name = symtab->canonicalize_name(name); + this->warnings_[name].set(obj, shndx); +} + +// Look through the warnings and mark the symbols for which we should +// warn. This is called during Layout::finalize when we know the +// sources for all the symbols. + +void +Warnings::note_warnings(Symbol_table* symtab) +{ + for (Warning_table::iterator p = this->warnings_.begin(); + p != this->warnings_.end(); + ++p) + { + Symbol* sym = symtab->lookup(p->first, NULL); + if (sym != NULL + && sym->source() == Symbol::FROM_OBJECT + && sym->object() == p->second.object) + { + sym->set_has_warning(); + + // Read the section contents to get the warning text. It + // would be nicer if we only did this if we have to actually + // issue a warning. Unfortunately, warnings are issued as + // we relocate sections. That means that we can not lock + // the object then, as we might try to issue the same + // warning multiple times simultaneously. + const unsigned char* c; + off_t len; + c = p->second.object->section_contents(p->second.shndx, &len); + p->second.set_text(reinterpret_cast(c), len); + } + } +} + +// Issue a warning. This is called when we see a relocation against a +// symbol for which has a warning. + +void +Warnings::issue_warning(Symbol* sym, const std::string& location) const +{ + assert(sym->has_warning()); + Warning_table::const_iterator p = this->warnings_.find(sym->name()); + assert(p != this->warnings_.end()); + fprintf(stderr, _("%s: %s: warning: %s\n"), program_name, location.c_str(), + p->second.text.c_str()); +} + // Instantiate the templates we need. We could use the configure // script to restrict this to only the ones needed for implemented // targets. @@ -1044,8 +1122,8 @@ Symbol_table::sized_write_globals(const Target*, template void Symbol_table::add_from_object<32, true>( - Sized_object<32, true>* object, - const elfcpp::Sym<32, true>* syms, + Relobj* object, + const unsigned char* syms, size_t count, const char* sym_names, size_t sym_name_size, @@ -1054,8 +1132,8 @@ Symbol_table::add_from_object<32, true>( template void Symbol_table::add_from_object<32, false>( - Sized_object<32, false>* object, - const elfcpp::Sym<32, false>* syms, + Relobj* object, + const unsigned char* syms, size_t count, const char* sym_names, size_t sym_name_size, @@ -1064,8 +1142,8 @@ Symbol_table::add_from_object<32, false>( template void Symbol_table::add_from_object<64, true>( - Sized_object<64, true>* object, - const elfcpp::Sym<64, true>* syms, + Relobj* object, + const unsigned char* syms, size_t count, const char* sym_names, size_t sym_name_size, @@ -1074,8 +1152,8 @@ Symbol_table::add_from_object<64, true>( template void Symbol_table::add_from_object<64, false>( - Sized_object<64, false>* object, - const elfcpp::Sym<64, false>* syms, + Relobj* object, + const unsigned char* syms, size_t count, const char* sym_names, size_t sym_name_size, diff --git a/gold/symtab.h b/gold/symtab.h index 2fa3396a5c..f544e0664d 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -10,6 +10,7 @@ #include "elfcpp.h" #include "stringpool.h" +#include "object.h" #ifndef GOLD_SYMTAB_H #define GOLD_SYMTAB_H @@ -18,14 +19,13 @@ namespace gold { class Object; +class Relobj; +class Dynobj; class Output_data; class Output_segment; class Output_file; class Target; -template -class Sized_object; - // The base class of an entry in the symbol table. The symbol table // can have a lot of entries, so we don't want this class to big. // Size dependent fields can be found in the template class @@ -40,7 +40,8 @@ class Symbol // sources of symbols we support. enum Source { - // Symbol defined in an input file--this is the most common case. + // Symbol defined in a relocatable or dynamic input file--this is + // the most common case. FROM_OBJECT, // Symbol defined in an Output_data, a special section created by // the target. @@ -89,7 +90,8 @@ class Symbol return this->u_.from_object.object; } - // Return the index of the section in the input object file. + // Return the index of the section in the input relocatable or + // dynamic object file. unsigned int shnum() const { @@ -167,12 +169,12 @@ class Symbol set_forwarder() { this->is_forwarder_ = true; } - // Return whether this symbol was seen in a dynamic object. + // Return whether this symbol was ever seen in a dynamic object. bool in_dyn() const { return this->in_dyn_; } - // Mark this symbol as seen in a dynamic object. + // Mark this symbol as having been seen in a dynamic object. void set_in_dyn() { this->in_dyn_ = true; } @@ -207,6 +209,16 @@ class Symbol is_resolved_locally() const { return !this->in_dyn_; } + // Return whether this is a defined symbol (not undefined or + // common). + bool + is_defined() const + { + return (this->source_ != FROM_OBJECT + || (this->u_.from_object.shnum != elfcpp::SHN_UNDEF + && this->u_.from_object.shnum != elfcpp::SHN_COMMON)); + } + // Return whether this is an undefined symbol. bool is_undefined() const @@ -218,14 +230,27 @@ class Symbol bool is_common() const { - return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_COMMON; + return (this->source_ == FROM_OBJECT + && (this->u_.from_object.shnum == elfcpp::SHN_COMMON + || this->type_ == elfcpp::STT_COMMON)); } + // Return whether there should be a warning for references to this + // symbol. + bool + has_warning() const + { return this->has_warning_; } + + // Mark this symbol as having a warning. + void + set_has_warning() + { this->has_warning_ = true; } + protected: // Instances of this class should always be created at a specific // size. Symbol() - { } + { memset(this, 0, sizeof *this); } // Initialize the general fields. void @@ -317,7 +342,7 @@ class Symbol // Rest of symbol st_other field. unsigned int nonvis_ : 6; // The type of symbol. - Source source_ : 2; + Source source_ : 3; // True if this symbol always requires special target-specific // handling. bool is_target_special_ : 1; @@ -335,6 +360,8 @@ class Symbol bool in_dyn_ : 1; // True if the symbol has an entry in the GOT section. bool has_got_offset_ : 1; + // True if there is a warning for this symbol. + bool has_warning_ : 1; }; // The parts of a symbol which are size specific. Using a template @@ -484,6 +511,78 @@ struct Define_symbol_in_segment bool only_if_ref; }; +// This class manages warnings. Warnings are a GNU extension. When +// we see a section named .gnu.warning.SYM in an object file, and if +// we wind using the definition of SYM from that object file, then we +// will issue a warning for any relocation against SYM from a +// different object file. The text of the warning is the contents of +// the section. This is not precisely the definition used by the old +// GNU linker; the old GNU linker treated an occurrence of +// .gnu.warning.SYM as defining a warning symbol. A warning symbol +// would trigger a warning on any reference. However, it was +// inconsistent in that a warning in a dynamic object only triggered +// if there was no definition in a regular object. This linker is +// different in that we only issue a warning if we use the symbol +// definition from the same object file as the warning section. + +class Warnings +{ + public: + Warnings() + : warnings_() + { } + + // Add a warning for symbol NAME in section SHNDX in object OBJ. + void + add_warning(Symbol_table* symtab, const char* name, Object* obj, + unsigned int shndx); + + // For each symbol for which we should give a warning, make a note + // on the symbol. + void + note_warnings(Symbol_table* symtab); + + // Issue a warning for a reference to SYM at LOCATION. + void + issue_warning(Symbol* sym, const std::string& location) const; + + private: + Warnings(const Warnings&); + Warnings& operator=(const Warnings&); + + // What we need to know to get the warning text. + struct Warning_location + { + // The object the warning is in. + Object* object; + // The index of the warning section. + unsigned int shndx; + // The warning text if we have already loaded it. + std::string text; + + Warning_location() + : object(NULL), shndx(0), text() + { } + + void + set(Object* o, unsigned int s) + { + this->object = o; + this->shndx = s; + } + + void + set_text(const char* t, off_t l) + { this->text.assign(t, l); } + }; + + // A mapping from warning symbol names (canonicalized in + // Symbol_table's namepool_ field) to + typedef Unordered_map Warning_table; + + Warning_table warnings_; +}; + // The main linker symbol table. class Symbol_table @@ -493,14 +592,13 @@ class Symbol_table ~Symbol_table(); - // Add COUNT external symbols from OBJECT to the symbol table. SYMS - // is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the - // size of SYM_NAMES. This sets SYMPOINTERS to point to the symbols - // in the symbol table. + // Add COUNT external symbols from the relocatable object OBJECT to + // the symbol table. SYMS is the symbols, SYM_NAMES is their names, + // SYM_NAME_SIZE is the size of SYM_NAMES. This sets SYMPOINTERS to + // point to the symbols in the symbol table. template void - add_from_object(Sized_object* object, - const elfcpp::Sym* syms, + add_from_object(Relobj* object, const unsigned char* syms, size_t count, const char* sym_names, size_t sym_name_size, Symbol** sympointers); @@ -577,6 +675,22 @@ class Symbol_table void allocate_commons(const General_options&, Layout*); + // Add a warning for symbol NAME in section SHNDX in object OBJ. + void + add_warning(const char* name, Object* obj, unsigned int shndx) + { this->warnings_.add_warning(this, name, obj, shndx); } + + // Canonicalize a symbol name for use in the hash table. + const char* + canonicalize_name(const char* name) + { return this->namepool_.add(name); } + + // Possibly issue a warning for a reference to SYM at LOCATION which + // is in OBJ. + void + issue_warning(Symbol* sym, const std::string& location) const + { this->warnings_.issue_warning(sym, location); } + // Finalize the symbol table after we have set the final addresses // of all the input sections. This sets the final symbol values and // adds the names to *POOL. It records the file offset OFF, and @@ -604,7 +718,7 @@ class Symbol_table // Add a symbol. template Symbol* - add_from_object(Sized_object*, const char *name, + add_from_object(Object*, const char *name, const char *version, bool def, const elfcpp::Sym& sym); @@ -720,6 +834,9 @@ class Symbol_table // symbol is no longer a common symbol. It may also have become a // forwarder. Commons_type commons_; + + // Manage symbol warnings. + Warnings warnings_; }; // We inline get_sized_symbol for efficiency. diff --git a/gold/target-reloc.h b/gold/target-reloc.h index ebaa8276cf..70692783e0 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -44,7 +44,7 @@ scan_relocs( Symbol_table* symtab, Layout* layout, Target_type* target, - Sized_object* object, + Sized_relobj* object, const unsigned char* prelocs, size_t reloc_count, size_t local_count, @@ -193,6 +193,9 @@ relocate_section( sym->name()); // gold_exit(false); } + + if (sym != NULL && sym->has_warning()) + relinfo->symtab->issue_warning(sym, relinfo->location(i, offset)); } } diff --git a/gold/target.h b/gold/target.h index b72998da35..8e00a4da5a 100644 --- a/gold/target.h +++ b/gold/target.h @@ -16,7 +16,6 @@ #include #include "elfcpp.h" -#include "symtab.h" namespace gold { @@ -24,9 +23,13 @@ namespace gold class General_options; class Object; template -class Sized_object; +class Sized_relobj; template struct Relocate_info; +class Symbol; +template +class Sized_symbol; +class Symbol_table; // The abstract class for target specific handling. @@ -150,7 +153,7 @@ class Sized_target : public Target scan_relocs(const General_options& options, Symbol_table* symtab, Layout* layout, - Sized_object* object, + Sized_relobj* object, unsigned int sh_type, const unsigned char* prelocs, size_t reloc_count, -- 2.34.1