1 |
/* PowerPC-specific support for 32-bit ELF |
/* PowerPC-specific support for 32-bit ELF |
2 |
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 |
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
3 |
Free Software Foundation, Inc. |
2004, 2005 Free Software Foundation, Inc. |
4 |
Written by Ian Lance Taylor, Cygnus Support. |
Written by Ian Lance Taylor, Cygnus Support. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
7 |
|
|
8 |
This program is free software; you can redistribute it and/or modify |
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 |
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 |
the Free Software Foundation; either version 2 of the License, or |
11 |
(at your option) any later version. |
(at your option) any later version. |
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
GNU General Public License for more details. |
GNU General Public License for more details. |
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
19 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the |
20 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
21 |
|
Boston, MA 02111-1307, USA. */ |
22 |
|
|
23 |
/* This file is based on a preliminary PowerPC ELF ABI. The |
/* This file is based on a preliminary PowerPC ELF ABI. The |
24 |
information may not match the final PowerPC ELF ABI. It includes |
information may not match the final PowerPC ELF ABI. It includes |
31 |
#include "libbfd.h" |
#include "libbfd.h" |
32 |
#include "elf-bfd.h" |
#include "elf-bfd.h" |
33 |
#include "elf/ppc.h" |
#include "elf/ppc.h" |
34 |
|
#include "elf32-ppc.h" |
35 |
|
|
36 |
#define USE_RELA /* we want RELA relocations, not REL */ |
/* RELA relocations are used here. */ |
37 |
|
|
|
static reloc_howto_type *ppc_elf_reloc_type_lookup |
|
|
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
|
|
static void ppc_elf_info_to_howto |
|
|
PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst)); |
|
|
static void ppc_elf_howto_init PARAMS ((void)); |
|
|
static int ppc_elf_sort_rela PARAMS ((const PTR, const PTR)); |
|
|
static boolean ppc_elf_relax_section |
|
|
PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); |
|
38 |
static bfd_reloc_status_type ppc_elf_addr16_ha_reloc |
static bfd_reloc_status_type ppc_elf_addr16_ha_reloc |
39 |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
40 |
static boolean ppc_elf_object_p PARAMS ((bfd *)); |
static bfd_reloc_status_type ppc_elf_unhandled_reloc |
41 |
static boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword)); |
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
42 |
static boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); |
|
43 |
|
/* Branch prediction bit for branch taken relocs. */ |
44 |
static int ppc_elf_additional_program_headers PARAMS ((bfd *)); |
#define BRANCH_PREDICT_BIT 0x200000 |
45 |
static boolean ppc_elf_modify_segment_map PARAMS ((bfd *)); |
/* Mask to set RA in memory instructions. */ |
46 |
|
#define RA_REGISTER_MASK 0x001f0000 |
47 |
static asection *ppc_elf_create_got |
/* Value to shift register by to insert RA. */ |
48 |
PARAMS ((bfd *, struct bfd_link_info *)); |
#define RA_REGISTER_SHIFT 16 |
|
static boolean ppc_elf_create_dynamic_sections |
|
|
PARAMS ((bfd *, struct bfd_link_info *)); |
|
|
|
|
|
static boolean ppc_elf_section_from_shdr PARAMS ((bfd *, |
|
|
Elf32_Internal_Shdr *, |
|
|
const char *)); |
|
|
static boolean ppc_elf_fake_sections |
|
|
PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); |
|
|
|
|
|
static elf_linker_section_t *ppc_elf_create_linker_section |
|
|
PARAMS ((bfd *abfd, |
|
|
struct bfd_link_info *info, |
|
|
enum elf_linker_section_enum)); |
|
|
|
|
|
static boolean ppc_elf_check_relocs PARAMS ((bfd *, |
|
|
struct bfd_link_info *, |
|
|
asection *, |
|
|
const Elf_Internal_Rela *)); |
|
|
|
|
|
static asection * ppc_elf_gc_mark_hook PARAMS ((asection *sec, |
|
|
struct bfd_link_info *info, |
|
|
Elf_Internal_Rela *rel, |
|
|
struct elf_link_hash_entry *h, |
|
|
Elf_Internal_Sym *sym)); |
|
|
|
|
|
static boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd, |
|
|
struct bfd_link_info *info, |
|
|
asection *sec, |
|
|
const Elf_Internal_Rela *relocs)); |
|
|
|
|
|
static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, |
|
|
struct elf_link_hash_entry *)); |
|
|
|
|
|
static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); |
|
|
|
|
|
static boolean ppc_elf_relocate_section PARAMS ((bfd *, |
|
|
struct bfd_link_info *info, |
|
|
bfd *, |
|
|
asection *, |
|
|
bfd_byte *, |
|
|
Elf_Internal_Rela *relocs, |
|
|
Elf_Internal_Sym *local_syms, |
|
|
asection **)); |
|
|
|
|
|
static boolean ppc_elf_add_symbol_hook PARAMS ((bfd *, |
|
|
struct bfd_link_info *, |
|
|
const Elf_Internal_Sym *, |
|
|
const char **, |
|
|
flagword *, |
|
|
asection **, |
|
|
bfd_vma *)); |
|
|
|
|
|
static boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *, |
|
|
struct bfd_link_info *, |
|
|
struct elf_link_hash_entry *, |
|
|
Elf_Internal_Sym *)); |
|
|
|
|
|
static boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); |
|
|
static enum elf_reloc_type_class ppc_elf_reloc_type_class |
|
|
PARAMS ((const Elf_Internal_Rela *)); |
|
|
static boolean ppc_elf_grok_prstatus |
|
|
PARAMS ((bfd *abfd, Elf_Internal_Note *note)); |
|
|
static boolean ppc_elf_grok_psinfo |
|
|
PARAMS ((bfd *abfd, Elf_Internal_Note *note)); |
|
|
|
|
|
#define BRANCH_PREDICT_BIT 0x200000 /* branch prediction bit for branch taken relocs */ |
|
|
#define RA_REGISTER_MASK 0x001f0000 /* mask to set RA in memory instructions */ |
|
|
#define RA_REGISTER_SHIFT 16 /* value to shift register by to insert RA */ |
|
49 |
|
|
50 |
/* The name of the dynamic interpreter. This is put in the .interp |
/* The name of the dynamic interpreter. This is put in the .interp |
51 |
section. */ |
section. */ |
|
|
|
52 |
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" |
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" |
53 |
|
|
54 |
/* The size in bytes of an entry in the procedure linkage table. */ |
/* The size in bytes of an entry in the procedure linkage table. */ |
60 |
/* The number of single-slot PLT entries (the rest use two slots). */ |
/* The number of single-slot PLT entries (the rest use two slots). */ |
61 |
#define PLT_NUM_SINGLE_ENTRIES 8192 |
#define PLT_NUM_SINGLE_ENTRIES 8192 |
62 |
|
|
63 |
/* Will references to this symbol always reference the symbol |
/* Some nop instructions. */ |
64 |
in this object? */ |
#define NOP 0x60000000 |
65 |
#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ |
#define CROR_151515 0x4def7b82 |
66 |
((! INFO->shared \ |
#define CROR_313131 0x4ffffb82 |
67 |
|| INFO->symbolic \ |
|
68 |
|| H->dynindx == -1 \ |
/* Offset of tp and dtp pointers from start of TLS block. */ |
69 |
|| ELF_ST_VISIBILITY (H->other) == STV_INTERNAL \ |
#define TP_OFFSET 0x7000 |
70 |
|| ELF_ST_VISIBILITY (H->other) == STV_HIDDEN) \ |
#define DTP_OFFSET 0x8000 |
71 |
&& (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) |
|
|
|
|
|
/* Will _calls_ to this symbol always call the version in this object? */ |
|
|
#define SYMBOL_CALLS_LOCAL(INFO, H) \ |
|
|
((! INFO->shared \ |
|
|
|| INFO->symbolic \ |
|
|
|| H->dynindx == -1 \ |
|
|
|| ELF_ST_VISIBILITY (H->other) != STV_DEFAULT) \ |
|
|
&& (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) |
|
72 |
|
|
73 |
static reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max]; |
/* Enumeration to specify the special section. */ |
74 |
|
enum elf_linker_section_enum |
75 |
|
{ |
76 |
|
LINKER_SECTION_SDATA, |
77 |
|
LINKER_SECTION_SDATA2 |
78 |
|
}; |
79 |
|
|
80 |
|
/* Sections created by the linker. */ |
81 |
|
|
82 |
|
typedef struct elf_linker_section |
83 |
|
{ |
84 |
|
/* pointer to the section */ |
85 |
|
asection *section; |
86 |
|
/* pointer to the relocations needed for this section */ |
87 |
|
asection *rel_section; |
88 |
|
/* pointer to the created symbol hash value */ |
89 |
|
struct elf_link_hash_entry *sym_hash; |
90 |
|
/* offset of symbol from beginning of section */ |
91 |
|
bfd_vma sym_offset; |
92 |
|
} elf_linker_section_t; |
93 |
|
|
94 |
|
/* Linked list of allocated pointer entries. This hangs off of the |
95 |
|
symbol lists, and provides allows us to return different pointers, |
96 |
|
based on different addend's. */ |
97 |
|
|
98 |
|
typedef struct elf_linker_section_pointers |
99 |
|
{ |
100 |
|
/* next allocated pointer for this symbol */ |
101 |
|
struct elf_linker_section_pointers *next; |
102 |
|
/* offset of pointer from beginning of section */ |
103 |
|
bfd_vma offset; |
104 |
|
/* addend used */ |
105 |
|
bfd_vma addend; |
106 |
|
/* which linker section this is */ |
107 |
|
elf_linker_section_t *lsect; |
108 |
|
/* whether address was written yet */ |
109 |
|
bfd_boolean written_address_p; |
110 |
|
} elf_linker_section_pointers_t; |
111 |
|
|
112 |
|
struct ppc_elf_obj_tdata |
113 |
|
{ |
114 |
|
struct elf_obj_tdata elf; |
115 |
|
|
116 |
|
/* A mapping from local symbols to offsets into the various linker |
117 |
|
sections added. This is index by the symbol index. */ |
118 |
|
elf_linker_section_pointers_t **linker_section_pointers; |
119 |
|
}; |
120 |
|
|
121 |
|
#define ppc_elf_tdata(bfd) \ |
122 |
|
((struct ppc_elf_obj_tdata *) (bfd)->tdata.any) |
123 |
|
|
124 |
|
#define elf_local_ptr_offsets(bfd) \ |
125 |
|
(ppc_elf_tdata (bfd)->linker_section_pointers) |
126 |
|
|
127 |
|
/* Override the generic function because we store some extras. */ |
128 |
|
|
129 |
|
static bfd_boolean |
130 |
|
ppc_elf_mkobject (bfd *abfd) |
131 |
|
{ |
132 |
|
bfd_size_type amt = sizeof (struct ppc_elf_obj_tdata); |
133 |
|
abfd->tdata.any = bfd_zalloc (abfd, amt); |
134 |
|
if (abfd->tdata.any == NULL) |
135 |
|
return FALSE; |
136 |
|
return TRUE; |
137 |
|
} |
138 |
|
|
139 |
|
/* The PPC linker needs to keep track of the number of relocs that it |
140 |
|
decides to copy as dynamic relocs in check_relocs for each symbol. |
141 |
|
This is so that it can later discard them if they are found to be |
142 |
|
unnecessary. We store the information in a field extending the |
143 |
|
regular ELF linker hash table. */ |
144 |
|
|
145 |
|
struct ppc_elf_dyn_relocs |
146 |
|
{ |
147 |
|
struct ppc_elf_dyn_relocs *next; |
148 |
|
|
149 |
|
/* The input section of the reloc. */ |
150 |
|
asection *sec; |
151 |
|
|
152 |
|
/* Total number of relocs copied for the input section. */ |
153 |
|
bfd_size_type count; |
154 |
|
|
155 |
|
/* Number of pc-relative relocs copied for the input section. */ |
156 |
|
bfd_size_type pc_count; |
157 |
|
}; |
158 |
|
|
159 |
|
/* PPC ELF linker hash entry. */ |
160 |
|
|
161 |
|
struct ppc_elf_link_hash_entry |
162 |
|
{ |
163 |
|
struct elf_link_hash_entry elf; |
164 |
|
|
165 |
|
/* If this symbol is used in the linker created sections, the processor |
166 |
|
specific backend uses this field to map the field into the offset |
167 |
|
from the beginning of the section. */ |
168 |
|
elf_linker_section_pointers_t *linker_section_pointer; |
169 |
|
|
170 |
|
/* Track dynamic relocs copied for this symbol. */ |
171 |
|
struct ppc_elf_dyn_relocs *dyn_relocs; |
172 |
|
|
173 |
|
/* Contexts in which symbol is used in the GOT (or TOC). |
174 |
|
TLS_GD .. TLS_TLS bits are or'd into the mask as the |
175 |
|
corresponding relocs are encountered during check_relocs. |
176 |
|
tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to |
177 |
|
indicate the corresponding GOT entry type is not needed. */ |
178 |
|
#define TLS_GD 1 /* GD reloc. */ |
179 |
|
#define TLS_LD 2 /* LD reloc. */ |
180 |
|
#define TLS_TPREL 4 /* TPREL reloc, => IE. */ |
181 |
|
#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ |
182 |
|
#define TLS_TLS 16 /* Any TLS reloc. */ |
183 |
|
#define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */ |
184 |
|
char tls_mask; |
185 |
|
}; |
186 |
|
|
187 |
|
#define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent)) |
188 |
|
|
189 |
|
/* PPC ELF linker hash table. */ |
190 |
|
|
191 |
|
struct ppc_elf_link_hash_table |
192 |
|
{ |
193 |
|
struct elf_link_hash_table elf; |
194 |
|
|
195 |
|
/* Short-cuts to get to dynamic linker sections. */ |
196 |
|
asection *got; |
197 |
|
asection *relgot; |
198 |
|
asection *plt; |
199 |
|
asection *relplt; |
200 |
|
asection *dynbss; |
201 |
|
asection *relbss; |
202 |
|
asection *dynsbss; |
203 |
|
asection *relsbss; |
204 |
|
elf_linker_section_t *sdata; |
205 |
|
elf_linker_section_t *sdata2; |
206 |
|
asection *sbss; |
207 |
|
|
208 |
|
/* Shortcut to .__tls_get_addr. */ |
209 |
|
struct elf_link_hash_entry *tls_get_addr; |
210 |
|
|
211 |
|
/* TLS local dynamic got entry handling. */ |
212 |
|
union { |
213 |
|
bfd_signed_vma refcount; |
214 |
|
bfd_vma offset; |
215 |
|
} tlsld_got; |
216 |
|
|
217 |
|
/* Small local sym to section mapping cache. */ |
218 |
|
struct sym_sec_cache sym_sec; |
219 |
|
}; |
220 |
|
|
221 |
|
/* Get the PPC ELF linker hash table from a link_info structure. */ |
222 |
|
|
223 |
|
#define ppc_elf_hash_table(p) \ |
224 |
|
((struct ppc_elf_link_hash_table *) (p)->hash) |
225 |
|
|
226 |
|
/* Create an entry in a PPC ELF linker hash table. */ |
227 |
|
|
228 |
|
static struct bfd_hash_entry * |
229 |
|
ppc_elf_link_hash_newfunc (struct bfd_hash_entry *entry, |
230 |
|
struct bfd_hash_table *table, |
231 |
|
const char *string) |
232 |
|
{ |
233 |
|
/* Allocate the structure if it has not already been allocated by a |
234 |
|
subclass. */ |
235 |
|
if (entry == NULL) |
236 |
|
{ |
237 |
|
entry = bfd_hash_allocate (table, |
238 |
|
sizeof (struct ppc_elf_link_hash_entry)); |
239 |
|
if (entry == NULL) |
240 |
|
return entry; |
241 |
|
} |
242 |
|
|
243 |
|
/* Call the allocation method of the superclass. */ |
244 |
|
entry = _bfd_elf_link_hash_newfunc (entry, table, string); |
245 |
|
if (entry != NULL) |
246 |
|
{ |
247 |
|
ppc_elf_hash_entry (entry)->linker_section_pointer = NULL; |
248 |
|
ppc_elf_hash_entry (entry)->dyn_relocs = NULL; |
249 |
|
ppc_elf_hash_entry (entry)->tls_mask = 0; |
250 |
|
} |
251 |
|
|
252 |
|
return entry; |
253 |
|
} |
254 |
|
|
255 |
|
/* Create a PPC ELF linker hash table. */ |
256 |
|
|
257 |
|
static struct bfd_link_hash_table * |
258 |
|
ppc_elf_link_hash_table_create (bfd *abfd) |
259 |
|
{ |
260 |
|
struct ppc_elf_link_hash_table *ret; |
261 |
|
|
262 |
|
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table)); |
263 |
|
if (ret == NULL) |
264 |
|
return NULL; |
265 |
|
|
266 |
|
if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, |
267 |
|
ppc_elf_link_hash_newfunc)) |
268 |
|
{ |
269 |
|
free (ret); |
270 |
|
return NULL; |
271 |
|
} |
272 |
|
|
273 |
|
return &ret->elf.root; |
274 |
|
} |
275 |
|
|
276 |
|
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid |
277 |
|
copying dynamic variables from a shared lib into an app's dynbss |
278 |
|
section, and instead use a dynamic relocation to point into the |
279 |
|
shared lib. */ |
280 |
|
#define ELIMINATE_COPY_RELOCS 1 |
281 |
|
|
282 |
|
/* Copy the extra info we tack onto an elf_link_hash_entry. */ |
283 |
|
|
284 |
|
static void |
285 |
|
ppc_elf_copy_indirect_symbol (const struct elf_backend_data *bed, |
286 |
|
struct elf_link_hash_entry *dir, |
287 |
|
struct elf_link_hash_entry *ind) |
288 |
|
{ |
289 |
|
struct ppc_elf_link_hash_entry *edir, *eind; |
290 |
|
|
291 |
|
edir = (struct ppc_elf_link_hash_entry *) dir; |
292 |
|
eind = (struct ppc_elf_link_hash_entry *) ind; |
293 |
|
|
294 |
|
if (eind->dyn_relocs != NULL) |
295 |
|
{ |
296 |
|
if (edir->dyn_relocs != NULL) |
297 |
|
{ |
298 |
|
struct ppc_elf_dyn_relocs **pp; |
299 |
|
struct ppc_elf_dyn_relocs *p; |
300 |
|
|
301 |
|
if (ind->root.type == bfd_link_hash_indirect) |
302 |
|
abort (); |
303 |
|
|
304 |
|
/* Add reloc counts against the weak sym to the strong sym |
305 |
|
list. Merge any entries against the same section. */ |
306 |
|
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) |
307 |
|
{ |
308 |
|
struct ppc_elf_dyn_relocs *q; |
309 |
|
|
310 |
|
for (q = edir->dyn_relocs; q != NULL; q = q->next) |
311 |
|
if (q->sec == p->sec) |
312 |
|
{ |
313 |
|
q->pc_count += p->pc_count; |
314 |
|
q->count += p->count; |
315 |
|
*pp = p->next; |
316 |
|
break; |
317 |
|
} |
318 |
|
if (q == NULL) |
319 |
|
pp = &p->next; |
320 |
|
} |
321 |
|
*pp = edir->dyn_relocs; |
322 |
|
} |
323 |
|
|
324 |
|
edir->dyn_relocs = eind->dyn_relocs; |
325 |
|
eind->dyn_relocs = NULL; |
326 |
|
} |
327 |
|
|
328 |
|
edir->tls_mask |= eind->tls_mask; |
329 |
|
|
330 |
|
if (ELIMINATE_COPY_RELOCS |
331 |
|
&& ind->root.type != bfd_link_hash_indirect |
332 |
|
&& dir->dynamic_adjusted) |
333 |
|
{ |
334 |
|
/* If called to transfer flags for a weakdef during processing |
335 |
|
of elf_adjust_dynamic_symbol, don't copy non_got_ref. |
336 |
|
We clear it ourselves for ELIMINATE_COPY_RELOCS. */ |
337 |
|
dir->ref_dynamic |= ind->ref_dynamic; |
338 |
|
dir->ref_regular |= ind->ref_regular; |
339 |
|
dir->ref_regular_nonweak |= ind->ref_regular_nonweak; |
340 |
|
dir->needs_plt |= ind->needs_plt; |
341 |
|
} |
342 |
|
else |
343 |
|
_bfd_elf_link_hash_copy_indirect (bed, dir, ind); |
344 |
|
} |
345 |
|
|
346 |
|
static reloc_howto_type *ppc_elf_howto_table[R_PPC_max]; |
347 |
|
|
348 |
static reloc_howto_type ppc_elf_howto_raw[] = { |
static reloc_howto_type ppc_elf_howto_raw[] = { |
349 |
/* This reloc does nothing. */ |
/* This reloc does nothing. */ |
351 |
0, /* rightshift */ |
0, /* rightshift */ |
352 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
353 |
32, /* bitsize */ |
32, /* bitsize */ |
354 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
355 |
0, /* bitpos */ |
0, /* bitpos */ |
356 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
357 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
358 |
"R_PPC_NONE", /* name */ |
"R_PPC_NONE", /* name */ |
359 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
360 |
0, /* src_mask */ |
0, /* src_mask */ |
361 |
0, /* dst_mask */ |
0, /* dst_mask */ |
362 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
363 |
|
|
364 |
/* A standard 32 bit relocation. */ |
/* A standard 32 bit relocation. */ |
365 |
HOWTO (R_PPC_ADDR32, /* type */ |
HOWTO (R_PPC_ADDR32, /* type */ |
366 |
0, /* rightshift */ |
0, /* rightshift */ |
367 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
368 |
32, /* bitsize */ |
32, /* bitsize */ |
369 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
370 |
0, /* bitpos */ |
0, /* bitpos */ |
371 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
372 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
373 |
"R_PPC_ADDR32", /* name */ |
"R_PPC_ADDR32", /* name */ |
374 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
375 |
0, /* src_mask */ |
0, /* src_mask */ |
376 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
377 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
378 |
|
|
379 |
/* An absolute 26 bit branch; the lower two bits must be zero. |
/* An absolute 26 bit branch; the lower two bits must be zero. |
380 |
FIXME: we don't check that, we just clear them. */ |
FIXME: we don't check that, we just clear them. */ |
382 |
0, /* rightshift */ |
0, /* rightshift */ |
383 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
384 |
26, /* bitsize */ |
26, /* bitsize */ |
385 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
386 |
0, /* bitpos */ |
0, /* bitpos */ |
387 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
388 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
389 |
"R_PPC_ADDR24", /* name */ |
"R_PPC_ADDR24", /* name */ |
390 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
391 |
0, /* src_mask */ |
0, /* src_mask */ |
392 |
0x3fffffc, /* dst_mask */ |
0x3fffffc, /* dst_mask */ |
393 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
394 |
|
|
395 |
/* A standard 16 bit relocation. */ |
/* A standard 16 bit relocation. */ |
396 |
HOWTO (R_PPC_ADDR16, /* type */ |
HOWTO (R_PPC_ADDR16, /* type */ |
397 |
0, /* rightshift */ |
0, /* rightshift */ |
398 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
399 |
16, /* bitsize */ |
16, /* bitsize */ |
400 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
401 |
0, /* bitpos */ |
0, /* bitpos */ |
402 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
403 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
404 |
"R_PPC_ADDR16", /* name */ |
"R_PPC_ADDR16", /* name */ |
405 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
406 |
0, /* src_mask */ |
0, /* src_mask */ |
407 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
408 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
409 |
|
|
410 |
/* A 16 bit relocation without overflow. */ |
/* A 16 bit relocation without overflow. */ |
411 |
HOWTO (R_PPC_ADDR16_LO, /* type */ |
HOWTO (R_PPC_ADDR16_LO, /* type */ |
412 |
0, /* rightshift */ |
0, /* rightshift */ |
413 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
414 |
16, /* bitsize */ |
16, /* bitsize */ |
415 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
416 |
0, /* bitpos */ |
0, /* bitpos */ |
417 |
complain_overflow_dont,/* complain_on_overflow */ |
complain_overflow_dont,/* complain_on_overflow */ |
418 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
419 |
"R_PPC_ADDR16_LO", /* name */ |
"R_PPC_ADDR16_LO", /* name */ |
420 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
421 |
0, /* src_mask */ |
0, /* src_mask */ |
422 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
423 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
424 |
|
|
425 |
/* The high order 16 bits of an address. */ |
/* The high order 16 bits of an address. */ |
426 |
HOWTO (R_PPC_ADDR16_HI, /* type */ |
HOWTO (R_PPC_ADDR16_HI, /* type */ |
427 |
16, /* rightshift */ |
16, /* rightshift */ |
428 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
429 |
16, /* bitsize */ |
16, /* bitsize */ |
430 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
431 |
0, /* bitpos */ |
0, /* bitpos */ |
432 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
433 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
434 |
"R_PPC_ADDR16_HI", /* name */ |
"R_PPC_ADDR16_HI", /* name */ |
435 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
436 |
0, /* src_mask */ |
0, /* src_mask */ |
437 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
438 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
439 |
|
|
440 |
/* The high order 16 bits of an address, plus 1 if the contents of |
/* The high order 16 bits of an address, plus 1 if the contents of |
441 |
the low 16 bits, treated as a signed number, is negative. */ |
the low 16 bits, treated as a signed number, is negative. */ |
443 |
16, /* rightshift */ |
16, /* rightshift */ |
444 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
445 |
16, /* bitsize */ |
16, /* bitsize */ |
446 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
447 |
0, /* bitpos */ |
0, /* bitpos */ |
448 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
449 |
ppc_elf_addr16_ha_reloc, /* special_function */ |
ppc_elf_addr16_ha_reloc, /* special_function */ |
450 |
"R_PPC_ADDR16_HA", /* name */ |
"R_PPC_ADDR16_HA", /* name */ |
451 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
452 |
0, /* src_mask */ |
0, /* src_mask */ |
453 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
454 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
455 |
|
|
456 |
/* An absolute 16 bit branch; the lower two bits must be zero. |
/* An absolute 16 bit branch; the lower two bits must be zero. |
457 |
FIXME: we don't check that, we just clear them. */ |
FIXME: we don't check that, we just clear them. */ |
459 |
0, /* rightshift */ |
0, /* rightshift */ |
460 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
461 |
16, /* bitsize */ |
16, /* bitsize */ |
462 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
463 |
0, /* bitpos */ |
0, /* bitpos */ |
464 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
465 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
466 |
"R_PPC_ADDR14", /* name */ |
"R_PPC_ADDR14", /* name */ |
467 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
468 |
0, /* src_mask */ |
0, /* src_mask */ |
469 |
0xfffc, /* dst_mask */ |
0xfffc, /* dst_mask */ |
470 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
471 |
|
|
472 |
/* An absolute 16 bit branch, for which bit 10 should be set to |
/* An absolute 16 bit branch, for which bit 10 should be set to |
473 |
indicate that the branch is expected to be taken. The lower two |
indicate that the branch is expected to be taken. The lower two |
476 |
0, /* rightshift */ |
0, /* rightshift */ |
477 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
478 |
16, /* bitsize */ |
16, /* bitsize */ |
479 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
480 |
0, /* bitpos */ |
0, /* bitpos */ |
481 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
482 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
483 |
"R_PPC_ADDR14_BRTAKEN",/* name */ |
"R_PPC_ADDR14_BRTAKEN",/* name */ |
484 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
485 |
0, /* src_mask */ |
0, /* src_mask */ |
486 |
0xfffc, /* dst_mask */ |
0xfffc, /* dst_mask */ |
487 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
488 |
|
|
489 |
/* An absolute 16 bit branch, for which bit 10 should be set to |
/* An absolute 16 bit branch, for which bit 10 should be set to |
490 |
indicate that the branch is not expected to be taken. The lower |
indicate that the branch is not expected to be taken. The lower |
493 |
0, /* rightshift */ |
0, /* rightshift */ |
494 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
495 |
16, /* bitsize */ |
16, /* bitsize */ |
496 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
497 |
0, /* bitpos */ |
0, /* bitpos */ |
498 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
499 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
500 |
"R_PPC_ADDR14_BRNTAKEN",/* name */ |
"R_PPC_ADDR14_BRNTAKEN",/* name */ |
501 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
502 |
0, /* src_mask */ |
0, /* src_mask */ |
503 |
0xfffc, /* dst_mask */ |
0xfffc, /* dst_mask */ |
504 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
505 |
|
|
506 |
/* A relative 26 bit branch; the lower two bits must be zero. */ |
/* A relative 26 bit branch; the lower two bits must be zero. */ |
507 |
HOWTO (R_PPC_REL24, /* type */ |
HOWTO (R_PPC_REL24, /* type */ |
508 |
0, /* rightshift */ |
0, /* rightshift */ |
509 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
510 |
26, /* bitsize */ |
26, /* bitsize */ |
511 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
512 |
0, /* bitpos */ |
0, /* bitpos */ |
513 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
514 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
515 |
"R_PPC_REL24", /* name */ |
"R_PPC_REL24", /* name */ |
516 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
517 |
0, /* src_mask */ |
0, /* src_mask */ |
518 |
0x3fffffc, /* dst_mask */ |
0x3fffffc, /* dst_mask */ |
519 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
520 |
|
|
521 |
/* A relative 16 bit branch; the lower two bits must be zero. */ |
/* A relative 16 bit branch; the lower two bits must be zero. */ |
522 |
HOWTO (R_PPC_REL14, /* type */ |
HOWTO (R_PPC_REL14, /* type */ |
523 |
0, /* rightshift */ |
0, /* rightshift */ |
524 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
525 |
16, /* bitsize */ |
16, /* bitsize */ |
526 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
527 |
0, /* bitpos */ |
0, /* bitpos */ |
528 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
529 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
530 |
"R_PPC_REL14", /* name */ |
"R_PPC_REL14", /* name */ |
531 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
532 |
0, /* src_mask */ |
0, /* src_mask */ |
533 |
0xfffc, /* dst_mask */ |
0xfffc, /* dst_mask */ |
534 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
535 |
|
|
536 |
/* A relative 16 bit branch. Bit 10 should be set to indicate that |
/* A relative 16 bit branch. Bit 10 should be set to indicate that |
537 |
the branch is expected to be taken. The lower two bits must be |
the branch is expected to be taken. The lower two bits must be |
540 |
0, /* rightshift */ |
0, /* rightshift */ |
541 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
542 |
16, /* bitsize */ |
16, /* bitsize */ |
543 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
544 |
0, /* bitpos */ |
0, /* bitpos */ |
545 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
546 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
547 |
"R_PPC_REL14_BRTAKEN", /* name */ |
"R_PPC_REL14_BRTAKEN", /* name */ |
548 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
549 |
0, /* src_mask */ |
0, /* src_mask */ |
550 |
0xfffc, /* dst_mask */ |
0xfffc, /* dst_mask */ |
551 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
552 |
|
|
553 |
/* A relative 16 bit branch. Bit 10 should be set to indicate that |
/* A relative 16 bit branch. Bit 10 should be set to indicate that |
554 |
the branch is not expected to be taken. The lower two bits must |
the branch is not expected to be taken. The lower two bits must |
557 |
0, /* rightshift */ |
0, /* rightshift */ |
558 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
559 |
16, /* bitsize */ |
16, /* bitsize */ |
560 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
561 |
0, /* bitpos */ |
0, /* bitpos */ |
562 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
563 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
564 |
"R_PPC_REL14_BRNTAKEN",/* name */ |
"R_PPC_REL14_BRNTAKEN",/* name */ |
565 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
566 |
0, /* src_mask */ |
0, /* src_mask */ |
567 |
0xfffc, /* dst_mask */ |
0xfffc, /* dst_mask */ |
568 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
569 |
|
|
570 |
/* Like R_PPC_ADDR16, but referring to the GOT table entry for the |
/* Like R_PPC_ADDR16, but referring to the GOT table entry for the |
571 |
symbol. */ |
symbol. */ |
573 |
0, /* rightshift */ |
0, /* rightshift */ |
574 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
575 |
16, /* bitsize */ |
16, /* bitsize */ |
576 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
577 |
0, /* bitpos */ |
0, /* bitpos */ |
578 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
579 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
580 |
"R_PPC_GOT16", /* name */ |
"R_PPC_GOT16", /* name */ |
581 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
582 |
0, /* src_mask */ |
0, /* src_mask */ |
583 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
584 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
585 |
|
|
586 |
/* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for |
/* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for |
587 |
the symbol. */ |
the symbol. */ |
589 |
0, /* rightshift */ |
0, /* rightshift */ |
590 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
591 |
16, /* bitsize */ |
16, /* bitsize */ |
592 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
593 |
0, /* bitpos */ |
0, /* bitpos */ |
594 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
595 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
596 |
"R_PPC_GOT16_LO", /* name */ |
"R_PPC_GOT16_LO", /* name */ |
597 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
598 |
0, /* src_mask */ |
0, /* src_mask */ |
599 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
600 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
601 |
|
|
602 |
/* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for |
/* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for |
603 |
the symbol. */ |
the symbol. */ |
605 |
16, /* rightshift */ |
16, /* rightshift */ |
606 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
607 |
16, /* bitsize */ |
16, /* bitsize */ |
608 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
609 |
0, /* bitpos */ |
0, /* bitpos */ |
610 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
611 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
612 |
"R_PPC_GOT16_HI", /* name */ |
"R_PPC_GOT16_HI", /* name */ |
613 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
614 |
0, /* src_mask */ |
0, /* src_mask */ |
615 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
616 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
617 |
|
|
618 |
/* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for |
/* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for |
619 |
the symbol. */ |
the symbol. */ |
621 |
16, /* rightshift */ |
16, /* rightshift */ |
622 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
623 |
16, /* bitsize */ |
16, /* bitsize */ |
624 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
625 |
0, /* bitpos */ |
0, /* bitpos */ |
626 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
627 |
ppc_elf_addr16_ha_reloc, /* special_function */ |
ppc_elf_addr16_ha_reloc, /* special_function */ |
628 |
"R_PPC_GOT16_HA", /* name */ |
"R_PPC_GOT16_HA", /* name */ |
629 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
630 |
0, /* src_mask */ |
0, /* src_mask */ |
631 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
632 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
633 |
|
|
634 |
/* Like R_PPC_REL24, but referring to the procedure linkage table |
/* Like R_PPC_REL24, but referring to the procedure linkage table |
635 |
entry for the symbol. */ |
entry for the symbol. */ |
637 |
0, /* rightshift */ |
0, /* rightshift */ |
638 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
639 |
26, /* bitsize */ |
26, /* bitsize */ |
640 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
641 |
0, /* bitpos */ |
0, /* bitpos */ |
642 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
643 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
644 |
"R_PPC_PLTREL24", /* name */ |
"R_PPC_PLTREL24", /* name */ |
645 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
646 |
0, /* src_mask */ |
0, /* src_mask */ |
647 |
0x3fffffc, /* dst_mask */ |
0x3fffffc, /* dst_mask */ |
648 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
649 |
|
|
650 |
/* This is used only by the dynamic linker. The symbol should exist |
/* This is used only by the dynamic linker. The symbol should exist |
651 |
both in the object being run and in some shared library. The |
both in the object being run and in some shared library. The |
656 |
0, /* rightshift */ |
0, /* rightshift */ |
657 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
658 |
32, /* bitsize */ |
32, /* bitsize */ |
659 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
660 |
0, /* bitpos */ |
0, /* bitpos */ |
661 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
662 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
663 |
"R_PPC_COPY", /* name */ |
"R_PPC_COPY", /* name */ |
664 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
665 |
0, /* src_mask */ |
0, /* src_mask */ |
666 |
0, /* dst_mask */ |
0, /* dst_mask */ |
667 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
668 |
|
|
669 |
/* Like R_PPC_ADDR32, but used when setting global offset table |
/* Like R_PPC_ADDR32, but used when setting global offset table |
670 |
entries. */ |
entries. */ |
672 |
0, /* rightshift */ |
0, /* rightshift */ |
673 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
674 |
32, /* bitsize */ |
32, /* bitsize */ |
675 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
676 |
0, /* bitpos */ |
0, /* bitpos */ |
677 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
678 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
679 |
"R_PPC_GLOB_DAT", /* name */ |
"R_PPC_GLOB_DAT", /* name */ |
680 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
681 |
0, /* src_mask */ |
0, /* src_mask */ |
682 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
683 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
684 |
|
|
685 |
/* Marks a procedure linkage table entry for a symbol. */ |
/* Marks a procedure linkage table entry for a symbol. */ |
686 |
HOWTO (R_PPC_JMP_SLOT, /* type */ |
HOWTO (R_PPC_JMP_SLOT, /* type */ |
687 |
0, /* rightshift */ |
0, /* rightshift */ |
688 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
689 |
32, /* bitsize */ |
32, /* bitsize */ |
690 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
691 |
0, /* bitpos */ |
0, /* bitpos */ |
692 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
693 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
694 |
"R_PPC_JMP_SLOT", /* name */ |
"R_PPC_JMP_SLOT", /* name */ |
695 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
696 |
0, /* src_mask */ |
0, /* src_mask */ |
697 |
0, /* dst_mask */ |
0, /* dst_mask */ |
698 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
699 |
|
|
700 |
/* Used only by the dynamic linker. When the object is run, this |
/* Used only by the dynamic linker. When the object is run, this |
701 |
longword is set to the load address of the object, plus the |
longword is set to the load address of the object, plus the |
704 |
0, /* rightshift */ |
0, /* rightshift */ |
705 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
706 |
32, /* bitsize */ |
32, /* bitsize */ |
707 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
708 |
0, /* bitpos */ |
0, /* bitpos */ |
709 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
710 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
711 |
"R_PPC_RELATIVE", /* name */ |
"R_PPC_RELATIVE", /* name */ |
712 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
713 |
0, /* src_mask */ |
0, /* src_mask */ |
714 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
715 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
716 |
|
|
717 |
/* Like R_PPC_REL24, but uses the value of the symbol within the |
/* Like R_PPC_REL24, but uses the value of the symbol within the |
718 |
object rather than the final value. Normally used for |
object rather than the final value. Normally used for |
721 |
0, /* rightshift */ |
0, /* rightshift */ |
722 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
723 |
26, /* bitsize */ |
26, /* bitsize */ |
724 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
725 |
0, /* bitpos */ |
0, /* bitpos */ |
726 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
727 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
728 |
"R_PPC_LOCAL24PC", /* name */ |
"R_PPC_LOCAL24PC", /* name */ |
729 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
730 |
0, /* src_mask */ |
0, /* src_mask */ |
731 |
0x3fffffc, /* dst_mask */ |
0x3fffffc, /* dst_mask */ |
732 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
733 |
|
|
734 |
/* Like R_PPC_ADDR32, but may be unaligned. */ |
/* Like R_PPC_ADDR32, but may be unaligned. */ |
735 |
HOWTO (R_PPC_UADDR32, /* type */ |
HOWTO (R_PPC_UADDR32, /* type */ |
736 |
0, /* rightshift */ |
0, /* rightshift */ |
737 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
738 |
32, /* bitsize */ |
32, /* bitsize */ |
739 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
740 |
0, /* bitpos */ |
0, /* bitpos */ |
741 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
742 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
743 |
"R_PPC_UADDR32", /* name */ |
"R_PPC_UADDR32", /* name */ |
744 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
745 |
0, /* src_mask */ |
0, /* src_mask */ |
746 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
747 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
748 |
|
|
749 |
/* Like R_PPC_ADDR16, but may be unaligned. */ |
/* Like R_PPC_ADDR16, but may be unaligned. */ |
750 |
HOWTO (R_PPC_UADDR16, /* type */ |
HOWTO (R_PPC_UADDR16, /* type */ |
751 |
0, /* rightshift */ |
0, /* rightshift */ |
752 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
753 |
16, /* bitsize */ |
16, /* bitsize */ |
754 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
755 |
0, /* bitpos */ |
0, /* bitpos */ |
756 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
757 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
758 |
"R_PPC_UADDR16", /* name */ |
"R_PPC_UADDR16", /* name */ |
759 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
760 |
0, /* src_mask */ |
0, /* src_mask */ |
761 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
762 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
763 |
|
|
764 |
/* 32-bit PC relative */ |
/* 32-bit PC relative */ |
765 |
HOWTO (R_PPC_REL32, /* type */ |
HOWTO (R_PPC_REL32, /* type */ |
766 |
0, /* rightshift */ |
0, /* rightshift */ |
767 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
768 |
32, /* bitsize */ |
32, /* bitsize */ |
769 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
770 |
0, /* bitpos */ |
0, /* bitpos */ |
771 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
772 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
773 |
"R_PPC_REL32", /* name */ |
"R_PPC_REL32", /* name */ |
774 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
775 |
0, /* src_mask */ |
0, /* src_mask */ |
776 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
777 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
778 |
|
|
779 |
/* 32-bit relocation to the symbol's procedure linkage table. |
/* 32-bit relocation to the symbol's procedure linkage table. |
780 |
FIXME: not supported. */ |
FIXME: not supported. */ |
782 |
0, /* rightshift */ |
0, /* rightshift */ |
783 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
784 |
32, /* bitsize */ |
32, /* bitsize */ |
785 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
786 |
0, /* bitpos */ |
0, /* bitpos */ |
787 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
788 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
789 |
"R_PPC_PLT32", /* name */ |
"R_PPC_PLT32", /* name */ |
790 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
791 |
0, /* src_mask */ |
0, /* src_mask */ |
792 |
0, /* dst_mask */ |
0, /* dst_mask */ |
793 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
794 |
|
|
795 |
/* 32-bit PC relative relocation to the symbol's procedure linkage table. |
/* 32-bit PC relative relocation to the symbol's procedure linkage table. |
796 |
FIXME: not supported. */ |
FIXME: not supported. */ |
798 |
0, /* rightshift */ |
0, /* rightshift */ |
799 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
800 |
32, /* bitsize */ |
32, /* bitsize */ |
801 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
802 |
0, /* bitpos */ |
0, /* bitpos */ |
803 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
804 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
805 |
"R_PPC_PLTREL32", /* name */ |
"R_PPC_PLTREL32", /* name */ |
806 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
807 |
0, /* src_mask */ |
0, /* src_mask */ |
808 |
0, /* dst_mask */ |
0, /* dst_mask */ |
809 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
810 |
|
|
811 |
/* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for |
/* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for |
812 |
the symbol. */ |
the symbol. */ |
814 |
0, /* rightshift */ |
0, /* rightshift */ |
815 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
816 |
16, /* bitsize */ |
16, /* bitsize */ |
817 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
818 |
0, /* bitpos */ |
0, /* bitpos */ |
819 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
820 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
821 |
"R_PPC_PLT16_LO", /* name */ |
"R_PPC_PLT16_LO", /* name */ |
822 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
823 |
0, /* src_mask */ |
0, /* src_mask */ |
824 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
825 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
826 |
|
|
827 |
/* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for |
/* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for |
828 |
the symbol. */ |
the symbol. */ |
830 |
16, /* rightshift */ |
16, /* rightshift */ |
831 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
832 |
16, /* bitsize */ |
16, /* bitsize */ |
833 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
834 |
0, /* bitpos */ |
0, /* bitpos */ |
835 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
836 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
837 |
"R_PPC_PLT16_HI", /* name */ |
"R_PPC_PLT16_HI", /* name */ |
838 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
839 |
0, /* src_mask */ |
0, /* src_mask */ |
840 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
841 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
842 |
|
|
843 |
/* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for |
/* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for |
844 |
the symbol. */ |
the symbol. */ |
846 |
16, /* rightshift */ |
16, /* rightshift */ |
847 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
848 |
16, /* bitsize */ |
16, /* bitsize */ |
849 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
850 |
0, /* bitpos */ |
0, /* bitpos */ |
851 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
852 |
ppc_elf_addr16_ha_reloc, /* special_function */ |
ppc_elf_addr16_ha_reloc, /* special_function */ |
853 |
"R_PPC_PLT16_HA", /* name */ |
"R_PPC_PLT16_HA", /* name */ |
854 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
855 |
0, /* src_mask */ |
0, /* src_mask */ |
856 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
857 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
858 |
|
|
859 |
/* A sign-extended 16 bit value relative to _SDA_BASE_, for use with |
/* A sign-extended 16 bit value relative to _SDA_BASE_, for use with |
860 |
small data items. */ |
small data items. */ |
862 |
0, /* rightshift */ |
0, /* rightshift */ |
863 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
864 |
16, /* bitsize */ |
16, /* bitsize */ |
865 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
866 |
0, /* bitpos */ |
0, /* bitpos */ |
867 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
868 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
869 |
"R_PPC_SDAREL16", /* name */ |
"R_PPC_SDAREL16", /* name */ |
870 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
871 |
0, /* src_mask */ |
0, /* src_mask */ |
872 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
873 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
874 |
|
|
875 |
/* 16-bit section relative relocation. */ |
/* 16-bit section relative relocation. */ |
876 |
HOWTO (R_PPC_SECTOFF, /* type */ |
HOWTO (R_PPC_SECTOFF, /* type */ |
877 |
0, /* rightshift */ |
0, /* rightshift */ |
878 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
879 |
16, /* bitsize */ |
16, /* bitsize */ |
880 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
881 |
0, /* bitpos */ |
0, /* bitpos */ |
882 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
883 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
884 |
"R_PPC_SECTOFF", /* name */ |
"R_PPC_SECTOFF", /* name */ |
885 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
886 |
0, /* src_mask */ |
0, /* src_mask */ |
887 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
888 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
889 |
|
|
890 |
/* 16-bit lower half section relative relocation. */ |
/* 16-bit lower half section relative relocation. */ |
891 |
HOWTO (R_PPC_SECTOFF_LO, /* type */ |
HOWTO (R_PPC_SECTOFF_LO, /* type */ |
892 |
0, /* rightshift */ |
0, /* rightshift */ |
893 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
894 |
16, /* bitsize */ |
16, /* bitsize */ |
895 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
896 |
0, /* bitpos */ |
0, /* bitpos */ |
897 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
898 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
899 |
"R_PPC_SECTOFF_LO", /* name */ |
"R_PPC_SECTOFF_LO", /* name */ |
900 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
901 |
0, /* src_mask */ |
0, /* src_mask */ |
902 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
903 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
904 |
|
|
905 |
/* 16-bit upper half section relative relocation. */ |
/* 16-bit upper half section relative relocation. */ |
906 |
HOWTO (R_PPC_SECTOFF_HI, /* type */ |
HOWTO (R_PPC_SECTOFF_HI, /* type */ |
907 |
16, /* rightshift */ |
16, /* rightshift */ |
908 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
909 |
16, /* bitsize */ |
16, /* bitsize */ |
910 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
911 |
0, /* bitpos */ |
0, /* bitpos */ |
912 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
913 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
914 |
"R_PPC_SECTOFF_HI", /* name */ |
"R_PPC_SECTOFF_HI", /* name */ |
915 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
916 |
0, /* src_mask */ |
0, /* src_mask */ |
917 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
918 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
919 |
|
|
920 |
/* 16-bit upper half adjusted section relative relocation. */ |
/* 16-bit upper half adjusted section relative relocation. */ |
921 |
HOWTO (R_PPC_SECTOFF_HA, /* type */ |
HOWTO (R_PPC_SECTOFF_HA, /* type */ |
922 |
16, /* rightshift */ |
16, /* rightshift */ |
923 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
924 |
16, /* bitsize */ |
16, /* bitsize */ |
925 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
926 |
0, /* bitpos */ |
0, /* bitpos */ |
927 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
928 |
ppc_elf_addr16_ha_reloc, /* special_function */ |
ppc_elf_addr16_ha_reloc, /* special_function */ |
929 |
"R_PPC_SECTOFF_HA", /* name */ |
"R_PPC_SECTOFF_HA", /* name */ |
930 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
931 |
|
0, /* src_mask */ |
932 |
|
0xffff, /* dst_mask */ |
933 |
|
FALSE), /* pcrel_offset */ |
934 |
|
|
935 |
|
/* Marker reloc for TLS. */ |
936 |
|
HOWTO (R_PPC_TLS, |
937 |
|
0, /* rightshift */ |
938 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
939 |
|
32, /* bitsize */ |
940 |
|
FALSE, /* pc_relative */ |
941 |
|
0, /* bitpos */ |
942 |
|
complain_overflow_dont, /* complain_on_overflow */ |
943 |
|
bfd_elf_generic_reloc, /* special_function */ |
944 |
|
"R_PPC_TLS", /* name */ |
945 |
|
FALSE, /* partial_inplace */ |
946 |
|
0, /* src_mask */ |
947 |
|
0, /* dst_mask */ |
948 |
|
FALSE), /* pcrel_offset */ |
949 |
|
|
950 |
|
/* Computes the load module index of the load module that contains the |
951 |
|
definition of its TLS sym. */ |
952 |
|
HOWTO (R_PPC_DTPMOD32, |
953 |
|
0, /* rightshift */ |
954 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
955 |
|
32, /* bitsize */ |
956 |
|
FALSE, /* pc_relative */ |
957 |
|
0, /* bitpos */ |
958 |
|
complain_overflow_dont, /* complain_on_overflow */ |
959 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
960 |
|
"R_PPC_DTPMOD32", /* name */ |
961 |
|
FALSE, /* partial_inplace */ |
962 |
|
0, /* src_mask */ |
963 |
|
0xffffffff, /* dst_mask */ |
964 |
|
FALSE), /* pcrel_offset */ |
965 |
|
|
966 |
|
/* Computes a dtv-relative displacement, the difference between the value |
967 |
|
of sym+add and the base address of the thread-local storage block that |
968 |
|
contains the definition of sym, minus 0x8000. */ |
969 |
|
HOWTO (R_PPC_DTPREL32, |
970 |
|
0, /* rightshift */ |
971 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
972 |
|
32, /* bitsize */ |
973 |
|
FALSE, /* pc_relative */ |
974 |
|
0, /* bitpos */ |
975 |
|
complain_overflow_dont, /* complain_on_overflow */ |
976 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
977 |
|
"R_PPC_DTPREL32", /* name */ |
978 |
|
FALSE, /* partial_inplace */ |
979 |
|
0, /* src_mask */ |
980 |
|
0xffffffff, /* dst_mask */ |
981 |
|
FALSE), /* pcrel_offset */ |
982 |
|
|
983 |
|
/* A 16 bit dtprel reloc. */ |
984 |
|
HOWTO (R_PPC_DTPREL16, |
985 |
|
0, /* rightshift */ |
986 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
987 |
|
16, /* bitsize */ |
988 |
|
FALSE, /* pc_relative */ |
989 |
|
0, /* bitpos */ |
990 |
|
complain_overflow_signed, /* complain_on_overflow */ |
991 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
992 |
|
"R_PPC_DTPREL16", /* name */ |
993 |
|
FALSE, /* partial_inplace */ |
994 |
|
0, /* src_mask */ |
995 |
|
0xffff, /* dst_mask */ |
996 |
|
FALSE), /* pcrel_offset */ |
997 |
|
|
998 |
|
/* Like DTPREL16, but no overflow. */ |
999 |
|
HOWTO (R_PPC_DTPREL16_LO, |
1000 |
|
0, /* rightshift */ |
1001 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1002 |
|
16, /* bitsize */ |
1003 |
|
FALSE, /* pc_relative */ |
1004 |
|
0, /* bitpos */ |
1005 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1006 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1007 |
|
"R_PPC_DTPREL16_LO", /* name */ |
1008 |
|
FALSE, /* partial_inplace */ |
1009 |
|
0, /* src_mask */ |
1010 |
|
0xffff, /* dst_mask */ |
1011 |
|
FALSE), /* pcrel_offset */ |
1012 |
|
|
1013 |
|
/* Like DTPREL16_LO, but next higher group of 16 bits. */ |
1014 |
|
HOWTO (R_PPC_DTPREL16_HI, |
1015 |
|
16, /* rightshift */ |
1016 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1017 |
|
16, /* bitsize */ |
1018 |
|
FALSE, /* pc_relative */ |
1019 |
|
0, /* bitpos */ |
1020 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1021 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1022 |
|
"R_PPC_DTPREL16_HI", /* name */ |
1023 |
|
FALSE, /* partial_inplace */ |
1024 |
|
0, /* src_mask */ |
1025 |
|
0xffff, /* dst_mask */ |
1026 |
|
FALSE), /* pcrel_offset */ |
1027 |
|
|
1028 |
|
/* Like DTPREL16_HI, but adjust for low 16 bits. */ |
1029 |
|
HOWTO (R_PPC_DTPREL16_HA, |
1030 |
|
16, /* rightshift */ |
1031 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1032 |
|
16, /* bitsize */ |
1033 |
|
FALSE, /* pc_relative */ |
1034 |
|
0, /* bitpos */ |
1035 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1036 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1037 |
|
"R_PPC_DTPREL16_HA", /* name */ |
1038 |
|
FALSE, /* partial_inplace */ |
1039 |
|
0, /* src_mask */ |
1040 |
|
0xffff, /* dst_mask */ |
1041 |
|
FALSE), /* pcrel_offset */ |
1042 |
|
|
1043 |
|
/* Computes a tp-relative displacement, the difference between the value of |
1044 |
|
sym+add and the value of the thread pointer (r13). */ |
1045 |
|
HOWTO (R_PPC_TPREL32, |
1046 |
|
0, /* rightshift */ |
1047 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
1048 |
|
32, /* bitsize */ |
1049 |
|
FALSE, /* pc_relative */ |
1050 |
|
0, /* bitpos */ |
1051 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1052 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1053 |
|
"R_PPC_TPREL32", /* name */ |
1054 |
|
FALSE, /* partial_inplace */ |
1055 |
|
0, /* src_mask */ |
1056 |
|
0xffffffff, /* dst_mask */ |
1057 |
|
FALSE), /* pcrel_offset */ |
1058 |
|
|
1059 |
|
/* A 16 bit tprel reloc. */ |
1060 |
|
HOWTO (R_PPC_TPREL16, |
1061 |
|
0, /* rightshift */ |
1062 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1063 |
|
16, /* bitsize */ |
1064 |
|
FALSE, /* pc_relative */ |
1065 |
|
0, /* bitpos */ |
1066 |
|
complain_overflow_signed, /* complain_on_overflow */ |
1067 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1068 |
|
"R_PPC_TPREL16", /* name */ |
1069 |
|
FALSE, /* partial_inplace */ |
1070 |
|
0, /* src_mask */ |
1071 |
|
0xffff, /* dst_mask */ |
1072 |
|
FALSE), /* pcrel_offset */ |
1073 |
|
|
1074 |
|
/* Like TPREL16, but no overflow. */ |
1075 |
|
HOWTO (R_PPC_TPREL16_LO, |
1076 |
|
0, /* rightshift */ |
1077 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1078 |
|
16, /* bitsize */ |
1079 |
|
FALSE, /* pc_relative */ |
1080 |
|
0, /* bitpos */ |
1081 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1082 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1083 |
|
"R_PPC_TPREL16_LO", /* name */ |
1084 |
|
FALSE, /* partial_inplace */ |
1085 |
|
0, /* src_mask */ |
1086 |
|
0xffff, /* dst_mask */ |
1087 |
|
FALSE), /* pcrel_offset */ |
1088 |
|
|
1089 |
|
/* Like TPREL16_LO, but next higher group of 16 bits. */ |
1090 |
|
HOWTO (R_PPC_TPREL16_HI, |
1091 |
|
16, /* rightshift */ |
1092 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1093 |
|
16, /* bitsize */ |
1094 |
|
FALSE, /* pc_relative */ |
1095 |
|
0, /* bitpos */ |
1096 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1097 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1098 |
|
"R_PPC_TPREL16_HI", /* name */ |
1099 |
|
FALSE, /* partial_inplace */ |
1100 |
|
0, /* src_mask */ |
1101 |
|
0xffff, /* dst_mask */ |
1102 |
|
FALSE), /* pcrel_offset */ |
1103 |
|
|
1104 |
|
/* Like TPREL16_HI, but adjust for low 16 bits. */ |
1105 |
|
HOWTO (R_PPC_TPREL16_HA, |
1106 |
|
16, /* rightshift */ |
1107 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1108 |
|
16, /* bitsize */ |
1109 |
|
FALSE, /* pc_relative */ |
1110 |
|
0, /* bitpos */ |
1111 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1112 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1113 |
|
"R_PPC_TPREL16_HA", /* name */ |
1114 |
|
FALSE, /* partial_inplace */ |
1115 |
|
0, /* src_mask */ |
1116 |
|
0xffff, /* dst_mask */ |
1117 |
|
FALSE), /* pcrel_offset */ |
1118 |
|
|
1119 |
|
/* Allocates two contiguous entries in the GOT to hold a tls_index structure, |
1120 |
|
with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset |
1121 |
|
to the first entry. */ |
1122 |
|
HOWTO (R_PPC_GOT_TLSGD16, |
1123 |
|
0, /* rightshift */ |
1124 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1125 |
|
16, /* bitsize */ |
1126 |
|
FALSE, /* pc_relative */ |
1127 |
|
0, /* bitpos */ |
1128 |
|
complain_overflow_signed, /* complain_on_overflow */ |
1129 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1130 |
|
"R_PPC_GOT_TLSGD16", /* name */ |
1131 |
|
FALSE, /* partial_inplace */ |
1132 |
|
0, /* src_mask */ |
1133 |
|
0xffff, /* dst_mask */ |
1134 |
|
FALSE), /* pcrel_offset */ |
1135 |
|
|
1136 |
|
/* Like GOT_TLSGD16, but no overflow. */ |
1137 |
|
HOWTO (R_PPC_GOT_TLSGD16_LO, |
1138 |
|
0, /* rightshift */ |
1139 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1140 |
|
16, /* bitsize */ |
1141 |
|
FALSE, /* pc_relative */ |
1142 |
|
0, /* bitpos */ |
1143 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1144 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1145 |
|
"R_PPC_GOT_TLSGD16_LO", /* name */ |
1146 |
|
FALSE, /* partial_inplace */ |
1147 |
|
0, /* src_mask */ |
1148 |
|
0xffff, /* dst_mask */ |
1149 |
|
FALSE), /* pcrel_offset */ |
1150 |
|
|
1151 |
|
/* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ |
1152 |
|
HOWTO (R_PPC_GOT_TLSGD16_HI, |
1153 |
|
16, /* rightshift */ |
1154 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1155 |
|
16, /* bitsize */ |
1156 |
|
FALSE, /* pc_relative */ |
1157 |
|
0, /* bitpos */ |
1158 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1159 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1160 |
|
"R_PPC_GOT_TLSGD16_HI", /* name */ |
1161 |
|
FALSE, /* partial_inplace */ |
1162 |
|
0, /* src_mask */ |
1163 |
|
0xffff, /* dst_mask */ |
1164 |
|
FALSE), /* pcrel_offset */ |
1165 |
|
|
1166 |
|
/* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ |
1167 |
|
HOWTO (R_PPC_GOT_TLSGD16_HA, |
1168 |
|
16, /* rightshift */ |
1169 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1170 |
|
16, /* bitsize */ |
1171 |
|
FALSE, /* pc_relative */ |
1172 |
|
0, /* bitpos */ |
1173 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1174 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1175 |
|
"R_PPC_GOT_TLSGD16_HA", /* name */ |
1176 |
|
FALSE, /* partial_inplace */ |
1177 |
|
0, /* src_mask */ |
1178 |
|
0xffff, /* dst_mask */ |
1179 |
|
FALSE), /* pcrel_offset */ |
1180 |
|
|
1181 |
|
/* Allocates two contiguous entries in the GOT to hold a tls_index structure, |
1182 |
|
with values (sym+add)@dtpmod and zero, and computes the offset to the |
1183 |
|
first entry. */ |
1184 |
|
HOWTO (R_PPC_GOT_TLSLD16, |
1185 |
|
0, /* rightshift */ |
1186 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1187 |
|
16, /* bitsize */ |
1188 |
|
FALSE, /* pc_relative */ |
1189 |
|
0, /* bitpos */ |
1190 |
|
complain_overflow_signed, /* complain_on_overflow */ |
1191 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1192 |
|
"R_PPC_GOT_TLSLD16", /* name */ |
1193 |
|
FALSE, /* partial_inplace */ |
1194 |
|
0, /* src_mask */ |
1195 |
|
0xffff, /* dst_mask */ |
1196 |
|
FALSE), /* pcrel_offset */ |
1197 |
|
|
1198 |
|
/* Like GOT_TLSLD16, but no overflow. */ |
1199 |
|
HOWTO (R_PPC_GOT_TLSLD16_LO, |
1200 |
|
0, /* rightshift */ |
1201 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1202 |
|
16, /* bitsize */ |
1203 |
|
FALSE, /* pc_relative */ |
1204 |
|
0, /* bitpos */ |
1205 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1206 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1207 |
|
"R_PPC_GOT_TLSLD16_LO", /* name */ |
1208 |
|
FALSE, /* partial_inplace */ |
1209 |
|
0, /* src_mask */ |
1210 |
|
0xffff, /* dst_mask */ |
1211 |
|
FALSE), /* pcrel_offset */ |
1212 |
|
|
1213 |
|
/* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ |
1214 |
|
HOWTO (R_PPC_GOT_TLSLD16_HI, |
1215 |
|
16, /* rightshift */ |
1216 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1217 |
|
16, /* bitsize */ |
1218 |
|
FALSE, /* pc_relative */ |
1219 |
|
0, /* bitpos */ |
1220 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1221 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1222 |
|
"R_PPC_GOT_TLSLD16_HI", /* name */ |
1223 |
|
FALSE, /* partial_inplace */ |
1224 |
|
0, /* src_mask */ |
1225 |
|
0xffff, /* dst_mask */ |
1226 |
|
FALSE), /* pcrel_offset */ |
1227 |
|
|
1228 |
|
/* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ |
1229 |
|
HOWTO (R_PPC_GOT_TLSLD16_HA, |
1230 |
|
16, /* rightshift */ |
1231 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1232 |
|
16, /* bitsize */ |
1233 |
|
FALSE, /* pc_relative */ |
1234 |
|
0, /* bitpos */ |
1235 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1236 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1237 |
|
"R_PPC_GOT_TLSLD16_HA", /* name */ |
1238 |
|
FALSE, /* partial_inplace */ |
1239 |
|
0, /* src_mask */ |
1240 |
|
0xffff, /* dst_mask */ |
1241 |
|
FALSE), /* pcrel_offset */ |
1242 |
|
|
1243 |
|
/* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes |
1244 |
|
the offset to the entry. */ |
1245 |
|
HOWTO (R_PPC_GOT_DTPREL16, |
1246 |
|
0, /* rightshift */ |
1247 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1248 |
|
16, /* bitsize */ |
1249 |
|
FALSE, /* pc_relative */ |
1250 |
|
0, /* bitpos */ |
1251 |
|
complain_overflow_signed, /* complain_on_overflow */ |
1252 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1253 |
|
"R_PPC_GOT_DTPREL16", /* name */ |
1254 |
|
FALSE, /* partial_inplace */ |
1255 |
|
0, /* src_mask */ |
1256 |
|
0xffff, /* dst_mask */ |
1257 |
|
FALSE), /* pcrel_offset */ |
1258 |
|
|
1259 |
|
/* Like GOT_DTPREL16, but no overflow. */ |
1260 |
|
HOWTO (R_PPC_GOT_DTPREL16_LO, |
1261 |
|
0, /* rightshift */ |
1262 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1263 |
|
16, /* bitsize */ |
1264 |
|
FALSE, /* pc_relative */ |
1265 |
|
0, /* bitpos */ |
1266 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1267 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1268 |
|
"R_PPC_GOT_DTPREL16_LO", /* name */ |
1269 |
|
FALSE, /* partial_inplace */ |
1270 |
|
0, /* src_mask */ |
1271 |
|
0xffff, /* dst_mask */ |
1272 |
|
FALSE), /* pcrel_offset */ |
1273 |
|
|
1274 |
|
/* Like GOT_DTPREL16_LO, but next higher group of 16 bits. */ |
1275 |
|
HOWTO (R_PPC_GOT_DTPREL16_HI, |
1276 |
|
16, /* rightshift */ |
1277 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1278 |
|
16, /* bitsize */ |
1279 |
|
FALSE, /* pc_relative */ |
1280 |
|
0, /* bitpos */ |
1281 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1282 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1283 |
|
"R_PPC_GOT_DTPREL16_HI", /* name */ |
1284 |
|
FALSE, /* partial_inplace */ |
1285 |
|
0, /* src_mask */ |
1286 |
|
0xffff, /* dst_mask */ |
1287 |
|
FALSE), /* pcrel_offset */ |
1288 |
|
|
1289 |
|
/* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ |
1290 |
|
HOWTO (R_PPC_GOT_DTPREL16_HA, |
1291 |
|
16, /* rightshift */ |
1292 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1293 |
|
16, /* bitsize */ |
1294 |
|
FALSE, /* pc_relative */ |
1295 |
|
0, /* bitpos */ |
1296 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1297 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1298 |
|
"R_PPC_GOT_DTPREL16_HA", /* name */ |
1299 |
|
FALSE, /* partial_inplace */ |
1300 |
|
0, /* src_mask */ |
1301 |
|
0xffff, /* dst_mask */ |
1302 |
|
FALSE), /* pcrel_offset */ |
1303 |
|
|
1304 |
|
/* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the |
1305 |
|
offset to the entry. */ |
1306 |
|
HOWTO (R_PPC_GOT_TPREL16, |
1307 |
|
0, /* rightshift */ |
1308 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1309 |
|
16, /* bitsize */ |
1310 |
|
FALSE, /* pc_relative */ |
1311 |
|
0, /* bitpos */ |
1312 |
|
complain_overflow_signed, /* complain_on_overflow */ |
1313 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1314 |
|
"R_PPC_GOT_TPREL16", /* name */ |
1315 |
|
FALSE, /* partial_inplace */ |
1316 |
|
0, /* src_mask */ |
1317 |
|
0xffff, /* dst_mask */ |
1318 |
|
FALSE), /* pcrel_offset */ |
1319 |
|
|
1320 |
|
/* Like GOT_TPREL16, but no overflow. */ |
1321 |
|
HOWTO (R_PPC_GOT_TPREL16_LO, |
1322 |
|
0, /* rightshift */ |
1323 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1324 |
|
16, /* bitsize */ |
1325 |
|
FALSE, /* pc_relative */ |
1326 |
|
0, /* bitpos */ |
1327 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1328 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1329 |
|
"R_PPC_GOT_TPREL16_LO", /* name */ |
1330 |
|
FALSE, /* partial_inplace */ |
1331 |
|
0, /* src_mask */ |
1332 |
|
0xffff, /* dst_mask */ |
1333 |
|
FALSE), /* pcrel_offset */ |
1334 |
|
|
1335 |
|
/* Like GOT_TPREL16_LO, but next higher group of 16 bits. */ |
1336 |
|
HOWTO (R_PPC_GOT_TPREL16_HI, |
1337 |
|
16, /* rightshift */ |
1338 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1339 |
|
16, /* bitsize */ |
1340 |
|
FALSE, /* pc_relative */ |
1341 |
|
0, /* bitpos */ |
1342 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1343 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1344 |
|
"R_PPC_GOT_TPREL16_HI", /* name */ |
1345 |
|
FALSE, /* partial_inplace */ |
1346 |
|
0, /* src_mask */ |
1347 |
|
0xffff, /* dst_mask */ |
1348 |
|
FALSE), /* pcrel_offset */ |
1349 |
|
|
1350 |
|
/* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ |
1351 |
|
HOWTO (R_PPC_GOT_TPREL16_HA, |
1352 |
|
16, /* rightshift */ |
1353 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1354 |
|
16, /* bitsize */ |
1355 |
|
FALSE, /* pc_relative */ |
1356 |
|
0, /* bitpos */ |
1357 |
|
complain_overflow_dont, /* complain_on_overflow */ |
1358 |
|
ppc_elf_unhandled_reloc, /* special_function */ |
1359 |
|
"R_PPC_GOT_TPREL16_HA", /* name */ |
1360 |
|
FALSE, /* partial_inplace */ |
1361 |
0, /* src_mask */ |
0, /* src_mask */ |
1362 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1363 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1364 |
|
|
1365 |
/* The remaining relocs are from the Embedded ELF ABI, and are not |
/* The remaining relocs are from the Embedded ELF ABI, and are not |
1366 |
in the SVR4 ELF ABI. */ |
in the SVR4 ELF ABI. */ |
1367 |
|
|
1368 |
/* 32 bit value resulting from the addend minus the symbol */ |
/* 32 bit value resulting from the addend minus the symbol. */ |
1369 |
HOWTO (R_PPC_EMB_NADDR32, /* type */ |
HOWTO (R_PPC_EMB_NADDR32, /* type */ |
1370 |
0, /* rightshift */ |
0, /* rightshift */ |
1371 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
1372 |
32, /* bitsize */ |
32, /* bitsize */ |
1373 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1374 |
0, /* bitpos */ |
0, /* bitpos */ |
1375 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
1376 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1377 |
"R_PPC_EMB_NADDR32", /* name */ |
"R_PPC_EMB_NADDR32", /* name */ |
1378 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1379 |
0, /* src_mask */ |
0, /* src_mask */ |
1380 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
1381 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1382 |
|
|
1383 |
/* 16 bit value resulting from the addend minus the symbol */ |
/* 16 bit value resulting from the addend minus the symbol. */ |
1384 |
HOWTO (R_PPC_EMB_NADDR16, /* type */ |
HOWTO (R_PPC_EMB_NADDR16, /* type */ |
1385 |
0, /* rightshift */ |
0, /* rightshift */ |
1386 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1387 |
16, /* bitsize */ |
16, /* bitsize */ |
1388 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1389 |
0, /* bitpos */ |
0, /* bitpos */ |
1390 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
1391 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1392 |
"R_PPC_EMB_NADDR16", /* name */ |
"R_PPC_EMB_NADDR16", /* name */ |
1393 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1394 |
0, /* src_mask */ |
0, /* src_mask */ |
1395 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1396 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1397 |
|
|
1398 |
/* 16 bit value resulting from the addend minus the symbol */ |
/* 16 bit value resulting from the addend minus the symbol. */ |
1399 |
HOWTO (R_PPC_EMB_NADDR16_LO, /* type */ |
HOWTO (R_PPC_EMB_NADDR16_LO, /* type */ |
1400 |
0, /* rightshift */ |
0, /* rightshift */ |
1401 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1402 |
16, /* bitsize */ |
16, /* bitsize */ |
1403 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1404 |
0, /* bitpos */ |
0, /* bitpos */ |
1405 |
complain_overflow_dont,/* complain_on_overflow */ |
complain_overflow_dont,/* complain_on_overflow */ |
1406 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1407 |
"R_PPC_EMB_ADDR16_LO", /* name */ |
"R_PPC_EMB_ADDR16_LO", /* name */ |
1408 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1409 |
0, /* src_mask */ |
0, /* src_mask */ |
1410 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1411 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1412 |
|
|
1413 |
/* The high order 16 bits of the addend minus the symbol */ |
/* The high order 16 bits of the addend minus the symbol. */ |
1414 |
HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ |
HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ |
1415 |
16, /* rightshift */ |
16, /* rightshift */ |
1416 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1417 |
16, /* bitsize */ |
16, /* bitsize */ |
1418 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1419 |
0, /* bitpos */ |
0, /* bitpos */ |
1420 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
1421 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1422 |
"R_PPC_EMB_NADDR16_HI", /* name */ |
"R_PPC_EMB_NADDR16_HI", /* name */ |
1423 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1424 |
0, /* src_mask */ |
0, /* src_mask */ |
1425 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1426 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1427 |
|
|
1428 |
/* The high order 16 bits of the result of the addend minus the address, |
/* The high order 16 bits of the result of the addend minus the address, |
1429 |
plus 1 if the contents of the low 16 bits, treated as a signed number, |
plus 1 if the contents of the low 16 bits, treated as a signed number, |
1432 |
16, /* rightshift */ |
16, /* rightshift */ |
1433 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1434 |
16, /* bitsize */ |
16, /* bitsize */ |
1435 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1436 |
0, /* bitpos */ |
0, /* bitpos */ |
1437 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
1438 |
ppc_elf_addr16_ha_reloc, /* special_function */ |
ppc_elf_addr16_ha_reloc, /* special_function */ |
1439 |
"R_PPC_EMB_NADDR16_HA", /* name */ |
"R_PPC_EMB_NADDR16_HA", /* name */ |
1440 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1441 |
0, /* src_mask */ |
0, /* src_mask */ |
1442 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1443 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1444 |
|
|
1445 |
/* 16 bit value resulting from allocating a 4 byte word to hold an |
/* 16 bit value resulting from allocating a 4 byte word to hold an |
1446 |
address in the .sdata section, and returning the offset from |
address in the .sdata section, and returning the offset from |
1447 |
_SDA_BASE_ for that relocation */ |
_SDA_BASE_ for that relocation. */ |
1448 |
HOWTO (R_PPC_EMB_SDAI16, /* type */ |
HOWTO (R_PPC_EMB_SDAI16, /* type */ |
1449 |
0, /* rightshift */ |
0, /* rightshift */ |
1450 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1451 |
16, /* bitsize */ |
16, /* bitsize */ |
1452 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1453 |
0, /* bitpos */ |
0, /* bitpos */ |
1454 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
1455 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1456 |
"R_PPC_EMB_SDAI16", /* name */ |
"R_PPC_EMB_SDAI16", /* name */ |
1457 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1458 |
0, /* src_mask */ |
0, /* src_mask */ |
1459 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1460 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1461 |
|
|
1462 |
/* 16 bit value resulting from allocating a 4 byte word to hold an |
/* 16 bit value resulting from allocating a 4 byte word to hold an |
1463 |
address in the .sdata2 section, and returning the offset from |
address in the .sdata2 section, and returning the offset from |
1464 |
_SDA2_BASE_ for that relocation */ |
_SDA2_BASE_ for that relocation. */ |
1465 |
HOWTO (R_PPC_EMB_SDA2I16, /* type */ |
HOWTO (R_PPC_EMB_SDA2I16, /* type */ |
1466 |
0, /* rightshift */ |
0, /* rightshift */ |
1467 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1468 |
16, /* bitsize */ |
16, /* bitsize */ |
1469 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1470 |
0, /* bitpos */ |
0, /* bitpos */ |
1471 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
1472 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1473 |
"R_PPC_EMB_SDA2I16", /* name */ |
"R_PPC_EMB_SDA2I16", /* name */ |
1474 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1475 |
0, /* src_mask */ |
0, /* src_mask */ |
1476 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1477 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1478 |
|
|
1479 |
/* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with |
/* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with |
1480 |
small data items. */ |
small data items. */ |
1482 |
0, /* rightshift */ |
0, /* rightshift */ |
1483 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1484 |
16, /* bitsize */ |
16, /* bitsize */ |
1485 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1486 |
0, /* bitpos */ |
0, /* bitpos */ |
1487 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
1488 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1489 |
"R_PPC_EMB_SDA2REL", /* name */ |
"R_PPC_EMB_SDA2REL", /* name */ |
1490 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1491 |
0, /* src_mask */ |
0, /* src_mask */ |
1492 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1493 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1494 |
|
|
1495 |
/* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit |
/* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit |
1496 |
signed offset from the appropriate base, and filling in the register |
signed offset from the appropriate base, and filling in the register |
1499 |
0, /* rightshift */ |
0, /* rightshift */ |
1500 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
1501 |
16, /* bitsize */ |
16, /* bitsize */ |
1502 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1503 |
0, /* bitpos */ |
0, /* bitpos */ |
1504 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
1505 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1506 |
"R_PPC_EMB_SDA21", /* name */ |
"R_PPC_EMB_SDA21", /* name */ |
1507 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1508 |
0, /* src_mask */ |
0, /* src_mask */ |
1509 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1510 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1511 |
|
|
1512 |
/* Relocation not handled: R_PPC_EMB_MRKREF */ |
/* Relocation not handled: R_PPC_EMB_MRKREF */ |
1513 |
/* Relocation not handled: R_PPC_EMB_RELSEC16 */ |
/* Relocation not handled: R_PPC_EMB_RELSEC16 */ |
1523 |
0, /* rightshift */ |
0, /* rightshift */ |
1524 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1525 |
16, /* bitsize */ |
16, /* bitsize */ |
1526 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
1527 |
0, /* bitpos */ |
0, /* bitpos */ |
1528 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
1529 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1530 |
"R_PPC_EMB_RELSDA", /* name */ |
"R_PPC_EMB_RELSDA", /* name */ |
1531 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1532 |
0, /* src_mask */ |
0, /* src_mask */ |
1533 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1534 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1535 |
|
|
1536 |
/* GNU extension to record C++ vtable hierarchy */ |
/* GNU extension to record C++ vtable hierarchy. */ |
1537 |
HOWTO (R_PPC_GNU_VTINHERIT, /* type */ |
HOWTO (R_PPC_GNU_VTINHERIT, /* type */ |
1538 |
0, /* rightshift */ |
0, /* rightshift */ |
1539 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
1540 |
0, /* bitsize */ |
0, /* bitsize */ |
1541 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1542 |
0, /* bitpos */ |
0, /* bitpos */ |
1543 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
1544 |
NULL, /* special_function */ |
NULL, /* special_function */ |
1545 |
"R_PPC_GNU_VTINHERIT", /* name */ |
"R_PPC_GNU_VTINHERIT", /* name */ |
1546 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1547 |
0, /* src_mask */ |
0, /* src_mask */ |
1548 |
0, /* dst_mask */ |
0, /* dst_mask */ |
1549 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1550 |
|
|
1551 |
/* GNU extension to record C++ vtable member usage */ |
/* GNU extension to record C++ vtable member usage. */ |
1552 |
HOWTO (R_PPC_GNU_VTENTRY, /* type */ |
HOWTO (R_PPC_GNU_VTENTRY, /* type */ |
1553 |
0, /* rightshift */ |
0, /* rightshift */ |
1554 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
1555 |
0, /* bitsize */ |
0, /* bitsize */ |
1556 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1557 |
0, /* bitpos */ |
0, /* bitpos */ |
1558 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
1559 |
NULL, /* special_function */ |
NULL, /* special_function */ |
1560 |
"R_PPC_GNU_VTENTRY", /* name */ |
"R_PPC_GNU_VTENTRY", /* name */ |
1561 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1562 |
0, /* src_mask */ |
0, /* src_mask */ |
1563 |
0, /* dst_mask */ |
0, /* dst_mask */ |
1564 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1565 |
|
|
1566 |
/* Phony reloc to handle AIX style TOC entries */ |
/* Phony reloc to handle AIX style TOC entries. */ |
1567 |
HOWTO (R_PPC_TOC16, /* type */ |
HOWTO (R_PPC_TOC16, /* type */ |
1568 |
0, /* rightshift */ |
0, /* rightshift */ |
1569 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1570 |
16, /* bitsize */ |
16, /* bitsize */ |
1571 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
1572 |
0, /* bitpos */ |
0, /* bitpos */ |
1573 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
1574 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
1575 |
"R_PPC_TOC16", /* name */ |
"R_PPC_TOC16", /* name */ |
1576 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
1577 |
0, /* src_mask */ |
0, /* src_mask */ |
1578 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
1579 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
1580 |
}; |
}; |
1581 |
|
|
1582 |
/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */ |
/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */ |
1583 |
|
|
1584 |
static void |
static void |
1585 |
ppc_elf_howto_init () |
ppc_elf_howto_init (void) |
1586 |
{ |
{ |
1587 |
unsigned int i, type; |
unsigned int i, type; |
1588 |
|
|
1589 |
for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++) |
for (i = 0; |
1590 |
|
i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); |
1591 |
|
i++) |
1592 |
{ |
{ |
1593 |
type = ppc_elf_howto_raw[i].type; |
type = ppc_elf_howto_raw[i].type; |
1594 |
BFD_ASSERT (type < sizeof (ppc_elf_howto_table) / sizeof (ppc_elf_howto_table[0])); |
if (type >= (sizeof (ppc_elf_howto_table) |
1595 |
|
/ sizeof (ppc_elf_howto_table[0]))) |
1596 |
|
abort (); |
1597 |
ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i]; |
ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i]; |
1598 |
} |
} |
1599 |
} |
} |
1600 |
|
|
1601 |
/* This function handles relaxing for the PPC with option --mpc860c0[=<n>]. |
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) |
|
|
|
|
The MPC860, revision C0 or earlier contains a bug in the die. |
|
|
If all of the following conditions are true, the next instruction |
|
|
to be executed *may* be treated as a no-op. |
|
|
1/ A forward branch is executed. |
|
|
2/ The branch is predicted as not taken. |
|
|
3/ The branch is taken. |
|
|
4/ The branch is located in the last 5 words of a page. |
|
|
(The EOP limit is 5 by default but may be specified as any value from 1-10.) |
|
|
|
|
|
Our software solution is to detect these problematic branches in a |
|
|
linker pass and modify them as follows: |
|
|
1/ Unconditional branches - Since these are always predicted taken, |
|
|
there is no problem and no action is required. |
|
|
2/ Conditional backward branches - No problem, no action required. |
|
|
3/ Conditional forward branches - Ensure that the "inverse prediction |
|
|
bit" is set (ensure it is predicted taken). |
|
|
4/ Conditional register branches - Ensure that the "y bit" is set |
|
|
(ensure it is predicted taken). |
|
|
*/ |
|
1602 |
|
|
1603 |
/* Sort sections by address. */ |
static const int shared_stub_entry[] = |
1604 |
|
{ |
1605 |
|
0x7c0802a6, /* mflr 0 */ |
1606 |
|
0x429f0005, /* bcl 20, 31, .Lxxx */ |
1607 |
|
0x7d6802a6, /* mflr 11 */ |
1608 |
|
0x3d6b0000, /* addis 11, 11, (xxx-.Lxxx)@ha */ |
1609 |
|
0x396b0018, /* addi 11, 11, (xxx-.Lxxx)@l */ |
1610 |
|
0x7c0803a6, /* mtlr 0 */ |
1611 |
|
0x7d6903a6, /* mtctr 11 */ |
1612 |
|
0x4e800420, /* bctr */ |
1613 |
|
}; |
1614 |
|
|
1615 |
static int |
static const int stub_entry[] = |
1616 |
ppc_elf_sort_rela (arg1, arg2) |
{ |
1617 |
const PTR arg1; |
0x3d600000, /* lis 11,xxx@ha */ |
1618 |
const PTR arg2; |
0x396b0000, /* addi 11,11,xxx@l */ |
1619 |
{ |
0x7d6903a6, /* mtctr 11 */ |
1620 |
const Elf_Internal_Rela **rela1 = (const Elf_Internal_Rela**) arg1; |
0x4e800420, /* bctr */ |
1621 |
const Elf_Internal_Rela **rela2 = (const Elf_Internal_Rela**) arg2; |
}; |
1622 |
|
|
|
/* Sort by offset. */ |
|
|
return ((*rela1)->r_offset - (*rela2)->r_offset); |
|
|
} |
|
1623 |
|
|
1624 |
static boolean |
static bfd_boolean |
1625 |
ppc_elf_relax_section (abfd, isec, link_info, again) |
ppc_elf_relax_section (bfd *abfd, |
1626 |
bfd *abfd; |
asection *isec, |
1627 |
asection *isec; |
struct bfd_link_info *link_info, |
1628 |
struct bfd_link_info *link_info; |
bfd_boolean *again) |
|
boolean *again; |
|
1629 |
{ |
{ |
1630 |
#define PAGESIZE 0x1000 |
struct one_fixup |
1631 |
|
{ |
1632 |
|
struct one_fixup *next; |
1633 |
|
asection *tsec; |
1634 |
|
bfd_vma toff; |
1635 |
|
bfd_vma trampoff; |
1636 |
|
}; |
1637 |
|
|
1638 |
|
Elf_Internal_Shdr *symtab_hdr; |
1639 |
bfd_byte *contents = NULL; |
bfd_byte *contents = NULL; |
1640 |
bfd_byte *free_contents = NULL; |
Elf_Internal_Sym *isymbuf = NULL; |
1641 |
Elf_Internal_Rela *internal_relocs = NULL; |
Elf_Internal_Rela *internal_relocs = NULL; |
1642 |
Elf_Internal_Rela *free_relocs = NULL; |
Elf_Internal_Rela *irel, *irelend; |
1643 |
Elf_Internal_Rela **rela_comb = NULL; |
struct one_fixup *fixups = NULL; |
1644 |
int comb_curr, comb_count; |
bfd_boolean changed; |
1645 |
|
struct ppc_elf_link_hash_table *ppc_info; |
1646 |
/* We never have to do this more than once per input section. */ |
bfd_size_type trampoff; |
1647 |
*again = false; |
|
1648 |
|
*again = FALSE; |
1649 |
/* If needed, initialize this section's cooked size. */ |
|
1650 |
if (isec->_cooked_size == 0) |
/* Nothing to do if there are no relocations, and no need to do |
1651 |
isec->_cooked_size = isec->_raw_size; |
anything with non-alloc sections. */ |
1652 |
|
if ((isec->flags & SEC_ALLOC) == 0 |
1653 |
/* We're only interested in text sections which overlap the |
|| (isec->flags & SEC_RELOC) == 0 |
1654 |
troublesome area at the end of a page. */ |
|| isec->reloc_count == 0) |
1655 |
if (link_info->mpc860c0 && (isec->flags & SEC_CODE) && isec->_cooked_size) |
return TRUE; |
1656 |
|
|
1657 |
|
trampoff = (isec->size + 3) & (bfd_vma) -4; |
1658 |
|
/* Space for a branch around any trampolines. */ |
1659 |
|
trampoff += 4; |
1660 |
|
|
1661 |
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
1662 |
|
|
1663 |
|
/* Get a copy of the native relocations. */ |
1664 |
|
internal_relocs = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, |
1665 |
|
link_info->keep_memory); |
1666 |
|
if (internal_relocs == NULL) |
1667 |
|
goto error_return; |
1668 |
|
|
1669 |
|
ppc_info = ppc_elf_hash_table (link_info); |
1670 |
|
irelend = internal_relocs + isec->reloc_count; |
1671 |
|
|
1672 |
|
for (irel = internal_relocs; irel < irelend; irel++) |
1673 |
{ |
{ |
1674 |
bfd_vma dot, end_page, end_section; |
unsigned long r_type = ELF32_R_TYPE (irel->r_info); |
1675 |
boolean section_modified; |
bfd_vma symaddr, reladdr, toff, roff; |
1676 |
|
asection *tsec; |
1677 |
|
struct one_fixup *f; |
1678 |
|
size_t insn_offset = 0; |
1679 |
|
bfd_vma max_branch_offset, val; |
1680 |
|
bfd_byte *hit_addr; |
1681 |
|
unsigned long t0; |
1682 |
|
unsigned char sym_type; |
1683 |
|
|
1684 |
/* Get the section contents. */ |
switch (r_type) |
1685 |
/* Get cached copy if it exists. */ |
{ |
1686 |
if (elf_section_data (isec)->this_hdr.contents != NULL) |
case R_PPC_REL24: |
1687 |
contents = elf_section_data (isec)->this_hdr.contents; |
case R_PPC_LOCAL24PC: |
1688 |
|
case R_PPC_PLTREL24: |
1689 |
|
max_branch_offset = 1 << 25; |
1690 |
|
break; |
1691 |
|
|
1692 |
|
case R_PPC_REL14: |
1693 |
|
case R_PPC_REL14_BRTAKEN: |
1694 |
|
case R_PPC_REL14_BRNTAKEN: |
1695 |
|
max_branch_offset = 1 << 15; |
1696 |
|
break; |
1697 |
|
|
1698 |
|
default: |
1699 |
|
continue; |
1700 |
|
} |
1701 |
|
|
1702 |
|
/* Get the value of the symbol referred to by the reloc. */ |
1703 |
|
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) |
1704 |
|
{ |
1705 |
|
/* A local symbol. */ |
1706 |
|
Elf_Internal_Sym *isym; |
1707 |
|
|
1708 |
|
/* Read this BFD's local symbols. */ |
1709 |
|
if (isymbuf == NULL) |
1710 |
|
{ |
1711 |
|
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; |
1712 |
|
if (isymbuf == NULL) |
1713 |
|
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, |
1714 |
|
symtab_hdr->sh_info, 0, |
1715 |
|
NULL, NULL, NULL); |
1716 |
|
if (isymbuf == 0) |
1717 |
|
goto error_return; |
1718 |
|
} |
1719 |
|
isym = isymbuf + ELF32_R_SYM (irel->r_info); |
1720 |
|
if (isym->st_shndx == SHN_UNDEF) |
1721 |
|
continue; /* We can't do anything with undefined symbols. */ |
1722 |
|
else if (isym->st_shndx == SHN_ABS) |
1723 |
|
tsec = bfd_abs_section_ptr; |
1724 |
|
else if (isym->st_shndx == SHN_COMMON) |
1725 |
|
tsec = bfd_com_section_ptr; |
1726 |
|
else |
1727 |
|
tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); |
1728 |
|
|
1729 |
|
toff = isym->st_value; |
1730 |
|
sym_type = ELF_ST_TYPE (isym->st_info); |
1731 |
|
} |
1732 |
else |
else |
1733 |
{ |
{ |
1734 |
/* Go get them off disk. */ |
/* Global symbol handling. */ |
1735 |
contents = (bfd_byte *) bfd_malloc (isec->_raw_size); |
unsigned long indx; |
1736 |
if (contents == NULL) |
struct elf_link_hash_entry *h; |
1737 |
goto error_return; |
|
1738 |
free_contents = contents; |
indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; |
1739 |
|
h = elf_sym_hashes (abfd)[indx]; |
1740 |
if (! bfd_get_section_contents (abfd, isec, contents, |
|
1741 |
(file_ptr) 0, isec->_raw_size)) |
while (h->root.type == bfd_link_hash_indirect |
1742 |
goto error_return; |
|| h->root.type == bfd_link_hash_warning) |
1743 |
} |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
1744 |
|
|
1745 |
comb_curr = 0; |
if (r_type == R_PPC_PLTREL24 |
1746 |
comb_count = 0; |
&& ppc_info->plt != NULL |
1747 |
if (isec->reloc_count) |
&& h->plt.offset != (bfd_vma) -1) |
1748 |
{ |
{ |
1749 |
unsigned n; |
tsec = ppc_info->plt; |
1750 |
bfd_size_type amt; |
toff = h->plt.offset; |
1751 |
|
} |
1752 |
/* Get a copy of the native relocations. */ |
else if (h->root.type == bfd_link_hash_defined |
1753 |
internal_relocs = _bfd_elf32_link_read_relocs ( |
|| h->root.type == bfd_link_hash_defweak) |
1754 |
abfd, isec, (PTR) NULL, (Elf_Internal_Rela *) NULL, |
{ |
1755 |
link_info->keep_memory); |
tsec = h->root.u.def.section; |
1756 |
if (internal_relocs == NULL) |
toff = h->root.u.def.value; |
1757 |
goto error_return; |
} |
1758 |
if (! link_info->keep_memory) |
else |
1759 |
free_relocs = internal_relocs; |
continue; |
1760 |
|
|
1761 |
/* Setup a faster access method for the reloc info we need. */ |
sym_type = h->type; |
1762 |
amt = isec->reloc_count; |
} |
1763 |
amt *= sizeof (Elf_Internal_Rela*); |
|
1764 |
rela_comb = (Elf_Internal_Rela**) bfd_malloc (amt); |
/* If the branch and target are in the same section, you have |
1765 |
if (rela_comb == NULL) |
no hope of adding stubs. We'll error out later should the |
1766 |
goto error_return; |
branch overflow. */ |
1767 |
for (n = 0; n < isec->reloc_count; ++n) |
if (tsec == isec) |
1768 |
{ |
continue; |
1769 |
long r_type; |
|
1770 |
|
/* There probably isn't any reason to handle symbols in |
1771 |
r_type = ELF32_R_TYPE (internal_relocs[n].r_info); |
SEC_MERGE sections; SEC_MERGE doesn't seem a likely |
1772 |
if (r_type < 0 || r_type >= (int) R_PPC_max) |
attribute for a code section, and we are only looking at |
1773 |
goto error_return; |
branches. However, implement it correctly here as a |
1774 |
|
reference for other target relax_section functions. */ |
1775 |
/* Prologue constants are sometimes present in the ".text" |
if (0 && tsec->sec_info_type == ELF_INFO_TYPE_MERGE) |
|
sections and they can be identified by their associated relocation. |
|
|
We don't want to process those words and some others which |
|
|
can also be identified by their relocations. However, not all |
|
|
conditional branches will have a relocation so we will |
|
|
only ignore words that 1) have a reloc, and 2) the reloc |
|
|
is not applicable to a conditional branch. |
|
|
The array rela_comb is built here for use in the EOP scan loop. */ |
|
|
switch (r_type) |
|
|
{ |
|
|
case R_PPC_ADDR14_BRNTAKEN: /* absolute, predicted not taken */ |
|
|
case R_PPC_REL14: /* relative cond. br. */ |
|
|
case R_PPC_REL14_BRNTAKEN: /* rel. cond. br., predicted not taken */ |
|
|
/* We should check the instruction. */ |
|
|
break; |
|
|
default: |
|
|
/* The word is not a conditional branch - ignore it. */ |
|
|
rela_comb[comb_count++] = &internal_relocs[n]; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (comb_count > 1) |
|
|
qsort (rela_comb, (size_t) comb_count, sizeof (int), ppc_elf_sort_rela); |
|
|
} |
|
|
|
|
|
/* Enumerate each EOP region that overlaps this section. */ |
|
|
end_section = isec->vma + isec->_cooked_size; |
|
|
dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1; |
|
|
dot -= link_info->mpc860c0; |
|
|
section_modified = false; |
|
|
if (dot < isec->vma) /* Increment the start position if this section */ |
|
|
dot = isec->vma; /* begins in the middle of its first EOP region. */ |
|
|
for (; |
|
|
dot < end_section; |
|
|
dot += PAGESIZE, end_page += PAGESIZE) |
|
|
{ |
|
|
|
|
|
/* Check each word in this EOP region. */ |
|
|
for (; dot < end_page; dot += 4) |
|
|
{ |
|
|
bfd_vma isec_offset; |
|
|
unsigned long insn; |
|
|
boolean skip, modified; |
|
|
|
|
|
/* Don't process this word if there is a relocation for it and |
|
|
the relocation indicates the word is not a conditional branch. */ |
|
|
skip = false; |
|
|
isec_offset = dot - isec->vma; |
|
|
for (; comb_curr<comb_count; ++comb_curr) |
|
|
{ |
|
|
bfd_vma r_offset; |
|
|
|
|
|
r_offset = rela_comb[comb_curr]->r_offset; |
|
|
if (r_offset >= isec_offset) |
|
|
{ |
|
|
if (r_offset == isec_offset) skip = true; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (skip) continue; |
|
|
|
|
|
/* Check the current word for a problematic conditional branch. */ |
|
|
#define BO0(insn) ((insn) & 0x02000000) |
|
|
#define BO2(insn) ((insn) & 0x00800000) |
|
|
#define BO4(insn) ((insn) & 0x00200000) |
|
|
insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset); |
|
|
modified = false; |
|
|
if ((insn & 0xFc000000) == 0x40000000) |
|
|
{ |
|
|
/* Instruction is BCx */ |
|
|
if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) |
|
|
{ |
|
|
bfd_vma target; |
|
|
/* This branch is predicted as "normal". |
|
|
If this is a forward branch, it is problematic. */ |
|
|
|
|
|
target = insn & 0x0000Fffc; /*extract*/ |
|
|
target = (target ^ 0x8000) - 0x8000; /*sign extend*/ |
|
|
if ((insn & 0x00000002) == 0) |
|
|
target += dot; /*convert to abs*/ |
|
|
if (target > dot) |
|
|
{ |
|
|
insn |= 0x00200000; /* set the prediction bit */ |
|
|
modified = true; |
|
|
} |
|
|
} |
|
|
} |
|
|
else if ((insn & 0xFc00Fffe) == 0x4c000420) |
|
|
{ |
|
|
/* Instruction is BCCTRx */ |
|
|
if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) |
|
|
{ |
|
|
/* This branch is predicted as not-taken. |
|
|
If this is a forward branch, it is problematic. |
|
|
Since we can't tell statically if it will branch forward, |
|
|
always set the prediction bit. */ |
|
|
insn |= 0x00200000; /* set the prediction bit */ |
|
|
modified = true; |
|
|
} |
|
|
} |
|
|
else if ((insn & 0xFc00Fffe) == 0x4c000020) |
|
|
{ |
|
|
/* Instruction is BCLRx */ |
|
|
if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) |
|
|
{ |
|
|
/* This branch is predicted as not-taken. |
|
|
If this is a forward branch, it is problematic. |
|
|
Since we can't tell statically if it will branch forward, |
|
|
always set the prediction bit. */ |
|
|
insn |= 0x00200000; /* set the prediction bit */ |
|
|
modified = true; |
|
|
} |
|
|
} |
|
|
#undef BO0 |
|
|
#undef BO2 |
|
|
#undef BO4 |
|
|
if (modified) |
|
|
{ |
|
|
bfd_put_32 (abfd, (bfd_vma) insn, contents + isec_offset); |
|
|
section_modified = true; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (section_modified) |
|
1776 |
{ |
{ |
1777 |
elf_section_data (isec)->this_hdr.contents = contents; |
/* At this stage in linking, no SEC_MERGE symbol has been |
1778 |
free_contents = NULL; |
adjusted, so all references to such symbols need to be |
1779 |
|
passed through _bfd_merged_section_offset. (Later, in |
1780 |
|
relocate_section, all SEC_MERGE symbols *except* for |
1781 |
|
section symbols have been adjusted.) |
1782 |
|
|
1783 |
|
gas may reduce relocations against symbols in SEC_MERGE |
1784 |
|
sections to a relocation against the section symbol when |
1785 |
|
the original addend was zero. When the reloc is against |
1786 |
|
a section symbol we should include the addend in the |
1787 |
|
offset passed to _bfd_merged_section_offset, since the |
1788 |
|
location of interest is the original symbol. On the |
1789 |
|
other hand, an access to "sym+addend" where "sym" is not |
1790 |
|
a section symbol should not include the addend; Such an |
1791 |
|
access is presumed to be an offset from "sym"; The |
1792 |
|
location of interest is just "sym". */ |
1793 |
|
if (sym_type == STT_SECTION) |
1794 |
|
toff += irel->r_addend; |
1795 |
|
|
1796 |
|
toff = _bfd_merged_section_offset (abfd, &tsec, |
1797 |
|
elf_section_data (tsec)->sec_info, |
1798 |
|
toff); |
1799 |
|
|
1800 |
|
if (sym_type != STT_SECTION) |
1801 |
|
toff += irel->r_addend; |
1802 |
|
} |
1803 |
|
else |
1804 |
|
toff += irel->r_addend; |
1805 |
|
|
1806 |
|
symaddr = tsec->output_section->vma + tsec->output_offset + toff; |
1807 |
|
|
1808 |
|
roff = irel->r_offset; |
1809 |
|
reladdr = isec->output_section->vma + isec->output_offset + roff; |
1810 |
|
|
1811 |
|
/* If the branch is in range, no need to do anything. */ |
1812 |
|
if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) |
1813 |
|
continue; |
1814 |
|
|
1815 |
|
/* Look for an existing fixup to this address. */ |
1816 |
|
for (f = fixups; f ; f = f->next) |
1817 |
|
if (f->tsec == tsec && f->toff == toff) |
1818 |
|
break; |
1819 |
|
|
1820 |
|
if (f == NULL) |
1821 |
|
{ |
1822 |
|
size_t size; |
1823 |
|
unsigned long stub_rtype; |
1824 |
|
|
1825 |
|
val = trampoff - roff; |
1826 |
|
if (val >= max_branch_offset) |
1827 |
|
/* Oh dear, we can't reach a trampoline. Don't try to add |
1828 |
|
one. We'll report an error later. */ |
1829 |
|
continue; |
1830 |
|
|
1831 |
|
if (link_info->shared) |
1832 |
|
{ |
1833 |
|
size = 4 * ARRAY_SIZE (shared_stub_entry); |
1834 |
|
insn_offset = 12; |
1835 |
|
stub_rtype = R_PPC_RELAX32PC; |
1836 |
|
} |
1837 |
|
else |
1838 |
|
{ |
1839 |
|
size = 4 * ARRAY_SIZE (stub_entry); |
1840 |
|
insn_offset = 0; |
1841 |
|
stub_rtype = R_PPC_RELAX32; |
1842 |
|
} |
1843 |
|
|
1844 |
|
if (R_PPC_RELAX32_PLT - R_PPC_RELAX32 |
1845 |
|
!= R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC) |
1846 |
|
abort (); |
1847 |
|
if (tsec == ppc_info->plt) |
1848 |
|
stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32; |
1849 |
|
|
1850 |
|
/* Hijack the old relocation. Since we need two |
1851 |
|
relocations for this use a "composite" reloc. */ |
1852 |
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), |
1853 |
|
stub_rtype); |
1854 |
|
irel->r_offset = trampoff + insn_offset; |
1855 |
|
|
1856 |
|
/* Record the fixup so we don't do it again this section. */ |
1857 |
|
f = bfd_malloc (sizeof (*f)); |
1858 |
|
f->next = fixups; |
1859 |
|
f->tsec = tsec; |
1860 |
|
f->toff = toff; |
1861 |
|
f->trampoff = trampoff; |
1862 |
|
fixups = f; |
1863 |
|
|
1864 |
|
trampoff += size; |
1865 |
|
} |
1866 |
|
else |
1867 |
|
{ |
1868 |
|
val = f->trampoff - roff; |
1869 |
|
if (val >= max_branch_offset) |
1870 |
|
continue; |
1871 |
|
|
1872 |
|
/* Nop out the reloc, since we're finalizing things here. */ |
1873 |
|
irel->r_info = ELF32_R_INFO (0, R_PPC_NONE); |
1874 |
|
} |
1875 |
|
|
1876 |
|
/* Get the section contents. */ |
1877 |
|
if (contents == NULL) |
1878 |
|
{ |
1879 |
|
/* Get cached copy if it exists. */ |
1880 |
|
if (elf_section_data (isec)->this_hdr.contents != NULL) |
1881 |
|
contents = elf_section_data (isec)->this_hdr.contents; |
1882 |
|
else |
1883 |
|
{ |
1884 |
|
/* Go get them off disk. */ |
1885 |
|
if (!bfd_malloc_and_get_section (abfd, isec, &contents)) |
1886 |
|
goto error_return; |
1887 |
|
} |
1888 |
|
} |
1889 |
|
|
1890 |
|
/* Fix up the existing branch to hit the trampoline. */ |
1891 |
|
hit_addr = contents + roff; |
1892 |
|
switch (r_type) |
1893 |
|
{ |
1894 |
|
case R_PPC_REL24: |
1895 |
|
case R_PPC_LOCAL24PC: |
1896 |
|
case R_PPC_PLTREL24: |
1897 |
|
t0 = bfd_get_32 (abfd, hit_addr); |
1898 |
|
t0 &= ~0x3fffffc; |
1899 |
|
t0 |= val & 0x3fffffc; |
1900 |
|
bfd_put_32 (abfd, t0, hit_addr); |
1901 |
|
break; |
1902 |
|
|
1903 |
|
case R_PPC_REL14: |
1904 |
|
case R_PPC_REL14_BRTAKEN: |
1905 |
|
case R_PPC_REL14_BRNTAKEN: |
1906 |
|
t0 = bfd_get_32 (abfd, hit_addr); |
1907 |
|
t0 &= ~0xfffc; |
1908 |
|
t0 |= val & 0xfffc; |
1909 |
|
bfd_put_32 (abfd, t0, hit_addr); |
1910 |
|
break; |
1911 |
} |
} |
1912 |
} |
} |
1913 |
|
|
1914 |
if (rela_comb != NULL) |
/* Write out the trampolines. */ |
1915 |
|
changed = fixups != NULL; |
1916 |
|
if (fixups != NULL) |
1917 |
{ |
{ |
1918 |
free (rela_comb); |
const int *stub; |
1919 |
rela_comb = NULL; |
bfd_byte *dest; |
1920 |
|
bfd_vma val; |
1921 |
|
int i, size; |
1922 |
|
|
1923 |
|
do |
1924 |
|
{ |
1925 |
|
struct one_fixup *f = fixups; |
1926 |
|
fixups = fixups->next; |
1927 |
|
free (f); |
1928 |
|
} |
1929 |
|
while (fixups); |
1930 |
|
|
1931 |
|
contents = bfd_realloc (contents, trampoff); |
1932 |
|
if (contents == NULL) |
1933 |
|
goto error_return; |
1934 |
|
|
1935 |
|
isec->size = (isec->size + 3) & (bfd_vma) -4; |
1936 |
|
/* Branch around the trampolines. */ |
1937 |
|
val = trampoff - isec->size + 0x48000000; |
1938 |
|
dest = contents + isec->size; |
1939 |
|
isec->size = trampoff; |
1940 |
|
bfd_put_32 (abfd, val, dest); |
1941 |
|
dest += 4; |
1942 |
|
|
1943 |
|
if (link_info->shared) |
1944 |
|
{ |
1945 |
|
stub = shared_stub_entry; |
1946 |
|
size = ARRAY_SIZE (shared_stub_entry); |
1947 |
|
} |
1948 |
|
else |
1949 |
|
{ |
1950 |
|
stub = stub_entry; |
1951 |
|
size = ARRAY_SIZE (stub_entry); |
1952 |
|
} |
1953 |
|
|
1954 |
|
i = 0; |
1955 |
|
while (dest < contents + trampoff) |
1956 |
|
{ |
1957 |
|
bfd_put_32 (abfd, stub[i], dest); |
1958 |
|
i++; |
1959 |
|
if (i == size) |
1960 |
|
i = 0; |
1961 |
|
dest += 4; |
1962 |
|
} |
1963 |
|
BFD_ASSERT (i == 0); |
1964 |
} |
} |
1965 |
|
|
1966 |
if (free_relocs != NULL) |
if (isymbuf != NULL |
1967 |
|
&& symtab_hdr->contents != (unsigned char *) isymbuf) |
1968 |
{ |
{ |
1969 |
free (free_relocs); |
if (! link_info->keep_memory) |
1970 |
free_relocs = NULL; |
free (isymbuf); |
1971 |
|
else |
1972 |
|
{ |
1973 |
|
/* Cache the symbols for elf_link_input_bfd. */ |
1974 |
|
symtab_hdr->contents = (unsigned char *) isymbuf; |
1975 |
|
} |
1976 |
} |
} |
1977 |
|
|
1978 |
if (free_contents != NULL) |
if (contents != NULL |
1979 |
|
&& elf_section_data (isec)->this_hdr.contents != contents) |
1980 |
{ |
{ |
1981 |
if (! link_info->keep_memory) |
if (!changed && !link_info->keep_memory) |
1982 |
free (free_contents); |
free (contents); |
1983 |
else |
else |
1984 |
{ |
{ |
1985 |
/* Cache the section contents for elf_link_input_bfd. */ |
/* Cache the section contents for elf_link_input_bfd. */ |
1986 |
elf_section_data (isec)->this_hdr.contents = contents; |
elf_section_data (isec)->this_hdr.contents = contents; |
1987 |
} |
} |
|
free_contents = NULL; |
|
1988 |
} |
} |
1989 |
|
|
1990 |
return true; |
if (elf_section_data (isec)->relocs != internal_relocs) |
1991 |
|
{ |
1992 |
|
if (!changed) |
1993 |
|
free (internal_relocs); |
1994 |
|
else |
1995 |
|
elf_section_data (isec)->relocs = internal_relocs; |
1996 |
|
} |
1997 |
|
|
1998 |
error_return: |
*again = changed; |
1999 |
if (rela_comb != NULL) |
return TRUE; |
2000 |
free (rela_comb); |
|
2001 |
if (free_relocs != NULL) |
error_return: |
2002 |
free (free_relocs); |
if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) |
2003 |
if (free_contents != NULL) |
free (isymbuf); |
2004 |
free (free_contents); |
if (contents != NULL |
2005 |
return false; |
&& elf_section_data (isec)->this_hdr.contents != contents) |
2006 |
|
free (contents); |
2007 |
|
if (internal_relocs != NULL |
2008 |
|
&& elf_section_data (isec)->relocs != internal_relocs) |
2009 |
|
free (internal_relocs); |
2010 |
|
return FALSE; |
2011 |
} |
} |
2012 |
|
|
2013 |
static reloc_howto_type * |
static reloc_howto_type * |
2014 |
ppc_elf_reloc_type_lookup (abfd, code) |
ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
2015 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd_reloc_code_real_type code) |
|
bfd_reloc_code_real_type code; |
|
2016 |
{ |
{ |
2017 |
enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; |
enum elf_ppc_reloc_type r; |
2018 |
|
|
2019 |
|
/* Initialize howto table if not already done. */ |
2020 |
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
|
/* Initialize howto table if needed. */ |
|
2021 |
ppc_elf_howto_init (); |
ppc_elf_howto_init (); |
2022 |
|
|
2023 |
switch ((int) code) |
switch (code) |
2024 |
{ |
{ |
2025 |
default: |
default: |
2026 |
return (reloc_howto_type *) NULL; |
return NULL; |
2027 |
|
|
2028 |
case BFD_RELOC_NONE: ppc_reloc = R_PPC_NONE; break; |
case BFD_RELOC_NONE: r = R_PPC_NONE; break; |
2029 |
case BFD_RELOC_32: ppc_reloc = R_PPC_ADDR32; break; |
case BFD_RELOC_32: r = R_PPC_ADDR32; break; |
2030 |
case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC_ADDR24; break; |
case BFD_RELOC_PPC_BA26: r = R_PPC_ADDR24; break; |
2031 |
case BFD_RELOC_16: ppc_reloc = R_PPC_ADDR16; break; |
case BFD_RELOC_16: r = R_PPC_ADDR16; break; |
2032 |
case BFD_RELOC_LO16: ppc_reloc = R_PPC_ADDR16_LO; break; |
case BFD_RELOC_LO16: r = R_PPC_ADDR16_LO; break; |
2033 |
case BFD_RELOC_HI16: ppc_reloc = R_PPC_ADDR16_HI; break; |
case BFD_RELOC_HI16: r = R_PPC_ADDR16_HI; break; |
2034 |
case BFD_RELOC_HI16_S: ppc_reloc = R_PPC_ADDR16_HA; break; |
case BFD_RELOC_HI16_S: r = R_PPC_ADDR16_HA; break; |
2035 |
case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC_ADDR14; break; |
case BFD_RELOC_PPC_BA16: r = R_PPC_ADDR14; break; |
2036 |
case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC_ADDR14_BRTAKEN; break; |
case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC_ADDR14_BRTAKEN; break; |
2037 |
case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC_ADDR14_BRNTAKEN; break; |
case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC_ADDR14_BRNTAKEN; break; |
2038 |
case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC_REL24; break; |
case BFD_RELOC_PPC_B26: r = R_PPC_REL24; break; |
2039 |
case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC_REL14; break; |
case BFD_RELOC_PPC_B16: r = R_PPC_REL14; break; |
2040 |
case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC_REL14_BRTAKEN; break; |
case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC_REL14_BRTAKEN; break; |
2041 |
case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC_REL14_BRNTAKEN; break; |
case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC_REL14_BRNTAKEN; break; |
2042 |
case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC_GOT16; break; |
case BFD_RELOC_16_GOTOFF: r = R_PPC_GOT16; break; |
2043 |
case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC_GOT16_LO; break; |
case BFD_RELOC_LO16_GOTOFF: r = R_PPC_GOT16_LO; break; |
2044 |
case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC_GOT16_HI; break; |
case BFD_RELOC_HI16_GOTOFF: r = R_PPC_GOT16_HI; break; |
2045 |
case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC_GOT16_HA; break; |
case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC_GOT16_HA; break; |
2046 |
case BFD_RELOC_24_PLT_PCREL: ppc_reloc = R_PPC_PLTREL24; break; |
case BFD_RELOC_24_PLT_PCREL: r = R_PPC_PLTREL24; break; |
2047 |
case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC_COPY; break; |
case BFD_RELOC_PPC_COPY: r = R_PPC_COPY; break; |
2048 |
case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC_GLOB_DAT; break; |
case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC_GLOB_DAT; break; |
2049 |
case BFD_RELOC_PPC_LOCAL24PC: ppc_reloc = R_PPC_LOCAL24PC; break; |
case BFD_RELOC_PPC_LOCAL24PC: r = R_PPC_LOCAL24PC; break; |
2050 |
case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC_REL32; break; |
case BFD_RELOC_32_PCREL: r = R_PPC_REL32; break; |
2051 |
case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC_PLT32; break; |
case BFD_RELOC_32_PLTOFF: r = R_PPC_PLT32; break; |
2052 |
case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC_PLTREL32; break; |
case BFD_RELOC_32_PLT_PCREL: r = R_PPC_PLTREL32; break; |
2053 |
case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC_PLT16_LO; break; |
case BFD_RELOC_LO16_PLTOFF: r = R_PPC_PLT16_LO; break; |
2054 |
case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC_PLT16_HI; break; |
case BFD_RELOC_HI16_PLTOFF: r = R_PPC_PLT16_HI; break; |
2055 |
case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC_PLT16_HA; break; |
case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC_PLT16_HA; break; |
2056 |
case BFD_RELOC_GPREL16: ppc_reloc = R_PPC_SDAREL16; break; |
case BFD_RELOC_GPREL16: r = R_PPC_SDAREL16; break; |
2057 |
case BFD_RELOC_16_BASEREL: ppc_reloc = R_PPC_SECTOFF; break; |
case BFD_RELOC_16_BASEREL: r = R_PPC_SECTOFF; break; |
2058 |
case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC_SECTOFF_LO; break; |
case BFD_RELOC_LO16_BASEREL: r = R_PPC_SECTOFF_LO; break; |
2059 |
case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC_SECTOFF_HI; break; |
case BFD_RELOC_HI16_BASEREL: r = R_PPC_SECTOFF_HI; break; |
2060 |
case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC_SECTOFF_HA; break; |
case BFD_RELOC_HI16_S_BASEREL: r = R_PPC_SECTOFF_HA; break; |
2061 |
case BFD_RELOC_CTOR: ppc_reloc = R_PPC_ADDR32; break; |
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break; |
2062 |
case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC_TOC16; break; |
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break; |
2063 |
case BFD_RELOC_PPC_EMB_NADDR32: ppc_reloc = R_PPC_EMB_NADDR32; break; |
case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break; |
2064 |
case BFD_RELOC_PPC_EMB_NADDR16: ppc_reloc = R_PPC_EMB_NADDR16; break; |
case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break; |
2065 |
case BFD_RELOC_PPC_EMB_NADDR16_LO: ppc_reloc = R_PPC_EMB_NADDR16_LO; break; |
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break; |
2066 |
case BFD_RELOC_PPC_EMB_NADDR16_HI: ppc_reloc = R_PPC_EMB_NADDR16_HI; break; |
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break; |
2067 |
case BFD_RELOC_PPC_EMB_NADDR16_HA: ppc_reloc = R_PPC_EMB_NADDR16_HA; break; |
case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC_TPREL16_HI; break; |
2068 |
case BFD_RELOC_PPC_EMB_SDAI16: ppc_reloc = R_PPC_EMB_SDAI16; break; |
case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC_TPREL16_HA; break; |
2069 |
case BFD_RELOC_PPC_EMB_SDA2I16: ppc_reloc = R_PPC_EMB_SDA2I16; break; |
case BFD_RELOC_PPC_TPREL: r = R_PPC_TPREL32; break; |
2070 |
case BFD_RELOC_PPC_EMB_SDA2REL: ppc_reloc = R_PPC_EMB_SDA2REL; break; |
case BFD_RELOC_PPC_DTPREL16: r = R_PPC_DTPREL16; break; |
2071 |
case BFD_RELOC_PPC_EMB_SDA21: ppc_reloc = R_PPC_EMB_SDA21; break; |
case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC_DTPREL16_LO; break; |
2072 |
case BFD_RELOC_PPC_EMB_MRKREF: ppc_reloc = R_PPC_EMB_MRKREF; break; |
case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC_DTPREL16_HI; break; |
2073 |
case BFD_RELOC_PPC_EMB_RELSEC16: ppc_reloc = R_PPC_EMB_RELSEC16; break; |
case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC_DTPREL16_HA; break; |
2074 |
case BFD_RELOC_PPC_EMB_RELST_LO: ppc_reloc = R_PPC_EMB_RELST_LO; break; |
case BFD_RELOC_PPC_DTPREL: r = R_PPC_DTPREL32; break; |
2075 |
case BFD_RELOC_PPC_EMB_RELST_HI: ppc_reloc = R_PPC_EMB_RELST_HI; break; |
case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC_GOT_TLSGD16; break; |
2076 |
case BFD_RELOC_PPC_EMB_RELST_HA: ppc_reloc = R_PPC_EMB_RELST_HA; break; |
case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC_GOT_TLSGD16_LO; break; |
2077 |
case BFD_RELOC_PPC_EMB_BIT_FLD: ppc_reloc = R_PPC_EMB_BIT_FLD; break; |
case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC_GOT_TLSGD16_HI; break; |
2078 |
case BFD_RELOC_PPC_EMB_RELSDA: ppc_reloc = R_PPC_EMB_RELSDA; break; |
case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC_GOT_TLSGD16_HA; break; |
2079 |
case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC_GNU_VTINHERIT; break; |
case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC_GOT_TLSLD16; break; |
2080 |
case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC_GNU_VTENTRY; break; |
case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC_GOT_TLSLD16_LO; break; |
2081 |
|
case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC_GOT_TLSLD16_HI; break; |
2082 |
|
case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC_GOT_TLSLD16_HA; break; |
2083 |
|
case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC_GOT_TPREL16; break; |
2084 |
|
case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC_GOT_TPREL16_LO; break; |
2085 |
|
case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC_GOT_TPREL16_HI; break; |
2086 |
|
case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC_GOT_TPREL16_HA; break; |
2087 |
|
case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC_GOT_DTPREL16; break; |
2088 |
|
case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC_GOT_DTPREL16_LO; break; |
2089 |
|
case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC_GOT_DTPREL16_HI; break; |
2090 |
|
case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC_GOT_DTPREL16_HA; break; |
2091 |
|
case BFD_RELOC_PPC_EMB_NADDR32: r = R_PPC_EMB_NADDR32; break; |
2092 |
|
case BFD_RELOC_PPC_EMB_NADDR16: r = R_PPC_EMB_NADDR16; break; |
2093 |
|
case BFD_RELOC_PPC_EMB_NADDR16_LO: r = R_PPC_EMB_NADDR16_LO; break; |
2094 |
|
case BFD_RELOC_PPC_EMB_NADDR16_HI: r = R_PPC_EMB_NADDR16_HI; break; |
2095 |
|
case BFD_RELOC_PPC_EMB_NADDR16_HA: r = R_PPC_EMB_NADDR16_HA; break; |
2096 |
|
case BFD_RELOC_PPC_EMB_SDAI16: r = R_PPC_EMB_SDAI16; break; |
2097 |
|
case BFD_RELOC_PPC_EMB_SDA2I16: r = R_PPC_EMB_SDA2I16; break; |
2098 |
|
case BFD_RELOC_PPC_EMB_SDA2REL: r = R_PPC_EMB_SDA2REL; break; |
2099 |
|
case BFD_RELOC_PPC_EMB_SDA21: r = R_PPC_EMB_SDA21; break; |
2100 |
|
case BFD_RELOC_PPC_EMB_MRKREF: r = R_PPC_EMB_MRKREF; break; |
2101 |
|
case BFD_RELOC_PPC_EMB_RELSEC16: r = R_PPC_EMB_RELSEC16; break; |
2102 |
|
case BFD_RELOC_PPC_EMB_RELST_LO: r = R_PPC_EMB_RELST_LO; break; |
2103 |
|
case BFD_RELOC_PPC_EMB_RELST_HI: r = R_PPC_EMB_RELST_HI; break; |
2104 |
|
case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break; |
2105 |
|
case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break; |
2106 |
|
case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break; |
2107 |
|
case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break; |
2108 |
|
case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break; |
2109 |
} |
} |
2110 |
|
|
2111 |
return ppc_elf_howto_table[(int) ppc_reloc]; |
return ppc_elf_howto_table[r]; |
2112 |
}; |
}; |
2113 |
|
|
2114 |
/* Set the howto pointer for a PowerPC ELF reloc. */ |
/* Set the howto pointer for a PowerPC ELF reloc. */ |
2115 |
|
|
2116 |
static void |
static void |
2117 |
ppc_elf_info_to_howto (abfd, cache_ptr, dst) |
ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, |
2118 |
bfd *abfd ATTRIBUTE_UNUSED; |
arelent *cache_ptr, |
2119 |
arelent *cache_ptr; |
Elf_Internal_Rela *dst) |
|
Elf32_Internal_Rela *dst; |
|
2120 |
{ |
{ |
2121 |
|
/* Initialize howto table if not already done. */ |
2122 |
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
|
/* Initialize howto table if needed. */ |
|
2123 |
ppc_elf_howto_init (); |
ppc_elf_howto_init (); |
2124 |
|
|
2125 |
BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); |
BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); |
2129 |
/* Handle the R_PPC_ADDR16_HA reloc. */ |
/* Handle the R_PPC_ADDR16_HA reloc. */ |
2130 |
|
|
2131 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
2132 |
ppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section, |
ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED, |
2133 |
output_bfd, error_message) |
arelent *reloc_entry, |
2134 |
bfd *abfd ATTRIBUTE_UNUSED; |
asymbol *symbol, |
2135 |
arelent *reloc_entry; |
void *data ATTRIBUTE_UNUSED, |
2136 |
asymbol *symbol; |
asection *input_section, |
2137 |
PTR data ATTRIBUTE_UNUSED; |
bfd *output_bfd, |
2138 |
asection *input_section; |
char **error_message ATTRIBUTE_UNUSED) |
|
bfd *output_bfd; |
|
|
char **error_message ATTRIBUTE_UNUSED; |
|
2139 |
{ |
{ |
2140 |
bfd_vma relocation; |
bfd_vma relocation; |
2141 |
|
|
2145 |
return bfd_reloc_ok; |
return bfd_reloc_ok; |
2146 |
} |
} |
2147 |
|
|
2148 |
if (reloc_entry->address > input_section->_cooked_size) |
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) |
2149 |
return bfd_reloc_outofrange; |
return bfd_reloc_outofrange; |
2150 |
|
|
2151 |
if (bfd_is_com_section (symbol->section)) |
if (bfd_is_com_section (symbol->section)) |
2162 |
return bfd_reloc_continue; |
return bfd_reloc_continue; |
2163 |
} |
} |
2164 |
|
|
2165 |
|
static bfd_reloc_status_type |
2166 |
|
ppc_elf_unhandled_reloc (bfd *abfd, |
2167 |
|
arelent *reloc_entry, |
2168 |
|
asymbol *symbol, |
2169 |
|
void *data, |
2170 |
|
asection *input_section, |
2171 |
|
bfd *output_bfd, |
2172 |
|
char **error_message) |
2173 |
|
{ |
2174 |
|
/* If this is a relocatable link (output_bfd test tells us), just |
2175 |
|
call the generic function. Any adjustment will be done at final |
2176 |
|
link time. */ |
2177 |
|
if (output_bfd != NULL) |
2178 |
|
return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
2179 |
|
input_section, output_bfd, error_message); |
2180 |
|
|
2181 |
|
if (error_message != NULL) |
2182 |
|
{ |
2183 |
|
static char buf[60]; |
2184 |
|
sprintf (buf, _("generic linker can't handle %s"), |
2185 |
|
reloc_entry->howto->name); |
2186 |
|
*error_message = buf; |
2187 |
|
} |
2188 |
|
return bfd_reloc_dangerous; |
2189 |
|
} |
2190 |
|
|
2191 |
/* Fix bad default arch selected for a 32 bit input bfd when the |
/* Fix bad default arch selected for a 32 bit input bfd when the |
2192 |
default is 64 bit. */ |
default is 64 bit. */ |
2193 |
|
|
2194 |
static boolean |
static bfd_boolean |
2195 |
ppc_elf_object_p (abfd) |
ppc_elf_object_p (bfd *abfd) |
|
bfd *abfd; |
|
2196 |
{ |
{ |
2197 |
if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64) |
if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64) |
2198 |
{ |
{ |
2205 |
BFD_ASSERT (abfd->arch_info->bits_per_word == 32); |
BFD_ASSERT (abfd->arch_info->bits_per_word == 32); |
2206 |
} |
} |
2207 |
} |
} |
2208 |
return true; |
return TRUE; |
2209 |
} |
} |
2210 |
|
|
2211 |
/* Function to set whether a module needs the -mrelocatable bit set. */ |
/* Function to set whether a module needs the -mrelocatable bit set. */ |
2212 |
|
|
2213 |
static boolean |
static bfd_boolean |
2214 |
ppc_elf_set_private_flags (abfd, flags) |
ppc_elf_set_private_flags (bfd *abfd, flagword flags) |
|
bfd *abfd; |
|
|
flagword flags; |
|
2215 |
{ |
{ |
2216 |
BFD_ASSERT (!elf_flags_init (abfd) |
BFD_ASSERT (!elf_flags_init (abfd) |
2217 |
|| elf_elfheader (abfd)->e_flags == flags); |
|| elf_elfheader (abfd)->e_flags == flags); |
2218 |
|
|
2219 |
elf_elfheader (abfd)->e_flags = flags; |
elf_elfheader (abfd)->e_flags = flags; |
2220 |
elf_flags_init (abfd) = true; |
elf_flags_init (abfd) = TRUE; |
2221 |
return true; |
return TRUE; |
2222 |
|
} |
2223 |
|
|
2224 |
|
/* Return 1 if target is one of ours. */ |
2225 |
|
|
2226 |
|
static bfd_boolean |
2227 |
|
is_ppc_elf_target (const struct bfd_target *targ) |
2228 |
|
{ |
2229 |
|
extern const bfd_target bfd_elf32_powerpc_vec; |
2230 |
|
extern const bfd_target bfd_elf32_powerpcle_vec; |
2231 |
|
|
2232 |
|
return targ == &bfd_elf32_powerpc_vec || targ == &bfd_elf32_powerpcle_vec; |
2233 |
} |
} |
2234 |
|
|
2235 |
/* Merge backend specific data from an object file to the output |
/* Merge backend specific data from an object file to the output |
2236 |
object file when linking */ |
object file when linking. */ |
2237 |
static boolean |
|
2238 |
ppc_elf_merge_private_bfd_data (ibfd, obfd) |
static bfd_boolean |
2239 |
bfd *ibfd; |
ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) |
|
bfd *obfd; |
|
2240 |
{ |
{ |
2241 |
flagword old_flags; |
flagword old_flags; |
2242 |
flagword new_flags; |
flagword new_flags; |
2243 |
boolean error; |
bfd_boolean error; |
2244 |
|
|
2245 |
/* Check if we have the same endianess */ |
if (!is_ppc_elf_target (ibfd->xvec) |
2246 |
if (! _bfd_generic_verify_endian_match (ibfd, obfd)) |
|| !is_ppc_elf_target (obfd->xvec)) |
2247 |
return false; |
return TRUE; |
2248 |
|
|
2249 |
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
/* Check if we have the same endianess. */ |
2250 |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
if (! _bfd_generic_verify_endian_match (ibfd, obfd)) |
2251 |
return true; |
return FALSE; |
2252 |
|
|
2253 |
new_flags = elf_elfheader (ibfd)->e_flags; |
new_flags = elf_elfheader (ibfd)->e_flags; |
2254 |
old_flags = elf_elfheader (obfd)->e_flags; |
old_flags = elf_elfheader (obfd)->e_flags; |
2255 |
if (!elf_flags_init (obfd)) /* First call, no flags set */ |
if (!elf_flags_init (obfd)) |
2256 |
{ |
{ |
2257 |
elf_flags_init (obfd) = true; |
/* First call, no flags set. */ |
2258 |
|
elf_flags_init (obfd) = TRUE; |
2259 |
elf_elfheader (obfd)->e_flags = new_flags; |
elf_elfheader (obfd)->e_flags = new_flags; |
2260 |
} |
} |
2261 |
|
|
2262 |
else if (new_flags == old_flags) /* Compatible flags are ok */ |
/* Compatible flags are ok. */ |
2263 |
|
else if (new_flags == old_flags) |
2264 |
; |
; |
2265 |
|
|
2266 |
else /* Incompatible flags */ |
/* Incompatible flags. */ |
2267 |
|
else |
2268 |
{ |
{ |
2269 |
/* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked |
/* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib |
2270 |
with either. */ |
to be linked with either. */ |
2271 |
error = false; |
error = FALSE; |
2272 |
if ((new_flags & EF_PPC_RELOCATABLE) != 0 |
if ((new_flags & EF_PPC_RELOCATABLE) != 0 |
2273 |
&& (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) |
&& (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) |
2274 |
{ |
{ |
2275 |
error = true; |
error = TRUE; |
2276 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2277 |
(_("%s: compiled with -mrelocatable and linked with modules compiled normally"), |
(_("%B: compiled with -mrelocatable and linked with " |
2278 |
bfd_archive_filename (ibfd)); |
"modules compiled normally"), ibfd); |
2279 |
} |
} |
2280 |
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 |
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 |
2281 |
&& (old_flags & EF_PPC_RELOCATABLE) != 0) |
&& (old_flags & EF_PPC_RELOCATABLE) != 0) |
2282 |
{ |
{ |
2283 |
error = true; |
error = TRUE; |
2284 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2285 |
(_("%s: compiled normally and linked with modules compiled with -mrelocatable"), |
(_("%B: compiled normally and linked with " |
2286 |
bfd_archive_filename (ibfd)); |
"modules compiled with -mrelocatable"), ibfd); |
2287 |
} |
} |
2288 |
|
|
2289 |
/* The output is -mrelocatable-lib iff both the input files are. */ |
/* The output is -mrelocatable-lib iff both the input files are. */ |
2291 |
elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; |
elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; |
2292 |
|
|
2293 |
/* The output is -mrelocatable iff it can't be -mrelocatable-lib, |
/* The output is -mrelocatable iff it can't be -mrelocatable-lib, |
2294 |
but each input file is either -mrelocatable or -mrelocatable-lib. */ |
but each input file is either -mrelocatable or -mrelocatable-lib. */ |
2295 |
if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) |
if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) |
2296 |
&& (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) |
&& (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) |
2297 |
&& (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) |
&& (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) |
2298 |
elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; |
elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; |
2299 |
|
|
2300 |
/* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */ |
/* Do not warn about eabi vs. V.4 mismatch, just or in the bit if |
2301 |
|
any module uses it. */ |
2302 |
elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); |
elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); |
2303 |
|
|
2304 |
new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); |
new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); |
2305 |
old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); |
old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); |
2306 |
|
|
2307 |
/* Warn about any other mismatches */ |
/* Warn about any other mismatches. */ |
2308 |
if (new_flags != old_flags) |
if (new_flags != old_flags) |
2309 |
{ |
{ |
2310 |
error = true; |
error = TRUE; |
2311 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2312 |
(_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), |
(_("%B: uses different e_flags (0x%lx) fields " |
2313 |
bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags); |
"than previous modules (0x%lx)"), |
2314 |
|
ibfd, (long) new_flags, (long) old_flags); |
2315 |
} |
} |
2316 |
|
|
2317 |
if (error) |
if (error) |
2318 |
{ |
{ |
2319 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
2320 |
return false; |
return FALSE; |
2321 |
} |
} |
2322 |
} |
} |
2323 |
|
|
2324 |
return true; |
return TRUE; |
2325 |
} |
} |
2326 |
|
|
2327 |
/* Handle a PowerPC specific section when reading an object file. This |
/* Handle a PowerPC specific section when reading an object file. This |
2328 |
is called when elfcode.h finds a section with an unknown type. */ |
is called when elfcode.h finds a section with an unknown type. */ |
2329 |
|
|
2330 |
static boolean |
static bfd_boolean |
2331 |
ppc_elf_section_from_shdr (abfd, hdr, name) |
ppc_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name) |
|
bfd *abfd; |
|
|
Elf32_Internal_Shdr *hdr; |
|
|
const char *name; |
|
2332 |
{ |
{ |
2333 |
asection *newsect; |
asection *newsect; |
2334 |
flagword flags; |
flagword flags; |
2335 |
|
|
2336 |
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
2337 |
return false; |
return FALSE; |
2338 |
|
|
2339 |
newsect = hdr->bfd_section; |
newsect = hdr->bfd_section; |
2340 |
flags = bfd_get_section_flags (abfd, newsect); |
flags = bfd_get_section_flags (abfd, newsect); |
2345 |
flags |= SEC_SORT_ENTRIES; |
flags |= SEC_SORT_ENTRIES; |
2346 |
|
|
2347 |
bfd_set_section_flags (abfd, newsect, flags); |
bfd_set_section_flags (abfd, newsect, flags); |
2348 |
return true; |
return TRUE; |
2349 |
} |
} |
2350 |
|
|
2351 |
/* Set up any other section flags and such that may be necessary. */ |
/* Set up any other section flags and such that may be necessary. */ |
2352 |
|
|
2353 |
static boolean |
static bfd_boolean |
2354 |
ppc_elf_fake_sections (abfd, shdr, asect) |
ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, |
2355 |
bfd *abfd ATTRIBUTE_UNUSED; |
Elf_Internal_Shdr *shdr, |
2356 |
Elf32_Internal_Shdr *shdr; |
asection *asect) |
|
asection *asect; |
|
2357 |
{ |
{ |
2358 |
if ((asect->flags & SEC_EXCLUDE) != 0) |
if ((asect->flags & SEC_EXCLUDE) != 0) |
2359 |
shdr->sh_flags |= SHF_EXCLUDE; |
shdr->sh_flags |= SHF_EXCLUDE; |
2361 |
if ((asect->flags & SEC_SORT_ENTRIES) != 0) |
if ((asect->flags & SEC_SORT_ENTRIES) != 0) |
2362 |
shdr->sh_type = SHT_ORDERED; |
shdr->sh_type = SHT_ORDERED; |
2363 |
|
|
2364 |
return true; |
return TRUE; |
2365 |
|
} |
2366 |
|
|
2367 |
|
/* Find a linker generated pointer with a given addend and type. */ |
2368 |
|
|
2369 |
|
static elf_linker_section_pointers_t * |
2370 |
|
elf_find_pointer_linker_section |
2371 |
|
(elf_linker_section_pointers_t *linker_pointers, |
2372 |
|
bfd_vma addend, |
2373 |
|
elf_linker_section_t *lsect) |
2374 |
|
{ |
2375 |
|
for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next) |
2376 |
|
if (lsect == linker_pointers->lsect && addend == linker_pointers->addend) |
2377 |
|
return linker_pointers; |
2378 |
|
|
2379 |
|
return NULL; |
2380 |
|
} |
2381 |
|
|
2382 |
|
/* Allocate a pointer to live in a linker created section. */ |
2383 |
|
|
2384 |
|
static bfd_boolean |
2385 |
|
elf_create_pointer_linker_section (bfd *abfd, |
2386 |
|
struct bfd_link_info *info, |
2387 |
|
elf_linker_section_t *lsect, |
2388 |
|
struct elf_link_hash_entry *h, |
2389 |
|
const Elf_Internal_Rela *rel) |
2390 |
|
{ |
2391 |
|
elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL; |
2392 |
|
elf_linker_section_pointers_t *linker_section_ptr; |
2393 |
|
unsigned long r_symndx = ELF32_R_SYM (rel->r_info); |
2394 |
|
bfd_size_type amt; |
2395 |
|
|
2396 |
|
BFD_ASSERT (lsect != NULL); |
2397 |
|
|
2398 |
|
/* Is this a global symbol? */ |
2399 |
|
if (h != NULL) |
2400 |
|
{ |
2401 |
|
struct ppc_elf_link_hash_entry *eh; |
2402 |
|
|
2403 |
|
/* Has this symbol already been allocated? If so, our work is done. */ |
2404 |
|
eh = (struct ppc_elf_link_hash_entry *) h; |
2405 |
|
if (elf_find_pointer_linker_section (eh->linker_section_pointer, |
2406 |
|
rel->r_addend, |
2407 |
|
lsect)) |
2408 |
|
return TRUE; |
2409 |
|
|
2410 |
|
ptr_linker_section_ptr = &eh->linker_section_pointer; |
2411 |
|
/* Make sure this symbol is output as a dynamic symbol. */ |
2412 |
|
if (h->dynindx == -1) |
2413 |
|
{ |
2414 |
|
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
2415 |
|
return FALSE; |
2416 |
|
} |
2417 |
|
|
2418 |
|
if (lsect->rel_section) |
2419 |
|
lsect->rel_section->size += sizeof (Elf32_External_Rela); |
2420 |
|
} |
2421 |
|
else |
2422 |
|
{ |
2423 |
|
/* Allocation of a pointer to a local symbol. */ |
2424 |
|
elf_linker_section_pointers_t **ptr = elf_local_ptr_offsets (abfd); |
2425 |
|
|
2426 |
|
/* Allocate a table to hold the local symbols if first time. */ |
2427 |
|
if (!ptr) |
2428 |
|
{ |
2429 |
|
unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info; |
2430 |
|
|
2431 |
|
amt = num_symbols; |
2432 |
|
amt *= sizeof (elf_linker_section_pointers_t *); |
2433 |
|
ptr = bfd_zalloc (abfd, amt); |
2434 |
|
|
2435 |
|
if (!ptr) |
2436 |
|
return FALSE; |
2437 |
|
|
2438 |
|
elf_local_ptr_offsets (abfd) = ptr; |
2439 |
|
} |
2440 |
|
|
2441 |
|
/* Has this symbol already been allocated? If so, our work is done. */ |
2442 |
|
if (elf_find_pointer_linker_section (ptr[r_symndx], |
2443 |
|
rel->r_addend, |
2444 |
|
lsect)) |
2445 |
|
return TRUE; |
2446 |
|
|
2447 |
|
ptr_linker_section_ptr = &ptr[r_symndx]; |
2448 |
|
|
2449 |
|
if (info->shared) |
2450 |
|
{ |
2451 |
|
/* If we are generating a shared object, we need to |
2452 |
|
output a R_<xxx>_RELATIVE reloc so that the |
2453 |
|
dynamic linker can adjust this GOT entry. */ |
2454 |
|
BFD_ASSERT (lsect->rel_section != NULL); |
2455 |
|
lsect->rel_section->size += sizeof (Elf32_External_Rela); |
2456 |
|
} |
2457 |
|
} |
2458 |
|
|
2459 |
|
/* Allocate space for a pointer in the linker section, and allocate |
2460 |
|
a new pointer record from internal memory. */ |
2461 |
|
BFD_ASSERT (ptr_linker_section_ptr != NULL); |
2462 |
|
amt = sizeof (elf_linker_section_pointers_t); |
2463 |
|
linker_section_ptr = bfd_alloc (abfd, amt); |
2464 |
|
|
2465 |
|
if (!linker_section_ptr) |
2466 |
|
return FALSE; |
2467 |
|
|
2468 |
|
linker_section_ptr->next = *ptr_linker_section_ptr; |
2469 |
|
linker_section_ptr->addend = rel->r_addend; |
2470 |
|
linker_section_ptr->lsect = lsect; |
2471 |
|
linker_section_ptr->written_address_p = FALSE; |
2472 |
|
*ptr_linker_section_ptr = linker_section_ptr; |
2473 |
|
|
2474 |
|
linker_section_ptr->offset = lsect->section->size; |
2475 |
|
lsect->section->size += 4; |
2476 |
|
|
2477 |
|
#ifdef DEBUG |
2478 |
|
fprintf (stderr, |
2479 |
|
"Create pointer in linker section %s, offset = %ld, section size = %ld\n", |
2480 |
|
lsect->name, (long) linker_section_ptr->offset, |
2481 |
|
(long) lsect->section->size); |
2482 |
|
#endif |
2483 |
|
|
2484 |
|
return TRUE; |
2485 |
|
} |
2486 |
|
|
2487 |
|
#define bfd_put_ptr(BFD, VAL, ADDR) bfd_put_32 (BFD, VAL, ADDR) |
2488 |
|
|
2489 |
|
/* Fill in the address for a pointer generated in a linker section. */ |
2490 |
|
|
2491 |
|
static bfd_vma |
2492 |
|
elf_finish_pointer_linker_section (bfd *output_bfd, |
2493 |
|
bfd *input_bfd, |
2494 |
|
struct bfd_link_info *info, |
2495 |
|
elf_linker_section_t *lsect, |
2496 |
|
struct elf_link_hash_entry *h, |
2497 |
|
bfd_vma relocation, |
2498 |
|
const Elf_Internal_Rela *rel, |
2499 |
|
int relative_reloc) |
2500 |
|
{ |
2501 |
|
elf_linker_section_pointers_t *linker_section_ptr; |
2502 |
|
|
2503 |
|
BFD_ASSERT (lsect != NULL); |
2504 |
|
|
2505 |
|
if (h != NULL) |
2506 |
|
{ |
2507 |
|
/* Handle global symbol. */ |
2508 |
|
struct ppc_elf_link_hash_entry *eh; |
2509 |
|
|
2510 |
|
eh = (struct ppc_elf_link_hash_entry *) h; |
2511 |
|
linker_section_ptr |
2512 |
|
= elf_find_pointer_linker_section (eh->linker_section_pointer, |
2513 |
|
rel->r_addend, |
2514 |
|
lsect); |
2515 |
|
|
2516 |
|
BFD_ASSERT (linker_section_ptr != NULL); |
2517 |
|
|
2518 |
|
if (! elf_hash_table (info)->dynamic_sections_created |
2519 |
|
|| (info->shared |
2520 |
|
&& info->symbolic |
2521 |
|
&& h->def_regular)) |
2522 |
|
{ |
2523 |
|
/* This is actually a static link, or it is a |
2524 |
|
-Bsymbolic link and the symbol is defined |
2525 |
|
locally. We must initialize this entry in the |
2526 |
|
global section. |
2527 |
|
|
2528 |
|
When doing a dynamic link, we create a .rela.<xxx> |
2529 |
|
relocation entry to initialize the value. This |
2530 |
|
is done in the finish_dynamic_symbol routine. */ |
2531 |
|
if (!linker_section_ptr->written_address_p) |
2532 |
|
{ |
2533 |
|
linker_section_ptr->written_address_p = TRUE; |
2534 |
|
bfd_put_ptr (output_bfd, |
2535 |
|
relocation + linker_section_ptr->addend, |
2536 |
|
(lsect->section->contents |
2537 |
|
+ linker_section_ptr->offset)); |
2538 |
|
} |
2539 |
|
} |
2540 |
|
} |
2541 |
|
else |
2542 |
|
{ |
2543 |
|
/* Handle local symbol. */ |
2544 |
|
unsigned long r_symndx = ELF32_R_SYM (rel->r_info); |
2545 |
|
BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL); |
2546 |
|
BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL); |
2547 |
|
linker_section_ptr = (elf_find_pointer_linker_section |
2548 |
|
(elf_local_ptr_offsets (input_bfd)[r_symndx], |
2549 |
|
rel->r_addend, |
2550 |
|
lsect)); |
2551 |
|
|
2552 |
|
BFD_ASSERT (linker_section_ptr != NULL); |
2553 |
|
|
2554 |
|
/* Write out pointer if it hasn't been rewritten out before. */ |
2555 |
|
if (!linker_section_ptr->written_address_p) |
2556 |
|
{ |
2557 |
|
linker_section_ptr->written_address_p = TRUE; |
2558 |
|
bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend, |
2559 |
|
lsect->section->contents + linker_section_ptr->offset); |
2560 |
|
|
2561 |
|
if (info->shared) |
2562 |
|
{ |
2563 |
|
/* We need to generate a relative reloc for the dynamic |
2564 |
|
linker. */ |
2565 |
|
|
2566 |
|
asection *srel = lsect->rel_section; |
2567 |
|
Elf_Internal_Rela outrel[MAX_INT_RELS_PER_EXT_REL]; |
2568 |
|
bfd_byte *erel; |
2569 |
|
const struct elf_backend_data *bed; |
2570 |
|
unsigned int i; |
2571 |
|
|
2572 |
|
BFD_ASSERT (srel != NULL); |
2573 |
|
|
2574 |
|
bed = get_elf_backend_data (output_bfd); |
2575 |
|
for (i = 0; i < bed->s->int_rels_per_ext_rel; i++) |
2576 |
|
{ |
2577 |
|
outrel[i].r_offset = (lsect->section->output_section->vma |
2578 |
|
+ lsect->section->output_offset |
2579 |
|
+ linker_section_ptr->offset); |
2580 |
|
outrel[i].r_info = 0; |
2581 |
|
outrel[i].r_addend = 0; |
2582 |
|
} |
2583 |
|
outrel[0].r_info = ELF32_R_INFO (0, relative_reloc); |
2584 |
|
erel = lsect->section->contents; |
2585 |
|
erel += (elf_section_data (lsect->section)->rel_count++ |
2586 |
|
* sizeof (Elf32_External_Rela)); |
2587 |
|
bfd_elf32_swap_reloca_out (output_bfd, outrel, erel); |
2588 |
|
} |
2589 |
|
} |
2590 |
|
} |
2591 |
|
|
2592 |
|
relocation = (lsect->section->output_offset |
2593 |
|
+ linker_section_ptr->offset |
2594 |
|
- lsect->sym_offset); |
2595 |
|
|
2596 |
|
#ifdef DEBUG |
2597 |
|
fprintf (stderr, |
2598 |
|
"Finish pointer in linker section %s, offset = %ld (0x%lx)\n", |
2599 |
|
lsect->name, (long) relocation, (long) relocation); |
2600 |
|
#endif |
2601 |
|
|
2602 |
|
/* Subtract out the addend, because it will get added back in by the normal |
2603 |
|
processing. */ |
2604 |
|
return relocation - linker_section_ptr->addend; |
2605 |
} |
} |
2606 |
|
|
2607 |
/* Create a special linker section */ |
/* Create a special linker section */ |
2608 |
static elf_linker_section_t * |
static elf_linker_section_t * |
2609 |
ppc_elf_create_linker_section (abfd, info, which) |
ppc_elf_create_linker_section (bfd *abfd, |
2610 |
bfd *abfd; |
struct bfd_link_info *info, |
2611 |
struct bfd_link_info *info; |
enum elf_linker_section_enum which) |
|
enum elf_linker_section_enum which; |
|
2612 |
{ |
{ |
|
bfd *dynobj = elf_hash_table (info)->dynobj; |
|
2613 |
elf_linker_section_t *lsect; |
elf_linker_section_t *lsect; |
2614 |
|
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); |
2615 |
|
asection *s, *sym_sec; |
2616 |
|
bfd_size_type amt; |
2617 |
|
flagword flags; |
2618 |
|
const char *name; |
2619 |
|
const char *rel_name; |
2620 |
|
const char *sym_name; |
2621 |
|
bfd_vma sym_offset; |
2622 |
|
|
2623 |
|
/* The linker creates these sections so it has somewhere to attach |
2624 |
|
their respective symbols. Startup code (crt1.o) uses these symbols |
2625 |
|
to initialize a register pointing to the section. If the output |
2626 |
|
sections corresponding to these input sections were empty it would |
2627 |
|
be OK to set the symbol to 0 (or any random number), because the |
2628 |
|
associated register should never be used. |
2629 |
|
FIXME: Setting a symbol this way is silly. The symbols ought to |
2630 |
|
be set the same way other backends set gp. */ |
2631 |
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
2632 |
|
| SEC_LINKER_CREATED); |
2633 |
|
sym_offset = 32768; |
2634 |
|
|
2635 |
/* Record the first bfd section that needs the special section */ |
switch (which) |
2636 |
if (!dynobj) |
{ |
2637 |
dynobj = elf_hash_table (info)->dynobj = abfd; |
default: |
2638 |
|
abort (); |
2639 |
/* If this is the first time, create the section */ |
return NULL; |
|
lsect = elf_linker_section (dynobj, which); |
|
|
if (!lsect) |
|
|
{ |
|
|
elf_linker_section_t defaults; |
|
|
static elf_linker_section_t zero_section; |
|
|
|
|
|
defaults = zero_section; |
|
|
defaults.which = which; |
|
|
defaults.hole_written_p = false; |
|
|
defaults.alignment = 2; |
|
|
|
|
|
/* Both of these sections are (technically) created by the user |
|
|
putting data in them, so they shouldn't be marked |
|
|
SEC_LINKER_CREATED. |
|
|
|
|
|
The linker creates them so it has somewhere to attach their |
|
|
respective symbols. In fact, if they were empty it would |
|
|
be OK to leave the symbol set to 0 (or any random number), because |
|
|
the appropriate register should never be used. */ |
|
|
defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS |
|
|
| SEC_IN_MEMORY); |
|
2640 |
|
|
2641 |
switch (which) |
case LINKER_SECTION_SDATA: /* .sdata/.sbss section */ |
2642 |
{ |
name = ".sdata"; |
2643 |
default: |
rel_name = ".rela.sdata"; |
2644 |
(*_bfd_error_handler) (_("%s: Unknown special linker type %d"), |
sym_name = "_SDA_BASE_"; |
2645 |
bfd_get_filename (abfd), |
break; |
2646 |
(int) which); |
|
2647 |
|
case LINKER_SECTION_SDATA2: /* .sdata2/.sbss2 section */ |
2648 |
|
name = ".sdata2"; |
2649 |
|
rel_name = ".rela.sdata2"; |
2650 |
|
sym_name = "_SDA2_BASE_"; |
2651 |
|
flags |= SEC_READONLY; |
2652 |
|
break; |
2653 |
|
} |
2654 |
|
|
2655 |
bfd_set_error (bfd_error_bad_value); |
/* Record the first bfd that needs the special sections. */ |
2656 |
return (elf_linker_section_t *) 0; |
if (!htab->elf.dynobj) |
2657 |
|
htab->elf.dynobj = abfd; |
2658 |
|
|
2659 |
|
amt = sizeof (elf_linker_section_t); |
2660 |
|
lsect = bfd_zalloc (htab->elf.dynobj, amt); |
2661 |
|
|
2662 |
|
lsect->sym_offset = sym_offset; |
2663 |
|
|
2664 |
|
/* See if the sections already exist. */ |
2665 |
|
sym_sec = s = bfd_get_section_by_name (htab->elf.dynobj, name); |
2666 |
|
if (s == NULL || (s->flags & flags) != flags) |
2667 |
|
{ |
2668 |
|
s = bfd_make_section_anyway (htab->elf.dynobj, name); |
2669 |
|
if (s == NULL |
2670 |
|
|| !bfd_set_section_flags (htab->elf.dynobj, s, flags)) |
2671 |
|
return NULL; |
2672 |
|
if (sym_sec == NULL) |
2673 |
|
sym_sec = s; |
2674 |
|
} |
2675 |
|
lsect->section = s; |
2676 |
|
|
2677 |
case LINKER_SECTION_SDATA: /* .sdata/.sbss section */ |
if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2 |
2678 |
defaults.name = ".sdata"; |
&& !bfd_set_section_alignment (htab->elf.dynobj, s, 2)) |
2679 |
defaults.rel_name = ".rela.sdata"; |
return NULL; |
|
defaults.bss_name = ".sbss"; |
|
|
defaults.sym_name = "_SDA_BASE_"; |
|
|
defaults.sym_offset = 32768; |
|
|
break; |
|
2680 |
|
|
2681 |
case LINKER_SECTION_SDATA2: /* .sdata2/.sbss2 section */ |
s->size = align_power (s->size, 2); |
2682 |
defaults.name = ".sdata2"; |
|
2683 |
defaults.rel_name = ".rela.sdata2"; |
#ifdef DEBUG |
2684 |
defaults.bss_name = ".sbss2"; |
fprintf (stderr, "Creating section %s, current size = %ld\n", |
2685 |
defaults.sym_name = "_SDA2_BASE_"; |
name, (long) s->size); |
2686 |
defaults.sym_offset = 32768; |
#endif |
|
defaults.flags |= SEC_READONLY; |
|
|
break; |
|
|
} |
|
2687 |
|
|
2688 |
lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults); |
if (sym_name) |
2689 |
|
{ |
2690 |
|
struct elf_link_hash_entry *h; |
2691 |
|
struct bfd_link_hash_entry *bh; |
2692 |
|
|
2693 |
|
#ifdef DEBUG |
2694 |
|
fprintf (stderr, "Adding %s to section %s\n", sym_name, name); |
2695 |
|
#endif |
2696 |
|
bh = bfd_link_hash_lookup (info->hash, sym_name, |
2697 |
|
FALSE, FALSE, FALSE); |
2698 |
|
|
2699 |
|
if ((bh == NULL || bh->type == bfd_link_hash_undefined) |
2700 |
|
&& !(_bfd_generic_link_add_one_symbol |
2701 |
|
(info, abfd, sym_name, BSF_GLOBAL, sym_sec, sym_offset, NULL, |
2702 |
|
FALSE, get_elf_backend_data (abfd)->collect, &bh))) |
2703 |
|
return NULL; |
2704 |
|
h = (struct elf_link_hash_entry *) bh; |
2705 |
|
|
2706 |
|
h->type = STT_OBJECT; |
2707 |
|
lsect->sym_hash = h; |
2708 |
|
|
2709 |
|
if (info->shared |
2710 |
|
&& ! bfd_elf_link_record_dynamic_symbol (info, h)) |
2711 |
|
return NULL; |
2712 |
|
} |
2713 |
|
|
2714 |
|
if (info->shared) |
2715 |
|
{ |
2716 |
|
s = bfd_make_section_anyway (htab->elf.dynobj, rel_name); |
2717 |
|
lsect->rel_section = s; |
2718 |
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
2719 |
|
| SEC_LINKER_CREATED | SEC_READONLY); |
2720 |
|
if (s == NULL |
2721 |
|
|| ! bfd_set_section_flags (htab->elf.dynobj, s, flags) |
2722 |
|
|| ! bfd_set_section_alignment (htab->elf.dynobj, s, 2)) |
2723 |
|
return NULL; |
2724 |
} |
} |
2725 |
|
|
2726 |
return lsect; |
return lsect; |
2727 |
} |
} |
2728 |
|
|
2729 |
/* If we have a non-zero sized .sbss2 or .PPC.EMB.sbss0 sections, we |
/* If we have .sbss2 or .PPC.EMB.sbss0 output sections, we |
2730 |
need to bump up the number of section headers. */ |
need to bump up the number of section headers. */ |
2731 |
|
|
2732 |
static int |
static int |
2733 |
ppc_elf_additional_program_headers (abfd) |
ppc_elf_additional_program_headers (bfd *abfd) |
|
bfd *abfd; |
|
2734 |
{ |
{ |
2735 |
asection *s; |
asection *s; |
2736 |
int ret; |
int ret = 0; |
|
|
|
|
ret = 0; |
|
|
|
|
|
s = bfd_get_section_by_name (abfd, ".interp"); |
|
|
if (s != NULL) |
|
|
++ret; |
|
2737 |
|
|
2738 |
s = bfd_get_section_by_name (abfd, ".sbss2"); |
s = bfd_get_section_by_name (abfd, ".sbss2"); |
2739 |
if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0) |
if (s != NULL && (s->flags & SEC_ALLOC) != 0) |
2740 |
++ret; |
++ret; |
2741 |
|
|
2742 |
s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0"); |
s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0"); |
2743 |
if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0) |
if (s != NULL && (s->flags & SEC_ALLOC) != 0) |
2744 |
++ret; |
++ret; |
2745 |
|
|
2746 |
return ret; |
return ret; |
2747 |
} |
} |
|
|
|
|
/* Modify the segment map if needed. */ |
|
|
|
|
|
static boolean |
|
|
ppc_elf_modify_segment_map (abfd) |
|
|
bfd *abfd ATTRIBUTE_UNUSED; |
|
|
{ |
|
|
return true; |
|
|
} |
|
2748 |
|
|
2749 |
/* The powerpc .got has a blrl instruction in it. Mark it executable. */ |
/* The powerpc .got has a blrl instruction in it. Mark it executable. */ |
2750 |
|
|
2751 |
static asection * |
static bfd_boolean |
2752 |
ppc_elf_create_got (abfd, info) |
ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) |
|
bfd *abfd; |
|
|
struct bfd_link_info *info; |
|
2753 |
{ |
{ |
2754 |
register asection *s; |
struct ppc_elf_link_hash_table *htab; |
2755 |
|
asection *s; |
2756 |
flagword flags; |
flagword flags; |
2757 |
|
|
2758 |
if (!_bfd_elf_create_got_section (abfd, info)) |
if (!_bfd_elf_create_got_section (abfd, info)) |
2759 |
return NULL; |
return FALSE; |
2760 |
|
|
2761 |
s = bfd_get_section_by_name (abfd, ".got"); |
htab = ppc_elf_hash_table (info); |
2762 |
|
htab->got = s = bfd_get_section_by_name (abfd, ".got"); |
2763 |
if (s == NULL) |
if (s == NULL) |
2764 |
abort (); |
abort (); |
2765 |
|
|
2766 |
flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
2767 |
| SEC_LINKER_CREATED); |
| SEC_LINKER_CREATED); |
2768 |
if (!bfd_set_section_flags (abfd, s, flags)) |
if (!bfd_set_section_flags (abfd, s, flags)) |
2769 |
return NULL; |
return FALSE; |
2770 |
return s; |
|
2771 |
|
htab->relgot = bfd_make_section (abfd, ".rela.got"); |
2772 |
|
if (!htab->relgot |
2773 |
|
|| ! bfd_set_section_flags (abfd, htab->relgot, |
2774 |
|
(SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS |
2775 |
|
| SEC_IN_MEMORY | SEC_LINKER_CREATED |
2776 |
|
| SEC_READONLY)) |
2777 |
|
|| ! bfd_set_section_alignment (abfd, htab->relgot, 2)) |
2778 |
|
return FALSE; |
2779 |
|
|
2780 |
|
return TRUE; |
2781 |
} |
} |
2782 |
|
|
2783 |
/* We have to create .dynsbss and .rela.sbss here so that they get mapped |
/* We have to create .dynsbss and .rela.sbss here so that they get mapped |
2784 |
to output sections (just like _bfd_elf_create_dynamic_sections has |
to output sections (just like _bfd_elf_create_dynamic_sections has |
2785 |
to create .dynbss and .rela.bss). */ |
to create .dynbss and .rela.bss). */ |
2786 |
|
|
2787 |
static boolean |
static bfd_boolean |
2788 |
ppc_elf_create_dynamic_sections (abfd, info) |
ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
|
bfd *abfd; |
|
|
struct bfd_link_info *info; |
|
2789 |
{ |
{ |
2790 |
register asection *s; |
struct ppc_elf_link_hash_table *htab; |
2791 |
|
asection *s; |
2792 |
flagword flags; |
flagword flags; |
2793 |
|
|
2794 |
if (!ppc_elf_create_got (abfd, info)) |
htab = ppc_elf_hash_table (info); |
2795 |
return false; |
|
2796 |
|
if (htab->got == NULL |
2797 |
|
&& !ppc_elf_create_got (abfd, info)) |
2798 |
|
return FALSE; |
2799 |
|
|
2800 |
if (!_bfd_elf_create_dynamic_sections (abfd, info)) |
if (!_bfd_elf_create_dynamic_sections (abfd, info)) |
2801 |
return false; |
return FALSE; |
2802 |
|
|
2803 |
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
2804 |
| SEC_LINKER_CREATED); |
| SEC_LINKER_CREATED); |
2805 |
|
|
2806 |
s = bfd_make_section (abfd, ".dynsbss"); |
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss"); |
2807 |
|
htab->dynsbss = s = bfd_make_section (abfd, ".dynsbss"); |
2808 |
if (s == NULL |
if (s == NULL |
2809 |
|| ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) |
|| ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED)) |
2810 |
return false; |
return FALSE; |
2811 |
|
|
2812 |
if (! info->shared) |
if (! info->shared) |
2813 |
{ |
{ |
2814 |
s = bfd_make_section (abfd, ".rela.sbss"); |
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss"); |
2815 |
|
htab->relsbss = s = bfd_make_section (abfd, ".rela.sbss"); |
2816 |
if (s == NULL |
if (s == NULL |
2817 |
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) |
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) |
2818 |
|| ! bfd_set_section_alignment (abfd, s, 2)) |
|| ! bfd_set_section_alignment (abfd, s, 2)) |
2819 |
return false; |
return FALSE; |
2820 |
} |
} |
2821 |
|
|
2822 |
s = bfd_get_section_by_name (abfd, ".plt"); |
htab->relplt = bfd_get_section_by_name (abfd, ".rela.plt"); |
2823 |
|
htab->plt = s = bfd_get_section_by_name (abfd, ".plt"); |
2824 |
if (s == NULL) |
if (s == NULL) |
2825 |
abort (); |
abort (); |
2826 |
|
|
2834 |
change the definition to something the rest of the link can |
change the definition to something the rest of the link can |
2835 |
understand. */ |
understand. */ |
2836 |
|
|
2837 |
static boolean |
static bfd_boolean |
2838 |
ppc_elf_adjust_dynamic_symbol (info, h) |
ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, |
2839 |
struct bfd_link_info *info; |
struct elf_link_hash_entry *h) |
|
struct elf_link_hash_entry *h; |
|
2840 |
{ |
{ |
2841 |
bfd *dynobj = elf_hash_table (info)->dynobj; |
struct ppc_elf_link_hash_table *htab; |
2842 |
asection *s; |
asection *s; |
2843 |
unsigned int power_of_two; |
unsigned int power_of_two; |
|
bfd_vma plt_offset; |
|
2844 |
|
|
2845 |
#ifdef DEBUG |
#ifdef DEBUG |
2846 |
fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string); |
fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", |
2847 |
|
h->root.root.string); |
2848 |
#endif |
#endif |
2849 |
|
|
2850 |
/* Make sure we know what is going on here. */ |
/* Make sure we know what is going on here. */ |
2851 |
BFD_ASSERT (dynobj != NULL |
htab = ppc_elf_hash_table (info); |
2852 |
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) |
BFD_ASSERT (htab->elf.dynobj != NULL |
2853 |
|| h->weakdef != NULL |
&& (h->needs_plt |
2854 |
|| ((h->elf_link_hash_flags |
|| h->u.weakdef != NULL |
2855 |
& ELF_LINK_HASH_DEF_DYNAMIC) != 0 |
|| (h->def_dynamic |
2856 |
&& (h->elf_link_hash_flags |
&& h->ref_regular |
2857 |
& ELF_LINK_HASH_REF_REGULAR) != 0 |
&& !h->def_regular))); |
2858 |
&& (h->elf_link_hash_flags |
|
2859 |
& ELF_LINK_HASH_DEF_REGULAR) == 0))); |
/* Deal with function syms. */ |
|
|
|
|
/* If this is a function, put it in the procedure linkage table. We |
|
|
will fill in the contents of the procedure linkage table later, |
|
|
when we know the address of the .got section. */ |
|
2860 |
if (h->type == STT_FUNC |
if (h->type == STT_FUNC |
2861 |
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) |
|| h->needs_plt) |
2862 |
{ |
{ |
2863 |
if (! elf_hash_table (info)->dynamic_sections_created |
/* Clear procedure linkage table information for any symbol that |
2864 |
|| SYMBOL_CALLS_LOCAL (info, h) |
won't need a .plt entry. */ |
2865 |
|| (info->shared && h->plt.refcount <= 0)) |
if (h->plt.refcount <= 0 |
2866 |
|
|| SYMBOL_CALLS_LOCAL (info, h) |
2867 |
|
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
2868 |
|
&& h->root.type == bfd_link_hash_undefweak)) |
2869 |
{ |
{ |
2870 |
/* A PLT entry is not required/allowed when: |
/* A PLT entry is not required/allowed when: |
2871 |
|
|
2872 |
1. We are not using ld.so; because then the PLT entry |
1. We are not using ld.so; because then the PLT entry |
2873 |
can't be set up, so we can't use one. |
can't be set up, so we can't use one. In this case, |
2874 |
|
ppc_elf_adjust_dynamic_symbol won't even be called. |
2875 |
|
|
2876 |
2. We know for certain that a call to this symbol |
2. GC has rendered the entry unused. |
|
will go to this object. |
|
2877 |
|
|
2878 |
3. GC has rendered the entry unused. |
3. We know for certain that a call to this symbol |
2879 |
Note, however, that in an executable all references to the |
will go to this object, or will remain undefined. */ |
|
symbol go to the PLT, so we can't turn it off in that case. |
|
|
??? The correct thing to do here is to reference count |
|
|
all uses of the symbol, not just those to the GOT or PLT. */ |
|
2880 |
h->plt.offset = (bfd_vma) -1; |
h->plt.offset = (bfd_vma) -1; |
2881 |
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 0; |
|
return true; |
|
|
} |
|
|
|
|
|
/* Make sure this symbol is output as a dynamic symbol. */ |
|
|
if (h->dynindx == -1) |
|
|
{ |
|
|
if (! bfd_elf32_link_record_dynamic_symbol (info, h)) |
|
|
return false; |
|
2882 |
} |
} |
2883 |
BFD_ASSERT (h->dynindx != -1); |
return TRUE; |
|
|
|
|
s = bfd_get_section_by_name (dynobj, ".plt"); |
|
|
BFD_ASSERT (s != NULL); |
|
|
|
|
|
/* If this is the first .plt entry, make room for the special |
|
|
first entry. */ |
|
|
if (s->_raw_size == 0) |
|
|
s->_raw_size += PLT_INITIAL_ENTRY_SIZE; |
|
|
|
|
|
/* The PowerPC PLT is actually composed of two parts, the first part |
|
|
is 2 words (for a load and a jump), and then there is a remaining |
|
|
word available at the end. */ |
|
|
plt_offset = (PLT_INITIAL_ENTRY_SIZE |
|
|
+ (PLT_SLOT_SIZE |
|
|
* ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) |
|
|
/ PLT_ENTRY_SIZE))); |
|
|
|
|
|
/* If this symbol is not defined in a regular file, and we are |
|
|
not generating a shared library, then set the symbol to this |
|
|
location in the .plt. This is required to make function |
|
|
pointers compare as equal between the normal executable and |
|
|
the shared library. */ |
|
|
if (! info->shared |
|
|
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
|
|
{ |
|
|
h->root.u.def.section = s; |
|
|
h->root.u.def.value = plt_offset; |
|
|
} |
|
|
|
|
|
h->plt.offset = plt_offset; |
|
|
|
|
|
/* Make room for this entry. After the 8192nd entry, room |
|
|
for two entries is allocated. */ |
|
|
if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE |
|
|
>= PLT_NUM_SINGLE_ENTRIES) |
|
|
s->_raw_size += 2 * PLT_ENTRY_SIZE; |
|
|
else |
|
|
s->_raw_size += PLT_ENTRY_SIZE; |
|
|
|
|
|
/* We also need to make an entry in the .rela.plt section. */ |
|
|
s = bfd_get_section_by_name (dynobj, ".rela.plt"); |
|
|
BFD_ASSERT (s != NULL); |
|
|
s->_raw_size += sizeof (Elf32_External_Rela); |
|
|
|
|
|
return true; |
|
2884 |
} |
} |
2885 |
else |
else |
2886 |
h->plt.offset = (bfd_vma) -1; |
h->plt.offset = (bfd_vma) -1; |
2888 |
/* If this is a weak symbol, and there is a real definition, the |
/* If this is a weak symbol, and there is a real definition, the |
2889 |
processor independent code will have arranged for us to see the |
processor independent code will have arranged for us to see the |
2890 |
real definition first, and we can just use the same value. */ |
real definition first, and we can just use the same value. */ |
2891 |
if (h->weakdef != NULL) |
if (h->u.weakdef != NULL) |
2892 |
{ |
{ |
2893 |
BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined |
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined |
2894 |
|| h->weakdef->root.type == bfd_link_hash_defweak); |
|| h->u.weakdef->root.type == bfd_link_hash_defweak); |
2895 |
h->root.u.def.section = h->weakdef->root.u.def.section; |
h->root.u.def.section = h->u.weakdef->root.u.def.section; |
2896 |
h->root.u.def.value = h->weakdef->root.u.def.value; |
h->root.u.def.value = h->u.weakdef->root.u.def.value; |
2897 |
return true; |
if (ELIMINATE_COPY_RELOCS) |
2898 |
|
h->non_got_ref = h->u.weakdef->non_got_ref; |
2899 |
|
return TRUE; |
2900 |
} |
} |
2901 |
|
|
2902 |
/* This is a reference to a symbol defined by a dynamic object which |
/* This is a reference to a symbol defined by a dynamic object which |
2907 |
For such cases we need not do anything here; the relocations will |
For such cases we need not do anything here; the relocations will |
2908 |
be handled correctly by relocate_section. */ |
be handled correctly by relocate_section. */ |
2909 |
if (info->shared) |
if (info->shared) |
2910 |
return true; |
return TRUE; |
2911 |
|
|
2912 |
|
/* If there are no references to this symbol that do not use the |
2913 |
|
GOT, we don't need to generate a copy reloc. */ |
2914 |
|
if (!h->non_got_ref) |
2915 |
|
return TRUE; |
2916 |
|
|
2917 |
|
if (ELIMINATE_COPY_RELOCS) |
2918 |
|
{ |
2919 |
|
struct ppc_elf_dyn_relocs *p; |
2920 |
|
for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) |
2921 |
|
{ |
2922 |
|
s = p->sec->output_section; |
2923 |
|
if (s != NULL && (s->flags & SEC_READONLY) != 0) |
2924 |
|
break; |
2925 |
|
} |
2926 |
|
|
2927 |
|
/* If we didn't find any dynamic relocs in read-only sections, then |
2928 |
|
we'll be keeping the dynamic relocs and avoiding the copy reloc. */ |
2929 |
|
if (p == NULL) |
2930 |
|
{ |
2931 |
|
h->non_got_ref = 0; |
2932 |
|
return TRUE; |
2933 |
|
} |
2934 |
|
} |
2935 |
|
|
2936 |
/* We must allocate the symbol in our .dynbss section, which will |
/* We must allocate the symbol in our .dynbss section, which will |
2937 |
become part of the .bss section of the executable. There will be |
become part of the .bss section of the executable. There will be |
2947 |
allocate it in .sbss. FIXME: It would be better to do this if and |
allocate it in .sbss. FIXME: It would be better to do this if and |
2948 |
only if there were actually SDAREL relocs for that symbol. */ |
only if there were actually SDAREL relocs for that symbol. */ |
2949 |
|
|
2950 |
if (h->size <= elf_gp_size (dynobj)) |
if (h->size <= elf_gp_size (htab->elf.dynobj)) |
2951 |
s = bfd_get_section_by_name (dynobj, ".dynsbss"); |
s = htab->dynsbss; |
2952 |
else |
else |
2953 |
s = bfd_get_section_by_name (dynobj, ".dynbss"); |
s = htab->dynbss; |
2954 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
2955 |
|
|
2956 |
/* We must generate a R_PPC_COPY reloc to tell the dynamic linker to |
/* We must generate a R_PPC_COPY reloc to tell the dynamic linker to |
2961 |
{ |
{ |
2962 |
asection *srel; |
asection *srel; |
2963 |
|
|
2964 |
if (h->size <= elf_gp_size (dynobj)) |
if (h->size <= elf_gp_size (htab->elf.dynobj)) |
2965 |
srel = bfd_get_section_by_name (dynobj, ".rela.sbss"); |
srel = htab->relsbss; |
2966 |
else |
else |
2967 |
srel = bfd_get_section_by_name (dynobj, ".rela.bss"); |
srel = htab->relbss; |
2968 |
BFD_ASSERT (srel != NULL); |
BFD_ASSERT (srel != NULL); |
2969 |
srel->_raw_size += sizeof (Elf32_External_Rela); |
srel->size += sizeof (Elf32_External_Rela); |
2970 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; |
h->needs_copy = 1; |
2971 |
} |
} |
2972 |
|
|
2973 |
/* We need to figure out the alignment required for this symbol. I |
/* We need to figure out the alignment required for this symbol. I |
2977 |
power_of_two = 4; |
power_of_two = 4; |
2978 |
|
|
2979 |
/* Apply the required alignment. */ |
/* Apply the required alignment. */ |
2980 |
s->_raw_size = BFD_ALIGN (s->_raw_size, |
s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); |
2981 |
(bfd_size_type) (1 << power_of_two)); |
if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) |
|
if (power_of_two > bfd_get_section_alignment (dynobj, s)) |
|
2982 |
{ |
{ |
2983 |
if (! bfd_set_section_alignment (dynobj, s, power_of_two)) |
if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) |
2984 |
return false; |
return FALSE; |
2985 |
} |
} |
2986 |
|
|
2987 |
/* Define the symbol as being at this point in the section. */ |
/* Define the symbol as being at this point in the section. */ |
2988 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
2989 |
h->root.u.def.value = s->_raw_size; |
h->root.u.def.value = s->size; |
2990 |
|
|
2991 |
/* Increment the section size to make room for the symbol. */ |
/* Increment the section size to make room for the symbol. */ |
2992 |
s->_raw_size += h->size; |
s->size += h->size; |
2993 |
|
|
2994 |
return true; |
return TRUE; |
2995 |
} |
} |
2996 |
|
|
2997 |
|
/* Of those relocs that might be copied as dynamic relocs, this macro |
2998 |
|
selects those that must be copied when linking a shared library, |
2999 |
|
even when the symbol is local. */ |
3000 |
|
|
3001 |
|
#define MUST_BE_DYN_RELOC(RTYPE) \ |
3002 |
|
((RTYPE) != R_PPC_REL24 \ |
3003 |
|
&& (RTYPE) != R_PPC_REL14 \ |
3004 |
|
&& (RTYPE) != R_PPC_REL14_BRTAKEN \ |
3005 |
|
&& (RTYPE) != R_PPC_REL14_BRNTAKEN \ |
3006 |
|
&& (RTYPE) != R_PPC_REL32) |
3007 |
|
|
3008 |
|
/* Allocate space in associated reloc sections for dynamic relocs. */ |
3009 |
|
|
3010 |
|
static bfd_boolean |
3011 |
|
allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
3012 |
|
{ |
3013 |
|
struct bfd_link_info *info = inf; |
3014 |
|
struct ppc_elf_link_hash_entry *eh; |
3015 |
|
struct ppc_elf_link_hash_table *htab; |
3016 |
|
struct ppc_elf_dyn_relocs *p; |
3017 |
|
|
3018 |
|
if (h->root.type == bfd_link_hash_indirect) |
3019 |
|
return TRUE; |
3020 |
|
|
3021 |
|
if (h->root.type == bfd_link_hash_warning) |
3022 |
|
/* When warning symbols are created, they **replace** the "real" |
3023 |
|
entry in the hash table, thus we never get to see the real |
3024 |
|
symbol in a hash traversal. So look at it now. */ |
3025 |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
3026 |
|
|
3027 |
|
htab = ppc_elf_hash_table (info); |
3028 |
|
if (htab->elf.dynamic_sections_created |
3029 |
|
&& h->plt.refcount > 0) |
3030 |
|
{ |
3031 |
|
/* Make sure this symbol is output as a dynamic symbol. */ |
3032 |
|
if (h->dynindx == -1 |
3033 |
|
&& !h->forced_local) |
3034 |
|
{ |
3035 |
|
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
3036 |
|
return FALSE; |
3037 |
|
} |
3038 |
|
|
3039 |
|
if (info->shared |
3040 |
|
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) |
3041 |
|
{ |
3042 |
|
asection *s = htab->plt; |
3043 |
|
|
3044 |
|
/* If this is the first .plt entry, make room for the special |
3045 |
|
first entry. */ |
3046 |
|
if (s->size == 0) |
3047 |
|
s->size += PLT_INITIAL_ENTRY_SIZE; |
3048 |
|
|
3049 |
|
/* The PowerPC PLT is actually composed of two parts, the |
3050 |
|
first part is 2 words (for a load and a jump), and then |
3051 |
|
there is a remaining word available at the end. */ |
3052 |
|
h->plt.offset = (PLT_INITIAL_ENTRY_SIZE |
3053 |
|
+ (PLT_SLOT_SIZE |
3054 |
|
* ((s->size - PLT_INITIAL_ENTRY_SIZE) |
3055 |
|
/ PLT_ENTRY_SIZE))); |
3056 |
|
|
3057 |
|
/* If this symbol is not defined in a regular file, and we |
3058 |
|
are not generating a shared library, then set the symbol |
3059 |
|
to this location in the .plt. This is required to make |
3060 |
|
function pointers compare as equal between the normal |
3061 |
|
executable and the shared library. */ |
3062 |
|
if (! info->shared |
3063 |
|
&& !h->def_regular) |
3064 |
|
{ |
3065 |
|
h->root.u.def.section = s; |
3066 |
|
h->root.u.def.value = h->plt.offset; |
3067 |
|
} |
3068 |
|
|
3069 |
|
/* Make room for this entry. After the 8192nd entry, room |
3070 |
|
for two entries is allocated. */ |
3071 |
|
s->size += PLT_ENTRY_SIZE; |
3072 |
|
if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE |
3073 |
|
> PLT_NUM_SINGLE_ENTRIES) |
3074 |
|
s->size += PLT_ENTRY_SIZE; |
3075 |
|
|
3076 |
|
/* We also need to make an entry in the .rela.plt section. */ |
3077 |
|
htab->relplt->size += sizeof (Elf32_External_Rela); |
3078 |
|
} |
3079 |
|
else |
3080 |
|
{ |
3081 |
|
h->plt.offset = (bfd_vma) -1; |
3082 |
|
h->needs_plt = 0; |
3083 |
|
} |
3084 |
|
} |
3085 |
|
else |
3086 |
|
{ |
3087 |
|
h->plt.offset = (bfd_vma) -1; |
3088 |
|
h->needs_plt = 0; |
3089 |
|
} |
3090 |
|
|
3091 |
|
eh = (struct ppc_elf_link_hash_entry *) h; |
3092 |
|
if (eh->elf.got.refcount > 0) |
3093 |
|
{ |
3094 |
|
/* Make sure this symbol is output as a dynamic symbol. */ |
3095 |
|
if (eh->elf.dynindx == -1 |
3096 |
|
&& !eh->elf.forced_local) |
3097 |
|
{ |
3098 |
|
if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf)) |
3099 |
|
return FALSE; |
3100 |
|
} |
3101 |
|
|
3102 |
|
if (eh->tls_mask == (TLS_TLS | TLS_LD) |
3103 |
|
&& !eh->elf.def_dynamic) |
3104 |
|
/* If just an LD reloc, we'll just use htab->tlsld_got.offset. */ |
3105 |
|
eh->elf.got.offset = (bfd_vma) -1; |
3106 |
|
else |
3107 |
|
{ |
3108 |
|
bfd_boolean dyn; |
3109 |
|
eh->elf.got.offset = htab->got->size; |
3110 |
|
if ((eh->tls_mask & TLS_TLS) != 0) |
3111 |
|
{ |
3112 |
|
if ((eh->tls_mask & TLS_LD) != 0) |
3113 |
|
htab->got->size += 8; |
3114 |
|
if ((eh->tls_mask & TLS_GD) != 0) |
3115 |
|
htab->got->size += 8; |
3116 |
|
if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) |
3117 |
|
htab->got->size += 4; |
3118 |
|
if ((eh->tls_mask & TLS_DTPREL) != 0) |
3119 |
|
htab->got->size += 4; |
3120 |
|
} |
3121 |
|
else |
3122 |
|
htab->got->size += 4; |
3123 |
|
dyn = htab->elf.dynamic_sections_created; |
3124 |
|
if ((info->shared |
3125 |
|
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) |
3126 |
|
&& (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT |
3127 |
|
|| eh->elf.root.type != bfd_link_hash_undefweak)) |
3128 |
|
{ |
3129 |
|
/* All the entries we allocated need relocs. */ |
3130 |
|
htab->relgot->size |
3131 |
|
+= ((htab->got->size - eh->elf.got.offset) / 4 |
3132 |
|
* sizeof (Elf32_External_Rela)); |
3133 |
|
/* Except LD only needs one. */ |
3134 |
|
if ((eh->tls_mask & TLS_LD) != 0) |
3135 |
|
htab->relgot->size -= sizeof (Elf32_External_Rela); |
3136 |
|
} |
3137 |
|
} |
3138 |
|
} |
3139 |
|
else |
3140 |
|
eh->elf.got.offset = (bfd_vma) -1; |
3141 |
|
|
3142 |
|
if (eh->dyn_relocs == NULL) |
3143 |
|
return TRUE; |
3144 |
|
|
3145 |
|
/* In the shared -Bsymbolic case, discard space allocated for |
3146 |
|
dynamic pc-relative relocs against symbols which turn out to be |
3147 |
|
defined in regular objects. For the normal shared case, discard |
3148 |
|
space for relocs that have become local due to symbol visibility |
3149 |
|
changes. */ |
3150 |
|
|
3151 |
|
if (info->shared) |
3152 |
|
{ |
3153 |
|
/* Relocs that use pc_count are those that appear on a call insn, |
3154 |
|
or certain REL relocs (see MUST_BE_DYN_RELOC) that can be |
3155 |
|
generated via assembly. We want calls to protected symbols to |
3156 |
|
resolve directly to the function rather than going via the plt. |
3157 |
|
If people want function pointer comparisons to work as expected |
3158 |
|
then they should avoid writing weird assembly. */ |
3159 |
|
if (SYMBOL_CALLS_LOCAL (info, h)) |
3160 |
|
{ |
3161 |
|
struct ppc_elf_dyn_relocs **pp; |
3162 |
|
|
3163 |
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
3164 |
|
{ |
3165 |
|
p->count -= p->pc_count; |
3166 |
|
p->pc_count = 0; |
3167 |
|
if (p->count == 0) |
3168 |
|
*pp = p->next; |
3169 |
|
else |
3170 |
|
pp = &p->next; |
3171 |
|
} |
3172 |
|
} |
3173 |
|
|
3174 |
|
/* Also discard relocs on undefined weak syms with non-default |
3175 |
|
visibility. */ |
3176 |
|
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
3177 |
|
&& h->root.type == bfd_link_hash_undefweak) |
3178 |
|
eh->dyn_relocs = NULL; |
3179 |
|
|
3180 |
|
/* Make sure undefined weak symbols are output as a dynamic symbol |
3181 |
|
in PIEs. */ |
3182 |
|
if (info->pie |
3183 |
|
&& eh->dyn_relocs != NULL |
3184 |
|
&& h->dynindx == -1 |
3185 |
|
&& h->root.type == bfd_link_hash_undefweak |
3186 |
|
&& !h->forced_local) |
3187 |
|
{ |
3188 |
|
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
3189 |
|
return FALSE; |
3190 |
|
} |
3191 |
|
} |
3192 |
|
else if (ELIMINATE_COPY_RELOCS) |
3193 |
|
{ |
3194 |
|
/* For the non-shared case, discard space for relocs against |
3195 |
|
symbols which turn out to need copy relocs or are not |
3196 |
|
dynamic. */ |
3197 |
|
|
3198 |
|
if (!h->non_got_ref |
3199 |
|
&& h->def_dynamic |
3200 |
|
&& !h->def_regular) |
3201 |
|
{ |
3202 |
|
/* Make sure this symbol is output as a dynamic symbol. |
3203 |
|
Undefined weak syms won't yet be marked as dynamic. */ |
3204 |
|
if (h->dynindx == -1 |
3205 |
|
&& !h->forced_local) |
3206 |
|
{ |
3207 |
|
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
3208 |
|
return FALSE; |
3209 |
|
} |
3210 |
|
|
3211 |
|
/* If that succeeded, we know we'll be keeping all the |
3212 |
|
relocs. */ |
3213 |
|
if (h->dynindx != -1) |
3214 |
|
goto keep; |
3215 |
|
} |
3216 |
|
|
3217 |
|
eh->dyn_relocs = NULL; |
3218 |
|
|
3219 |
|
keep: ; |
3220 |
|
} |
3221 |
|
|
3222 |
|
/* Finally, allocate space. */ |
3223 |
|
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
3224 |
|
{ |
3225 |
|
asection *sreloc = elf_section_data (p->sec)->sreloc; |
3226 |
|
sreloc->size += p->count * sizeof (Elf32_External_Rela); |
3227 |
|
} |
3228 |
|
|
3229 |
|
return TRUE; |
3230 |
|
} |
3231 |
|
|
3232 |
|
/* Find any dynamic relocs that apply to read-only sections. */ |
3233 |
|
|
3234 |
|
static bfd_boolean |
3235 |
|
readonly_dynrelocs (struct elf_link_hash_entry *h, void *info) |
3236 |
|
{ |
3237 |
|
struct ppc_elf_dyn_relocs *p; |
3238 |
|
|
3239 |
|
if (h->root.type == bfd_link_hash_indirect) |
3240 |
|
return TRUE; |
3241 |
|
|
3242 |
|
if (h->root.type == bfd_link_hash_warning) |
3243 |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
3244 |
|
|
3245 |
|
for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) |
3246 |
|
{ |
3247 |
|
asection *s = p->sec->output_section; |
3248 |
|
|
3249 |
|
if (s != NULL |
3250 |
|
&& ((s->flags & (SEC_READONLY | SEC_ALLOC)) |
3251 |
|
== (SEC_READONLY | SEC_ALLOC))) |
3252 |
|
{ |
3253 |
|
((struct bfd_link_info *) info)->flags |= DF_TEXTREL; |
3254 |
|
|
3255 |
|
/* Not an error, just cut short the traversal. */ |
3256 |
|
return FALSE; |
3257 |
|
} |
3258 |
|
} |
3259 |
|
return TRUE; |
3260 |
|
} |
3261 |
|
|
3262 |
/* Set the sizes of the dynamic sections. */ |
/* Set the sizes of the dynamic sections. */ |
3263 |
|
|
3264 |
static boolean |
static bfd_boolean |
3265 |
ppc_elf_size_dynamic_sections (output_bfd, info) |
ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
3266 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
struct bfd_link_info *info) |
|
struct bfd_link_info *info; |
|
3267 |
{ |
{ |
3268 |
bfd *dynobj; |
struct ppc_elf_link_hash_table *htab; |
3269 |
asection *s; |
asection *s; |
3270 |
boolean plt; |
bfd_boolean relocs; |
3271 |
boolean relocs; |
bfd *ibfd; |
3272 |
|
|
3273 |
#ifdef DEBUG |
#ifdef DEBUG |
3274 |
fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); |
fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); |
3275 |
#endif |
#endif |
3276 |
|
|
3277 |
dynobj = elf_hash_table (info)->dynobj; |
htab = ppc_elf_hash_table (info); |
3278 |
BFD_ASSERT (dynobj != NULL); |
BFD_ASSERT (htab->elf.dynobj != NULL); |
3279 |
|
|
3280 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (elf_hash_table (info)->dynamic_sections_created) |
3281 |
{ |
{ |
3282 |
/* Set the contents of the .interp section to the interpreter. */ |
/* Set the contents of the .interp section to the interpreter. */ |
3283 |
if (! info->shared) |
if (info->executable) |
3284 |
{ |
{ |
3285 |
s = bfd_get_section_by_name (dynobj, ".interp"); |
s = bfd_get_section_by_name (htab->elf.dynobj, ".interp"); |
3286 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
3287 |
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; |
s->size = sizeof ELF_DYNAMIC_INTERPRETER; |
3288 |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
3289 |
} |
} |
3290 |
} |
} |
3291 |
else |
|
3292 |
|
if (htab->tlsld_got.refcount > 0) |
3293 |
{ |
{ |
3294 |
/* We may have created entries in the .rela.got, .rela.sdata, and |
htab->tlsld_got.offset = htab->got->size; |
3295 |
.rela.sdata2 sections. However, if we are not creating the |
htab->got->size += 8; |
3296 |
dynamic sections, we will not actually use these entries. Reset |
if (info->shared) |
3297 |
the size of .rela.got, et al, which will cause it to get |
htab->relgot->size += sizeof (Elf32_External_Rela); |
|
stripped from the output file below. */ |
|
|
static char *rela_sections[] = { ".rela.got", ".rela.sdata", |
|
|
".rela.sdata2", ".rela.sbss", |
|
|
(char *) 0 }; |
|
|
char **p; |
|
|
|
|
|
for (p = rela_sections; *p != (char *) 0; p++) |
|
|
{ |
|
|
s = bfd_get_section_by_name (dynobj, *p); |
|
|
if (s != NULL) |
|
|
s->_raw_size = 0; |
|
|
} |
|
3298 |
} |
} |
3299 |
|
else |
3300 |
|
htab->tlsld_got.offset = (bfd_vma) -1; |
3301 |
|
|
3302 |
/* The check_relocs and adjust_dynamic_symbol entry points have |
/* Set up .got offsets for local syms, and space for local dynamic |
3303 |
determined the sizes of the various dynamic sections. Allocate |
relocs. */ |
3304 |
memory for them. */ |
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) |
|
plt = false; |
|
|
relocs = false; |
|
|
for (s = dynobj->sections; s != NULL; s = s->next) |
|
3305 |
{ |
{ |
3306 |
const char *name; |
bfd_signed_vma *local_got; |
3307 |
boolean strip; |
bfd_signed_vma *end_local_got; |
3308 |
|
char *lgot_masks; |
3309 |
|
bfd_size_type locsymcount; |
3310 |
|
Elf_Internal_Shdr *symtab_hdr; |
3311 |
|
asection *srel; |
3312 |
|
|
3313 |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
if (!is_ppc_elf_target (ibfd->xvec)) |
3314 |
continue; |
continue; |
3315 |
|
|
3316 |
/* It's OK to base decisions on the section name, because none |
for (s = ibfd->sections; s != NULL; s = s->next) |
|
of the dynobj section names depend upon the input files. */ |
|
|
name = bfd_get_section_name (dynobj, s); |
|
|
|
|
|
strip = false; |
|
|
|
|
|
if (strcmp (name, ".plt") == 0) |
|
3317 |
{ |
{ |
3318 |
if (s->_raw_size == 0) |
struct ppc_elf_dyn_relocs *p; |
3319 |
{ |
|
3320 |
/* Strip this section if we don't need it; see the |
for (p = ((struct ppc_elf_dyn_relocs *) |
3321 |
comment below. */ |
elf_section_data (s)->local_dynrel); |
3322 |
strip = true; |
p != NULL; |
3323 |
} |
p = p->next) |
|
else |
|
3324 |
{ |
{ |
3325 |
/* Remember whether there is a PLT. */ |
if (!bfd_is_abs_section (p->sec) |
3326 |
plt = true; |
&& bfd_is_abs_section (p->sec->output_section)) |
3327 |
|
{ |
3328 |
|
/* Input section has been discarded, either because |
3329 |
|
it is a copy of a linkonce section or due to |
3330 |
|
linker script /DISCARD/, so we'll be discarding |
3331 |
|
the relocs too. */ |
3332 |
|
} |
3333 |
|
else if (p->count != 0) |
3334 |
|
{ |
3335 |
|
elf_section_data (p->sec)->sreloc->size |
3336 |
|
+= p->count * sizeof (Elf32_External_Rela); |
3337 |
|
if ((p->sec->output_section->flags |
3338 |
|
& (SEC_READONLY | SEC_ALLOC)) |
3339 |
|
== (SEC_READONLY | SEC_ALLOC)) |
3340 |
|
info->flags |= DF_TEXTREL; |
3341 |
|
} |
3342 |
} |
} |
3343 |
} |
} |
3344 |
else if (strncmp (name, ".rela", 5) == 0) |
|
3345 |
|
local_got = elf_local_got_refcounts (ibfd); |
3346 |
|
if (!local_got) |
3347 |
|
continue; |
3348 |
|
|
3349 |
|
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; |
3350 |
|
locsymcount = symtab_hdr->sh_info; |
3351 |
|
end_local_got = local_got + locsymcount; |
3352 |
|
lgot_masks = (char *) end_local_got; |
3353 |
|
s = htab->got; |
3354 |
|
srel = htab->relgot; |
3355 |
|
for (; local_got < end_local_got; ++local_got, ++lgot_masks) |
3356 |
|
if (*local_got > 0) |
3357 |
|
{ |
3358 |
|
if (*lgot_masks == (TLS_TLS | TLS_LD)) |
3359 |
|
{ |
3360 |
|
/* If just an LD reloc, we'll just use |
3361 |
|
htab->tlsld_got.offset. */ |
3362 |
|
if (htab->tlsld_got.offset == (bfd_vma) -1) |
3363 |
|
{ |
3364 |
|
htab->tlsld_got.offset = s->size; |
3365 |
|
s->size += 8; |
3366 |
|
if (info->shared) |
3367 |
|
srel->size += sizeof (Elf32_External_Rela); |
3368 |
|
} |
3369 |
|
*local_got = (bfd_vma) -1; |
3370 |
|
} |
3371 |
|
else |
3372 |
|
{ |
3373 |
|
*local_got = s->size; |
3374 |
|
if ((*lgot_masks & TLS_TLS) != 0) |
3375 |
|
{ |
3376 |
|
if ((*lgot_masks & TLS_GD) != 0) |
3377 |
|
s->size += 8; |
3378 |
|
if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0) |
3379 |
|
s->size += 4; |
3380 |
|
if ((*lgot_masks & TLS_DTPREL) != 0) |
3381 |
|
s->size += 4; |
3382 |
|
} |
3383 |
|
else |
3384 |
|
s->size += 4; |
3385 |
|
if (info->shared) |
3386 |
|
srel->size += ((s->size - *local_got) / 4 |
3387 |
|
* sizeof (Elf32_External_Rela)); |
3388 |
|
} |
3389 |
|
} |
3390 |
|
else |
3391 |
|
*local_got = (bfd_vma) -1; |
3392 |
|
} |
3393 |
|
|
3394 |
|
/* Allocate space for global sym dynamic relocs. */ |
3395 |
|
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info); |
3396 |
|
|
3397 |
|
/* We've now determined the sizes of the various dynamic sections. |
3398 |
|
Allocate memory for them. */ |
3399 |
|
relocs = FALSE; |
3400 |
|
for (s = htab->elf.dynobj->sections; s != NULL; s = s->next) |
3401 |
|
{ |
3402 |
|
if ((s->flags & SEC_LINKER_CREATED) == 0) |
3403 |
|
continue; |
3404 |
|
|
3405 |
|
if (s == htab->plt |
3406 |
|
|| s == htab->got) |
3407 |
{ |
{ |
3408 |
if (s->_raw_size == 0) |
/* Strip this section if we don't need it; see the |
3409 |
|
comment below. */ |
3410 |
|
} |
3411 |
|
else if ((htab->sdata != NULL && s == htab->sdata->section) |
3412 |
|
|| (htab->sdata2 != NULL && s == htab->sdata2->section)) |
3413 |
|
{ |
3414 |
|
if (s->size == 0) |
3415 |
|
/* Don't strip these sections. We need them because they |
3416 |
|
define _SDA_BASE_ and _SDA2_BASE_. crt1.o makes a |
3417 |
|
reference to _SDA_BASE_ to set up r13. */ |
3418 |
|
continue; |
3419 |
|
} |
3420 |
|
else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) |
3421 |
|
{ |
3422 |
|
if (s->size == 0) |
3423 |
{ |
{ |
3424 |
/* If we don't need this section, strip it from the |
/* If we don't need this section, strip it from the |
3425 |
output file. This is mostly to handle .rela.bss and |
output file. This is mostly to handle .rela.bss and |
3430 |
adjust_dynamic_symbol is called, and it is that |
adjust_dynamic_symbol is called, and it is that |
3431 |
function which decides whether anything needs to go |
function which decides whether anything needs to go |
3432 |
into these sections. */ |
into these sections. */ |
|
strip = true; |
|
3433 |
} |
} |
3434 |
else |
else |
3435 |
{ |
{ |
3436 |
/* Remember whether there are any relocation sections. */ |
/* Remember whether there are any relocation sections. */ |
3437 |
relocs = true; |
relocs = TRUE; |
3438 |
|
|
3439 |
/* We use the reloc_count field as a counter if we need |
/* We use the reloc_count field as a counter if we need |
3440 |
to copy relocs into the output file. */ |
to copy relocs into the output file. */ |
3441 |
s->reloc_count = 0; |
s->reloc_count = 0; |
3442 |
} |
} |
3443 |
} |
} |
3444 |
else if (strcmp (name, ".got") != 0 |
else |
|
&& strcmp (name, ".sdata") != 0 |
|
|
&& strcmp (name, ".sdata2") != 0) |
|
3445 |
{ |
{ |
3446 |
/* It's not one of our sections, so don't allocate space. */ |
/* It's not one of our sections, so don't allocate space. */ |
3447 |
continue; |
continue; |
3448 |
} |
} |
3449 |
|
|
3450 |
if (strip) |
if (s->size == 0) |
3451 |
{ |
{ |
3452 |
_bfd_strip_section_from_output (info, s); |
_bfd_strip_section_from_output (info, s); |
3453 |
continue; |
continue; |
3454 |
} |
} |
3455 |
|
|
3456 |
/* Allocate memory for the section contents. */ |
/* Allocate memory for the section contents. */ |
3457 |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); |
s->contents = bfd_zalloc (htab->elf.dynobj, s->size); |
3458 |
if (s->contents == NULL && s->_raw_size != 0) |
if (s->contents == NULL) |
3459 |
return false; |
return FALSE; |
3460 |
} |
} |
3461 |
|
|
3462 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (htab->elf.dynamic_sections_created) |
3463 |
{ |
{ |
3464 |
/* Add some entries to the .dynamic section. We fill in the |
/* Add some entries to the .dynamic section. We fill in the |
3465 |
values later, in ppc_elf_finish_dynamic_sections, but we |
values later, in ppc_elf_finish_dynamic_sections, but we |
3467 |
the .dynamic section. The DT_DEBUG entry is filled in by the |
the .dynamic section. The DT_DEBUG entry is filled in by the |
3468 |
dynamic linker and used by the debugger. */ |
dynamic linker and used by the debugger. */ |
3469 |
#define add_dynamic_entry(TAG, VAL) \ |
#define add_dynamic_entry(TAG, VAL) \ |
3470 |
bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) |
_bfd_elf_add_dynamic_entry (info, TAG, VAL) |
3471 |
|
|
3472 |
if (!info->shared) |
if (info->executable) |
3473 |
{ |
{ |
3474 |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
3475 |
return false; |
return FALSE; |
3476 |
} |
} |
3477 |
|
|
3478 |
if (plt) |
if (htab->plt != NULL && htab->plt->size != 0) |
3479 |
{ |
{ |
3480 |
if (!add_dynamic_entry (DT_PLTGOT, 0) |
if (!add_dynamic_entry (DT_PLTGOT, 0) |
3481 |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
3482 |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
3483 |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
3484 |
return false; |
return FALSE; |
3485 |
} |
} |
3486 |
|
|
3487 |
if (relocs) |
if (relocs) |
3489 |
if (!add_dynamic_entry (DT_RELA, 0) |
if (!add_dynamic_entry (DT_RELA, 0) |
3490 |
|| !add_dynamic_entry (DT_RELASZ, 0) |
|| !add_dynamic_entry (DT_RELASZ, 0) |
3491 |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) |
3492 |
return false; |
return FALSE; |
3493 |
} |
} |
3494 |
|
|
3495 |
|
/* If any dynamic relocs apply to a read-only section, then we |
3496 |
|
need a DT_TEXTREL entry. */ |
3497 |
|
if ((info->flags & DF_TEXTREL) == 0) |
3498 |
|
elf_link_hash_traverse (elf_hash_table (info), readonly_dynrelocs, |
3499 |
|
info); |
3500 |
|
|
3501 |
if ((info->flags & DF_TEXTREL) != 0) |
if ((info->flags & DF_TEXTREL) != 0) |
3502 |
{ |
{ |
3503 |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
3504 |
return false; |
return FALSE; |
|
info->flags |= DF_TEXTREL; |
|
3505 |
} |
} |
3506 |
} |
} |
3507 |
#undef add_dynamic_entry |
#undef add_dynamic_entry |
3508 |
|
|
3509 |
return true; |
return TRUE; |
3510 |
} |
} |
3511 |
|
|
3512 |
|
static bfd_boolean |
3513 |
|
update_local_sym_info (bfd *abfd, |
3514 |
|
Elf_Internal_Shdr *symtab_hdr, |
3515 |
|
unsigned long r_symndx, |
3516 |
|
int tls_type) |
3517 |
|
{ |
3518 |
|
bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd); |
3519 |
|
char *local_got_tls_masks; |
3520 |
|
|
3521 |
|
if (local_got_refcounts == NULL) |
3522 |
|
{ |
3523 |
|
bfd_size_type size = symtab_hdr->sh_info; |
3524 |
|
|
3525 |
|
size *= sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks); |
3526 |
|
local_got_refcounts = bfd_zalloc (abfd, size); |
3527 |
|
if (local_got_refcounts == NULL) |
3528 |
|
return FALSE; |
3529 |
|
elf_local_got_refcounts (abfd) = local_got_refcounts; |
3530 |
|
} |
3531 |
|
|
3532 |
|
local_got_refcounts[r_symndx] += 1; |
3533 |
|
local_got_tls_masks = (char *) (local_got_refcounts + symtab_hdr->sh_info); |
3534 |
|
local_got_tls_masks[r_symndx] |= tls_type; |
3535 |
|
return TRUE; |
3536 |
|
} |
3537 |
|
|
3538 |
|
static void |
3539 |
|
bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) |
3540 |
|
{ |
3541 |
|
(*_bfd_error_handler) |
3542 |
|
(_("%B: relocation %s cannot be used when making a shared object"), |
3543 |
|
abfd, |
3544 |
|
ppc_elf_howto_table[r_type]->name); |
3545 |
|
bfd_set_error (bfd_error_bad_value); |
3546 |
|
} |
3547 |
|
|
3548 |
/* Look through the relocs for a section during the first phase, and |
/* Look through the relocs for a section during the first phase, and |
3549 |
allocate space in the global offset table or procedure linkage |
allocate space in the global offset table or procedure linkage |
3550 |
table. */ |
table. */ |
3551 |
|
|
3552 |
static boolean |
static bfd_boolean |
3553 |
ppc_elf_check_relocs (abfd, info, sec, relocs) |
ppc_elf_check_relocs (bfd *abfd, |
3554 |
bfd *abfd; |
struct bfd_link_info *info, |
3555 |
struct bfd_link_info *info; |
asection *sec, |
3556 |
asection *sec; |
const Elf_Internal_Rela *relocs) |
|
const Elf_Internal_Rela *relocs; |
|
3557 |
{ |
{ |
3558 |
bfd *dynobj; |
struct ppc_elf_link_hash_table *htab; |
3559 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
3560 |
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; |
struct elf_link_hash_entry **sym_hashes; |
3561 |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel; |
3562 |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
|
bfd_signed_vma *local_got_refcounts; |
|
|
elf_linker_section_t *sdata; |
|
|
elf_linker_section_t *sdata2; |
|
3563 |
asection *sreloc; |
asection *sreloc; |
|
asection *sgot = NULL; |
|
|
asection *srelgot = NULL; |
|
3564 |
|
|
3565 |
if (info->relocateable) |
if (info->relocatable) |
3566 |
return true; |
return TRUE; |
3567 |
|
|
3568 |
|
/* Don't do anything special with non-loaded, non-alloced sections. |
3569 |
|
In particular, any relocs in such sections should not affect GOT |
3570 |
|
and PLT reference counting (ie. we don't allow them to create GOT |
3571 |
|
or PLT entries), there's no possibility or desire to optimize TLS |
3572 |
|
relocs, and there's not much point in propagating relocs to shared |
3573 |
|
libs that the dynamic linker won't relocate. */ |
3574 |
|
if ((sec->flags & SEC_ALLOC) == 0) |
3575 |
|
return TRUE; |
3576 |
|
|
3577 |
#ifdef DEBUG |
#ifdef DEBUG |
3578 |
fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n", |
_bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B", |
3579 |
bfd_get_section_name (abfd, sec), |
sec, abfd); |
|
bfd_archive_filename (abfd)); |
|
3580 |
#endif |
#endif |
3581 |
|
|
3582 |
|
/* Initialize howto table if not already done. */ |
3583 |
|
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
3584 |
|
ppc_elf_howto_init (); |
3585 |
|
|
3586 |
/* Create the linker generated sections all the time so that the |
/* Create the linker generated sections all the time so that the |
3587 |
special symbols are created. */ |
special symbols are created. */ |
3588 |
|
htab = ppc_elf_hash_table (info); |
3589 |
if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL) |
if (htab->sdata == NULL) |
3590 |
{ |
{ |
3591 |
sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); |
htab->sdata = ppc_elf_create_linker_section (abfd, info, |
3592 |
if (!sdata) |
LINKER_SECTION_SDATA); |
3593 |
return false; |
if (htab->sdata == NULL) |
3594 |
|
return FALSE; |
3595 |
} |
} |
3596 |
|
|
3597 |
if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL) |
if (htab->sdata2 == NULL) |
3598 |
{ |
{ |
3599 |
sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2); |
htab->sdata2 = ppc_elf_create_linker_section (abfd, info, |
3600 |
if (!sdata2) |
LINKER_SECTION_SDATA2); |
3601 |
return false; |
if (htab->sdata2 == NULL) |
3602 |
|
return FALSE; |
3603 |
} |
} |
3604 |
|
|
|
dynobj = elf_hash_table (info)->dynobj; |
|
3605 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
|
local_got_refcounts = elf_local_got_refcounts (abfd); |
|
|
|
|
3606 |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
|
sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); |
|
|
if (!elf_bad_symtab (abfd)) |
|
|
sym_hashes_end -= symtab_hdr->sh_info; |
|
|
|
|
3607 |
sreloc = NULL; |
sreloc = NULL; |
3608 |
|
|
3609 |
rel_end = relocs + sec->reloc_count; |
rel_end = relocs + sec->reloc_count; |
3610 |
for (rel = relocs; rel < rel_end; rel++) |
for (rel = relocs; rel < rel_end; rel++) |
3611 |
{ |
{ |
3612 |
unsigned long r_symndx; |
unsigned long r_symndx; |
3613 |
|
enum elf_ppc_reloc_type r_type; |
3614 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
3615 |
|
int tls_type = 0; |
3616 |
|
|
3617 |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_symndx = ELF32_R_SYM (rel->r_info); |
3618 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
3625 |
startup code. */ |
startup code. */ |
3626 |
if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
3627 |
{ |
{ |
3628 |
if (sgot == NULL) |
if (htab->got == NULL) |
3629 |
{ |
{ |
3630 |
if (dynobj == NULL) |
if (htab->elf.dynobj == NULL) |
3631 |
elf_hash_table (info)->dynobj = dynobj = abfd; |
htab->elf.dynobj = abfd; |
3632 |
sgot = ppc_elf_create_got (dynobj, info); |
if (!ppc_elf_create_got (htab->elf.dynobj, info)) |
3633 |
if (sgot == NULL) |
return FALSE; |
|
return false; |
|
3634 |
} |
} |
3635 |
} |
} |
3636 |
|
|
3637 |
switch (ELF32_R_TYPE (rel->r_info)) |
r_type = ELF32_R_TYPE (rel->r_info); |
3638 |
|
switch (r_type) |
3639 |
{ |
{ |
3640 |
/* GOT16 relocations */ |
case R_PPC_GOT_TLSLD16: |
3641 |
|
case R_PPC_GOT_TLSLD16_LO: |
3642 |
|
case R_PPC_GOT_TLSLD16_HI: |
3643 |
|
case R_PPC_GOT_TLSLD16_HA: |
3644 |
|
htab->tlsld_got.refcount += 1; |
3645 |
|
tls_type = TLS_TLS | TLS_LD; |
3646 |
|
goto dogottls; |
3647 |
|
|
3648 |
|
case R_PPC_GOT_TLSGD16: |
3649 |
|
case R_PPC_GOT_TLSGD16_LO: |
3650 |
|
case R_PPC_GOT_TLSGD16_HI: |
3651 |
|
case R_PPC_GOT_TLSGD16_HA: |
3652 |
|
tls_type = TLS_TLS | TLS_GD; |
3653 |
|
goto dogottls; |
3654 |
|
|
3655 |
|
case R_PPC_GOT_TPREL16: |
3656 |
|
case R_PPC_GOT_TPREL16_LO: |
3657 |
|
case R_PPC_GOT_TPREL16_HI: |
3658 |
|
case R_PPC_GOT_TPREL16_HA: |
3659 |
|
if (info->shared) |
3660 |
|
info->flags |= DF_STATIC_TLS; |
3661 |
|
tls_type = TLS_TLS | TLS_TPREL; |
3662 |
|
goto dogottls; |
3663 |
|
|
3664 |
|
case R_PPC_GOT_DTPREL16: |
3665 |
|
case R_PPC_GOT_DTPREL16_LO: |
3666 |
|
case R_PPC_GOT_DTPREL16_HI: |
3667 |
|
case R_PPC_GOT_DTPREL16_HA: |
3668 |
|
tls_type = TLS_TLS | TLS_DTPREL; |
3669 |
|
dogottls: |
3670 |
|
sec->has_tls_reloc = 1; |
3671 |
|
/* Fall thru */ |
3672 |
|
|
3673 |
|
/* GOT16 relocations */ |
3674 |
case R_PPC_GOT16: |
case R_PPC_GOT16: |
3675 |
case R_PPC_GOT16_LO: |
case R_PPC_GOT16_LO: |
3676 |
case R_PPC_GOT16_HI: |
case R_PPC_GOT16_HI: |
3677 |
case R_PPC_GOT16_HA: |
case R_PPC_GOT16_HA: |
3678 |
/* This symbol requires a global offset table entry. */ |
/* This symbol requires a global offset table entry. */ |
3679 |
|
if (htab->got == NULL) |
|
if (sgot == NULL) |
|
|
{ |
|
|
if (dynobj == NULL) |
|
|
elf_hash_table (info)->dynobj = dynobj = abfd; |
|
|
sgot = ppc_elf_create_got (dynobj, info); |
|
|
if (sgot == NULL) |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (srelgot == NULL |
|
|
&& (h != NULL || info->shared)) |
|
3680 |
{ |
{ |
3681 |
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
if (htab->elf.dynobj == NULL) |
3682 |
if (srelgot == NULL) |
htab->elf.dynobj = abfd; |
3683 |
{ |
if (!ppc_elf_create_got (htab->elf.dynobj, info)) |
3684 |
srelgot = bfd_make_section (dynobj, ".rela.got"); |
return FALSE; |
|
if (srelgot == NULL |
|
|
|| ! bfd_set_section_flags (dynobj, srelgot, |
|
|
(SEC_ALLOC |
|
|
| SEC_LOAD |
|
|
| SEC_HAS_CONTENTS |
|
|
| SEC_IN_MEMORY |
|
|
| SEC_LINKER_CREATED |
|
|
| SEC_READONLY)) |
|
|
|| ! bfd_set_section_alignment (dynobj, srelgot, 2)) |
|
|
return false; |
|
|
} |
|
3685 |
} |
} |
|
|
|
3686 |
if (h != NULL) |
if (h != NULL) |
3687 |
{ |
{ |
3688 |
if (h->got.refcount == 0) |
h->got.refcount += 1; |
3689 |
{ |
ppc_elf_hash_entry (h)->tls_mask |= tls_type; |
|
/* Make sure this symbol is output as a dynamic symbol. */ |
|
|
if (h->dynindx == -1) |
|
|
if (!bfd_elf32_link_record_dynamic_symbol (info, h)) |
|
|
return false; |
|
|
|
|
|
/* Allocate space in the .got. */ |
|
|
sgot->_raw_size += 4; |
|
|
/* Allocate relocation space. */ |
|
|
srelgot->_raw_size += sizeof (Elf32_External_Rela); |
|
|
} |
|
|
h->got.refcount++; |
|
3690 |
} |
} |
3691 |
else |
else |
3692 |
{ |
/* This is a global offset table entry for a local symbol. */ |
3693 |
/* This is a global offset table entry for a local symbol. */ |
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type)) |
3694 |
if (local_got_refcounts == NULL) |
return FALSE; |
|
{ |
|
|
bfd_size_type size; |
|
|
|
|
|
size = symtab_hdr->sh_info; |
|
|
size *= sizeof (bfd_signed_vma); |
|
|
local_got_refcounts |
|
|
= (bfd_signed_vma *) bfd_zalloc (abfd, size); |
|
|
if (local_got_refcounts == NULL) |
|
|
return false; |
|
|
elf_local_got_refcounts (abfd) = local_got_refcounts; |
|
|
} |
|
|
if (local_got_refcounts[r_symndx] == 0) |
|
|
{ |
|
|
sgot->_raw_size += 4; |
|
|
|
|
|
/* If we are generating a shared object, we need to |
|
|
output a R_PPC_RELATIVE reloc so that the |
|
|
dynamic linker can adjust this GOT entry. */ |
|
|
if (info->shared) |
|
|
srelgot->_raw_size += sizeof (Elf32_External_Rela); |
|
|
} |
|
|
local_got_refcounts[r_symndx]++; |
|
|
} |
|
3695 |
break; |
break; |
3696 |
|
|
3697 |
/* Indirect .sdata relocation */ |
/* Indirect .sdata relocation. */ |
3698 |
case R_PPC_EMB_SDAI16: |
case R_PPC_EMB_SDAI16: |
3699 |
if (info->shared) |
if (info->shared) |
3700 |
{ |
{ |
3701 |
((*_bfd_error_handler) |
bad_shared_reloc (abfd, r_type); |
3702 |
(_("%s: relocation %s cannot be used when making a shared object"), |
return FALSE; |
|
bfd_archive_filename (abfd), "R_PPC_EMB_SDAI16")); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (srelgot == NULL && (h != NULL || info->shared)) |
|
|
{ |
|
|
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
|
|
if (srelgot == NULL) |
|
|
{ |
|
|
srelgot = bfd_make_section (dynobj, ".rela.got"); |
|
|
if (srelgot == NULL |
|
|
|| ! bfd_set_section_flags (dynobj, srelgot, |
|
|
(SEC_ALLOC |
|
|
| SEC_LOAD |
|
|
| SEC_HAS_CONTENTS |
|
|
| SEC_IN_MEMORY |
|
|
| SEC_LINKER_CREATED |
|
|
| SEC_READONLY)) |
|
|
|| ! bfd_set_section_alignment (dynobj, srelgot, 2)) |
|
|
return false; |
|
|
} |
|
3703 |
} |
} |
3704 |
|
if (!elf_create_pointer_linker_section (abfd, info, |
3705 |
if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel)) |
htab->sdata, h, rel)) |
3706 |
return false; |
return FALSE; |
|
|
|
3707 |
break; |
break; |
3708 |
|
|
3709 |
/* Indirect .sdata2 relocation */ |
/* Indirect .sdata2 relocation. */ |
3710 |
case R_PPC_EMB_SDA2I16: |
case R_PPC_EMB_SDA2I16: |
3711 |
if (info->shared) |
if (info->shared) |
3712 |
{ |
{ |
3713 |
((*_bfd_error_handler) |
bad_shared_reloc (abfd, r_type); |
3714 |
(_("%s: relocation %s cannot be used when making a shared object"), |
return FALSE; |
|
bfd_archive_filename (abfd), "R_PPC_EMB_SDA2I16")); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (srelgot == NULL && (h != NULL || info->shared)) |
|
|
{ |
|
|
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
|
|
if (srelgot == NULL) |
|
|
{ |
|
|
srelgot = bfd_make_section (dynobj, ".rela.got"); |
|
|
if (srelgot == NULL |
|
|
|| ! bfd_set_section_flags (dynobj, srelgot, |
|
|
(SEC_ALLOC |
|
|
| SEC_LOAD |
|
|
| SEC_HAS_CONTENTS |
|
|
| SEC_IN_MEMORY |
|
|
| SEC_LINKER_CREATED |
|
|
| SEC_READONLY)) |
|
|
|| ! bfd_set_section_alignment (dynobj, srelgot, 2)) |
|
|
return false; |
|
|
} |
|
3715 |
} |
} |
3716 |
|
if (!elf_create_pointer_linker_section (abfd, info, |
3717 |
if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel)) |
htab->sdata2, h, rel)) |
3718 |
return false; |
return FALSE; |
|
|
|
3719 |
break; |
break; |
3720 |
|
|
3721 |
case R_PPC_SDAREL16: |
case R_PPC_SDAREL16: |
3722 |
case R_PPC_EMB_SDA2REL: |
case R_PPC_EMB_SDA2REL: |
3723 |
case R_PPC_EMB_SDA21: |
case R_PPC_EMB_SDA21: |
3724 |
|
case R_PPC_EMB_RELSDA: |
3725 |
|
case R_PPC_EMB_NADDR32: |
3726 |
|
case R_PPC_EMB_NADDR16: |
3727 |
|
case R_PPC_EMB_NADDR16_LO: |
3728 |
|
case R_PPC_EMB_NADDR16_HI: |
3729 |
|
case R_PPC_EMB_NADDR16_HA: |
3730 |
if (info->shared) |
if (info->shared) |
3731 |
{ |
{ |
3732 |
((*_bfd_error_handler) |
bad_shared_reloc (abfd, r_type); |
3733 |
(_("%s: relocation %s cannot be used when making a shared object"), |
return FALSE; |
|
bfd_archive_filename (abfd), |
|
|
ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name)); |
|
|
return false; |
|
3734 |
} |
} |
3735 |
break; |
break; |
3736 |
|
|
3737 |
case R_PPC_PLT32: |
case R_PPC_PLT32: |
3738 |
case R_PPC_PLTREL24: |
case R_PPC_PLTREL24: |
3739 |
|
case R_PPC_PLTREL32: |
3740 |
case R_PPC_PLT16_LO: |
case R_PPC_PLT16_LO: |
3741 |
case R_PPC_PLT16_HI: |
case R_PPC_PLT16_HI: |
3742 |
case R_PPC_PLT16_HA: |
case R_PPC_PLT16_HA: |
3744 |
fprintf (stderr, "Reloc requires a PLT entry\n"); |
fprintf (stderr, "Reloc requires a PLT entry\n"); |
3745 |
#endif |
#endif |
3746 |
/* This symbol requires a procedure linkage table entry. We |
/* This symbol requires a procedure linkage table entry. We |
3747 |
actually build the entry in adjust_dynamic_symbol, |
actually build the entry in finish_dynamic_symbol, |
3748 |
because this might be a case of linking PIC code without |
because this might be a case of linking PIC code without |
3749 |
linking in any dynamic objects, in which case we don't |
linking in any dynamic objects, in which case we don't |
3750 |
need to generate a procedure linkage table after all. */ |
need to generate a procedure linkage table after all. */ |
3751 |
|
|
3752 |
if (h == NULL) |
if (h == NULL) |
3753 |
{ |
{ |
3754 |
/* It does not make sense to have a procedure linkage |
/* It does not make sense to have a procedure linkage |
3755 |
table entry for a local symbol. */ |
table entry for a local symbol. */ |
3756 |
|
(*_bfd_error_handler) (_("%B(%A+0x%lx): %s reloc against " |
3757 |
|
"local symbol"), |
3758 |
|
abfd, |
3759 |
|
sec, |
3760 |
|
(long) rel->r_offset, |
3761 |
|
ppc_elf_howto_table[r_type]->name); |
3762 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
3763 |
return false; |
return FALSE; |
3764 |
} |
} |
3765 |
|
|
3766 |
/* Make sure this symbol is output as a dynamic symbol. */ |
h->needs_plt = 1; |
|
if (h->dynindx == -1) |
|
|
{ |
|
|
if (! bfd_elf32_link_record_dynamic_symbol (info, h)) |
|
|
return false; |
|
|
} |
|
|
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; |
|
3767 |
h->plt.refcount++; |
h->plt.refcount++; |
3768 |
break; |
break; |
3769 |
|
|
3774 |
case R_PPC_SECTOFF_LO: |
case R_PPC_SECTOFF_LO: |
3775 |
case R_PPC_SECTOFF_HI: |
case R_PPC_SECTOFF_HI: |
3776 |
case R_PPC_SECTOFF_HA: |
case R_PPC_SECTOFF_HA: |
3777 |
|
case R_PPC_DTPREL16: |
3778 |
|
case R_PPC_DTPREL16_LO: |
3779 |
|
case R_PPC_DTPREL16_HI: |
3780 |
|
case R_PPC_DTPREL16_HA: |
3781 |
|
case R_PPC_TOC16: |
3782 |
break; |
break; |
3783 |
|
|
3784 |
/* This refers only to functions defined in the shared library */ |
/* This are just markers. */ |
3785 |
|
case R_PPC_TLS: |
3786 |
|
case R_PPC_EMB_MRKREF: |
3787 |
|
case R_PPC_NONE: |
3788 |
|
case R_PPC_max: |
3789 |
|
break; |
3790 |
|
|
3791 |
|
/* These should only appear in dynamic objects. */ |
3792 |
|
case R_PPC_COPY: |
3793 |
|
case R_PPC_GLOB_DAT: |
3794 |
|
case R_PPC_JMP_SLOT: |
3795 |
|
case R_PPC_RELATIVE: |
3796 |
|
break; |
3797 |
|
|
3798 |
|
/* These aren't handled yet. We'll report an error later. */ |
3799 |
|
case R_PPC_ADDR30: |
3800 |
|
case R_PPC_EMB_RELSEC16: |
3801 |
|
case R_PPC_EMB_RELST_LO: |
3802 |
|
case R_PPC_EMB_RELST_HI: |
3803 |
|
case R_PPC_EMB_RELST_HA: |
3804 |
|
case R_PPC_EMB_BIT_FLD: |
3805 |
|
break; |
3806 |
|
|
3807 |
|
/* This refers only to functions defined in the shared library. */ |
3808 |
case R_PPC_LOCAL24PC: |
case R_PPC_LOCAL24PC: |
3809 |
break; |
break; |
3810 |
|
|
3811 |
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
3812 |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
3813 |
case R_PPC_GNU_VTINHERIT: |
case R_PPC_GNU_VTINHERIT: |
3814 |
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
3815 |
return false; |
return FALSE; |
3816 |
break; |
break; |
3817 |
|
|
3818 |
/* This relocation describes which C++ vtable entries are actually |
/* This relocation describes which C++ vtable entries are actually |
3819 |
used. Record for later use during GC. */ |
used. Record for later use during GC. */ |
3820 |
case R_PPC_GNU_VTENTRY: |
case R_PPC_GNU_VTENTRY: |
3821 |
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
3822 |
return false; |
return FALSE; |
3823 |
break; |
break; |
3824 |
|
|
3825 |
|
/* We shouldn't really be seeing these. */ |
3826 |
|
case R_PPC_TPREL32: |
3827 |
|
if (info->shared) |
3828 |
|
info->flags |= DF_STATIC_TLS; |
3829 |
|
goto dodyn; |
3830 |
|
|
3831 |
|
/* Nor these. */ |
3832 |
|
case R_PPC_DTPMOD32: |
3833 |
|
case R_PPC_DTPREL32: |
3834 |
|
goto dodyn; |
3835 |
|
|
3836 |
|
case R_PPC_TPREL16: |
3837 |
|
case R_PPC_TPREL16_LO: |
3838 |
|
case R_PPC_TPREL16_HI: |
3839 |
|
case R_PPC_TPREL16_HA: |
3840 |
|
if (info->shared) |
3841 |
|
info->flags |= DF_STATIC_TLS; |
3842 |
|
goto dodyn; |
3843 |
|
|
3844 |
/* When creating a shared object, we must copy these |
/* When creating a shared object, we must copy these |
3845 |
relocs into the output file. We create a reloc |
relocs into the output file. We create a reloc |
3846 |
section in dynobj and make room for the reloc. */ |
section in dynobj and make room for the reloc. */ |
3850 |
case R_PPC_REL14_BRNTAKEN: |
case R_PPC_REL14_BRNTAKEN: |
3851 |
case R_PPC_REL32: |
case R_PPC_REL32: |
3852 |
if (h == NULL |
if (h == NULL |
3853 |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
|
|| SYMBOL_REFERENCES_LOCAL (info, h)) |
|
3854 |
break; |
break; |
3855 |
/* fall through */ |
/* fall through */ |
3856 |
|
|
3857 |
default: |
case R_PPC_ADDR32: |
3858 |
if (info->shared && (sec->flags & SEC_ALLOC) != 0) |
case R_PPC_ADDR24: |
3859 |
|
case R_PPC_ADDR16: |
3860 |
|
case R_PPC_ADDR16_LO: |
3861 |
|
case R_PPC_ADDR16_HI: |
3862 |
|
case R_PPC_ADDR16_HA: |
3863 |
|
case R_PPC_ADDR14: |
3864 |
|
case R_PPC_ADDR14_BRTAKEN: |
3865 |
|
case R_PPC_ADDR14_BRNTAKEN: |
3866 |
|
case R_PPC_UADDR32: |
3867 |
|
case R_PPC_UADDR16: |
3868 |
|
if (h != NULL && !info->shared) |
3869 |
{ |
{ |
3870 |
|
/* We may need a plt entry if the symbol turns out to be |
3871 |
|
a function defined in a dynamic object. */ |
3872 |
|
h->plt.refcount++; |
3873 |
|
|
3874 |
|
/* We may need a copy reloc too. */ |
3875 |
|
h->non_got_ref = 1; |
3876 |
|
} |
3877 |
|
|
3878 |
|
dodyn: |
3879 |
|
/* If we are creating a shared library, and this is a reloc |
3880 |
|
against a global symbol, or a non PC relative reloc |
3881 |
|
against a local symbol, then we need to copy the reloc |
3882 |
|
into the shared library. However, if we are linking with |
3883 |
|
-Bsymbolic, we do not need to copy a reloc against a |
3884 |
|
global symbol which is defined in an object we are |
3885 |
|
including in the link (i.e., DEF_REGULAR is set). At |
3886 |
|
this point we have not seen all the input files, so it is |
3887 |
|
possible that DEF_REGULAR is not set now but will be set |
3888 |
|
later (it is never cleared). In case of a weak definition, |
3889 |
|
DEF_REGULAR may be cleared later by a strong definition in |
3890 |
|
a shared library. We account for that possibility below by |
3891 |
|
storing information in the dyn_relocs field of the hash |
3892 |
|
table entry. A similar situation occurs when creating |
3893 |
|
shared libraries and symbol visibility changes render the |
3894 |
|
symbol local. |
3895 |
|
|
3896 |
|
If on the other hand, we are creating an executable, we |
3897 |
|
may need to keep relocations for symbols satisfied by a |
3898 |
|
dynamic library if we manage to avoid copy relocs for the |
3899 |
|
symbol. */ |
3900 |
|
if ((info->shared |
3901 |
|
&& (MUST_BE_DYN_RELOC (r_type) |
3902 |
|
|| (h != NULL |
3903 |
|
&& (! info->symbolic |
3904 |
|
|| h->root.type == bfd_link_hash_defweak |
3905 |
|
|| !h->def_regular)))) |
3906 |
|
|| (ELIMINATE_COPY_RELOCS |
3907 |
|
&& !info->shared |
3908 |
|
&& h != NULL |
3909 |
|
&& (h->root.type == bfd_link_hash_defweak |
3910 |
|
|| !h->def_regular))) |
3911 |
|
{ |
3912 |
|
struct ppc_elf_dyn_relocs *p; |
3913 |
|
struct ppc_elf_dyn_relocs **head; |
3914 |
|
|
3915 |
#ifdef DEBUG |
#ifdef DEBUG |
3916 |
fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n", |
fprintf (stderr, |
3917 |
(h && h->root.root.string) ? h->root.root.string : "<unknown>"); |
"ppc_elf_check_relocs needs to " |
3918 |
|
"create relocation for %s\n", |
3919 |
|
(h && h->root.root.string |
3920 |
|
? h->root.root.string : "<unknown>")); |
3921 |
#endif |
#endif |
3922 |
if (sreloc == NULL) |
if (sreloc == NULL) |
3923 |
{ |
{ |
3928 |
elf_elfheader (abfd)->e_shstrndx, |
elf_elfheader (abfd)->e_shstrndx, |
3929 |
elf_section_data (sec)->rel_hdr.sh_name)); |
elf_section_data (sec)->rel_hdr.sh_name)); |
3930 |
if (name == NULL) |
if (name == NULL) |
3931 |
return false; |
return FALSE; |
3932 |
|
|
3933 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
3934 |
&& strcmp (bfd_get_section_name (abfd, sec), |
&& strcmp (bfd_get_section_name (abfd, sec), |
3935 |
name + 5) == 0); |
name + 5) == 0); |
3936 |
|
|
3937 |
sreloc = bfd_get_section_by_name (dynobj, name); |
sreloc = bfd_get_section_by_name (htab->elf.dynobj, name); |
3938 |
if (sreloc == NULL) |
if (sreloc == NULL) |
3939 |
{ |
{ |
3940 |
flagword flags; |
flagword flags; |
3941 |
|
|
3942 |
sreloc = bfd_make_section (dynobj, name); |
sreloc = bfd_make_section (htab->elf.dynobj, name); |
3943 |
flags = (SEC_HAS_CONTENTS | SEC_READONLY |
flags = (SEC_HAS_CONTENTS | SEC_READONLY |
3944 |
| SEC_IN_MEMORY | SEC_LINKER_CREATED); |
| SEC_IN_MEMORY | SEC_LINKER_CREATED |
3945 |
if ((sec->flags & SEC_ALLOC) != 0) |
| SEC_ALLOC | SEC_LOAD); |
|
flags |= SEC_ALLOC | SEC_LOAD; |
|
3946 |
if (sreloc == NULL |
if (sreloc == NULL |
3947 |
|| ! bfd_set_section_flags (dynobj, sreloc, flags) |
|| ! bfd_set_section_flags (htab->elf.dynobj, |
3948 |
|| ! bfd_set_section_alignment (dynobj, sreloc, 2)) |
sreloc, flags) |
3949 |
return false; |
|| ! bfd_set_section_alignment (htab->elf.dynobj, |
3950 |
|
sreloc, 2)) |
3951 |
|
return FALSE; |
3952 |
} |
} |
3953 |
if (sec->flags & SEC_READONLY) |
elf_section_data (sec)->sreloc = sreloc; |
3954 |
info->flags |= DF_TEXTREL; |
} |
3955 |
|
|
3956 |
|
/* If this is a global symbol, we count the number of |
3957 |
|
relocations we need for this symbol. */ |
3958 |
|
if (h != NULL) |
3959 |
|
{ |
3960 |
|
head = &ppc_elf_hash_entry (h)->dyn_relocs; |
3961 |
|
} |
3962 |
|
else |
3963 |
|
{ |
3964 |
|
/* Track dynamic relocs needed for local syms too. |
3965 |
|
We really need local syms available to do this |
3966 |
|
easily. Oh well. */ |
3967 |
|
|
3968 |
|
asection *s; |
3969 |
|
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, |
3970 |
|
sec, r_symndx); |
3971 |
|
if (s == NULL) |
3972 |
|
return FALSE; |
3973 |
|
|
3974 |
|
head = ((struct ppc_elf_dyn_relocs **) |
3975 |
|
&elf_section_data (s)->local_dynrel); |
3976 |
} |
} |
3977 |
|
|
3978 |
sreloc->_raw_size += sizeof (Elf32_External_Rela); |
p = *head; |
3979 |
|
if (p == NULL || p->sec != sec) |
3980 |
|
{ |
3981 |
|
p = bfd_alloc (htab->elf.dynobj, sizeof *p); |
3982 |
|
if (p == NULL) |
3983 |
|
return FALSE; |
3984 |
|
p->next = *head; |
3985 |
|
*head = p; |
3986 |
|
p->sec = sec; |
3987 |
|
p->count = 0; |
3988 |
|
p->pc_count = 0; |
3989 |
|
} |
3990 |
|
|
3991 |
/* FIXME: We should here do what the m68k and i386 |
p->count += 1; |
3992 |
backends do: if the reloc is pc-relative, record it |
if (!MUST_BE_DYN_RELOC (r_type)) |
3993 |
in case it turns out that the reloc is unnecessary |
p->pc_count += 1; |
|
because the symbol is forced local by versioning or |
|
|
we are linking with -Bdynamic. Fortunately this |
|
|
case is not frequent. */ |
|
3994 |
} |
} |
3995 |
|
|
3996 |
break; |
break; |
3997 |
} |
} |
3998 |
} |
} |
3999 |
|
|
4000 |
return true; |
return TRUE; |
4001 |
} |
} |
4002 |
|
|
4003 |
/* Return the section that should be marked against GC for a given |
/* Return the section that should be marked against GC for a given |
4004 |
relocation. */ |
relocation. */ |
4005 |
|
|
4006 |
static asection * |
static asection * |
4007 |
ppc_elf_gc_mark_hook (sec, info, rel, h, sym) |
ppc_elf_gc_mark_hook (asection *sec, |
4008 |
asection *sec; |
struct bfd_link_info *info ATTRIBUTE_UNUSED, |
4009 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
Elf_Internal_Rela *rel, |
4010 |
Elf_Internal_Rela *rel; |
struct elf_link_hash_entry *h, |
4011 |
struct elf_link_hash_entry *h; |
Elf_Internal_Sym *sym) |
|
Elf_Internal_Sym *sym; |
|
4012 |
{ |
{ |
4013 |
if (h != NULL) |
if (h != NULL) |
4014 |
{ |
{ |
4039 |
return NULL; |
return NULL; |
4040 |
} |
} |
4041 |
|
|
4042 |
/* Update the got entry reference counts for the section being removed. */ |
/* Update the got, plt and dynamic reloc reference counts for the |
4043 |
|
section being removed. */ |
4044 |
|
|
4045 |
static boolean |
static bfd_boolean |
4046 |
ppc_elf_gc_sweep_hook (abfd, info, sec, relocs) |
ppc_elf_gc_sweep_hook (bfd *abfd, |
4047 |
bfd *abfd; |
struct bfd_link_info *info, |
4048 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
asection *sec, |
4049 |
asection *sec; |
const Elf_Internal_Rela *relocs) |
|
const Elf_Internal_Rela *relocs; |
|
4050 |
{ |
{ |
4051 |
|
struct ppc_elf_link_hash_table *htab; |
4052 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
4053 |
struct elf_link_hash_entry **sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
4054 |
bfd_signed_vma *local_got_refcounts; |
bfd_signed_vma *local_got_refcounts; |
4055 |
const Elf_Internal_Rela *rel, *relend; |
const Elf_Internal_Rela *rel, *relend; |
|
unsigned long r_symndx; |
|
|
struct elf_link_hash_entry *h; |
|
4056 |
|
|
4057 |
|
if ((sec->flags & SEC_ALLOC) == 0) |
4058 |
|
return TRUE; |
4059 |
|
|
4060 |
|
elf_section_data (sec)->local_dynrel = NULL; |
4061 |
|
|
4062 |
|
htab = ppc_elf_hash_table (info); |
4063 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
4064 |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
4065 |
local_got_refcounts = elf_local_got_refcounts (abfd); |
local_got_refcounts = elf_local_got_refcounts (abfd); |
4066 |
|
|
4067 |
relend = relocs + sec->reloc_count; |
relend = relocs + sec->reloc_count; |
4068 |
for (rel = relocs; rel < relend; rel++) |
for (rel = relocs; rel < relend; rel++) |
4069 |
switch (ELF32_R_TYPE (rel->r_info)) |
{ |
4070 |
{ |
unsigned long r_symndx; |
4071 |
case R_PPC_GOT16: |
enum elf_ppc_reloc_type r_type; |
4072 |
case R_PPC_GOT16_LO: |
struct elf_link_hash_entry *h = NULL; |
4073 |
case R_PPC_GOT16_HI: |
|
4074 |
case R_PPC_GOT16_HA: |
r_symndx = ELF32_R_SYM (rel->r_info); |
4075 |
r_symndx = ELF32_R_SYM (rel->r_info); |
if (r_symndx >= symtab_hdr->sh_info) |
4076 |
if (r_symndx >= symtab_hdr->sh_info) |
{ |
4077 |
{ |
struct ppc_elf_dyn_relocs **pp, *p; |
4078 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
struct ppc_elf_link_hash_entry *eh; |
4079 |
if (h->got.refcount > 0) |
|
4080 |
h->got.refcount--; |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
4081 |
} |
while (h->root.type == bfd_link_hash_indirect |
4082 |
else if (local_got_refcounts != NULL) |
|| h->root.type == bfd_link_hash_warning) |
4083 |
{ |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
4084 |
if (local_got_refcounts[r_symndx] > 0) |
eh = (struct ppc_elf_link_hash_entry *) h; |
|
local_got_refcounts[r_symndx]--; |
|
|
} |
|
|
break; |
|
4085 |
|
|
4086 |
case R_PPC_PLT32: |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) |
4087 |
case R_PPC_PLTREL24: |
if (p->sec == sec) |
4088 |
case R_PPC_PLT16_LO: |
{ |
4089 |
case R_PPC_PLT16_HI: |
/* Everything must go for SEC. */ |
4090 |
case R_PPC_PLT16_HA: |
*pp = p->next; |
4091 |
r_symndx = ELF32_R_SYM (rel->r_info); |
break; |
4092 |
if (r_symndx >= symtab_hdr->sh_info) |
} |
4093 |
|
} |
4094 |
|
|
4095 |
|
r_type = ELF32_R_TYPE (rel->r_info); |
4096 |
|
switch (r_type) |
4097 |
|
{ |
4098 |
|
case R_PPC_GOT_TLSLD16: |
4099 |
|
case R_PPC_GOT_TLSLD16_LO: |
4100 |
|
case R_PPC_GOT_TLSLD16_HI: |
4101 |
|
case R_PPC_GOT_TLSLD16_HA: |
4102 |
|
htab->tlsld_got.refcount -= 1; |
4103 |
|
/* Fall thru */ |
4104 |
|
|
4105 |
|
case R_PPC_GOT_TLSGD16: |
4106 |
|
case R_PPC_GOT_TLSGD16_LO: |
4107 |
|
case R_PPC_GOT_TLSGD16_HI: |
4108 |
|
case R_PPC_GOT_TLSGD16_HA: |
4109 |
|
case R_PPC_GOT_TPREL16: |
4110 |
|
case R_PPC_GOT_TPREL16_LO: |
4111 |
|
case R_PPC_GOT_TPREL16_HI: |
4112 |
|
case R_PPC_GOT_TPREL16_HA: |
4113 |
|
case R_PPC_GOT_DTPREL16: |
4114 |
|
case R_PPC_GOT_DTPREL16_LO: |
4115 |
|
case R_PPC_GOT_DTPREL16_HI: |
4116 |
|
case R_PPC_GOT_DTPREL16_HA: |
4117 |
|
case R_PPC_GOT16: |
4118 |
|
case R_PPC_GOT16_LO: |
4119 |
|
case R_PPC_GOT16_HI: |
4120 |
|
case R_PPC_GOT16_HA: |
4121 |
|
if (h != NULL) |
4122 |
|
{ |
4123 |
|
if (h->got.refcount > 0) |
4124 |
|
h->got.refcount--; |
4125 |
|
} |
4126 |
|
else if (local_got_refcounts != NULL) |
4127 |
|
{ |
4128 |
|
if (local_got_refcounts[r_symndx] > 0) |
4129 |
|
local_got_refcounts[r_symndx]--; |
4130 |
|
} |
4131 |
|
break; |
4132 |
|
|
4133 |
|
case R_PPC_REL24: |
4134 |
|
case R_PPC_REL14: |
4135 |
|
case R_PPC_REL14_BRTAKEN: |
4136 |
|
case R_PPC_REL14_BRNTAKEN: |
4137 |
|
case R_PPC_REL32: |
4138 |
|
if (h == NULL |
4139 |
|
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
4140 |
|
break; |
4141 |
|
/* Fall thru */ |
4142 |
|
|
4143 |
|
case R_PPC_ADDR32: |
4144 |
|
case R_PPC_ADDR24: |
4145 |
|
case R_PPC_ADDR16: |
4146 |
|
case R_PPC_ADDR16_LO: |
4147 |
|
case R_PPC_ADDR16_HI: |
4148 |
|
case R_PPC_ADDR16_HA: |
4149 |
|
case R_PPC_ADDR14: |
4150 |
|
case R_PPC_ADDR14_BRTAKEN: |
4151 |
|
case R_PPC_ADDR14_BRNTAKEN: |
4152 |
|
case R_PPC_UADDR32: |
4153 |
|
case R_PPC_UADDR16: |
4154 |
|
case R_PPC_PLT32: |
4155 |
|
case R_PPC_PLTREL24: |
4156 |
|
case R_PPC_PLT16_LO: |
4157 |
|
case R_PPC_PLT16_HI: |
4158 |
|
case R_PPC_PLT16_HA: |
4159 |
|
if (h != NULL) |
4160 |
|
{ |
4161 |
|
if (h->plt.refcount > 0) |
4162 |
|
h->plt.refcount--; |
4163 |
|
} |
4164 |
|
break; |
4165 |
|
|
4166 |
|
default: |
4167 |
|
break; |
4168 |
|
} |
4169 |
|
} |
4170 |
|
return TRUE; |
4171 |
|
} |
4172 |
|
|
4173 |
|
/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ |
4174 |
|
|
4175 |
|
asection * |
4176 |
|
ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) |
4177 |
|
{ |
4178 |
|
struct ppc_elf_link_hash_table *htab; |
4179 |
|
|
4180 |
|
htab = ppc_elf_hash_table (info); |
4181 |
|
htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", |
4182 |
|
FALSE, FALSE, TRUE); |
4183 |
|
|
4184 |
|
return _bfd_elf_tls_setup (obfd, info); |
4185 |
|
} |
4186 |
|
|
4187 |
|
/* Run through all the TLS relocs looking for optimization |
4188 |
|
opportunities. */ |
4189 |
|
|
4190 |
|
bfd_boolean |
4191 |
|
ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, |
4192 |
|
struct bfd_link_info *info) |
4193 |
|
{ |
4194 |
|
bfd *ibfd; |
4195 |
|
asection *sec; |
4196 |
|
struct ppc_elf_link_hash_table *htab; |
4197 |
|
|
4198 |
|
if (info->relocatable || info->shared) |
4199 |
|
return TRUE; |
4200 |
|
|
4201 |
|
htab = ppc_elf_hash_table (info); |
4202 |
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) |
4203 |
|
{ |
4204 |
|
Elf_Internal_Sym *locsyms = NULL; |
4205 |
|
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; |
4206 |
|
|
4207 |
|
for (sec = ibfd->sections; sec != NULL; sec = sec->next) |
4208 |
|
if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) |
4209 |
{ |
{ |
4210 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
Elf_Internal_Rela *relstart, *rel, *relend; |
4211 |
if (h->plt.refcount > 0) |
int expecting_tls_get_addr; |
|
h->plt.refcount--; |
|
|
} |
|
|
break; |
|
4212 |
|
|
4213 |
default: |
/* Read the relocations. */ |
4214 |
break; |
relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, |
4215 |
} |
info->keep_memory); |
4216 |
|
if (relstart == NULL) |
4217 |
|
return FALSE; |
4218 |
|
|
4219 |
|
expecting_tls_get_addr = 0; |
4220 |
|
relend = relstart + sec->reloc_count; |
4221 |
|
for (rel = relstart; rel < relend; rel++) |
4222 |
|
{ |
4223 |
|
enum elf_ppc_reloc_type r_type; |
4224 |
|
unsigned long r_symndx; |
4225 |
|
struct elf_link_hash_entry *h = NULL; |
4226 |
|
char *tls_mask; |
4227 |
|
char tls_set, tls_clear; |
4228 |
|
bfd_boolean is_local; |
4229 |
|
|
4230 |
|
r_symndx = ELF32_R_SYM (rel->r_info); |
4231 |
|
if (r_symndx >= symtab_hdr->sh_info) |
4232 |
|
{ |
4233 |
|
struct elf_link_hash_entry **sym_hashes; |
4234 |
|
|
4235 |
|
sym_hashes = elf_sym_hashes (ibfd); |
4236 |
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
4237 |
|
while (h->root.type == bfd_link_hash_indirect |
4238 |
|
|| h->root.type == bfd_link_hash_warning) |
4239 |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
4240 |
|
} |
4241 |
|
|
4242 |
|
is_local = FALSE; |
4243 |
|
if (h == NULL |
4244 |
|
|| !h->def_dynamic) |
4245 |
|
is_local = TRUE; |
4246 |
|
|
4247 |
|
r_type = ELF32_R_TYPE (rel->r_info); |
4248 |
|
switch (r_type) |
4249 |
|
{ |
4250 |
|
case R_PPC_GOT_TLSLD16: |
4251 |
|
case R_PPC_GOT_TLSLD16_LO: |
4252 |
|
case R_PPC_GOT_TLSLD16_HI: |
4253 |
|
case R_PPC_GOT_TLSLD16_HA: |
4254 |
|
/* These relocs should never be against a symbol |
4255 |
|
defined in a shared lib. Leave them alone if |
4256 |
|
that turns out to be the case. */ |
4257 |
|
expecting_tls_get_addr = 0; |
4258 |
|
htab->tlsld_got.refcount -= 1; |
4259 |
|
if (!is_local) |
4260 |
|
continue; |
4261 |
|
|
4262 |
|
/* LD -> LE */ |
4263 |
|
tls_set = 0; |
4264 |
|
tls_clear = TLS_LD; |
4265 |
|
expecting_tls_get_addr = 1; |
4266 |
|
break; |
4267 |
|
|
4268 |
|
case R_PPC_GOT_TLSGD16: |
4269 |
|
case R_PPC_GOT_TLSGD16_LO: |
4270 |
|
case R_PPC_GOT_TLSGD16_HI: |
4271 |
|
case R_PPC_GOT_TLSGD16_HA: |
4272 |
|
if (is_local) |
4273 |
|
/* GD -> LE */ |
4274 |
|
tls_set = 0; |
4275 |
|
else |
4276 |
|
/* GD -> IE */ |
4277 |
|
tls_set = TLS_TLS | TLS_TPRELGD; |
4278 |
|
tls_clear = TLS_GD; |
4279 |
|
expecting_tls_get_addr = 1; |
4280 |
|
break; |
4281 |
|
|
4282 |
|
case R_PPC_GOT_TPREL16: |
4283 |
|
case R_PPC_GOT_TPREL16_LO: |
4284 |
|
case R_PPC_GOT_TPREL16_HI: |
4285 |
|
case R_PPC_GOT_TPREL16_HA: |
4286 |
|
expecting_tls_get_addr = 0; |
4287 |
|
if (is_local) |
4288 |
|
{ |
4289 |
|
/* IE -> LE */ |
4290 |
|
tls_set = 0; |
4291 |
|
tls_clear = TLS_TPREL; |
4292 |
|
break; |
4293 |
|
} |
4294 |
|
else |
4295 |
|
continue; |
4296 |
|
|
4297 |
|
case R_PPC_REL14: |
4298 |
|
case R_PPC_REL14_BRTAKEN: |
4299 |
|
case R_PPC_REL14_BRNTAKEN: |
4300 |
|
case R_PPC_REL24: |
4301 |
|
if (expecting_tls_get_addr |
4302 |
|
&& h != NULL |
4303 |
|
&& h == htab->tls_get_addr) |
4304 |
|
{ |
4305 |
|
if (h->plt.refcount > 0) |
4306 |
|
h->plt.refcount -= 1; |
4307 |
|
} |
4308 |
|
expecting_tls_get_addr = 0; |
4309 |
|
continue; |
4310 |
|
|
4311 |
|
default: |
4312 |
|
expecting_tls_get_addr = 0; |
4313 |
|
continue; |
4314 |
|
} |
4315 |
|
|
4316 |
|
if (h != NULL) |
4317 |
|
{ |
4318 |
|
if (tls_set == 0) |
4319 |
|
{ |
4320 |
|
/* We managed to get rid of a got entry. */ |
4321 |
|
if (h->got.refcount > 0) |
4322 |
|
h->got.refcount -= 1; |
4323 |
|
} |
4324 |
|
tls_mask = &ppc_elf_hash_entry (h)->tls_mask; |
4325 |
|
} |
4326 |
|
else |
4327 |
|
{ |
4328 |
|
Elf_Internal_Sym *sym; |
4329 |
|
bfd_signed_vma *lgot_refs; |
4330 |
|
char *lgot_masks; |
4331 |
|
|
4332 |
|
if (locsyms == NULL) |
4333 |
|
{ |
4334 |
|
locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; |
4335 |
|
if (locsyms == NULL) |
4336 |
|
locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, |
4337 |
|
symtab_hdr->sh_info, |
4338 |
|
0, NULL, NULL, NULL); |
4339 |
|
if (locsyms == NULL) |
4340 |
|
{ |
4341 |
|
if (elf_section_data (sec)->relocs != relstart) |
4342 |
|
free (relstart); |
4343 |
|
return FALSE; |
4344 |
|
} |
4345 |
|
} |
4346 |
|
sym = locsyms + r_symndx; |
4347 |
|
lgot_refs = elf_local_got_refcounts (ibfd); |
4348 |
|
if (lgot_refs == NULL) |
4349 |
|
abort (); |
4350 |
|
if (tls_set == 0) |
4351 |
|
{ |
4352 |
|
/* We managed to get rid of a got entry. */ |
4353 |
|
if (lgot_refs[r_symndx] > 0) |
4354 |
|
lgot_refs[r_symndx] -= 1; |
4355 |
|
} |
4356 |
|
lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info); |
4357 |
|
tls_mask = &lgot_masks[r_symndx]; |
4358 |
|
} |
4359 |
|
|
4360 |
|
*tls_mask |= tls_set; |
4361 |
|
*tls_mask &= ~tls_clear; |
4362 |
|
} |
4363 |
|
|
4364 |
return true; |
if (elf_section_data (sec)->relocs != relstart) |
4365 |
|
free (relstart); |
4366 |
|
} |
4367 |
|
|
4368 |
|
if (locsyms != NULL |
4369 |
|
&& (symtab_hdr->contents != (unsigned char *) locsyms)) |
4370 |
|
{ |
4371 |
|
if (!info->keep_memory) |
4372 |
|
free (locsyms); |
4373 |
|
else |
4374 |
|
symtab_hdr->contents = (unsigned char *) locsyms; |
4375 |
|
} |
4376 |
|
} |
4377 |
|
return TRUE; |
4378 |
} |
} |
4379 |
|
|
4380 |
/* Hook called by the linker routine which adds symbols from an object |
/* Hook called by the linker routine which adds symbols from an object |
4381 |
file. We use it to put .comm items in .sbss, and not .bss. */ |
file. We use it to put .comm items in .sbss, and not .bss. */ |
4382 |
|
|
4383 |
static boolean |
static bfd_boolean |
4384 |
ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
ppc_elf_add_symbol_hook (bfd *abfd, |
4385 |
bfd *abfd; |
struct bfd_link_info *info, |
4386 |
struct bfd_link_info *info; |
Elf_Internal_Sym *sym, |
4387 |
const Elf_Internal_Sym *sym; |
const char **namep ATTRIBUTE_UNUSED, |
4388 |
const char **namep ATTRIBUTE_UNUSED; |
flagword *flagsp ATTRIBUTE_UNUSED, |
4389 |
flagword *flagsp ATTRIBUTE_UNUSED; |
asection **secp, |
4390 |
asection **secp; |
bfd_vma *valp) |
|
bfd_vma *valp; |
|
4391 |
{ |
{ |
4392 |
if (sym->st_shndx == SHN_COMMON |
if (sym->st_shndx == SHN_COMMON |
4393 |
&& !info->relocateable |
&& !info->relocatable |
4394 |
&& sym->st_size <= elf_gp_size (abfd) |
&& sym->st_size <= elf_gp_size (abfd) |
4395 |
&& info->hash->creator->flavour == bfd_target_elf_flavour) |
&& is_ppc_elf_target (info->hash->creator)) |
4396 |
{ |
{ |
4397 |
/* Common symbols less than or equal to -G nn bytes are automatically |
/* Common symbols less than or equal to -G nn bytes are automatically |
4398 |
put into .sdata. */ |
put into .sbss. */ |
4399 |
elf_linker_section_t *sdata |
struct ppc_elf_link_hash_table *htab; |
4400 |
= ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); |
|
4401 |
|
htab = ppc_elf_hash_table (info); |
4402 |
if (!sdata->bss_section) |
if (htab->sbss == NULL) |
4403 |
{ |
{ |
4404 |
bfd_size_type amt; |
flagword flags = SEC_IS_COMMON; |
4405 |
|
|
4406 |
/* We don't go through bfd_make_section, because we don't |
htab->sbss = bfd_make_section_anyway (abfd, ".sbss"); |
4407 |
want to attach this common section to DYNOBJ. The linker |
if (htab->sbss == NULL |
4408 |
will move the symbols to the appropriate output section |
|| ! bfd_set_section_flags (abfd, htab->sbss, flags)) |
4409 |
when it defines common symbols. */ |
return FALSE; |
|
amt = sizeof (asection); |
|
|
sdata->bss_section = (asection *) bfd_zalloc (abfd, amt); |
|
|
if (sdata->bss_section == NULL) |
|
|
return false; |
|
|
sdata->bss_section->name = sdata->bss_name; |
|
|
sdata->bss_section->flags = SEC_IS_COMMON; |
|
|
sdata->bss_section->output_section = sdata->bss_section; |
|
|
amt = sizeof (asymbol); |
|
|
sdata->bss_section->symbol = (asymbol *) bfd_zalloc (abfd, amt); |
|
|
amt = sizeof (asymbol *); |
|
|
sdata->bss_section->symbol_ptr_ptr = |
|
|
(asymbol **) bfd_zalloc (abfd, amt); |
|
|
if (sdata->bss_section->symbol == NULL |
|
|
|| sdata->bss_section->symbol_ptr_ptr == NULL) |
|
|
return false; |
|
|
sdata->bss_section->symbol->name = sdata->bss_name; |
|
|
sdata->bss_section->symbol->flags = BSF_SECTION_SYM; |
|
|
sdata->bss_section->symbol->section = sdata->bss_section; |
|
|
*sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol; |
|
4410 |
} |
} |
4411 |
|
|
4412 |
*secp = sdata->bss_section; |
*secp = htab->sbss; |
4413 |
*valp = sym->st_size; |
*valp = sym->st_size; |
4414 |
} |
} |
4415 |
|
|
4416 |
return true; |
return TRUE; |
4417 |
} |
} |
4418 |
|
|
4419 |
/* Finish up dynamic symbol handling. We set the contents of various |
/* Finish up dynamic symbol handling. We set the contents of various |
4420 |
dynamic sections here. */ |
dynamic sections here. */ |
4421 |
|
|
4422 |
static boolean |
static bfd_boolean |
4423 |
ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) |
ppc_elf_finish_dynamic_symbol (bfd *output_bfd, |
4424 |
bfd *output_bfd; |
struct bfd_link_info *info, |
4425 |
struct bfd_link_info *info; |
struct elf_link_hash_entry *h, |
4426 |
struct elf_link_hash_entry *h; |
Elf_Internal_Sym *sym) |
|
Elf_Internal_Sym *sym; |
|
4427 |
{ |
{ |
4428 |
bfd *dynobj; |
struct ppc_elf_link_hash_table *htab; |
4429 |
|
|
4430 |
#ifdef DEBUG |
#ifdef DEBUG |
4431 |
fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", |
fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", |
4432 |
h->root.root.string); |
h->root.root.string); |
4433 |
#endif |
#endif |
4434 |
|
|
4435 |
dynobj = elf_hash_table (info)->dynobj; |
htab = ppc_elf_hash_table (info); |
4436 |
BFD_ASSERT (dynobj != NULL); |
BFD_ASSERT (htab->elf.dynobj != NULL); |
4437 |
|
|
4438 |
if (h->plt.offset != (bfd_vma) -1) |
if (h->plt.offset != (bfd_vma) -1) |
4439 |
{ |
{ |
|
asection *splt; |
|
|
asection *srela; |
|
4440 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
4441 |
|
bfd_byte *loc; |
4442 |
bfd_vma reloc_index; |
bfd_vma reloc_index; |
4443 |
|
|
4444 |
#ifdef DEBUG |
#ifdef DEBUG |
4446 |
#endif |
#endif |
4447 |
|
|
4448 |
/* This symbol has an entry in the procedure linkage table. Set |
/* This symbol has an entry in the procedure linkage table. Set |
4449 |
it up. */ |
it up. */ |
4450 |
|
|
4451 |
BFD_ASSERT (h->dynindx != -1); |
BFD_ASSERT (h->dynindx != -1); |
4452 |
|
BFD_ASSERT (htab->plt != NULL && htab->relplt != NULL); |
|
splt = bfd_get_section_by_name (dynobj, ".plt"); |
|
|
srela = bfd_get_section_by_name (dynobj, ".rela.plt"); |
|
|
BFD_ASSERT (splt != NULL && srela != NULL); |
|
4453 |
|
|
4454 |
/* We don't need to fill in the .plt. The ppc dynamic linker |
/* We don't need to fill in the .plt. The ppc dynamic linker |
4455 |
will fill it in. */ |
will fill it in. */ |
4456 |
|
|
4457 |
/* Fill in the entry in the .rela.plt section. */ |
/* Fill in the entry in the .rela.plt section. */ |
4458 |
rela.r_offset = (splt->output_section->vma |
rela.r_offset = (htab->plt->output_section->vma |
4459 |
+ splt->output_offset |
+ htab->plt->output_offset |
4460 |
+ h->plt.offset); |
+ h->plt.offset); |
4461 |
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); |
4462 |
rela.r_addend = 0; |
rela.r_addend = 0; |
4464 |
reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE; |
reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE; |
4465 |
if (reloc_index > PLT_NUM_SINGLE_ENTRIES) |
if (reloc_index > PLT_NUM_SINGLE_ENTRIES) |
4466 |
reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; |
reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; |
4467 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, |
loc = (htab->relplt->contents |
4468 |
((Elf32_External_Rela *) srela->contents |
+ reloc_index * sizeof (Elf32_External_Rela)); |
4469 |
+ reloc_index)); |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
4470 |
|
|
4471 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
if (!h->def_regular) |
4472 |
{ |
{ |
4473 |
/* Mark the symbol as undefined, rather than as defined in |
/* Mark the symbol as undefined, rather than as defined in |
4474 |
the .plt section. Leave the value alone. */ |
the .plt section. Leave the value alone. */ |
4477 |
Otherwise, the PLT entry would provide a definition for |
Otherwise, the PLT entry would provide a definition for |
4478 |
the symbol even if the symbol wasn't defined anywhere, |
the symbol even if the symbol wasn't defined anywhere, |
4479 |
and so the symbol would never be NULL. */ |
and so the symbol would never be NULL. */ |
4480 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) |
if (!h->ref_regular_nonweak) |
|
== 0) |
|
4481 |
sym->st_value = 0; |
sym->st_value = 0; |
4482 |
} |
} |
4483 |
} |
} |
4484 |
|
|
4485 |
if (h->got.offset != (bfd_vma) -1) |
if (h->needs_copy) |
|
{ |
|
|
asection *sgot; |
|
|
asection *srela; |
|
|
Elf_Internal_Rela rela; |
|
|
|
|
|
/* This symbol has an entry in the global offset table. Set it |
|
|
up. */ |
|
|
|
|
|
sgot = bfd_get_section_by_name (dynobj, ".got"); |
|
|
srela = bfd_get_section_by_name (dynobj, ".rela.got"); |
|
|
BFD_ASSERT (sgot != NULL && srela != NULL); |
|
|
|
|
|
rela.r_offset = (sgot->output_section->vma |
|
|
+ sgot->output_offset |
|
|
+ (h->got.offset &~ (bfd_vma) 1)); |
|
|
|
|
|
/* If this is a -Bsymbolic link, and the symbol is defined |
|
|
locally, we just want to emit a RELATIVE reloc. The entry in |
|
|
the global offset table will already have been initialized in |
|
|
the relocate_section function. */ |
|
|
if (info->shared |
|
|
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
|
|
{ |
|
|
rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); |
|
|
rela.r_addend = (h->root.u.def.value |
|
|
+ h->root.u.def.section->output_section->vma |
|
|
+ h->root.u.def.section->output_offset); |
|
|
} |
|
|
else |
|
|
{ |
|
|
BFD_ASSERT ((h->got.offset & 1) == 0); |
|
|
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); |
|
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT); |
|
|
rela.r_addend = 0; |
|
|
} |
|
|
|
|
|
bfd_elf32_swap_reloca_out (output_bfd, &rela, |
|
|
((Elf32_External_Rela *) srela->contents |
|
|
+ srela->reloc_count)); |
|
|
++srela->reloc_count; |
|
|
} |
|
|
|
|
|
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) |
|
4486 |
{ |
{ |
4487 |
asection *s; |
asection *s; |
4488 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
4489 |
|
bfd_byte *loc; |
4490 |
|
|
4491 |
/* This symbols needs a copy reloc. Set it up. */ |
/* This symbols needs a copy reloc. Set it up. */ |
4492 |
|
|
4496 |
|
|
4497 |
BFD_ASSERT (h->dynindx != -1); |
BFD_ASSERT (h->dynindx != -1); |
4498 |
|
|
4499 |
if (h->size <= elf_gp_size (dynobj)) |
if (h->size <= elf_gp_size (htab->elf.dynobj)) |
4500 |
s = bfd_get_section_by_name (h->root.u.def.section->owner, |
s = htab->relsbss; |
|
".rela.sbss"); |
|
4501 |
else |
else |
4502 |
s = bfd_get_section_by_name (h->root.u.def.section->owner, |
s = htab->relbss; |
|
".rela.bss"); |
|
4503 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
4504 |
|
|
4505 |
rela.r_offset = (h->root.u.def.value |
rela.r_offset = (h->root.u.def.value |
4507 |
+ h->root.u.def.section->output_offset); |
+ h->root.u.def.section->output_offset); |
4508 |
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); |
4509 |
rela.r_addend = 0; |
rela.r_addend = 0; |
4510 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, |
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); |
4511 |
((Elf32_External_Rela *) s->contents |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
|
+ s->reloc_count)); |
|
|
++s->reloc_count; |
|
4512 |
} |
} |
4513 |
|
|
4514 |
#ifdef DEBUG |
#ifdef DEBUG |
4521 |
|| strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) |
|| strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) |
4522 |
sym->st_shndx = SHN_ABS; |
sym->st_shndx = SHN_ABS; |
4523 |
|
|
4524 |
return true; |
return TRUE; |
4525 |
} |
} |
4526 |
|
|
4527 |
/* Finish up the dynamic sections. */ |
/* Finish up the dynamic sections. */ |
4528 |
|
|
4529 |
static boolean |
static bfd_boolean |
4530 |
ppc_elf_finish_dynamic_sections (output_bfd, info) |
ppc_elf_finish_dynamic_sections (bfd *output_bfd, |
4531 |
bfd *output_bfd; |
struct bfd_link_info *info) |
|
struct bfd_link_info *info; |
|
4532 |
{ |
{ |
4533 |
asection *sdyn; |
asection *sdyn; |
4534 |
bfd *dynobj = elf_hash_table (info)->dynobj; |
struct ppc_elf_link_hash_table *htab; |
|
asection *sgot = bfd_get_section_by_name (dynobj, ".got"); |
|
4535 |
|
|
4536 |
#ifdef DEBUG |
#ifdef DEBUG |
4537 |
fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); |
fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); |
4538 |
#endif |
#endif |
4539 |
|
|
4540 |
sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); |
htab = ppc_elf_hash_table (info); |
4541 |
|
sdyn = bfd_get_section_by_name (htab->elf.dynobj, ".dynamic"); |
4542 |
|
|
4543 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (htab->elf.dynamic_sections_created) |
4544 |
{ |
{ |
|
asection *splt; |
|
4545 |
Elf32_External_Dyn *dyncon, *dynconend; |
Elf32_External_Dyn *dyncon, *dynconend; |
4546 |
|
|
4547 |
splt = bfd_get_section_by_name (dynobj, ".plt"); |
BFD_ASSERT (htab->plt != NULL && sdyn != NULL); |
|
BFD_ASSERT (splt != NULL && sdyn != NULL); |
|
4548 |
|
|
4549 |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
4550 |
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); |
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); |
4551 |
for (; dyncon < dynconend; dyncon++) |
for (; dyncon < dynconend; dyncon++) |
4552 |
{ |
{ |
4553 |
Elf_Internal_Dyn dyn; |
Elf_Internal_Dyn dyn; |
4554 |
const char *name; |
asection *s; |
|
boolean size; |
|
4555 |
|
|
4556 |
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); |
bfd_elf32_swap_dyn_in (htab->elf.dynobj, dyncon, &dyn); |
4557 |
|
|
4558 |
switch (dyn.d_tag) |
switch (dyn.d_tag) |
4559 |
{ |
{ |
4560 |
case DT_PLTGOT: name = ".plt"; size = false; break; |
case DT_PLTGOT: |
4561 |
case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; |
s = htab->plt; |
4562 |
case DT_JMPREL: name = ".rela.plt"; size = false; break; |
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
4563 |
default: name = NULL; size = false; break; |
break; |
|
} |
|
4564 |
|
|
4565 |
if (name != NULL) |
case DT_PLTRELSZ: |
4566 |
{ |
dyn.d_un.d_val = htab->relplt->size; |
4567 |
asection *s; |
break; |
4568 |
|
|
4569 |
s = bfd_get_section_by_name (output_bfd, name); |
case DT_JMPREL: |
4570 |
if (s == NULL) |
s = htab->relplt; |
4571 |
dyn.d_un.d_val = 0; |
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
4572 |
else |
break; |
4573 |
{ |
|
4574 |
if (! size) |
default: |
4575 |
dyn.d_un.d_ptr = s->vma; |
continue; |
|
else |
|
|
{ |
|
|
if (s->_cooked_size != 0) |
|
|
dyn.d_un.d_val = s->_cooked_size; |
|
|
else |
|
|
dyn.d_un.d_val = s->_raw_size; |
|
|
} |
|
|
} |
|
|
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
|
4576 |
} |
} |
4577 |
|
|
4578 |
|
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
4579 |
} |
} |
4580 |
} |
} |
4581 |
|
|
4582 |
/* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can |
/* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can |
4583 |
easily find the address of the _GLOBAL_OFFSET_TABLE_. */ |
easily find the address of the _GLOBAL_OFFSET_TABLE_. */ |
4584 |
if (sgot) |
if (htab->got) |
4585 |
{ |
{ |
4586 |
unsigned char *contents = sgot->contents; |
unsigned char *contents = htab->got->contents; |
4587 |
bfd_put_32 (output_bfd, (bfd_vma) 0x4e800021 /* blrl */, contents); |
bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents); |
4588 |
|
|
4589 |
if (sdyn == NULL) |
if (sdyn == NULL) |
4590 |
bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4); |
bfd_put_32 (output_bfd, 0, contents + 4); |
4591 |
else |
else |
4592 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
4593 |
sdyn->output_section->vma + sdyn->output_offset, |
sdyn->output_section->vma + sdyn->output_offset, |
4594 |
contents+4); |
contents + 4); |
4595 |
|
|
4596 |
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; |
elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4; |
4597 |
} |
} |
4598 |
|
|
4599 |
return true; |
return TRUE; |
4600 |
} |
} |
4601 |
|
|
4602 |
/* The RELOCATE_SECTION function is called by the ELF backend linker |
/* The RELOCATE_SECTION function is called by the ELF backend linker |
4608 |
|
|
4609 |
This function is responsible for adjust the section contents as |
This function is responsible for adjust the section contents as |
4610 |
necessary, and (if using Rela relocs and generating a |
necessary, and (if using Rela relocs and generating a |
4611 |
relocateable output file) adjusting the reloc addend as |
relocatable output file) adjusting the reloc addend as |
4612 |
necessary. |
necessary. |
4613 |
|
|
4614 |
This function does not have to worry about setting the reloc |
This function does not have to worry about setting the reloc |
4622 |
The global hash table entry for the global symbols can be found |
The global hash table entry for the global symbols can be found |
4623 |
via elf_sym_hashes (input_bfd). |
via elf_sym_hashes (input_bfd). |
4624 |
|
|
4625 |
When generating relocateable output, this function must handle |
When generating relocatable output, this function must handle |
4626 |
STB_LOCAL/STT_SECTION symbols specially. The output symbol is |
STB_LOCAL/STT_SECTION symbols specially. The output symbol is |
4627 |
going to be the section symbol corresponding to the output |
going to be the section symbol corresponding to the output |
4628 |
section, which means that the addend must be adjusted |
section, which means that the addend must be adjusted |
4629 |
accordingly. */ |
accordingly. */ |
4630 |
|
|
4631 |
static boolean |
static bfd_boolean |
4632 |
ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
ppc_elf_relocate_section (bfd *output_bfd, |
4633 |
contents, relocs, local_syms, local_sections) |
struct bfd_link_info *info, |
4634 |
bfd *output_bfd; |
bfd *input_bfd, |
4635 |
struct bfd_link_info *info; |
asection *input_section, |
4636 |
bfd *input_bfd; |
bfd_byte *contents, |
4637 |
asection *input_section; |
Elf_Internal_Rela *relocs, |
4638 |
bfd_byte *contents; |
Elf_Internal_Sym *local_syms, |
4639 |
Elf_Internal_Rela *relocs; |
asection **local_sections) |
4640 |
Elf_Internal_Sym *local_syms; |
{ |
4641 |
asection **local_sections; |
Elf_Internal_Shdr *symtab_hdr; |
4642 |
{ |
struct elf_link_hash_entry **sym_hashes; |
4643 |
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
struct ppc_elf_link_hash_table *htab; |
4644 |
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); |
Elf_Internal_Rela *rel; |
4645 |
bfd *dynobj = elf_hash_table (info)->dynobj; |
Elf_Internal_Rela *relend; |
4646 |
elf_linker_section_t *sdata = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA) : NULL; |
Elf_Internal_Rela outrel; |
4647 |
elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL; |
bfd_byte *loc; |
4648 |
Elf_Internal_Rela *rel = relocs; |
asection *sreloc = NULL; |
|
Elf_Internal_Rela *relend = relocs + input_section->reloc_count; |
|
|
asection *sreloc = NULL; |
|
|
asection *splt; |
|
|
asection *sgot; |
|
4649 |
bfd_vma *local_got_offsets; |
bfd_vma *local_got_offsets; |
4650 |
boolean ret = true; |
bfd_boolean ret = TRUE; |
|
long insn; |
|
4651 |
|
|
4652 |
#ifdef DEBUG |
#ifdef DEBUG |
4653 |
fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n", |
_bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, " |
4654 |
bfd_archive_filename (input_bfd), |
"%ld relocations%s", |
4655 |
bfd_section_name(input_bfd, input_section), |
input_bfd, input_section, |
4656 |
(long) input_section->reloc_count, |
(long) input_section->reloc_count, |
4657 |
(info->relocateable) ? " (relocatable)" : ""); |
(info->relocatable) ? " (relocatable)" : ""); |
4658 |
#endif |
#endif |
4659 |
|
|
4660 |
if (info->relocateable) |
if (info->relocatable) |
4661 |
return true; |
return TRUE; |
4662 |
|
|
4663 |
|
/* Initialize howto table if not already done. */ |
4664 |
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
if (!ppc_elf_howto_table[R_PPC_ADDR32]) |
|
/* Initialize howto table if needed. */ |
|
4665 |
ppc_elf_howto_init (); |
ppc_elf_howto_init (); |
4666 |
|
|
4667 |
|
htab = ppc_elf_hash_table (info); |
4668 |
local_got_offsets = elf_local_got_offsets (input_bfd); |
local_got_offsets = elf_local_got_offsets (input_bfd); |
4669 |
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
4670 |
splt = sgot = NULL; |
sym_hashes = elf_sym_hashes (input_bfd); |
4671 |
if (dynobj != NULL) |
rel = relocs; |
4672 |
{ |
relend = relocs + input_section->reloc_count; |
|
splt = bfd_get_section_by_name (dynobj, ".plt"); |
|
|
sgot = bfd_get_section_by_name (dynobj, ".got"); |
|
|
} |
|
|
|
|
4673 |
for (; rel < relend; rel++) |
for (; rel < relend; rel++) |
4674 |
{ |
{ |
4675 |
enum elf_ppc_reloc_type r_type = (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info); |
enum elf_ppc_reloc_type r_type; |
4676 |
bfd_vma offset = rel->r_offset; |
bfd_vma addend; |
4677 |
bfd_vma addend = rel->r_addend; |
bfd_reloc_status_type r; |
4678 |
bfd_reloc_status_type r = bfd_reloc_other; |
Elf_Internal_Sym *sym; |
4679 |
Elf_Internal_Sym *sym = (Elf_Internal_Sym *) 0; |
asection *sec; |
4680 |
asection *sec = (asection *) 0; |
struct elf_link_hash_entry *h; |
4681 |
struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) 0; |
const char *sym_name; |
|
const char *sym_name = (const char *) 0; |
|
4682 |
reloc_howto_type *howto; |
reloc_howto_type *howto; |
4683 |
unsigned long r_symndx; |
unsigned long r_symndx; |
4684 |
bfd_vma relocation; |
bfd_vma relocation; |
4685 |
int will_become_local; |
bfd_vma branch_bit, insn, from; |
4686 |
|
bfd_boolean unresolved_reloc; |
4687 |
/* Unknown relocation handling */ |
bfd_boolean warned; |
4688 |
if ((unsigned) r_type >= (unsigned) R_PPC_max |
unsigned int tls_type, tls_mask, tls_gd; |
4689 |
|| !ppc_elf_howto_table[(int) r_type]) |
|
4690 |
{ |
r_type = ELF32_R_TYPE (rel->r_info); |
4691 |
(*_bfd_error_handler) (_("%s: unknown relocation type %d"), |
sym = NULL; |
4692 |
bfd_archive_filename (input_bfd), |
sec = NULL; |
4693 |
(int) r_type); |
h = NULL; |
4694 |
|
unresolved_reloc = FALSE; |
4695 |
bfd_set_error (bfd_error_bad_value); |
warned = FALSE; |
|
ret = false; |
|
|
continue; |
|
|
} |
|
|
|
|
|
howto = ppc_elf_howto_table[(int) r_type]; |
|
4696 |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_symndx = ELF32_R_SYM (rel->r_info); |
4697 |
|
|
4698 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
4699 |
{ |
{ |
4700 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
4701 |
sec = local_sections[r_symndx]; |
sec = local_sections[r_symndx]; |
4702 |
sym_name = "<local symbol>"; |
sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym); |
4703 |
|
|
4704 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
|
addend = rel->r_addend; |
|
|
/* Relocs to local symbols are always resolved. */ |
|
|
will_become_local = 1; |
|
4705 |
} |
} |
4706 |
else |
else |
4707 |
{ |
{ |
4708 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
4709 |
while (h->root.type == bfd_link_hash_indirect |
r_symndx, symtab_hdr, sym_hashes, |
4710 |
|| h->root.type == bfd_link_hash_warning) |
h, sec, relocation, |
4711 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
unresolved_reloc, warned); |
4712 |
|
|
4713 |
sym_name = h->root.root.string; |
sym_name = h->root.root.string; |
4714 |
|
} |
4715 |
|
|
4716 |
|
/* TLS optimizations. Replace instruction sequences and relocs |
4717 |
|
based on information we collected in tls_optimize. We edit |
4718 |
|
RELOCS so that --emit-relocs will output something sensible |
4719 |
|
for the final instruction stream. */ |
4720 |
|
tls_mask = 0; |
4721 |
|
tls_gd = 0; |
4722 |
|
if (IS_PPC_TLS_RELOC (r_type)) |
4723 |
|
{ |
4724 |
|
if (h != NULL) |
4725 |
|
tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; |
4726 |
|
else if (local_got_offsets != NULL) |
4727 |
|
{ |
4728 |
|
char *lgot_masks; |
4729 |
|
lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info); |
4730 |
|
tls_mask = lgot_masks[r_symndx]; |
4731 |
|
} |
4732 |
|
} |
4733 |
|
|
4734 |
|
/* Ensure reloc mapping code below stays sane. */ |
4735 |
|
if ((R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TLSGD16 & 3) |
4736 |
|
|| (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TLSGD16_LO & 3) |
4737 |
|
|| (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TLSGD16_HI & 3) |
4738 |
|
|| (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TLSGD16_HA & 3) |
4739 |
|
|| (R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TPREL16 & 3) |
4740 |
|
|| (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TPREL16_LO & 3) |
4741 |
|
|| (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TPREL16_HI & 3) |
4742 |
|
|| (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TPREL16_HA & 3)) |
4743 |
|
abort (); |
4744 |
|
switch (r_type) |
4745 |
|
{ |
4746 |
|
default: |
4747 |
|
break; |
4748 |
|
|
4749 |
|
case R_PPC_GOT_TPREL16: |
4750 |
|
case R_PPC_GOT_TPREL16_LO: |
4751 |
|
if (tls_mask != 0 |
4752 |
|
&& (tls_mask & TLS_TPREL) == 0) |
4753 |
|
{ |
4754 |
|
bfd_vma insn; |
4755 |
|
insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2); |
4756 |
|
insn &= 31 << 21; |
4757 |
|
insn |= 0x3c020000; /* addis 0,2,0 */ |
4758 |
|
bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2); |
4759 |
|
r_type = R_PPC_TPREL16_HA; |
4760 |
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
4761 |
|
} |
4762 |
|
break; |
4763 |
|
|
4764 |
|
case R_PPC_TLS: |
4765 |
|
if (tls_mask != 0 |
4766 |
|
&& (tls_mask & TLS_TPREL) == 0) |
4767 |
|
{ |
4768 |
|
bfd_vma insn, rtra; |
4769 |
|
insn = bfd_get_32 (output_bfd, contents + rel->r_offset); |
4770 |
|
if ((insn & ((31 << 26) | (31 << 11))) |
4771 |
|
== ((31 << 26) | (2 << 11))) |
4772 |
|
rtra = insn & ((1 << 26) - (1 << 16)); |
4773 |
|
else if ((insn & ((31 << 26) | (31 << 16))) |
4774 |
|
== ((31 << 26) | (2 << 16))) |
4775 |
|
rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5); |
4776 |
|
else |
4777 |
|
abort (); |
4778 |
|
if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1) |
4779 |
|
/* add -> addi. */ |
4780 |
|
insn = 14 << 26; |
4781 |
|
else if ((insn & (31 << 1)) == 23 << 1 |
4782 |
|
&& ((insn & (31 << 6)) < 14 << 6 |
4783 |
|
|| ((insn & (31 << 6)) >= 16 << 6 |
4784 |
|
&& (insn & (31 << 6)) < 24 << 6))) |
4785 |
|
/* load and store indexed -> dform. */ |
4786 |
|
insn = (32 | ((insn >> 6) & 31)) << 26; |
4787 |
|
else if ((insn & (31 << 1)) == 21 << 1 |
4788 |
|
&& (insn & (0x1a << 6)) == 0) |
4789 |
|
/* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ |
4790 |
|
insn = (((58 | ((insn >> 6) & 4)) << 26) |
4791 |
|
| ((insn >> 6) & 1)); |
4792 |
|
else if ((insn & (31 << 1)) == 21 << 1 |
4793 |
|
&& (insn & ((1 << 11) - (1 << 1))) == 341 << 1) |
4794 |
|
/* lwax -> lwa. */ |
4795 |
|
insn = (58 << 26) | 2; |
4796 |
|
else |
4797 |
|
abort (); |
4798 |
|
insn |= rtra; |
4799 |
|
bfd_put_32 (output_bfd, insn, contents + rel->r_offset); |
4800 |
|
r_type = R_PPC_TPREL16_LO; |
4801 |
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
4802 |
|
/* Was PPC_TLS which sits on insn boundary, now |
4803 |
|
PPC_TPREL16_LO which is at insn+2. */ |
4804 |
|
rel->r_offset += 2; |
4805 |
|
} |
4806 |
|
break; |
4807 |
|
|
4808 |
/* Can this relocation be resolved immediately? */ |
case R_PPC_GOT_TLSGD16_HI: |
4809 |
will_become_local = SYMBOL_REFERENCES_LOCAL (info, h); |
case R_PPC_GOT_TLSGD16_HA: |
4810 |
|
tls_gd = TLS_TPRELGD; |
4811 |
|
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) |
4812 |
|
goto tls_gdld_hi; |
4813 |
|
break; |
4814 |
|
|
4815 |
if (h->root.type == bfd_link_hash_defined |
case R_PPC_GOT_TLSLD16_HI: |
4816 |
|| h->root.type == bfd_link_hash_defweak) |
case R_PPC_GOT_TLSLD16_HA: |
4817 |
|
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) |
4818 |
{ |
{ |
4819 |
sec = h->root.u.def.section; |
tls_gdld_hi: |
4820 |
if (((r_type == R_PPC_PLT32 |
if ((tls_mask & tls_gd) != 0) |
4821 |
|| r_type == R_PPC_PLTREL24) |
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) |
4822 |
&& splt != NULL |
+ R_PPC_GOT_TPREL16); |
4823 |
&& h->plt.offset != (bfd_vma) -1) |
else |
|
|| (r_type == R_PPC_LOCAL24PC |
|
|
&& sec->output_section == NULL) |
|
|
|| ((r_type == R_PPC_GOT16 |
|
|
|| r_type == R_PPC_GOT16_LO |
|
|
|| r_type == R_PPC_GOT16_HI |
|
|
|| r_type == R_PPC_GOT16_HA) |
|
|
&& elf_hash_table (info)->dynamic_sections_created |
|
|
&& (! info->shared || ! will_become_local)) |
|
|
|| (info->shared |
|
|
&& ! will_become_local |
|
|
&& ((input_section->flags & SEC_ALLOC) != 0 |
|
|
/* Testing SEC_DEBUGGING here may be wrong. |
|
|
It's here to avoid a crash when |
|
|
generating a shared library with DWARF |
|
|
debugging information. */ |
|
|
|| ((input_section->flags & SEC_DEBUGGING) != 0 |
|
|
&& (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_DYNAMIC) != 0)) |
|
|
&& (r_type == R_PPC_ADDR32 |
|
|
|| r_type == R_PPC_ADDR24 |
|
|
|| r_type == R_PPC_ADDR16 |
|
|
|| r_type == R_PPC_ADDR16_LO |
|
|
|| r_type == R_PPC_ADDR16_HI |
|
|
|| r_type == R_PPC_ADDR16_HA |
|
|
|| r_type == R_PPC_ADDR14 |
|
|
|| r_type == R_PPC_ADDR14_BRTAKEN |
|
|
|| r_type == R_PPC_ADDR14_BRNTAKEN |
|
|
|| r_type == R_PPC_COPY |
|
|
|| r_type == R_PPC_GLOB_DAT |
|
|
|| r_type == R_PPC_JMP_SLOT |
|
|
|| r_type == R_PPC_UADDR32 |
|
|
|| r_type == R_PPC_UADDR16 |
|
|
|| r_type == R_PPC_SDAREL16 |
|
|
|| r_type == R_PPC_EMB_NADDR32 |
|
|
|| r_type == R_PPC_EMB_NADDR16 |
|
|
|| r_type == R_PPC_EMB_NADDR16_LO |
|
|
|| r_type == R_PPC_EMB_NADDR16_HI |
|
|
|| r_type == R_PPC_EMB_NADDR16_HA |
|
|
|| r_type == R_PPC_EMB_SDAI16 |
|
|
|| r_type == R_PPC_EMB_SDA2I16 |
|
|
|| r_type == R_PPC_EMB_SDA2REL |
|
|
|| r_type == R_PPC_EMB_SDA21 |
|
|
|| r_type == R_PPC_EMB_MRKREF |
|
|
|| r_type == R_PPC_EMB_BIT_FLD |
|
|
|| r_type == R_PPC_EMB_RELSDA |
|
|
|| ((r_type == R_PPC_REL24 |
|
|
|| r_type == R_PPC_REL32 |
|
|
|| r_type == R_PPC_REL14 |
|
|
|| r_type == R_PPC_REL14_BRTAKEN |
|
|
|| r_type == R_PPC_REL14_BRNTAKEN |
|
|
|| r_type == R_PPC_RELATIVE) |
|
|
&& strcmp (h->root.root.string, |
|
|
"_GLOBAL_OFFSET_TABLE_") != 0)))) |
|
4824 |
{ |
{ |
4825 |
/* In these cases, we don't need the relocation |
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); |
4826 |
value. We check specially because in some |
rel->r_offset -= 2; |
4827 |
obscure cases sec->output_section will be NULL. */ |
r_type = R_PPC_NONE; |
|
relocation = 0; |
|
4828 |
} |
} |
4829 |
else if (sec->output_section == NULL) |
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
4830 |
|
} |
4831 |
|
break; |
4832 |
|
|
4833 |
|
case R_PPC_GOT_TLSGD16: |
4834 |
|
case R_PPC_GOT_TLSGD16_LO: |
4835 |
|
tls_gd = TLS_TPRELGD; |
4836 |
|
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) |
4837 |
|
goto tls_get_addr_check; |
4838 |
|
break; |
4839 |
|
|
4840 |
|
case R_PPC_GOT_TLSLD16: |
4841 |
|
case R_PPC_GOT_TLSLD16_LO: |
4842 |
|
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) |
4843 |
|
{ |
4844 |
|
tls_get_addr_check: |
4845 |
|
if (rel + 1 < relend) |
4846 |
{ |
{ |
4847 |
(*_bfd_error_handler) |
enum elf_ppc_reloc_type r_type2; |
4848 |
(_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), |
unsigned long r_symndx2; |
4849 |
bfd_archive_filename (input_bfd), h->root.root.string, |
struct elf_link_hash_entry *h2; |
4850 |
bfd_get_section_name (input_bfd, input_section)); |
bfd_vma insn1, insn2; |
4851 |
relocation = 0; |
bfd_vma offset; |
4852 |
|
|
4853 |
|
/* The next instruction should be a call to |
4854 |
|
__tls_get_addr. Peek at the reloc to be sure. */ |
4855 |
|
r_type2 = ELF32_R_TYPE (rel[1].r_info); |
4856 |
|
r_symndx2 = ELF32_R_SYM (rel[1].r_info); |
4857 |
|
if (r_symndx2 < symtab_hdr->sh_info |
4858 |
|
|| (r_type2 != R_PPC_REL14 |
4859 |
|
&& r_type2 != R_PPC_REL14_BRTAKEN |
4860 |
|
&& r_type2 != R_PPC_REL14_BRNTAKEN |
4861 |
|
&& r_type2 != R_PPC_REL24 |
4862 |
|
&& r_type2 != R_PPC_PLTREL24)) |
4863 |
|
break; |
4864 |
|
|
4865 |
|
h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; |
4866 |
|
while (h2->root.type == bfd_link_hash_indirect |
4867 |
|
|| h2->root.type == bfd_link_hash_warning) |
4868 |
|
h2 = (struct elf_link_hash_entry *) h2->root.u.i.link; |
4869 |
|
if (h2 == NULL || h2 != htab->tls_get_addr) |
4870 |
|
break; |
4871 |
|
|
4872 |
|
/* OK, it checks out. Replace the call. */ |
4873 |
|
offset = rel[1].r_offset; |
4874 |
|
insn1 = bfd_get_32 (output_bfd, |
4875 |
|
contents + rel->r_offset - 2); |
4876 |
|
if ((tls_mask & tls_gd) != 0) |
4877 |
|
{ |
4878 |
|
/* IE */ |
4879 |
|
insn1 &= (1 << 26) - 1; |
4880 |
|
insn1 |= 32 << 26; /* lwz */ |
4881 |
|
insn2 = 0x7c631214; /* add 3,3,2 */ |
4882 |
|
rel[1].r_info = ELF32_R_INFO (r_symndx2, R_PPC_NONE); |
4883 |
|
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) |
4884 |
|
+ R_PPC_GOT_TPREL16); |
4885 |
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
4886 |
|
} |
4887 |
|
else |
4888 |
|
{ |
4889 |
|
/* LE */ |
4890 |
|
insn1 = 0x3c620000; /* addis 3,2,0 */ |
4891 |
|
insn2 = 0x38630000; /* addi 3,3,0 */ |
4892 |
|
if (tls_gd == 0) |
4893 |
|
{ |
4894 |
|
/* Was an LD reloc. */ |
4895 |
|
r_symndx = 0; |
4896 |
|
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; |
4897 |
|
rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; |
4898 |
|
} |
4899 |
|
r_type = R_PPC_TPREL16_HA; |
4900 |
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
4901 |
|
rel[1].r_info = ELF32_R_INFO (r_symndx, |
4902 |
|
R_PPC_TPREL16_LO); |
4903 |
|
rel[1].r_offset += 2; |
4904 |
|
} |
4905 |
|
bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2); |
4906 |
|
bfd_put_32 (output_bfd, insn2, contents + offset); |
4907 |
|
if (tls_gd == 0) |
4908 |
|
{ |
4909 |
|
/* We changed the symbol on an LD reloc. Start over |
4910 |
|
in order to get h, sym, sec etc. right. */ |
4911 |
|
rel--; |
4912 |
|
continue; |
4913 |
|
} |
4914 |
} |
} |
|
else |
|
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
relocation = 0; |
|
|
else if (info->shared |
|
|
&& (!info->symbolic || info->allow_shlib_undefined) |
|
|
&& !info->no_undefined |
|
|
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) |
|
|
relocation = 0; |
|
|
else |
|
|
{ |
|
|
if (! (*info->callbacks->undefined_symbol) (info, |
|
|
h->root.root.string, |
|
|
input_bfd, |
|
|
input_section, |
|
|
rel->r_offset, |
|
|
(!info->shared |
|
|
|| info->no_undefined |
|
|
|| ELF_ST_VISIBILITY (h->other)))) |
|
|
return false; |
|
|
relocation = 0; |
|
4915 |
} |
} |
4916 |
|
break; |
4917 |
} |
} |
4918 |
|
|
4919 |
switch ((int) r_type) |
/* Handle other relocations that tweak non-addend part of insn. */ |
4920 |
|
branch_bit = 0; |
4921 |
|
switch (r_type) |
4922 |
{ |
{ |
4923 |
default: |
default: |
4924 |
(*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"), |
break; |
4925 |
bfd_archive_filename (input_bfd), |
|
4926 |
(int) r_type, sym_name); |
/* Branch taken prediction relocations. */ |
4927 |
|
case R_PPC_ADDR14_BRTAKEN: |
4928 |
|
case R_PPC_REL14_BRTAKEN: |
4929 |
|
branch_bit = BRANCH_PREDICT_BIT; |
4930 |
|
/* Fall thru */ |
4931 |
|
|
4932 |
|
/* Branch not taken prediction relocations. */ |
4933 |
|
case R_PPC_ADDR14_BRNTAKEN: |
4934 |
|
case R_PPC_REL14_BRNTAKEN: |
4935 |
|
insn = bfd_get_32 (output_bfd, contents + rel->r_offset); |
4936 |
|
insn &= ~BRANCH_PREDICT_BIT; |
4937 |
|
insn |= branch_bit; |
4938 |
|
|
4939 |
|
from = (rel->r_offset |
4940 |
|
+ input_section->output_offset |
4941 |
|
+ input_section->output_section->vma); |
4942 |
|
|
4943 |
|
/* Invert 'y' bit if not the default. */ |
4944 |
|
if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) |
4945 |
|
insn ^= BRANCH_PREDICT_BIT; |
4946 |
|
|
4947 |
|
bfd_put_32 (output_bfd, insn, contents + rel->r_offset); |
4948 |
|
break; |
4949 |
|
} |
4950 |
|
|
4951 |
|
addend = rel->r_addend; |
4952 |
|
tls_type = 0; |
4953 |
|
howto = NULL; |
4954 |
|
if (r_type < R_PPC_max) |
4955 |
|
howto = ppc_elf_howto_table[r_type]; |
4956 |
|
switch (r_type) |
4957 |
|
{ |
4958 |
|
default: |
4959 |
|
(*_bfd_error_handler) |
4960 |
|
(_("%B: unknown relocation type %d for symbol %s"), |
4961 |
|
input_bfd, (int) r_type, sym_name); |
4962 |
|
|
4963 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
4964 |
ret = false; |
ret = FALSE; |
4965 |
continue; |
continue; |
4966 |
|
|
4967 |
case (int) R_PPC_NONE: |
case R_PPC_NONE: |
4968 |
|
case R_PPC_TLS: |
4969 |
|
case R_PPC_EMB_MRKREF: |
4970 |
|
case R_PPC_GNU_VTINHERIT: |
4971 |
|
case R_PPC_GNU_VTENTRY: |
4972 |
continue; |
continue; |
4973 |
|
|
4974 |
|
/* GOT16 relocations. Like an ADDR16 using the symbol's |
4975 |
|
address in the GOT as relocation value instead of the |
4976 |
|
symbol's value itself. Also, create a GOT entry for the |
4977 |
|
symbol and put the symbol value there. */ |
4978 |
|
case R_PPC_GOT_TLSGD16: |
4979 |
|
case R_PPC_GOT_TLSGD16_LO: |
4980 |
|
case R_PPC_GOT_TLSGD16_HI: |
4981 |
|
case R_PPC_GOT_TLSGD16_HA: |
4982 |
|
tls_type = TLS_TLS | TLS_GD; |
4983 |
|
goto dogot; |
4984 |
|
|
4985 |
|
case R_PPC_GOT_TLSLD16: |
4986 |
|
case R_PPC_GOT_TLSLD16_LO: |
4987 |
|
case R_PPC_GOT_TLSLD16_HI: |
4988 |
|
case R_PPC_GOT_TLSLD16_HA: |
4989 |
|
tls_type = TLS_TLS | TLS_LD; |
4990 |
|
goto dogot; |
4991 |
|
|
4992 |
|
case R_PPC_GOT_TPREL16: |
4993 |
|
case R_PPC_GOT_TPREL16_LO: |
4994 |
|
case R_PPC_GOT_TPREL16_HI: |
4995 |
|
case R_PPC_GOT_TPREL16_HA: |
4996 |
|
tls_type = TLS_TLS | TLS_TPREL; |
4997 |
|
goto dogot; |
4998 |
|
|
4999 |
|
case R_PPC_GOT_DTPREL16: |
5000 |
|
case R_PPC_GOT_DTPREL16_LO: |
5001 |
|
case R_PPC_GOT_DTPREL16_HI: |
5002 |
|
case R_PPC_GOT_DTPREL16_HA: |
5003 |
|
tls_type = TLS_TLS | TLS_DTPREL; |
5004 |
|
goto dogot; |
5005 |
|
|
5006 |
|
case R_PPC_GOT16: |
5007 |
|
case R_PPC_GOT16_LO: |
5008 |
|
case R_PPC_GOT16_HI: |
5009 |
|
case R_PPC_GOT16_HA: |
5010 |
|
dogot: |
5011 |
|
{ |
5012 |
|
/* Relocation is to the entry for this symbol in the global |
5013 |
|
offset table. */ |
5014 |
|
bfd_vma off; |
5015 |
|
bfd_vma *offp; |
5016 |
|
unsigned long indx; |
5017 |
|
|
5018 |
|
if (htab->got == NULL) |
5019 |
|
abort (); |
5020 |
|
|
5021 |
|
indx = 0; |
5022 |
|
if (tls_type == (TLS_TLS | TLS_LD) |
5023 |
|
&& (h == NULL |
5024 |
|
|| !h->def_dynamic)) |
5025 |
|
offp = &htab->tlsld_got.offset; |
5026 |
|
else if (h != NULL) |
5027 |
|
{ |
5028 |
|
bfd_boolean dyn; |
5029 |
|
dyn = htab->elf.dynamic_sections_created; |
5030 |
|
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
5031 |
|
|| (info->shared |
5032 |
|
&& SYMBOL_REFERENCES_LOCAL (info, h))) |
5033 |
|
/* This is actually a static link, or it is a |
5034 |
|
-Bsymbolic link and the symbol is defined |
5035 |
|
locally, or the symbol was forced to be local |
5036 |
|
because of a version file. */ |
5037 |
|
; |
5038 |
|
else |
5039 |
|
{ |
5040 |
|
indx = h->dynindx; |
5041 |
|
unresolved_reloc = FALSE; |
5042 |
|
} |
5043 |
|
offp = &h->got.offset; |
5044 |
|
} |
5045 |
|
else |
5046 |
|
{ |
5047 |
|
if (local_got_offsets == NULL) |
5048 |
|
abort (); |
5049 |
|
offp = &local_got_offsets[r_symndx]; |
5050 |
|
} |
5051 |
|
|
5052 |
|
/* The offset must always be a multiple of 4. We use the |
5053 |
|
least significant bit to record whether we have already |
5054 |
|
processed this entry. */ |
5055 |
|
off = *offp; |
5056 |
|
if ((off & 1) != 0) |
5057 |
|
off &= ~1; |
5058 |
|
else |
5059 |
|
{ |
5060 |
|
unsigned int tls_m = (tls_mask |
5061 |
|
& (TLS_LD | TLS_GD | TLS_DTPREL |
5062 |
|
| TLS_TPREL | TLS_TPRELGD)); |
5063 |
|
|
5064 |
|
if (offp == &htab->tlsld_got.offset) |
5065 |
|
tls_m = TLS_LD; |
5066 |
|
else if (h == NULL |
5067 |
|
|| !h->def_dynamic) |
5068 |
|
tls_m &= ~TLS_LD; |
5069 |
|
|
5070 |
|
/* We might have multiple got entries for this sym. |
5071 |
|
Initialize them all. */ |
5072 |
|
do |
5073 |
|
{ |
5074 |
|
int tls_ty = 0; |
5075 |
|
|
5076 |
|
if ((tls_m & TLS_LD) != 0) |
5077 |
|
{ |
5078 |
|
tls_ty = TLS_TLS | TLS_LD; |
5079 |
|
tls_m &= ~TLS_LD; |
5080 |
|
} |
5081 |
|
else if ((tls_m & TLS_GD) != 0) |
5082 |
|
{ |
5083 |
|
tls_ty = TLS_TLS | TLS_GD; |
5084 |
|
tls_m &= ~TLS_GD; |
5085 |
|
} |
5086 |
|
else if ((tls_m & TLS_DTPREL) != 0) |
5087 |
|
{ |
5088 |
|
tls_ty = TLS_TLS | TLS_DTPREL; |
5089 |
|
tls_m &= ~TLS_DTPREL; |
5090 |
|
} |
5091 |
|
else if ((tls_m & (TLS_TPREL | TLS_TPRELGD)) != 0) |
5092 |
|
{ |
5093 |
|
tls_ty = TLS_TLS | TLS_TPREL; |
5094 |
|
tls_m = 0; |
5095 |
|
} |
5096 |
|
|
5097 |
|
/* Generate relocs for the dynamic linker. */ |
5098 |
|
if ((info->shared || indx != 0) |
5099 |
|
&& (h == NULL |
5100 |
|
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
5101 |
|
|| h->root.type != bfd_link_hash_undefweak)) |
5102 |
|
{ |
5103 |
|
outrel.r_offset = (htab->got->output_section->vma |
5104 |
|
+ htab->got->output_offset |
5105 |
|
+ off); |
5106 |
|
outrel.r_addend = 0; |
5107 |
|
if (tls_ty & (TLS_LD | TLS_GD)) |
5108 |
|
{ |
5109 |
|
outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32); |
5110 |
|
if (tls_ty == (TLS_TLS | TLS_GD)) |
5111 |
|
{ |
5112 |
|
loc = htab->relgot->contents; |
5113 |
|
loc += (htab->relgot->reloc_count++ |
5114 |
|
* sizeof (Elf32_External_Rela)); |
5115 |
|
bfd_elf32_swap_reloca_out (output_bfd, |
5116 |
|
&outrel, loc); |
5117 |
|
outrel.r_offset += 4; |
5118 |
|
outrel.r_info |
5119 |
|
= ELF32_R_INFO (indx, R_PPC_DTPREL32); |
5120 |
|
} |
5121 |
|
} |
5122 |
|
else if (tls_ty == (TLS_TLS | TLS_DTPREL)) |
5123 |
|
outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPREL32); |
5124 |
|
else if (tls_ty == (TLS_TLS | TLS_TPREL)) |
5125 |
|
outrel.r_info = ELF32_R_INFO (indx, R_PPC_TPREL32); |
5126 |
|
else if (indx == 0) |
5127 |
|
outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE); |
5128 |
|
else |
5129 |
|
outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT); |
5130 |
|
if (indx == 0) |
5131 |
|
{ |
5132 |
|
outrel.r_addend += relocation; |
5133 |
|
if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL)) |
5134 |
|
outrel.r_addend -= htab->elf.tls_sec->vma; |
5135 |
|
} |
5136 |
|
loc = htab->relgot->contents; |
5137 |
|
loc += (htab->relgot->reloc_count++ |
5138 |
|
* sizeof (Elf32_External_Rela)); |
5139 |
|
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); |
5140 |
|
} |
5141 |
|
|
5142 |
|
/* Init the .got section contents if we're not |
5143 |
|
emitting a reloc. */ |
5144 |
|
else |
5145 |
|
{ |
5146 |
|
bfd_vma value = relocation; |
5147 |
|
|
5148 |
|
if (tls_ty == (TLS_TLS | TLS_LD)) |
5149 |
|
value = 1; |
5150 |
|
else if (tls_ty != 0) |
5151 |
|
{ |
5152 |
|
value -= htab->elf.tls_sec->vma + DTP_OFFSET; |
5153 |
|
if (tls_ty == (TLS_TLS | TLS_TPREL)) |
5154 |
|
value += DTP_OFFSET - TP_OFFSET; |
5155 |
|
|
5156 |
|
if (tls_ty == (TLS_TLS | TLS_GD)) |
5157 |
|
{ |
5158 |
|
bfd_put_32 (output_bfd, value, |
5159 |
|
htab->got->contents + off + 4); |
5160 |
|
value = 1; |
5161 |
|
} |
5162 |
|
} |
5163 |
|
bfd_put_32 (output_bfd, value, |
5164 |
|
htab->got->contents + off); |
5165 |
|
} |
5166 |
|
|
5167 |
|
off += 4; |
5168 |
|
if (tls_ty & (TLS_LD | TLS_GD)) |
5169 |
|
off += 4; |
5170 |
|
} |
5171 |
|
while (tls_m != 0); |
5172 |
|
|
5173 |
|
off = *offp; |
5174 |
|
*offp = off | 1; |
5175 |
|
} |
5176 |
|
|
5177 |
|
if (off >= (bfd_vma) -2) |
5178 |
|
abort (); |
5179 |
|
|
5180 |
|
if ((tls_type & TLS_TLS) != 0) |
5181 |
|
{ |
5182 |
|
if (tls_type != (TLS_TLS | TLS_LD)) |
5183 |
|
{ |
5184 |
|
if ((tls_mask & TLS_LD) != 0 |
5185 |
|
&& !(h == NULL |
5186 |
|
|| !h->def_dynamic)) |
5187 |
|
off += 8; |
5188 |
|
if (tls_type != (TLS_TLS | TLS_GD)) |
5189 |
|
{ |
5190 |
|
if ((tls_mask & TLS_GD) != 0) |
5191 |
|
off += 8; |
5192 |
|
if (tls_type != (TLS_TLS | TLS_DTPREL)) |
5193 |
|
{ |
5194 |
|
if ((tls_mask & TLS_DTPREL) != 0) |
5195 |
|
off += 4; |
5196 |
|
} |
5197 |
|
} |
5198 |
|
} |
5199 |
|
} |
5200 |
|
|
5201 |
|
relocation = htab->got->output_offset + off - 4; |
5202 |
|
|
5203 |
|
/* Addends on got relocations don't make much sense. |
5204 |
|
x+off@got is actually x@got+off, and since the got is |
5205 |
|
generated by a hash table traversal, the value in the |
5206 |
|
got at entry m+n bears little relation to the entry m. */ |
5207 |
|
if (addend != 0) |
5208 |
|
(*_bfd_error_handler) |
5209 |
|
(_("%B(%A+0x%lx): non-zero addend on %s reloc against `%s'"), |
5210 |
|
input_bfd, |
5211 |
|
input_section, |
5212 |
|
(long) rel->r_offset, |
5213 |
|
howto->name, |
5214 |
|
sym_name); |
5215 |
|
} |
5216 |
|
break; |
5217 |
|
|
5218 |
/* Relocations that need no special processing. */ |
/* Relocations that need no special processing. */ |
5219 |
case (int) R_PPC_LOCAL24PC: |
case R_PPC_LOCAL24PC: |
5220 |
/* It makes no sense to point a local relocation |
/* It makes no sense to point a local relocation |
5221 |
at a symbol not in this object. */ |
at a symbol not in this object. */ |
5222 |
if (h != NULL |
if (unresolved_reloc) |
|
&& (h->root.type == bfd_link_hash_defined |
|
|
|| h->root.type == bfd_link_hash_defweak) |
|
|
&& sec->output_section == NULL) |
|
5223 |
{ |
{ |
5224 |
if (! (*info->callbacks->undefined_symbol) (info, |
if (! (*info->callbacks->undefined_symbol) (info, |
5225 |
h->root.root.string, |
h->root.root.string, |
5226 |
input_bfd, |
input_bfd, |
5227 |
input_section, |
input_section, |
5228 |
rel->r_offset, |
rel->r_offset, |
5229 |
true)) |
TRUE)) |
5230 |
return false; |
return FALSE; |
5231 |
continue; |
continue; |
5232 |
} |
} |
5233 |
break; |
break; |
5234 |
|
|
5235 |
/* Relocations that may need to be propagated if this is a shared |
case R_PPC_DTPREL16: |
5236 |
object. */ |
case R_PPC_DTPREL16_LO: |
5237 |
case (int) R_PPC_REL24: |
case R_PPC_DTPREL16_HI: |
5238 |
case (int) R_PPC_REL32: |
case R_PPC_DTPREL16_HA: |
5239 |
case (int) R_PPC_REL14: |
addend -= htab->elf.tls_sec->vma + DTP_OFFSET; |
5240 |
|
break; |
5241 |
|
|
5242 |
|
/* Relocations that may need to be propagated if this is a shared |
5243 |
|
object. */ |
5244 |
|
case R_PPC_TPREL16: |
5245 |
|
case R_PPC_TPREL16_LO: |
5246 |
|
case R_PPC_TPREL16_HI: |
5247 |
|
case R_PPC_TPREL16_HA: |
5248 |
|
addend -= htab->elf.tls_sec->vma + TP_OFFSET; |
5249 |
|
/* The TPREL16 relocs shouldn't really be used in shared |
5250 |
|
libs as they will result in DT_TEXTREL being set, but |
5251 |
|
support them anyway. */ |
5252 |
|
goto dodyn; |
5253 |
|
|
5254 |
|
case R_PPC_TPREL32: |
5255 |
|
addend -= htab->elf.tls_sec->vma + TP_OFFSET; |
5256 |
|
goto dodyn; |
5257 |
|
|
5258 |
|
case R_PPC_DTPREL32: |
5259 |
|
addend -= htab->elf.tls_sec->vma + DTP_OFFSET; |
5260 |
|
goto dodyn; |
5261 |
|
|
5262 |
|
case R_PPC_DTPMOD32: |
5263 |
|
relocation = 1; |
5264 |
|
addend = 0; |
5265 |
|
goto dodyn; |
5266 |
|
|
5267 |
|
case R_PPC_REL24: |
5268 |
|
case R_PPC_REL32: |
5269 |
|
case R_PPC_REL14: |
5270 |
|
case R_PPC_REL14_BRTAKEN: |
5271 |
|
case R_PPC_REL14_BRNTAKEN: |
5272 |
/* If these relocations are not to a named symbol, they can be |
/* If these relocations are not to a named symbol, they can be |
5273 |
handled right here, no need to bother the dynamic linker. */ |
handled right here, no need to bother the dynamic linker. */ |
5274 |
if (h == NULL |
if (SYMBOL_REFERENCES_LOCAL (info, h) |
5275 |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
5276 |
|| SYMBOL_REFERENCES_LOCAL (info, h)) |
break; |
5277 |
|
/* fall through */ |
5278 |
|
|
5279 |
|
/* Relocations that always need to be propagated if this is a shared |
5280 |
|
object. */ |
5281 |
|
case R_PPC_ADDR32: |
5282 |
|
case R_PPC_ADDR24: |
5283 |
|
case R_PPC_ADDR16: |
5284 |
|
case R_PPC_ADDR16_LO: |
5285 |
|
case R_PPC_ADDR16_HI: |
5286 |
|
case R_PPC_ADDR16_HA: |
5287 |
|
case R_PPC_ADDR14: |
5288 |
|
case R_PPC_ADDR14_BRTAKEN: |
5289 |
|
case R_PPC_ADDR14_BRNTAKEN: |
5290 |
|
case R_PPC_UADDR32: |
5291 |
|
case R_PPC_UADDR16: |
5292 |
|
/* r_symndx will be zero only for relocs against symbols |
5293 |
|
from removed linkonce sections, or sections discarded by |
5294 |
|
a linker script. */ |
5295 |
|
dodyn: |
5296 |
|
if (r_symndx == 0) |
5297 |
break; |
break; |
5298 |
/* fall through */ |
/* Fall thru. */ |
5299 |
|
|
5300 |
/* Relocations that always need to be propagated if this is a shared |
if ((input_section->flags & SEC_ALLOC) == 0) |
5301 |
object. */ |
break; |
5302 |
case (int) R_PPC_ADDR32: |
/* Fall thru. */ |
5303 |
case (int) R_PPC_ADDR24: |
|
5304 |
case (int) R_PPC_ADDR16: |
if ((info->shared |
5305 |
case (int) R_PPC_ADDR16_LO: |
&& (h == NULL |
5306 |
case (int) R_PPC_ADDR16_HI: |
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
5307 |
case (int) R_PPC_ADDR16_HA: |
|| h->root.type != bfd_link_hash_undefweak) |
5308 |
case (int) R_PPC_ADDR14: |
&& (MUST_BE_DYN_RELOC (r_type) |
5309 |
case (int) R_PPC_UADDR32: |
|| !SYMBOL_CALLS_LOCAL (info, h))) |
5310 |
case (int) R_PPC_UADDR16: |
|| (ELIMINATE_COPY_RELOCS |
5311 |
if (info->shared && r_symndx != 0 |
&& !info->shared |
5312 |
&& (input_section->flags & SEC_ALLOC) != 0) |
&& h != NULL |
5313 |
|
&& h->dynindx != -1 |
5314 |
|
&& !h->non_got_ref |
5315 |
|
&& h->def_dynamic |
5316 |
|
&& !h->def_regular)) |
5317 |
{ |
{ |
|
Elf_Internal_Rela outrel; |
|
5318 |
int skip; |
int skip; |
5319 |
|
|
5320 |
#ifdef DEBUG |
#ifdef DEBUG |
5321 |
fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n", |
fprintf (stderr, "ppc_elf_relocate_section needs to " |
5322 |
(h && h->root.root.string) ? h->root.root.string : "<unknown>"); |
"create relocation for %s\n", |
5323 |
|
(h && h->root.root.string |
5324 |
|
? h->root.root.string : "<unknown>")); |
5325 |
#endif |
#endif |
5326 |
|
|
5327 |
/* When generating a shared object, these relocations |
/* When generating a shared object, these relocations |
5328 |
are copied into the output file to be resolved at run |
are copied into the output file to be resolved at run |
5329 |
time. */ |
time. */ |
|
|
|
5330 |
if (sreloc == NULL) |
if (sreloc == NULL) |
5331 |
{ |
{ |
5332 |
const char *name; |
const char *name; |
5336 |
elf_elfheader (input_bfd)->e_shstrndx, |
elf_elfheader (input_bfd)->e_shstrndx, |
5337 |
elf_section_data (input_section)->rel_hdr.sh_name)); |
elf_section_data (input_section)->rel_hdr.sh_name)); |
5338 |
if (name == NULL) |
if (name == NULL) |
5339 |
return false; |
return FALSE; |
5340 |
|
|
5341 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
5342 |
&& strcmp (bfd_get_section_name (input_bfd, |
&& strcmp (bfd_get_section_name (input_bfd, |
5343 |
input_section), |
input_section), |
5344 |
name + 5) == 0); |
name + 5) == 0); |
5345 |
|
|
5346 |
sreloc = bfd_get_section_by_name (dynobj, name); |
sreloc = bfd_get_section_by_name (htab->elf.dynobj, name); |
5347 |
BFD_ASSERT (sreloc != NULL); |
BFD_ASSERT (sreloc != NULL); |
5348 |
} |
} |
5349 |
|
|
5360 |
|
|
5361 |
if (skip) |
if (skip) |
5362 |
memset (&outrel, 0, sizeof outrel); |
memset (&outrel, 0, sizeof outrel); |
5363 |
/* h->dynindx may be -1 if this symbol was marked to |
else if (!SYMBOL_REFERENCES_LOCAL (info, h)) |
|
become local. */ |
|
|
else if (! will_become_local) |
|
5364 |
{ |
{ |
5365 |
|
unresolved_reloc = FALSE; |
5366 |
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
5367 |
outrel.r_addend = rel->r_addend; |
outrel.r_addend = rel->r_addend; |
5368 |
} |
} |
5369 |
else |
else |
5370 |
{ |
{ |
5371 |
|
outrel.r_addend = relocation + rel->r_addend; |
5372 |
|
|
5373 |
if (r_type == R_PPC_ADDR32) |
if (r_type == R_PPC_ADDR32) |
5374 |
{ |
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); |
|
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); |
|
|
outrel.r_addend = relocation + rel->r_addend; |
|
|
} |
|
5375 |
else |
else |
5376 |
{ |
{ |
5377 |
long indx; |
long indx; |
5378 |
|
|
5379 |
if (h == NULL) |
if (bfd_is_abs_section (sec)) |
|
sec = local_sections[r_symndx]; |
|
|
else |
|
|
{ |
|
|
BFD_ASSERT (h->root.type == bfd_link_hash_defined |
|
|
|| (h->root.type |
|
|
== bfd_link_hash_defweak)); |
|
|
sec = h->root.u.def.section; |
|
|
} |
|
|
if (sec != NULL && bfd_is_abs_section (sec)) |
|
5380 |
indx = 0; |
indx = 0; |
5381 |
else if (sec == NULL || sec->owner == NULL) |
else if (sec == NULL || sec->owner == NULL) |
5382 |
{ |
{ |
5383 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
5384 |
return false; |
return FALSE; |
5385 |
} |
} |
5386 |
else |
else |
5387 |
{ |
{ |
5388 |
asection *osec; |
asection *osec; |
5389 |
|
|
5390 |
|
/* We are turning this relocation into one |
5391 |
|
against a section symbol. It would be |
5392 |
|
proper to subtract the symbol's value, |
5393 |
|
osec->vma, from the emitted reloc addend, |
5394 |
|
but ld.so expects buggy relocs. */ |
5395 |
osec = sec->output_section; |
osec = sec->output_section; |
5396 |
indx = elf_section_data (osec)->dynindx; |
indx = elf_section_data (osec)->dynindx; |
5397 |
BFD_ASSERT (indx > 0); |
BFD_ASSERT (indx > 0); |
5398 |
#ifdef DEBUG |
#ifdef DEBUG |
5399 |
if (indx <= 0) |
if (indx <= 0) |
5400 |
{ |
printf ("indx=%d section=%s flags=%08x name=%s\n", |
5401 |
printf ("indx=%d section=%s flags=%08x name=%s\n", |
indx, osec->name, osec->flags, |
5402 |
indx, osec->name, osec->flags, |
h->root.root.string); |
|
h->root.root.string); |
|
|
} |
|
5403 |
#endif |
#endif |
5404 |
} |
} |
5405 |
|
|
5406 |
outrel.r_info = ELF32_R_INFO (indx, r_type); |
outrel.r_info = ELF32_R_INFO (indx, r_type); |
|
outrel.r_addend = relocation + rel->r_addend; |
|
5407 |
} |
} |
5408 |
} |
} |
5409 |
|
|
5410 |
bfd_elf32_swap_reloca_out (output_bfd, &outrel, |
loc = sreloc->contents; |
5411 |
(((Elf32_External_Rela *) |
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); |
5412 |
sreloc->contents) |
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); |
|
+ sreloc->reloc_count)); |
|
|
++sreloc->reloc_count; |
|
|
|
|
|
/* This reloc will be computed at runtime, so there's no |
|
|
need to do anything now, unless this is a RELATIVE |
|
|
reloc in an unallocated section. */ |
|
|
if (skip != -1 |
|
|
|| (input_section->flags & SEC_ALLOC) != 0 |
|
|
|| ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE) |
|
|
continue; |
|
|
} |
|
|
|
|
|
/* Arithmetic adjust relocations that aren't going into a |
|
|
shared object. */ |
|
|
if (r_type == R_PPC_ADDR16_HA |
|
|
/* It's just possible that this symbol is a weak symbol |
|
|
that's not actually defined anywhere. In that case, |
|
|
'sec' would be NULL, and we should leave the symbol |
|
|
alone (it will be set to zero elsewhere in the link). */ |
|
|
&& sec != NULL) |
|
|
{ |
|
|
addend += ((relocation + addend) & 0x8000) << 1; |
|
|
} |
|
|
break; |
|
|
|
|
|
/* branch taken prediction relocations */ |
|
|
case (int) R_PPC_ADDR14_BRTAKEN: |
|
|
case (int) R_PPC_REL14_BRTAKEN: |
|
|
insn = bfd_get_32 (output_bfd, contents + offset); |
|
|
if ((relocation - offset) & 0x8000) |
|
|
insn &= ~BRANCH_PREDICT_BIT; |
|
|
else |
|
|
insn |= BRANCH_PREDICT_BIT; |
|
|
bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); |
|
|
break; |
|
|
|
|
|
/* branch not taken predicition relocations */ |
|
|
case (int) R_PPC_ADDR14_BRNTAKEN: |
|
|
case (int) R_PPC_REL14_BRNTAKEN: |
|
|
insn = bfd_get_32 (output_bfd, contents + offset); |
|
|
if ((relocation - offset) & 0x8000) |
|
|
insn |= BRANCH_PREDICT_BIT; |
|
|
else |
|
|
insn &= ~BRANCH_PREDICT_BIT; |
|
|
bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); |
|
|
break; |
|
|
|
|
|
/* GOT16 relocations */ |
|
|
case (int) R_PPC_GOT16: |
|
|
case (int) R_PPC_GOT16_LO: |
|
|
case (int) R_PPC_GOT16_HI: |
|
|
case (int) R_PPC_GOT16_HA: |
|
|
/* Relocation is to the entry for this symbol in the global |
|
|
offset table. */ |
|
|
BFD_ASSERT (sgot != NULL); |
|
|
|
|
|
if (h != NULL) |
|
|
{ |
|
|
bfd_vma off; |
|
5413 |
|
|
5414 |
off = h->got.offset; |
if (skip == -1) |
5415 |
BFD_ASSERT (off != (bfd_vma) -1); |
continue; |
5416 |
|
|
5417 |
if (! elf_hash_table (info)->dynamic_sections_created |
/* This reloc will be computed at runtime. We clear the memory |
5418 |
|| (info->shared |
so that it contains predictable value. */ |
5419 |
&& SYMBOL_REFERENCES_LOCAL (info, h))) |
if (! skip |
5420 |
|
&& ((input_section->flags & SEC_ALLOC) != 0 |
5421 |
|
|| ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)) |
5422 |
{ |
{ |
5423 |
/* This is actually a static link, or it is a |
relocation = howto->pc_relative ? outrel.r_offset : 0; |
5424 |
-Bsymbolic link and the symbol is defined |
addend = 0; |
5425 |
locally. We must initialize this entry in the |
break; |
|
global offset table. Since the offset must |
|
|
always be a multiple of 4, we use the least |
|
|
significant bit to record whether we have |
|
|
initialized it already. |
|
|
|
|
|
When doing a dynamic link, we create a .rela.got |
|
|
relocation entry to initialize the value. This |
|
|
is done in the finish_dynamic_symbol routine. */ |
|
|
if ((off & 1) != 0) |
|
|
off &= ~1; |
|
|
else |
|
|
{ |
|
|
bfd_put_32 (output_bfd, relocation, |
|
|
sgot->contents + off); |
|
|
h->got.offset |= 1; |
|
|
} |
|
5426 |
} |
} |
|
|
|
|
relocation = sgot->output_offset + off - 4; |
|
5427 |
} |
} |
5428 |
else |
break; |
|
{ |
|
|
bfd_vma off; |
|
|
|
|
|
BFD_ASSERT (local_got_offsets != NULL |
|
|
&& local_got_offsets[r_symndx] != (bfd_vma) -1); |
|
5429 |
|
|
5430 |
off = local_got_offsets[r_symndx]; |
case R_PPC_RELAX32PC_PLT: |
5431 |
|
case R_PPC_RELAX32_PLT: |
5432 |
|
BFD_ASSERT (h != NULL |
5433 |
|
&& h->plt.offset != (bfd_vma) -1 |
5434 |
|
&& htab->plt != NULL); |
5435 |
|
|
5436 |
/* The offset must always be a multiple of 4. We use |
relocation = (htab->plt->output_section->vma |
5437 |
the least significant bit to record whether we have |
+ htab->plt->output_offset |
5438 |
already processed this entry. */ |
+ h->plt.offset); |
5439 |
if ((off & 1) != 0) |
if (r_type == R_PPC_RELAX32_PLT) |
5440 |
off &= ~1; |
goto relax32; |
5441 |
else |
/* Fall thru */ |
5442 |
{ |
|
5443 |
bfd_put_32 (output_bfd, relocation, sgot->contents + off); |
case R_PPC_RELAX32PC: |
5444 |
|
relocation -= (input_section->output_section->vma |
5445 |
|
+ input_section->output_offset |
5446 |
|
+ rel->r_offset - 4); |
5447 |
|
/* Fall thru */ |
5448 |
|
|
5449 |
if (info->shared) |
case R_PPC_RELAX32: |
5450 |
{ |
relax32: |
5451 |
asection *srelgot; |
{ |
5452 |
Elf_Internal_Rela outrel; |
unsigned long t0; |
5453 |
|
unsigned long t1; |
5454 |
|
|
5455 |
/* We need to generate a R_PPC_RELATIVE reloc |
t0 = bfd_get_32 (output_bfd, contents + rel->r_offset); |
5456 |
for the dynamic linker. */ |
t1 = bfd_get_32 (output_bfd, contents + rel->r_offset + 4); |
|
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
|
|
BFD_ASSERT (srelgot != NULL); |
|
|
|
|
|
outrel.r_offset = (sgot->output_section->vma |
|
|
+ sgot->output_offset |
|
|
+ off); |
|
|
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); |
|
|
outrel.r_addend = relocation; |
|
|
bfd_elf32_swap_reloca_out (output_bfd, &outrel, |
|
|
(((Elf32_External_Rela *) |
|
|
srelgot->contents) |
|
|
+ srelgot->reloc_count)); |
|
|
++srelgot->reloc_count; |
|
|
} |
|
5457 |
|
|
5458 |
local_got_offsets[r_symndx] |= 1; |
/* We're clearing the bits for R_PPC_ADDR16_HA |
5459 |
} |
and R_PPC_ADDR16_LO here. */ |
5460 |
|
t0 &= ~0xffff; |
5461 |
|
t1 &= ~0xffff; |
5462 |
|
|
5463 |
|
/* t0 is HA, t1 is LO */ |
5464 |
|
relocation += addend; |
5465 |
|
t0 |= ((relocation + 0x8000) >> 16) & 0xffff; |
5466 |
|
t1 |= relocation & 0xffff; |
5467 |
|
|
5468 |
relocation = sgot->output_offset + off - 4; |
bfd_put_32 (output_bfd, t0, contents + rel->r_offset); |
5469 |
} |
bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4); |
5470 |
break; |
} |
5471 |
|
continue; |
5472 |
|
|
5473 |
/* Indirect .sdata relocation */ |
/* Indirect .sdata relocation. */ |
5474 |
case (int) R_PPC_EMB_SDAI16: |
case R_PPC_EMB_SDAI16: |
5475 |
BFD_ASSERT (sdata != NULL); |
BFD_ASSERT (htab->sdata != NULL); |
5476 |
relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, |
relocation |
5477 |
sdata, h, relocation, rel, |
= elf_finish_pointer_linker_section (output_bfd, input_bfd, info, |
5478 |
R_PPC_RELATIVE); |
htab->sdata, h, relocation, |
5479 |
|
rel, R_PPC_RELATIVE); |
5480 |
break; |
break; |
5481 |
|
|
5482 |
/* Indirect .sdata2 relocation */ |
/* Indirect .sdata2 relocation. */ |
5483 |
case (int) R_PPC_EMB_SDA2I16: |
case R_PPC_EMB_SDA2I16: |
5484 |
BFD_ASSERT (sdata2 != NULL); |
BFD_ASSERT (htab->sdata2 != NULL); |
5485 |
relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, |
relocation |
5486 |
sdata2, h, relocation, rel, |
= elf_finish_pointer_linker_section (output_bfd, input_bfd, info, |
5487 |
R_PPC_RELATIVE); |
htab->sdata2, h, relocation, |
5488 |
|
rel, R_PPC_RELATIVE); |
5489 |
break; |
break; |
5490 |
|
|
5491 |
/* Handle the TOC16 reloc. We want to use the offset within the .got |
/* Handle the TOC16 reloc. We want to use the offset within the .got |
5492 |
section, not the actual VMA. This is appropriate when generating |
section, not the actual VMA. This is appropriate when generating |
5493 |
an embedded ELF object, for which the .got section acts like the |
an embedded ELF object, for which the .got section acts like the |
5494 |
AIX .toc section. */ |
AIX .toc section. */ |
5495 |
case (int) R_PPC_TOC16: /* phony GOT16 relocations */ |
case R_PPC_TOC16: /* phony GOT16 relocations */ |
5496 |
BFD_ASSERT (sec != (asection *) 0); |
BFD_ASSERT (sec != NULL); |
5497 |
BFD_ASSERT (bfd_is_und_section (sec) |
BFD_ASSERT (bfd_is_und_section (sec) |
5498 |
|| strcmp (bfd_get_section_name (abfd, sec), ".got") == 0 |
|| strcmp (bfd_get_section_name (abfd, sec), ".got") == 0 |
5499 |
|| strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0) |
|| strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0); |
5500 |
|
|
5501 |
addend -= sec->output_section->vma + sec->output_offset + 0x8000; |
addend -= sec->output_section->vma + sec->output_offset + 0x8000; |
5502 |
break; |
break; |
5503 |
|
|
5504 |
case (int) R_PPC_PLTREL24: |
case R_PPC_PLTREL24: |
5505 |
/* Relocation is to the entry for this symbol in the |
/* Relocation is to the entry for this symbol in the |
5506 |
procedure linkage table. */ |
procedure linkage table. */ |
5507 |
BFD_ASSERT (h != NULL); |
BFD_ASSERT (h != NULL); |
5508 |
|
|
5509 |
if (h->plt.offset == (bfd_vma) -1 |
if (h->plt.offset == (bfd_vma) -1 |
5510 |
|| splt == NULL) |
|| htab->plt == NULL) |
5511 |
{ |
{ |
5512 |
/* We didn't make a PLT entry for this symbol. This |
/* We didn't make a PLT entry for this symbol. This |
5513 |
happens when statically linking PIC code, or when |
happens when statically linking PIC code, or when |
5514 |
using -Bsymbolic. */ |
using -Bsymbolic. */ |
5515 |
break; |
break; |
5516 |
} |
} |
5517 |
|
|
5518 |
relocation = (splt->output_section->vma |
unresolved_reloc = FALSE; |
5519 |
+ splt->output_offset |
relocation = (htab->plt->output_section->vma |
5520 |
|
+ htab->plt->output_offset |
5521 |
+ h->plt.offset); |
+ h->plt.offset); |
5522 |
break; |
break; |
5523 |
|
|
5524 |
/* relocate against _SDA_BASE_ */ |
/* Relocate against _SDA_BASE_. */ |
5525 |
case (int) R_PPC_SDAREL16: |
case R_PPC_SDAREL16: |
5526 |
{ |
{ |
5527 |
const char *name; |
const char *name; |
5528 |
|
const struct elf_link_hash_entry *sh; |
5529 |
|
|
5530 |
BFD_ASSERT (sec != (asection *) 0); |
BFD_ASSERT (sec != NULL); |
5531 |
name = bfd_get_section_name (abfd, sec->output_section); |
name = bfd_get_section_name (abfd, sec->output_section); |
5532 |
if (strcmp (name, ".sdata") != 0 |
if (! ((strncmp (name, ".sdata", 6) == 0 |
5533 |
&& strcmp (name, ".sbss") != 0) |
&& (name[6] == 0 || name[6] == '.')) |
5534 |
|
|| (strncmp (name, ".sbss", 5) == 0 |
5535 |
|
&& (name[5] == 0 || name[5] == '.')))) |
5536 |
{ |
{ |
5537 |
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), |
(*_bfd_error_handler) |
5538 |
bfd_archive_filename (input_bfd), |
(_("%B: the target (%s) of a %s relocation is " |
5539 |
sym_name, |
"in the wrong output section (%s)"), |
5540 |
ppc_elf_howto_table[(int) r_type]->name, |
input_bfd, |
5541 |
name); |
sym_name, |
5542 |
|
howto->name, |
5543 |
|
name); |
5544 |
} |
} |
5545 |
addend -= (sdata->sym_hash->root.u.def.value |
sh = htab->sdata->sym_hash; |
5546 |
+ sdata->sym_hash->root.u.def.section->output_section->vma |
addend -= (sh->root.u.def.value |
5547 |
+ sdata->sym_hash->root.u.def.section->output_offset); |
+ sh->root.u.def.section->output_section->vma |
5548 |
|
+ sh->root.u.def.section->output_offset); |
5549 |
} |
} |
5550 |
break; |
break; |
5551 |
|
|
5552 |
/* relocate against _SDA2_BASE_ */ |
/* Relocate against _SDA2_BASE_. */ |
5553 |
case (int) R_PPC_EMB_SDA2REL: |
case R_PPC_EMB_SDA2REL: |
5554 |
{ |
{ |
5555 |
const char *name; |
const char *name; |
5556 |
|
const struct elf_link_hash_entry *sh; |
5557 |
|
|
5558 |
BFD_ASSERT (sec != (asection *) 0); |
BFD_ASSERT (sec != NULL); |
5559 |
name = bfd_get_section_name (abfd, sec->output_section); |
name = bfd_get_section_name (abfd, sec->output_section); |
5560 |
if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0) |
if (! (strncmp (name, ".sdata2", 7) == 0 |
5561 |
|
|| strncmp (name, ".sbss2", 6) == 0)) |
5562 |
{ |
{ |
5563 |
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), |
(*_bfd_error_handler) |
5564 |
bfd_archive_filename (input_bfd), |
(_("%B: the target (%s) of a %s relocation is " |
5565 |
sym_name, |
"in the wrong output section (%s)"), |
5566 |
ppc_elf_howto_table[(int) r_type]->name, |
input_bfd, |
5567 |
name); |
sym_name, |
5568 |
|
howto->name, |
5569 |
|
name); |
5570 |
|
|
5571 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
5572 |
ret = false; |
ret = FALSE; |
5573 |
continue; |
continue; |
5574 |
} |
} |
5575 |
addend -= (sdata2->sym_hash->root.u.def.value |
sh = htab->sdata2->sym_hash; |
5576 |
+ sdata2->sym_hash->root.u.def.section->output_section->vma |
addend -= (sh->root.u.def.value |
5577 |
+ sdata2->sym_hash->root.u.def.section->output_offset); |
+ sh->root.u.def.section->output_section->vma |
5578 |
|
+ sh->root.u.def.section->output_offset); |
5579 |
} |
} |
5580 |
break; |
break; |
5581 |
|
|
5582 |
/* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */ |
/* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */ |
5583 |
case (int) R_PPC_EMB_SDA21: |
case R_PPC_EMB_SDA21: |
5584 |
case (int) R_PPC_EMB_RELSDA: |
case R_PPC_EMB_RELSDA: |
5585 |
{ |
{ |
5586 |
const char *name; |
const char *name; |
5587 |
|
const struct elf_link_hash_entry *sh; |
5588 |
int reg; |
int reg; |
5589 |
|
|
5590 |
BFD_ASSERT (sec != (asection *) 0); |
BFD_ASSERT (sec != NULL); |
5591 |
name = bfd_get_section_name (abfd, sec->output_section); |
name = bfd_get_section_name (abfd, sec->output_section); |
5592 |
if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) |
if (((strncmp (name, ".sdata", 6) == 0 |
5593 |
|
&& (name[6] == 0 || name[6] == '.')) |
5594 |
|
|| (strncmp (name, ".sbss", 5) == 0 |
5595 |
|
&& (name[5] == 0 || name[5] == '.')))) |
5596 |
{ |
{ |
5597 |
reg = 13; |
reg = 13; |
5598 |
addend -= (sdata->sym_hash->root.u.def.value |
sh = htab->sdata->sym_hash; |
5599 |
+ sdata->sym_hash->root.u.def.section->output_section->vma |
addend -= (sh->root.u.def.value |
5600 |
+ sdata->sym_hash->root.u.def.section->output_offset); |
+ sh->root.u.def.section->output_section->vma |
5601 |
|
+ sh->root.u.def.section->output_offset); |
5602 |
} |
} |
5603 |
|
|
5604 |
else if (strcmp (name, ".sdata2") == 0 |
else if (strncmp (name, ".sdata2", 7) == 0 |
5605 |
|| strcmp (name, ".sbss2") == 0) |
|| strncmp (name, ".sbss2", 6) == 0) |
5606 |
{ |
{ |
5607 |
reg = 2; |
reg = 2; |
5608 |
addend -= (sdata2->sym_hash->root.u.def.value |
sh = htab->sdata2->sym_hash; |
5609 |
+ sdata2->sym_hash->root.u.def.section->output_section->vma |
addend -= (sh->root.u.def.value |
5610 |
+ sdata2->sym_hash->root.u.def.section->output_offset); |
+ sh->root.u.def.section->output_section->vma |
5611 |
|
+ sh->root.u.def.section->output_offset); |
5612 |
} |
} |
5613 |
|
|
5614 |
else if (strcmp (name, ".PPC.EMB.sdata0") == 0 |
else if (strcmp (name, ".PPC.EMB.sdata0") == 0 |
5619 |
|
|
5620 |
else |
else |
5621 |
{ |
{ |
5622 |
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), |
(*_bfd_error_handler) |
5623 |
bfd_archive_filename (input_bfd), |
(_("%B: the target (%s) of a %s relocation is " |
5624 |
sym_name, |
"in the wrong output section (%s)"), |
5625 |
ppc_elf_howto_table[(int) r_type]->name, |
input_bfd, |
5626 |
name); |
sym_name, |
5627 |
|
howto->name, |
5628 |
|
name); |
5629 |
|
|
5630 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
5631 |
ret = false; |
ret = FALSE; |
5632 |
continue; |
continue; |
5633 |
} |
} |
5634 |
|
|
5635 |
if (r_type == R_PPC_EMB_SDA21) |
if (r_type == R_PPC_EMB_SDA21) |
5636 |
{ /* fill in register field */ |
{ /* fill in register field */ |
5637 |
insn = bfd_get_32 (output_bfd, contents + offset); |
insn = bfd_get_32 (output_bfd, contents + rel->r_offset); |
5638 |
insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); |
insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); |
5639 |
bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); |
bfd_put_32 (output_bfd, insn, contents + rel->r_offset); |
5640 |
} |
} |
5641 |
} |
} |
5642 |
break; |
break; |
5643 |
|
|
5644 |
/* Relocate against the beginning of the section */ |
/* Relocate against the beginning of the section. */ |
5645 |
case (int) R_PPC_SECTOFF: |
case R_PPC_SECTOFF: |
5646 |
case (int) R_PPC_SECTOFF_LO: |
case R_PPC_SECTOFF_LO: |
5647 |
case (int) R_PPC_SECTOFF_HI: |
case R_PPC_SECTOFF_HI: |
5648 |
BFD_ASSERT (sec != (asection *) 0); |
case R_PPC_SECTOFF_HA: |
5649 |
addend -= sec->output_section->vma; |
BFD_ASSERT (sec != NULL); |
|
break; |
|
|
|
|
|
case (int) R_PPC_SECTOFF_HA: |
|
|
BFD_ASSERT (sec != (asection *) 0); |
|
5650 |
addend -= sec->output_section->vma; |
addend -= sec->output_section->vma; |
|
addend += ((relocation + addend) & 0x8000) << 1; |
|
5651 |
break; |
break; |
5652 |
|
|
5653 |
/* Negative relocations */ |
/* Negative relocations. */ |
5654 |
case (int) R_PPC_EMB_NADDR32: |
case R_PPC_EMB_NADDR32: |
5655 |
case (int) R_PPC_EMB_NADDR16: |
case R_PPC_EMB_NADDR16: |
5656 |
case (int) R_PPC_EMB_NADDR16_LO: |
case R_PPC_EMB_NADDR16_LO: |
5657 |
case (int) R_PPC_EMB_NADDR16_HI: |
case R_PPC_EMB_NADDR16_HI: |
5658 |
|
case R_PPC_EMB_NADDR16_HA: |
5659 |
addend -= 2 * relocation; |
addend -= 2 * relocation; |
5660 |
break; |
break; |
5661 |
|
|
5662 |
case (int) R_PPC_EMB_NADDR16_HA: |
case R_PPC_COPY: |
5663 |
addend -= 2 * relocation; |
case R_PPC_GLOB_DAT: |
5664 |
addend += ((relocation + addend) & 0x8000) << 1; |
case R_PPC_JMP_SLOT: |
5665 |
break; |
case R_PPC_RELATIVE: |
5666 |
|
case R_PPC_PLT32: |
5667 |
/* NOP relocation that prevents garbage collecting linkers from omitting a |
case R_PPC_PLTREL32: |
5668 |
reference. */ |
case R_PPC_PLT16_LO: |
5669 |
case (int) R_PPC_EMB_MRKREF: |
case R_PPC_PLT16_HI: |
5670 |
continue; |
case R_PPC_PLT16_HA: |
5671 |
|
case R_PPC_ADDR30: |
5672 |
case (int) R_PPC_COPY: |
case R_PPC_EMB_RELSEC16: |
5673 |
case (int) R_PPC_GLOB_DAT: |
case R_PPC_EMB_RELST_LO: |
5674 |
case (int) R_PPC_JMP_SLOT: |
case R_PPC_EMB_RELST_HI: |
5675 |
case (int) R_PPC_RELATIVE: |
case R_PPC_EMB_RELST_HA: |
5676 |
case (int) R_PPC_PLT32: |
case R_PPC_EMB_BIT_FLD: |
5677 |
case (int) R_PPC_PLTREL32: |
(*_bfd_error_handler) |
5678 |
case (int) R_PPC_PLT16_LO: |
(_("%B: relocation %s is not yet supported for symbol %s."), |
5679 |
case (int) R_PPC_PLT16_HI: |
input_bfd, |
5680 |
case (int) R_PPC_PLT16_HA: |
howto->name, |
5681 |
case (int) R_PPC_EMB_RELSEC16: |
sym_name); |
|
case (int) R_PPC_EMB_RELST_LO: |
|
|
case (int) R_PPC_EMB_RELST_HI: |
|
|
case (int) R_PPC_EMB_RELST_HA: |
|
|
case (int) R_PPC_EMB_BIT_FLD: |
|
|
(*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."), |
|
|
bfd_archive_filename (input_bfd), |
|
|
ppc_elf_howto_table[(int) r_type]->name, |
|
|
sym_name); |
|
5682 |
|
|
5683 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
5684 |
ret = false; |
ret = FALSE; |
5685 |
continue; |
continue; |
5686 |
|
} |
5687 |
|
|
5688 |
case (int) R_PPC_GNU_VTINHERIT: |
/* Do any further special processing. */ |
5689 |
case (int) R_PPC_GNU_VTENTRY: |
switch (r_type) |
5690 |
/* These are no-ops in the end. */ |
{ |
5691 |
continue; |
default: |
5692 |
|
break; |
5693 |
|
|
5694 |
|
case R_PPC_ADDR16_HA: |
5695 |
|
case R_PPC_GOT16_HA: |
5696 |
|
case R_PPC_PLT16_HA: |
5697 |
|
case R_PPC_SECTOFF_HA: |
5698 |
|
case R_PPC_TPREL16_HA: |
5699 |
|
case R_PPC_DTPREL16_HA: |
5700 |
|
case R_PPC_GOT_TLSGD16_HA: |
5701 |
|
case R_PPC_GOT_TLSLD16_HA: |
5702 |
|
case R_PPC_GOT_TPREL16_HA: |
5703 |
|
case R_PPC_GOT_DTPREL16_HA: |
5704 |
|
case R_PPC_EMB_NADDR16_HA: |
5705 |
|
case R_PPC_EMB_RELST_HA: |
5706 |
|
/* It's just possible that this symbol is a weak symbol |
5707 |
|
that's not actually defined anywhere. In that case, |
5708 |
|
'sec' would be NULL, and we should leave the symbol |
5709 |
|
alone (it will be set to zero elsewhere in the link). */ |
5710 |
|
if (sec != NULL) |
5711 |
|
/* Add 0x10000 if sign bit in 0:15 is set. |
5712 |
|
Bits 0:15 are not used. */ |
5713 |
|
addend += 0x8000; |
5714 |
|
break; |
5715 |
} |
} |
5716 |
|
|
5717 |
#ifdef DEBUG |
#ifdef DEBUG |
5718 |
fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, offset = %ld, addend = %ld\n", |
fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, " |
5719 |
|
"offset = %ld, addend = %ld\n", |
5720 |
howto->name, |
howto->name, |
5721 |
(int) r_type, |
(int) r_type, |
5722 |
sym_name, |
sym_name, |
5723 |
r_symndx, |
r_symndx, |
5724 |
(long) offset, |
(long) rel->r_offset, |
5725 |
(long) addend); |
(long) addend); |
5726 |
#endif |
#endif |
5727 |
|
|
5728 |
|
if (unresolved_reloc |
5729 |
|
&& !((input_section->flags & SEC_DEBUGGING) != 0 |
5730 |
|
&& h->def_dynamic)) |
5731 |
|
{ |
5732 |
|
(*_bfd_error_handler) |
5733 |
|
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), |
5734 |
|
input_bfd, |
5735 |
|
input_section, |
5736 |
|
(long) rel->r_offset, |
5737 |
|
howto->name, |
5738 |
|
sym_name); |
5739 |
|
ret = FALSE; |
5740 |
|
} |
5741 |
|
|
5742 |
r = _bfd_final_link_relocate (howto, |
r = _bfd_final_link_relocate (howto, |
5743 |
input_bfd, |
input_bfd, |
5744 |
input_section, |
input_section, |
5745 |
contents, |
contents, |
5746 |
offset, |
rel->r_offset, |
5747 |
relocation, |
relocation, |
5748 |
addend); |
addend); |
5749 |
|
|
5750 |
if (r == bfd_reloc_ok) |
if (r != bfd_reloc_ok) |
|
; |
|
|
else if (r == bfd_reloc_overflow) |
|
5751 |
{ |
{ |
5752 |
const char *name; |
if (sym_name == NULL) |
5753 |
|
sym_name = "(null)"; |
5754 |
if (h != NULL) |
if (r == bfd_reloc_overflow) |
5755 |
{ |
{ |
5756 |
if (h->root.type == bfd_link_hash_undefweak |
if (warned) |
5757 |
|
continue; |
5758 |
|
if (h != NULL |
5759 |
|
&& h->root.type == bfd_link_hash_undefweak |
5760 |
&& howto->pc_relative) |
&& howto->pc_relative) |
5761 |
{ |
{ |
5762 |
/* Assume this is a call protected by other code that |
/* Assume this is a call protected by other code that |
5768 |
continue; |
continue; |
5769 |
} |
} |
5770 |
|
|
5771 |
name = h->root.root.string; |
if (! (*info->callbacks->reloc_overflow) (info, |
5772 |
|
(h ? &h->root : NULL), |
5773 |
|
sym_name, |
5774 |
|
howto->name, |
5775 |
|
rel->r_addend, |
5776 |
|
input_bfd, |
5777 |
|
input_section, |
5778 |
|
rel->r_offset)) |
5779 |
|
return FALSE; |
5780 |
} |
} |
5781 |
else |
else |
5782 |
{ |
{ |
5783 |
name = bfd_elf_string_from_elf_section (input_bfd, |
(*_bfd_error_handler) |
5784 |
symtab_hdr->sh_link, |
(_("%B(%A+0x%lx): %s reloc against `%s': error %d"), |
5785 |
sym->st_name); |
input_bfd, input_section, |
5786 |
if (name == NULL) |
(long) rel->r_offset, howto->name, sym_name, (int) r); |
5787 |
continue; |
ret = FALSE; |
|
if (*name == '\0') |
|
|
name = bfd_section_name (input_bfd, sec); |
|
5788 |
} |
} |
|
|
|
|
if (! (*info->callbacks->reloc_overflow) (info, |
|
|
name, |
|
|
howto->name, |
|
|
(bfd_vma) 0, |
|
|
input_bfd, |
|
|
input_section, |
|
|
offset)) |
|
|
return false; |
|
5789 |
} |
} |
|
else |
|
|
ret = false; |
|
5790 |
} |
} |
5791 |
|
|
5792 |
#ifdef DEBUG |
#ifdef DEBUG |
5797 |
} |
} |
5798 |
|
|
5799 |
static enum elf_reloc_type_class |
static enum elf_reloc_type_class |
5800 |
ppc_elf_reloc_type_class (rela) |
ppc_elf_reloc_type_class (const Elf_Internal_Rela *rela) |
|
const Elf_Internal_Rela *rela; |
|
5801 |
{ |
{ |
5802 |
switch ((int) ELF32_R_TYPE (rela->r_info)) |
switch (ELF32_R_TYPE (rela->r_info)) |
5803 |
{ |
{ |
5804 |
case R_PPC_RELATIVE: |
case R_PPC_RELATIVE: |
5805 |
return reloc_class_relative; |
return reloc_class_relative; |
5814 |
} |
} |
5815 |
} |
} |
5816 |
|
|
5817 |
/* Support for core dump NOTE sections */ |
/* Support for core dump NOTE sections. */ |
5818 |
static boolean |
|
5819 |
ppc_elf_grok_prstatus (abfd, note) |
static bfd_boolean |
5820 |
bfd *abfd; |
ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) |
|
Elf_Internal_Note *note; |
|
5821 |
{ |
{ |
5822 |
int offset; |
int offset; |
5823 |
unsigned int raw_size; |
unsigned int size; |
5824 |
|
|
5825 |
switch (note->descsz) |
switch (note->descsz) |
5826 |
{ |
{ |
5827 |
default: |
default: |
5828 |
return false; |
return FALSE; |
5829 |
|
|
5830 |
case 268: /* Linux/PPC */ |
case 268: /* Linux/PPC. */ |
5831 |
/* pr_cursig */ |
/* pr_cursig */ |
5832 |
elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); |
elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); |
|
|
|
|
/* pr_pid */ |
|
|
elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); |
|
|
|
|
|
/* pr_reg */ |
|
|
offset = 72; |
|
|
raw_size = 192; |
|
5833 |
|
|
5834 |
break; |
/* pr_pid */ |
5835 |
|
elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); |
5836 |
|
|
5837 |
|
/* pr_reg */ |
5838 |
|
offset = 72; |
5839 |
|
size = 192; |
5840 |
|
|
5841 |
|
break; |
5842 |
} |
} |
5843 |
|
|
5844 |
/* Make a ".reg/999" section. */ |
/* Make a ".reg/999" section. */ |
5845 |
return _bfd_elfcore_make_pseudosection (abfd, ".reg", |
return _bfd_elfcore_make_pseudosection (abfd, ".reg", |
5846 |
raw_size, note->descpos + offset); |
size, note->descpos + offset); |
5847 |
} |
} |
5848 |
|
|
5849 |
static boolean |
static bfd_boolean |
5850 |
ppc_elf_grok_psinfo (abfd, note) |
ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
|
bfd *abfd; |
|
|
Elf_Internal_Note *note; |
|
5851 |
{ |
{ |
5852 |
switch (note->descsz) |
switch (note->descsz) |
5853 |
{ |
{ |
5854 |
default: |
default: |
5855 |
return false; |
return FALSE; |
5856 |
|
|
5857 |
case 128: /* Linux/PPC elf_prpsinfo */ |
case 128: /* Linux/PPC elf_prpsinfo. */ |
5858 |
elf_tdata (abfd)->core_program |
elf_tdata (abfd)->core_program |
5859 |
= _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); |
= _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); |
5860 |
elf_tdata (abfd)->core_command |
elf_tdata (abfd)->core_command |
5861 |
= _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); |
= _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); |
5862 |
} |
} |
5863 |
|
|
5864 |
/* Note that for some reason, a spurious space is tacked |
/* Note that for some reason, a spurious space is tacked |
5873 |
command[n - 1] = '\0'; |
command[n - 1] = '\0'; |
5874 |
} |
} |
5875 |
|
|
5876 |
return true; |
return TRUE; |
5877 |
} |
} |
5878 |
|
|
5879 |
|
/* Very simple linked list structure for recording apuinfo values. */ |
5880 |
|
typedef struct apuinfo_list |
5881 |
|
{ |
5882 |
|
struct apuinfo_list *next; |
5883 |
|
unsigned long value; |
5884 |
|
} |
5885 |
|
apuinfo_list; |
5886 |
|
|
5887 |
|
static apuinfo_list *head; |
5888 |
|
|
5889 |
|
|
5890 |
|
static void |
5891 |
|
apuinfo_list_init (void) |
5892 |
|
{ |
5893 |
|
head = NULL; |
5894 |
|
} |
5895 |
|
|
5896 |
|
static void |
5897 |
|
apuinfo_list_add (unsigned long value) |
5898 |
|
{ |
5899 |
|
apuinfo_list *entry = head; |
5900 |
|
|
5901 |
|
while (entry != NULL) |
5902 |
|
{ |
5903 |
|
if (entry->value == value) |
5904 |
|
return; |
5905 |
|
entry = entry->next; |
5906 |
|
} |
5907 |
|
|
5908 |
|
entry = bfd_malloc (sizeof (* entry)); |
5909 |
|
if (entry == NULL) |
5910 |
|
return; |
5911 |
|
|
5912 |
|
entry->value = value; |
5913 |
|
entry->next = head; |
5914 |
|
head = entry; |
5915 |
|
} |
5916 |
|
|
5917 |
|
static unsigned |
5918 |
|
apuinfo_list_length (void) |
5919 |
|
{ |
5920 |
|
apuinfo_list *entry; |
5921 |
|
unsigned long count; |
5922 |
|
|
5923 |
|
for (entry = head, count = 0; |
5924 |
|
entry; |
5925 |
|
entry = entry->next) |
5926 |
|
++ count; |
5927 |
|
|
5928 |
|
return count; |
5929 |
|
} |
5930 |
|
|
5931 |
|
static inline unsigned long |
5932 |
|
apuinfo_list_element (unsigned long number) |
5933 |
|
{ |
5934 |
|
apuinfo_list * entry; |
5935 |
|
|
5936 |
|
for (entry = head; |
5937 |
|
entry && number --; |
5938 |
|
entry = entry->next) |
5939 |
|
; |
5940 |
|
|
5941 |
|
return entry ? entry->value : 0; |
5942 |
|
} |
5943 |
|
|
5944 |
|
static void |
5945 |
|
apuinfo_list_finish (void) |
5946 |
|
{ |
5947 |
|
apuinfo_list *entry; |
5948 |
|
|
5949 |
|
for (entry = head; entry;) |
5950 |
|
{ |
5951 |
|
apuinfo_list *next = entry->next; |
5952 |
|
free (entry); |
5953 |
|
entry = next; |
5954 |
|
} |
5955 |
|
|
5956 |
|
head = NULL; |
5957 |
|
} |
5958 |
|
|
5959 |
|
#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo" |
5960 |
|
#define APUINFO_LABEL "APUinfo" |
5961 |
|
|
5962 |
|
/* Scan the input BFDs and create a linked list of |
5963 |
|
the APUinfo values that will need to be emitted. */ |
5964 |
|
|
5965 |
|
static void |
5966 |
|
ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) |
5967 |
|
{ |
5968 |
|
bfd *ibfd; |
5969 |
|
asection *asec; |
5970 |
|
char *buffer; |
5971 |
|
unsigned num_input_sections; |
5972 |
|
bfd_size_type output_section_size; |
5973 |
|
unsigned i; |
5974 |
|
unsigned num_entries; |
5975 |
|
unsigned long offset; |
5976 |
|
unsigned long length; |
5977 |
|
const char *error_message = NULL; |
5978 |
|
|
5979 |
|
if (link_info == NULL) |
5980 |
|
return; |
5981 |
|
|
5982 |
|
/* Scan the input bfds, looking for apuinfo sections. */ |
5983 |
|
num_input_sections = 0; |
5984 |
|
output_section_size = 0; |
5985 |
|
|
5986 |
|
for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) |
5987 |
|
{ |
5988 |
|
asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); |
5989 |
|
if (asec) |
5990 |
|
{ |
5991 |
|
++ num_input_sections; |
5992 |
|
output_section_size += asec->size; |
5993 |
|
} |
5994 |
|
} |
5995 |
|
|
5996 |
|
/* We need at least one input sections |
5997 |
|
in order to make merging worthwhile. */ |
5998 |
|
if (num_input_sections < 1) |
5999 |
|
return; |
6000 |
|
|
6001 |
|
/* Just make sure that the output section exists as well. */ |
6002 |
|
asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); |
6003 |
|
if (asec == NULL) |
6004 |
|
return; |
6005 |
|
|
6006 |
|
/* Allocate a buffer for the contents of the input sections. */ |
6007 |
|
buffer = bfd_malloc (output_section_size); |
6008 |
|
if (buffer == NULL) |
6009 |
|
return; |
6010 |
|
|
6011 |
|
offset = 0; |
6012 |
|
apuinfo_list_init (); |
6013 |
|
|
6014 |
|
/* Read in the input sections contents. */ |
6015 |
|
for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) |
6016 |
|
{ |
6017 |
|
unsigned long datum; |
6018 |
|
char *ptr; |
6019 |
|
|
6020 |
|
asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); |
6021 |
|
if (asec == NULL) |
6022 |
|
continue; |
6023 |
|
|
6024 |
|
length = asec->size; |
6025 |
|
if (length < 24) |
6026 |
|
{ |
6027 |
|
error_message = _("corrupt or empty %s section in %B"); |
6028 |
|
goto fail; |
6029 |
|
} |
6030 |
|
|
6031 |
|
if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0 |
6032 |
|
|| (bfd_bread (buffer + offset, length, ibfd) != length)) |
6033 |
|
{ |
6034 |
|
error_message = _("unable to read in %s section from %B"); |
6035 |
|
goto fail; |
6036 |
|
} |
6037 |
|
|
6038 |
|
/* Process the contents of the section. */ |
6039 |
|
ptr = buffer + offset; |
6040 |
|
error_message = _("corrupt %s section in %B"); |
6041 |
|
|
6042 |
|
/* Verify the contents of the header. Note - we have to |
6043 |
|
extract the values this way in order to allow for a |
6044 |
|
host whose endian-ness is different from the target. */ |
6045 |
|
datum = bfd_get_32 (ibfd, ptr); |
6046 |
|
if (datum != sizeof APUINFO_LABEL) |
6047 |
|
goto fail; |
6048 |
|
|
6049 |
|
datum = bfd_get_32 (ibfd, ptr + 8); |
6050 |
|
if (datum != 0x2) |
6051 |
|
goto fail; |
6052 |
|
|
6053 |
|
if (strcmp (ptr + 12, APUINFO_LABEL) != 0) |
6054 |
|
goto fail; |
6055 |
|
|
6056 |
|
/* Get the number of bytes used for apuinfo entries. */ |
6057 |
|
datum = bfd_get_32 (ibfd, ptr + 4); |
6058 |
|
if (datum + 20 != length) |
6059 |
|
goto fail; |
6060 |
|
|
6061 |
|
/* Make sure that we do not run off the end of the section. */ |
6062 |
|
if (offset + length > output_section_size) |
6063 |
|
goto fail; |
6064 |
|
|
6065 |
|
/* Scan the apuinfo section, building a list of apuinfo numbers. */ |
6066 |
|
for (i = 0; i < datum; i += 4) |
6067 |
|
apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + i)); |
6068 |
|
|
6069 |
|
/* Update the offset. */ |
6070 |
|
offset += length; |
6071 |
|
} |
6072 |
|
|
6073 |
|
error_message = NULL; |
6074 |
|
|
6075 |
|
/* Compute the size of the output section. */ |
6076 |
|
num_entries = apuinfo_list_length (); |
6077 |
|
output_section_size = 20 + num_entries * 4; |
6078 |
|
|
6079 |
|
asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); |
6080 |
|
|
6081 |
|
if (! bfd_set_section_size (abfd, asec, output_section_size)) |
6082 |
|
ibfd = abfd, |
6083 |
|
error_message = _("warning: unable to set size of %s section in %B"); |
6084 |
|
|
6085 |
|
fail: |
6086 |
|
free (buffer); |
6087 |
|
|
6088 |
|
if (error_message) |
6089 |
|
(*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME); |
6090 |
|
} |
6091 |
|
|
6092 |
|
|
6093 |
|
/* Prevent the output section from accumulating the input sections' |
6094 |
|
contents. We have already stored this in our linked list structure. */ |
6095 |
|
|
6096 |
|
static bfd_boolean |
6097 |
|
ppc_elf_write_section (bfd *abfd ATTRIBUTE_UNUSED, |
6098 |
|
asection *asec, |
6099 |
|
bfd_byte *contents ATTRIBUTE_UNUSED) |
6100 |
|
{ |
6101 |
|
return (apuinfo_list_length () |
6102 |
|
&& strcmp (asec->name, APUINFO_SECTION_NAME) == 0); |
6103 |
|
} |
6104 |
|
|
6105 |
|
|
6106 |
|
/* Finally we can generate the output section. */ |
6107 |
|
|
6108 |
|
static void |
6109 |
|
ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) |
6110 |
|
{ |
6111 |
|
bfd_byte *buffer; |
6112 |
|
asection *asec; |
6113 |
|
unsigned i; |
6114 |
|
unsigned num_entries; |
6115 |
|
bfd_size_type length; |
6116 |
|
|
6117 |
|
asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); |
6118 |
|
if (asec == NULL) |
6119 |
|
return; |
6120 |
|
|
6121 |
|
if (apuinfo_list_length () == 0) |
6122 |
|
return; |
6123 |
|
|
6124 |
|
length = asec->size; |
6125 |
|
if (length < 20) |
6126 |
|
return; |
6127 |
|
|
6128 |
|
buffer = bfd_malloc (length); |
6129 |
|
if (buffer == NULL) |
6130 |
|
{ |
6131 |
|
(*_bfd_error_handler) |
6132 |
|
(_("failed to allocate space for new APUinfo section.")); |
6133 |
|
return; |
6134 |
|
} |
6135 |
|
|
6136 |
|
/* Create the apuinfo header. */ |
6137 |
|
num_entries = apuinfo_list_length (); |
6138 |
|
bfd_put_32 (abfd, sizeof APUINFO_LABEL, buffer); |
6139 |
|
bfd_put_32 (abfd, num_entries * 4, buffer + 4); |
6140 |
|
bfd_put_32 (abfd, 0x2, buffer + 8); |
6141 |
|
strcpy ((char *) buffer + 12, APUINFO_LABEL); |
6142 |
|
|
6143 |
|
length = 20; |
6144 |
|
for (i = 0; i < num_entries; i++) |
6145 |
|
{ |
6146 |
|
bfd_put_32 (abfd, apuinfo_list_element (i), buffer + length); |
6147 |
|
length += 4; |
6148 |
|
} |
6149 |
|
|
6150 |
|
if (length != asec->size) |
6151 |
|
(*_bfd_error_handler) (_("failed to compute new APUinfo section.")); |
6152 |
|
|
6153 |
|
if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length)) |
6154 |
|
(*_bfd_error_handler) (_("failed to install new APUinfo section.")); |
6155 |
|
|
6156 |
|
free (buffer); |
6157 |
|
|
6158 |
|
apuinfo_list_finish (); |
6159 |
|
} |
6160 |
|
|
6161 |
|
/* Return address for Ith PLT stub in section PLT, for relocation REL |
6162 |
|
or (bfd_vma) -1 if it should not be included. */ |
6163 |
|
|
6164 |
|
static bfd_vma |
6165 |
|
ppc_elf_plt_sym_val (bfd_vma i ATTRIBUTE_UNUSED, |
6166 |
|
const asection *plt ATTRIBUTE_UNUSED, |
6167 |
|
const arelent *rel) |
6168 |
|
{ |
6169 |
|
return rel->address; |
6170 |
|
} |
6171 |
|
|
6172 |
|
/* Add extra PPC sections -- Note, for now, make .sbss2 and |
6173 |
|
.PPC.EMB.sbss0 a normal section, and not a bss section so |
6174 |
|
that the linker doesn't crater when trying to make more than |
6175 |
|
2 sections. */ |
6176 |
|
|
6177 |
|
static struct bfd_elf_special_section const ppc_elf_special_sections[]= |
6178 |
|
{ |
6179 |
|
{ ".tags", 5, 0, SHT_ORDERED, SHF_ALLOC }, |
6180 |
|
{ ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
6181 |
|
{ ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, |
6182 |
|
{ ".sdata2", 7, -2, SHT_PROGBITS, SHF_ALLOC }, |
6183 |
|
{ ".sbss2", 6, -2, SHT_PROGBITS, SHF_ALLOC }, |
6184 |
|
{ ".PPC.EMB.apuinfo", 16, 0, SHT_NOTE, 0 }, |
6185 |
|
{ ".PPC.EMB.sdata0", 15, 0, SHT_PROGBITS, SHF_ALLOC }, |
6186 |
|
{ ".PPC.EMB.sbss0", 14, 0, SHT_PROGBITS, SHF_ALLOC }, |
6187 |
|
{ ".plt", 4, 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR }, |
6188 |
|
{ NULL, 0, 0, 0, 0 } |
6189 |
|
}; |
6190 |
|
|
6191 |
#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec |
#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec |
6192 |
#define TARGET_LITTLE_NAME "elf32-powerpcle" |
#define TARGET_LITTLE_NAME "elf32-powerpcle" |
6193 |
#define TARGET_BIG_SYM bfd_elf32_powerpc_vec |
#define TARGET_BIG_SYM bfd_elf32_powerpc_vec |
6194 |
#define TARGET_BIG_NAME "elf32-powerpc" |
#define TARGET_BIG_NAME "elf32-powerpc" |
6195 |
#define ELF_ARCH bfd_arch_powerpc |
#define ELF_ARCH bfd_arch_powerpc |
6196 |
#define ELF_MACHINE_CODE EM_PPC |
#define ELF_MACHINE_CODE EM_PPC |
6197 |
|
#ifdef __QNXTARGET__ |
6198 |
|
#define ELF_MAXPAGESIZE 0x1000 |
6199 |
|
#else |
6200 |
#define ELF_MAXPAGESIZE 0x10000 |
#define ELF_MAXPAGESIZE 0x10000 |
6201 |
|
#endif |
6202 |
|
#define ELF_MINPAGESIZE 0x1000 |
6203 |
#define elf_info_to_howto ppc_elf_info_to_howto |
#define elf_info_to_howto ppc_elf_info_to_howto |
6204 |
|
|
6205 |
#ifdef EM_CYGNUS_POWERPC |
#ifdef EM_CYGNUS_POWERPC |
6215 |
#define elf_backend_can_gc_sections 1 |
#define elf_backend_can_gc_sections 1 |
6216 |
#define elf_backend_can_refcount 1 |
#define elf_backend_can_refcount 1 |
6217 |
#define elf_backend_got_header_size 12 |
#define elf_backend_got_header_size 12 |
|
#define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE |
|
6218 |
#define elf_backend_rela_normal 1 |
#define elf_backend_rela_normal 1 |
6219 |
|
|
6220 |
|
#define bfd_elf32_mkobject ppc_elf_mkobject |
6221 |
#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data |
#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data |
6222 |
#define bfd_elf32_bfd_relax_section ppc_elf_relax_section |
#define bfd_elf32_bfd_relax_section ppc_elf_relax_section |
6223 |
#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup |
#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup |
6224 |
#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags |
#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags |
6225 |
#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link |
#define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create |
6226 |
|
|
6227 |
#define elf_backend_object_p ppc_elf_object_p |
#define elf_backend_object_p ppc_elf_object_p |
6228 |
#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook |
#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook |
6231 |
#define elf_backend_relocate_section ppc_elf_relocate_section |
#define elf_backend_relocate_section ppc_elf_relocate_section |
6232 |
#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections |
#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections |
6233 |
#define elf_backend_check_relocs ppc_elf_check_relocs |
#define elf_backend_check_relocs ppc_elf_check_relocs |
6234 |
|
#define elf_backend_copy_indirect_symbol ppc_elf_copy_indirect_symbol |
6235 |
#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol |
#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol |
6236 |
#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook |
#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook |
6237 |
#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections |
#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections |
6239 |
#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections |
#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections |
6240 |
#define elf_backend_fake_sections ppc_elf_fake_sections |
#define elf_backend_fake_sections ppc_elf_fake_sections |
6241 |
#define elf_backend_additional_program_headers ppc_elf_additional_program_headers |
#define elf_backend_additional_program_headers ppc_elf_additional_program_headers |
|
#define elf_backend_modify_segment_map ppc_elf_modify_segment_map |
|
6242 |
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus |
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus |
6243 |
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo |
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo |
6244 |
#define elf_backend_reloc_type_class ppc_elf_reloc_type_class |
#define elf_backend_reloc_type_class ppc_elf_reloc_type_class |
6245 |
|
#define elf_backend_begin_write_processing ppc_elf_begin_write_processing |
6246 |
|
#define elf_backend_final_write_processing ppc_elf_final_write_processing |
6247 |
|
#define elf_backend_write_section ppc_elf_write_section |
6248 |
|
#define elf_backend_special_sections ppc_elf_special_sections |
6249 |
|
#define elf_backend_plt_sym_val ppc_elf_plt_sym_val |
6250 |
|
|
6251 |
#include "elf32-target.h" |
#include "elf32-target.h" |