diff options
author | Ian Lance Taylor <ian@airs.com> | 2008-07-22 22:08:43 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2008-07-22 22:08:43 +0000 |
commit | 92de84a60cbdb80b808c8571e709c1384c6ee6fc (patch) | |
tree | 850dc6691e2bef093d847da5d35241b98b04e2ea /gold/archive.cc | |
parent | 3f7c5e1d995c658ef8709e5fae244f25434db931 (diff) | |
download | gdb-92de84a60cbdb80b808c8571e709c1384c6ee6fc.zip gdb-92de84a60cbdb80b808c8571e709c1384c6ee6fc.tar.gz gdb-92de84a60cbdb80b808c8571e709c1384c6ee6fc.tar.bz2 |
* cref.cc: New file.
* cref.h: New file.
* options.h (class General_options): Add --print-symbol-counts.
* main.cc (main): Issue defined symbol report if requested.
* archive.cc (Archive::interpret_header): Make into a const member
function.
(Archive::add_symbols): Call Input_objects::archive_start and
archive_stop.
(Archive::const_iterator): Define new class.
(Archive::begin, Archive::end): New functions.
(Archive::include_all_members): Rewrite to use iterator.
(Archive::count_members): New function.
* archive.h (class Archive): Update declarations.
(Archive::filename): New function.
* object.cc: Include "cref.h".
(Sized_relobj::Sized_relobj): Initialize defined_count_.
(Sized_relobj::do_get_global_symbol_counts): New function.
(Input_objects::add_object): Add object to cross-referencer.
(Input_objects::archive_start): New function.
(Input_objects::archive_stop): New function.
(Input_objects::print_symbol_counts): New function.
* object.h: Declare Cref and Archive.
(Object::get_global_symbol_counts): New function.
(Object::do_get_global_symbol_counts): New pure virtual function.
(class Sized_relobj): Add defined_count_ field. Update
declarations.
(class Input_objects): Add cref_ field. Update constructor.
Update declarations.
* dynobj.cc (Sized_dynobj::Sized_dynobj): Initialize symbols_ and
defined_count_.
(Sized_dynobj::do_add_symbols): Allocate symbols_ if printing
symbol counts.
(Sized_dynobj::do_get_global_symbol_counts): New function.
* dynobj.h (class Sized_dynobj): Add fields symbols_ and
defined_count_. Update declarations. Define Symbols typedef.
* symtab.cc (Symbol_table::add_from_relobj): Add defined
parameter. Change all callers.
(Symbol_table::add_from_dynobj): Add sympointers and defined
parameters. Change all callers.
* symtab.h (class Symbol_table): Update declarations.
* Makefile.am (CCFILES): Add cref.cc.
(HFILES): Add cref.h.
* Makefile.in: Rebuild.
Diffstat (limited to 'gold/archive.cc')
-rw-r--r-- | gold/archive.cc | 194 |
1 files changed, 155 insertions, 39 deletions
diff --git a/gold/archive.cc b/gold/archive.cc index 737f3e2..8d11797 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -191,7 +191,7 @@ Archive::read_header(off_t off, bool cache, std::string* pname, off_t Archive::interpret_header(const Archive_header* hdr, off_t off, - std::string* pname, off_t* nested_off) + std::string* pname, off_t* nested_off) const { if (memcmp(hdr->ar_fmag, arfmag, sizeof arfmag) != 0) { @@ -293,6 +293,8 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, return this->include_all_members(symtab, layout, input_objects, mapfile); + input_objects->archive_start(this); + const size_t armap_size = this->armap_.size(); // This is a quick optimization, since we usually see many symbols @@ -359,56 +361,170 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, } } while (added_new_object); + + input_objects->archive_stop(this); } -// Include all the archive members in the link. This is for --whole-archive. +// An archive member iterator. + +class Archive::const_iterator +{ + public: + // The header of an archive member. This is what this iterator + // points to. + struct Header + { + // The name of the member. + std::string name; + // The file offset of the member. + off_t off; + // The file offset of a nested archive member. + off_t nested_off; + // The size of the member. + off_t size; + }; + + const_iterator(const Archive* archive, off_t off) + : archive_(archive), off_(off) + { this->read_next_header(); } + + const Header& + operator*() const + { return this->header_; } + + const Header* + operator->() const + { return &this->header_; } + + const_iterator& + operator++() + { + if (this->off_ == this->archive_->file().filesize()) + return *this; + this->off_ += sizeof(Archive_header); + if (!this->archive_->is_thin_archive()) + this->off_ += this->header_.size; + if ((this->off_ & 1) != 0) + ++this->off_; + this->read_next_header(); + return *this; + } + + const_iterator + operator++(int) + { + const_iterator ret = *this; + ++*this; + return ret; + } + + bool + operator==(const const_iterator p) const + { return this->off_ == p->off; } + + bool + operator!=(const const_iterator p) const + { return this->off_ != p->off; } + + private: + void + read_next_header(); + + // The underlying archive. + const Archive* archive_; + // The current offset in the file. + off_t off_; + // The current archive header. + Header header_; +}; + +// Read the next archive header. void -Archive::include_all_members(Symbol_table* symtab, Layout* layout, - Input_objects* input_objects, Mapfile* mapfile) +Archive::const_iterator::read_next_header() { - off_t off = sarmag; - off_t filesize = this->input_file_->file().filesize(); + off_t filesize = this->archive_->file().filesize(); while (true) { - if (filesize - off < static_cast<off_t>(sizeof(Archive_header))) - { - if (filesize != off) - gold_error(_("%s: short archive header at %zu"), - this->name().c_str(), static_cast<size_t>(off)); - break; - } + if (filesize - this->off_ < static_cast<off_t>(sizeof(Archive_header))) + { + if (filesize != this->off_) + { + gold_error(_("%s: short archive header at %zu"), + this->archive_->filename().c_str(), + static_cast<size_t>(this->off_)); + this->off_ = filesize; + } + this->header_.off = filesize; + return; + } - unsigned char hdr_buf[sizeof(Archive_header)]; - this->input_file_->file().read(off, sizeof(Archive_header), hdr_buf); + unsigned char buf[sizeof(Archive_header)]; + this->archive_->file().read(this->off_, sizeof(Archive_header), buf); - const Archive_header* hdr = - reinterpret_cast<const Archive_header*>(hdr_buf); - std::string name; - off_t size = this->interpret_header(hdr, off, &name, NULL); - bool special_member = false; - if (name.empty()) - { - // Symbol table. - special_member = true; - } - else if (name == "/") - { - // Extended name table. - special_member = true; - } - else - this->include_member(symtab, layout, input_objects, off, - mapfile, NULL, "--whole-archive"); - - off += sizeof(Archive_header); - if (special_member || !this->is_thin_archive_) - off += size; - if ((off & 1) != 0) - ++off; + const Archive_header* hdr = reinterpret_cast<const Archive_header*>(buf); + this->header_.size = + this->archive_->interpret_header(hdr, this->off_, &this->header_.name, + &this->header_.nested_off); + this->header_.off = this->off_; + + // Skip special members. + if (!this->header_.name.empty() && this->header_.name != "/") + return; + + this->off_ += sizeof(Archive_header) + this->header_.size; + if ((this->off_ & 1) != 0) + ++this->off_; } } +// Initial iterator. + +Archive::const_iterator +Archive::begin() const +{ + return Archive::const_iterator(this, sarmag); +} + +// Final iterator. + +Archive::const_iterator +Archive::end() const +{ + return Archive::const_iterator(this, this->input_file_->file().filesize()); +} + +// Include all the archive members in the link. This is for --whole-archive. + +void +Archive::include_all_members(Symbol_table* symtab, Layout* layout, + Input_objects* input_objects, Mapfile* mapfile) +{ + input_objects->archive_start(this); + + for (Archive::const_iterator p = this->begin(); + p != this->end(); + ++p) + this->include_member(symtab, layout, input_objects, p->off, + mapfile, NULL, "--whole-archive"); + + input_objects->archive_stop(this); +} + +// Return the number of members in the archive. This is only used for +// reports. + +size_t +Archive::count_members() const +{ + size_t ret = 0; + for (Archive::const_iterator p = this->begin(); + p != this->end(); + ++p) + ++ret; + return ret; +} + // Include an archive member in the link. OFF is the file offset of // the member header. WHY is the reason we are including this member. |