Rework patch to check by both armap entry and archive offset. Also,
[external/binutils.git] / gold / archive.cc
1 // archive.cc -- archive support for gold
2
3 #include "gold.h"
4
5 #include <cerrno>
6 #include <cstring>
7 #include <climits>
8 #include <vector>
9
10 #include "elfcpp.h"
11 #include "fileread.h"
12 #include "readsyms.h"
13 #include "symtab.h"
14 #include "object.h"
15 #include "archive.h"
16
17 namespace gold
18 {
19
20 // The header of an entry in the archive.  This is all readable text,
21 // padded with spaces where necesary.  If the contents of an archive
22 // are all text file, the entire archive is readable.
23
24 struct Archive::Archive_header
25 {
26   // The entry name.
27   char ar_name[16];
28   // The file modification time.
29   char ar_date[12];
30   // The user's UID in decimal.
31   char ar_uid[6];
32   // The user's GID in decimal.
33   char ar_gid[6];
34   // The file mode in octal.
35   char ar_mode[8];
36   // The file size in decimal.
37   char ar_size[10];
38   // The final magic code.
39   char ar_fmag[2];
40 };
41
42 // Archive methods.
43
44 const char Archive::armag[sarmag] =
45 {
46   '!', '<', 'a', 'r', 'c', 'h', '>', '\n'
47 };
48
49 const char Archive::arfmag[2] = { '`', '\n' };
50
51 // Set up the archive: read the symbol map and the extended name
52 // table.
53
54 void
55 Archive::setup()
56 {
57   // The first member of the archive should be the symbol table.
58   std::string armap_name;
59   off_t armap_size = this->read_header(sarmag, &armap_name);
60   off_t off;
61   if (armap_name.empty())
62     {
63       this->read_armap(sarmag + sizeof(Archive_header), armap_size);
64       off = sarmag + sizeof(Archive_header) + armap_size;
65     }
66   else if (!this->input_file_->options().include_whole_archive())
67     {
68       fprintf(stderr, _("%s: %s: no archive symbol table (run ranlib)\n"),
69               program_name, this->name().c_str());
70       gold_exit(false);
71     }
72   else
73     off = sarmag;
74
75   // See if there is an extended name table.
76   if ((off & 1) != 0)
77     ++off;
78   std::string xname;
79   off_t extended_size = this->read_header(off, &xname);
80   if (xname == "/")
81     {
82       const unsigned char* p = this->get_view(off + sizeof(Archive_header),
83                                               extended_size);
84       const char* px = reinterpret_cast<const char*>(p);
85       this->extended_names_.assign(px, extended_size);
86     }
87
88   // Opening the file locked it.  Unlock it now.
89   this->input_file_->file().unlock();
90 }
91
92 // Read the archive symbol map.
93
94 void
95 Archive::read_armap(off_t start, off_t size)
96 {
97   // Read in the entire armap.
98   const unsigned char* p = this->get_view(start, size);
99
100   // Numbers in the armap are always big-endian.
101   const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
102   unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword);
103   ++pword;
104
105   // Note that the addition is in units of sizeof(elfcpp::Elf_Word).
106   const char* pnames = reinterpret_cast<const char*>(pword + nsyms);
107
108   this->armap_.resize(nsyms);
109
110   for (unsigned int i = 0; i < nsyms; ++i)
111     {
112       this->armap_[i].name = pnames;
113       this->armap_[i].offset = elfcpp::Swap<32, true>::readval(pword);
114       pnames += strlen(pnames) + 1;
115       ++pword;
116     }
117
118   if (reinterpret_cast<const unsigned char*>(pnames) - p > size)
119     {
120       fprintf(stderr, _("%s: %s: bad archive symbol table names\n"),
121               program_name, this->name().c_str());
122       gold_exit(false);
123     }
124
125   // This array keeps track of which symbols are for archive elements
126   // which we have already included in the link.
127   this->armap_checked_.resize(nsyms);
128 }
129
130 // Read the header of an archive member at OFF.  Fail if something
131 // goes wrong.  Return the size of the member.  Set *PNAME to the name
132 // of the member.
133
134 off_t
135 Archive::read_header(off_t off, std::string* pname)
136 {
137   const unsigned char* p = this->get_view(off, sizeof(Archive_header));
138   const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
139   return this->interpret_header(hdr, off,  pname);
140 }
141
142 // Interpret the header of HDR, the header of the archive member at
143 // file offset OFF.  Fail if something goes wrong.  Return the size of
144 // the member.  Set *PNAME to the name of the member.
145
146 off_t
147 Archive::interpret_header(const Archive_header* hdr, off_t off,
148                           std::string* pname)
149 {
150   if (memcmp(hdr->ar_fmag, arfmag, sizeof arfmag) != 0)
151     {
152       fprintf(stderr, _("%s; %s: malformed archive header at %ld\n"),
153               program_name, this->name().c_str(),
154               static_cast<long>(off));
155       gold_exit(false);
156     }
157
158   const int size_string_size = sizeof hdr->ar_size;
159   char size_string[size_string_size + 1];
160   memcpy(size_string, hdr->ar_size, size_string_size);
161   char* ps = size_string + size_string_size;
162   while (ps[-1] == ' ')
163     --ps;
164   *ps = '\0';
165
166   errno = 0;
167   char* end;
168   off_t member_size = strtol(size_string, &end, 10);
169   if (*end != '\0'
170       || member_size < 0
171       || (member_size == LONG_MAX && errno == ERANGE))
172     {
173       fprintf(stderr, _("%s: %s: malformed archive header size at %ld\n"),
174               program_name, this->name().c_str(),
175               static_cast<long>(off));
176       gold_exit(false);
177     }
178
179   if (hdr->ar_name[0] != '/')
180     {
181       const char* name_end = strchr(hdr->ar_name, '/');
182       if (name_end == NULL
183           || name_end - hdr->ar_name >= static_cast<int>(sizeof hdr->ar_name))
184         {
185           fprintf(stderr, _("%s: %s: malformed archive header name at %ld\n"),
186                   program_name, this->name().c_str(),
187                   static_cast<long>(off));
188           gold_exit(false);
189         }
190       pname->assign(hdr->ar_name, name_end - hdr->ar_name);
191     }
192   else if (hdr->ar_name[1] == ' ')
193     {
194       // This is the symbol table.
195       pname->clear();
196     }
197   else if (hdr->ar_name[1] == '/')
198     {
199       // This is the extended name table.
200       pname->assign(1, '/');
201     }
202   else
203     {
204       errno = 0;
205       long x = strtol(hdr->ar_name + 1, &end, 10);
206       if (*end != ' '
207           || x < 0
208           || (x == LONG_MAX && errno == ERANGE)
209           || static_cast<size_t>(x) >= this->extended_names_.size())
210         {
211           fprintf(stderr, _("%s: %s: bad extended name index at %ld\n"),
212                   program_name, this->name().c_str(),
213                   static_cast<long>(off));
214           gold_exit(false);
215         }
216
217       const char* name = this->extended_names_.data() + x;
218       const char* name_end = strchr(name, '/');
219       if (static_cast<size_t>(name_end - name) > this->extended_names_.size()
220           || name_end[1] != '\n')
221         {
222           fprintf(stderr, _("%s: %s: bad extended name entry at header %ld\n"),
223                   program_name, this->name().c_str(),
224                   static_cast<long>(off));
225           gold_exit(false);
226         }
227       pname->assign(name, name_end - name);
228     }
229
230   return member_size;
231 }
232
233 // Select members from the archive and add them to the link.  We walk
234 // through the elements in the archive map, and look each one up in
235 // the symbol table.  If it exists as a strong undefined symbol, we
236 // pull in the corresponding element.  We have to do this in a loop,
237 // since pulling in one element may create new undefined symbols which
238 // may be satisfied by other objects in the archive.
239
240 void
241 Archive::add_symbols(const General_options& options, Symbol_table* symtab,
242                      Layout* layout, Input_objects* input_objects)
243 {
244   if (this->input_file_->options().include_whole_archive())
245     return this->include_all_members(options, symtab, layout, input_objects);
246
247   const size_t armap_size = this->armap_.size();
248
249   // This is a quick optimization, since we usually see many symbols
250   // in a row with the same offset.  last_seen holds the last offset
251   // we saw that was present in the seen_ set.
252   off_t last_seen_offset = -1;
253
254   // Track which symbols in the symbol table we've already found to be
255   // defined.
256
257   bool added_new_object;
258   do
259     {
260       added_new_object = false;
261       for (size_t i = 0; i < armap_size; ++i)
262         {
263           if (this->armap_checked_[i])
264             continue;
265           if (this->armap_[i].offset == last_seen_offset)
266             {
267               this->armap_checked_[i] = true;
268               continue;
269             }
270           if (this->seen_offsets_.find(this->armap_[i].offset)
271               != this->seen_offsets_.end())
272             {
273               this->armap_checked_[i] = true;
274               last_seen_offset = this->armap_[i].offset;
275               continue;
276             }
277
278           Symbol* sym = symtab->lookup(this->armap_[i].name);
279           if (sym == NULL)
280             continue;
281           else if (!sym->is_undefined())
282             {
283               this->armap_checked_[i] = true;
284               continue;
285             }
286           else if (sym->binding() == elfcpp::STB_WEAK)
287             continue;
288
289           // We want to include this object in the link.
290           last_seen_offset = this->armap_[i].offset;
291           this->seen_offsets_.insert(last_seen_offset);
292           this->armap_checked_[i] = true;
293           this->include_member(options, symtab, layout, input_objects,
294                                last_seen_offset);
295           added_new_object = true;
296         }
297     }
298   while (added_new_object);
299 }
300
301 // Include all the archive members in the link.  This is for --whole-archive.
302
303 void
304 Archive::include_all_members(const General_options& options,
305                              Symbol_table* symtab, Layout* layout,
306                              Input_objects* input_objects)
307 {
308   off_t off = sarmag;
309   while (true)
310     {
311       off_t bytes;
312       const unsigned char* p = this->get_view(off, sizeof(Archive_header),
313                                               &bytes);
314       if (bytes < sizeof(Archive_header))
315         {
316           if (bytes != 0)
317             {
318               fprintf(stderr, _("%s: %s: short archive header at %ld\n"),
319                       program_name, this->name().c_str(),
320                       static_cast<long>(off));
321               gold_exit(false);
322             }
323
324           break;
325         }
326
327       const Archive_header* hdr = reinterpret_cast<const Archive_header*>(p);
328       std::string name;
329       off_t size = this->interpret_header(hdr, off, &name);
330       if (name.empty())
331         {
332           // Symbol table.
333         }
334       else if (name == "/")
335         {
336           // Extended name table.
337         }
338       else
339         this->include_member(options, symtab, layout, input_objects, off);
340
341       off += sizeof(Archive_header) + size;
342       if ((off & 1) != 0)
343         ++off;
344     }
345 }
346
347 // Include an archive member in the link.  OFF is the file offset of
348 // the member header.
349
350 void
351 Archive::include_member(const General_options& options, Symbol_table* symtab,
352                         Layout* layout, Input_objects* input_objects,
353                         off_t off)
354 {
355   std::string n;
356   this->read_header(off, &n);
357
358   size_t memoff = off + sizeof(Archive_header);
359
360   // Read enough of the file to pick up the entire ELF header.
361   int ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
362   off_t bytes;
363   const unsigned char* p = this->input_file_->file().get_view(memoff,
364                                                               ehdr_size,
365                                                               &bytes);
366   if (bytes < 4)
367     {
368       fprintf(stderr, _("%s: %s: member at %ld is not an ELF object"),
369               program_name, this->name().c_str(),
370               static_cast<long>(off));
371       gold_exit(false);
372     }
373
374   static unsigned char elfmagic[4] =
375     {
376       elfcpp::ELFMAG0, elfcpp::ELFMAG1,
377       elfcpp::ELFMAG2, elfcpp::ELFMAG3
378     };
379   if (memcmp(p, elfmagic, 4) != 0)
380     {
381       fprintf(stderr, _("%s: %s: member at %ld is not an ELF object"),
382               program_name, this->name().c_str(),
383               static_cast<long>(off));
384       gold_exit(false);
385     }
386
387   Object* obj = make_elf_object((std::string(this->input_file_->filename())
388                                  + "(" + n + ")"),
389                                 this->input_file_, memoff, p, bytes);
390
391   input_objects->add_object(obj);
392
393   Read_symbols_data sd;
394   obj->read_symbols(&sd);
395   obj->layout(options, symtab, layout, &sd);
396   obj->add_symbols(symtab, &sd);
397 }
398
399 // Add_archive_symbols methods.
400
401 Add_archive_symbols::~Add_archive_symbols()
402 {
403   if (this->this_blocker_ != NULL)
404     delete this->this_blocker_;
405   // next_blocker_ is deleted by the task associated with the next
406   // input file.
407 }
408
409 // Return whether we can add the archive symbols.  We are blocked by
410 // this_blocker_.  We block next_blocker_.  We also lock the file.
411
412 Task::Is_runnable_type
413 Add_archive_symbols::is_runnable(Workqueue*)
414 {
415   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
416     return IS_BLOCKED;
417   return IS_RUNNABLE;
418 }
419
420 class Add_archive_symbols::Add_archive_symbols_locker : public Task_locker
421 {
422  public:
423   Add_archive_symbols_locker(Task_token& token, Workqueue* workqueue,
424                              File_read& file)
425     : blocker_(token, workqueue), filelock_(file)
426   { }
427
428  private:
429   Task_locker_block blocker_;
430   Task_locker_obj<File_read> filelock_;
431 };
432
433 Task_locker*
434 Add_archive_symbols::locks(Workqueue* workqueue)
435 {
436   return new Add_archive_symbols_locker(*this->next_blocker_,
437                                         workqueue,
438                                         this->archive_->file());
439 }
440
441 void
442 Add_archive_symbols::run(Workqueue*)
443 {
444   this->archive_->add_symbols(this->options_, this->symtab_, this->layout_,
445                               this->input_objects_);
446
447   if (this->input_group_ != NULL)
448     this->input_group_->add_archive(this->archive_);
449   else
450     {
451       // We no longer need to know about this archive.
452       delete this->archive_;
453     }
454 }
455
456 } // End namespace gold.