Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* BFD back-end for HP PA-RISC ELF files. |
43cbcf28 | 2 | Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 |
252b5132 RH |
3 | Free Software Foundation, Inc. |
4 | ||
5 | Written by | |
6 | ||
7 | Center for Software Science | |
8 | Department of Computer Science | |
9 | University of Utah | |
10 | ||
11 | This file is part of BFD, the Binary File Descriptor library. | |
12 | ||
13 | This program is free software; you can redistribute it and/or modify | |
14 | it under the terms of the GNU General Public License as published by | |
15 | the Free Software Foundation; either version 2 of the License, or | |
16 | (at your option) any later version. | |
17 | ||
18 | This program is distributed in the hope that it will be useful, | |
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | GNU General Public License for more details. | |
22 | ||
23 | You should have received a copy of the GNU General Public License | |
24 | along with this program; if not, write to the Free Software | |
25 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
26 | ||
27 | #include "bfd.h" | |
28 | #include "sysdep.h" | |
252b5132 RH |
29 | #include "libbfd.h" |
30 | #include "elf-bfd.h" | |
9e103c9c JL |
31 | #include "elf/hppa.h" |
32 | #include "libhppa.h" | |
33 | #include "elf32-hppa.h" | |
34 | #define ARCH_SIZE 32 | |
35 | #include "elf-hppa.h" | |
edd21aca | 36 | #include "elf32-hppa.h" |
9e103c9c | 37 | |
252b5132 | 38 | |
edd21aca | 39 | /* We use two hash tables to hold information for linking PA ELF objects. |
252b5132 RH |
40 | |
41 | The first is the elf32_hppa_link_hash_table which is derived | |
42 | from the standard ELF linker hash table. We use this as a place to | |
43 | attach other hash tables and static information. | |
44 | ||
45 | The second is the stub hash table which is derived from the | |
46 | base BFD hash table. The stub hash table holds the information | |
31bd8f25 | 47 | necessary to build the linker stubs during a link. */ |
252b5132 RH |
48 | |
49 | /* Hash table for linker stubs. */ | |
50 | ||
51 | struct elf32_hppa_stub_hash_entry | |
52 | { | |
edd21aca | 53 | /* Base hash table entry structure. */ |
252b5132 RH |
54 | struct bfd_hash_entry root; |
55 | ||
edd21aca AM |
56 | /* The stub section. */ |
57 | asection *stub_sec; | |
58 | ||
59 | /* Offset within stub_sec of the beginning of this stub. */ | |
252b5132 RH |
60 | bfd_vma offset; |
61 | ||
62 | /* Given the symbol's value and its section we can determine its final | |
63 | value when building the stubs (so the stub knows where to jump. */ | |
64 | symvalue target_value; | |
65 | asection *target_section; | |
66 | }; | |
67 | ||
252b5132 RH |
68 | struct elf32_hppa_link_hash_table |
69 | { | |
70 | /* The main hash table. */ | |
71 | struct elf_link_hash_table root; | |
72 | ||
73 | /* The stub hash table. */ | |
edd21aca | 74 | struct bfd_hash_table stub_hash_table; |
252b5132 | 75 | |
edd21aca AM |
76 | /* Current offsets in the stub sections. */ |
77 | bfd_vma *offset; | |
252b5132 | 78 | |
edd21aca AM |
79 | /* Global data pointer. */ |
80 | bfd_vma global_value; | |
252b5132 RH |
81 | }; |
82 | ||
252b5132 | 83 | |
edd21aca | 84 | /* For linker stub hash tables. */ |
252b5132 | 85 | |
edd21aca AM |
86 | #define elf32_hppa_stub_hash_lookup(table, string, create, copy) \ |
87 | ((struct elf32_hppa_stub_hash_entry *) \ | |
88 | bfd_hash_lookup ((table), (string), (create), (copy))) | |
252b5132 | 89 | |
edd21aca | 90 | /* Get the PA ELF linker hash table from a link_info structure. */ |
252b5132 | 91 | |
edd21aca AM |
92 | #define elf32_hppa_hash_table(p) \ |
93 | ((struct elf32_hppa_link_hash_table *) ((p)->hash)) | |
252b5132 | 94 | |
edd21aca AM |
95 | |
96 | static struct bfd_hash_entry *elf32_hppa_stub_hash_newfunc | |
97 | PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); | |
252b5132 RH |
98 | |
99 | static struct bfd_link_hash_table *elf32_hppa_link_hash_table_create | |
100 | PARAMS ((bfd *)); | |
101 | ||
edd21aca AM |
102 | static char *elf32_hppa_stub_name |
103 | PARAMS ((const char *, const asection *, const asection *, | |
104 | bfd_vma, const struct elf_link_hash_entry *)); | |
252b5132 | 105 | |
edd21aca AM |
106 | static int elf32_hppa_relocate_insn |
107 | PARAMS ((int, bfd_vma, bfd_signed_vma, unsigned int, int, | |
108 | enum hppa_reloc_field_selector_type_alt)); | |
109 | ||
110 | static bfd_reloc_status_type elf32_hppa_bfd_final_link_relocate | |
111 | PARAMS ((reloc_howto_type *, bfd *, asection *, | |
112 | bfd_byte *, bfd_vma, bfd_vma, bfd_signed_vma, | |
113 | struct bfd_link_info *, asection *, const char *, | |
114 | struct elf_link_hash_entry *)); | |
115 | ||
116 | static boolean elf32_hppa_relocate_section | |
252b5132 RH |
117 | PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, |
118 | bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); | |
119 | ||
edd21aca AM |
120 | static boolean elf32_hppa_add_symbol_hook |
121 | PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, | |
122 | const char **, flagword *, asection **, bfd_vma *)); | |
252b5132 | 123 | |
252b5132 | 124 | static unsigned int elf32_hppa_size_of_stub |
edd21aca | 125 | PARAMS ((asection *, bfd_vma, bfd_vma)); |
252b5132 | 126 | |
edd21aca AM |
127 | static boolean elf32_hppa_build_one_stub |
128 | PARAMS ((struct bfd_hash_entry *, PTR)); | |
252b5132 RH |
129 | |
130 | ||
252b5132 RH |
131 | /* Assorted hash table functions. */ |
132 | ||
133 | /* Initialize an entry in the stub hash table. */ | |
134 | ||
135 | static struct bfd_hash_entry * | |
136 | elf32_hppa_stub_hash_newfunc (entry, table, string) | |
137 | struct bfd_hash_entry *entry; | |
138 | struct bfd_hash_table *table; | |
139 | const char *string; | |
140 | { | |
141 | struct elf32_hppa_stub_hash_entry *ret; | |
142 | ||
143 | ret = (struct elf32_hppa_stub_hash_entry *) entry; | |
144 | ||
145 | /* Allocate the structure if it has not already been allocated by a | |
146 | subclass. */ | |
147 | if (ret == NULL) | |
148 | ret = ((struct elf32_hppa_stub_hash_entry *) | |
149 | bfd_hash_allocate (table, | |
150 | sizeof (struct elf32_hppa_stub_hash_entry))); | |
151 | if (ret == NULL) | |
152 | return NULL; | |
153 | ||
154 | /* Call the allocation method of the superclass. */ | |
155 | ret = ((struct elf32_hppa_stub_hash_entry *) | |
156 | bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); | |
157 | ||
158 | if (ret) | |
159 | { | |
160 | /* Initialize the local fields. */ | |
edd21aca | 161 | ret->stub_sec = NULL; |
252b5132 RH |
162 | ret->offset = 0; |
163 | ret->target_value = 0; | |
164 | ret->target_section = NULL; | |
165 | } | |
166 | ||
167 | return (struct bfd_hash_entry *) ret; | |
168 | } | |
169 | ||
252b5132 RH |
170 | /* Create the derived linker hash table. The PA ELF port uses the derived |
171 | hash table to keep information specific to the PA ELF linker (without | |
172 | using static variables). */ | |
173 | ||
174 | static struct bfd_link_hash_table * | |
175 | elf32_hppa_link_hash_table_create (abfd) | |
176 | bfd *abfd; | |
177 | { | |
178 | struct elf32_hppa_link_hash_table *ret; | |
179 | ||
edd21aca | 180 | ret = ((struct elf32_hppa_link_hash_table *) bfd_alloc (abfd, sizeof (*ret))); |
252b5132 RH |
181 | if (ret == NULL) |
182 | return NULL; | |
edd21aca | 183 | |
252b5132 RH |
184 | if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, |
185 | _bfd_elf_link_hash_newfunc)) | |
186 | { | |
187 | bfd_release (abfd, ret); | |
188 | return NULL; | |
189 | } | |
edd21aca AM |
190 | |
191 | /* Init the stub hash table too. */ | |
192 | if (!bfd_hash_table_init (&ret->stub_hash_table, | |
193 | elf32_hppa_stub_hash_newfunc)) | |
194 | return NULL; | |
195 | ||
196 | ret->offset = NULL; | |
252b5132 | 197 | ret->global_value = 0; |
252b5132 RH |
198 | |
199 | return &ret->root.root; | |
200 | } | |
201 | ||
edd21aca AM |
202 | /* Build a name for a long branch stub. */ |
203 | static char * | |
204 | elf32_hppa_stub_name (sym_name, sym_sec, input_section, addend, hash) | |
205 | const char *sym_name; | |
206 | const asection *sym_sec; | |
207 | const asection *input_section; | |
208 | bfd_vma addend; | |
209 | const struct elf_link_hash_entry *hash; | |
210 | { | |
211 | char *stub_name; | |
212 | int len; | |
213 | ||
214 | len = strlen (sym_name) + 19; | |
215 | if (hash == NULL) | |
216 | len += 9; | |
252b5132 | 217 | |
edd21aca AM |
218 | stub_name = bfd_malloc (len); |
219 | if (stub_name != NULL) | |
220 | { | |
221 | sprintf (stub_name, "%08x_%08x_%s", | |
222 | input_section->id & 0xffffffff, | |
223 | (int) addend & 0xffffffff, | |
224 | sym_name); | |
225 | ||
226 | /* Tack on an ID so we can uniquely identify | |
227 | this local symbol in the stub hash tables. */ | |
228 | if (hash == NULL) | |
229 | sprintf (stub_name + len - 10, "_%08x", | |
230 | sym_sec->id & 0xffffffff); | |
231 | } | |
232 | return stub_name; | |
233 | } | |
252b5132 | 234 | |
edd21aca AM |
235 | /* Relocate the given INSN given the various input parameters. */ |
236 | ||
237 | static int | |
238 | elf32_hppa_relocate_insn (insn, sym_value, r_addend, r_type, r_format, r_field) | |
239 | int insn; | |
240 | bfd_vma sym_value; | |
241 | bfd_signed_vma r_addend; | |
242 | unsigned int r_type; | |
243 | int r_format; | |
244 | enum hppa_reloc_field_selector_type_alt r_field; | |
252b5132 | 245 | { |
edd21aca AM |
246 | int value; |
247 | #ifdef ELF_ARG_RELOC | |
248 | #ifndef ELF_ARG_RELOC_INSN | |
249 | /* Ick. Who would want to support this? */ | |
250 | int imm; | |
251 | ||
252 | switch (r_type) | |
253 | { | |
254 | /* The offset is partly stored in the instruction for cases | |
255 | where the top ten bits of the addend are used for arg_reloc. | |
256 | This is a little tricky, because the immediate value in the | |
257 | instruction not only needs to be pieced together from | |
258 | multiple bit fields, but also needs to be shifted left to | |
259 | restore the original quantity. Which bits of the offset | |
260 | we can retrieve from the instruction depend on exactly which | |
261 | instruction we are dealing with. */ | |
262 | case R_PARISC_PCREL17R: | |
263 | case R_PARISC_PCREL17F: | |
264 | case R_PARISC_PCREL17C: | |
265 | case R_PARISC_DIR17R: | |
266 | case R_PARISC_DIR17F: | |
267 | /* For these relocs, we choose to use the low 10 bits from the | |
268 | instruction and store the high 22 bits in the reloc addend. | |
269 | It doesn't matter that the bottom 2 bits of the value are | |
270 | always zero, as branches must be to a location which is a | |
271 | multiple of 4. */ | |
272 | #if 0 | |
273 | /* It isn't necessary to retrieve the whole immediate, but | |
274 | this documents what we have in the instruction. */ | |
275 | imm = (((insn & 0x1f0000) >> 5) | |
276 | | ((insn & 0x0004) << 8) | |
277 | | ((insn & 0x1ff8) >> 3)) - ((insn & 1) << 17); | |
278 | imm <<= 2; | |
279 | imm = imm & 0x3ff; | |
280 | #else | |
281 | imm = (insn & 0x7f8) >> 1; | |
282 | #endif | |
283 | r_addend = (r_addend << (BFD_ARCH_SIZE-22)) >> (BFD_ARCH_SIZE-32); | |
284 | r_addend = r_addend | imm; | |
285 | break; | |
286 | ||
287 | case R_PARISC_PCREL21L: | |
288 | case R_PARISC_DIR21L: | |
289 | /* In this case, the instruction stores the high 21 bits of the | |
290 | value, so we pick off the top 10 bits, and use the reloc | |
291 | addend to store the low 22 bits. */ | |
292 | #if 0 | |
293 | /* It isn't necessary to retrieve the whole immediate, but | |
294 | this documents what we have in the instruction. */ | |
295 | imm = (( (insn & 0x000ffe) << 8) | |
296 | | ((insn & 0x00c000) >> 7) | |
297 | | ((insn & 0x1f0000) >> 14) | |
298 | | ((insn & 0x003000) >> 12)) - ((insn & 1) << 20); | |
299 | imm <<= 11; | |
300 | imm = imm & ~ 0x3fffff; | |
301 | #else | |
302 | /* Just pick off the 10 needed bits, ensuring we sign extend. */ | |
303 | imm = ((insn & 0x000ff8) << 19) - ((insn & 1) << 31); | |
304 | #endif | |
305 | r_addend = imm | (r_addend & 0x3fffff); | |
306 | break; | |
307 | ||
308 | default: | |
309 | break; | |
310 | } | |
311 | #endif | |
312 | #endif | |
313 | ||
314 | switch (r_type) | |
315 | { | |
316 | case R_PARISC_PCREL21L: | |
317 | case R_PARISC_PCREL17C: | |
318 | case R_PARISC_PCREL17F: | |
319 | case R_PARISC_PCREL17R: | |
320 | case R_PARISC_PCREL14R: | |
321 | /* Adjust PC relative offset. */ | |
322 | r_addend -= 8; | |
323 | break; | |
324 | default: | |
325 | break; | |
326 | } | |
327 | value = hppa_field_adjust (sym_value, r_addend, r_field); | |
252b5132 | 328 | |
edd21aca | 329 | switch (r_type) |
252b5132 | 330 | { |
edd21aca AM |
331 | case R_PARISC_PCREL17C: |
332 | case R_PARISC_PCREL17F: | |
333 | case R_PARISC_PCREL17R: | |
334 | case R_PARISC_DIR17F: | |
335 | case R_PARISC_DIR17R: | |
336 | /* This is a branch. Divide the offset by four. | |
337 | Note that we need to decide whether it's a branch or | |
338 | otherwise by inspecting the reloc. Inspecting insn won't | |
339 | work as insn might be from a .word directive. */ | |
340 | value >>= 2; | |
341 | break; | |
342 | ||
343 | default: | |
344 | break; | |
345 | } | |
346 | ||
347 | return hppa_rebuild_insn (insn, value, r_format); | |
348 | } | |
349 | ||
350 | /* Actually perform a relocation as part of a final link. This can get | |
351 | rather hairy when linker stubs are needed. */ | |
352 | ||
353 | static bfd_reloc_status_type | |
354 | elf32_hppa_bfd_final_link_relocate (howto, input_bfd, input_section, | |
355 | contents, offset, value, addend, | |
356 | info, sym_sec, sym_name, h) | |
357 | reloc_howto_type *howto; | |
358 | bfd *input_bfd; | |
359 | asection *input_section; | |
360 | bfd_byte *contents; | |
361 | bfd_vma offset; | |
362 | bfd_vma value; | |
363 | bfd_signed_vma addend; | |
364 | struct bfd_link_info *info; | |
365 | asection *sym_sec; | |
366 | const char *sym_name; | |
367 | struct elf_link_hash_entry *h; | |
368 | { | |
369 | int insn; | |
370 | unsigned int r_type = howto->type; | |
371 | int r_format = howto->bitsize; | |
372 | enum hppa_reloc_field_selector_type_alt r_field = e_fsel; | |
373 | bfd_byte *hit_data = contents + offset; | |
374 | bfd_vma location; | |
375 | ||
376 | if (r_type == R_PARISC_NONE) | |
377 | return bfd_reloc_ok; | |
378 | ||
379 | insn = bfd_get_32 (input_bfd, hit_data); | |
380 | ||
381 | /* Find out where we are and where we're going. */ | |
382 | location = (offset + | |
383 | input_section->output_offset + | |
384 | input_section->output_section->vma); | |
385 | ||
386 | switch (r_type) | |
387 | { | |
388 | case R_PARISC_PCREL21L: | |
389 | case R_PARISC_PCREL17C: | |
390 | case R_PARISC_PCREL17F: | |
391 | case R_PARISC_PCREL17R: | |
392 | case R_PARISC_PCREL14R: | |
393 | /* Make it a pc relative offset. */ | |
394 | value -= location; | |
395 | break; | |
396 | default: | |
397 | break; | |
398 | } | |
399 | ||
400 | switch (r_type) | |
401 | { | |
402 | case R_PARISC_DIR32: | |
403 | case R_PARISC_DIR17F: | |
404 | case R_PARISC_PCREL17C: | |
405 | r_field = e_fsel; | |
406 | break; | |
407 | ||
408 | case R_PARISC_DIR21L: | |
409 | case R_PARISC_PCREL21L: | |
410 | r_field = e_lrsel; | |
411 | break; | |
412 | ||
413 | case R_PARISC_DIR17R: | |
414 | case R_PARISC_PCREL17R: | |
415 | case R_PARISC_DIR14R: | |
416 | case R_PARISC_PCREL14R: | |
417 | r_field = e_rrsel; | |
418 | break; | |
419 | ||
420 | /* For all the DP relative relocations, we need to examine the symbol's | |
421 | section. If it's a code section, then "data pointer relative" makes | |
422 | no sense. In that case we don't adjust the "value", and for 21 bit | |
423 | addil instructions, we change the source addend register from %dp to | |
424 | %r0. */ | |
425 | case R_PARISC_DPREL21L: | |
426 | r_field = e_lrsel; | |
427 | if (sym_sec != NULL) | |
252b5132 | 428 | { |
edd21aca AM |
429 | if ((sym_sec->flags & SEC_CODE) != 0) |
430 | { | |
431 | if ((insn & ((0x3f << 26) | (0x1f << 21))) | |
432 | == (((int) OP_ADDIL << 26) | (27 << 21))) | |
433 | { | |
434 | insn &= ~ (0x1f << 21); | |
435 | } | |
436 | } | |
437 | else | |
438 | value -= elf32_hppa_hash_table (info)->global_value; | |
252b5132 | 439 | } |
edd21aca AM |
440 | break; |
441 | ||
442 | case R_PARISC_DPREL14R: | |
443 | r_field = e_rrsel; | |
444 | if (sym_sec != NULL && (sym_sec->flags & SEC_CODE) == 0) | |
445 | value -= elf32_hppa_hash_table (info)->global_value; | |
446 | break; | |
252b5132 | 447 | |
edd21aca AM |
448 | case R_PARISC_DPREL14F: |
449 | r_field = e_fsel; | |
450 | if (sym_sec != NULL && (sym_sec->flags & SEC_CODE) == 0) | |
451 | value -= elf32_hppa_hash_table (info)->global_value; | |
452 | break; | |
252b5132 | 453 | |
edd21aca AM |
454 | case R_PARISC_PLABEL32: |
455 | r_field = e_fsel; | |
456 | break; | |
457 | ||
458 | case R_PARISC_PLABEL21L: | |
459 | r_field = e_lrsel; | |
460 | break; | |
461 | ||
462 | case R_PARISC_PLABEL14R: | |
463 | r_field = e_rrsel; | |
464 | break; | |
465 | ||
466 | /* This case is separate as it may involve a lot more work | |
467 | to deal with linker stubs. */ | |
468 | case R_PARISC_PCREL17F: | |
469 | r_field = e_fsel; | |
470 | ||
471 | /* bfd_link_hash_undefweak symbols have sym_sec == NULL. */ | |
472 | if (sym_sec == NULL) | |
473 | break; | |
474 | ||
475 | /* Any kind of linker stub needed? */ | |
476 | /* bfd_vma value is unsigned, so this is testing for offsets | |
477 | outside the range -0x40000 to +0x3ffff */ | |
478 | if (value + addend - 8 + 0x40000 >= 0x80000) | |
252b5132 | 479 | { |
edd21aca AM |
480 | struct bfd_hash_table *stub_hash_table; |
481 | struct elf32_hppa_stub_hash_entry *stub_entry; | |
482 | char *stub_name; | |
483 | ||
484 | stub_name = elf32_hppa_stub_name (sym_name, sym_sec, | |
485 | input_section, addend, h); | |
486 | if (!stub_name) | |
487 | { | |
488 | (*_bfd_error_handler) ("%s: %s", | |
489 | bfd_get_filename (input_bfd), | |
490 | bfd_errmsg (bfd_get_error ())); | |
491 | return bfd_reloc_notsupported; | |
492 | } | |
493 | ||
494 | stub_hash_table = &elf32_hppa_hash_table (info)->stub_hash_table; | |
252b5132 | 495 | |
edd21aca AM |
496 | stub_entry = elf32_hppa_stub_hash_lookup (stub_hash_table, |
497 | stub_name, | |
498 | false, | |
499 | false); | |
500 | if (stub_entry == NULL) | |
501 | { | |
502 | (*_bfd_error_handler) | |
503 | (_("%s: cannot find stub entry %s"), | |
504 | bfd_get_filename (input_bfd), | |
505 | stub_name); | |
506 | free (stub_name); | |
507 | return bfd_reloc_notsupported; | |
508 | } | |
509 | ||
510 | /* Munge up the value and addend for elf32_hppa_relocate_insn. */ | |
511 | value = (stub_entry->offset | |
512 | + stub_entry->stub_sec->output_offset | |
513 | + stub_entry->stub_sec->output_section->vma | |
514 | - location); | |
515 | addend = 0; | |
516 | ||
517 | if (value + addend - 8 + 0x40000 >= 0x80000) | |
518 | { | |
519 | (*_bfd_error_handler) | |
520 | (_("%s: cannot reach stub %s, recompile with -ffunction-sections"), | |
521 | bfd_get_filename (input_bfd), | |
522 | stub_name); | |
523 | free (stub_name); | |
524 | return bfd_reloc_notsupported; | |
525 | } | |
252b5132 | 526 | |
edd21aca | 527 | free (stub_name); |
252b5132 | 528 | } |
edd21aca AM |
529 | break; |
530 | ||
531 | /* Something we don't know how to handle. */ | |
532 | default: | |
533 | return bfd_reloc_notsupported; | |
252b5132 | 534 | } |
edd21aca AM |
535 | |
536 | /* bfd_link_hash_undefweak symbols have sym_sec == NULL. */ | |
537 | if (sym_sec == NULL) | |
538 | { | |
539 | BFD_ASSERT (h != NULL && h->root.type == bfd_link_hash_undefweak); | |
540 | value = 0; | |
541 | } | |
542 | ||
543 | insn = elf32_hppa_relocate_insn (insn, value, addend, | |
544 | r_type, r_format, r_field); | |
545 | ||
546 | /* Update the instruction word. */ | |
547 | bfd_put_32 (input_bfd, insn, hit_data); | |
548 | return bfd_reloc_ok; | |
252b5132 RH |
549 | } |
550 | ||
551 | /* Relocate an HPPA ELF section. */ | |
552 | ||
553 | static boolean | |
554 | elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, | |
555 | contents, relocs, local_syms, local_sections) | |
edd21aca | 556 | bfd *output_bfd ATTRIBUTE_UNUSED; |
252b5132 RH |
557 | struct bfd_link_info *info; |
558 | bfd *input_bfd; | |
559 | asection *input_section; | |
560 | bfd_byte *contents; | |
561 | Elf_Internal_Rela *relocs; | |
562 | Elf_Internal_Sym *local_syms; | |
563 | asection **local_sections; | |
564 | { | |
565 | Elf_Internal_Shdr *symtab_hdr; | |
566 | Elf_Internal_Rela *rel; | |
567 | Elf_Internal_Rela *relend; | |
568 | ||
569 | symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | |
570 | ||
571 | rel = relocs; | |
572 | relend = relocs + input_section->reloc_count; | |
573 | for (; rel < relend; rel++) | |
574 | { | |
edd21aca | 575 | unsigned int r_type; |
252b5132 | 576 | reloc_howto_type *howto; |
edd21aca | 577 | unsigned int r_symndx; |
252b5132 RH |
578 | struct elf_link_hash_entry *h; |
579 | Elf_Internal_Sym *sym; | |
580 | asection *sym_sec; | |
581 | bfd_vma relocation; | |
582 | bfd_reloc_status_type r; | |
583 | const char *sym_name; | |
584 | ||
585 | r_type = ELF32_R_TYPE (rel->r_info); | |
edd21aca | 586 | if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED) |
252b5132 RH |
587 | { |
588 | bfd_set_error (bfd_error_bad_value); | |
589 | return false; | |
590 | } | |
591 | howto = elf_hppa_howto_table + r_type; | |
592 | ||
593 | r_symndx = ELF32_R_SYM (rel->r_info); | |
594 | ||
595 | if (info->relocateable) | |
596 | { | |
597 | /* This is a relocateable link. We don't have to change | |
598 | anything, unless the reloc is against a section symbol, | |
599 | in which case we have to adjust according to where the | |
600 | section symbol winds up in the output section. */ | |
601 | if (r_symndx < symtab_hdr->sh_info) | |
602 | { | |
603 | sym = local_syms + r_symndx; | |
604 | if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) | |
605 | { | |
606 | sym_sec = local_sections[r_symndx]; | |
607 | rel->r_addend += sym_sec->output_offset; | |
608 | } | |
609 | } | |
610 | ||
611 | continue; | |
612 | } | |
613 | ||
614 | /* This is a final link. */ | |
615 | h = NULL; | |
616 | sym = NULL; | |
617 | sym_sec = NULL; | |
618 | if (r_symndx < symtab_hdr->sh_info) | |
619 | { | |
620 | sym = local_syms + r_symndx; | |
621 | sym_sec = local_sections[r_symndx]; | |
622 | relocation = ((ELF_ST_TYPE (sym->st_info) == STT_SECTION | |
623 | ? 0 : sym->st_value) | |
624 | + sym_sec->output_offset | |
625 | + sym_sec->output_section->vma); | |
626 | } | |
627 | else | |
628 | { | |
edd21aca | 629 | int indx; |
252b5132 RH |
630 | |
631 | indx = r_symndx - symtab_hdr->sh_info; | |
632 | h = elf_sym_hashes (input_bfd)[indx]; | |
633 | while (h->root.type == bfd_link_hash_indirect | |
634 | || h->root.type == bfd_link_hash_warning) | |
635 | h = (struct elf_link_hash_entry *) h->root.u.i.link; | |
636 | if (h->root.type == bfd_link_hash_defined | |
637 | || h->root.type == bfd_link_hash_defweak) | |
638 | { | |
639 | sym_sec = h->root.u.def.section; | |
640 | relocation = (h->root.u.def.value | |
641 | + sym_sec->output_offset | |
642 | + sym_sec->output_section->vma); | |
643 | } | |
644 | else if (h->root.type == bfd_link_hash_undefweak) | |
645 | relocation = 0; | |
646 | else | |
647 | { | |
648 | if (!((*info->callbacks->undefined_symbol) | |
649 | (info, h->root.root.string, input_bfd, | |
5cc7c785 | 650 | input_section, rel->r_offset, true))) |
252b5132 RH |
651 | return false; |
652 | break; | |
653 | } | |
654 | } | |
655 | ||
656 | if (h != NULL) | |
657 | sym_name = h->root.root.string; | |
658 | else | |
659 | { | |
660 | sym_name = bfd_elf_string_from_elf_section (input_bfd, | |
661 | symtab_hdr->sh_link, | |
662 | sym->st_name); | |
663 | if (sym_name == NULL) | |
664 | return false; | |
665 | if (*sym_name == '\0') | |
666 | sym_name = bfd_section_name (input_bfd, sym_sec); | |
667 | } | |
668 | ||
edd21aca | 669 | r = elf32_hppa_bfd_final_link_relocate (howto, input_bfd, |
252b5132 RH |
670 | input_section, contents, |
671 | rel->r_offset, relocation, | |
672 | rel->r_addend, info, sym_sec, | |
edd21aca | 673 | sym_name, h); |
252b5132 | 674 | |
edd21aca | 675 | switch (r) |
252b5132 | 676 | { |
edd21aca AM |
677 | case bfd_reloc_ok: |
678 | break; | |
679 | ||
680 | case bfd_reloc_undefined: | |
681 | case bfd_reloc_notsupported: | |
682 | (*_bfd_error_handler) | |
683 | (_("%s: cannot handle relocation %s for %s at 0x%x in %s"), | |
684 | bfd_get_filename (input_bfd), | |
685 | howto->name, | |
686 | sym_name, | |
687 | rel->r_offset, | |
688 | input_section->name); | |
689 | return false; | |
690 | ||
691 | default: | |
692 | case bfd_reloc_outofrange: | |
693 | case bfd_reloc_overflow: | |
694 | { | |
695 | if (!((*info->callbacks->reloc_overflow) | |
696 | (info, sym_name, howto->name, (bfd_vma) 0, | |
697 | input_bfd, input_section, rel->r_offset))) | |
252b5132 | 698 | return false; |
edd21aca AM |
699 | } |
700 | break; | |
252b5132 RH |
701 | } |
702 | } | |
703 | ||
704 | return true; | |
705 | } | |
706 | ||
edd21aca AM |
707 | /* Called after we have seen all the input files/sections, but before |
708 | final symbol resolution and section placement has been determined. | |
252b5132 | 709 | |
edd21aca AM |
710 | We use this hook to (possibly) provide a value for __gp, then we |
711 | fall back to the generic ELF final link routine. */ | |
712 | ||
713 | boolean | |
714 | elf32_hppa_final_link (abfd, info) | |
715 | bfd *abfd; | |
252b5132 | 716 | struct bfd_link_info *info; |
252b5132 | 717 | { |
edd21aca | 718 | if (!info->relocateable) |
252b5132 RH |
719 | { |
720 | struct elf_link_hash_entry *h; | |
721 | asection *sec; | |
edd21aca | 722 | bfd_vma gp_val; |
252b5132 | 723 | |
edd21aca AM |
724 | h = elf_link_hash_lookup (elf_hash_table (info), "$global$", |
725 | false, false, false); | |
252b5132 | 726 | |
edd21aca AM |
727 | if (h != NULL |
728 | && h->root.type == bfd_link_hash_defined) | |
252b5132 | 729 | { |
edd21aca AM |
730 | gp_val = h->root.u.def.value; |
731 | sec = h->root.u.def.section; | |
252b5132 RH |
732 | } |
733 | else | |
edd21aca AM |
734 | { |
735 | /* If $global$ isn't defined, we could make one up ourselves | |
736 | from the start of .plt, .dlt, or .data For the time | |
737 | being, just bomb. */ | |
738 | (*info->callbacks->undefined_symbol) | |
739 | (info, "$global$", abfd, NULL, 0, true); | |
740 | return false; | |
741 | } | |
252b5132 | 742 | |
edd21aca AM |
743 | elf32_hppa_hash_table (info)->global_value = (gp_val |
744 | + sec->output_section->vma | |
745 | + sec->output_offset); | |
252b5132 RH |
746 | } |
747 | ||
edd21aca AM |
748 | /* Invoke the standard linker. */ |
749 | return bfd_elf_bfd_final_link (abfd, info); | |
252b5132 RH |
750 | } |
751 | ||
252b5132 RH |
752 | /* Undo the generic ELF code's subtraction of section->vma from the |
753 | value of each external symbol. */ | |
754 | ||
755 | static boolean | |
756 | elf32_hppa_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) | |
5f771d47 ILT |
757 | bfd *abfd ATTRIBUTE_UNUSED; |
758 | struct bfd_link_info *info ATTRIBUTE_UNUSED; | |
759 | const Elf_Internal_Sym *sym ATTRIBUTE_UNUSED; | |
760 | const char **namep ATTRIBUTE_UNUSED; | |
761 | flagword *flagsp ATTRIBUTE_UNUSED; | |
252b5132 RH |
762 | asection **secp; |
763 | bfd_vma *valp; | |
764 | { | |
765 | *valp += (*secp)->vma; | |
766 | return true; | |
767 | } | |
768 | ||
edd21aca AM |
769 | /* Compute the size of the stub needed to call from INPUT_SEC (OFFSET) |
770 | to DESTINATION. Return zero if no stub is needed to perform such a | |
771 | call. */ | |
252b5132 RH |
772 | |
773 | static unsigned int | |
edd21aca AM |
774 | elf32_hppa_size_of_stub (input_sec, offset, destination) |
775 | asection *input_sec; | |
776 | bfd_vma offset; | |
777 | bfd_vma destination; | |
252b5132 | 778 | { |
edd21aca AM |
779 | bfd_vma location; |
780 | ||
781 | /* Determine where the call point is. */ | |
782 | location = (input_sec->output_offset | |
783 | + input_sec->output_section->vma | |
784 | + offset); | |
785 | ||
786 | /* Determine if a long branch stub is needed. parisc branch offsets | |
787 | are relative to the second instruction past the branch, ie. +8 | |
788 | bytes on from the branch instruction location. The offset is | |
789 | signed, 17 bits wide, and counts in units of 4 bytes. | |
790 | bfd_vma is unsigned, so this is testing for offsets outside the | |
791 | range -0x40000 to +0x3ffff */ | |
792 | if (destination - location - 8 + 0x40000 >= 0x80000) | |
793 | return 8; | |
794 | return 0; | |
252b5132 RH |
795 | } |
796 | ||
797 | /* Build one linker stub as defined by the stub hash table entry GEN_ENTRY. | |
edd21aca AM |
798 | IN_ARG contains the link info pointer. */ |
799 | ||
800 | #define LDIL_R1 0x20200000 /* ldil LR'XXX,%r1 */ | |
801 | #define BE_SR4_R1 0xe0202002 /* be,n RR'XXX(%sr4,%r1) */ | |
252b5132 RH |
802 | |
803 | static boolean | |
edd21aca | 804 | elf32_hppa_build_one_stub (gen_entry, in_arg) |
252b5132 | 805 | struct bfd_hash_entry *gen_entry; |
edd21aca | 806 | PTR in_arg; |
252b5132 | 807 | { |
edd21aca AM |
808 | struct elf32_hppa_stub_hash_entry *stub_entry; |
809 | struct elf32_hppa_link_hash_table *hppa_link_hash; | |
810 | asection *stub_sec; | |
811 | bfd *stub_bfd; | |
252b5132 RH |
812 | bfd_byte *loc; |
813 | symvalue sym_value; | |
edd21aca AM |
814 | int insn; |
815 | ||
816 | /* Massage our args to the form they really have. */ | |
817 | stub_entry = (struct elf32_hppa_stub_hash_entry *) gen_entry; | |
818 | hppa_link_hash = (struct elf32_hppa_link_hash_table *) in_arg; | |
252b5132 | 819 | |
edd21aca | 820 | stub_sec = stub_entry->stub_sec; |
252b5132 RH |
821 | |
822 | /* Make a note of the offset within the stubs for this entry. */ | |
edd21aca AM |
823 | stub_entry->offset = hppa_link_hash->offset[stub_sec->index]; |
824 | loc = stub_sec->contents + stub_entry->offset; | |
252b5132 | 825 | |
edd21aca AM |
826 | sym_value = (stub_entry->target_value |
827 | + stub_entry->target_section->output_offset | |
828 | + stub_entry->target_section->output_section->vma); | |
252b5132 | 829 | |
edd21aca | 830 | stub_bfd = stub_sec->owner; |
252b5132 | 831 | |
edd21aca AM |
832 | /* Create the long branch. A long branch is formed with "ldil" |
833 | loading the upper bits of the target address into a register, | |
834 | then branching with "be" which adds in the lower bits. | |
835 | The "be" has its delay slot nullified. */ | |
836 | insn = hppa_rebuild_insn (LDIL_R1, | |
837 | hppa_field_adjust (sym_value, 0, e_lrsel), | |
838 | 21); | |
839 | bfd_put_32 (stub_bfd, insn, loc); | |
840 | ||
841 | insn = hppa_rebuild_insn (BE_SR4_R1, | |
842 | hppa_field_adjust (sym_value, 0, e_rrsel) >> 2, | |
843 | 17); | |
844 | bfd_put_32 (stub_bfd, insn, loc + 4); | |
845 | ||
846 | hppa_link_hash->offset[stub_sec->index] += 8; | |
847 | ||
848 | return true; | |
849 | } | |
850 | ||
851 | /* As above, but don't actually build the stub. Just bump offset so | |
852 | we know stub section sizes. */ | |
853 | ||
854 | static boolean | |
855 | elf32_hppa_size_one_stub (gen_entry, in_arg) | |
856 | struct bfd_hash_entry *gen_entry; | |
857 | PTR in_arg; | |
858 | { | |
859 | struct elf32_hppa_stub_hash_entry *stub_entry; | |
860 | struct elf32_hppa_link_hash_table *hppa_link_hash; | |
861 | ||
862 | /* Massage our args to the form they really have. */ | |
863 | stub_entry = (struct elf32_hppa_stub_hash_entry *) gen_entry; | |
864 | hppa_link_hash = (struct elf32_hppa_link_hash_table *) in_arg; | |
865 | ||
866 | hppa_link_hash->offset[stub_entry->stub_sec->index] += 8; | |
252b5132 | 867 | |
252b5132 RH |
868 | return true; |
869 | } | |
870 | ||
871 | /* External entry points for sizing and building linker stubs. */ | |
872 | ||
873 | /* Build all the stubs associated with the current output file. The | |
874 | stubs are kept in a hash table attached to the main linker hash | |
875 | table. This is called via hppaelf_finish in the linker. */ | |
876 | ||
877 | boolean | |
edd21aca | 878 | elf32_hppa_build_stubs (stub_bfd, link_info) |
252b5132 | 879 | bfd *stub_bfd; |
edd21aca | 880 | struct bfd_link_info *link_info; |
252b5132 | 881 | { |
edd21aca AM |
882 | asection *stub_sec; |
883 | struct bfd_hash_table *table; | |
884 | struct elf32_hppa_link_hash_table *hppa_link_hash; | |
885 | ||
886 | for (stub_sec = stub_bfd->sections; stub_sec; stub_sec = stub_sec->next) | |
887 | { | |
888 | unsigned int size; | |
889 | ||
890 | /* Allocate memory to hold the linker stubs. */ | |
891 | size = bfd_section_size (stub_bfd, stub_sec); | |
892 | stub_sec->contents = (unsigned char *) bfd_zalloc (stub_bfd, size); | |
893 | if (stub_sec->contents == NULL && size != 0) | |
894 | return false; | |
895 | } | |
252b5132 RH |
896 | |
897 | /* Build the stubs as directed by the stub hash table. */ | |
edd21aca AM |
898 | hppa_link_hash = elf32_hppa_hash_table (link_info); |
899 | memset (hppa_link_hash->offset, 0, | |
900 | stub_bfd->section_count * sizeof (bfd_vma)); | |
901 | ||
902 | table = &hppa_link_hash->stub_hash_table; | |
903 | bfd_hash_traverse (table, elf32_hppa_build_one_stub, hppa_link_hash); | |
252b5132 RH |
904 | |
905 | return true; | |
906 | } | |
907 | ||
908 | /* Determine and set the size of the stub section for a final link. | |
909 | ||
910 | The basic idea here is to examine all the relocations looking for | |
911 | PC-relative calls to a target that is unreachable with a "bl" | |
912 | instruction or calls where the caller and callee disagree on the | |
edd21aca AM |
913 | location of their arguments or return value. Currently, we don't |
914 | support elf arg relocs. */ | |
252b5132 RH |
915 | |
916 | boolean | |
edd21aca AM |
917 | elf32_hppa_size_stubs (stub_bfd, link_info, |
918 | add_stub_section, layout_sections_again) | |
252b5132 | 919 | bfd *stub_bfd; |
252b5132 | 920 | struct bfd_link_info *link_info; |
edd21aca AM |
921 | asection * (*add_stub_section) PARAMS ((const char *, asection *)); |
922 | void (*layout_sections_again) PARAMS ((void)); | |
252b5132 RH |
923 | { |
924 | bfd *input_bfd; | |
edd21aca | 925 | asection *section; |
e049a0de | 926 | Elf_Internal_Sym *local_syms, **all_local_syms; |
edd21aca AM |
927 | asection **stub_section_created; |
928 | unsigned int i, indx, bfd_count, sec_count; | |
929 | asection *stub_sec; | |
930 | asection *first_init_sec = NULL; | |
931 | asection *first_fini_sec = NULL; | |
932 | struct elf32_hppa_link_hash_table *hppa_link_hash; | |
933 | struct bfd_hash_table *stub_hash_table; | |
934 | boolean stub_changed; | |
935 | ||
936 | /* Count the number of input BFDs and the total number of input sections. */ | |
937 | for (input_bfd = link_info->input_bfds, bfd_count = 0, sec_count = 0; | |
252b5132 RH |
938 | input_bfd != NULL; |
939 | input_bfd = input_bfd->link_next) | |
252b5132 | 940 | { |
edd21aca AM |
941 | bfd_count += 1; |
942 | sec_count += input_bfd->section_count; | |
252b5132 RH |
943 | } |
944 | ||
edd21aca AM |
945 | stub_section_created |
946 | = (asection **) bfd_zmalloc (sizeof (asection *) * sec_count); | |
947 | if (stub_section_created == NULL) | |
948 | return false; | |
949 | ||
950 | /* We want to read in symbol extension records only once. To do this | |
951 | we need to read in the local symbols in parallel and save them for | |
952 | later use; so hold pointers to the local symbols in an array. */ | |
953 | all_local_syms | |
954 | = (Elf_Internal_Sym **) bfd_zmalloc (sizeof (Elf_Internal_Sym *) | |
955 | * bfd_count); | |
956 | if (all_local_syms == NULL) | |
957 | goto error_ret_free_stub; | |
958 | ||
959 | /* Walk over all the input BFDs adding entries to the args hash table | |
960 | for all the external functions. */ | |
961 | for (input_bfd = link_info->input_bfds, indx = 0; | |
252b5132 | 962 | input_bfd != NULL; |
edd21aca | 963 | input_bfd = input_bfd->link_next, indx++) |
252b5132 | 964 | { |
edd21aca AM |
965 | Elf_Internal_Shdr *symtab_hdr; |
966 | Elf_Internal_Sym *isym; | |
967 | Elf32_External_Sym *ext_syms, *esym; | |
968 | ||
252b5132 RH |
969 | /* We'll need the symbol table in a second. */ |
970 | symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | |
971 | if (symtab_hdr->sh_info == 0) | |
972 | continue; | |
973 | ||
edd21aca AM |
974 | /* We need an array of the local symbols attached to the input bfd. |
975 | Unfortunately, we're going to have to read & swap them in. */ | |
976 | local_syms = (Elf_Internal_Sym *) | |
977 | bfd_malloc (symtab_hdr->sh_info * sizeof (Elf_Internal_Sym)); | |
978 | if (local_syms == NULL) | |
979 | { | |
980 | goto error_ret_free_local; | |
981 | } | |
982 | all_local_syms[indx] = local_syms; | |
983 | ext_syms = (Elf32_External_Sym *) | |
984 | bfd_malloc (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)); | |
985 | if (ext_syms == NULL) | |
986 | { | |
987 | goto error_ret_free_local; | |
988 | } | |
989 | ||
990 | if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 | |
991 | || (bfd_read (ext_syms, 1, | |
992 | (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)), | |
993 | input_bfd) | |
994 | != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)))) | |
995 | { | |
996 | free (ext_syms); | |
997 | goto error_ret_free_local; | |
998 | } | |
999 | ||
1000 | /* Swap the local symbols in. */ | |
1001 | isym = local_syms; | |
1002 | esym = ext_syms; | |
1003 | for (i = 0; i < symtab_hdr->sh_info; i++, esym++, isym++) | |
1004 | bfd_elf32_swap_symbol_in (input_bfd, esym, isym); | |
1005 | ||
1006 | /* Now we can free the external symbols. */ | |
1007 | free (ext_syms); | |
1008 | } | |
1009 | ||
1010 | stub_hash_table = &elf32_hppa_hash_table (link_info)->stub_hash_table; | |
1011 | ||
1012 | while (1) | |
1013 | { | |
1014 | stub_changed = 0; | |
252b5132 | 1015 | |
edd21aca AM |
1016 | /* Now that we have argument location information for all the |
1017 | global functions we can start looking for stubs. */ | |
1018 | for (input_bfd = link_info->input_bfds, indx = 0, sec_count = 0; | |
1019 | input_bfd != NULL; | |
1020 | input_bfd = input_bfd->link_next, indx++) | |
252b5132 | 1021 | { |
edd21aca | 1022 | Elf_Internal_Shdr *symtab_hdr; |
252b5132 | 1023 | |
edd21aca AM |
1024 | /* We'll need the symbol table in a second. */ |
1025 | symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | |
1026 | if (symtab_hdr->sh_info == 0) | |
252b5132 RH |
1027 | continue; |
1028 | ||
edd21aca | 1029 | local_syms = all_local_syms[indx]; |
252b5132 | 1030 | |
edd21aca AM |
1031 | /* Walk over each section attached to the input bfd. */ |
1032 | for (section = input_bfd->sections; | |
1033 | section != NULL; | |
1034 | section = section->next, sec_count++) | |
252b5132 | 1035 | { |
edd21aca AM |
1036 | Elf_Internal_Shdr *input_rel_hdr; |
1037 | Elf32_External_Rela *external_relocs, *erelaend, *erela; | |
1038 | Elf_Internal_Rela *internal_relocs, *irelaend, *irela; | |
252b5132 | 1039 | |
edd21aca AM |
1040 | /* If there aren't any relocs, then there's nothing to do. */ |
1041 | if ((section->flags & SEC_RELOC) == 0 | |
1042 | || section->reloc_count == 0) | |
1043 | continue; | |
252b5132 | 1044 | |
edd21aca AM |
1045 | /* Allocate space for the external relocations. */ |
1046 | external_relocs | |
1047 | = ((Elf32_External_Rela *) | |
1048 | bfd_malloc (section->reloc_count | |
1049 | * sizeof (Elf32_External_Rela))); | |
1050 | if (external_relocs == NULL) | |
1051 | { | |
1052 | goto error_ret_free_local; | |
1053 | } | |
252b5132 | 1054 | |
edd21aca AM |
1055 | /* Likewise for the internal relocations. */ |
1056 | internal_relocs = ((Elf_Internal_Rela *) | |
1057 | bfd_malloc (section->reloc_count | |
1058 | * sizeof (Elf_Internal_Rela))); | |
1059 | if (internal_relocs == NULL) | |
1060 | { | |
1061 | free (external_relocs); | |
1062 | goto error_ret_free_local; | |
1063 | } | |
252b5132 | 1064 | |
edd21aca AM |
1065 | /* Read in the external relocs. */ |
1066 | input_rel_hdr = &elf_section_data (section)->rel_hdr; | |
1067 | if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0 | |
1068 | || bfd_read (external_relocs, 1, | |
1069 | input_rel_hdr->sh_size, | |
1070 | input_bfd) != input_rel_hdr->sh_size) | |
252b5132 | 1071 | { |
edd21aca AM |
1072 | free (external_relocs); |
1073 | error_ret_free_internal: | |
252b5132 | 1074 | free (internal_relocs); |
edd21aca | 1075 | goto error_ret_free_local; |
252b5132 RH |
1076 | } |
1077 | ||
edd21aca AM |
1078 | /* Swap in the relocs. */ |
1079 | erela = external_relocs; | |
1080 | erelaend = erela + section->reloc_count; | |
1081 | irela = internal_relocs; | |
1082 | for (; erela < erelaend; erela++, irela++) | |
1083 | bfd_elf32_swap_reloca_in (input_bfd, erela, irela); | |
1084 | ||
1085 | /* We're done with the external relocs, free them. */ | |
1086 | free (external_relocs); | |
252b5132 | 1087 | |
edd21aca AM |
1088 | /* Now examine each relocation. */ |
1089 | irela = internal_relocs; | |
1090 | irelaend = irela + section->reloc_count; | |
1091 | for (; irela < irelaend; irela++) | |
252b5132 | 1092 | { |
edd21aca AM |
1093 | unsigned int r_type, r_indx, size_of_stub; |
1094 | struct elf32_hppa_stub_hash_entry *stub_entry; | |
1095 | asection *sym_sec; | |
1096 | const char *sym_name; | |
1097 | symvalue sym_value; | |
1098 | bfd_vma destination; | |
1099 | struct elf_link_hash_entry *hash; | |
1100 | char *stub_name; | |
1101 | ||
1102 | r_type = ELF32_R_TYPE (irela->r_info); | |
1103 | r_indx = ELF32_R_SYM (irela->r_info); | |
1104 | ||
1105 | if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED) | |
252b5132 | 1106 | { |
edd21aca AM |
1107 | bfd_set_error (bfd_error_bad_value); |
1108 | goto error_ret_free_internal; | |
252b5132 | 1109 | } |
252b5132 | 1110 | |
edd21aca AM |
1111 | /* Only look for stubs on call instructions. */ |
1112 | if (r_type != (unsigned int) R_PARISC_PCREL17F) | |
1113 | continue; | |
1114 | ||
1115 | /* Now determine the call target, its name, value, section | |
1116 | and argument relocation bits. */ | |
1117 | sym_sec = NULL; | |
1118 | hash = NULL; | |
1119 | if (r_indx < symtab_hdr->sh_info) | |
252b5132 | 1120 | { |
edd21aca AM |
1121 | /* It's a local symbol. */ |
1122 | Elf_Internal_Sym *sym; | |
1123 | Elf_Internal_Shdr *hdr; | |
1124 | ||
1125 | sym = local_syms + r_indx; | |
1126 | hdr = elf_elfsections (input_bfd)[sym->st_shndx]; | |
1127 | sym_sec = hdr->bfd_section; | |
1128 | sym_name = | |
1129 | bfd_elf_string_from_elf_section (input_bfd, | |
1130 | symtab_hdr->sh_link, | |
1131 | sym->st_name); | |
1132 | sym_value = (ELF_ST_TYPE (sym->st_info) == STT_SECTION | |
1133 | ? 0 : sym->st_value); | |
1134 | destination = (sym_value + irela->r_addend | |
252b5132 RH |
1135 | + sym_sec->output_offset |
1136 | + sym_sec->output_section->vma); | |
1137 | } | |
1138 | else | |
1139 | { | |
edd21aca AM |
1140 | /* It's an external symbol. */ |
1141 | int e_indx; | |
252b5132 | 1142 | |
edd21aca AM |
1143 | e_indx = r_indx - symtab_hdr->sh_info; |
1144 | hash = elf_sym_hashes (input_bfd)[e_indx]; | |
252b5132 | 1145 | |
edd21aca AM |
1146 | while (hash->root.type == bfd_link_hash_indirect |
1147 | || hash->root.type == bfd_link_hash_warning) | |
1148 | hash = (struct elf_link_hash_entry *) | |
1149 | hash->root.u.i.link; | |
252b5132 | 1150 | |
edd21aca AM |
1151 | if (hash->root.type == bfd_link_hash_undefined |
1152 | || hash->root.type == bfd_link_hash_undefweak) | |
1153 | continue; | |
1154 | ||
1155 | if (hash->root.type == bfd_link_hash_defined | |
1156 | || hash->root.type == bfd_link_hash_defweak) | |
1157 | { | |
1158 | sym_sec = hash->root.u.def.section; | |
1159 | sym_name = hash->root.root.string; | |
1160 | sym_value = hash->root.u.def.value; | |
1161 | destination = (sym_value + irela->r_addend | |
1162 | + sym_sec->output_offset | |
1163 | + sym_sec->output_section->vma); | |
1164 | } | |
1165 | else | |
1166 | { | |
1167 | bfd_set_error (bfd_error_bad_value); | |
1168 | goto error_ret_free_internal; | |
1169 | } | |
252b5132 | 1170 | } |
252b5132 | 1171 | |
edd21aca AM |
1172 | /* Determine what (if any) linker stub is needed and its |
1173 | size (in bytes). */ | |
1174 | size_of_stub = elf32_hppa_size_of_stub (section, | |
1175 | irela->r_offset, | |
1176 | destination); | |
1177 | if (size_of_stub == 0) | |
1178 | continue; | |
1179 | ||
1180 | /* Get the name of this stub. */ | |
1181 | stub_name = elf32_hppa_stub_name (sym_name, | |
1182 | sym_sec, | |
1183 | section, | |
1184 | irela->r_addend, | |
1185 | hash); | |
1186 | if (!stub_name) | |
1187 | goto error_ret_free_internal; | |
252b5132 | 1188 | |
edd21aca AM |
1189 | stub_entry = elf32_hppa_stub_hash_lookup (stub_hash_table, |
1190 | stub_name, | |
1191 | false, | |
1192 | false); | |
1193 | if (stub_entry != NULL) | |
252b5132 | 1194 | { |
edd21aca | 1195 | /* The proper stub has already been created. */ |
252b5132 | 1196 | free (stub_name); |
edd21aca | 1197 | continue; |
252b5132 | 1198 | } |
edd21aca AM |
1199 | |
1200 | stub_sec = stub_section_created[sec_count]; | |
1201 | if (stub_sec == NULL) | |
252b5132 | 1202 | { |
edd21aca AM |
1203 | char *s_name; |
1204 | int nstub; | |
1205 | int special_sec = 0; | |
1206 | ||
1207 | /* We only want one stub for .init and .fini | |
1208 | because glibc splits the _init and _fini | |
1209 | functions into two parts. We don't want to | |
1210 | put a stub in the middle of a function. */ | |
1211 | if (strncmp (section->name, ".init", 5) == 0) | |
1212 | { | |
1213 | stub_sec = first_init_sec; | |
1214 | special_sec = 1; | |
1215 | } | |
1216 | else if (strncmp (section->name, ".fini", 5) == 0) | |
1217 | { | |
1218 | stub_sec = first_fini_sec; | |
1219 | special_sec = 2; | |
1220 | } | |
1221 | if (stub_sec == NULL) | |
252b5132 | 1222 | { |
edd21aca AM |
1223 | s_name = bfd_alloc (stub_bfd, 16); |
1224 | if (s_name == NULL) | |
1225 | { | |
1226 | free (stub_name); | |
1227 | goto error_ret_free_internal; | |
1228 | } | |
1229 | nstub = stub_bfd->section_count; | |
1230 | sprintf (s_name, ".stub_%x", nstub); | |
1231 | stub_sec = (*add_stub_section) (s_name, section); | |
1232 | if (stub_sec == NULL) | |
1233 | { | |
1234 | free (stub_name); | |
1235 | goto error_ret_free_internal; | |
1236 | } | |
1237 | if (special_sec != 0) | |
1238 | { | |
1239 | if (special_sec == 1) | |
1240 | first_init_sec = stub_sec; | |
1241 | else | |
1242 | first_fini_sec = stub_sec; | |
1243 | } | |
252b5132 | 1244 | } |
edd21aca AM |
1245 | stub_section_created[sec_count] = stub_sec; |
1246 | } | |
252b5132 | 1247 | |
edd21aca AM |
1248 | /* Enter this entry into the linker stub |
1249 | hash table. */ | |
1250 | stub_entry = elf32_hppa_stub_hash_lookup (stub_hash_table, | |
1251 | stub_name, | |
1252 | true, | |
1253 | false); | |
1254 | if (stub_entry == NULL) | |
1255 | { | |
1256 | (*_bfd_error_handler) | |
1257 | (_("%s: cannot find stub entry %s"), | |
1258 | bfd_get_filename (section->owner), | |
1259 | stub_name); | |
1260 | free (stub_name); | |
1261 | goto error_ret_free_internal; | |
252b5132 | 1262 | } |
edd21aca AM |
1263 | |
1264 | /* We'll need these to determine the address | |
1265 | that the stub will branch to. */ | |
1266 | stub_entry->stub_sec = stub_sec; | |
1267 | stub_entry->offset = 0; | |
1268 | stub_entry->target_value = sym_value; | |
1269 | stub_entry->target_section = sym_sec; | |
1270 | stub_changed = 1; | |
252b5132 | 1271 | } |
edd21aca AM |
1272 | /* We're done with the internal relocs, free them. */ |
1273 | free (internal_relocs); | |
252b5132 | 1274 | } |
252b5132 | 1275 | } |
edd21aca AM |
1276 | |
1277 | if (!stub_changed) | |
1278 | break; | |
1279 | ||
1280 | /* OK, we've added some stubs. Find out the new size of the | |
1281 | stub sections. */ | |
1282 | hppa_link_hash = elf32_hppa_hash_table (link_info); | |
1283 | hppa_link_hash->offset = (bfd_vma *) | |
1284 | bfd_realloc (hppa_link_hash->offset, | |
1285 | stub_bfd->section_count * sizeof (bfd_vma)); | |
1286 | if (hppa_link_hash->offset == NULL) | |
1287 | goto error_ret_free_local; | |
1288 | ||
1289 | memset (hppa_link_hash->offset, 0, | |
1290 | stub_bfd->section_count * sizeof (bfd_vma)); | |
1291 | ||
1292 | bfd_hash_traverse (stub_hash_table, | |
1293 | elf32_hppa_size_one_stub, | |
1294 | hppa_link_hash); | |
1295 | ||
1296 | for (stub_sec = stub_bfd->sections; | |
1297 | stub_sec != NULL; | |
1298 | stub_sec = stub_sec->next) | |
1299 | { | |
1300 | bfd_set_section_size (stub_bfd, stub_sec, | |
1301 | hppa_link_hash->offset[stub_sec->index]); | |
1302 | } | |
1303 | /* Ask the linker to do its stuff. */ | |
1304 | (*layout_sections_again) (); | |
252b5132 | 1305 | } |
edd21aca | 1306 | |
252b5132 RH |
1307 | /* We're done with the local symbols, free them. */ |
1308 | for (i = 0; i < bfd_count; i++) | |
1309 | if (all_local_syms[i]) | |
1310 | free (all_local_syms[i]); | |
1311 | free (all_local_syms); | |
edd21aca | 1312 | free (stub_section_created); |
252b5132 RH |
1313 | return true; |
1314 | ||
edd21aca AM |
1315 | error_ret_free_local: |
1316 | for (i = 0; i < bfd_count; i++) | |
1317 | if (all_local_syms[i]) | |
1318 | free (all_local_syms[i]); | |
1319 | free (all_local_syms); | |
1320 | ||
1321 | error_ret_free_stub: | |
1322 | free (stub_section_created); | |
252b5132 RH |
1323 | return false; |
1324 | } | |
1325 | ||
1326 | /* Misc BFD support code. */ | |
1327 | #define bfd_elf32_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup | |
1396cd2d | 1328 | #define bfd_elf32_bfd_is_local_label_name elf_hppa_is_local_label_name |
9e103c9c JL |
1329 | #define elf_info_to_howto elf_hppa_info_to_howto |
1330 | #define elf_info_to_howto_rel elf_hppa_info_to_howto_rel | |
252b5132 | 1331 | |
252b5132 RH |
1332 | /* Stuff for the BFD linker. */ |
1333 | #define elf_backend_relocate_section elf32_hppa_relocate_section | |
1334 | #define elf_backend_add_symbol_hook elf32_hppa_add_symbol_hook | |
edd21aca AM |
1335 | #define bfd_elf32_bfd_final_link elf32_hppa_final_link |
1336 | #if 0 | |
1337 | #define elf_backend_check_relocs elf32_hppa_check_relocs | |
1338 | #endif | |
252b5132 RH |
1339 | #define bfd_elf32_bfd_link_hash_table_create \ |
1340 | elf32_hppa_link_hash_table_create | |
052e120f JL |
1341 | #define elf_backend_fake_sections elf_hppa_fake_sections |
1342 | ||
252b5132 RH |
1343 | |
1344 | #define TARGET_BIG_SYM bfd_elf32_hppa_vec | |
1345 | #define TARGET_BIG_NAME "elf32-hppa" | |
1346 | #define ELF_ARCH bfd_arch_hppa | |
1347 | #define ELF_MACHINE_CODE EM_PARISC | |
1348 | #define ELF_MAXPAGESIZE 0x1000 | |
1349 | ||
1350 | #include "elf32-target.h" |