1*a9fa9459Szrj // archive.cc -- archive support for gold
2*a9fa9459Szrj 
3*a9fa9459Szrj // Copyright (C) 2006-2016 Free Software Foundation, Inc.
4*a9fa9459Szrj // Written by Ian Lance Taylor <iant@google.com>.
5*a9fa9459Szrj 
6*a9fa9459Szrj // This file is part of gold.
7*a9fa9459Szrj 
8*a9fa9459Szrj // This program is free software; you can redistribute it and/or modify
9*a9fa9459Szrj // it under the terms of the GNU General Public License as published by
10*a9fa9459Szrj // the Free Software Foundation; either version 3 of the License, or
11*a9fa9459Szrj // (at your option) any later version.
12*a9fa9459Szrj 
13*a9fa9459Szrj // This program is distributed in the hope that it will be useful,
14*a9fa9459Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*a9fa9459Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*a9fa9459Szrj // GNU General Public License for more details.
17*a9fa9459Szrj 
18*a9fa9459Szrj // You should have received a copy of the GNU General Public License
19*a9fa9459Szrj // along with this program; if not, write to the Free Software
20*a9fa9459Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*a9fa9459Szrj // MA 02110-1301, USA.
22*a9fa9459Szrj 
23*a9fa9459Szrj #include "gold.h"
24*a9fa9459Szrj 
25*a9fa9459Szrj #include <cerrno>
26*a9fa9459Szrj #include <cstring>
27*a9fa9459Szrj #include <climits>
28*a9fa9459Szrj #include <vector>
29*a9fa9459Szrj #include "libiberty.h"
30*a9fa9459Szrj #include "filenames.h"
31*a9fa9459Szrj 
32*a9fa9459Szrj #include "elfcpp.h"
33*a9fa9459Szrj #include "options.h"
34*a9fa9459Szrj #include "mapfile.h"
35*a9fa9459Szrj #include "fileread.h"
36*a9fa9459Szrj #include "readsyms.h"
37*a9fa9459Szrj #include "symtab.h"
38*a9fa9459Szrj #include "object.h"
39*a9fa9459Szrj #include "layout.h"
40*a9fa9459Szrj #include "archive.h"
41*a9fa9459Szrj #include "plugin.h"
42*a9fa9459Szrj #include "incremental.h"
43*a9fa9459Szrj 
44*a9fa9459Szrj namespace gold
45*a9fa9459Szrj {
46*a9fa9459Szrj 
47*a9fa9459Szrj // Library_base methods.
48*a9fa9459Szrj 
49*a9fa9459Szrj // Determine whether a definition of SYM_NAME should cause an archive
50*a9fa9459Szrj // library member to be included in the link.  Returns SHOULD_INCLUDE_YES
51*a9fa9459Szrj // if the symbol is referenced but not defined, SHOULD_INCLUDE_NO if the
52*a9fa9459Szrj // symbol is already defined, and SHOULD_INCLUDE_UNKNOWN if the symbol is
53*a9fa9459Szrj // neither referenced nor defined.
54*a9fa9459Szrj 
55*a9fa9459Szrj Library_base::Should_include
should_include_member(Symbol_table * symtab,Layout * layout,const char * sym_name,Symbol ** symp,std::string * why,char ** tmpbufp,size_t * tmpbuflen)56*a9fa9459Szrj Library_base::should_include_member(Symbol_table* symtab, Layout* layout,
57*a9fa9459Szrj 				    const char* sym_name, Symbol** symp,
58*a9fa9459Szrj 				    std::string* why, char** tmpbufp,
59*a9fa9459Szrj 				    size_t* tmpbuflen)
60*a9fa9459Szrj {
61*a9fa9459Szrj   // In an object file, and therefore in an archive map, an
62*a9fa9459Szrj   // '@' in the name separates the symbol name from the
63*a9fa9459Szrj   // version name.  If there are two '@' characters, this is
64*a9fa9459Szrj   // the default version.
65*a9fa9459Szrj   char* tmpbuf = *tmpbufp;
66*a9fa9459Szrj   const char* ver = strchr(sym_name, '@');
67*a9fa9459Szrj   bool def = false;
68*a9fa9459Szrj   if (ver != NULL)
69*a9fa9459Szrj     {
70*a9fa9459Szrj       size_t symlen = ver - sym_name;
71*a9fa9459Szrj       if (symlen + 1 > *tmpbuflen)
72*a9fa9459Szrj         {
73*a9fa9459Szrj           tmpbuf = static_cast<char*>(xrealloc(tmpbuf, symlen + 1));
74*a9fa9459Szrj           *tmpbufp = tmpbuf;
75*a9fa9459Szrj           *tmpbuflen = symlen + 1;
76*a9fa9459Szrj         }
77*a9fa9459Szrj       memcpy(tmpbuf, sym_name, symlen);
78*a9fa9459Szrj       tmpbuf[symlen] = '\0';
79*a9fa9459Szrj       sym_name = tmpbuf;
80*a9fa9459Szrj 
81*a9fa9459Szrj       ++ver;
82*a9fa9459Szrj       if (*ver == '@')
83*a9fa9459Szrj         {
84*a9fa9459Szrj           ++ver;
85*a9fa9459Szrj           def = true;
86*a9fa9459Szrj         }
87*a9fa9459Szrj     }
88*a9fa9459Szrj 
89*a9fa9459Szrj   Symbol* sym = symtab->lookup(sym_name, ver);
90*a9fa9459Szrj   if (def
91*a9fa9459Szrj       && ver != NULL
92*a9fa9459Szrj       && (sym == NULL
93*a9fa9459Szrj           || !sym->is_undefined()
94*a9fa9459Szrj           || sym->binding() == elfcpp::STB_WEAK))
95*a9fa9459Szrj     sym = symtab->lookup(sym_name, NULL);
96*a9fa9459Szrj 
97*a9fa9459Szrj   *symp = sym;
98*a9fa9459Szrj 
99*a9fa9459Szrj   if (sym != NULL)
100*a9fa9459Szrj     {
101*a9fa9459Szrj       if (!sym->is_undefined())
102*a9fa9459Szrj 	return Library_base::SHOULD_INCLUDE_NO;
103*a9fa9459Szrj 
104*a9fa9459Szrj       // PR 12001: Do not include an archive when the undefined
105*a9fa9459Szrj       // symbol has actually been defined on the command line.
106*a9fa9459Szrj       if (layout->script_options()->is_pending_assignment(sym_name))
107*a9fa9459Szrj 	return Library_base::SHOULD_INCLUDE_NO;
108*a9fa9459Szrj 
109*a9fa9459Szrj       // If the symbol is weak undefined, we still need to check
110*a9fa9459Szrj       // for other reasons (like a -u option).
111*a9fa9459Szrj       if (sym->binding() != elfcpp::STB_WEAK)
112*a9fa9459Szrj 	return Library_base::SHOULD_INCLUDE_YES;
113*a9fa9459Szrj     }
114*a9fa9459Szrj 
115*a9fa9459Szrj   // Check whether the symbol was named in a -u option.
116*a9fa9459Szrj   if (parameters->options().is_undefined(sym_name))
117*a9fa9459Szrj     {
118*a9fa9459Szrj       *why = "-u ";
119*a9fa9459Szrj       *why += sym_name;
120*a9fa9459Szrj       return Library_base::SHOULD_INCLUDE_YES;
121*a9fa9459Szrj     }
122*a9fa9459Szrj 
123*a9fa9459Szrj   if (parameters->options().is_export_dynamic_symbol(sym_name))
124*a9fa9459Szrj     {
125*a9fa9459Szrj       *why = "--export-dynamic-symbol ";
126*a9fa9459Szrj       *why += sym_name;
127*a9fa9459Szrj       return Library_base::SHOULD_INCLUDE_YES;
128*a9fa9459Szrj     }
129*a9fa9459Szrj 
130*a9fa9459Szrj   if (layout->script_options()->is_referenced(sym_name))
131*a9fa9459Szrj     {
132*a9fa9459Szrj       size_t alc = 100 + strlen(sym_name);
133*a9fa9459Szrj       char* buf = new char[alc];
134*a9fa9459Szrj       snprintf(buf, alc, _("script or expression reference to %s"),
135*a9fa9459Szrj 	       sym_name);
136*a9fa9459Szrj       *why = buf;
137*a9fa9459Szrj       delete[] buf;
138*a9fa9459Szrj       return Library_base::SHOULD_INCLUDE_YES;
139*a9fa9459Szrj     }
140*a9fa9459Szrj 
141*a9fa9459Szrj   if (!parameters->options().relocatable())
142*a9fa9459Szrj     {
143*a9fa9459Szrj       const char* entry_sym = parameters->entry();
144*a9fa9459Szrj       if (entry_sym != NULL && strcmp(sym_name, entry_sym) == 0)
145*a9fa9459Szrj 	{
146*a9fa9459Szrj 	  *why = "entry symbol ";
147*a9fa9459Szrj 	  *why += sym_name;
148*a9fa9459Szrj 	  return Library_base::SHOULD_INCLUDE_YES;
149*a9fa9459Szrj 	}
150*a9fa9459Szrj     }
151*a9fa9459Szrj 
152*a9fa9459Szrj   return Library_base::SHOULD_INCLUDE_UNKNOWN;
153*a9fa9459Szrj }
154*a9fa9459Szrj 
155*a9fa9459Szrj // The header of an entry in the archive.  This is all readable text,
156*a9fa9459Szrj // padded with spaces where necessary.  If the contents of an archive
157*a9fa9459Szrj // are all text file, the entire archive is readable.
158*a9fa9459Szrj 
159*a9fa9459Szrj struct Archive::Archive_header
160*a9fa9459Szrj {
161*a9fa9459Szrj   // The entry name.
162*a9fa9459Szrj   char ar_name[16];
163*a9fa9459Szrj   // The file modification time.
164*a9fa9459Szrj   char ar_date[12];
165*a9fa9459Szrj   // The user's UID in decimal.
166*a9fa9459Szrj   char ar_uid[6];
167*a9fa9459Szrj   // The user's GID in decimal.
168*a9fa9459Szrj   char ar_gid[6];
169*a9fa9459Szrj   // The file mode in octal.
170*a9fa9459Szrj   char ar_mode[8];
171*a9fa9459Szrj   // The file size in decimal.
172*a9fa9459Szrj   char ar_size[10];
173*a9fa9459Szrj   // The final magic code.
174*a9fa9459Szrj   char ar_fmag[2];
175*a9fa9459Szrj };
176*a9fa9459Szrj 
177*a9fa9459Szrj // Class Archive static variables.
178*a9fa9459Szrj unsigned int Archive::total_archives;
179*a9fa9459Szrj unsigned int Archive::total_members;
180*a9fa9459Szrj unsigned int Archive::total_members_loaded;
181*a9fa9459Szrj 
182*a9fa9459Szrj // Archive methods.
183*a9fa9459Szrj 
184*a9fa9459Szrj const char Archive::armag[sarmag] =
185*a9fa9459Szrj {
186*a9fa9459Szrj   '!', '<', 'a', 'r', 'c', 'h', '>', '\n'
187*a9fa9459Szrj };
188*a9fa9459Szrj 
189*a9fa9459Szrj const char Archive::armagt[sarmag] =
190*a9fa9459Szrj {
191*a9fa9459Szrj   '!', '<', 't', 'h', 'i', 'n', '>', '\n'
192*a9fa9459Szrj };
193*a9fa9459Szrj 
194*a9fa9459Szrj const char Archive::arfmag[2] = { '`', '\n' };
195*a9fa9459Szrj 
196*a9fa9459Szrj const char Archive::sym64name[7] = { '/', 'S', 'Y', 'M', '6', '4', '/' };
197*a9fa9459Szrj 
Archive(const std::string & name,Input_file * input_file,bool is_thin_archive,Dirsearch * dirpath,Task * task)198*a9fa9459Szrj Archive::Archive(const std::string& name, Input_file* input_file,
199*a9fa9459Szrj                  bool is_thin_archive, Dirsearch* dirpath, Task* task)
200*a9fa9459Szrj   : Library_base(task), name_(name), input_file_(input_file), armap_(),
201*a9fa9459Szrj     armap_names_(), extended_names_(), armap_checked_(), seen_offsets_(),
202*a9fa9459Szrj     members_(), is_thin_archive_(is_thin_archive), included_member_(false),
203*a9fa9459Szrj     nested_archives_(), dirpath_(dirpath), num_members_(0),
204*a9fa9459Szrj     included_all_members_(false)
205*a9fa9459Szrj {
206*a9fa9459Szrj   this->no_export_ =
207*a9fa9459Szrj     parameters->options().check_excluded_libs(input_file->found_name());
208*a9fa9459Szrj }
209*a9fa9459Szrj 
210*a9fa9459Szrj // Set up the archive: read the symbol map and the extended name
211*a9fa9459Szrj // table.
212*a9fa9459Szrj 
213*a9fa9459Szrj void
setup()214*a9fa9459Szrj Archive::setup()
215*a9fa9459Szrj {
216*a9fa9459Szrj   // We need to ignore empty archives.
217*a9fa9459Szrj   if (this->input_file_->file().filesize() == sarmag)
218*a9fa9459Szrj     return;
219*a9fa9459Szrj 
220*a9fa9459Szrj   // The first member of the archive should be the symbol table.
221*a9fa9459Szrj   std::string armap_name;
222*a9fa9459Szrj   off_t header_size = this->read_header(sarmag, false, &armap_name, NULL);
223*a9fa9459Szrj   if (header_size == -1)
224*a9fa9459Szrj     return;
225*a9fa9459Szrj 
226*a9fa9459Szrj   section_size_type armap_size = convert_to_section_size_type(header_size);
227*a9fa9459Szrj   off_t off = sarmag;
228*a9fa9459Szrj   if (armap_name.empty())
229*a9fa9459Szrj     {
230*a9fa9459Szrj       this->read_armap<32>(sarmag + sizeof(Archive_header), armap_size);
231*a9fa9459Szrj       off = sarmag + sizeof(Archive_header) + armap_size;
232*a9fa9459Szrj     }
233*a9fa9459Szrj   else if (armap_name == "/SYM64/")
234*a9fa9459Szrj     {
235*a9fa9459Szrj       this->read_armap<64>(sarmag + sizeof(Archive_header), armap_size);
236*a9fa9459Szrj       off = sarmag + sizeof(Archive_header) + armap_size;
237*a9fa9459Szrj     }
238*a9fa9459Szrj   else if (!this->input_file_->options().whole_archive())
239*a9fa9459Szrj     gold_error(_("%s: no archive symbol table (run ranlib)"),
240*a9fa9459Szrj 	       this->name().c_str());
241*a9fa9459Szrj 
242*a9fa9459Szrj   // See if there is an extended name table.  We cache these views
243*a9fa9459Szrj   // because it is likely that we will want to read the following
244*a9fa9459Szrj   // header in the add_symbols routine.
245*a9fa9459Szrj   if ((off & 1) != 0)
246*a9fa9459Szrj     ++off;
247*a9fa9459Szrj   std::string xname;
248*a9fa9459Szrj   header_size = this->read_header(off, true, &xname, NULL);
249*a9fa9459Szrj   if (header_size == -1)
250*a9fa9459Szrj     return;
251*a9fa9459Szrj 
252*a9fa9459Szrj   section_size_type extended_size = convert_to_section_size_type(header_size);
253*a9fa9459Szrj   if (xname == "/")
254*a9fa9459Szrj     {
255*a9fa9459Szrj       const unsigned char* p = this->get_view(off + sizeof(Archive_header),
256*a9fa9459Szrj                                               extended_size, false, true);
257*a9fa9459Szrj       const char* px = reinterpret_cast<const char*>(p);
258*a9fa9459Szrj       this->extended_names_.assign(px, extended_size);
259*a9fa9459Szrj     }
260*a9fa9459Szrj   bool preread_syms = (parameters->options().threads()
261*a9fa9459Szrj                        && parameters->options().preread_archive_symbols());
262*a9fa9459Szrj #ifndef ENABLE_THREADS
263*a9fa9459Szrj   preread_syms = false;
264*a9fa9459Szrj #else
265*a9fa9459Szrj   if (parameters->options().has_plugins())
266*a9fa9459Szrj     preread_syms = false;
267*a9fa9459Szrj #endif
268*a9fa9459Szrj   if (preread_syms)
269*a9fa9459Szrj     this->read_all_symbols();
270*a9fa9459Szrj }
271*a9fa9459Szrj 
272*a9fa9459Szrj // Unlock any nested archives.
273*a9fa9459Szrj 
274*a9fa9459Szrj void
unlock_nested_archives()275*a9fa9459Szrj Archive::unlock_nested_archives()
276*a9fa9459Szrj {
277*a9fa9459Szrj   for (Nested_archive_table::iterator p = this->nested_archives_.begin();
278*a9fa9459Szrj        p != this->nested_archives_.end();
279*a9fa9459Szrj        ++p)
280*a9fa9459Szrj     {
281*a9fa9459Szrj       p->second->unlock(this->task_);
282*a9fa9459Szrj     }
283*a9fa9459Szrj }
284*a9fa9459Szrj 
285*a9fa9459Szrj // Read the archive symbol map.
286*a9fa9459Szrj 
287*a9fa9459Szrj template<int mapsize>
288*a9fa9459Szrj void
read_armap(off_t start,section_size_type size)289*a9fa9459Szrj Archive::read_armap(off_t start, section_size_type size)
290*a9fa9459Szrj {
291*a9fa9459Szrj   // To count the total number of archive members, we'll just count
292*a9fa9459Szrj   // the number of times the file offset changes.  Since most archives
293*a9fa9459Szrj   // group the symbols in the armap by object, this ought to give us
294*a9fa9459Szrj   // an accurate count.
295*a9fa9459Szrj   off_t last_seen_offset = -1;
296*a9fa9459Szrj 
297*a9fa9459Szrj   // Read in the entire armap.
298*a9fa9459Szrj   const unsigned char* p = this->get_view(start, size, true, false);
299*a9fa9459Szrj 
300*a9fa9459Szrj   // Numbers in the armap are always big-endian.
301*a9fa9459Szrj   typedef typename elfcpp::Elf_types<mapsize>::Elf_Addr Entry_type;
302*a9fa9459Szrj   const Entry_type* pword = reinterpret_cast<const Entry_type*>(p);
303*a9fa9459Szrj   unsigned long nsyms = convert_types<unsigned long, Entry_type>(
304*a9fa9459Szrj     elfcpp::Swap<mapsize, true>::readval(pword));
305*a9fa9459Szrj   ++pword;
306*a9fa9459Szrj 
307*a9fa9459Szrj   // Note that the addition is in units of sizeof(elfcpp::Elf_Word).
308*a9fa9459Szrj   const char* pnames = reinterpret_cast<const char*>(pword + nsyms);
309*a9fa9459Szrj   section_size_type names_size =
310*a9fa9459Szrj     reinterpret_cast<const char*>(p) + size - pnames;
311*a9fa9459Szrj   this->armap_names_.assign(pnames, names_size);
312*a9fa9459Szrj 
313*a9fa9459Szrj   this->armap_.resize(nsyms);
314*a9fa9459Szrj 
315*a9fa9459Szrj   section_offset_type name_offset = 0;
316*a9fa9459Szrj   for (unsigned long i = 0; i < nsyms; ++i)
317*a9fa9459Szrj     {
318*a9fa9459Szrj       this->armap_[i].name_offset = name_offset;
319*a9fa9459Szrj       this->armap_[i].file_offset = convert_types<off_t, Entry_type>(
320*a9fa9459Szrj         elfcpp::Swap<mapsize, true>::readval(pword));
321*a9fa9459Szrj       name_offset += strlen(pnames + name_offset) + 1;
322*a9fa9459Szrj       ++pword;
323*a9fa9459Szrj       if (this->armap_[i].file_offset != last_seen_offset)
324*a9fa9459Szrj         {
325*a9fa9459Szrj           last_seen_offset = this->armap_[i].file_offset;
326*a9fa9459Szrj           ++this->num_members_;
327*a9fa9459Szrj         }
328*a9fa9459Szrj     }
329*a9fa9459Szrj 
330*a9fa9459Szrj   if (static_cast<section_size_type>(name_offset) > names_size)
331*a9fa9459Szrj     gold_error(_("%s: bad archive symbol table names"),
332*a9fa9459Szrj 	       this->name().c_str());
333*a9fa9459Szrj 
334*a9fa9459Szrj   // This array keeps track of which symbols are for archive elements
335*a9fa9459Szrj   // which we have already included in the link.
336*a9fa9459Szrj   this->armap_checked_.resize(nsyms);
337*a9fa9459Szrj }
338*a9fa9459Szrj 
339*a9fa9459Szrj // Read the header of an archive member at OFF.  Fail if something
340*a9fa9459Szrj // goes wrong.  Return the size of the member.  Set *PNAME to the name
341*a9fa9459Szrj // of the member.
342*a9fa9459Szrj 
343*a9fa9459Szrj off_t
read_header(off_t off,bool cache,std::string * pname,off_t * nested_off)344*a9fa9459Szrj Archive::read_header(off_t off, bool cache, std::string* pname,
345*a9fa9459Szrj                      off_t* nested_off)
346*a9fa9459Szrj {
347*a9fa9459Szrj   const unsigned char* p = this->get_view(off, sizeof(Archive_header), true,
348*a9fa9459Szrj 					  cache);
349*a9fa9459Szrj   const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
350*a9fa9459Szrj   return this->interpret_header(hdr, off,  pname, nested_off);
351*a9fa9459Szrj }
352*a9fa9459Szrj 
353*a9fa9459Szrj // Interpret the header of HDR, the header of the archive member at
354*a9fa9459Szrj // file offset OFF.  Return the size of the member, or -1 if something
355*a9fa9459Szrj // has gone wrong.  Set *PNAME to the name of the member.
356*a9fa9459Szrj 
357*a9fa9459Szrj off_t
interpret_header(const Archive_header * hdr,off_t off,std::string * pname,off_t * nested_off) const358*a9fa9459Szrj Archive::interpret_header(const Archive_header* hdr, off_t off,
359*a9fa9459Szrj                           std::string* pname, off_t* nested_off) const
360*a9fa9459Szrj {
361*a9fa9459Szrj   if (memcmp(hdr->ar_fmag, arfmag, sizeof arfmag) != 0)
362*a9fa9459Szrj     {
363*a9fa9459Szrj       gold_error(_("%s: malformed archive header at %zu"),
364*a9fa9459Szrj 		 this->name().c_str(), static_cast<size_t>(off));
365*a9fa9459Szrj       return -1;
366*a9fa9459Szrj     }
367*a9fa9459Szrj 
368*a9fa9459Szrj   const int size_string_size = sizeof hdr->ar_size;
369*a9fa9459Szrj   char size_string[size_string_size + 1];
370*a9fa9459Szrj   memcpy(size_string, hdr->ar_size, size_string_size);
371*a9fa9459Szrj   char* ps = size_string + size_string_size;
372*a9fa9459Szrj   while (ps[-1] == ' ')
373*a9fa9459Szrj     --ps;
374*a9fa9459Szrj   *ps = '\0';
375*a9fa9459Szrj 
376*a9fa9459Szrj   errno = 0;
377*a9fa9459Szrj   char* end;
378*a9fa9459Szrj   off_t member_size = strtol(size_string, &end, 10);
379*a9fa9459Szrj   if (*end != '\0'
380*a9fa9459Szrj       || member_size < 0
381*a9fa9459Szrj       || (member_size == LONG_MAX && errno == ERANGE))
382*a9fa9459Szrj     {
383*a9fa9459Szrj       gold_error(_("%s: malformed archive header size at %zu"),
384*a9fa9459Szrj 		 this->name().c_str(), static_cast<size_t>(off));
385*a9fa9459Szrj       return -1;
386*a9fa9459Szrj     }
387*a9fa9459Szrj 
388*a9fa9459Szrj   if (hdr->ar_name[0] != '/')
389*a9fa9459Szrj     {
390*a9fa9459Szrj       const char* name_end = strchr(hdr->ar_name, '/');
391*a9fa9459Szrj       if (name_end == NULL
392*a9fa9459Szrj 	  || name_end - hdr->ar_name >= static_cast<int>(sizeof hdr->ar_name))
393*a9fa9459Szrj 	{
394*a9fa9459Szrj 	  gold_error(_("%s: malformed archive header name at %zu"),
395*a9fa9459Szrj 		     this->name().c_str(), static_cast<size_t>(off));
396*a9fa9459Szrj 	  return -1;
397*a9fa9459Szrj 	}
398*a9fa9459Szrj       pname->assign(hdr->ar_name, name_end - hdr->ar_name);
399*a9fa9459Szrj       if (nested_off != NULL)
400*a9fa9459Szrj         *nested_off = 0;
401*a9fa9459Szrj     }
402*a9fa9459Szrj   else if (hdr->ar_name[1] == ' ')
403*a9fa9459Szrj     {
404*a9fa9459Szrj       // This is the symbol table.
405*a9fa9459Szrj       if (!pname->empty())
406*a9fa9459Szrj 	pname->clear();
407*a9fa9459Szrj     }
408*a9fa9459Szrj   else if (memcmp(hdr->ar_name, sym64name, sizeof sym64name) == 0)
409*a9fa9459Szrj     {
410*a9fa9459Szrj       // This is the symbol table, 64-bit version.
411*a9fa9459Szrj       pname->assign(sym64name, sizeof sym64name);
412*a9fa9459Szrj     }
413*a9fa9459Szrj   else if (hdr->ar_name[1] == '/')
414*a9fa9459Szrj     {
415*a9fa9459Szrj       // This is the extended name table.
416*a9fa9459Szrj       pname->assign(1, '/');
417*a9fa9459Szrj     }
418*a9fa9459Szrj   else
419*a9fa9459Szrj     {
420*a9fa9459Szrj       errno = 0;
421*a9fa9459Szrj       long x = strtol(hdr->ar_name + 1, &end, 10);
422*a9fa9459Szrj       long y = 0;
423*a9fa9459Szrj       if (*end == ':')
424*a9fa9459Szrj         y = strtol(end + 1, &end, 10);
425*a9fa9459Szrj       if (*end != ' '
426*a9fa9459Szrj 	  || x < 0
427*a9fa9459Szrj 	  || (x == LONG_MAX && errno == ERANGE)
428*a9fa9459Szrj 	  || static_cast<size_t>(x) >= this->extended_names_.size())
429*a9fa9459Szrj 	{
430*a9fa9459Szrj 	  gold_error(_("%s: bad extended name index at %zu"),
431*a9fa9459Szrj 		     this->name().c_str(), static_cast<size_t>(off));
432*a9fa9459Szrj 	  return -1;
433*a9fa9459Szrj 	}
434*a9fa9459Szrj 
435*a9fa9459Szrj       const char* name = this->extended_names_.data() + x;
436*a9fa9459Szrj       const char* name_end = strchr(name, '\n');
437*a9fa9459Szrj       if (static_cast<size_t>(name_end - name) > this->extended_names_.size()
438*a9fa9459Szrj 	  || name_end[-1] != '/')
439*a9fa9459Szrj 	{
440*a9fa9459Szrj 	  gold_error(_("%s: bad extended name entry at header %zu"),
441*a9fa9459Szrj 		     this->name().c_str(), static_cast<size_t>(off));
442*a9fa9459Szrj 	  return -1;
443*a9fa9459Szrj 	}
444*a9fa9459Szrj       pname->assign(name, name_end - 1 - name);
445*a9fa9459Szrj       if (nested_off != NULL)
446*a9fa9459Szrj         *nested_off = y;
447*a9fa9459Szrj     }
448*a9fa9459Szrj 
449*a9fa9459Szrj   return member_size;
450*a9fa9459Szrj }
451*a9fa9459Szrj 
452*a9fa9459Szrj // An archive member iterator.
453*a9fa9459Szrj 
454*a9fa9459Szrj class Archive::const_iterator
455*a9fa9459Szrj {
456*a9fa9459Szrj  public:
457*a9fa9459Szrj   // The header of an archive member.  This is what this iterator
458*a9fa9459Szrj   // points to.
459*a9fa9459Szrj   struct Header
460*a9fa9459Szrj   {
461*a9fa9459Szrj     // The name of the member.
462*a9fa9459Szrj     std::string name;
463*a9fa9459Szrj     // The file offset of the member.
464*a9fa9459Szrj     off_t off;
465*a9fa9459Szrj     // The file offset of a nested archive member.
466*a9fa9459Szrj     off_t nested_off;
467*a9fa9459Szrj     // The size of the member.
468*a9fa9459Szrj     off_t size;
469*a9fa9459Szrj   };
470*a9fa9459Szrj 
const_iterator(Archive * archive,off_t off)471*a9fa9459Szrj   const_iterator(Archive* archive, off_t off)
472*a9fa9459Szrj     : archive_(archive), off_(off)
473*a9fa9459Szrj   { this->read_next_header(); }
474*a9fa9459Szrj 
475*a9fa9459Szrj   const Header&
operator *() const476*a9fa9459Szrj   operator*() const
477*a9fa9459Szrj   { return this->header_; }
478*a9fa9459Szrj 
479*a9fa9459Szrj   const Header*
operator ->() const480*a9fa9459Szrj   operator->() const
481*a9fa9459Szrj   { return &this->header_; }
482*a9fa9459Szrj 
483*a9fa9459Szrj   const_iterator&
operator ++()484*a9fa9459Szrj   operator++()
485*a9fa9459Szrj   {
486*a9fa9459Szrj     if (this->off_ == this->archive_->file().filesize())
487*a9fa9459Szrj       return *this;
488*a9fa9459Szrj     this->off_ += sizeof(Archive_header);
489*a9fa9459Szrj     if (!this->archive_->is_thin_archive())
490*a9fa9459Szrj       this->off_ += this->header_.size;
491*a9fa9459Szrj     if ((this->off_ & 1) != 0)
492*a9fa9459Szrj       ++this->off_;
493*a9fa9459Szrj     this->read_next_header();
494*a9fa9459Szrj     return *this;
495*a9fa9459Szrj   }
496*a9fa9459Szrj 
497*a9fa9459Szrj   const_iterator
operator ++(int)498*a9fa9459Szrj   operator++(int)
499*a9fa9459Szrj   {
500*a9fa9459Szrj     const_iterator ret = *this;
501*a9fa9459Szrj     ++*this;
502*a9fa9459Szrj     return ret;
503*a9fa9459Szrj   }
504*a9fa9459Szrj 
505*a9fa9459Szrj   bool
operator ==(const const_iterator p) const506*a9fa9459Szrj   operator==(const const_iterator p) const
507*a9fa9459Szrj   { return this->off_ == p->off; }
508*a9fa9459Szrj 
509*a9fa9459Szrj   bool
operator !=(const const_iterator p) const510*a9fa9459Szrj   operator!=(const const_iterator p) const
511*a9fa9459Szrj   { return this->off_ != p->off; }
512*a9fa9459Szrj 
513*a9fa9459Szrj  private:
514*a9fa9459Szrj   void
515*a9fa9459Szrj   read_next_header();
516*a9fa9459Szrj 
517*a9fa9459Szrj   // The underlying archive.
518*a9fa9459Szrj   Archive* archive_;
519*a9fa9459Szrj   // The current offset in the file.
520*a9fa9459Szrj   off_t off_;
521*a9fa9459Szrj   // The current archive header.
522*a9fa9459Szrj   Header header_;
523*a9fa9459Szrj };
524*a9fa9459Szrj 
525*a9fa9459Szrj // Read the next archive header.
526*a9fa9459Szrj 
527*a9fa9459Szrj void
read_next_header()528*a9fa9459Szrj Archive::const_iterator::read_next_header()
529*a9fa9459Szrj {
530*a9fa9459Szrj   off_t filesize = this->archive_->file().filesize();
531*a9fa9459Szrj   while (true)
532*a9fa9459Szrj     {
533*a9fa9459Szrj       if (filesize - this->off_ < static_cast<off_t>(sizeof(Archive_header)))
534*a9fa9459Szrj 	{
535*a9fa9459Szrj 	  if (filesize != this->off_)
536*a9fa9459Szrj 	    {
537*a9fa9459Szrj 	      gold_error(_("%s: short archive header at %zu"),
538*a9fa9459Szrj 			 this->archive_->filename().c_str(),
539*a9fa9459Szrj 			 static_cast<size_t>(this->off_));
540*a9fa9459Szrj 	      this->off_ = filesize;
541*a9fa9459Szrj 	    }
542*a9fa9459Szrj 	  this->header_.off = filesize;
543*a9fa9459Szrj 	  return;
544*a9fa9459Szrj 	}
545*a9fa9459Szrj 
546*a9fa9459Szrj       unsigned char buf[sizeof(Archive_header)];
547*a9fa9459Szrj       this->archive_->file().read(this->off_, sizeof(Archive_header), buf);
548*a9fa9459Szrj 
549*a9fa9459Szrj       const Archive_header* hdr = reinterpret_cast<const Archive_header*>(buf);
550*a9fa9459Szrj       off_t size = this->archive_->interpret_header(hdr, this->off_,
551*a9fa9459Szrj 						    &this->header_.name,
552*a9fa9459Szrj 						    &this->header_.nested_off);
553*a9fa9459Szrj       if (size == -1)
554*a9fa9459Szrj 	{
555*a9fa9459Szrj 	  this->header_.off = filesize;
556*a9fa9459Szrj 	  return;
557*a9fa9459Szrj 	}
558*a9fa9459Szrj 
559*a9fa9459Szrj       this->header_.size = size;
560*a9fa9459Szrj       this->header_.off = this->off_;
561*a9fa9459Szrj 
562*a9fa9459Szrj       // Skip special members.
563*a9fa9459Szrj       if (!this->header_.name.empty()
564*a9fa9459Szrj 	  && this->header_.name != "/"
565*a9fa9459Szrj 	  && this->header_.name != "/SYM64/")
566*a9fa9459Szrj 	return;
567*a9fa9459Szrj 
568*a9fa9459Szrj       this->off_ += sizeof(Archive_header) + this->header_.size;
569*a9fa9459Szrj       if ((this->off_ & 1) != 0)
570*a9fa9459Szrj 	++this->off_;
571*a9fa9459Szrj     }
572*a9fa9459Szrj }
573*a9fa9459Szrj 
574*a9fa9459Szrj // Initial iterator.
575*a9fa9459Szrj 
576*a9fa9459Szrj Archive::const_iterator
begin()577*a9fa9459Szrj Archive::begin()
578*a9fa9459Szrj {
579*a9fa9459Szrj   return Archive::const_iterator(this, sarmag);
580*a9fa9459Szrj }
581*a9fa9459Szrj 
582*a9fa9459Szrj // Final iterator.
583*a9fa9459Szrj 
584*a9fa9459Szrj Archive::const_iterator
end()585*a9fa9459Szrj Archive::end()
586*a9fa9459Szrj {
587*a9fa9459Szrj   return Archive::const_iterator(this, this->input_file_->file().filesize());
588*a9fa9459Szrj }
589*a9fa9459Szrj 
590*a9fa9459Szrj // Get the file and offset for an archive member, which may be an
591*a9fa9459Szrj // external member of a thin archive.  Set *INPUT_FILE to the
592*a9fa9459Szrj // file containing the actual member, *MEMOFF to the offset
593*a9fa9459Szrj // within that file (0 if not a nested archive), and *MEMBER_NAME
594*a9fa9459Szrj // to the name of the archive member.  Return TRUE on success.
595*a9fa9459Szrj 
596*a9fa9459Szrj bool
get_file_and_offset(off_t off,Input_file ** input_file,off_t * memoff,off_t * memsize,std::string * member_name)597*a9fa9459Szrj Archive::get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
598*a9fa9459Szrj                              off_t* memsize, std::string* member_name)
599*a9fa9459Szrj {
600*a9fa9459Szrj   off_t nested_off;
601*a9fa9459Szrj 
602*a9fa9459Szrj   *memsize = this->read_header(off, false, member_name, &nested_off);
603*a9fa9459Szrj   if (*memsize == -1)
604*a9fa9459Szrj     return false;
605*a9fa9459Szrj 
606*a9fa9459Szrj   *input_file = this->input_file_;
607*a9fa9459Szrj   *memoff = off + static_cast<off_t>(sizeof(Archive_header));
608*a9fa9459Szrj 
609*a9fa9459Szrj   if (!this->is_thin_archive_)
610*a9fa9459Szrj     return true;
611*a9fa9459Szrj 
612*a9fa9459Szrj   // Adjust a relative pathname so that it is relative
613*a9fa9459Szrj   // to the directory containing the archive.
614*a9fa9459Szrj   if (!IS_ABSOLUTE_PATH(member_name->c_str()))
615*a9fa9459Szrj     {
616*a9fa9459Szrj       const char* arch_path = this->filename().c_str();
617*a9fa9459Szrj       const char* basename = lbasename(arch_path);
618*a9fa9459Szrj       if (basename > arch_path)
619*a9fa9459Szrj         member_name->replace(0, 0,
620*a9fa9459Szrj                              this->filename().substr(0, basename - arch_path));
621*a9fa9459Szrj     }
622*a9fa9459Szrj 
623*a9fa9459Szrj   if (nested_off > 0)
624*a9fa9459Szrj     {
625*a9fa9459Szrj       // This is a member of a nested archive.  Open the containing
626*a9fa9459Szrj       // archive if we don't already have it open, then do a recursive
627*a9fa9459Szrj       // call to include the member from that archive.
628*a9fa9459Szrj       Archive* arch;
629*a9fa9459Szrj       Nested_archive_table::const_iterator p =
630*a9fa9459Szrj         this->nested_archives_.find(*member_name);
631*a9fa9459Szrj       if (p != this->nested_archives_.end())
632*a9fa9459Szrj         arch = p->second;
633*a9fa9459Szrj       else
634*a9fa9459Szrj         {
635*a9fa9459Szrj           Input_file_argument* input_file_arg =
636*a9fa9459Szrj             new Input_file_argument(member_name->c_str(),
637*a9fa9459Szrj                                     Input_file_argument::INPUT_FILE_TYPE_FILE,
638*a9fa9459Szrj                                     "", false, parameters->options());
639*a9fa9459Szrj           *input_file = new Input_file(input_file_arg);
640*a9fa9459Szrj 	  int dummy = 0;
641*a9fa9459Szrj           if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
642*a9fa9459Szrj             return false;
643*a9fa9459Szrj           arch = new Archive(*member_name, *input_file, false, this->dirpath_,
644*a9fa9459Szrj                              this->task_);
645*a9fa9459Szrj           arch->setup();
646*a9fa9459Szrj           std::pair<Nested_archive_table::iterator, bool> ins =
647*a9fa9459Szrj             this->nested_archives_.insert(std::make_pair(*member_name, arch));
648*a9fa9459Szrj           gold_assert(ins.second);
649*a9fa9459Szrj         }
650*a9fa9459Szrj       return arch->get_file_and_offset(nested_off, input_file, memoff,
651*a9fa9459Szrj 				       memsize, member_name);
652*a9fa9459Szrj     }
653*a9fa9459Szrj 
654*a9fa9459Szrj   // This is an external member of a thin archive.  Open the
655*a9fa9459Szrj   // file as a regular relocatable object file.
656*a9fa9459Szrj   Input_file_argument* input_file_arg =
657*a9fa9459Szrj       new Input_file_argument(member_name->c_str(),
658*a9fa9459Szrj                               Input_file_argument::INPUT_FILE_TYPE_FILE,
659*a9fa9459Szrj                               "", false, this->input_file_->options());
660*a9fa9459Szrj   *input_file = new Input_file(input_file_arg);
661*a9fa9459Szrj   int dummy = 0;
662*a9fa9459Szrj   if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
663*a9fa9459Szrj     return false;
664*a9fa9459Szrj 
665*a9fa9459Szrj   *memoff = 0;
666*a9fa9459Szrj   *memsize = (*input_file)->file().filesize();
667*a9fa9459Szrj   return true;
668*a9fa9459Szrj }
669*a9fa9459Szrj 
670*a9fa9459Szrj // Return an ELF object for the member at offset OFF.  If
671*a9fa9459Szrj // PUNCONFIGURED is not NULL, then if the ELF object has an
672*a9fa9459Szrj // unsupported target type, set *PUNCONFIGURED to true and return
673*a9fa9459Szrj // NULL.
674*a9fa9459Szrj 
675*a9fa9459Szrj Object*
get_elf_object_for_member(off_t off,bool * punconfigured)676*a9fa9459Szrj Archive::get_elf_object_for_member(off_t off, bool* punconfigured)
677*a9fa9459Szrj {
678*a9fa9459Szrj   if (punconfigured != NULL)
679*a9fa9459Szrj     *punconfigured = false;
680*a9fa9459Szrj 
681*a9fa9459Szrj   Input_file* input_file;
682*a9fa9459Szrj   off_t memoff;
683*a9fa9459Szrj   off_t memsize;
684*a9fa9459Szrj   std::string member_name;
685*a9fa9459Szrj   if (!this->get_file_and_offset(off, &input_file, &memoff, &memsize,
686*a9fa9459Szrj 				 &member_name))
687*a9fa9459Szrj     return NULL;
688*a9fa9459Szrj 
689*a9fa9459Szrj   const unsigned char* ehdr;
690*a9fa9459Szrj   int read_size;
691*a9fa9459Szrj   Object *obj = NULL;
692*a9fa9459Szrj   bool is_elf_obj = false;
693*a9fa9459Szrj 
694*a9fa9459Szrj   if (is_elf_object(input_file, memoff, &ehdr, &read_size))
695*a9fa9459Szrj     {
696*a9fa9459Szrj       obj = make_elf_object((std::string(this->input_file_->filename())
697*a9fa9459Szrj 			     + "(" + member_name + ")"),
698*a9fa9459Szrj 			    input_file, memoff, ehdr, read_size,
699*a9fa9459Szrj 			    punconfigured);
700*a9fa9459Szrj       is_elf_obj = true;
701*a9fa9459Szrj     }
702*a9fa9459Szrj 
703*a9fa9459Szrj   if (parameters->options().has_plugins())
704*a9fa9459Szrj     {
705*a9fa9459Szrj       Object* plugin_obj
706*a9fa9459Szrj 	= parameters->options().plugins()->claim_file(input_file,
707*a9fa9459Szrj 						      memoff,
708*a9fa9459Szrj 						      memsize,
709*a9fa9459Szrj 						      obj);
710*a9fa9459Szrj       if (plugin_obj != NULL)
711*a9fa9459Szrj         {
712*a9fa9459Szrj           // The input file was claimed by a plugin, and its symbols
713*a9fa9459Szrj           // have been provided by the plugin.
714*a9fa9459Szrj 	  // Delete its elf object.
715*a9fa9459Szrj 	  if (obj != NULL)
716*a9fa9459Szrj 	    delete obj;
717*a9fa9459Szrj           return plugin_obj;
718*a9fa9459Szrj         }
719*a9fa9459Szrj     }
720*a9fa9459Szrj 
721*a9fa9459Szrj   if (!is_elf_obj)
722*a9fa9459Szrj     {
723*a9fa9459Szrj       gold_error(_("%s: member at %zu is not an ELF object"),
724*a9fa9459Szrj 		 this->name().c_str(), static_cast<size_t>(off));
725*a9fa9459Szrj       return NULL;
726*a9fa9459Szrj     }
727*a9fa9459Szrj 
728*a9fa9459Szrj   if (obj == NULL)
729*a9fa9459Szrj     return NULL;
730*a9fa9459Szrj   obj->set_no_export(this->no_export());
731*a9fa9459Szrj   return obj;
732*a9fa9459Szrj }
733*a9fa9459Szrj 
734*a9fa9459Szrj // Read the symbols from all the archive members in the link.
735*a9fa9459Szrj 
736*a9fa9459Szrj void
read_all_symbols()737*a9fa9459Szrj Archive::read_all_symbols()
738*a9fa9459Szrj {
739*a9fa9459Szrj   for (Archive::const_iterator p = this->begin();
740*a9fa9459Szrj        p != this->end();
741*a9fa9459Szrj        ++p)
742*a9fa9459Szrj     this->read_symbols(p->off);
743*a9fa9459Szrj }
744*a9fa9459Szrj 
745*a9fa9459Szrj // Read the symbols from an archive member in the link.  OFF is the file
746*a9fa9459Szrj // offset of the member header.
747*a9fa9459Szrj 
748*a9fa9459Szrj void
read_symbols(off_t off)749*a9fa9459Szrj Archive::read_symbols(off_t off)
750*a9fa9459Szrj {
751*a9fa9459Szrj   Object* obj = this->get_elf_object_for_member(off, NULL);
752*a9fa9459Szrj   if (obj == NULL)
753*a9fa9459Szrj     return;
754*a9fa9459Szrj 
755*a9fa9459Szrj   Read_symbols_data* sd = new Read_symbols_data;
756*a9fa9459Szrj   obj->read_symbols(sd);
757*a9fa9459Szrj   Archive_member member(obj, sd);
758*a9fa9459Szrj   this->members_[off] = member;
759*a9fa9459Szrj }
760*a9fa9459Szrj 
761*a9fa9459Szrj // Select members from the archive and add them to the link.  We walk
762*a9fa9459Szrj // through the elements in the archive map, and look each one up in
763*a9fa9459Szrj // the symbol table.  If it exists as a strong undefined symbol, we
764*a9fa9459Szrj // pull in the corresponding element.  We have to do this in a loop,
765*a9fa9459Szrj // since pulling in one element may create new undefined symbols which
766*a9fa9459Szrj // may be satisfied by other objects in the archive.  Return true in
767*a9fa9459Szrj // the normal case, false if the first member we tried to add from
768*a9fa9459Szrj // this archive had an incompatible target.
769*a9fa9459Szrj 
770*a9fa9459Szrj bool
add_symbols(Symbol_table * symtab,Layout * layout,Input_objects * input_objects,Mapfile * mapfile)771*a9fa9459Szrj Archive::add_symbols(Symbol_table* symtab, Layout* layout,
772*a9fa9459Szrj 		     Input_objects* input_objects, Mapfile* mapfile)
773*a9fa9459Szrj {
774*a9fa9459Szrj   ++Archive::total_archives;
775*a9fa9459Szrj 
776*a9fa9459Szrj   if (this->input_file_->options().whole_archive())
777*a9fa9459Szrj     return this->include_all_members(symtab, layout, input_objects,
778*a9fa9459Szrj 				     mapfile);
779*a9fa9459Szrj 
780*a9fa9459Szrj   Archive::total_members += this->num_members_;
781*a9fa9459Szrj 
782*a9fa9459Szrj   input_objects->archive_start(this);
783*a9fa9459Szrj 
784*a9fa9459Szrj   const size_t armap_size = this->armap_.size();
785*a9fa9459Szrj 
786*a9fa9459Szrj   // This is a quick optimization, since we usually see many symbols
787*a9fa9459Szrj   // in a row with the same offset.  last_seen_offset holds the last
788*a9fa9459Szrj   // offset we saw that was present in the seen_offsets_ set.
789*a9fa9459Szrj   off_t last_seen_offset = -1;
790*a9fa9459Szrj 
791*a9fa9459Szrj   // Track which symbols in the symbol table we've already found to be
792*a9fa9459Szrj   // defined.
793*a9fa9459Szrj 
794*a9fa9459Szrj   char* tmpbuf = NULL;
795*a9fa9459Szrj   size_t tmpbuflen = 0;
796*a9fa9459Szrj   bool added_new_object;
797*a9fa9459Szrj   do
798*a9fa9459Szrj     {
799*a9fa9459Szrj       added_new_object = false;
800*a9fa9459Szrj       for (size_t i = 0; i < armap_size; ++i)
801*a9fa9459Szrj 	{
802*a9fa9459Szrj           if (this->armap_checked_[i])
803*a9fa9459Szrj             continue;
804*a9fa9459Szrj 	  if (this->armap_[i].file_offset == last_seen_offset)
805*a9fa9459Szrj             {
806*a9fa9459Szrj               this->armap_checked_[i] = true;
807*a9fa9459Szrj               continue;
808*a9fa9459Szrj             }
809*a9fa9459Szrj 	  if (this->seen_offsets_.find(this->armap_[i].file_offset)
810*a9fa9459Szrj               != this->seen_offsets_.end())
811*a9fa9459Szrj 	    {
812*a9fa9459Szrj               this->armap_checked_[i] = true;
813*a9fa9459Szrj 	      last_seen_offset = this->armap_[i].file_offset;
814*a9fa9459Szrj 	      continue;
815*a9fa9459Szrj 	    }
816*a9fa9459Szrj 
817*a9fa9459Szrj 	  const char* sym_name = (this->armap_names_.data()
818*a9fa9459Szrj 				  + this->armap_[i].name_offset);
819*a9fa9459Szrj 
820*a9fa9459Szrj           Symbol* sym;
821*a9fa9459Szrj           std::string why;
822*a9fa9459Szrj           Archive::Should_include t =
823*a9fa9459Szrj 	    Archive::should_include_member(symtab, layout, sym_name, &sym,
824*a9fa9459Szrj 					   &why, &tmpbuf, &tmpbuflen);
825*a9fa9459Szrj 
826*a9fa9459Szrj 	  if (t == Archive::SHOULD_INCLUDE_NO
827*a9fa9459Szrj               || t == Archive::SHOULD_INCLUDE_YES)
828*a9fa9459Szrj 	    this->armap_checked_[i] = true;
829*a9fa9459Szrj 
830*a9fa9459Szrj 	  if (t != Archive::SHOULD_INCLUDE_YES)
831*a9fa9459Szrj 	    continue;
832*a9fa9459Szrj 
833*a9fa9459Szrj 	  // We want to include this object in the link.
834*a9fa9459Szrj 	  last_seen_offset = this->armap_[i].file_offset;
835*a9fa9459Szrj 	  this->seen_offsets_.insert(last_seen_offset);
836*a9fa9459Szrj 
837*a9fa9459Szrj 	  if (!this->include_member(symtab, layout, input_objects,
838*a9fa9459Szrj 				    last_seen_offset, mapfile, sym,
839*a9fa9459Szrj 				    why.c_str()))
840*a9fa9459Szrj 	    {
841*a9fa9459Szrj 	      if (tmpbuf != NULL)
842*a9fa9459Szrj 		free(tmpbuf);
843*a9fa9459Szrj 	      return false;
844*a9fa9459Szrj 	    }
845*a9fa9459Szrj 
846*a9fa9459Szrj 	  added_new_object = true;
847*a9fa9459Szrj 	}
848*a9fa9459Szrj     }
849*a9fa9459Szrj   while (added_new_object);
850*a9fa9459Szrj 
851*a9fa9459Szrj   if (tmpbuf != NULL)
852*a9fa9459Szrj     free(tmpbuf);
853*a9fa9459Szrj 
854*a9fa9459Szrj   input_objects->archive_stop(this);
855*a9fa9459Szrj 
856*a9fa9459Szrj   return true;
857*a9fa9459Szrj }
858*a9fa9459Szrj 
859*a9fa9459Szrj // Return whether the archive includes a member which defines the
860*a9fa9459Szrj // symbol SYM.
861*a9fa9459Szrj 
862*a9fa9459Szrj bool
defines_symbol(Symbol * sym) const863*a9fa9459Szrj Archive::defines_symbol(Symbol* sym) const
864*a9fa9459Szrj {
865*a9fa9459Szrj   const char* symname = sym->name();
866*a9fa9459Szrj   size_t symname_len = strlen(symname);
867*a9fa9459Szrj   size_t armap_size = this->armap_.size();
868*a9fa9459Szrj   for (size_t i = 0; i < armap_size; ++i)
869*a9fa9459Szrj     {
870*a9fa9459Szrj       if (this->armap_checked_[i])
871*a9fa9459Szrj 	continue;
872*a9fa9459Szrj       const char* archive_symname = (this->armap_names_.data()
873*a9fa9459Szrj 				     + this->armap_[i].name_offset);
874*a9fa9459Szrj       if (strncmp(archive_symname, symname, symname_len) != 0)
875*a9fa9459Szrj 	continue;
876*a9fa9459Szrj       char c = archive_symname[symname_len];
877*a9fa9459Szrj       if (c == '\0' && sym->version() == NULL)
878*a9fa9459Szrj 	return true;
879*a9fa9459Szrj       if (c == '@')
880*a9fa9459Szrj 	{
881*a9fa9459Szrj 	  const char* ver = archive_symname + symname_len + 1;
882*a9fa9459Szrj 	  if (*ver == '@')
883*a9fa9459Szrj 	    {
884*a9fa9459Szrj 	      if (sym->version() == NULL)
885*a9fa9459Szrj 		return true;
886*a9fa9459Szrj 	      ++ver;
887*a9fa9459Szrj 	    }
888*a9fa9459Szrj 	  if (sym->version() != NULL && strcmp(sym->version(), ver) == 0)
889*a9fa9459Szrj 	    return true;
890*a9fa9459Szrj 	}
891*a9fa9459Szrj     }
892*a9fa9459Szrj   return false;
893*a9fa9459Szrj }
894*a9fa9459Szrj 
895*a9fa9459Szrj // Include all the archive members in the link.  This is for --whole-archive.
896*a9fa9459Szrj 
897*a9fa9459Szrj bool
include_all_members(Symbol_table * symtab,Layout * layout,Input_objects * input_objects,Mapfile * mapfile)898*a9fa9459Szrj Archive::include_all_members(Symbol_table* symtab, Layout* layout,
899*a9fa9459Szrj                              Input_objects* input_objects, Mapfile* mapfile)
900*a9fa9459Szrj {
901*a9fa9459Szrj   // Don't include the same archive twice.  This can happen if
902*a9fa9459Szrj   // --whole-archive is nested inside --start-group (PR gold/12163).
903*a9fa9459Szrj   if (this->included_all_members_)
904*a9fa9459Szrj     return true;
905*a9fa9459Szrj 
906*a9fa9459Szrj   this->included_all_members_ = true;
907*a9fa9459Szrj 
908*a9fa9459Szrj   input_objects->archive_start(this);
909*a9fa9459Szrj 
910*a9fa9459Szrj   if (this->members_.size() > 0)
911*a9fa9459Szrj     {
912*a9fa9459Szrj       std::map<off_t, Archive_member>::const_iterator p;
913*a9fa9459Szrj       for (p = this->members_.begin();
914*a9fa9459Szrj            p != this->members_.end();
915*a9fa9459Szrj            ++p)
916*a9fa9459Szrj         {
917*a9fa9459Szrj           if (!this->include_member(symtab, layout, input_objects, p->first,
918*a9fa9459Szrj 				    mapfile, NULL, "--whole-archive"))
919*a9fa9459Szrj 	    return false;
920*a9fa9459Szrj           ++Archive::total_members;
921*a9fa9459Szrj         }
922*a9fa9459Szrj     }
923*a9fa9459Szrj   else
924*a9fa9459Szrj     {
925*a9fa9459Szrj       for (Archive::const_iterator p = this->begin();
926*a9fa9459Szrj            p != this->end();
927*a9fa9459Szrj            ++p)
928*a9fa9459Szrj         {
929*a9fa9459Szrj           if (!this->include_member(symtab, layout, input_objects, p->off,
930*a9fa9459Szrj 				    mapfile, NULL, "--whole-archive"))
931*a9fa9459Szrj 	    return false;
932*a9fa9459Szrj           ++Archive::total_members;
933*a9fa9459Szrj         }
934*a9fa9459Szrj     }
935*a9fa9459Szrj 
936*a9fa9459Szrj   input_objects->archive_stop(this);
937*a9fa9459Szrj 
938*a9fa9459Szrj   return true;
939*a9fa9459Szrj }
940*a9fa9459Szrj 
941*a9fa9459Szrj // Return the number of members in the archive.  This is only used for
942*a9fa9459Szrj // reports.
943*a9fa9459Szrj 
944*a9fa9459Szrj size_t
count_members()945*a9fa9459Szrj Archive::count_members()
946*a9fa9459Szrj {
947*a9fa9459Szrj   size_t ret = 0;
948*a9fa9459Szrj   for (Archive::const_iterator p = this->begin();
949*a9fa9459Szrj        p != this->end();
950*a9fa9459Szrj        ++p)
951*a9fa9459Szrj     ++ret;
952*a9fa9459Szrj   return ret;
953*a9fa9459Szrj }
954*a9fa9459Szrj 
955*a9fa9459Szrj // RAII class to ensure we unlock the object if it's a member of a
956*a9fa9459Szrj // thin archive. We can't use Task_lock_obj in Archive::include_member
957*a9fa9459Szrj // because the object file is already locked when it's opened by
958*a9fa9459Szrj // get_elf_object_for_member.
959*a9fa9459Szrj 
960*a9fa9459Szrj class Thin_archive_object_unlocker
961*a9fa9459Szrj {
962*a9fa9459Szrj  public:
Thin_archive_object_unlocker(const Task * task,Object * obj)963*a9fa9459Szrj   Thin_archive_object_unlocker(const Task *task, Object* obj)
964*a9fa9459Szrj     : task_(task), obj_(obj)
965*a9fa9459Szrj   { }
966*a9fa9459Szrj 
~Thin_archive_object_unlocker()967*a9fa9459Szrj   ~Thin_archive_object_unlocker()
968*a9fa9459Szrj   {
969*a9fa9459Szrj     if (this->obj_->offset() == 0)
970*a9fa9459Szrj       this->obj_->unlock(this->task_);
971*a9fa9459Szrj   }
972*a9fa9459Szrj 
973*a9fa9459Szrj  private:
974*a9fa9459Szrj   Thin_archive_object_unlocker(const Thin_archive_object_unlocker&);
975*a9fa9459Szrj   Thin_archive_object_unlocker& operator=(const Thin_archive_object_unlocker&);
976*a9fa9459Szrj 
977*a9fa9459Szrj   const Task* task_;
978*a9fa9459Szrj   Object* obj_;
979*a9fa9459Szrj };
980*a9fa9459Szrj 
981*a9fa9459Szrj // Include an archive member in the link.  OFF is the file offset of
982*a9fa9459Szrj // the member header.  WHY is the reason we are including this member.
983*a9fa9459Szrj // Return true if we added the member or if we had an error, return
984*a9fa9459Szrj // false if this was the first member we tried to add from this
985*a9fa9459Szrj // archive and it had an incompatible format.
986*a9fa9459Szrj 
987*a9fa9459Szrj bool
include_member(Symbol_table * symtab,Layout * layout,Input_objects * input_objects,off_t off,Mapfile * mapfile,Symbol * sym,const char * why)988*a9fa9459Szrj Archive::include_member(Symbol_table* symtab, Layout* layout,
989*a9fa9459Szrj 			Input_objects* input_objects, off_t off,
990*a9fa9459Szrj 			Mapfile* mapfile, Symbol* sym, const char* why)
991*a9fa9459Szrj {
992*a9fa9459Szrj   ++Archive::total_members_loaded;
993*a9fa9459Szrj 
994*a9fa9459Szrj   std::map<off_t, Archive_member>::const_iterator p = this->members_.find(off);
995*a9fa9459Szrj   if (p != this->members_.end())
996*a9fa9459Szrj     {
997*a9fa9459Szrj       Object* obj = p->second.obj_;
998*a9fa9459Szrj 
999*a9fa9459Szrj       Read_symbols_data* sd = p->second.sd_;
1000*a9fa9459Szrj       if (mapfile != NULL)
1001*a9fa9459Szrj         mapfile->report_include_archive_member(obj->name(), sym, why);
1002*a9fa9459Szrj       if (input_objects->add_object(obj))
1003*a9fa9459Szrj         {
1004*a9fa9459Szrj           obj->layout(symtab, layout, sd);
1005*a9fa9459Szrj           obj->add_symbols(symtab, sd, layout);
1006*a9fa9459Szrj 	  this->included_member_ = true;
1007*a9fa9459Szrj         }
1008*a9fa9459Szrj       delete sd;
1009*a9fa9459Szrj       return true;
1010*a9fa9459Szrj     }
1011*a9fa9459Szrj 
1012*a9fa9459Szrj   // If this is the first object we are including from this archive,
1013*a9fa9459Szrj   // and we searched for this archive, most likely because it was
1014*a9fa9459Szrj   // found via a -l option, then if the target is incompatible we want
1015*a9fa9459Szrj   // to move on to the next archive found in the search path.
1016*a9fa9459Szrj   bool unconfigured = false;
1017*a9fa9459Szrj   bool* punconfigured = NULL;
1018*a9fa9459Szrj   if (!this->included_member_ && this->searched_for())
1019*a9fa9459Szrj     punconfigured = &unconfigured;
1020*a9fa9459Szrj 
1021*a9fa9459Szrj   Object* obj = this->get_elf_object_for_member(off, punconfigured);
1022*a9fa9459Szrj   if (obj == NULL)
1023*a9fa9459Szrj     {
1024*a9fa9459Szrj       // Return false to search for another archive, true if we found
1025*a9fa9459Szrj       // an error.
1026*a9fa9459Szrj       return unconfigured ? false : true;
1027*a9fa9459Szrj     }
1028*a9fa9459Szrj 
1029*a9fa9459Szrj   // If the object is an external member of a thin archive,
1030*a9fa9459Szrj   // unlock it when we're done here.
1031*a9fa9459Szrj   Thin_archive_object_unlocker unlocker(this->task_, obj);
1032*a9fa9459Szrj 
1033*a9fa9459Szrj   if (mapfile != NULL)
1034*a9fa9459Szrj     mapfile->report_include_archive_member(obj->name(), sym, why);
1035*a9fa9459Szrj 
1036*a9fa9459Szrj   Pluginobj* pluginobj = obj->pluginobj();
1037*a9fa9459Szrj   if (pluginobj != NULL)
1038*a9fa9459Szrj     {
1039*a9fa9459Szrj       pluginobj->add_symbols(symtab, NULL, layout);
1040*a9fa9459Szrj       this->included_member_ = true;
1041*a9fa9459Szrj       return true;
1042*a9fa9459Szrj     }
1043*a9fa9459Szrj 
1044*a9fa9459Szrj   if (!input_objects->add_object(obj))
1045*a9fa9459Szrj     {
1046*a9fa9459Szrj       delete obj;
1047*a9fa9459Szrj       return true;
1048*a9fa9459Szrj     }
1049*a9fa9459Szrj 
1050*a9fa9459Szrj   if (layout->incremental_inputs() != NULL)
1051*a9fa9459Szrj     layout->incremental_inputs()->report_object(obj, 0, this, NULL);
1052*a9fa9459Szrj 
1053*a9fa9459Szrj   {
1054*a9fa9459Szrj     Read_symbols_data sd;
1055*a9fa9459Szrj     obj->read_symbols(&sd);
1056*a9fa9459Szrj     obj->layout(symtab, layout, &sd);
1057*a9fa9459Szrj     obj->add_symbols(symtab, &sd, layout);
1058*a9fa9459Szrj   }
1059*a9fa9459Szrj 
1060*a9fa9459Szrj   this->included_member_ = true;
1061*a9fa9459Szrj   return true;
1062*a9fa9459Szrj }
1063*a9fa9459Szrj 
1064*a9fa9459Szrj // Iterate over all unused symbols, and call the visitor class V for each.
1065*a9fa9459Szrj 
1066*a9fa9459Szrj void
do_for_all_unused_symbols(Symbol_visitor_base * v) const1067*a9fa9459Szrj Archive::do_for_all_unused_symbols(Symbol_visitor_base* v) const
1068*a9fa9459Szrj {
1069*a9fa9459Szrj   for (std::vector<Armap_entry>::const_iterator p = this->armap_.begin();
1070*a9fa9459Szrj        p != this->armap_.end();
1071*a9fa9459Szrj        ++p)
1072*a9fa9459Szrj     {
1073*a9fa9459Szrj       if (this->seen_offsets_.find(p->file_offset)
1074*a9fa9459Szrj           == this->seen_offsets_.end())
1075*a9fa9459Szrj         v->visit(this->armap_names_.data() + p->name_offset);
1076*a9fa9459Szrj     }
1077*a9fa9459Szrj }
1078*a9fa9459Szrj 
1079*a9fa9459Szrj // Print statistical information to stderr.  This is used for --stats.
1080*a9fa9459Szrj 
1081*a9fa9459Szrj void
print_stats()1082*a9fa9459Szrj Archive::print_stats()
1083*a9fa9459Szrj {
1084*a9fa9459Szrj   fprintf(stderr, _("%s: archive libraries: %u\n"),
1085*a9fa9459Szrj           program_name, Archive::total_archives);
1086*a9fa9459Szrj   fprintf(stderr, _("%s: total archive members: %u\n"),
1087*a9fa9459Szrj           program_name, Archive::total_members);
1088*a9fa9459Szrj   fprintf(stderr, _("%s: loaded archive members: %u\n"),
1089*a9fa9459Szrj           program_name, Archive::total_members_loaded);
1090*a9fa9459Szrj }
1091*a9fa9459Szrj 
1092*a9fa9459Szrj // Add_archive_symbols methods.
1093*a9fa9459Szrj 
~Add_archive_symbols()1094*a9fa9459Szrj Add_archive_symbols::~Add_archive_symbols()
1095*a9fa9459Szrj {
1096*a9fa9459Szrj   if (this->this_blocker_ != NULL)
1097*a9fa9459Szrj     delete this->this_blocker_;
1098*a9fa9459Szrj   // next_blocker_ is deleted by the task associated with the next
1099*a9fa9459Szrj   // input file.
1100*a9fa9459Szrj }
1101*a9fa9459Szrj 
1102*a9fa9459Szrj // Return whether we can add the archive symbols.  We are blocked by
1103*a9fa9459Szrj // this_blocker_.  We block next_blocker_.  We also lock the file.
1104*a9fa9459Szrj 
1105*a9fa9459Szrj Task_token*
is_runnable()1106*a9fa9459Szrj Add_archive_symbols::is_runnable()
1107*a9fa9459Szrj {
1108*a9fa9459Szrj   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
1109*a9fa9459Szrj     return this->this_blocker_;
1110*a9fa9459Szrj   return NULL;
1111*a9fa9459Szrj }
1112*a9fa9459Szrj 
1113*a9fa9459Szrj void
locks(Task_locker * tl)1114*a9fa9459Szrj Add_archive_symbols::locks(Task_locker* tl)
1115*a9fa9459Szrj {
1116*a9fa9459Szrj   tl->add(this, this->next_blocker_);
1117*a9fa9459Szrj   tl->add(this, this->archive_->token());
1118*a9fa9459Szrj }
1119*a9fa9459Szrj 
1120*a9fa9459Szrj void
run(Workqueue * workqueue)1121*a9fa9459Szrj Add_archive_symbols::run(Workqueue* workqueue)
1122*a9fa9459Szrj {
1123*a9fa9459Szrj   // For an incremental link, begin recording layout information.
1124*a9fa9459Szrj   Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
1125*a9fa9459Szrj   if (incremental_inputs != NULL)
1126*a9fa9459Szrj     {
1127*a9fa9459Szrj       unsigned int arg_serial = this->input_argument_->file().arg_serial();
1128*a9fa9459Szrj       Script_info* script_info = this->input_argument_->script_info();
1129*a9fa9459Szrj       incremental_inputs->report_archive_begin(this->archive_, arg_serial,
1130*a9fa9459Szrj 					       script_info);
1131*a9fa9459Szrj     }
1132*a9fa9459Szrj 
1133*a9fa9459Szrj   bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
1134*a9fa9459Szrj 					   this->input_objects_,
1135*a9fa9459Szrj 					   this->mapfile_);
1136*a9fa9459Szrj   this->archive_->unlock_nested_archives();
1137*a9fa9459Szrj 
1138*a9fa9459Szrj   this->archive_->release();
1139*a9fa9459Szrj   this->archive_->clear_uncached_views();
1140*a9fa9459Szrj 
1141*a9fa9459Szrj   if (!added)
1142*a9fa9459Szrj     {
1143*a9fa9459Szrj       // This archive holds object files which are incompatible with
1144*a9fa9459Szrj       // our output file.
1145*a9fa9459Szrj       Read_symbols::incompatible_warning(this->input_argument_,
1146*a9fa9459Szrj 					 this->archive_->input_file());
1147*a9fa9459Szrj       Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_,
1148*a9fa9459Szrj 			    this->layout_, this->dirpath_, this->dirindex_,
1149*a9fa9459Szrj 			    this->mapfile_, this->input_argument_,
1150*a9fa9459Szrj 			    this->input_group_, this->next_blocker_);
1151*a9fa9459Szrj       delete this->archive_;
1152*a9fa9459Szrj       return;
1153*a9fa9459Szrj     }
1154*a9fa9459Szrj 
1155*a9fa9459Szrj   if (this->input_group_ != NULL)
1156*a9fa9459Szrj     this->input_group_->add_archive(this->archive_);
1157*a9fa9459Szrj   else
1158*a9fa9459Szrj     {
1159*a9fa9459Szrj       // For an incremental link, finish recording the layout information.
1160*a9fa9459Szrj       if (incremental_inputs != NULL)
1161*a9fa9459Szrj 	incremental_inputs->report_archive_end(this->archive_);
1162*a9fa9459Szrj 
1163*a9fa9459Szrj       if (!parameters->options().has_plugins()
1164*a9fa9459Szrj 	  || this->archive_->input_file()->options().whole_archive())
1165*a9fa9459Szrj 	{
1166*a9fa9459Szrj 	  // We no longer need to know about this archive.
1167*a9fa9459Szrj 	  delete this->archive_;
1168*a9fa9459Szrj 	}
1169*a9fa9459Szrj       else
1170*a9fa9459Szrj 	{
1171*a9fa9459Szrj 	  // The plugin interface may want to rescan this archive.
1172*a9fa9459Szrj 	  parameters->options().plugins()->save_archive(this->archive_);
1173*a9fa9459Szrj 	}
1174*a9fa9459Szrj 
1175*a9fa9459Szrj       this->archive_ = NULL;
1176*a9fa9459Szrj     }
1177*a9fa9459Szrj }
1178*a9fa9459Szrj 
1179*a9fa9459Szrj // Class Lib_group static variables.
1180*a9fa9459Szrj unsigned int Lib_group::total_lib_groups;
1181*a9fa9459Szrj unsigned int Lib_group::total_members;
1182*a9fa9459Szrj unsigned int Lib_group::total_members_loaded;
1183*a9fa9459Szrj 
Lib_group(const Input_file_lib * lib,Task * task)1184*a9fa9459Szrj Lib_group::Lib_group(const Input_file_lib* lib, Task* task)
1185*a9fa9459Szrj   : Library_base(task), members_()
1186*a9fa9459Szrj {
1187*a9fa9459Szrj   this->members_.resize(lib->size());
1188*a9fa9459Szrj }
1189*a9fa9459Szrj 
1190*a9fa9459Szrj const std::string&
do_filename() const1191*a9fa9459Szrj Lib_group::do_filename() const
1192*a9fa9459Szrj {
1193*a9fa9459Szrj   std::string *filename = new std::string("/group/");
1194*a9fa9459Szrj   return *filename;
1195*a9fa9459Szrj }
1196*a9fa9459Szrj 
1197*a9fa9459Szrj // Select members from the lib group and add them to the link.  We walk
1198*a9fa9459Szrj // through the members, and check if each one up should be included.
1199*a9fa9459Szrj // If the object says it should be included, we do so.  We have to do
1200*a9fa9459Szrj // this in a loop, since including one member may create new undefined
1201*a9fa9459Szrj // symbols which may be satisfied by other members.
1202*a9fa9459Szrj 
1203*a9fa9459Szrj void
add_symbols(Symbol_table * symtab,Layout * layout,Input_objects * input_objects)1204*a9fa9459Szrj Lib_group::add_symbols(Symbol_table* symtab, Layout* layout,
1205*a9fa9459Szrj                        Input_objects* input_objects)
1206*a9fa9459Szrj {
1207*a9fa9459Szrj   ++Lib_group::total_lib_groups;
1208*a9fa9459Szrj 
1209*a9fa9459Szrj   Lib_group::total_members += this->members_.size();
1210*a9fa9459Szrj 
1211*a9fa9459Szrj   bool added_new_object;
1212*a9fa9459Szrj   do
1213*a9fa9459Szrj     {
1214*a9fa9459Szrj       added_new_object = false;
1215*a9fa9459Szrj       unsigned int i = 0;
1216*a9fa9459Szrj       while (i < this->members_.size())
1217*a9fa9459Szrj 	{
1218*a9fa9459Szrj 	  const Archive_member& member = this->members_[i];
1219*a9fa9459Szrj 	  Object* obj = member.obj_;
1220*a9fa9459Szrj 	  std::string why;
1221*a9fa9459Szrj 
1222*a9fa9459Szrj           // Skip files with no symbols. Plugin objects have
1223*a9fa9459Szrj           // member.sd_ == NULL.
1224*a9fa9459Szrj           if (obj != NULL
1225*a9fa9459Szrj 	      && (member.sd_ == NULL || member.sd_->symbol_names != NULL))
1226*a9fa9459Szrj             {
1227*a9fa9459Szrj 	      Archive::Should_include t = obj->should_include_member(symtab,
1228*a9fa9459Szrj 								     layout,
1229*a9fa9459Szrj 								     member.sd_,
1230*a9fa9459Szrj 								     &why);
1231*a9fa9459Szrj 
1232*a9fa9459Szrj 	      if (t != Archive::SHOULD_INCLUDE_YES)
1233*a9fa9459Szrj 		{
1234*a9fa9459Szrj 		  ++i;
1235*a9fa9459Szrj 		  continue;
1236*a9fa9459Szrj 		}
1237*a9fa9459Szrj 
1238*a9fa9459Szrj 	      this->include_member(symtab, layout, input_objects, member);
1239*a9fa9459Szrj 
1240*a9fa9459Szrj 	      added_new_object = true;
1241*a9fa9459Szrj 	    }
1242*a9fa9459Szrj           else
1243*a9fa9459Szrj             {
1244*a9fa9459Szrj               if (member.sd_ != NULL)
1245*a9fa9459Szrj 		{
1246*a9fa9459Szrj 		  // The file must be locked in order to destroy the views
1247*a9fa9459Szrj 		  // associated with it.
1248*a9fa9459Szrj 		  gold_assert(obj != NULL);
1249*a9fa9459Szrj 		  obj->lock(this->task_);
1250*a9fa9459Szrj 		  delete member.sd_;
1251*a9fa9459Szrj 		  obj->unlock(this->task_);
1252*a9fa9459Szrj 		}
1253*a9fa9459Szrj             }
1254*a9fa9459Szrj 
1255*a9fa9459Szrj 	  this->members_[i] = this->members_.back();
1256*a9fa9459Szrj 	  this->members_.pop_back();
1257*a9fa9459Szrj 	}
1258*a9fa9459Szrj     }
1259*a9fa9459Szrj   while (added_new_object);
1260*a9fa9459Szrj }
1261*a9fa9459Szrj 
1262*a9fa9459Szrj // Include a lib group member in the link.
1263*a9fa9459Szrj 
1264*a9fa9459Szrj void
include_member(Symbol_table * symtab,Layout * layout,Input_objects * input_objects,const Archive_member & member)1265*a9fa9459Szrj Lib_group::include_member(Symbol_table* symtab, Layout* layout,
1266*a9fa9459Szrj 			  Input_objects* input_objects,
1267*a9fa9459Szrj 			  const Archive_member& member)
1268*a9fa9459Szrj {
1269*a9fa9459Szrj   ++Lib_group::total_members_loaded;
1270*a9fa9459Szrj 
1271*a9fa9459Szrj   Object* obj = member.obj_;
1272*a9fa9459Szrj   gold_assert(obj != NULL);
1273*a9fa9459Szrj 
1274*a9fa9459Szrj   Pluginobj* pluginobj = obj->pluginobj();
1275*a9fa9459Szrj   if (pluginobj != NULL)
1276*a9fa9459Szrj     {
1277*a9fa9459Szrj       pluginobj->add_symbols(symtab, NULL, layout);
1278*a9fa9459Szrj       return;
1279*a9fa9459Szrj     }
1280*a9fa9459Szrj 
1281*a9fa9459Szrj   Read_symbols_data* sd = member.sd_;
1282*a9fa9459Szrj   gold_assert(sd != NULL);
1283*a9fa9459Szrj   obj->lock(this->task_);
1284*a9fa9459Szrj   if (input_objects->add_object(obj))
1285*a9fa9459Szrj     {
1286*a9fa9459Szrj       if (layout->incremental_inputs() != NULL)
1287*a9fa9459Szrj 	layout->incremental_inputs()->report_object(obj, member.arg_serial_,
1288*a9fa9459Szrj 						    this, NULL);
1289*a9fa9459Szrj       obj->layout(symtab, layout, sd);
1290*a9fa9459Szrj       obj->add_symbols(symtab, sd, layout);
1291*a9fa9459Szrj     }
1292*a9fa9459Szrj   delete sd;
1293*a9fa9459Szrj   // Unlock the file for the next task.
1294*a9fa9459Szrj   obj->unlock(this->task_);
1295*a9fa9459Szrj }
1296*a9fa9459Szrj 
1297*a9fa9459Szrj // Iterate over all unused symbols, and call the visitor class V for each.
1298*a9fa9459Szrj 
1299*a9fa9459Szrj void
do_for_all_unused_symbols(Symbol_visitor_base * v) const1300*a9fa9459Szrj Lib_group::do_for_all_unused_symbols(Symbol_visitor_base* v) const
1301*a9fa9459Szrj {
1302*a9fa9459Szrj   // Files are removed from the members list when used, so all the
1303*a9fa9459Szrj   // files remaining on the list are unused.
1304*a9fa9459Szrj   for (std::vector<Archive_member>::const_iterator p = this->members_.begin();
1305*a9fa9459Szrj        p != this->members_.end();
1306*a9fa9459Szrj        ++p)
1307*a9fa9459Szrj     {
1308*a9fa9459Szrj       Object* obj = p->obj_;
1309*a9fa9459Szrj       obj->for_all_global_symbols(p->sd_, v);
1310*a9fa9459Szrj     }
1311*a9fa9459Szrj }
1312*a9fa9459Szrj 
1313*a9fa9459Szrj // Print statistical information to stderr.  This is used for --stats.
1314*a9fa9459Szrj 
1315*a9fa9459Szrj void
print_stats()1316*a9fa9459Szrj Lib_group::print_stats()
1317*a9fa9459Szrj {
1318*a9fa9459Szrj   fprintf(stderr, _("%s: lib groups: %u\n"),
1319*a9fa9459Szrj           program_name, Lib_group::total_lib_groups);
1320*a9fa9459Szrj   fprintf(stderr, _("%s: total lib groups members: %u\n"),
1321*a9fa9459Szrj           program_name, Lib_group::total_members);
1322*a9fa9459Szrj   fprintf(stderr, _("%s: loaded lib groups members: %u\n"),
1323*a9fa9459Szrj           program_name, Lib_group::total_members_loaded);
1324*a9fa9459Szrj }
1325*a9fa9459Szrj 
1326*a9fa9459Szrj Task_token*
is_runnable()1327*a9fa9459Szrj Add_lib_group_symbols::is_runnable()
1328*a9fa9459Szrj {
1329*a9fa9459Szrj   if (this->readsyms_blocker_ != NULL && this->readsyms_blocker_->is_blocked())
1330*a9fa9459Szrj     return this->readsyms_blocker_;
1331*a9fa9459Szrj   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
1332*a9fa9459Szrj     return this->this_blocker_;
1333*a9fa9459Szrj   return NULL;
1334*a9fa9459Szrj }
1335*a9fa9459Szrj 
1336*a9fa9459Szrj void
locks(Task_locker * tl)1337*a9fa9459Szrj Add_lib_group_symbols::locks(Task_locker* tl)
1338*a9fa9459Szrj {
1339*a9fa9459Szrj   tl->add(this, this->next_blocker_);
1340*a9fa9459Szrj }
1341*a9fa9459Szrj 
1342*a9fa9459Szrj void
run(Workqueue *)1343*a9fa9459Szrj Add_lib_group_symbols::run(Workqueue*)
1344*a9fa9459Szrj {
1345*a9fa9459Szrj   // For an incremental link, begin recording layout information.
1346*a9fa9459Szrj   Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
1347*a9fa9459Szrj   if (incremental_inputs != NULL)
1348*a9fa9459Szrj     incremental_inputs->report_archive_begin(this->lib_, 0, NULL);
1349*a9fa9459Szrj 
1350*a9fa9459Szrj   this->lib_->add_symbols(this->symtab_, this->layout_, this->input_objects_);
1351*a9fa9459Szrj 
1352*a9fa9459Szrj   if (incremental_inputs != NULL)
1353*a9fa9459Szrj     incremental_inputs->report_archive_end(this->lib_);
1354*a9fa9459Szrj }
1355*a9fa9459Szrj 
~Add_lib_group_symbols()1356*a9fa9459Szrj Add_lib_group_symbols::~Add_lib_group_symbols()
1357*a9fa9459Szrj {
1358*a9fa9459Szrj   if (this->this_blocker_ != NULL)
1359*a9fa9459Szrj     delete this->this_blocker_;
1360*a9fa9459Szrj   // next_blocker_ is deleted by the task associated with the next
1361*a9fa9459Szrj   // input file.
1362*a9fa9459Szrj }
1363*a9fa9459Szrj 
1364*a9fa9459Szrj } // End namespace gold.
1365