// archive.h -- archive support for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
{
class Task;
+class Input_argument;
class Input_file;
class Input_objects;
class Input_group;
class Symbol_table;
class Object;
class Read_symbols_data;
+class Input_file_lib;
+class Incremental_archive_entry;
+
+// An entry in the archive map of offsets to members.
+struct Archive_member
+{
+ Archive_member()
+ : obj_(NULL), sd_(NULL)
+ { }
+ Archive_member(Object* obj, Read_symbols_data* sd)
+ : obj_(obj), sd_(sd)
+ { }
+ // The object file.
+ Object* obj_;
+ // The data to pass from read_symbols() to add_symbols().
+ Read_symbols_data* sd_;
+};
// This class represents an archive--generally a libNAME.a file.
// Archives have a symbol table and a list of objects.
{
public:
Archive(const std::string& name, Input_file* input_file,
- bool is_thin_archive, Dirsearch* dirpath, Task* task)
- : name_(name), input_file_(input_file), armap_(), armap_names_(),
- extended_names_(), armap_checked_(), seen_offsets_(), members_(),
- is_thin_archive_(is_thin_archive), nested_archives_(),
- dirpath_(dirpath), task_(task), num_members_(0)
- { }
+ bool is_thin_archive, Dirsearch* dirpath, Task* task);
// The length of the magic string at the start of an archive.
static const int sarmag = 8;
name() const
{ return this->name_; }
+ // The input file.
+ const Input_file*
+ input_file() const
+ { return this->input_file_; }
+
// The file name.
const std::string&
filename() const
// Set up the archive: read the symbol map.
void
- setup(Input_objects*);
+ setup();
// Get a reference to the underlying file.
File_read&
// Select members from the archive as needed and add them to the
// link.
- void
+ bool
add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
+ // Return whether the archive defines the symbol.
+ bool
+ defines_symbol(Symbol*) const;
+
// Dump statistical information to stderr.
static void
print_stats();
size_t
count_members();
+ // Return the no-export flag.
+ bool
+ no_export()
+ { return this->no_export_; }
+
+ // Store a pointer to the incremental link info for the archive.
+ void
+ set_incremental_info(Incremental_archive_entry* info)
+ { this->incremental_info_ = info; }
+
+ // Return the pointer to the incremental link info for the archive.
+ Incremental_archive_entry*
+ incremental_info() const
+ { return this->incremental_info_; }
+
+ // When we see a symbol in an archive we might decide to include the member,
+ // not include the member or be undecided. This enum represents these
+ // possibilities.
+
+ enum Should_include
+ {
+ SHOULD_INCLUDE_NO,
+ SHOULD_INCLUDE_YES,
+ SHOULD_INCLUDE_UNKNOWN
+ };
+
+ static Should_include
+ should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
+ Symbol** symp, std::string* why, char** tmpbufp,
+ size_t* tmpbuflen);
+
+ private:
+ struct Armap_entry;
+
+ public:
+ // Iterator class for unused global symbols. This iterator is used
+ // for incremental links.
+
+ class Unused_symbol_iterator
+ {
+ public:
+ Unused_symbol_iterator(Archive* arch,
+ std::vector<Armap_entry>::const_iterator it)
+ : arch_(arch), it_(it)
+ { this->skip_used_symbols(); }
+
+ const char*
+ operator*() const
+ { return this->arch_->armap_names_.data() + this->it_->name_offset; }
+
+ Unused_symbol_iterator&
+ operator++()
+ {
+ ++this->it_;
+ this->skip_used_symbols();
+ return *this;
+ }
+
+ bool
+ operator==(const Unused_symbol_iterator p) const
+ { return this->it_ == p.it_; }
+
+ bool
+ operator!=(const Unused_symbol_iterator p) const
+ { return this->it_ != p.it_; }
+
+ private:
+ // Skip over symbols defined by members that have been included.
+ void
+ skip_used_symbols()
+ {
+ while (this->it_ != this->arch_->armap_.end()
+ && (this->arch_->seen_offsets_.find(this->it_->file_offset)
+ != this->arch_->seen_offsets_.end()))
+ ++it_;
+ }
+
+ // The underlying archive.
+ Archive* arch_;
+
+ // The underlying iterator over all entries in the archive map.
+ std::vector<Armap_entry>::const_iterator it_;
+ };
+
+ // Return an iterator referring to the first unused symbol.
+ Unused_symbol_iterator
+ unused_symbols_begin()
+ { return Unused_symbol_iterator(this, this->armap_.begin()); }
+
+ // Return an iterator referring to the end of the unused symbols.
+ Unused_symbol_iterator
+ unused_symbols_end()
+ { return Unused_symbol_iterator(this, this->armap_.end()); }
+
private:
Archive(const Archive&);
Archive& operator=(const Archive&);
// within that file (0 if not a nested archive), and *MEMBER_NAME
// to the name of the archive member. Return TRUE on success.
bool
- get_file_and_offset(off_t off, Input_objects* input_objects,
- Input_file** input_file, off_t* memoff,
- std::string* member_name);
+ get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
+ off_t* memsize, std::string* member_name);
- // Return an ELF object for the member at offset OFF. Set *MEMBER_NAME to
- // the name of the member.
+ // Return an ELF object for the member at offset OFF.
Object*
- get_elf_object_for_member(off_t off, Input_objects* input_objects);
+ get_elf_object_for_member(off_t off, bool*);
// Read the symbols from all the archive members in the link.
void
- read_all_symbols(Input_objects* input_objects);
+ read_all_symbols();
// Read the symbols from an archive member in the link. OFF is the file
// offset of the member header.
void
- read_symbols(Input_objects* input_objects, off_t off);
+ read_symbols(off_t off);
// Include all the archive members in the link.
- void
+ bool
include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*);
// Include an archive member in the link.
- void
+ bool
include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
Mapfile*, Symbol*, const char* why);
+ // Return whether we found this archive by searching a directory.
+ bool
+ searched_for() const
+ { return this->input_file_->will_search_for(); }
+
// Iterate over archive members.
class const_iterator;
off_t file_offset;
};
- // An entry in the archive map of offsets to members.
- struct Archive_member
- {
- Archive_member()
- : obj_(NULL), sd_(NULL)
- { }
- Archive_member(Object* obj, Read_symbols_data* sd)
- : obj_(obj), sd_(sd)
- { }
- // The object file.
- Object* obj_;
- // The data to pass from read_symbols() to add_symbols().
- Read_symbols_data* sd_;
- };
-
// A simple hash code for off_t values.
class Seen_hash
{
std::map<off_t, Archive_member> members_;
// True if this is a thin archive.
const bool is_thin_archive_;
+ // True if we have included at least one object from this archive.
+ bool included_member_;
// Table of nested archives, indexed by filename.
Nested_archive_table nested_archives_;
// The directory search path.
Dirsearch* dirpath_;
// The task reading this archive.
- Task *task_;
+ Task* task_;
// Number of members in this archive;
unsigned int num_members_;
+ // True if we exclude this library archive from automatic export.
+ bool no_export_;
+ // The incremental link information for this archive.
+ Incremental_archive_entry* incremental_info_;
};
// This class is used to read an archive and pick out the desired
{
public:
Add_archive_symbols(Symbol_table* symtab, Layout* layout,
- Input_objects* input_objects, Mapfile* mapfile,
+ Input_objects* input_objects, Dirsearch* dirpath,
+ int dirindex, Mapfile* mapfile,
+ const Input_argument* input_argument,
Archive* archive, Input_group* input_group,
Task_token* this_blocker,
Task_token* next_blocker)
: symtab_(symtab), layout_(layout), input_objects_(input_objects),
- mapfile_(mapfile), archive_(archive), input_group_(input_group),
- this_blocker_(this_blocker), next_blocker_(next_blocker)
+ dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
+ input_argument_(input_argument), archive_(archive),
+ input_group_(input_group), this_blocker_(this_blocker),
+ next_blocker_(next_blocker)
{ }
~Add_archive_symbols();
Symbol_table* symtab_;
Layout* layout_;
Input_objects* input_objects_;
+ Dirsearch* dirpath_;
+ int dirindex_;
Mapfile* mapfile_;
+ const Input_argument* input_argument_;
Archive* archive_;
Input_group* input_group_;
Task_token* this_blocker_;
Task_token* next_blocker_;
};
+// This class represents the files surrounded by a --start-lib ... --end-lib.
+
+class Lib_group
+{
+ public:
+ Lib_group(const Input_file_lib* lib, Task* task);
+
+ // Select members from the lib group as needed and add them to the link.
+ void
+ add_symbols(Symbol_table*, Layout*, Input_objects*);
+
+ // Include a member of the lib group in the link.
+ void
+ include_member(Symbol_table*, Layout*, Input_objects*, const Archive_member&);
+
+ Archive_member*
+ get_member(int i)
+ {
+ return &this->members_[i];
+ }
+
+ // Dump statistical information to stderr.
+ static void
+ print_stats();
+
+ // Total number of archives seen.
+ static unsigned int total_lib_groups;
+ // Total number of archive members seen.
+ static unsigned int total_members;
+ // Number of archive members loaded.
+ static unsigned int total_members_loaded;
+
+ private:
+ // For reading the files.
+ const Input_file_lib* lib_;
+ // The task reading this lib group.
+ Task* task_;
+ // Table of the objects in the group.
+ std::vector<Archive_member> members_;
+};
+
+// This class is used to pick out the desired elements and add them to the link.
+
+class Add_lib_group_symbols : public Task
+{
+ public:
+ Add_lib_group_symbols(Symbol_table* symtab, Layout* layout,
+ Input_objects* input_objects,
+ Lib_group* lib, Task_token* next_blocker)
+ : symtab_(symtab), layout_(layout), input_objects_(input_objects),
+ lib_(lib), readsyms_blocker_(NULL), this_blocker_(NULL),
+ next_blocker_(next_blocker)
+ { }
+
+ ~Add_lib_group_symbols();
+
+ // The standard Task methods.
+
+ Task_token*
+ is_runnable();
+
+ void
+ locks(Task_locker*);
+
+ void
+ run(Workqueue*);
+
+ // Set the blocker to use for this task.
+ void
+ set_blocker(Task_token* readsyms_blocker, Task_token* this_blocker)
+ {
+ gold_assert(this->readsyms_blocker_ == NULL && this->this_blocker_ == NULL);
+ this->readsyms_blocker_ = readsyms_blocker;
+ this->this_blocker_ = this_blocker;
+ }
+
+ std::string
+ get_name() const
+ {
+ return "Add_lib_group_symbols";
+ }
+
+ private:
+ Symbol_table* symtab_;
+ Layout* layout_;
+ Input_objects* input_objects_;
+ Lib_group* lib_;
+ Task_token* readsyms_blocker_;
+ Task_token* this_blocker_;
+ Task_token* next_blocker_;
+};
+
} // End namespace gold.
#endif // !defined(GOLD_ARCHIVE_H)