1ed0d50c3Schristos // archive.h -- archive support for gold      -*- C++ -*-
2ed0d50c3Schristos 
3*b88e3e88Schristos // Copyright (C) 2006-2020 Free Software Foundation, Inc.
4ed0d50c3Schristos // Written by Ian Lance Taylor <iant@google.com>.
5ed0d50c3Schristos 
6ed0d50c3Schristos // This file is part of gold.
7ed0d50c3Schristos 
8ed0d50c3Schristos // This program is free software; you can redistribute it and/or modify
9ed0d50c3Schristos // it under the terms of the GNU General Public License as published by
10ed0d50c3Schristos // the Free Software Foundation; either version 3 of the License, or
11ed0d50c3Schristos // (at your option) any later version.
12ed0d50c3Schristos 
13ed0d50c3Schristos // This program is distributed in the hope that it will be useful,
14ed0d50c3Schristos // but WITHOUT ANY WARRANTY; without even the implied warranty of
15ed0d50c3Schristos // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16ed0d50c3Schristos // GNU General Public License for more details.
17ed0d50c3Schristos 
18ed0d50c3Schristos // You should have received a copy of the GNU General Public License
19ed0d50c3Schristos // along with this program; if not, write to the Free Software
20ed0d50c3Schristos // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21ed0d50c3Schristos // MA 02110-1301, USA.
22ed0d50c3Schristos 
23ed0d50c3Schristos #ifndef GOLD_ARCHIVE_H
24ed0d50c3Schristos #define GOLD_ARCHIVE_H
25ed0d50c3Schristos 
26ed0d50c3Schristos #include <string>
27ed0d50c3Schristos #include <vector>
28ed0d50c3Schristos 
29ed0d50c3Schristos #include "fileread.h"
30ed0d50c3Schristos #include "workqueue.h"
31ed0d50c3Schristos 
32ed0d50c3Schristos namespace gold
33ed0d50c3Schristos {
34ed0d50c3Schristos 
35ed0d50c3Schristos class Task;
36ed0d50c3Schristos class Input_argument;
37ed0d50c3Schristos class Input_file;
38ed0d50c3Schristos class Input_objects;
39ed0d50c3Schristos class Input_group;
40ed0d50c3Schristos class Layout;
41ed0d50c3Schristos class Symbol_table;
42ed0d50c3Schristos class Object;
43ed0d50c3Schristos struct Read_symbols_data;
44ed0d50c3Schristos class Input_file_lib;
45ed0d50c3Schristos class Incremental_archive_entry;
46ed0d50c3Schristos 
47ed0d50c3Schristos // An entry in the archive map of offsets to members.
48ed0d50c3Schristos struct Archive_member
49ed0d50c3Schristos {
Archive_memberArchive_member50ed0d50c3Schristos   Archive_member()
51ed0d50c3Schristos       : obj_(NULL), sd_(NULL), arg_serial_(0)
52ed0d50c3Schristos   { }
Archive_memberArchive_member53ed0d50c3Schristos   Archive_member(Object* obj, Read_symbols_data* sd)
54ed0d50c3Schristos       : obj_(obj), sd_(sd), arg_serial_(0)
55ed0d50c3Schristos   { }
56ed0d50c3Schristos   // The object file.
57ed0d50c3Schristos   Object* obj_;
58ed0d50c3Schristos   // The data to pass from read_symbols() to add_symbols().
59ed0d50c3Schristos   Read_symbols_data* sd_;
60ed0d50c3Schristos   // The serial number of the file in the argument list.
61ed0d50c3Schristos   unsigned int arg_serial_;
62ed0d50c3Schristos };
63ed0d50c3Schristos 
64ed0d50c3Schristos // This class serves as a base class for Archive and Lib_group objects.
65ed0d50c3Schristos 
66ed0d50c3Schristos class Library_base
67ed0d50c3Schristos {
68ed0d50c3Schristos  public:
Library_base(Task * task)69ed0d50c3Schristos   Library_base(Task* task)
70ed0d50c3Schristos     : task_(task), incremental_info_(NULL)
71ed0d50c3Schristos   { }
72ed0d50c3Schristos 
73ed0d50c3Schristos   virtual
~Library_base()74ed0d50c3Schristos   ~Library_base()
75ed0d50c3Schristos   { }
76ed0d50c3Schristos 
77ed0d50c3Schristos   // The file name.
78ed0d50c3Schristos   const std::string&
filename()79ed0d50c3Schristos   filename() const
80ed0d50c3Schristos   { return this->do_filename(); }
81ed0d50c3Schristos 
82ed0d50c3Schristos   // The modification time of the archive file.
83ed0d50c3Schristos   Timespec
get_mtime()84ed0d50c3Schristos   get_mtime()
85ed0d50c3Schristos   { return this->do_get_mtime(); }
86ed0d50c3Schristos 
87ed0d50c3Schristos   // When we see a symbol in an archive we might decide to include the member,
88ed0d50c3Schristos   // not include the member or be undecided. This enum represents these
89ed0d50c3Schristos   // possibilities.
90ed0d50c3Schristos 
91ed0d50c3Schristos   enum Should_include
92ed0d50c3Schristos   {
93ed0d50c3Schristos     SHOULD_INCLUDE_NO,
94ed0d50c3Schristos     SHOULD_INCLUDE_YES,
95ed0d50c3Schristos     SHOULD_INCLUDE_UNKNOWN
96ed0d50c3Schristos   };
97ed0d50c3Schristos 
98ed0d50c3Schristos   static Should_include
99ed0d50c3Schristos   should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
100ed0d50c3Schristos                         Symbol** symp, std::string* why, char** tmpbufp,
101ed0d50c3Schristos                         size_t* tmpbuflen);
102ed0d50c3Schristos 
103ed0d50c3Schristos   // Store a pointer to the incremental link info for the library.
104ed0d50c3Schristos   void
set_incremental_info(Incremental_archive_entry * info)105ed0d50c3Schristos   set_incremental_info(Incremental_archive_entry* info)
106ed0d50c3Schristos   { this->incremental_info_ = info; }
107ed0d50c3Schristos 
108ed0d50c3Schristos   // Return the pointer to the incremental link info for the library.
109ed0d50c3Schristos   Incremental_archive_entry*
incremental_info()110ed0d50c3Schristos   incremental_info() const
111ed0d50c3Schristos   { return this->incremental_info_; }
112ed0d50c3Schristos 
113ed0d50c3Schristos   // Abstract base class for processing unused symbols.
114ed0d50c3Schristos   class Symbol_visitor_base
115ed0d50c3Schristos   {
116ed0d50c3Schristos    public:
Symbol_visitor_base()117ed0d50c3Schristos     Symbol_visitor_base()
118ed0d50c3Schristos     { }
119ed0d50c3Schristos 
120ed0d50c3Schristos     virtual
~Symbol_visitor_base()121ed0d50c3Schristos     ~Symbol_visitor_base()
122ed0d50c3Schristos     { }
123ed0d50c3Schristos 
124ed0d50c3Schristos     // This function will be called for each unused global
125ed0d50c3Schristos     // symbol in a library, with a pointer to the symbol name.
126ed0d50c3Schristos     virtual void
127ed0d50c3Schristos     visit(const char* /* name */) = 0;
128ed0d50c3Schristos   };
129ed0d50c3Schristos 
130ed0d50c3Schristos   // Iterator for unused global symbols in the library.
131ed0d50c3Schristos   // Calls v->visit() for each global symbol defined
132ed0d50c3Schristos   // in each unused library member, passing a pointer to
133ed0d50c3Schristos   // the symbol name.
134ed0d50c3Schristos   void
for_all_unused_symbols(Symbol_visitor_base * v)135ed0d50c3Schristos   for_all_unused_symbols(Symbol_visitor_base* v) const
136ed0d50c3Schristos   { this->do_for_all_unused_symbols(v); }
137ed0d50c3Schristos 
138ed0d50c3Schristos  protected:
139ed0d50c3Schristos   // The task reading this archive.
140ed0d50c3Schristos   Task *task_;
141ed0d50c3Schristos 
142ed0d50c3Schristos  private:
143ed0d50c3Schristos   // The file name.
144ed0d50c3Schristos   virtual const std::string&
145ed0d50c3Schristos   do_filename() const = 0;
146ed0d50c3Schristos 
147ed0d50c3Schristos   // Return the modification time of the archive file.
148ed0d50c3Schristos   virtual Timespec
149ed0d50c3Schristos   do_get_mtime() = 0;
150ed0d50c3Schristos 
151ed0d50c3Schristos   // Iterator for unused global symbols in the library.
152ed0d50c3Schristos   virtual void
153ed0d50c3Schristos   do_for_all_unused_symbols(Symbol_visitor_base* v) const = 0;
154ed0d50c3Schristos 
155ed0d50c3Schristos   // The incremental link information for this archive.
156ed0d50c3Schristos   Incremental_archive_entry* incremental_info_;
157ed0d50c3Schristos };
158ed0d50c3Schristos 
159ed0d50c3Schristos // This class represents an archive--generally a libNAME.a file.
160ed0d50c3Schristos // Archives have a symbol table and a list of objects.
161ed0d50c3Schristos 
162ed0d50c3Schristos class Archive : public Library_base
163ed0d50c3Schristos {
164ed0d50c3Schristos  public:
165ed0d50c3Schristos   Archive(const std::string& name, Input_file* input_file,
166ed0d50c3Schristos           bool is_thin_archive, Dirsearch* dirpath, Task* task);
167ed0d50c3Schristos 
168ed0d50c3Schristos   // The length of the magic string at the start of an archive.
169ed0d50c3Schristos   static const int sarmag = 8;
170ed0d50c3Schristos 
171ed0d50c3Schristos   // The magic string at the start of an archive.
172ed0d50c3Schristos   static const char armag[sarmag];
173ed0d50c3Schristos   static const char armagt[sarmag];
174ed0d50c3Schristos 
175ed0d50c3Schristos   // The string expected at the end of an archive member header.
176ed0d50c3Schristos   static const char arfmag[2];
177ed0d50c3Schristos 
178ed0d50c3Schristos   // Name of 64-bit symbol table member.
179ed0d50c3Schristos   static const char sym64name[7];
180ed0d50c3Schristos 
181ed0d50c3Schristos   // The name of the object.  This is the name used on the command
182ed0d50c3Schristos   // line; e.g., if "-lgcc" is on the command line, this will be
183ed0d50c3Schristos   // "gcc".
184ed0d50c3Schristos   const std::string&
name()185ed0d50c3Schristos   name() const
186ed0d50c3Schristos   { return this->name_; }
187ed0d50c3Schristos 
188ed0d50c3Schristos   // The input file.
189ed0d50c3Schristos   const Input_file*
input_file()190ed0d50c3Schristos   input_file() const
191ed0d50c3Schristos   { return this->input_file_; }
192ed0d50c3Schristos 
193ed0d50c3Schristos   // Set up the archive: read the symbol map.
194ed0d50c3Schristos   void
195ed0d50c3Schristos   setup();
196ed0d50c3Schristos 
197ed0d50c3Schristos   // Get a reference to the underlying file.
198ed0d50c3Schristos   File_read&
file()199ed0d50c3Schristos   file()
200ed0d50c3Schristos   { return this->input_file_->file(); }
201ed0d50c3Schristos 
202ed0d50c3Schristos   const File_read&
file()203ed0d50c3Schristos   file() const
204ed0d50c3Schristos   { return this->input_file_->file(); }
205ed0d50c3Schristos 
206ed0d50c3Schristos   // Lock the underlying file.
207ed0d50c3Schristos   void
lock(const Task * t)208ed0d50c3Schristos   lock(const Task* t)
209ed0d50c3Schristos   { this->input_file_->file().lock(t); }
210ed0d50c3Schristos 
211ed0d50c3Schristos   // Unlock the underlying file.
212ed0d50c3Schristos   void
unlock(const Task * t)213ed0d50c3Schristos   unlock(const Task* t)
214ed0d50c3Schristos   { this->input_file_->file().unlock(t); }
215ed0d50c3Schristos 
216ed0d50c3Schristos   // Return whether the underlying file is locked.
217ed0d50c3Schristos   bool
is_locked()218ed0d50c3Schristos   is_locked() const
219ed0d50c3Schristos   { return this->input_file_->file().is_locked(); }
220ed0d50c3Schristos 
221ed0d50c3Schristos   // Return the token, so that the task can be queued.
222ed0d50c3Schristos   Task_token*
token()223ed0d50c3Schristos   token()
224ed0d50c3Schristos   { return this->input_file_->file().token(); }
225ed0d50c3Schristos 
226ed0d50c3Schristos   // Release the underlying file.
227ed0d50c3Schristos   void
release()228ed0d50c3Schristos   release()
229ed0d50c3Schristos   { this->input_file_->file().release(); }
230ed0d50c3Schristos 
231ed0d50c3Schristos   // Clear uncached views in the underlying file.
232ed0d50c3Schristos   void
clear_uncached_views()233ed0d50c3Schristos   clear_uncached_views()
234ed0d50c3Schristos   { this->input_file_->file().clear_uncached_views(); }
235ed0d50c3Schristos 
236ed0d50c3Schristos   // Whether this is a thin archive.
237ed0d50c3Schristos   bool
is_thin_archive()238ed0d50c3Schristos   is_thin_archive() const
239ed0d50c3Schristos   { return this->is_thin_archive_; }
240ed0d50c3Schristos 
241ed0d50c3Schristos   // Unlock any nested archives.
242ed0d50c3Schristos   void
243ed0d50c3Schristos   unlock_nested_archives();
244ed0d50c3Schristos 
245ed0d50c3Schristos   // Select members from the archive as needed and add them to the
246ed0d50c3Schristos   // link.
247ed0d50c3Schristos   bool
248ed0d50c3Schristos   add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
249ed0d50c3Schristos 
250ed0d50c3Schristos   // Return whether the archive defines the symbol.
251ed0d50c3Schristos   bool
252ed0d50c3Schristos   defines_symbol(Symbol*) const;
253ed0d50c3Schristos 
254ed0d50c3Schristos   // Dump statistical information to stderr.
255ed0d50c3Schristos   static void
256ed0d50c3Schristos   print_stats();
257ed0d50c3Schristos 
258ed0d50c3Schristos   // Return the number of members in the archive.
259ed0d50c3Schristos   size_t
260ed0d50c3Schristos   count_members();
261ed0d50c3Schristos 
262ed0d50c3Schristos   // Return the no-export flag.
263ed0d50c3Schristos   bool
no_export()264ed0d50c3Schristos   no_export()
265ed0d50c3Schristos   { return this->no_export_; }
266ed0d50c3Schristos 
267ed0d50c3Schristos  private:
268ed0d50c3Schristos   Archive(const Archive&);
269ed0d50c3Schristos   Archive& operator=(const Archive&);
270ed0d50c3Schristos 
271ed0d50c3Schristos   // The file name.
272ed0d50c3Schristos   const std::string&
do_filename()273ed0d50c3Schristos   do_filename() const
274ed0d50c3Schristos   { return this->input_file_->filename(); }
275ed0d50c3Schristos 
276ed0d50c3Schristos   // The modification time of the archive file.
277ed0d50c3Schristos   Timespec
do_get_mtime()278ed0d50c3Schristos   do_get_mtime()
279ed0d50c3Schristos   { return this->file().get_mtime(); }
280ed0d50c3Schristos 
281ed0d50c3Schristos   struct Archive_header;
282ed0d50c3Schristos 
283ed0d50c3Schristos   // Total number of archives seen.
284ed0d50c3Schristos   static unsigned int total_archives;
285ed0d50c3Schristos   // Total number of archive members seen.
286ed0d50c3Schristos   static unsigned int total_members;
287ed0d50c3Schristos   // Number of archive members loaded.
288ed0d50c3Schristos   static unsigned int total_members_loaded;
289ed0d50c3Schristos 
290ed0d50c3Schristos   // Get a view into the underlying file.
291ed0d50c3Schristos   const unsigned char*
get_view(off_t start,section_size_type size,bool aligned,bool cache)292ed0d50c3Schristos   get_view(off_t start, section_size_type size, bool aligned, bool cache)
293ed0d50c3Schristos   { return this->input_file_->file().get_view(0, start, size, aligned, cache); }
294ed0d50c3Schristos 
295ed0d50c3Schristos   // Read the archive symbol map.
296ed0d50c3Schristos   template<int mapsize>
297ed0d50c3Schristos   void
298ed0d50c3Schristos   read_armap(off_t start, section_size_type size);
299ed0d50c3Schristos 
300ed0d50c3Schristos   // Read an archive member header at OFF.  CACHE is whether to cache
301ed0d50c3Schristos   // the file view.  Return the size of the member, and set *PNAME to
302ed0d50c3Schristos   // the name.
303ed0d50c3Schristos   off_t
304ed0d50c3Schristos   read_header(off_t off, bool cache, std::string* pname, off_t* nested_off);
305ed0d50c3Schristos 
306ed0d50c3Schristos   // Interpret an archive header HDR at OFF.  Return the size of the
307ed0d50c3Schristos   // member, and set *PNAME to the name.
308ed0d50c3Schristos   off_t
309ed0d50c3Schristos   interpret_header(const Archive_header* hdr, off_t off, std::string* pname,
310ed0d50c3Schristos                    off_t* nested_off) const;
311ed0d50c3Schristos 
312ed0d50c3Schristos   // Get the file and offset for an archive member, which may be an
313ed0d50c3Schristos   // external member of a thin archive.  Set *INPUT_FILE to the
314ed0d50c3Schristos   // file containing the actual member, *MEMOFF to the offset
315ed0d50c3Schristos   // within that file (0 if not a nested archive), and *MEMBER_NAME
316ed0d50c3Schristos   // to the name of the archive member.  Return TRUE on success.
317ed0d50c3Schristos   bool
318ed0d50c3Schristos   get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
319ed0d50c3Schristos                       off_t* memsize, std::string* member_name);
320ed0d50c3Schristos 
321ed0d50c3Schristos   // Return an ELF object for the member at offset OFF.
322ed0d50c3Schristos   Object*
323ed0d50c3Schristos   get_elf_object_for_member(off_t off, bool*);
324ed0d50c3Schristos 
325ed0d50c3Schristos   // Read the symbols from all the archive members in the link.
326ed0d50c3Schristos   void
327ed0d50c3Schristos   read_all_symbols();
328ed0d50c3Schristos 
329ed0d50c3Schristos   // Read the symbols from an archive member in the link.  OFF is the file
330ed0d50c3Schristos   // offset of the member header.
331ed0d50c3Schristos   void
332ed0d50c3Schristos   read_symbols(off_t off);
333ed0d50c3Schristos 
334ed0d50c3Schristos   // Include all the archive members in the link.
335ed0d50c3Schristos   bool
336ed0d50c3Schristos   include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*);
337ed0d50c3Schristos 
338ed0d50c3Schristos   // Include an archive member in the link.
339ed0d50c3Schristos   bool
340ed0d50c3Schristos   include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
341ed0d50c3Schristos 		 Mapfile*, Symbol*, const char* why);
342ed0d50c3Schristos 
343ed0d50c3Schristos   // Return whether we found this archive by searching a directory.
344ed0d50c3Schristos   bool
searched_for()345ed0d50c3Schristos   searched_for() const
346ed0d50c3Schristos   { return this->input_file_->will_search_for(); }
347ed0d50c3Schristos 
348ed0d50c3Schristos   // Iterate over archive members.
349ed0d50c3Schristos   class const_iterator;
350ed0d50c3Schristos 
351ed0d50c3Schristos   const_iterator
352ed0d50c3Schristos   begin();
353ed0d50c3Schristos 
354ed0d50c3Schristos   const_iterator
355ed0d50c3Schristos   end();
356ed0d50c3Schristos 
357ed0d50c3Schristos   friend class const_iterator;
358ed0d50c3Schristos 
359ed0d50c3Schristos   // Iterator for unused global symbols in the library.
360ed0d50c3Schristos   void
361ed0d50c3Schristos   do_for_all_unused_symbols(Symbol_visitor_base* v) const;
362ed0d50c3Schristos 
363ed0d50c3Schristos   // An entry in the archive map of symbols to object files.
364ed0d50c3Schristos   struct Armap_entry
365ed0d50c3Schristos   {
366ed0d50c3Schristos     // The offset to the symbol name in armap_names_.
367ed0d50c3Schristos     off_t name_offset;
368ed0d50c3Schristos     // The file offset to the object in the archive.
369ed0d50c3Schristos     off_t file_offset;
370ed0d50c3Schristos   };
371ed0d50c3Schristos 
372ed0d50c3Schristos   // A simple hash code for off_t values.
373ed0d50c3Schristos   class Seen_hash
374ed0d50c3Schristos   {
375ed0d50c3Schristos    public:
operator()376ed0d50c3Schristos     size_t operator()(off_t val) const
377ed0d50c3Schristos     { return static_cast<size_t>(val); }
378ed0d50c3Schristos   };
379ed0d50c3Schristos 
380ed0d50c3Schristos   // For keeping track of open nested archives in a thin archive file.
381ed0d50c3Schristos   typedef Unordered_map<std::string, Archive*> Nested_archive_table;
382ed0d50c3Schristos 
383ed0d50c3Schristos   // Name of object as printed to user.
384ed0d50c3Schristos   std::string name_;
385ed0d50c3Schristos   // For reading the file.
386ed0d50c3Schristos   Input_file* input_file_;
387ed0d50c3Schristos   // The archive map.
388ed0d50c3Schristos   std::vector<Armap_entry> armap_;
389ed0d50c3Schristos   // The names in the archive map.
390ed0d50c3Schristos   std::string armap_names_;
391ed0d50c3Schristos   // The extended name table.
392ed0d50c3Schristos   std::string extended_names_;
393ed0d50c3Schristos   // Track which symbols in the archive map are for elements which are
394ed0d50c3Schristos   // defined or which have already been included in the link.
395ed0d50c3Schristos   std::vector<bool> armap_checked_;
396ed0d50c3Schristos   // Track which elements have been included by offset.
397ed0d50c3Schristos   Unordered_set<off_t, Seen_hash> seen_offsets_;
398ed0d50c3Schristos   // Table of objects whose symbols have been pre-read.
399ed0d50c3Schristos   std::map<off_t, Archive_member> members_;
400ed0d50c3Schristos   // True if this is a thin archive.
401ed0d50c3Schristos   const bool is_thin_archive_;
402ed0d50c3Schristos   // True if we have included at least one object from this archive.
403ed0d50c3Schristos   bool included_member_;
404ed0d50c3Schristos   // Table of nested archives, indexed by filename.
405ed0d50c3Schristos   Nested_archive_table nested_archives_;
406ed0d50c3Schristos   // The directory search path.
407ed0d50c3Schristos   Dirsearch* dirpath_;
408ed0d50c3Schristos   // Number of members in this archive;
409ed0d50c3Schristos   unsigned int num_members_;
410ed0d50c3Schristos   // True if we exclude this library archive from automatic export.
411ed0d50c3Schristos   bool no_export_;
412ed0d50c3Schristos   // True if this library has been included as a --whole-archive.
413ed0d50c3Schristos   bool included_all_members_;
414ed0d50c3Schristos };
415ed0d50c3Schristos 
416ed0d50c3Schristos // This class is used to read an archive and pick out the desired
417ed0d50c3Schristos // elements and add them to the link.
418ed0d50c3Schristos 
419ed0d50c3Schristos class Add_archive_symbols : public Task
420ed0d50c3Schristos {
421ed0d50c3Schristos  public:
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)422ed0d50c3Schristos   Add_archive_symbols(Symbol_table* symtab, Layout* layout,
423ed0d50c3Schristos 		      Input_objects* input_objects, Dirsearch* dirpath,
424ed0d50c3Schristos 		      int dirindex, Mapfile* mapfile,
425ed0d50c3Schristos 		      const Input_argument* input_argument,
426ed0d50c3Schristos 		      Archive* archive, Input_group* input_group,
427ed0d50c3Schristos 		      Task_token* this_blocker,
428ed0d50c3Schristos 		      Task_token* next_blocker)
429ed0d50c3Schristos     : symtab_(symtab), layout_(layout), input_objects_(input_objects),
430ed0d50c3Schristos       dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
431ed0d50c3Schristos       input_argument_(input_argument), archive_(archive),
432ed0d50c3Schristos       input_group_(input_group), this_blocker_(this_blocker),
433ed0d50c3Schristos       next_blocker_(next_blocker)
434ed0d50c3Schristos   { }
435ed0d50c3Schristos 
436ed0d50c3Schristos   ~Add_archive_symbols();
437ed0d50c3Schristos 
438ed0d50c3Schristos   // The standard Task methods.
439ed0d50c3Schristos 
440ed0d50c3Schristos   Task_token*
441ed0d50c3Schristos   is_runnable();
442ed0d50c3Schristos 
443ed0d50c3Schristos   void
444ed0d50c3Schristos   locks(Task_locker*);
445ed0d50c3Schristos 
446ed0d50c3Schristos   void
447ed0d50c3Schristos   run(Workqueue*);
448ed0d50c3Schristos 
449ed0d50c3Schristos   std::string
get_name()450ed0d50c3Schristos   get_name() const
451ed0d50c3Schristos   {
452ed0d50c3Schristos     if (this->archive_ == NULL)
453ed0d50c3Schristos       return "Add_archive_symbols";
454ed0d50c3Schristos     return "Add_archive_symbols " + this->archive_->file().filename();
455ed0d50c3Schristos   }
456ed0d50c3Schristos 
457ed0d50c3Schristos  private:
458ed0d50c3Schristos   Symbol_table* symtab_;
459ed0d50c3Schristos   Layout* layout_;
460ed0d50c3Schristos   Input_objects* input_objects_;
461ed0d50c3Schristos   Dirsearch* dirpath_;
462ed0d50c3Schristos   int dirindex_;
463ed0d50c3Schristos   Mapfile* mapfile_;
464ed0d50c3Schristos   const Input_argument* input_argument_;
465ed0d50c3Schristos   Archive* archive_;
466ed0d50c3Schristos   Input_group* input_group_;
467ed0d50c3Schristos   Task_token* this_blocker_;
468ed0d50c3Schristos   Task_token* next_blocker_;
469ed0d50c3Schristos };
470ed0d50c3Schristos 
471ed0d50c3Schristos // This class represents the files surrounded by a --start-lib ... --end-lib.
472ed0d50c3Schristos 
473ed0d50c3Schristos class Lib_group : public Library_base
474ed0d50c3Schristos {
475ed0d50c3Schristos  public:
476ed0d50c3Schristos   Lib_group(const Input_file_lib* lib, Task* task);
477ed0d50c3Schristos 
478ed0d50c3Schristos   // Select members from the lib group as needed and add them to the link.
479ed0d50c3Schristos   void
480ed0d50c3Schristos   add_symbols(Symbol_table*, Layout*, Input_objects*);
481ed0d50c3Schristos 
482ed0d50c3Schristos   // Include a member of the lib group in the link.
483ed0d50c3Schristos   void
484ed0d50c3Schristos   include_member(Symbol_table*, Layout*, Input_objects*, const Archive_member&);
485ed0d50c3Schristos 
486ed0d50c3Schristos   Archive_member*
get_member(int i)487ed0d50c3Schristos   get_member(int i)
488ed0d50c3Schristos   {
489ed0d50c3Schristos     return &this->members_[i];
490ed0d50c3Schristos   }
491ed0d50c3Schristos 
492ed0d50c3Schristos   // Total number of archives seen.
493ed0d50c3Schristos   static unsigned int total_lib_groups;
494ed0d50c3Schristos   // Total number of archive members seen.
495ed0d50c3Schristos   static unsigned int total_members;
496ed0d50c3Schristos   // Number of archive members loaded.
497ed0d50c3Schristos   static unsigned int total_members_loaded;
498ed0d50c3Schristos 
499ed0d50c3Schristos   // Dump statistical information to stderr.
500ed0d50c3Schristos   static void
501ed0d50c3Schristos   print_stats();
502ed0d50c3Schristos 
503ed0d50c3Schristos  private:
504ed0d50c3Schristos   // The file name.
505ed0d50c3Schristos   const std::string&
506ed0d50c3Schristos   do_filename() const;
507ed0d50c3Schristos 
508ed0d50c3Schristos   // A Lib_group does not have a modification time, since there is no
509ed0d50c3Schristos   // real library file.
510ed0d50c3Schristos   Timespec
do_get_mtime()511ed0d50c3Schristos   do_get_mtime()
512ed0d50c3Schristos   { return Timespec(0, 0); }
513ed0d50c3Schristos 
514ed0d50c3Schristos   // Iterator for unused global symbols in the library.
515ed0d50c3Schristos   void
516ed0d50c3Schristos   do_for_all_unused_symbols(Symbol_visitor_base*) const;
517ed0d50c3Schristos 
518ed0d50c3Schristos   // Table of the objects in the group.
519ed0d50c3Schristos   std::vector<Archive_member> members_;
520ed0d50c3Schristos };
521ed0d50c3Schristos 
522ed0d50c3Schristos // This class is used to pick out the desired elements and add them to the link.
523ed0d50c3Schristos 
524ed0d50c3Schristos class Add_lib_group_symbols : public Task
525ed0d50c3Schristos {
526ed0d50c3Schristos  public:
Add_lib_group_symbols(Symbol_table * symtab,Layout * layout,Input_objects * input_objects,Lib_group * lib,Task_token * next_blocker)527ed0d50c3Schristos   Add_lib_group_symbols(Symbol_table* symtab, Layout* layout,
528ed0d50c3Schristos                         Input_objects* input_objects,
529ed0d50c3Schristos                         Lib_group* lib, Task_token* next_blocker)
530ed0d50c3Schristos       : symtab_(symtab), layout_(layout), input_objects_(input_objects),
531ed0d50c3Schristos         lib_(lib), readsyms_blocker_(NULL), this_blocker_(NULL),
532ed0d50c3Schristos         next_blocker_(next_blocker)
533ed0d50c3Schristos   { }
534ed0d50c3Schristos 
535ed0d50c3Schristos   ~Add_lib_group_symbols();
536ed0d50c3Schristos 
537ed0d50c3Schristos   // The standard Task methods.
538ed0d50c3Schristos 
539ed0d50c3Schristos   Task_token*
540ed0d50c3Schristos   is_runnable();
541ed0d50c3Schristos 
542ed0d50c3Schristos   void
543ed0d50c3Schristos   locks(Task_locker*);
544ed0d50c3Schristos 
545ed0d50c3Schristos   void
546ed0d50c3Schristos   run(Workqueue*);
547ed0d50c3Schristos 
548ed0d50c3Schristos   // Set the blocker to use for this task.
549ed0d50c3Schristos   void
set_blocker(Task_token * readsyms_blocker,Task_token * this_blocker)550ed0d50c3Schristos   set_blocker(Task_token* readsyms_blocker, Task_token* this_blocker)
551ed0d50c3Schristos   {
552ed0d50c3Schristos     gold_assert(this->readsyms_blocker_ == NULL && this->this_blocker_ == NULL);
553ed0d50c3Schristos     this->readsyms_blocker_ = readsyms_blocker;
554ed0d50c3Schristos     this->this_blocker_ = this_blocker;
555ed0d50c3Schristos   }
556ed0d50c3Schristos 
557ed0d50c3Schristos   std::string
get_name()558ed0d50c3Schristos   get_name() const
559ed0d50c3Schristos   {
560ed0d50c3Schristos     return "Add_lib_group_symbols";
561ed0d50c3Schristos   }
562ed0d50c3Schristos 
563ed0d50c3Schristos  private:
564ed0d50c3Schristos   Symbol_table* symtab_;
565ed0d50c3Schristos   Layout* layout_;
566ed0d50c3Schristos   Input_objects* input_objects_;
567ed0d50c3Schristos   Lib_group* lib_;
568ed0d50c3Schristos   Task_token* readsyms_blocker_;
569ed0d50c3Schristos   Task_token* this_blocker_;
570ed0d50c3Schristos   Task_token* next_blocker_;
571ed0d50c3Schristos };
572ed0d50c3Schristos 
573ed0d50c3Schristos } // End namespace gold.
574ed0d50c3Schristos 
575ed0d50c3Schristos #endif // !defined(GOLD_ARCHIVE_H)
576