]>
Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* ARC-specific support for 32-bit ELF |
acf8aed4 AM |
2 | Copyright 1994, 1995, 1997, 1999, 2001, 2002 |
3 | Free Software Foundation, Inc. | |
252b5132 RH |
4 | Contributed by Doug Evans ([email protected]). |
5 | ||
0d2bcfaf | 6 | This file is part of BFD, the Binary File Descriptor library. |
252b5132 | 7 | |
0d2bcfaf NC |
8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
252b5132 | 12 | |
0d2bcfaf NC |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
252b5132 | 17 | |
0d2bcfaf NC |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software | |
3e110533 | 20 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
252b5132 RH |
21 | |
22 | #include "bfd.h" | |
23 | #include "sysdep.h" | |
24 | #include "libbfd.h" | |
25 | #include "elf-bfd.h" | |
26 | #include "elf/arc.h" | |
ea04a8f6 | 27 | #include "libiberty.h" |
252b5132 RH |
28 | |
29 | static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup | |
0d2bcfaf | 30 | PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
252b5132 | 31 | static void arc_info_to_howto_rel |
947216bf | 32 | PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
b34976b6 | 33 | static bfd_boolean arc_elf_object_p |
0d2bcfaf NC |
34 | PARAMS ((bfd *)); |
35 | static void arc_elf_final_write_processing | |
b34976b6 | 36 | PARAMS ((bfd *, bfd_boolean)); |
ea04a8f6 NC |
37 | static bfd_reloc_status_type arc_elf_b22_pcrel |
38 | PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); | |
252b5132 RH |
39 | |
40 | /* Try to minimize the amount of space occupied by relocation tables | |
41 | on the ROM (not that the ROM won't be swamped by other ELF overhead). */ | |
0d2bcfaf | 42 | |
acf8aed4 | 43 | #define USE_REL 1 |
252b5132 RH |
44 | |
45 | static reloc_howto_type elf_arc_howto_table[] = | |
46 | { | |
47 | /* This reloc does nothing. */ | |
0d2bcfaf NC |
48 | HOWTO (R_ARC_NONE, /* type */ |
49 | 0, /* rightshift */ | |
50 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
51 | 32, /* bitsize */ | |
b34976b6 | 52 | FALSE, /* pc_relative */ |
0d2bcfaf NC |
53 | 0, /* bitpos */ |
54 | complain_overflow_bitfield, /* complain_on_overflow */ | |
55 | bfd_elf_generic_reloc, /* special_function */ | |
56 | "R_ARC_NONE", /* name */ | |
b34976b6 | 57 | TRUE, /* partial_inplace */ |
0d2bcfaf NC |
58 | 0, /* src_mask */ |
59 | 0, /* dst_mask */ | |
b34976b6 | 60 | FALSE), /* pcrel_offset */ |
252b5132 RH |
61 | |
62 | /* A standard 32 bit relocation. */ | |
0d2bcfaf | 63 | HOWTO (R_ARC_32, /* type */ |
bcee8eb8 AM |
64 | 0, /* rightshift */ |
65 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
66 | 32, /* bitsize */ | |
b34976b6 | 67 | FALSE, /* pc_relative */ |
bcee8eb8 | 68 | 0, /* bitpos */ |
0d2bcfaf | 69 | complain_overflow_bitfield, /* complain_on_overflow */ |
bcee8eb8 | 70 | bfd_elf_generic_reloc, /* special_function */ |
0d2bcfaf | 71 | "R_ARC_32", /* name */ |
b34976b6 | 72 | TRUE, /* partial_inplace */ |
bcee8eb8 AM |
73 | 0xffffffff, /* src_mask */ |
74 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 75 | FALSE), /* pcrel_offset */ |
252b5132 RH |
76 | |
77 | /* A 26 bit absolute branch, right shifted by 2. */ | |
0d2bcfaf NC |
78 | HOWTO (R_ARC_B26, /* type */ |
79 | 2, /* rightshift */ | |
80 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
81 | 26, /* bitsize */ | |
b34976b6 | 82 | FALSE, /* pc_relative */ |
0d2bcfaf NC |
83 | 0, /* bitpos */ |
84 | complain_overflow_bitfield, /* complain_on_overflow */ | |
85 | bfd_elf_generic_reloc, /* special_function */ | |
86 | "R_ARC_B26", /* name */ | |
b34976b6 | 87 | TRUE, /* partial_inplace */ |
0d2bcfaf NC |
88 | 0x00ffffff, /* src_mask */ |
89 | 0x00ffffff, /* dst_mask */ | |
b34976b6 | 90 | FALSE), /* pcrel_offset */ |
252b5132 RH |
91 | |
92 | /* A relative 22 bit branch; bits 21-2 are stored in bits 26-7. */ | |
0d2bcfaf NC |
93 | HOWTO (R_ARC_B22_PCREL, /* type */ |
94 | 2, /* rightshift */ | |
95 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
96 | 22, /* bitsize */ | |
b34976b6 | 97 | TRUE, /* pc_relative */ |
0d2bcfaf NC |
98 | 7, /* bitpos */ |
99 | complain_overflow_signed, /* complain_on_overflow */ | |
ea04a8f6 | 100 | arc_elf_b22_pcrel, /* special_function */ |
0d2bcfaf | 101 | "R_ARC_B22_PCREL", /* name */ |
b34976b6 | 102 | TRUE, /* partial_inplace */ |
0d2bcfaf NC |
103 | 0x07ffff80, /* src_mask */ |
104 | 0x07ffff80, /* dst_mask */ | |
b34976b6 | 105 | FALSE), /* pcrel_offset */ |
252b5132 RH |
106 | }; |
107 | ||
108 | /* Map BFD reloc types to ARC ELF reloc types. */ | |
109 | ||
110 | struct arc_reloc_map | |
111 | { | |
112 | bfd_reloc_code_real_type bfd_reloc_val; | |
113 | unsigned char elf_reloc_val; | |
114 | }; | |
115 | ||
116 | static const struct arc_reloc_map arc_reloc_map[] = | |
117 | { | |
118 | { BFD_RELOC_NONE, R_ARC_NONE, }, | |
119 | { BFD_RELOC_32, R_ARC_32 }, | |
120 | { BFD_RELOC_CTOR, R_ARC_32 }, | |
121 | { BFD_RELOC_ARC_B26, R_ARC_B26 }, | |
122 | { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL }, | |
123 | }; | |
124 | ||
125 | static reloc_howto_type * | |
126 | bfd_elf32_bfd_reloc_type_lookup (abfd, code) | |
5f771d47 | 127 | bfd *abfd ATTRIBUTE_UNUSED; |
252b5132 RH |
128 | bfd_reloc_code_real_type code; |
129 | { | |
130 | unsigned int i; | |
131 | ||
ea04a8f6 NC |
132 | for (i = ARRAY_SIZE (arc_reloc_map); i--;) |
133 | if (arc_reloc_map[i].bfd_reloc_val == code) | |
134 | return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val; | |
135 | ||
252b5132 RH |
136 | return NULL; |
137 | } | |
138 | ||
139 | /* Set the howto pointer for an ARC ELF reloc. */ | |
140 | ||
141 | static void | |
142 | arc_info_to_howto_rel (abfd, cache_ptr, dst) | |
5f771d47 | 143 | bfd *abfd ATTRIBUTE_UNUSED; |
252b5132 | 144 | arelent *cache_ptr; |
947216bf | 145 | Elf_Internal_Rela *dst; |
252b5132 RH |
146 | { |
147 | unsigned int r_type; | |
148 | ||
149 | r_type = ELF32_R_TYPE (dst->r_info); | |
150 | BFD_ASSERT (r_type < (unsigned int) R_ARC_max); | |
151 | cache_ptr->howto = &elf_arc_howto_table[r_type]; | |
152 | } | |
153 | ||
154 | /* Set the right machine number for an ARC ELF file. */ | |
155 | ||
b34976b6 | 156 | static bfd_boolean |
252b5132 RH |
157 | arc_elf_object_p (abfd) |
158 | bfd *abfd; | |
159 | { | |
dc810e39 | 160 | unsigned int mach = bfd_mach_arc_6; |
252b5132 | 161 | |
0d2bcfaf | 162 | if (elf_elfheader(abfd)->e_machine == EM_ARC) |
252b5132 | 163 | { |
0d2bcfaf NC |
164 | unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH; |
165 | ||
166 | switch (arch) | |
167 | { | |
0d2bcfaf NC |
168 | case E_ARC_MACH_ARC5: |
169 | mach = bfd_mach_arc_5; | |
170 | break; | |
bcee8eb8 | 171 | default: |
0d2bcfaf NC |
172 | case E_ARC_MACH_ARC6: |
173 | mach = bfd_mach_arc_6; | |
174 | break; | |
175 | case E_ARC_MACH_ARC7: | |
176 | mach = bfd_mach_arc_7; | |
177 | break; | |
178 | case E_ARC_MACH_ARC8: | |
179 | mach = bfd_mach_arc_8; | |
180 | break; | |
181 | } | |
252b5132 | 182 | } |
0d2bcfaf | 183 | return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach); |
252b5132 RH |
184 | } |
185 | ||
186 | /* The final processing done just before writing out an ARC ELF object file. | |
187 | This gets the ARC architecture right based on the machine number. */ | |
188 | ||
189 | static void | |
190 | arc_elf_final_write_processing (abfd, linker) | |
191 | bfd *abfd; | |
b34976b6 | 192 | bfd_boolean linker ATTRIBUTE_UNUSED; |
252b5132 | 193 | { |
252b5132 RH |
194 | unsigned long val; |
195 | ||
0d2bcfaf | 196 | switch (bfd_get_mach (abfd)) |
252b5132 | 197 | { |
0d2bcfaf NC |
198 | case bfd_mach_arc_5: |
199 | val = E_ARC_MACH_ARC5; | |
200 | break; | |
bcee8eb8 | 201 | default: |
0d2bcfaf NC |
202 | case bfd_mach_arc_6: |
203 | val = E_ARC_MACH_ARC6; | |
204 | break; | |
205 | case bfd_mach_arc_7: | |
206 | val = E_ARC_MACH_ARC7; | |
207 | break; | |
208 | case bfd_mach_arc_8: | |
209 | val = E_ARC_MACH_ARC8; | |
210 | break; | |
252b5132 | 211 | } |
252b5132 RH |
212 | elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH; |
213 | elf_elfheader (abfd)->e_flags |= val; | |
214 | } | |
215 | ||
ea04a8f6 NC |
216 | bfd_reloc_status_type |
217 | arc_elf_b22_pcrel (abfd, reloc_entry, symbol, data, input_section, | |
218 | output_bfd, error_message) | |
219 | bfd * abfd; | |
220 | arelent * reloc_entry; | |
221 | asymbol * symbol; | |
222 | PTR data; | |
223 | asection * input_section; | |
224 | bfd * output_bfd; | |
225 | char ** error_message; | |
226 | { | |
227 | /* If linking, back up the final symbol address by the address of the | |
228 | reloc. This cannot be accomplished by setting the pcrel_offset | |
b34976b6 | 229 | field to TRUE, as bfd_install_relocation will detect this and refuse |
ea04a8f6 NC |
230 | to install the offset in the first place, but bfd_perform_relocation |
231 | will still insist on removing it. */ | |
232 | if (output_bfd == (bfd *) NULL) | |
233 | reloc_entry->addend -= reloc_entry->address; | |
234 | ||
235 | /* Fall through to the default elf reloc handler. */ | |
236 | return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, | |
237 | input_section, output_bfd, error_message); | |
238 | } | |
cedb70c5 | 239 | |
0d2bcfaf NC |
240 | #define TARGET_LITTLE_SYM bfd_elf32_littlearc_vec |
241 | #define TARGET_LITTLE_NAME "elf32-littlearc" | |
242 | #define TARGET_BIG_SYM bfd_elf32_bigarc_vec | |
243 | #define TARGET_BIG_NAME "elf32-bigarc" | |
244 | #define ELF_ARCH bfd_arch_arc | |
245 | #define ELF_MACHINE_CODE EM_ARC | |
246 | #define ELF_MAXPAGESIZE 0x1000 | |
247 | ||
248 | #define elf_info_to_howto 0 | |
249 | #define elf_info_to_howto_rel arc_info_to_howto_rel | |
250 | #define elf_backend_object_p arc_elf_object_p | |
251 | #define elf_backend_final_write_processing arc_elf_final_write_processing | |
252b5132 RH |
252 | |
253 | #include "elf32-target.h" |