1 // reloc.cc -- relocate input files for gold.
13 // Read_relocs methods.
15 // These tasks just read the relocation information from the file.
16 // After reading it, the start another task to process the
17 // information. These tasks requires access to the file.
19 Task::Is_runnable_type
20 Read_relocs::is_runnable(Workqueue
*)
22 return this->object_
->is_locked() ? IS_LOCKED
: IS_RUNNABLE
;
28 Read_relocs::locks(Workqueue
*)
30 return new Task_locker_obj
<Object
>(*this->object_
);
33 // Read the relocations and then start a Scan_relocs_task.
36 Read_relocs::run(Workqueue
* workqueue
)
38 Read_relocs_data
*rd
= new Read_relocs_data
;
39 this->object_
->read_relocs(rd
);
40 workqueue
->queue_front(new Scan_relocs(this->options_
, this->symtab_
,
41 this->object_
, rd
, this->symtab_lock_
,
45 // Scan_relocs methods.
47 // These tasks scan the relocations read by Read_relocs and mark up
48 // the symbol table to indicate which relocations are required. We
49 // use a lock on the symbol table to keep them from interfering with
52 Task::Is_runnable_type
53 Scan_relocs::is_runnable(Workqueue
*)
55 return this->symtab_lock_
->is_writable() ? IS_RUNNABLE
: IS_LOCKED
;
58 // Return the locks we hold: one on the file, one on the symbol table
61 class Scan_relocs::Scan_relocs_locker
: public Task_locker
64 Scan_relocs_locker(Object
* object
, Task_token
& symtab_lock
, Task
* task
,
65 Task_token
& blocker
, Workqueue
* workqueue
)
66 : objlock_(*object
), symtab_locker_(symtab_lock
, task
),
67 blocker_(blocker
, workqueue
)
71 Task_locker_obj
<Object
> objlock_
;
72 Task_locker_write symtab_locker_
;
73 Task_locker_block blocker_
;
77 Scan_relocs::locks(Workqueue
* workqueue
)
79 return new Scan_relocs_locker(this->object_
, *this->symtab_lock_
, this,
80 *this->blocker_
, workqueue
);
86 Scan_relocs::run(Workqueue
*)
88 this->object_
->scan_relocs(this->options_
, this->symtab_
, this->rd_
);
93 // Relocate_task methods.
95 // These tasks are always runnable.
97 Task::Is_runnable_type
98 Relocate_task::is_runnable(Workqueue
*)
103 // We want to lock the file while we run. We want to unblock
104 // FINAL_BLOCKER when we are done.
106 class Relocate_task::Relocate_locker
: public Task_locker
109 Relocate_locker(Task_token
& token
, Workqueue
* workqueue
,
111 : blocker_(token
, workqueue
), objlock_(*object
)
115 Task_locker_block blocker_
;
116 Task_locker_obj
<Object
> objlock_
;
120 Relocate_task::locks(Workqueue
* workqueue
)
122 return new Relocate_locker(*this->final_blocker_
, workqueue
,
129 Relocate_task::run(Workqueue
*)
131 this->object_
->relocate(this->options_
, this->symtab_
, this->layout_
,
135 // Read the relocs and local symbols from the object file and store
136 // the information in RD.
138 template<int size
, bool big_endian
>
140 Sized_object
<size
, big_endian
>::do_read_relocs(Read_relocs_data
* rd
)
144 unsigned int shnum
= this->shnum();
148 rd
->relocs
.reserve(shnum
/ 2);
150 const unsigned char *pshdrs
= this->get_view(this->shoff_
,
151 shnum
* This::shdr_size
);
152 // Skip the first, dummy, section.
153 const unsigned char *ps
= pshdrs
+ This::shdr_size
;
154 for (unsigned int i
= 1; i
< shnum
; ++i
, ps
+= This::shdr_size
)
156 typename
This::Shdr
shdr(ps
);
158 unsigned int sh_type
= shdr
.get_sh_type();
159 if (sh_type
!= elfcpp::SHT_REL
&& sh_type
!= elfcpp::SHT_RELA
)
162 unsigned int shndx
= shdr
.get_sh_info();
165 fprintf(stderr
, _("%s: %s: relocation section %u has bad info %u\n"),
166 program_name
, this->name().c_str(), i
, shndx
);
170 if (!this->is_section_included(shndx
))
173 if (shdr
.get_sh_link() != this->symtab_shnum_
)
176 _("%s: %s: relocation section %u uses unexpected "
177 "symbol table %u\n"),
178 program_name
, this->name().c_str(), i
, shdr
.get_sh_link());
182 off_t sh_size
= shdr
.get_sh_size();
184 unsigned int reloc_size
;
185 if (sh_type
== elfcpp::SHT_REL
)
186 reloc_size
= elfcpp::Elf_sizes
<size
>::rel_size
;
188 reloc_size
= elfcpp::Elf_sizes
<size
>::rela_size
;
189 if (reloc_size
!= shdr
.get_sh_entsize())
192 _("%s: %s: unexpected entsize for reloc section %u: "
194 program_name
, this->name().c_str(), i
,
195 static_cast<unsigned long>(shdr
.get_sh_entsize()),
200 size_t reloc_count
= sh_size
/ reloc_size
;
201 if (reloc_count
* reloc_size
!= sh_size
)
203 fprintf(stderr
, _("%s: %s: reloc section %u size %lu uneven"),
204 program_name
, this->name().c_str(), i
,
205 static_cast<unsigned long>(sh_size
));
209 rd
->relocs
.push_back(Section_relocs());
210 Section_relocs
& sr(rd
->relocs
.back());
212 sr
.data_shndx
= shndx
;
213 sr
.contents
= this->get_lasting_view(shdr
.get_sh_offset(), sh_size
);
214 sr
.sh_type
= sh_type
;
215 sr
.reloc_count
= reloc_count
;
218 // Read the local symbols.
219 if (this->symtab_shnum_
== 0 || this->local_symbol_count_
== 0)
220 rd
->local_symbols
= NULL
;
223 typename
This::Shdr
symtabshdr(pshdrs
224 + this->symtab_shnum_
* This::shdr_size
);
225 assert(symtabshdr
.get_sh_type() == elfcpp::SHT_SYMTAB
);
226 const int sym_size
= This::sym_size
;
227 const unsigned int loccount
= this->local_symbol_count_
;
228 assert(loccount
== symtabshdr
.get_sh_info());
229 off_t locsize
= loccount
* sym_size
;
230 rd
->local_symbols
= this->get_lasting_view(symtabshdr
.get_sh_offset(),
235 // Scan the relocs and adjust the symbol table. This looks for
236 // relocations which require GOT/PLT/COPY relocations.
238 template<int size
, bool big_endian
>
240 Sized_object
<size
, big_endian
>::do_scan_relocs(const General_options
& options
,
241 Symbol_table
* symtab
,
242 Read_relocs_data
* rd
)
244 Sized_target
<size
, big_endian
>* target
= this->sized_target();
246 const unsigned char* local_symbols
;
247 if (rd
->local_symbols
== NULL
)
248 local_symbols
= NULL
;
250 local_symbols
= rd
->local_symbols
->data();
252 for (Read_relocs_data::Relocs_list::iterator p
= rd
->relocs
.begin();
253 p
!= rd
->relocs
.end();
256 target
->scan_relocs(options
, symtab
, this, p
->sh_type
,
257 p
->contents
->data(), p
->reloc_count
,
258 this->local_symbol_count_
,
265 if (rd
->local_symbols
!= NULL
)
267 delete rd
->local_symbols
;
268 rd
->local_symbols
= NULL
;
272 // Relocate the input sections and write out the local symbols.
274 template<int size
, bool big_endian
>
276 Sized_object
<size
, big_endian
>::do_relocate(const General_options
& options
,
277 const Symbol_table
* symtab
,
278 const Layout
* layout
,
281 unsigned int shnum
= this->shnum();
283 // Read the section headers.
284 const unsigned char* pshdrs
= this->get_view(this->shoff_
,
285 shnum
* This::shdr_size
);
290 // Make two passes over the sections. The first one copies the
291 // section data to the output file. The second one applies
294 this->write_sections(pshdrs
, of
, &views
);
296 // Apply relocations.
298 this->relocate_sections(options
, symtab
, layout
, pshdrs
, &views
);
300 // Write out the accumulated views.
301 for (unsigned int i
= 1; i
< shnum
; ++i
)
303 if (views
[i
].view
!= NULL
)
304 of
->write_output_view(views
[i
].offset
, views
[i
].view_size
,
308 // Write out the local symbols.
309 this->write_local_symbols(of
, layout
->sympool());
312 // Write section data to the output file. PSHDRS points to the
313 // section headers. Record the views in *PVIEWS for use when
316 template<int size
, bool big_endian
>
318 Sized_object
<size
, big_endian
>::write_sections(const unsigned char* pshdrs
,
322 unsigned int shnum
= this->shnum();
323 std::vector
<Map_to_output
>& map_sections(this->map_to_output());
325 const unsigned char* p
= pshdrs
+ This::shdr_size
;
326 for (unsigned int i
= 1; i
< shnum
; ++i
, p
+= This::shdr_size
)
328 View_size
* pvs
= &(*pviews
)[i
];
332 const Output_section
* os
= map_sections
[i
].output_section
;
336 typename
This::Shdr
shdr(p
);
338 if (shdr
.get_sh_type() == elfcpp::SHT_NOBITS
)
341 assert(map_sections
[i
].offset
>= 0
342 && map_sections
[i
].offset
< os
->data_size());
343 off_t start
= os
->offset() + map_sections
[i
].offset
;
344 off_t sh_size
= shdr
.get_sh_size();
346 unsigned char* view
= of
->get_output_view(start
, sh_size
);
347 this->read(shdr
.get_sh_offset(), sh_size
, view
);
350 pvs
->address
= os
->address() + map_sections
[i
].offset
;
352 pvs
->view_size
= sh_size
;
356 // Relocate section data. VIEWS points to the section data as views
357 // in the output file.
359 template<int size
, bool big_endian
>
361 Sized_object
<size
, big_endian
>::relocate_sections(
362 const General_options
& options
,
363 const Symbol_table
* symtab
,
364 const Layout
* layout
,
365 const unsigned char* pshdrs
,
368 unsigned int shnum
= this->shnum();
369 Sized_target
<size
, big_endian
>* target
= this->sized_target();
371 Relocate_info
<size
, big_endian
> relinfo
;
372 relinfo
.options
= &options
;
373 relinfo
.symtab
= symtab
;
374 relinfo
.layout
= layout
;
375 relinfo
.object
= this;
376 relinfo
.local_symbol_count
= this->local_symbol_count_
;
377 relinfo
.values
= this->values_
;
378 relinfo
.symbols
= this->symbols_
;
380 const unsigned char* p
= pshdrs
+ This::shdr_size
;
381 for (unsigned int i
= 1; i
< shnum
; ++i
, p
+= This::shdr_size
)
383 typename
This::Shdr
shdr(p
);
385 unsigned int sh_type
= shdr
.get_sh_type();
386 if (sh_type
!= elfcpp::SHT_REL
&& sh_type
!= elfcpp::SHT_RELA
)
389 unsigned int index
= shdr
.get_sh_info();
390 if (index
>= this->shnum())
392 fprintf(stderr
, _("%s: %s: relocation section %u has bad info %u\n"),
393 program_name
, this->name().c_str(), i
, index
);
397 if (!this->is_section_included(index
))
399 // This relocation section is against a section which we
404 assert((*pviews
)[index
].view
!= NULL
);
406 if (shdr
.get_sh_link() != this->symtab_shnum_
)
409 _("%s: %s: relocation section %u uses unexpected "
410 "symbol table %u\n"),
411 program_name
, this->name().c_str(), i
, shdr
.get_sh_link());
415 off_t sh_size
= shdr
.get_sh_size();
416 const unsigned char* prelocs
= this->get_view(shdr
.get_sh_offset(),
419 unsigned int reloc_size
;
420 if (sh_type
== elfcpp::SHT_REL
)
421 reloc_size
= elfcpp::Elf_sizes
<size
>::rel_size
;
423 reloc_size
= elfcpp::Elf_sizes
<size
>::rela_size
;
425 if (reloc_size
!= shdr
.get_sh_entsize())
428 _("%s: %s: unexpected entsize for reloc section %u: "
430 program_name
, this->name().c_str(), i
,
431 static_cast<unsigned long>(shdr
.get_sh_entsize()),
436 size_t reloc_count
= sh_size
/ reloc_size
;
437 if (reloc_count
* reloc_size
!= sh_size
)
439 fprintf(stderr
, _("%s: %s: reloc section %u size %lu uneven"),
440 program_name
, this->name().c_str(), i
,
441 static_cast<unsigned long>(sh_size
));
445 relinfo
.reloc_shndx
= i
;
446 relinfo
.data_shndx
= index
;
447 target
->relocate_section(&relinfo
,
451 (*pviews
)[index
].view
,
452 (*pviews
)[index
].address
,
453 (*pviews
)[index
].view_size
);
457 // Instantiate the templates we need. We could use the configure
458 // script to restrict this to only the ones for implemented targets.
462 Sized_object
<32, false>::do_read_relocs(Read_relocs_data
* rd
);
466 Sized_object
<32, true>::do_read_relocs(Read_relocs_data
* rd
);
470 Sized_object
<64, false>::do_read_relocs(Read_relocs_data
* rd
);
474 Sized_object
<64, true>::do_read_relocs(Read_relocs_data
* rd
);
478 Sized_object
<32, false>::do_scan_relocs(const General_options
& options
,
479 Symbol_table
* symtab
,
480 Read_relocs_data
* rd
);
484 Sized_object
<32, true>::do_scan_relocs(const General_options
& options
,
485 Symbol_table
* symtab
,
486 Read_relocs_data
* rd
);
490 Sized_object
<64, false>::do_scan_relocs(const General_options
& options
,
491 Symbol_table
* symtab
,
492 Read_relocs_data
* rd
);
496 Sized_object
<64, true>::do_scan_relocs(const General_options
& options
,
497 Symbol_table
* symtab
,
498 Read_relocs_data
* rd
);
502 Sized_object
<32, false>::do_relocate(const General_options
& options
,
503 const Symbol_table
* symtab
,
504 const Layout
* layout
,
509 Sized_object
<32, true>::do_relocate(const General_options
& options
,
510 const Symbol_table
* symtab
,
511 const Layout
* layout
,
516 Sized_object
<64, false>::do_relocate(const General_options
& options
,
517 const Symbol_table
* symtab
,
518 const Layout
* layout
,
523 Sized_object
<64, true>::do_relocate(const General_options
& options
,
524 const Symbol_table
* symtab
,
525 const Layout
* layout
,
529 } // End namespace gold.