2009-05-28 Doug Kwan <dougkwan@google.com>
[deliverable/binutils-gdb.git] / gold / arm.cc
CommitLineData
4a657b0d
DK
1// arm.cc -- arm target support for gold.
2
3// Copyright 2009 Free Software Foundation, Inc.
4// Written by Doug Kwan <dougkwan@google.com> based on the i386 code
5// by Ian Lance Taylor <iant@google.com>.
6
7// This file is part of gold.
8
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 3 of the License, or
12// (at your option) any later version.
13
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18
19// You should have received a copy of the GNU General Public License
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22// MA 02110-1301, USA.
23
24#include "gold.h"
25
26#include <cstring>
27#include <limits>
28#include <cstdio>
29#include <string>
30
31#include "elfcpp.h"
32#include "parameters.h"
33#include "reloc.h"
34#include "arm.h"
35#include "object.h"
36#include "symtab.h"
37#include "layout.h"
38#include "output.h"
39#include "copy-relocs.h"
40#include "target.h"
41#include "target-reloc.h"
42#include "target-select.h"
43#include "tls.h"
44#include "defstd.h"
45
46namespace
47{
48
49using namespace gold;
50
51// The arm target class.
52//
53// This is a very simple port of gold for ARM-EABI. It is intended for
54// supporting Android only for the time being. Only these relocation types
55// are supported.
56//
57// R_ARM_NONE
58// R_ARM_ABS32
59// R_ARM_REL32
60// R_ARM_THM_CALL
61// R_ARM_COPY
62// R_ARM_GLOB_DAT
63// R_ARM_BASE_PREL
64// R_ARM_JUMP_SLOT
65// R_ARM_RELATIVE
66// R_ARM_GOTOFF32
67// R_ARM_GOT_BREL
68// R_ARM_PLT32
69// R_ARM_CALL
70// R_ARM_JUMP24
71// R_ARM_TARGET1
72// R_ARM_PREL31
73//
74// Coming soon (pending patches):
75// - Support for dynamic symbols (GOT, PLT and etc).
76// - Local scanner
77// - Global scanner
78// - Relocation
79// - Defining section symbols __exidx_start and __exidx_stop.
80// - Support interworking.
81// - Mergeing all .ARM.xxx.yyy sections into .ARM.xxx. Currently, they
82// are incorrectly merged into an .ARM section.
83//
84// TODOs:
85// - Create a PT_ARM_EXIDX program header for a shared object that
86// might throw an exception.
87// - Support more relocation types as needed.
88
89template<bool big_endian>
90class Target_arm : public Sized_target<32, big_endian>
91{
92 public:
93 typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian>
94 Reloc_section;
95
96 Target_arm()
97 : Sized_target<32, big_endian>(&arm_info)
98 { }
99
100 // Process the relocations to determine unreferenced sections for
101 // garbage collection.
102 void
103 gc_process_relocs(const General_options& options,
104 Symbol_table* symtab,
105 Layout* layout,
106 Sized_relobj<32, big_endian>* object,
107 unsigned int data_shndx,
108 unsigned int sh_type,
109 const unsigned char* prelocs,
110 size_t reloc_count,
111 Output_section* output_section,
112 bool needs_special_offset_handling,
113 size_t local_symbol_count,
114 const unsigned char* plocal_symbols);
115
116 // Scan the relocations to look for symbol adjustments.
117 void
118 scan_relocs(const General_options& options,
119 Symbol_table* symtab,
120 Layout* layout,
121 Sized_relobj<32, big_endian>* object,
122 unsigned int data_shndx,
123 unsigned int sh_type,
124 const unsigned char* prelocs,
125 size_t reloc_count,
126 Output_section* output_section,
127 bool needs_special_offset_handling,
128 size_t local_symbol_count,
129 const unsigned char* plocal_symbols);
130
131 // Finalize the sections.
132 void
133 do_finalize_sections(Layout*);
134
135 // Return the value to use for a dynamic which requires special
136 // treatment.
137 uint64_t
138 do_dynsym_value(const Symbol*) const;
139
140 // Relocate a section.
141 void
142 relocate_section(const Relocate_info<32, big_endian>*,
143 unsigned int sh_type,
144 const unsigned char* prelocs,
145 size_t reloc_count,
146 Output_section* output_section,
147 bool needs_special_offset_handling,
148 unsigned char* view,
149 elfcpp::Elf_types<32>::Elf_Addr view_address,
150 section_size_type view_size);
151
152 // Scan the relocs during a relocatable link.
153 void
154 scan_relocatable_relocs(const General_options& options,
155 Symbol_table* symtab,
156 Layout* layout,
157 Sized_relobj<32, big_endian>* object,
158 unsigned int data_shndx,
159 unsigned int sh_type,
160 const unsigned char* prelocs,
161 size_t reloc_count,
162 Output_section* output_section,
163 bool needs_special_offset_handling,
164 size_t local_symbol_count,
165 const unsigned char* plocal_symbols,
166 Relocatable_relocs*);
167
168 // Relocate a section during a relocatable link.
169 void
170 relocate_for_relocatable(const Relocate_info<32, big_endian>*,
171 unsigned int sh_type,
172 const unsigned char* prelocs,
173 size_t reloc_count,
174 Output_section* output_section,
175 off_t offset_in_output_section,
176 const Relocatable_relocs*,
177 unsigned char* view,
178 elfcpp::Elf_types<32>::Elf_Addr view_address,
179 section_size_type view_size,
180 unsigned char* reloc_view,
181 section_size_type reloc_view_size);
182
183 // Return whether SYM is defined by the ABI.
184 bool
185 do_is_defined_by_abi(Symbol* sym) const
186 { return strcmp(sym->name(), "__tls_get_addr") == 0; }
187
188 // Map platform-specific reloc types
189 static unsigned int
190 get_real_reloc_type (unsigned int r_type);
191
192 private:
193 // The class which scans relocations.
194 class Scan
195 {
196 public:
197 Scan()
198 { }
199
200 inline void
201 local(const General_options& options, Symbol_table* symtab,
202 Layout* layout, Target_arm* target,
203 Sized_relobj<32, big_endian>* object,
204 unsigned int data_shndx,
205 Output_section* output_section,
206 const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type,
207 const elfcpp::Sym<32, big_endian>& lsym);
208
209 inline void
210 global(const General_options& options, Symbol_table* symtab,
211 Layout* layout, Target_arm* target,
212 Sized_relobj<32, big_endian>* object,
213 unsigned int data_shndx,
214 Output_section* output_section,
215 const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type,
216 Symbol* gsym);
217
218 private:
219 static void
220 unsupported_reloc_local(Sized_relobj<32, big_endian>*,
221 unsigned int r_type);
222
223 static void
224 unsupported_reloc_global(Sized_relobj<32, big_endian>*,
225 unsigned int r_type, Symbol*);
226 };
227
228 // The class which implements relocation.
229 class Relocate
230 {
231 public:
232 Relocate()
233 { }
234
235 ~Relocate()
236 { }
237
238 // Do a relocation. Return false if the caller should not issue
239 // any warnings about this relocation.
240 inline bool
241 relocate(const Relocate_info<32, big_endian>*, Target_arm*,
242 Output_section*, size_t relnum,
243 const elfcpp::Rel<32, big_endian>&,
244 unsigned int r_type, const Sized_symbol<32>*,
245 const Symbol_value<32>*,
246 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
247 section_size_type);
248 };
249
250 // A class which returns the size required for a relocation type,
251 // used while scanning relocs during a relocatable link.
252 class Relocatable_size_for_reloc
253 {
254 public:
255 unsigned int
256 get_size_for_reloc(unsigned int, Relobj*);
257 };
258
259 // Information about this specific target which we pass to the
260 // general Target structure.
261 static const Target::Target_info arm_info;
262};
263
264template<bool big_endian>
265const Target::Target_info Target_arm<big_endian>::arm_info =
266{
267 32, // size
268 big_endian, // is_big_endian
269 elfcpp::EM_ARM, // machine_code
270 false, // has_make_symbol
271 false, // has_resolve
272 false, // has_code_fill
273 true, // is_default_stack_executable
274 '\0', // wrap_char
275 "/usr/lib/libc.so.1", // dynamic_linker
276 0x8000, // default_text_segment_address
277 0x1000, // abi_pagesize (overridable by -z max-page-size)
278 0x1000 // common_pagesize (overridable by -z common-page-size)
279};
280
281// Report an unsupported relocation against a local symbol.
282
283template<bool big_endian>
284void
285Target_arm<big_endian>::Scan::unsupported_reloc_local(
286 Sized_relobj<32, big_endian>* object,
287 unsigned int r_type)
288{
289 gold_error(_("%s: unsupported reloc %u against local symbol"),
290 object->name().c_str(), r_type);
291}
292
293// Scan a relocation for a local symbol.
294
295template<bool big_endian>
296inline void
297Target_arm<big_endian>::Scan::local(const General_options&,
298 Symbol_table* /* symtab */,
299 Layout* /* layout */,
300 Target_arm* /* target */,
301 Sized_relobj<32, big_endian>* object,
302 unsigned int /* data_shndx */,
303 Output_section* /* output_section */,
304 const elfcpp::Rel<32, big_endian>& /* reloc */,
305 unsigned int r_type,
306 const elfcpp::Sym<32, big_endian>&)
307{
308 r_type = get_real_reloc_type(r_type);
309 switch (r_type)
310 {
311 case elfcpp::R_ARM_NONE:
312 break;
313
314 default:
315 unsupported_reloc_local(object, r_type);
316 break;
317 }
318}
319
320// Report an unsupported relocation against a global symbol.
321
322template<bool big_endian>
323void
324Target_arm<big_endian>::Scan::unsupported_reloc_global(
325 Sized_relobj<32, big_endian>* object,
326 unsigned int r_type,
327 Symbol* gsym)
328{
329 gold_error(_("%s: unsupported reloc %u against global symbol %s"),
330 object->name().c_str(), r_type, gsym->demangled_name().c_str());
331}
332
333// Scan a relocation for a global symbol.
334
335template<bool big_endian>
336inline void
337Target_arm<big_endian>::Scan::global(const General_options&,
338 Symbol_table* /* symtab */,
339 Layout* /* layout */,
340 Target_arm* /* target */,
341 Sized_relobj<32, big_endian>* object,
342 unsigned int /* data_shndx */,
343 Output_section* /* output_section */,
344 const elfcpp::Rel<32, big_endian>& /* reloc */,
345 unsigned int r_type,
346 Symbol* gsym)
347{
348 r_type = get_real_reloc_type(r_type);
349 switch (r_type)
350 {
351 case elfcpp::R_ARM_NONE:
352 break;
353
354 default:
355 unsupported_reloc_global(object, r_type, gsym);
356 break;
357 }
358}
359
360// Process relocations for gc.
361
362template<bool big_endian>
363void
364Target_arm<big_endian>::gc_process_relocs(const General_options& options,
365 Symbol_table* symtab,
366 Layout* layout,
367 Sized_relobj<32, big_endian>* object,
368 unsigned int data_shndx,
369 unsigned int,
370 const unsigned char* prelocs,
371 size_t reloc_count,
372 Output_section* output_section,
373 bool needs_special_offset_handling,
374 size_t local_symbol_count,
375 const unsigned char* plocal_symbols)
376{
377 typedef Target_arm<big_endian> Arm;
378 typedef typename Target_arm<big_endian>::Scan Scan;
379
380 gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan>(
381 options,
382 symtab,
383 layout,
384 this,
385 object,
386 data_shndx,
387 prelocs,
388 reloc_count,
389 output_section,
390 needs_special_offset_handling,
391 local_symbol_count,
392 plocal_symbols);
393}
394
395// Scan relocations for a section.
396
397template<bool big_endian>
398void
399Target_arm<big_endian>::scan_relocs(const General_options& options,
400 Symbol_table* symtab,
401 Layout* layout,
402 Sized_relobj<32, big_endian>* object,
403 unsigned int data_shndx,
404 unsigned int sh_type,
405 const unsigned char* prelocs,
406 size_t reloc_count,
407 Output_section* output_section,
408 bool needs_special_offset_handling,
409 size_t local_symbol_count,
410 const unsigned char* plocal_symbols)
411{
412 typedef typename Target_arm<big_endian>::Scan Scan;
413 if (sh_type == elfcpp::SHT_RELA)
414 {
415 gold_error(_("%s: unsupported RELA reloc section"),
416 object->name().c_str());
417 return;
418 }
419
420 gold::scan_relocs<32, big_endian, Target_arm, elfcpp::SHT_REL, Scan>(
421 options,
422 symtab,
423 layout,
424 this,
425 object,
426 data_shndx,
427 prelocs,
428 reloc_count,
429 output_section,
430 needs_special_offset_handling,
431 local_symbol_count,
432 plocal_symbols);
433}
434
435// Finalize the sections.
436
437template<bool big_endian>
438void
439Target_arm<big_endian>::do_finalize_sections(Layout* /* layout */)
440{
441 gold_unreachable ();
442}
443
444// Perform a relocation.
445
446template<bool big_endian>
447inline bool
448Target_arm<big_endian>::Relocate::relocate(
449 const Relocate_info<32, big_endian>* /* relinfo */,
450 Target_arm* /* target */,
451 Output_section* /* output_section */,
452 size_t /* relnum */,
453 const elfcpp::Rel<32, big_endian>& /* rel */,
454 unsigned int r_type,
455 const Sized_symbol<32>* /* gsym */,
456 const Symbol_value<32>* /* psymval */,
457 unsigned char* /* view */,
458 elfcpp::Elf_types<32>::Elf_Addr /* address */,
459 section_size_type /* view_size */ )
460{
461 switch (r_type)
462 {
463 case elfcpp::R_ARM_NONE:
464 break;
465
466 default:
467 gold_unreachable();
468 }
469
470 return true;
471}
472
473// Relocate section data.
474
475template<bool big_endian>
476void
477Target_arm<big_endian>::relocate_section(
478 const Relocate_info<32, big_endian>* relinfo,
479 unsigned int sh_type,
480 const unsigned char* prelocs,
481 size_t reloc_count,
482 Output_section* output_section,
483 bool needs_special_offset_handling,
484 unsigned char* view,
485 elfcpp::Elf_types<32>::Elf_Addr address,
486 section_size_type view_size)
487{
488 typedef typename Target_arm<big_endian>::Relocate Arm_relocate;
489 gold_assert(sh_type == elfcpp::SHT_REL);
490
491 gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL,
492 Arm_relocate>(
493 relinfo,
494 this,
495 prelocs,
496 reloc_count,
497 output_section,
498 needs_special_offset_handling,
499 view,
500 address,
501 view_size);
502}
503
504// Return the size of a relocation while scanning during a relocatable
505// link.
506
507template<bool big_endian>
508unsigned int
509Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
510 unsigned int r_type,
511 Relobj* object)
512{
513 r_type = get_real_reloc_type(r_type);
514 switch (r_type)
515 {
516 case elfcpp::R_ARM_NONE:
517 return 0;
518
519 case elfcpp::R_ARM_ABS32:
520 case elfcpp::R_ARM_REL32:
521 case elfcpp::R_ARM_THM_CALL:
522 case elfcpp::R_ARM_GOTOFF32:
523 case elfcpp::R_ARM_BASE_PREL:
524 case elfcpp::R_ARM_GOT_BREL:
525 case elfcpp::R_ARM_PLT32:
526 case elfcpp::R_ARM_CALL:
527 case elfcpp::R_ARM_JUMP24:
528 case elfcpp::R_ARM_PREL31:
529 return 4;
530
531 case elfcpp::R_ARM_TARGET1:
532 // This should have been mapped to another type already.
533 // Fall through.
534 case elfcpp::R_ARM_COPY:
535 case elfcpp::R_ARM_GLOB_DAT:
536 case elfcpp::R_ARM_JUMP_SLOT:
537 case elfcpp::R_ARM_RELATIVE:
538 // These are relocations which should only be seen by the
539 // dynamic linker, and should never be seen here.
540 gold_error(_("%s: unexpected reloc %u in object file"),
541 object->name().c_str(), r_type);
542 return 0;
543
544 default:
545 object->error(_("unsupported reloc %u in object file"), r_type);
546 return 0;
547 }
548}
549
550// Scan the relocs during a relocatable link.
551
552template<bool big_endian>
553void
554Target_arm<big_endian>::scan_relocatable_relocs(
555 const General_options& options,
556 Symbol_table* symtab,
557 Layout* layout,
558 Sized_relobj<32, big_endian>* object,
559 unsigned int data_shndx,
560 unsigned int sh_type,
561 const unsigned char* prelocs,
562 size_t reloc_count,
563 Output_section* output_section,
564 bool needs_special_offset_handling,
565 size_t local_symbol_count,
566 const unsigned char* plocal_symbols,
567 Relocatable_relocs* rr)
568{
569 gold_assert(sh_type == elfcpp::SHT_REL);
570
571 typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
572 Relocatable_size_for_reloc> Scan_relocatable_relocs;
573
574 gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL,
575 Scan_relocatable_relocs>(
576 options,
577 symtab,
578 layout,
579 object,
580 data_shndx,
581 prelocs,
582 reloc_count,
583 output_section,
584 needs_special_offset_handling,
585 local_symbol_count,
586 plocal_symbols,
587 rr);
588}
589
590// Relocate a section during a relocatable link.
591
592template<bool big_endian>
593void
594Target_arm<big_endian>::relocate_for_relocatable(
595 const Relocate_info<32, big_endian>* relinfo,
596 unsigned int sh_type,
597 const unsigned char* prelocs,
598 size_t reloc_count,
599 Output_section* output_section,
600 off_t offset_in_output_section,
601 const Relocatable_relocs* rr,
602 unsigned char* view,
603 elfcpp::Elf_types<32>::Elf_Addr view_address,
604 section_size_type view_size,
605 unsigned char* reloc_view,
606 section_size_type reloc_view_size)
607{
608 gold_assert(sh_type == elfcpp::SHT_REL);
609
610 gold::relocate_for_relocatable<32, big_endian, elfcpp::SHT_REL>(
611 relinfo,
612 prelocs,
613 reloc_count,
614 output_section,
615 offset_in_output_section,
616 rr,
617 view,
618 view_address,
619 view_size,
620 reloc_view,
621 reloc_view_size);
622}
623
624template<bool big_endian>
625uint64_t
626Target_arm<big_endian>::do_dynsym_value(const Symbol* /*gsym*/) const
627{
628 gold_unreachable ();
629 return 0;
630}
631
632// Map platform-specific relocs to real relocs
633//
634template<bool big_endian>
635unsigned int
636Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type)
637{
638 switch (r_type)
639 {
640 case elfcpp::R_ARM_TARGET1:
641 // This is either R_ARM_ABS32 or R_ARM_REL32;
642 return elfcpp::R_ARM_ABS32;
643
644 case elfcpp::R_ARM_TARGET2:
645 // This can be any reloc type but ususally is R_ARM_GOT_PREL
646 return elfcpp::R_ARM_GOT_PREL;
647
648 default:
649 return r_type;
650 }
651}
652
653// The selector for arm object files.
654
655template<bool big_endian>
656class Target_selector_arm : public Target_selector
657{
658 public:
659 Target_selector_arm()
660 : Target_selector(elfcpp::EM_ARM, 32, big_endian,
661 (big_endian ? "elf32-bigarm" : "elf32-littlearm"))
662 { }
663
664 Target*
665 do_instantiate_target()
666 { return new Target_arm<big_endian>(); }
667};
668
669Target_selector_arm<false> target_selector_arm;
670Target_selector_arm<true> target_selector_armbe;
671
672} // End anonymous namespace.
This page took 0.074344 seconds and 4 git commands to generate.