Commit | Line | Data |
---|---|---|
bae7f79e ILT |
1 | // object.cc -- support for an object file for linking in gold |
2 | ||
3 | #include "gold.h" | |
4 | ||
5 | #include <cerrno> | |
6 | #include <cstring> | |
7 | #include <cassert> | |
8 | ||
9 | #include "object.h" | |
14bfc3f5 | 10 | #include "target-select.h" |
a2fb1b05 | 11 | #include "layout.h" |
61ba1cf9 | 12 | #include "output.h" |
bae7f79e ILT |
13 | |
14 | namespace gold | |
15 | { | |
16 | ||
17 | // Class Object. | |
18 | ||
19 | const unsigned char* | |
20 | Object::get_view(off_t start, off_t size) | |
21 | { | |
22 | return this->input_file_->file().get_view(start + this->offset_, size); | |
23 | } | |
24 | ||
25 | void | |
26 | Object::read(off_t start, off_t size, void* p) | |
27 | { | |
28 | this->input_file_->file().read(start + this->offset_, size, p); | |
29 | } | |
30 | ||
31 | File_view* | |
32 | Object::get_lasting_view(off_t start, off_t size) | |
33 | { | |
34 | return this->input_file_->file().get_lasting_view(start + this->offset_, | |
35 | size); | |
36 | } | |
37 | ||
38 | // Class Sized_object. | |
39 | ||
40 | template<int size, bool big_endian> | |
41 | Sized_object<size, big_endian>::Sized_object( | |
42 | const std::string& name, | |
43 | Input_file* input_file, | |
44 | off_t offset, | |
45 | const elfcpp::Ehdr<size, big_endian>& ehdr) | |
14bfc3f5 | 46 | : Object(name, input_file, false, offset), |
12e14209 | 47 | section_headers_(NULL), |
bae7f79e | 48 | flags_(ehdr.get_e_flags()), |
bae7f79e | 49 | shoff_(ehdr.get_e_shoff()), |
bae7f79e | 50 | shstrndx_(0), |
14bfc3f5 | 51 | symtab_shnum_(0), |
61ba1cf9 ILT |
52 | local_symbol_count_(0), |
53 | output_local_symbol_count_(0), | |
75f65a3e | 54 | symbols_(NULL), |
61ba1cf9 ILT |
55 | local_symbol_offset_(0), |
56 | values_(NULL) | |
bae7f79e | 57 | { |
a2fb1b05 | 58 | if (ehdr.get_e_ehsize() != This::ehdr_size) |
bae7f79e ILT |
59 | { |
60 | fprintf(stderr, _("%s: %s: bad e_ehsize field (%d != %d)\n"), | |
61 | program_name, this->name().c_str(), ehdr.get_e_ehsize(), | |
a2fb1b05 | 62 | This::ehdr_size); |
bae7f79e ILT |
63 | gold_exit(false); |
64 | } | |
a2fb1b05 | 65 | if (ehdr.get_e_shentsize() != This::shdr_size) |
bae7f79e ILT |
66 | { |
67 | fprintf(stderr, _("%s: %s: bad e_shentsize field (%d != %d)\n"), | |
68 | program_name, this->name().c_str(), ehdr.get_e_shentsize(), | |
a2fb1b05 | 69 | This::shdr_size); |
bae7f79e ILT |
70 | gold_exit(false); |
71 | } | |
72 | } | |
73 | ||
74 | template<int size, bool big_endian> | |
75 | Sized_object<size, big_endian>::~Sized_object() | |
76 | { | |
77 | } | |
78 | ||
75f65a3e ILT |
79 | // Read the section header for section SHNUM. |
80 | ||
81 | template<int size, bool big_endian> | |
82 | const unsigned char* | |
83 | Sized_object<size, big_endian>::section_header(unsigned int shnum) | |
84 | { | |
61ba1cf9 | 85 | assert(shnum < this->shnum()); |
75f65a3e ILT |
86 | off_t symtabshdroff = this->shoff_ + shnum * This::shdr_size; |
87 | return this->get_view(symtabshdroff, This::shdr_size); | |
88 | } | |
89 | ||
bae7f79e ILT |
90 | // Set up an object file bsaed on the file header. This sets up the |
91 | // target and reads the section information. | |
92 | ||
93 | template<int size, bool big_endian> | |
94 | void | |
95 | Sized_object<size, big_endian>::setup( | |
96 | const elfcpp::Ehdr<size, big_endian>& ehdr) | |
97 | { | |
a2fb1b05 ILT |
98 | int machine = ehdr.get_e_machine(); |
99 | Target* target = select_target(machine, size, big_endian, | |
100 | ehdr.get_e_ident()[elfcpp::EI_OSABI], | |
101 | ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]); | |
14bfc3f5 ILT |
102 | if (target == NULL) |
103 | { | |
104 | fprintf(stderr, _("%s: %s: unsupported ELF machine number %d\n"), | |
a2fb1b05 | 105 | program_name, this->name().c_str(), machine); |
14bfc3f5 ILT |
106 | gold_exit(false); |
107 | } | |
108 | this->set_target(target); | |
12e14209 | 109 | |
bae7f79e ILT |
110 | unsigned int shnum = ehdr.get_e_shnum(); |
111 | unsigned int shstrndx = ehdr.get_e_shstrndx(); | |
112 | if ((shnum == 0 || shstrndx == elfcpp::SHN_XINDEX) | |
113 | && this->shoff_ != 0) | |
114 | { | |
75f65a3e | 115 | typename This::Shdr shdr(this->section_header(0)); |
bae7f79e ILT |
116 | if (shnum == 0) |
117 | shnum = shdr.get_sh_size(); | |
118 | if (shstrndx == elfcpp::SHN_XINDEX) | |
119 | shstrndx = shdr.get_sh_link(); | |
120 | } | |
a2fb1b05 | 121 | this->set_shnum(shnum); |
bae7f79e ILT |
122 | this->shstrndx_ = shstrndx; |
123 | ||
124 | if (shnum == 0) | |
125 | return; | |
126 | ||
12e14209 ILT |
127 | // We store the section headers in a File_view until do_read_symbols. |
128 | this->section_headers_ = this->get_lasting_view(this->shoff_, | |
129 | shnum * This::shdr_size); | |
130 | ||
131 | // Find the SHT_SYMTAB section. The ELF standard says that maybe in | |
132 | // the future there can be more than one SHT_SYMTAB section. Until | |
133 | // somebody figures out how that could work, we assume there is only | |
134 | // one. | |
135 | const unsigned char* p = this->section_headers_->data(); | |
136 | ||
bae7f79e | 137 | // Skip the first section, which is always empty. |
a2fb1b05 | 138 | p += This::shdr_size; |
12e14209 | 139 | for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size) |
bae7f79e | 140 | { |
75f65a3e | 141 | typename This::Shdr shdr(p); |
bae7f79e ILT |
142 | if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB) |
143 | { | |
144 | this->symtab_shnum_ = i; | |
145 | break; | |
146 | } | |
bae7f79e ILT |
147 | } |
148 | } | |
149 | ||
12e14209 | 150 | // Read the sections and symbols from an object file. |
bae7f79e ILT |
151 | |
152 | template<int size, bool big_endian> | |
12e14209 ILT |
153 | void |
154 | Sized_object<size, big_endian>::do_read_symbols(Read_symbols_data* sd) | |
bae7f79e | 155 | { |
12e14209 ILT |
156 | // Transfer our view of the section headers to SD. |
157 | sd->section_headers = this->section_headers_; | |
158 | this->section_headers_ = NULL; | |
159 | ||
160 | // Read the section names. | |
161 | const unsigned char* pshdrs = sd->section_headers->data(); | |
162 | const unsigned char* pshdrnames = pshdrs + this->shstrndx_ * This::shdr_size; | |
163 | typename This::Shdr shdrnames(pshdrnames); | |
164 | sd->section_names_size = shdrnames.get_sh_size(); | |
165 | sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(), | |
166 | sd->section_names_size); | |
167 | ||
bae7f79e ILT |
168 | if (this->symtab_shnum_ == 0) |
169 | { | |
170 | // No symbol table. Weird but legal. | |
12e14209 ILT |
171 | sd->symbols = NULL; |
172 | sd->symbols_size = 0; | |
173 | sd->symbol_names = NULL; | |
174 | sd->symbol_names_size = 0; | |
175 | return; | |
bae7f79e ILT |
176 | } |
177 | ||
12e14209 ILT |
178 | // Get the symbol table section header. |
179 | typename This::Shdr symtabshdr(pshdrs | |
180 | + this->symtab_shnum_ * This::shdr_size); | |
bae7f79e ILT |
181 | assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); |
182 | ||
75f65a3e ILT |
183 | // We only need the external symbols. |
184 | const int sym_size = This::sym_size; | |
185 | off_t locsize = symtabshdr.get_sh_info() * sym_size; | |
186 | off_t extoff = symtabshdr.get_sh_offset() + locsize; | |
187 | off_t extsize = symtabshdr.get_sh_size() - locsize; | |
188 | ||
bae7f79e | 189 | // Read the symbol table. |
75f65a3e | 190 | File_view* fvsymtab = this->get_lasting_view(extoff, extsize); |
bae7f79e ILT |
191 | |
192 | // Read the section header for the symbol names. | |
193 | unsigned int strtab_shnum = symtabshdr.get_sh_link(); | |
a2fb1b05 | 194 | if (strtab_shnum == 0 || strtab_shnum >= this->shnum()) |
bae7f79e ILT |
195 | { |
196 | fprintf(stderr, _("%s: %s: invalid symbol table name index: %u\n"), | |
197 | program_name, this->name().c_str(), strtab_shnum); | |
198 | gold_exit(false); | |
199 | } | |
75f65a3e | 200 | typename This::Shdr strtabshdr(this->section_header(strtab_shnum)); |
bae7f79e ILT |
201 | if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB) |
202 | { | |
203 | fprintf(stderr, | |
204 | _("%s: %s: symbol table name section has wrong type: %u\n"), | |
205 | program_name, this->name().c_str(), | |
206 | static_cast<unsigned int>(strtabshdr.get_sh_type())); | |
207 | gold_exit(false); | |
208 | } | |
209 | ||
210 | // Read the symbol names. | |
211 | File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(), | |
212 | strtabshdr.get_sh_size()); | |
213 | ||
12e14209 ILT |
214 | sd->symbols = fvsymtab; |
215 | sd->symbols_size = extsize; | |
216 | sd->symbol_names = fvstrtab; | |
217 | sd->symbol_names_size = strtabshdr.get_sh_size(); | |
a2fb1b05 ILT |
218 | } |
219 | ||
220 | // Return whether to include a section group in the link. LAYOUT is | |
221 | // used to keep track of which section groups we have already seen. | |
222 | // INDEX is the index of the section group and SHDR is the section | |
223 | // header. If we do not want to include this group, we set bits in | |
224 | // OMIT for each section which should be discarded. | |
225 | ||
226 | template<int size, bool big_endian> | |
227 | bool | |
228 | Sized_object<size, big_endian>::include_section_group( | |
229 | Layout* layout, | |
230 | unsigned int index, | |
231 | const elfcpp::Shdr<size, big_endian>& shdr, | |
232 | std::vector<bool>* omit) | |
233 | { | |
234 | // Read the section contents. | |
235 | const unsigned char* pcon = this->get_view(shdr.get_sh_offset(), | |
236 | shdr.get_sh_size()); | |
237 | const elfcpp::Elf_Word* pword = | |
238 | reinterpret_cast<const elfcpp::Elf_Word*>(pcon); | |
239 | ||
240 | // The first word contains flags. We only care about COMDAT section | |
241 | // groups. Other section groups are always included in the link | |
242 | // just like ordinary sections. | |
243 | elfcpp::Elf_Word flags = elfcpp::read_elf_word<big_endian>(pword); | |
244 | if ((flags & elfcpp::GRP_COMDAT) == 0) | |
245 | return true; | |
246 | ||
247 | // Look up the group signature, which is the name of a symbol. This | |
248 | // is a lot of effort to go to to read a string. Why didn't they | |
249 | // just use the name of the SHT_GROUP section as the group | |
250 | // signature? | |
251 | ||
252 | // Get the appropriate symbol table header (this will normally be | |
253 | // the single SHT_SYMTAB section, but in principle it need not be). | |
254 | if (shdr.get_sh_link() >= this->shnum()) | |
255 | { | |
256 | fprintf(stderr, _("%s: %s: section group %u link %u out of range\n"), | |
257 | program_name, this->name().c_str(), index, shdr.get_sh_link()); | |
258 | gold_exit(false); | |
259 | } | |
75f65a3e ILT |
260 | |
261 | typename This::Shdr symshdr(this->section_header(shdr.get_sh_link())); | |
a2fb1b05 ILT |
262 | |
263 | // Read the symbol table entry. | |
264 | if (shdr.get_sh_info() >= symshdr.get_sh_size() / This::sym_size) | |
265 | { | |
266 | fprintf(stderr, _("%s: %s: section group %u info %u out of range\n"), | |
267 | program_name, this->name().c_str(), index, shdr.get_sh_info()); | |
268 | gold_exit(false); | |
269 | } | |
270 | off_t symoff = symshdr.get_sh_offset() + shdr.get_sh_info() * This::sym_size; | |
271 | const unsigned char* psym = this->get_view(symoff, This::sym_size); | |
272 | elfcpp::Sym<size, big_endian> sym(psym); | |
273 | ||
274 | // Read the section header for the symbol table names. | |
275 | if (symshdr.get_sh_link() >= this->shnum()) | |
276 | { | |
277 | fprintf(stderr, _("%s; %s: symtab section %u link %u out of range\n"), | |
278 | program_name, this->name().c_str(), shdr.get_sh_link(), | |
279 | symshdr.get_sh_link()); | |
280 | gold_exit(false); | |
281 | } | |
75f65a3e ILT |
282 | |
283 | typename This::Shdr symnamehdr(this->section_header(symshdr.get_sh_link())); | |
a2fb1b05 ILT |
284 | |
285 | // Read the symbol table names. | |
286 | const unsigned char *psymnamesu = this->get_view(symnamehdr.get_sh_offset(), | |
287 | symnamehdr.get_sh_size()); | |
288 | const char* psymnames = reinterpret_cast<const char*>(psymnamesu); | |
289 | ||
290 | // Get the section group signature. | |
291 | if (sym.get_st_name() >= symnamehdr.get_sh_size()) | |
292 | { | |
293 | fprintf(stderr, _("%s: %s: symbol %u name offset %u out of range\n"), | |
294 | program_name, this->name().c_str(), shdr.get_sh_info(), | |
295 | sym.get_st_name()); | |
296 | gold_exit(false); | |
297 | } | |
298 | ||
299 | const char* signature = psymnames + sym.get_st_name(); | |
300 | ||
301 | // Record this section group, and see whether we've already seen one | |
302 | // with the same signature. | |
303 | if (layout->add_comdat(signature, true)) | |
304 | return true; | |
305 | ||
306 | // This is a duplicate. We want to discard the sections in this | |
307 | // group. | |
308 | size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word); | |
309 | for (size_t i = 1; i < count; ++i) | |
310 | { | |
311 | elfcpp::Elf_Word secnum = elfcpp::read_elf_word<big_endian>(pword + i); | |
312 | if (secnum >= this->shnum()) | |
313 | { | |
314 | fprintf(stderr, | |
315 | _("%s: %s: section %u in section group %u out of range"), | |
316 | program_name, this->name().c_str(), secnum, | |
317 | index); | |
318 | gold_exit(false); | |
319 | } | |
320 | (*omit)[secnum] = true; | |
321 | } | |
322 | ||
323 | return false; | |
324 | } | |
325 | ||
326 | // Whether to include a linkonce section in the link. NAME is the | |
327 | // name of the section and SHDR is the section header. | |
328 | ||
329 | // Linkonce sections are a GNU extension implemented in the original | |
330 | // GNU linker before section groups were defined. The semantics are | |
331 | // that we only include one linkonce section with a given name. The | |
332 | // name of a linkonce section is normally .gnu.linkonce.T.SYMNAME, | |
333 | // where T is the type of section and SYMNAME is the name of a symbol. | |
334 | // In an attempt to make linkonce sections interact well with section | |
335 | // groups, we try to identify SYMNAME and use it like a section group | |
336 | // signature. We want to block section groups with that signature, | |
337 | // but not other linkonce sections with that signature. We also use | |
338 | // the full name of the linkonce section as a normal section group | |
339 | // signature. | |
340 | ||
341 | template<int size, bool big_endian> | |
342 | bool | |
343 | Sized_object<size, big_endian>::include_linkonce_section( | |
344 | Layout* layout, | |
345 | const char* name, | |
346 | const elfcpp::Shdr<size, big_endian>&) | |
347 | { | |
348 | const char* symname = strrchr(name, '.') + 1; | |
349 | bool omit1 = layout->add_comdat(symname, false); | |
350 | bool omit2 = layout->add_comdat(name, true); | |
351 | return omit1 || omit2; | |
352 | } | |
353 | ||
354 | // Lay out the input sections. We walk through the sections and check | |
355 | // whether they should be included in the link. If they should, we | |
356 | // pass them to the Layout object, which will return an output section | |
357 | // and an offset. | |
358 | ||
359 | template<int size, bool big_endian> | |
360 | void | |
12e14209 ILT |
361 | Sized_object<size, big_endian>::do_layout(Layout* layout, |
362 | Read_symbols_data* sd) | |
a2fb1b05 | 363 | { |
12e14209 ILT |
364 | unsigned int shnum = this->shnum(); |
365 | if (shnum == 0) | |
366 | return; | |
a2fb1b05 ILT |
367 | |
368 | // Get the section headers. | |
12e14209 | 369 | const unsigned char* pshdrs = sd->section_headers->data(); |
a2fb1b05 ILT |
370 | |
371 | // Get the section names. | |
12e14209 | 372 | const unsigned char* pnamesu = sd->section_names->data(); |
a2fb1b05 ILT |
373 | const char* pnames = reinterpret_cast<const char*>(pnamesu); |
374 | ||
375 | std::vector<Map_to_output>& map_sections(this->map_to_output()); | |
61ba1cf9 | 376 | map_sections.resize(shnum); |
a2fb1b05 ILT |
377 | |
378 | // Keep track of which sections to omit. | |
379 | std::vector<bool> omit(shnum, false); | |
380 | ||
12e14209 | 381 | for (unsigned int i = 0; i < shnum; ++i, pshdrs += This::shdr_size) |
a2fb1b05 | 382 | { |
75f65a3e | 383 | typename This::Shdr shdr(pshdrs); |
a2fb1b05 | 384 | |
12e14209 | 385 | if (shdr.get_sh_name() >= sd->section_names_size) |
a2fb1b05 ILT |
386 | { |
387 | fprintf(stderr, | |
388 | _("%s: %s: bad section name offset for section %u: %lu\n"), | |
389 | program_name, this->name().c_str(), i, | |
390 | static_cast<unsigned long>(shdr.get_sh_name())); | |
391 | gold_exit(false); | |
392 | } | |
393 | ||
394 | const char* name = pnames + shdr.get_sh_name(); | |
395 | ||
396 | bool discard = omit[i]; | |
397 | if (!discard) | |
398 | { | |
399 | if (shdr.get_sh_type() == elfcpp::SHT_GROUP) | |
400 | { | |
401 | if (!this->include_section_group(layout, i, shdr, &omit)) | |
402 | discard = true; | |
403 | } | |
404 | else if (Layout::is_linkonce(name)) | |
405 | { | |
406 | if (!this->include_linkonce_section(layout, name, shdr)) | |
407 | discard = true; | |
408 | } | |
409 | } | |
410 | ||
411 | if (discard) | |
412 | { | |
413 | // Do not include this section in the link. | |
414 | map_sections[i].output_section = NULL; | |
415 | continue; | |
416 | } | |
417 | ||
418 | off_t offset; | |
419 | Output_section* os = layout->layout(this, name, shdr, &offset); | |
420 | ||
421 | map_sections[i].output_section = os; | |
422 | map_sections[i].offset = offset; | |
12e14209 ILT |
423 | } |
424 | ||
425 | delete sd->section_headers; | |
426 | sd->section_headers = NULL; | |
427 | delete sd->section_names; | |
428 | sd->section_names = NULL; | |
429 | } | |
430 | ||
431 | // Add the symbols to the symbol table. | |
432 | ||
433 | template<int size, bool big_endian> | |
434 | void | |
435 | Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab, | |
436 | Read_symbols_data* sd) | |
437 | { | |
438 | if (sd->symbols == NULL) | |
439 | { | |
440 | assert(sd->symbol_names == NULL); | |
441 | return; | |
442 | } | |
a2fb1b05 | 443 | |
12e14209 ILT |
444 | const int sym_size = This::sym_size; |
445 | size_t symcount = sd->symbols_size / sym_size; | |
446 | if (symcount * sym_size != sd->symbols_size) | |
447 | { | |
448 | fprintf(stderr, | |
449 | _("%s: %s: size of symbols is not multiple of symbol size\n"), | |
450 | program_name, this->name().c_str()); | |
451 | gold_exit(false); | |
a2fb1b05 | 452 | } |
12e14209 ILT |
453 | |
454 | this->symbols_ = new Symbol*[symcount]; | |
455 | ||
456 | const unsigned char* psyms = sd->symbols->data(); | |
457 | const elfcpp::Sym<size, big_endian>* syms = | |
458 | reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(psyms); | |
459 | const char* sym_names = | |
460 | reinterpret_cast<const char*>(sd->symbol_names->data()); | |
461 | symtab->add_from_object(this, syms, symcount, sym_names, | |
462 | sd->symbol_names_size, this->symbols_); | |
463 | ||
464 | delete sd->symbols; | |
465 | sd->symbols = NULL; | |
466 | delete sd->symbol_names; | |
467 | sd->symbol_names = NULL; | |
bae7f79e ILT |
468 | } |
469 | ||
75f65a3e | 470 | // Finalize the local symbols. Here we record the file offset at |
61ba1cf9 ILT |
471 | // which they should be output, we add their names to *POOL, and we |
472 | // add their values to THIS->VALUES_. Return the new file offset. | |
473 | // This function is always called from the main thread. The actual | |
474 | // output of the local symbols will occur in a separate task. | |
75f65a3e ILT |
475 | |
476 | template<int size, bool big_endian> | |
477 | off_t | |
478 | Sized_object<size, big_endian>::do_finalize_local_symbols(off_t off, | |
479 | Stringpool* pool) | |
480 | { | |
61ba1cf9 ILT |
481 | if (this->symtab_shnum_ == 0) |
482 | { | |
483 | // This object has no symbols. Weird but legal. | |
484 | return off; | |
485 | } | |
486 | ||
487 | off = (off + (size >> 3) - 1) & ~ ((off_t) (size >> 3) - 1); | |
488 | ||
75f65a3e ILT |
489 | this->local_symbol_offset_ = off; |
490 | ||
491 | // Read the symbol table section header. | |
492 | typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_)); | |
493 | assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); | |
494 | ||
495 | // Read the local symbols. | |
496 | unsigned int loccount = symtabshdr.get_sh_info(); | |
497 | const int sym_size = This::sym_size; | |
498 | off_t locsize = loccount * sym_size; | |
499 | const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(), | |
500 | locsize); | |
501 | ||
61ba1cf9 ILT |
502 | this->local_symbol_count_ = loccount; |
503 | ||
504 | this->values_ = new typename elfcpp::Elf_types<size>::Elf_Addr[loccount]; | |
505 | ||
75f65a3e ILT |
506 | // Read the section header for the symbol names. |
507 | typename This::Shdr strtabshdr( | |
508 | this->section_header(symtabshdr.get_sh_link())); | |
509 | assert(strtabshdr.get_sh_type() == elfcpp::SHT_STRTAB); | |
510 | ||
511 | // Read the symbol names. | |
512 | const unsigned char* pnamesu = this->get_view(strtabshdr.get_sh_offset(), | |
513 | strtabshdr.get_sh_size()); | |
514 | const char* pnames = reinterpret_cast<const char*>(pnamesu); | |
515 | ||
516 | // Loop over the local symbols. | |
517 | ||
518 | std::vector<Map_to_output>& mo(this->map_to_output()); | |
519 | unsigned int shnum = this->shnum(); | |
61ba1cf9 | 520 | unsigned int count = 0; |
75f65a3e ILT |
521 | // Skip the first, dummy, symbol. |
522 | psyms += sym_size; | |
61ba1cf9 | 523 | for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) |
75f65a3e ILT |
524 | { |
525 | elfcpp::Sym<size, big_endian> sym(psyms); | |
526 | ||
527 | unsigned int shndx = sym.get_st_shndx(); | |
528 | ||
529 | if (shndx >= elfcpp::SHN_LORESERVE) | |
530 | { | |
61ba1cf9 ILT |
531 | if (shndx == elfcpp::SHN_ABS) |
532 | this->values_[i] = sym.get_st_value(); | |
533 | else | |
75f65a3e | 534 | { |
61ba1cf9 | 535 | // FIXME: Handle SHN_XINDEX. |
75f65a3e ILT |
536 | fprintf(stderr, |
537 | _("%s: %s: unknown section index %u " | |
538 | "for local symbol %u\n"), | |
539 | program_name, this->name().c_str(), shndx, i); | |
540 | gold_exit(false); | |
541 | } | |
75f65a3e ILT |
542 | } |
543 | else | |
544 | { | |
545 | if (shndx >= shnum) | |
546 | { | |
547 | fprintf(stderr, | |
548 | _("%s: %s: local symbol %u section index %u " | |
549 | "out of range\n"), | |
550 | program_name, this->name().c_str(), i, shndx); | |
551 | gold_exit(false); | |
552 | } | |
553 | ||
554 | if (mo[shndx].output_section == NULL) | |
61ba1cf9 ILT |
555 | { |
556 | this->values_[i] = 0; | |
557 | continue; | |
558 | } | |
559 | ||
560 | this->values_[i] = (mo[shndx].output_section->address() | |
561 | + sym.get_st_value()); | |
75f65a3e ILT |
562 | } |
563 | ||
564 | pool->add(pnames + sym.get_st_name()); | |
565 | off += sym_size; | |
61ba1cf9 | 566 | ++count; |
75f65a3e ILT |
567 | } |
568 | ||
61ba1cf9 ILT |
569 | this->output_local_symbol_count_ = count; |
570 | ||
75f65a3e ILT |
571 | return off; |
572 | } | |
573 | ||
61ba1cf9 ILT |
574 | // Write out the local symbols. |
575 | ||
576 | template<int size, bool big_endian> | |
577 | void | |
578 | Sized_object<size, big_endian>::write_local_symbols(Output_file* of, | |
579 | const Stringpool* sympool) | |
580 | { | |
581 | if (this->symtab_shnum_ == 0) | |
582 | { | |
583 | // This object has no symbols. Weird but legal. | |
584 | return; | |
585 | } | |
586 | ||
587 | // Read the symbol table section header. | |
588 | typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_)); | |
589 | assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); | |
590 | unsigned int local_symbol_count = this->local_symbol_count_; | |
591 | assert(local_symbol_count == symtabshdr.get_sh_info()); | |
592 | ||
593 | // Read the local symbols. | |
594 | const int sym_size = This::sym_size; | |
595 | off_t locsize = local_symbol_count * sym_size; | |
596 | const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(), | |
597 | locsize); | |
598 | ||
599 | // Read the section header for the symbol names. | |
600 | typename This::Shdr strtabshdr( | |
601 | this->section_header(symtabshdr.get_sh_link())); | |
602 | assert(strtabshdr.get_sh_type() == elfcpp::SHT_STRTAB); | |
603 | ||
604 | // Read the symbol names. | |
605 | const unsigned char* pnamesu = this->get_view(strtabshdr.get_sh_offset(), | |
606 | strtabshdr.get_sh_size()); | |
607 | const char* pnames = reinterpret_cast<const char*>(pnamesu); | |
608 | ||
609 | // Get a view into the output file. | |
610 | off_t output_size = this->output_local_symbol_count_ * sym_size; | |
611 | unsigned char* oview = of->get_output_view(this->local_symbol_offset_, | |
612 | output_size); | |
613 | ||
614 | std::vector<Map_to_output>& mo(this->map_to_output()); | |
615 | ||
616 | psyms += sym_size; | |
617 | unsigned char* ov = oview; | |
618 | for (unsigned int i = 1; i < local_symbol_count; ++i, psyms += sym_size) | |
619 | { | |
620 | elfcpp::Sym<size, big_endian> isym(psyms); | |
621 | elfcpp::Sym_write<size, big_endian> osym(ov); | |
622 | ||
623 | unsigned int st_shndx = isym.get_st_shndx(); | |
624 | if (st_shndx < elfcpp::SHN_LORESERVE) | |
625 | { | |
626 | assert(st_shndx < mo.size()); | |
627 | if (mo[st_shndx].output_section == NULL) | |
628 | continue; | |
629 | st_shndx = mo[st_shndx].output_section->shndx(); | |
630 | } | |
631 | ||
632 | osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name())); | |
633 | osym.put_st_value(this->values_[i]); | |
634 | osym.put_st_size(isym.get_st_size()); | |
635 | osym.put_st_info(isym.get_st_info()); | |
636 | osym.put_st_other(isym.get_st_other()); | |
637 | osym.put_st_shndx(st_shndx); | |
638 | ||
639 | ov += sym_size; | |
640 | } | |
641 | ||
642 | assert(ov - oview == output_size); | |
643 | ||
644 | of->write_output_view(this->local_symbol_offset_, output_size, oview); | |
645 | } | |
646 | ||
54dc6425 ILT |
647 | // Input_objects methods. |
648 | ||
649 | void | |
650 | Input_objects::add_object(Object* obj) | |
651 | { | |
652 | this->object_list_.push_back(obj); | |
75f65a3e ILT |
653 | |
654 | Target* target = obj->target(); | |
655 | if (this->target_ == NULL) | |
656 | this->target_ = target; | |
657 | else if (this->target_ != target) | |
658 | { | |
659 | fprintf(stderr, "%s: %s: incompatible target\n", | |
660 | program_name, obj->name().c_str()); | |
661 | gold_exit(false); | |
662 | } | |
663 | ||
54dc6425 ILT |
664 | if (obj->is_dynamic()) |
665 | this->any_dynamic_ = true; | |
666 | } | |
667 | ||
bae7f79e ILT |
668 | } // End namespace gold. |
669 | ||
670 | namespace | |
671 | { | |
672 | ||
673 | using namespace gold; | |
674 | ||
675 | // Read an ELF file with the header and return the appropriate | |
676 | // instance of Object. | |
677 | ||
678 | template<int size, bool big_endian> | |
679 | Object* | |
680 | make_elf_sized_object(const std::string& name, Input_file* input_file, | |
681 | off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr) | |
682 | { | |
683 | int et = ehdr.get_e_type(); | |
684 | if (et != elfcpp::ET_REL && et != elfcpp::ET_DYN) | |
685 | { | |
686 | fprintf(stderr, "%s: %s: unsupported ELF type %d\n", | |
687 | program_name, name.c_str(), static_cast<int>(et)); | |
688 | gold_exit(false); | |
689 | } | |
690 | ||
691 | if (et == elfcpp::ET_REL) | |
692 | { | |
693 | Sized_object<size, big_endian>* obj = | |
694 | new Sized_object<size, big_endian>(name, input_file, offset, ehdr); | |
695 | obj->setup(ehdr); | |
696 | return obj; | |
697 | } | |
698 | else | |
699 | { | |
700 | // elfcpp::ET_DYN | |
701 | fprintf(stderr, _("%s: %s: dynamic objects are not yet supported\n"), | |
702 | program_name, name.c_str()); | |
703 | gold_exit(false); | |
704 | // Sized_dynobj<size, big_endian>* obj = | |
705 | // new Sized_dynobj<size, big_endian>(this->input_.name(), input_file, | |
706 | // offset, ehdr); | |
707 | // obj->setup(ehdr); | |
708 | // return obj; | |
709 | } | |
710 | } | |
711 | ||
712 | } // End anonymous namespace. | |
713 | ||
714 | namespace gold | |
715 | { | |
716 | ||
717 | // Read an ELF file and return the appropriate instance of Object. | |
718 | ||
719 | Object* | |
720 | make_elf_object(const std::string& name, Input_file* input_file, off_t offset, | |
721 | const unsigned char* p, off_t bytes) | |
722 | { | |
723 | if (bytes < elfcpp::EI_NIDENT) | |
724 | { | |
725 | fprintf(stderr, _("%s: %s: ELF file too short\n"), | |
726 | program_name, name.c_str()); | |
727 | gold_exit(false); | |
728 | } | |
729 | ||
730 | int v = p[elfcpp::EI_VERSION]; | |
731 | if (v != elfcpp::EV_CURRENT) | |
732 | { | |
733 | if (v == elfcpp::EV_NONE) | |
734 | fprintf(stderr, _("%s: %s: invalid ELF version 0\n"), | |
735 | program_name, name.c_str()); | |
736 | else | |
737 | fprintf(stderr, _("%s: %s: unsupported ELF version %d\n"), | |
738 | program_name, name.c_str(), v); | |
739 | gold_exit(false); | |
740 | } | |
741 | ||
742 | int c = p[elfcpp::EI_CLASS]; | |
743 | if (c == elfcpp::ELFCLASSNONE) | |
744 | { | |
745 | fprintf(stderr, _("%s: %s: invalid ELF class 0\n"), | |
746 | program_name, name.c_str()); | |
747 | gold_exit(false); | |
748 | } | |
749 | else if (c != elfcpp::ELFCLASS32 | |
750 | && c != elfcpp::ELFCLASS64) | |
751 | { | |
752 | fprintf(stderr, _("%s: %s: unsupported ELF class %d\n"), | |
753 | program_name, name.c_str(), c); | |
754 | gold_exit(false); | |
755 | } | |
756 | ||
757 | int d = p[elfcpp::EI_DATA]; | |
758 | if (d == elfcpp::ELFDATANONE) | |
759 | { | |
760 | fprintf(stderr, _("%s: %s: invalid ELF data encoding\n"), | |
761 | program_name, name.c_str()); | |
762 | gold_exit(false); | |
763 | } | |
764 | else if (d != elfcpp::ELFDATA2LSB | |
765 | && d != elfcpp::ELFDATA2MSB) | |
766 | { | |
767 | fprintf(stderr, _("%s: %s: unsupported ELF data encoding %d\n"), | |
768 | program_name, name.c_str(), d); | |
769 | gold_exit(false); | |
770 | } | |
771 | ||
772 | bool big_endian = d == elfcpp::ELFDATA2MSB; | |
773 | ||
774 | if (c == elfcpp::ELFCLASS32) | |
775 | { | |
776 | if (bytes < elfcpp::Elf_sizes<32>::ehdr_size) | |
777 | { | |
778 | fprintf(stderr, _("%s: %s: ELF file too short\n"), | |
779 | program_name, name.c_str()); | |
780 | gold_exit(false); | |
781 | } | |
782 | if (big_endian) | |
783 | { | |
784 | elfcpp::Ehdr<32, true> ehdr(p); | |
785 | return make_elf_sized_object<32, true>(name, input_file, | |
786 | offset, ehdr); | |
787 | } | |
788 | else | |
789 | { | |
790 | elfcpp::Ehdr<32, false> ehdr(p); | |
791 | return make_elf_sized_object<32, false>(name, input_file, | |
792 | offset, ehdr); | |
793 | } | |
794 | } | |
795 | else | |
796 | { | |
797 | if (bytes < elfcpp::Elf_sizes<32>::ehdr_size) | |
798 | { | |
799 | fprintf(stderr, _("%s: %s: ELF file too short\n"), | |
800 | program_name, name.c_str()); | |
801 | gold_exit(false); | |
802 | } | |
803 | if (big_endian) | |
804 | { | |
805 | elfcpp::Ehdr<64, true> ehdr(p); | |
806 | return make_elf_sized_object<64, true>(name, input_file, | |
807 | offset, ehdr); | |
808 | } | |
809 | else | |
810 | { | |
811 | elfcpp::Ehdr<64, false> ehdr(p); | |
812 | return make_elf_sized_object<64, false>(name, input_file, | |
813 | offset, ehdr); | |
814 | } | |
815 | } | |
816 | } | |
817 | ||
818 | // Instantiate the templates we need. We could use the configure | |
819 | // script to restrict this to only the ones for implemented targets. | |
820 | ||
821 | template | |
822 | class Sized_object<32, false>; | |
823 | ||
824 | template | |
825 | class Sized_object<32, true>; | |
826 | ||
827 | template | |
828 | class Sized_object<64, false>; | |
829 | ||
830 | template | |
831 | class Sized_object<64, true>; | |
832 | ||
833 | } // End namespace gold. |