1 // archive.cc -- archive support for gold
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.
24 struct Archive::Archive_header
28 // The file modification time.
30 // The user's UID in decimal.
32 // The user's GID in decimal.
34 // The file mode in octal.
36 // The file size in decimal.
38 // The final magic code.
44 const char Archive::armag
[sarmag
] =
46 '!', '<', 'a', 'r', 'c', 'h', '>', '\n'
49 const char Archive::arfmag
[2] = { '`', '\n' };
51 // Set up the archive: read the symbol map and the extended name
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
);
61 if (armap_name
.empty())
63 this->read_armap(sarmag
+ sizeof(Archive_header
), armap_size
);
64 off
= sarmag
+ sizeof(Archive_header
) + armap_size
;
66 else if (!this->input_file_
->options().include_whole_archive())
68 fprintf(stderr
, _("%s: %s: no archive symbol table (run ranlib)\n"),
69 program_name
, this->name().c_str());
75 // See if there is an extended name table.
79 off_t extended_size
= this->read_header(off
, &xname
);
82 const unsigned char* p
= this->get_view(off
+ sizeof(Archive_header
),
84 const char* px
= reinterpret_cast<const char*>(p
);
85 this->extended_names_
.assign(px
, extended_size
);
88 // Opening the file locked it. Unlock it now.
89 this->input_file_
->file().unlock();
92 // Read the archive symbol map.
95 Archive::read_armap(off_t start
, off_t size
)
97 // Read in the entire armap.
98 const unsigned char* p
= this->get_view(start
, size
);
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
);
105 // Note that the addition is in units of sizeof(elfcpp::Elf_Word).
106 const char* pnames
= reinterpret_cast<const char*>(pword
+ nsyms
);
108 this->armap_
.resize(nsyms
);
110 for (unsigned int i
= 0; i
< nsyms
; ++i
)
112 this->armap_
[i
].name
= pnames
;
113 this->armap_
[i
].offset
= elfcpp::Swap
<32, true>::readval(pword
);
114 pnames
+= strlen(pnames
) + 1;
118 if (reinterpret_cast<const unsigned char*>(pnames
) - p
> size
)
120 fprintf(stderr
, _("%s: %s: bad archive symbol table names\n"),
121 program_name
, this->name().c_str());
126 // Read the header of an archive member at OFF. Fail if something
127 // goes wrong. Return the size of the member. Set *PNAME to the name
131 Archive::read_header(off_t off
, std::string
* pname
)
133 const unsigned char* p
= this->get_view(off
, sizeof(Archive_header
));
134 const Archive_header
* hdr
= reinterpret_cast<const Archive_header
*>(p
);
135 return this->interpret_header(hdr
, off
, pname
);
138 // Interpret the header of HDR, the header of the archive member at
139 // file offset OFF. Fail if something goes wrong. Return the size of
140 // the member. Set *PNAME to the name of the member.
143 Archive::interpret_header(const Archive_header
* hdr
, off_t off
,
146 if (memcmp(hdr
->ar_fmag
, arfmag
, sizeof arfmag
) != 0)
148 fprintf(stderr
, _("%s; %s: malformed archive header at %ld\n"),
149 program_name
, this->name().c_str(),
150 static_cast<long>(off
));
154 const int size_string_size
= sizeof hdr
->ar_size
;
155 char size_string
[size_string_size
+ 1];
156 memcpy(size_string
, hdr
->ar_size
, size_string_size
);
157 char* ps
= size_string
+ size_string_size
;
158 while (ps
[-1] == ' ')
164 off_t member_size
= strtol(size_string
, &end
, 10);
167 || (member_size
== LONG_MAX
&& errno
== ERANGE
))
169 fprintf(stderr
, _("%s: %s: malformed archive header size at %ld\n"),
170 program_name
, this->name().c_str(),
171 static_cast<long>(off
));
175 if (hdr
->ar_name
[0] != '/')
177 const char* name_end
= strchr(hdr
->ar_name
, '/');
179 || name_end
- hdr
->ar_name
>= static_cast<int>(sizeof hdr
->ar_name
))
181 fprintf(stderr
, _("%s: %s: malformed archive header name at %ld\n"),
182 program_name
, this->name().c_str(),
183 static_cast<long>(off
));
186 pname
->assign(hdr
->ar_name
, name_end
- hdr
->ar_name
);
188 else if (hdr
->ar_name
[1] == ' ')
190 // This is the symbol table.
193 else if (hdr
->ar_name
[1] == '/')
195 // This is the extended name table.
196 pname
->assign(1, '/');
201 long x
= strtol(hdr
->ar_name
+ 1, &end
, 10);
204 || (x
== LONG_MAX
&& errno
== ERANGE
)
205 || static_cast<size_t>(x
) >= this->extended_names_
.size())
207 fprintf(stderr
, _("%s: %s: bad extended name index at %ld\n"),
208 program_name
, this->name().c_str(),
209 static_cast<long>(off
));
213 const char* name
= this->extended_names_
.data() + x
;
214 const char* name_end
= strchr(name
, '/');
215 if (static_cast<size_t>(name_end
- name
) > this->extended_names_
.size()
216 || name_end
[1] != '\n')
218 fprintf(stderr
, _("%s: %s: bad extended name entry at header %ld\n"),
219 program_name
, this->name().c_str(),
220 static_cast<long>(off
));
223 pname
->assign(name
, name_end
- name
);
229 // A simple hash code for off_t values.
233 size_t operator()(off_t val
) const
234 { return static_cast<size_t>(val
); }
237 // Select members from the archive and add them to the link. We walk
238 // through the elements in the archive map, and look each one up in
239 // the symbol table. If it exists as a strong undefined symbol, we
240 // pull in the corresponding element. We have to do this in a loop,
241 // since pulling in one element may create new undefined symbols which
242 // may be satisfied by other objects in the archive.
245 Archive::add_symbols(const General_options
& options
, Symbol_table
* symtab
,
246 Layout
* layout
, Input_objects
* input_objects
)
248 if (this->input_file_
->options().include_whole_archive())
249 return this->include_all_members(options
, symtab
, layout
, input_objects
);
251 const size_t armap_size
= this->armap_
.size();
253 // Track which elements in the archive map have already been included
254 // in the link. Elements are identified by their offset.
255 Unordered_set
<off_t
, Seen_hash
> seen
;
256 // This is a quick optimization, since we usually see many symbols
257 // in a row with the same offset. last_seen holds the last offset
258 // we saw that was present in the seen_ set.
259 off_t last_seen
= -1;
261 bool added_new_object
;
264 added_new_object
= false;
265 for (size_t i
= 0; i
< armap_size
; ++i
)
267 if (this->armap_
[i
].offset
== last_seen
)
269 if (seen
.find(this->armap_
[i
].offset
) != seen
.end())
271 last_seen
= this->armap_
[i
].offset
;
275 Symbol
* sym
= symtab
->lookup(this->armap_
[i
].name
);
278 else if (!sym
->is_undefined())
280 seen
.insert(this->armap_
[i
].offset
);
281 last_seen
= this->armap_
[i
].offset
;
284 else if (sym
->binding() == elfcpp::STB_WEAK
)
287 // We want to include this object in the link.
288 last_seen
= this->armap_
[i
].offset
;
289 seen
.insert(last_seen
);
290 this->include_member(options
, symtab
, layout
, input_objects
,
292 added_new_object
= true;
295 while (added_new_object
);
298 // Include all the archive members in the link. This is for --whole-archive.
301 Archive::include_all_members(const General_options
& options
,
302 Symbol_table
* symtab
, Layout
* layout
,
303 Input_objects
* input_objects
)
309 const unsigned char* p
= this->get_view(off
, sizeof(Archive_header
),
311 if (bytes
< sizeof(Archive_header
))
315 fprintf(stderr
, _("%s: %s: short archive header at %ld\n"),
316 program_name
, this->name().c_str(),
317 static_cast<long>(off
));
324 const Archive_header
* hdr
= reinterpret_cast<const Archive_header
*>(p
);
326 off_t size
= this->interpret_header(hdr
, off
, &name
);
331 else if (name
== "/")
333 // Extended name table.
336 this->include_member(options
, symtab
, layout
, input_objects
, off
);
338 off
+= sizeof(Archive_header
) + size
;
344 // Include an archive member in the link. OFF is the file offset of
345 // the member header.
348 Archive::include_member(const General_options
& options
, Symbol_table
* symtab
,
349 Layout
* layout
, Input_objects
* input_objects
,
353 this->read_header(off
, &n
);
355 size_t memoff
= off
+ sizeof(Archive_header
);
357 // Read enough of the file to pick up the entire ELF header.
358 int ehdr_size
= elfcpp::Elf_sizes
<64>::ehdr_size
;
360 const unsigned char* p
= this->input_file_
->file().get_view(memoff
,
365 fprintf(stderr
, _("%s: %s: member at %ld is not an ELF object"),
366 program_name
, this->name().c_str(),
367 static_cast<long>(off
));
371 static unsigned char elfmagic
[4] =
373 elfcpp::ELFMAG0
, elfcpp::ELFMAG1
,
374 elfcpp::ELFMAG2
, elfcpp::ELFMAG3
376 if (memcmp(p
, elfmagic
, 4) != 0)
378 fprintf(stderr
, _("%s: %s: member at %ld is not an ELF object"),
379 program_name
, this->name().c_str(),
380 static_cast<long>(off
));
384 Object
* obj
= make_elf_object((std::string(this->input_file_
->filename())
386 this->input_file_
, memoff
, p
, bytes
);
388 input_objects
->add_object(obj
);
390 Read_symbols_data sd
;
391 obj
->read_symbols(&sd
);
392 obj
->layout(options
, symtab
, layout
, &sd
);
393 obj
->add_symbols(symtab
, &sd
);
396 // Add_archive_symbols methods.
398 Add_archive_symbols::~Add_archive_symbols()
400 if (this->this_blocker_
!= NULL
)
401 delete this->this_blocker_
;
402 // next_blocker_ is deleted by the task associated with the next
406 // Return whether we can add the archive symbols. We are blocked by
407 // this_blocker_. We block next_blocker_. We also lock the file.
409 Task::Is_runnable_type
410 Add_archive_symbols::is_runnable(Workqueue
*)
412 if (this->this_blocker_
!= NULL
&& this->this_blocker_
->is_blocked())
417 class Add_archive_symbols::Add_archive_symbols_locker
: public Task_locker
420 Add_archive_symbols_locker(Task_token
& token
, Workqueue
* workqueue
,
422 : blocker_(token
, workqueue
), filelock_(file
)
426 Task_locker_block blocker_
;
427 Task_locker_obj
<File_read
> filelock_
;
431 Add_archive_symbols::locks(Workqueue
* workqueue
)
433 return new Add_archive_symbols_locker(*this->next_blocker_
,
435 this->archive_
->file());
439 Add_archive_symbols::run(Workqueue
*)
441 this->archive_
->add_symbols(this->options_
, this->symtab_
, this->layout_
,
442 this->input_objects_
);
444 if (this->input_group_
!= NULL
)
445 this->input_group_
->add_archive(this->archive_
);
448 // We no longer need to know about this archive.
449 delete this->archive_
;
453 } // End namespace gold.