1 /* LoongArch-specific support for NN-bit ELF.
2 Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
28 #include "elf/loongarch.h"
29 #include "elfxx-loongarch.h"
32 loongarch_info_to_howto_rela (bfd
*abfd
, arelent
*cache_ptr
,
33 Elf_Internal_Rela
*dst
)
35 cache_ptr
->howto
= loongarch_elf_rtype_to_howto (abfd
,
36 ELFNN_R_TYPE (dst
->r_info
));
37 return cache_ptr
->howto
!= NULL
;
40 /* LoongArch ELF linker hash entry. */
41 struct loongarch_elf_link_hash_entry
43 struct elf_link_hash_entry elf
;
53 #define loongarch_elf_hash_entry(ent) \
54 ((struct loongarch_elf_link_hash_entry *) (ent))
56 struct _bfd_loongarch_elf_obj_tdata
58 struct elf_obj_tdata root
;
60 /* The tls_type for each local got entry. */
61 char *local_got_tls_type
;
64 #define _bfd_loongarch_elf_tdata(abfd) \
65 ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
67 #define _bfd_loongarch_elf_local_got_tls_type(abfd) \
68 (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
70 #define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
72 ? &loongarch_elf_hash_entry (h)->tls_type \
73 : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
75 #define is_loongarch_elf(bfd) \
76 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
77 && elf_tdata (bfd) != NULL \
78 && elf_object_id (bfd) == LARCH_ELF_DATA)
80 struct loongarch_elf_link_hash_table
82 struct elf_link_hash_table elf
;
84 /* Short-cuts to get to dynamic linker sections. */
87 /* Small local sym to section mapping cache. */
88 struct sym_cache sym_cache
;
90 /* Used by local STT_GNU_IFUNC symbols. */
91 htab_t loc_hash_table
;
92 void *loc_hash_memory
;
94 /* The max alignment of output sections. */
95 bfd_vma max_alignment
;
98 /* Get the LoongArch ELF linker hash table from a link_info structure. */
99 #define loongarch_elf_hash_table(p) \
100 (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
101 ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
104 #define MINUS_ONE ((bfd_vma) 0 - 1)
106 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
108 #define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
109 #define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
111 #define PLT_HEADER_INSNS 8
112 #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
114 #define PLT_ENTRY_INSNS 4
115 #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
117 #define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
119 #define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
121 #define elf_backend_want_got_plt 1
123 #define elf_backend_plt_readonly 1
125 #define elf_backend_want_plt_sym 1
126 #define elf_backend_plt_alignment 4
127 #define elf_backend_can_gc_sections 1
128 #define elf_backend_can_refcount 1
129 #define elf_backend_want_got_sym 1
131 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
133 #define elf_backend_want_dynrelro 1
134 #define elf_backend_rela_normal 1
135 #define elf_backend_default_execstack 0
137 /* Generate a PLT header. */
140 loongarch_make_plt_header (bfd_vma got_plt_addr
, bfd_vma plt_header_addr
,
143 bfd_vma pcrel
= got_plt_addr
- plt_header_addr
;
146 if (pcrel
+ 0x80000800 > 0xffffffff)
148 _bfd_error_handler (_("%#" PRIx64
" invaild imm"), (uint64_t) pcrel
);
149 bfd_set_error (bfd_error_bad_value
);
152 hi
= ((pcrel
+ 0x800) >> 12) & 0xfffff;
155 /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
156 sub.[wd] $t1, $t1, $t3
157 ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
158 addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
159 addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
160 srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
161 ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
164 if (GOT_ENTRY_SIZE
== 8)
166 entry
[0] = 0x1c00000e | (hi
& 0xfffff) << 5;
167 entry
[1] = 0x0011bdad;
168 entry
[2] = 0x28c001cf | (lo
& 0xfff) << 10;
169 entry
[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE
+ 12)) & 0xfff) << 10;
170 entry
[4] = 0x02c001cc | (lo
& 0xfff) << 10;
171 entry
[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES
) << 10;
172 entry
[6] = 0x28c0018c | GOT_ENTRY_SIZE
<< 10;
173 entry
[7] = 0x4c0001e0;
177 entry
[0] = 0x1c00000e | (hi
& 0xfffff) << 5;
178 entry
[1] = 0x00113dad;
179 entry
[2] = 0x288001cf | (lo
& 0xfff) << 10;
180 entry
[3] = 0x028001ad | ((-(PLT_HEADER_SIZE
+ 12)) & 0xfff) << 10;
181 entry
[4] = 0x028001cc | (lo
& 0xfff) << 10;
182 entry
[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES
) << 10;
183 entry
[6] = 0x2880018c | GOT_ENTRY_SIZE
<< 10;
184 entry
[7] = 0x4c0001e0;
189 /* Generate a PLT entry. */
192 loongarch_make_plt_entry (bfd_vma got_plt_entry_addr
, bfd_vma plt_entry_addr
,
195 bfd_vma pcrel
= got_plt_entry_addr
- plt_entry_addr
;
198 if (pcrel
+ 0x80000800 > 0xffffffff)
200 _bfd_error_handler (_("%#" PRIx64
" invaild imm"), (uint64_t) pcrel
);
201 bfd_set_error (bfd_error_bad_value
);
204 hi
= ((pcrel
+ 0x800) >> 12) & 0xfffff;
207 entry
[0] = 0x1c00000f | (hi
& 0xfffff) << 5;
208 entry
[1] = ((GOT_ENTRY_SIZE
== 8 ? 0x28c001ef : 0x288001ef)
209 | (lo
& 0xfff) << 10);
210 entry
[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
211 entry
[3] = 0x03400000; /* nop */
216 /* Create an entry in an LoongArch ELF linker hash table. */
218 static struct bfd_hash_entry
*
219 link_hash_newfunc (struct bfd_hash_entry
*entry
, struct bfd_hash_table
*table
,
222 struct loongarch_elf_link_hash_entry
*eh
;
224 /* Allocate the structure if it has not already been allocated by a
228 entry
= bfd_hash_allocate (table
, sizeof (*eh
));
233 /* Call the allocation method of the superclass. */
234 entry
= _bfd_elf_link_hash_newfunc (entry
, table
, string
);
237 eh
= (struct loongarch_elf_link_hash_entry
*) entry
;
238 eh
->tls_type
= GOT_UNKNOWN
;
244 /* Compute a hash of a local hash entry. We use elf_link_hash_entry
245 for local symbol so that we can handle local STT_GNU_IFUNC symbols
246 as global symbol. We reuse indx and dynstr_index for local symbol
247 hash since they aren't used by global symbols in this backend. */
250 elfNN_loongarch_local_htab_hash (const void *ptr
)
252 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) ptr
;
253 return ELF_LOCAL_SYMBOL_HASH (h
->indx
, h
->dynstr_index
);
256 /* Compare local hash entries. */
259 elfNN_loongarch_local_htab_eq (const void *ptr1
, const void *ptr2
)
261 struct elf_link_hash_entry
*h1
= (struct elf_link_hash_entry
*) ptr1
;
262 struct elf_link_hash_entry
*h2
= (struct elf_link_hash_entry
*) ptr2
;
264 return h1
->indx
== h2
->indx
&& h1
->dynstr_index
== h2
->dynstr_index
;
267 /* Find and/or create a hash entry for local symbol. */
268 static struct elf_link_hash_entry
*
269 elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table
*htab
,
270 bfd
*abfd
, const Elf_Internal_Rela
*rel
,
273 struct loongarch_elf_link_hash_entry e
, *ret
;
274 asection
*sec
= abfd
->sections
;
275 hashval_t h
= ELF_LOCAL_SYMBOL_HASH (sec
->id
, ELFNN_R_SYM (rel
->r_info
));
278 e
.elf
.indx
= sec
->id
;
279 e
.elf
.dynstr_index
= ELFNN_R_SYM (rel
->r_info
);
280 slot
= htab_find_slot_with_hash (htab
->loc_hash_table
, &e
, h
,
281 create
? INSERT
: NO_INSERT
);
288 ret
= (struct loongarch_elf_link_hash_entry
*) *slot
;
292 ret
= ((struct loongarch_elf_link_hash_entry
*)
293 objalloc_alloc ((struct objalloc
*) htab
->loc_hash_memory
,
294 sizeof (struct loongarch_elf_link_hash_entry
)));
297 memset (ret
, 0, sizeof (*ret
));
298 ret
->elf
.indx
= sec
->id
;
299 ret
->elf
.pointer_equality_needed
= 0;
300 ret
->elf
.dynstr_index
= ELFNN_R_SYM (rel
->r_info
);
301 ret
->elf
.dynindx
= -1;
302 ret
->elf
.needs_plt
= 0;
303 ret
->elf
.plt
.refcount
= -1;
304 ret
->elf
.got
.refcount
= -1;
305 ret
->elf
.def_dynamic
= 0;
306 ret
->elf
.def_regular
= 1;
307 ret
->elf
.ref_dynamic
= 0; /* This should be always 0 for local. */
308 ret
->elf
.ref_regular
= 0;
309 ret
->elf
.forced_local
= 1;
310 ret
->elf
.root
.type
= bfd_link_hash_defined
;
316 /* Destroy an LoongArch elf linker hash table. */
319 elfNN_loongarch_link_hash_table_free (bfd
*obfd
)
321 struct loongarch_elf_link_hash_table
*ret
;
322 ret
= (struct loongarch_elf_link_hash_table
*) obfd
->link
.hash
;
324 if (ret
->loc_hash_table
)
325 htab_delete (ret
->loc_hash_table
);
326 if (ret
->loc_hash_memory
)
327 objalloc_free ((struct objalloc
*) ret
->loc_hash_memory
);
329 _bfd_elf_link_hash_table_free (obfd
);
332 /* Create a LoongArch ELF linker hash table. */
334 static struct bfd_link_hash_table
*
335 loongarch_elf_link_hash_table_create (bfd
*abfd
)
337 struct loongarch_elf_link_hash_table
*ret
;
338 bfd_size_type amt
= sizeof (struct loongarch_elf_link_hash_table
);
340 ret
= (struct loongarch_elf_link_hash_table
*) bfd_zmalloc (amt
);
344 if (!_bfd_elf_link_hash_table_init
345 (&ret
->elf
, abfd
, link_hash_newfunc
,
346 sizeof (struct loongarch_elf_link_hash_entry
), LARCH_ELF_DATA
))
352 ret
->max_alignment
= MINUS_ONE
;
354 ret
->loc_hash_table
= htab_try_create (1024, elfNN_loongarch_local_htab_hash
,
355 elfNN_loongarch_local_htab_eq
, NULL
);
356 ret
->loc_hash_memory
= objalloc_create ();
357 if (!ret
->loc_hash_table
|| !ret
->loc_hash_memory
)
359 elfNN_loongarch_link_hash_table_free (abfd
);
362 ret
->elf
.root
.hash_table_free
= elfNN_loongarch_link_hash_table_free
;
364 return &ret
->elf
.root
;
367 /* Merge backend specific data from an object file to the output
368 object file when linking. */
371 elfNN_loongarch_merge_private_bfd_data (bfd
*ibfd
, struct bfd_link_info
*info
)
373 bfd
*obfd
= info
->output_bfd
;
374 flagword in_flags
= elf_elfheader (ibfd
)->e_flags
;
375 flagword out_flags
= elf_elfheader (obfd
)->e_flags
;
377 if (!is_loongarch_elf (ibfd
) || !is_loongarch_elf (obfd
))
380 if (strcmp (bfd_get_target (ibfd
), bfd_get_target (obfd
)) != 0)
382 _bfd_error_handler (_("%pB: ABI is incompatible with that of "
383 "the selected emulation:\n"
384 " target emulation `%s' does not match `%s'"),
385 ibfd
, bfd_get_target (ibfd
), bfd_get_target (obfd
));
389 if (!_bfd_elf_merge_object_attributes (ibfd
, info
))
392 /* If the input BFD is not a dynamic object and it does not contain any
393 non-data sections, do not account its ABI. For example, various
394 packages produces such data-only relocatable objects with
395 `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
396 But they are compatible with all ABIs. */
397 if (!(ibfd
->flags
& DYNAMIC
))
400 bool have_code_sections
= false;
401 for (sec
= ibfd
->sections
; sec
!= NULL
; sec
= sec
->next
)
402 if ((bfd_section_flags (sec
)
403 & (SEC_LOAD
| SEC_CODE
| SEC_HAS_CONTENTS
))
404 == (SEC_LOAD
| SEC_CODE
| SEC_HAS_CONTENTS
))
406 have_code_sections
= true;
409 if (!have_code_sections
)
413 if (!elf_flags_init (obfd
))
415 elf_flags_init (obfd
) = true;
416 elf_elfheader (obfd
)->e_flags
= in_flags
;
420 /* Disallow linking different ABIs. */
421 if (EF_LOONGARCH_ABI(out_flags
^ in_flags
) & EF_LOONGARCH_ABI_MASK
)
423 _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd
);
430 bfd_set_error (bfd_error_bad_value
);
434 /* Create the .got section. */
437 loongarch_elf_create_got_section (bfd
*abfd
, struct bfd_link_info
*info
)
442 struct elf_link_hash_entry
*h
;
443 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
444 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
446 /* This function may be called more than once. */
447 if (htab
->sgot
!= NULL
)
450 flags
= bed
->dynamic_sec_flags
;
451 name
= bed
->rela_plts_and_copies_p
? ".rela.got" : ".rel.got";
452 s
= bfd_make_section_anyway_with_flags (abfd
, name
, flags
| SEC_READONLY
);
454 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
458 s
= s_got
= bfd_make_section_anyway_with_flags (abfd
, ".got", flags
);
459 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
463 /* The first bit of the global offset table is the header. */
464 s
->size
+= bed
->got_header_size
;
466 if (bed
->want_got_plt
)
468 s
= bfd_make_section_anyway_with_flags (abfd
, ".got.plt", flags
);
469 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
473 /* Reserve room for the header. */
474 s
->size
= GOTPLT_HEADER_SIZE
;
477 if (bed
->want_got_sym
)
479 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
480 section. We don't do this in the linker script because we don't want
481 to define the symbol if we are not creating a global offset table. */
482 h
= _bfd_elf_define_linkage_sym (abfd
, info
, s_got
,
483 "_GLOBAL_OFFSET_TABLE_");
484 elf_hash_table (info
)->hgot
= h
;
491 /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
492 .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
496 loongarch_elf_create_dynamic_sections (bfd
*dynobj
, struct bfd_link_info
*info
)
498 struct loongarch_elf_link_hash_table
*htab
;
500 htab
= loongarch_elf_hash_table (info
);
501 BFD_ASSERT (htab
!= NULL
);
503 if (!loongarch_elf_create_got_section (dynobj
, info
))
506 if (!_bfd_elf_create_dynamic_sections (dynobj
, info
))
509 if (!bfd_link_pic (info
))
511 = bfd_make_section_anyway_with_flags (dynobj
, ".tdata.dyn",
512 SEC_ALLOC
| SEC_THREAD_LOCAL
);
514 if (!htab
->elf
.splt
|| !htab
->elf
.srelplt
|| !htab
->elf
.sdynbss
515 || (!bfd_link_pic (info
) && (!htab
->elf
.srelbss
|| !htab
->sdyntdata
)))
522 loongarch_elf_record_tls_and_got_reference (bfd
*abfd
,
523 struct bfd_link_info
*info
,
524 struct elf_link_hash_entry
*h
,
525 unsigned long symndx
,
528 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
529 Elf_Internal_Shdr
*symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
531 /* This is a global offset table entry for a local symbol. */
532 if (elf_local_got_refcounts (abfd
) == NULL
)
535 symtab_hdr
->sh_info
* (sizeof (bfd_vma
) + sizeof (tls_type
));
536 if (!(elf_local_got_refcounts (abfd
) = bfd_zalloc (abfd
, size
)))
538 _bfd_loongarch_elf_local_got_tls_type (abfd
) =
539 (char *) (elf_local_got_refcounts (abfd
) + symtab_hdr
->sh_info
);
548 if (htab
->elf
.sgot
== NULL
549 && !loongarch_elf_create_got_section (htab
->elf
.dynobj
, info
))
553 if (h
->got
.refcount
< 0)
558 elf_local_got_refcounts (abfd
)[symndx
]++;
561 /* No need for GOT. */
564 _bfd_error_handler (_("Internal error: unreachable."));
568 char *new_tls_type
= &_bfd_loongarch_elf_tls_type (abfd
, h
, symndx
);
569 *new_tls_type
|= tls_type
;
570 if ((*new_tls_type
& GOT_NORMAL
) && (*new_tls_type
& ~GOT_NORMAL
))
572 _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
573 "thread local symbol"),
575 h
? h
->root
.root
.string
: "<local>");
582 /* Look through the relocs for a section during the first phase, and
583 allocate space in the global offset table or procedure linkage
587 loongarch_elf_check_relocs (bfd
*abfd
, struct bfd_link_info
*info
,
588 asection
*sec
, const Elf_Internal_Rela
*relocs
)
590 struct loongarch_elf_link_hash_table
*htab
;
591 Elf_Internal_Shdr
*symtab_hdr
;
592 struct elf_link_hash_entry
**sym_hashes
;
593 const Elf_Internal_Rela
*rel
;
594 asection
*sreloc
= NULL
;
596 if (bfd_link_relocatable (info
))
599 htab
= loongarch_elf_hash_table (info
);
600 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
601 sym_hashes
= elf_sym_hashes (abfd
);
603 if (htab
->elf
.dynobj
== NULL
)
604 htab
->elf
.dynobj
= abfd
;
606 for (rel
= relocs
; rel
< relocs
+ sec
->reloc_count
; rel
++)
609 unsigned int r_symndx
;
610 struct elf_link_hash_entry
*h
;
611 Elf_Internal_Sym
*isym
= NULL
;
613 r_symndx
= ELFNN_R_SYM (rel
->r_info
);
614 r_type
= ELFNN_R_TYPE (rel
->r_info
);
616 if (r_symndx
>= NUM_SHDR_ENTRIES (symtab_hdr
))
618 _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd
, r_symndx
);
622 if (r_symndx
< symtab_hdr
->sh_info
)
624 /* A local symbol. */
625 isym
= bfd_sym_from_r_symndx (&htab
->elf
.sym_cache
, abfd
, r_symndx
);
629 if (ELF_ST_TYPE (isym
->st_info
) == STT_GNU_IFUNC
)
631 h
= elfNN_loongarch_get_local_sym_hash (htab
, abfd
, rel
, true);
635 h
->type
= STT_GNU_IFUNC
;
643 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
644 while (h
->root
.type
== bfd_link_hash_indirect
645 || h
->root
.type
== bfd_link_hash_warning
)
646 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
649 /* It is referenced by a non-shared object. */
653 if (h
&& h
->type
== STT_GNU_IFUNC
)
655 if (htab
->elf
.dynobj
== NULL
)
656 htab
->elf
.dynobj
= abfd
;
658 /* Create 'irelifunc' in PIC object. */
659 if (bfd_link_pic (info
)
660 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
662 /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
663 else if (!htab
->elf
.splt
664 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
666 /* Create the ifunc sections, iplt and ipltgot, for static
668 if ((r_type
== R_LARCH_64
|| r_type
== R_LARCH_32
)
669 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
672 if (h
->plt
.refcount
< 0)
677 elf_tdata (info
->output_bfd
)->has_gnu_osabi
|= elf_gnu_osabi_ifunc
;
680 int need_dynreloc
= 0;
681 int only_need_pcrel
= 0;
685 case R_LARCH_GOT_PC_HI20
:
686 case R_LARCH_GOT_HI20
:
687 case R_LARCH_SOP_PUSH_GPREL
:
690 h
->pointer_equality_needed
= 1;
691 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
697 case R_LARCH_TLS_LD_PC_HI20
:
698 case R_LARCH_TLS_LD_HI20
:
699 case R_LARCH_TLS_GD_PC_HI20
:
700 case R_LARCH_TLS_GD_HI20
:
701 case R_LARCH_SOP_PUSH_TLS_GD
:
702 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
708 case R_LARCH_TLS_IE_PC_HI20
:
709 case R_LARCH_TLS_IE_HI20
:
710 case R_LARCH_SOP_PUSH_TLS_GOT
:
711 if (bfd_link_pic (info
))
712 /* May fail for lazy-bind. */
713 info
->flags
|= DF_STATIC_TLS
;
715 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
721 case R_LARCH_TLS_LE_HI20
:
722 case R_LARCH_SOP_PUSH_TLS_TPREL
:
723 if (!bfd_link_executable (info
))
726 info
->flags
|= DF_STATIC_TLS
;
728 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
734 case R_LARCH_ABS_HI20
:
735 case R_LARCH_SOP_PUSH_ABSOLUTE
:
737 /* If this reloc is in a read-only section, we might
738 need a copy reloc. We can't check reliably at this
739 stage whether the section is read-only, as input
740 sections have not yet been mapped to output sections.
741 Tentatively set the flag for now, and correct in
742 adjust_dynamic_symbol. */
746 case R_LARCH_PCALA_HI20
:
749 /* For pcalau12i + jirl. */
751 if (h
->plt
.refcount
< 0)
756 h
->pointer_equality_needed
= 1;
767 if (!bfd_link_pic (info
))
770 /* We try to create PLT stub for all non-local function. */
771 if (h
->plt
.refcount
< 0)
778 case R_LARCH_SOP_PUSH_PCREL
:
781 if (!bfd_link_pic (info
))
784 /* We try to create PLT stub for all non-local function. */
785 if (h
->plt
.refcount
< 0)
788 h
->pointer_equality_needed
= 1;
793 case R_LARCH_SOP_PUSH_PLT_PCREL
:
794 /* This symbol requires a procedure linkage table entry. We
795 actually build the entry in adjust_dynamic_symbol,
796 because this might be a case of linking PIC code without
797 linking in any dynamic objects, in which case we don't
798 need to generate a procedure linkage table after all. */
802 if (h
->plt
.refcount
< 0)
808 case R_LARCH_TLS_DTPREL32
:
809 case R_LARCH_TLS_DTPREL64
:
814 case R_LARCH_JUMP_SLOT
:
820 /* If resolved symbol is defined in this object,
821 1. Under pie, the symbol is known. We convert it
822 into R_LARCH_RELATIVE and need load-addr still.
823 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
824 3. Under dll, R_LARCH_NN can't be changed normally, since
825 its defination could be covered by the one in executable.
826 For symbolic, we convert it into R_LARCH_RELATIVE.
827 Thus, only under pde, it needs pcrel only. We discard it. */
828 only_need_pcrel
= bfd_link_pde (info
);
831 && (!bfd_link_pic (info
)
832 || h
->type
== STT_GNU_IFUNC
))
834 /* This reloc might not bind locally. */
836 h
->pointer_equality_needed
= 1;
839 || (sec
->flags
& (SEC_CODE
| SEC_READONLY
)) != 0)
841 /* We may need a .plt entry if the symbol is a function
842 defined in a shared lib or is a function referenced
843 from the code or read-only section. */
844 h
->plt
.refcount
+= 1;
849 case R_LARCH_GNU_VTINHERIT
:
850 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
854 case R_LARCH_GNU_VTENTRY
:
855 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
863 /* Record some info for sizing and allocating dynamic entry. */
864 if (need_dynreloc
&& (sec
->flags
& SEC_ALLOC
))
866 /* When creating a shared object, we must copy these
867 relocs into the output file. We create a reloc
868 section in dynobj and make room for the reloc. */
869 struct elf_dyn_relocs
*p
;
870 struct elf_dyn_relocs
**head
;
875 = _bfd_elf_make_dynamic_reloc_section (sec
, htab
->elf
.dynobj
,
876 LARCH_ELF_LOG_WORD_BYTES
,
877 abfd
, /*rela?*/ true);
882 /* If this is a global symbol, we count the number of
883 relocations we need for this symbol. */
885 head
= &h
->dyn_relocs
;
888 /* Track dynamic relocs needed for local syms too.
889 We really need local syms available to do this
895 s
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
899 vpp
= &elf_section_data (s
)->local_dynrel
;
900 head
= (struct elf_dyn_relocs
**) vpp
;
904 if (p
== NULL
|| p
->sec
!= sec
)
906 bfd_size_type amt
= sizeof *p
;
907 p
= (struct elf_dyn_relocs
*) bfd_alloc (htab
->elf
.dynobj
, amt
);
918 p
->pc_count
+= only_need_pcrel
;
925 /* Find dynamic relocs for H that apply to read-only sections. */
928 readonly_dynrelocs (struct elf_link_hash_entry
*h
)
930 struct elf_dyn_relocs
*p
;
932 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
934 asection
*s
= p
->sec
->output_section
;
936 if (s
!= NULL
&& (s
->flags
& SEC_READONLY
) != 0)
942 /* Adjust a symbol defined by a dynamic object and referenced by a
943 regular object. The current definition is in some section of the
944 dynamic object, but we're not including those sections. We have to
945 change the definition to something the rest of the link can
948 loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info
*info
,
949 struct elf_link_hash_entry
*h
)
951 struct loongarch_elf_link_hash_table
*htab
;
954 htab
= loongarch_elf_hash_table (info
);
955 BFD_ASSERT (htab
!= NULL
);
957 dynobj
= htab
->elf
.dynobj
;
959 /* Make sure we know what is going on here. */
960 BFD_ASSERT (dynobj
!= NULL
961 && (h
->needs_plt
|| h
->type
== STT_GNU_IFUNC
|| h
->is_weakalias
962 || (h
->def_dynamic
&& h
->ref_regular
&& !h
->def_regular
)));
964 /* If this is a function, put it in the procedure linkage table. We
965 will fill in the contents of the procedure linkage table later
966 (although we could actually do it here). */
967 if (h
->type
== STT_FUNC
|| h
->type
== STT_GNU_IFUNC
|| h
->needs_plt
)
969 if (h
->plt
.refcount
< 0
970 || (h
->type
!= STT_GNU_IFUNC
971 && (SYMBOL_REFERENCES_LOCAL (info
, h
)
972 || (ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
973 && h
->root
.type
== bfd_link_hash_undefweak
))))
975 /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
976 in an input file, but the symbol was never referred to by a
977 dynamic object, or if all references were garbage collected.
978 In such a case, we don't actually need to build a PLT entry. */
979 h
->plt
.offset
= MINUS_ONE
;
988 h
->plt
.offset
= MINUS_ONE
;
990 /* If this is a weak symbol, and there is a real definition, the
991 processor independent code will have arranged for us to see the
992 real definition first, and we can just use the same value. */
995 struct elf_link_hash_entry
*def
= weakdef (h
);
996 BFD_ASSERT (def
->root
.type
== bfd_link_hash_defined
);
997 h
->root
.u
.def
.section
= def
->root
.u
.def
.section
;
998 h
->root
.u
.def
.value
= def
->root
.u
.def
.value
;
1002 /* R_LARCH_COPY is not adept glibc, not to generate. */
1003 /* Can not print anything, because make check ld. */
1007 /* Allocate space in .plt, .got and associated reloc sections for
1011 allocate_dynrelocs (struct elf_link_hash_entry
*h
, void *inf
)
1013 struct bfd_link_info
*info
;
1014 struct loongarch_elf_link_hash_table
*htab
;
1015 struct elf_dyn_relocs
*p
;
1017 if (h
->root
.type
== bfd_link_hash_indirect
)
1020 if (h
->type
== STT_GNU_IFUNC
1024 info
= (struct bfd_link_info
*) inf
;
1025 htab
= loongarch_elf_hash_table (info
);
1026 bool dyn
= htab
->elf
.dynamic_sections_created
;
1027 BFD_ASSERT (htab
!= NULL
);
1031 asection
*plt
, *gotplt
, *relplt
;
1040 if (h
->dynindx
== -1 && !h
->forced_local
&& dyn
1041 && h
->root
.type
== bfd_link_hash_undefweak
)
1043 if (!bfd_elf_link_record_dynamic_symbol (info
, h
))
1047 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info
), h
)
1048 && h
->type
!= STT_GNU_IFUNC
)
1051 plt
= htab
->elf
.splt
;
1052 gotplt
= htab
->elf
.sgotplt
;
1053 relplt
= htab
->elf
.srelplt
;
1055 else if (htab
->elf
.iplt
)
1057 /* .iplt only for IFUNC. */
1058 if (h
->type
!= STT_GNU_IFUNC
)
1061 plt
= htab
->elf
.iplt
;
1062 gotplt
= htab
->elf
.igotplt
;
1063 relplt
= htab
->elf
.irelplt
;
1069 plt
->size
= PLT_HEADER_SIZE
;
1071 h
->plt
.offset
= plt
->size
;
1072 plt
->size
+= PLT_ENTRY_SIZE
;
1073 gotplt
->size
+= GOT_ENTRY_SIZE
;
1074 relplt
->size
+= sizeof (ElfNN_External_Rela
);
1076 /* If this symbol is not defined in a regular file, and we are
1077 not generating a shared library, then set the symbol to this
1078 location in the .plt. This is required to make function
1079 pointers compare as equal between the normal executable and
1080 the shared library. */
1081 if (!bfd_link_pic (info
)
1084 h
->root
.u
.def
.section
= plt
;
1085 h
->root
.u
.def
.value
= h
->plt
.offset
;
1093 h
->plt
.offset
= MINUS_ONE
;
1095 if (0 < h
->got
.refcount
)
1098 int tls_type
= loongarch_elf_hash_entry (h
)->tls_type
;
1100 /* Make sure this symbol is output as a dynamic symbol.
1101 Undefined weak syms won't yet be marked as dynamic. */
1102 if (h
->dynindx
== -1 && !h
->forced_local
&& dyn
1103 && h
->root
.type
== bfd_link_hash_undefweak
)
1105 if (!bfd_elf_link_record_dynamic_symbol (info
, h
))
1110 h
->got
.offset
= s
->size
;
1111 if (tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
1113 /* TLS_GD needs two dynamic relocs and two GOT slots. */
1114 if (tls_type
& GOT_TLS_GD
)
1116 s
->size
+= 2 * GOT_ENTRY_SIZE
;
1117 if (bfd_link_executable (info
))
1119 /* Link exe and not defined local. */
1120 if (!SYMBOL_REFERENCES_LOCAL (info
, h
))
1121 htab
->elf
.srelgot
->size
+= 2 * sizeof (ElfNN_External_Rela
);
1125 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
1126 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1128 htab
->elf
.srelgot
->size
+= 2 * sizeof (ElfNN_External_Rela
);
1132 /* TLS_IE needs one dynamic reloc and one GOT slot. */
1133 if (tls_type
& GOT_TLS_IE
)
1135 s
->size
+= GOT_ENTRY_SIZE
;
1137 if (bfd_link_executable (info
))
1139 /* Link exe and not defined local. */
1140 if (!SYMBOL_REFERENCES_LOCAL (info
, h
))
1141 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1145 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1151 s
->size
+= GOT_ENTRY_SIZE
;
1152 if ((ELF_ST_VISIBILITY (h
->other
) == STV_DEFAULT
1153 || h
->root
.type
!= bfd_link_hash_undefweak
)
1154 && (bfd_link_pic (info
)
1155 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn
, bfd_link_pic (info
),
1157 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
1158 /* Undefined weak symbol in static PIE resolves to 0 without
1159 any dynamic relocations. */
1160 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1164 h
->got
.offset
= MINUS_ONE
;
1166 if (h
->dyn_relocs
== NULL
)
1169 /* Extra dynamic relocate,
1171 * R_LARCH_TLS_DTPRELNN
1175 if (SYMBOL_CALLS_LOCAL (info
, h
))
1177 struct elf_dyn_relocs
**pp
;
1179 for (pp
= &h
->dyn_relocs
; (p
= *pp
) != NULL
;)
1181 p
->count
-= p
->pc_count
;
1190 if (h
->root
.type
== bfd_link_hash_undefweak
)
1192 if (UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
)
1193 || ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
1194 || (!bfd_link_pic (info
) && h
->non_got_ref
))
1195 h
->dyn_relocs
= NULL
;
1196 else if (h
->dynindx
== -1 && !h
->forced_local
)
1198 /* Make sure this symbol is output as a dynamic symbol.
1199 Undefined weak syms won't yet be marked as dynamic. */
1200 if (!bfd_elf_link_record_dynamic_symbol (info
, h
))
1203 if (h
->dynindx
== -1)
1204 h
->dyn_relocs
= NULL
;
1208 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
1210 asection
*sreloc
= elf_section_data (p
->sec
)->sreloc
;
1211 sreloc
->size
+= p
->count
* sizeof (ElfNN_External_Rela
);
1217 /* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
1218 For local def and ref ifunc,
1219 dynamic relocations are stored in
1220 1. rela.srelgot section in dynamic object (dll or exec).
1221 2. rela.irelplt section in static executable.
1222 Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
1223 instead of rela.srelplt. Glibc ELF loader will not support
1224 R_LARCH_IRELATIVE relocation in rela.plt. */
1227 local_allocate_ifunc_dyn_relocs (struct bfd_link_info
*info
,
1228 struct elf_link_hash_entry
*h
,
1229 struct elf_dyn_relocs
**head
,
1230 unsigned int plt_entry_size
,
1231 unsigned int plt_header_size
,
1232 unsigned int got_entry_size
,
1235 asection
*plt
, *gotplt
, *relplt
;
1236 struct elf_dyn_relocs
*p
;
1237 unsigned int sizeof_reloc
;
1238 const struct elf_backend_data
*bed
;
1239 struct elf_link_hash_table
*htab
;
1240 /* If AVOID_PLT is TRUE, don't use PLT if possible. */
1241 bool use_plt
= !avoid_plt
|| h
->plt
.refcount
> 0;
1242 bool need_dynreloc
= !use_plt
|| bfd_link_pic (info
);
1244 /* When a PIC object references a STT_GNU_IFUNC symbol defined
1245 in executable or it isn't referenced via PLT, the address of
1246 the resolved function may be used. But in non-PIC executable,
1247 the address of its plt slot may be used. Pointer equality may
1248 not work correctly. PIE or non-PLT reference should be used if
1249 pointer equality is required here.
1251 If STT_GNU_IFUNC symbol is defined in position-dependent executable,
1252 backend should change it to the normal function and set its address
1253 to its PLT entry which should be resolved by R_*_IRELATIVE at
1254 run-time. All external references should be resolved to its PLT in
1257 && !(bfd_link_pde (info
) && h
->def_regular
)
1258 && (h
->dynindx
!= -1
1259 || info
->export_dynamic
)
1260 && h
->pointer_equality_needed
)
1262 info
->callbacks
->einfo
1263 /* xgettext:c-format. */
1264 (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
1265 "equality in `%pB' can not be used when making an "
1266 "executable; recompile with -fPIE and relink with -pie\n"),
1267 h
->root
.root
.string
,
1268 h
->root
.u
.def
.section
->owner
);
1269 bfd_set_error (bfd_error_bad_value
);
1273 htab
= elf_hash_table (info
);
1275 /* When the symbol is marked with regular reference, if PLT isn't used
1276 or we are building a PIC object, we must keep dynamic relocation
1277 if there is non-GOT reference and use PLT if there is PC-relative
1279 if (need_dynreloc
&& h
->ref_regular
)
1282 for (p
= *head
; p
!= NULL
; p
= p
->next
)
1286 /* Need dynamic relocations for non-GOT reference. */
1290 /* Must use PLT for PC-relative reference. */
1292 need_dynreloc
= bfd_link_pic (info
);
1300 /* Support garbage collection against STT_GNU_IFUNC symbols. */
1301 if (h
->plt
.refcount
<= 0 && h
->got
.refcount
<= 0)
1303 h
->got
= htab
->init_got_offset
;
1304 h
->plt
= htab
->init_plt_offset
;
1309 /* Return and discard space for dynamic relocations against it if
1310 it is never referenced. */
1311 if (!h
->ref_regular
)
1313 if (h
->plt
.refcount
> 0
1314 || h
->got
.refcount
> 0)
1316 h
->got
= htab
->init_got_offset
;
1317 h
->plt
= htab
->init_plt_offset
;
1323 bed
= get_elf_backend_data (info
->output_bfd
);
1324 if (bed
->rela_plts_and_copies_p
)
1325 sizeof_reloc
= bed
->s
->sizeof_rela
;
1327 sizeof_reloc
= bed
->s
->sizeof_rel
;
1329 /* When building a static executable, use iplt, igot.plt and
1330 rela.iplt sections for STT_GNU_IFUNC symbols. */
1331 if (htab
->splt
!= NULL
)
1334 gotplt
= htab
->sgotplt
;
1335 /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */
1336 relplt
= htab
->srelgot
;
1338 /* If this is the first plt entry and PLT is used, make room for
1339 the special first entry. */
1340 if (plt
->size
== 0 && use_plt
)
1341 plt
->size
+= plt_header_size
;
1346 gotplt
= htab
->igotplt
;
1347 relplt
= htab
->irelplt
;
1352 /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
1353 the original value for R_*_IRELATIVE. */
1354 h
->plt
.offset
= plt
->size
;
1356 /* Make room for this entry in the plt/iplt section. */
1357 plt
->size
+= plt_entry_size
;
1359 /* We also need to make an entry in the got.plt/got.iplt section,
1360 which will be placed in the got section by the linker script. */
1361 gotplt
->size
+= got_entry_size
;
1364 /* We also need to make an entry in the rela.plt/.rela.iplt
1365 section for GOTPLT relocation if PLT is used. */
1368 relplt
->size
+= sizeof_reloc
;
1369 relplt
->reloc_count
++;
1372 /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
1373 there is a non-GOT reference in a PIC object or PLT isn't used. */
1374 if (!need_dynreloc
|| !h
->non_got_ref
)
1377 /* Finally, allocate space. */
1381 bfd_size_type count
= 0;
1389 htab
->ifunc_resolvers
= count
!= 0;
1391 /* Dynamic relocations are stored in
1392 1. rela.srelgot section in PIC object.
1393 2. rela.srelgot section in dynamic executable.
1394 3. rela.irelplt section in static executable. */
1395 if (htab
->splt
!= NULL
)
1396 htab
->srelgot
->size
+= count
* sizeof_reloc
;
1399 relplt
->size
+= count
* sizeof_reloc
;
1400 relplt
->reloc_count
+= count
;
1404 /* For STT_GNU_IFUNC symbol, got.plt has the real function address
1405 and got has the PLT entry adddress. We will load the GOT entry
1406 with the PLT entry in finish_dynamic_symbol if it is used. For
1407 branch, it uses got.plt. For symbol value, if PLT is used,
1408 1. Use got.plt in a PIC object if it is forced local or not
1410 2. Use got.plt in a non-PIC object if pointer equality isn't
1412 3. Use got.plt in PIE.
1413 4. Use got.plt if got isn't used.
1414 5. Otherwise use got so that it can be shared among different
1415 objects at run-time.
1416 If PLT isn't used, always use got for symbol value.
1417 We only need to relocate got entry in PIC object or in dynamic
1418 executable without PLT. */
1420 && (h
->got
.refcount
<= 0
1421 || (bfd_link_pic (info
)
1422 && (h
->dynindx
== -1
1423 || h
->forced_local
))
1425 !h
->pointer_equality_needed
)
1426 || htab
->sgot
== NULL
))
1429 h
->got
.offset
= (bfd_vma
) -1;
1435 /* PLT isn't used. */
1436 h
->plt
.offset
= (bfd_vma
) -1;
1438 if (h
->got
.refcount
<= 0)
1440 /* GOT isn't need when there are only relocations for static
1442 h
->got
.offset
= (bfd_vma
) -1;
1446 h
->got
.offset
= htab
->sgot
->size
;
1447 htab
->sgot
->size
+= got_entry_size
;
1448 /* Need to relocate the GOT entry in a PIC object or PLT isn't
1449 used. Otherwise, the GOT entry will be filled with the PLT
1450 entry and dynamic GOT relocation isn't needed. */
1453 /* For non-static executable, dynamic GOT relocation is in
1454 rela.got section, but for static executable, it is
1455 in rela.iplt section. */
1456 if (htab
->splt
!= NULL
)
1457 htab
->srelgot
->size
+= sizeof_reloc
;
1460 relplt
->size
+= sizeof_reloc
;
1461 relplt
->reloc_count
++;
1470 /* Allocate space in .plt, .got and associated reloc sections for
1471 ifunc dynamic relocs. */
1474 elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry
*h
, void *inf
)
1476 struct bfd_link_info
*info
;
1477 /* An example of a bfd_link_hash_indirect symbol is versioned
1478 symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
1479 -> __gxx_personality_v0(bfd_link_hash_defined)
1481 There is no need to process bfd_link_hash_indirect symbols here
1482 because we will also be presented with the concrete instance of
1483 the symbol and loongarch_elf_copy_indirect_symbol () will have been
1484 called to copy all relevant data from the generic to the concrete
1486 if (h
->root
.type
== bfd_link_hash_indirect
)
1489 if (h
->root
.type
== bfd_link_hash_warning
)
1490 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
1492 info
= (struct bfd_link_info
*) inf
;
1494 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
1495 here if it is defined and referenced in a non-shared object. */
1496 if (h
->type
== STT_GNU_IFUNC
&& h
->def_regular
)
1498 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
1499 return local_allocate_ifunc_dyn_relocs (info
, h
,
1506 return _bfd_elf_allocate_ifunc_dyn_relocs (info
, h
,
1517 /* Allocate space in .plt, .got and associated reloc sections for
1518 ifunc dynamic relocs. */
1521 elfNN_allocate_local_ifunc_dynrelocs (void **slot
, void *inf
)
1523 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
1525 if (h
->type
!= STT_GNU_IFUNC
1529 || h
->root
.type
!= bfd_link_hash_defined
)
1532 return elfNN_allocate_ifunc_dynrelocs (h
, inf
);
1535 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
1536 read-only sections. */
1539 maybe_set_textrel (struct elf_link_hash_entry
*h
, void *info_p
)
1543 if (h
->root
.type
== bfd_link_hash_indirect
)
1546 sec
= readonly_dynrelocs (h
);
1549 struct bfd_link_info
*info
= (struct bfd_link_info
*) info_p
;
1551 info
->flags
|= DF_TEXTREL
;
1552 info
->callbacks
->minfo (_("%pB: dynamic relocation against `%pT' in "
1553 "read-only section `%pA'\n"),
1554 sec
->owner
, h
->root
.root
.string
, sec
);
1556 /* Not an error, just cut short the traversal. */
1563 loongarch_elf_size_dynamic_sections (bfd
*output_bfd
,
1564 struct bfd_link_info
*info
)
1566 struct loongarch_elf_link_hash_table
*htab
;
1571 htab
= loongarch_elf_hash_table (info
);
1572 BFD_ASSERT (htab
!= NULL
);
1573 dynobj
= htab
->elf
.dynobj
;
1574 BFD_ASSERT (dynobj
!= NULL
);
1576 if (htab
->elf
.dynamic_sections_created
)
1578 /* Set the contents of the .interp section to the interpreter. */
1579 if (bfd_link_executable (info
) && !info
->nointerp
)
1581 const char *interpreter
;
1582 flagword flags
= elf_elfheader (output_bfd
)->e_flags
;
1583 s
= bfd_get_linker_section (dynobj
, ".interp");
1584 BFD_ASSERT (s
!= NULL
);
1585 if (EF_LOONGARCH_IS_ILP32 (flags
))
1586 interpreter
= "/lib32/ld.so.1";
1587 else if (EF_LOONGARCH_IS_LP64 (flags
))
1588 interpreter
= "/lib64/ld.so.1";
1590 interpreter
= "/lib/ld.so.1";
1591 s
->contents
= (unsigned char *) interpreter
;
1592 s
->size
= strlen (interpreter
) + 1;
1596 /* Set up .got offsets for local syms, and space for local dynamic
1598 for (ibfd
= info
->input_bfds
; ibfd
!= NULL
; ibfd
= ibfd
->link
.next
)
1600 bfd_signed_vma
*local_got
;
1601 bfd_signed_vma
*end_local_got
;
1602 char *local_tls_type
;
1603 bfd_size_type locsymcount
;
1604 Elf_Internal_Shdr
*symtab_hdr
;
1607 if (!is_loongarch_elf (ibfd
))
1610 for (s
= ibfd
->sections
; s
!= NULL
; s
= s
->next
)
1612 struct elf_dyn_relocs
*p
;
1614 for (p
= elf_section_data (s
)->local_dynrel
; p
!= NULL
; p
= p
->next
)
1616 p
->count
-= p
->pc_count
;
1617 if (!bfd_is_abs_section (p
->sec
)
1618 && bfd_is_abs_section (p
->sec
->output_section
))
1620 /* Input section has been discarded, either because
1621 it is a copy of a linkonce section or due to
1622 linker script /DISCARD/, so we'll be discarding
1625 else if (0 < p
->count
)
1627 srel
= elf_section_data (p
->sec
)->sreloc
;
1628 srel
->size
+= p
->count
* sizeof (ElfNN_External_Rela
);
1629 if ((p
->sec
->output_section
->flags
& SEC_READONLY
) != 0)
1630 info
->flags
|= DF_TEXTREL
;
1635 local_got
= elf_local_got_refcounts (ibfd
);
1639 symtab_hdr
= &elf_symtab_hdr (ibfd
);
1640 locsymcount
= symtab_hdr
->sh_info
;
1641 end_local_got
= local_got
+ locsymcount
;
1642 local_tls_type
= _bfd_loongarch_elf_local_got_tls_type (ibfd
);
1644 srel
= htab
->elf
.srelgot
;
1645 for (; local_got
< end_local_got
; ++local_got
, ++local_tls_type
)
1649 *local_got
= s
->size
;
1651 /* TLS gd use two got. */
1652 if (*local_tls_type
& GOT_TLS_GD
)
1653 s
->size
+= GOT_ENTRY_SIZE
* 2;
1655 /* Normal got, tls ie/ld use one got. */
1656 s
->size
+= GOT_ENTRY_SIZE
;
1658 if (bfd_link_executable (info
)
1659 && (*local_tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
)))
1663 srel
->size
+= sizeof (ElfNN_External_Rela
);
1667 *local_got
= MINUS_ONE
;
1671 /* Allocate global sym .plt and .got entries, and space for global
1672 sym dynamic relocs. */
1673 elf_link_hash_traverse (&htab
->elf
, allocate_dynrelocs
, info
);
1675 /* Allocate global ifunc sym .plt and .got entries, and space for global
1676 ifunc sym dynamic relocs. */
1677 elf_link_hash_traverse (&htab
->elf
, elfNN_allocate_ifunc_dynrelocs
, info
);
1679 /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1680 htab_traverse (htab
->loc_hash_table
,
1681 (void *) elfNN_allocate_local_ifunc_dynrelocs
, info
);
1683 /* Don't allocate .got.plt section if there are no PLT. */
1684 if (htab
->elf
.sgotplt
&& htab
->elf
.sgotplt
->size
== GOTPLT_HEADER_SIZE
1685 && (htab
->elf
.splt
== NULL
|| htab
->elf
.splt
->size
== 0))
1686 htab
->elf
.sgotplt
->size
= 0;
1688 /* The check_relocs and adjust_dynamic_symbol entry points have
1689 determined the sizes of the various dynamic sections. Allocate
1691 for (s
= dynobj
->sections
; s
!= NULL
; s
= s
->next
)
1693 if ((s
->flags
& SEC_LINKER_CREATED
) == 0)
1696 if (s
== htab
->elf
.splt
|| s
== htab
->elf
.iplt
|| s
== htab
->elf
.sgot
1697 || s
== htab
->elf
.sgotplt
|| s
== htab
->elf
.igotplt
1698 || s
== htab
->elf
.sdynbss
|| s
== htab
->elf
.sdynrelro
)
1700 /* Strip this section if we don't need it; see the
1703 else if (strncmp (s
->name
, ".rela", 5) == 0)
1707 /* We use the reloc_count field as a counter if we need
1708 to copy relocs into the output file. */
1714 /* It's not one of our sections. */
1720 /* If we don't need this section, strip it from the
1721 output file. This is mostly to handle .rela.bss and
1722 .rela.plt. We must create both sections in
1723 create_dynamic_sections, because they must be created
1724 before the linker maps input sections to output
1725 sections. The linker does that before
1726 adjust_dynamic_symbol is called, and it is that
1727 function which decides whether anything needs to go
1728 into these sections. */
1729 s
->flags
|= SEC_EXCLUDE
;
1733 if ((s
->flags
& SEC_HAS_CONTENTS
) == 0)
1736 /* Allocate memory for the section contents. Zero the memory
1737 for the benefit of .rela.plt, which has 4 unused entries
1738 at the beginning, and we don't want garbage. */
1739 s
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, s
->size
);
1740 if (s
->contents
== NULL
)
1744 if (elf_hash_table (info
)->dynamic_sections_created
)
1746 /* Add some entries to the .dynamic section. We fill in the
1747 values later, in loongarch_elf_finish_dynamic_sections, but we
1748 must add the entries now so that we get the correct size for
1749 the .dynamic section. The DT_DEBUG entry is filled in by the
1750 dynamic linker and used by the debugger. */
1751 #define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1753 if (bfd_link_executable (info
))
1755 if (!add_dynamic_entry (DT_DEBUG
, 0))
1759 if (htab
->elf
.srelplt
->size
!= 0)
1761 if (!add_dynamic_entry (DT_PLTGOT
, 0)
1762 || !add_dynamic_entry (DT_PLTRELSZ
, 0)
1763 || !add_dynamic_entry (DT_PLTREL
, DT_RELA
)
1764 || !add_dynamic_entry (DT_JMPREL
, 0))
1768 if (!add_dynamic_entry (DT_RELA
, 0)
1769 || !add_dynamic_entry (DT_RELASZ
, 0)
1770 || !add_dynamic_entry (DT_RELAENT
, sizeof (ElfNN_External_Rela
)))
1773 /* If any dynamic relocs apply to a read-only section,
1774 then we need a DT_TEXTREL entry. */
1775 if ((info
->flags
& DF_TEXTREL
) == 0)
1776 elf_link_hash_traverse (&htab
->elf
, maybe_set_textrel
, info
);
1778 if (info
->flags
& DF_TEXTREL
)
1780 if (!add_dynamic_entry (DT_TEXTREL
, 0))
1782 /* Clear the DF_TEXTREL flag. It will be set again if we
1783 write out an actual text relocation; we may not, because
1784 at this point we do not know whether e.g. any .eh_frame
1785 absolute relocations have been converted to PC-relative. */
1786 info
->flags
&= ~DF_TEXTREL
;
1789 #undef add_dynamic_entry
1794 #define LARCH_LD_STACK_DEPTH 16
1795 static int64_t larch_opc_stack
[LARCH_LD_STACK_DEPTH
];
1796 static size_t larch_stack_top
= 0;
1798 static bfd_reloc_status_type
1799 loongarch_push (int64_t val
)
1801 if (LARCH_LD_STACK_DEPTH
<= larch_stack_top
)
1802 return bfd_reloc_outofrange
;
1803 larch_opc_stack
[larch_stack_top
++] = val
;
1804 return bfd_reloc_ok
;
1807 static bfd_reloc_status_type
1808 loongarch_pop (int64_t *val
)
1810 if (larch_stack_top
== 0)
1811 return bfd_reloc_outofrange
;
1813 *val
= larch_opc_stack
[--larch_stack_top
];
1814 return bfd_reloc_ok
;
1817 static bfd_reloc_status_type
1818 loongarch_top (int64_t *val
)
1820 if (larch_stack_top
== 0)
1821 return bfd_reloc_outofrange
;
1823 *val
= larch_opc_stack
[larch_stack_top
- 1];
1824 return bfd_reloc_ok
;
1828 loongarch_elf_append_rela (bfd
*abfd
, asection
*s
, Elf_Internal_Rela
*rel
)
1830 BFD_ASSERT (s
&& s
->contents
);
1831 const struct elf_backend_data
*bed
;
1834 bed
= get_elf_backend_data (abfd
);
1835 if (!(s
->size
> s
->reloc_count
* bed
->s
->sizeof_rela
))
1836 BFD_ASSERT (s
->size
> s
->reloc_count
* bed
->s
->sizeof_rela
);
1837 loc
= s
->contents
+ (s
->reloc_count
++ * bed
->s
->sizeof_rela
);
1838 bed
->s
->swap_reloca_out (abfd
, rel
, loc
);
1841 /* Check rel->r_offset in range of contents. */
1842 static bfd_reloc_status_type
1843 loongarch_check_offset (const Elf_Internal_Rela
*rel
,
1844 const asection
*input_section
)
1846 if (0 == strcmp(input_section
->name
, ".text")
1847 && rel
->r_offset
> input_section
->size
)
1848 return bfd_reloc_overflow
;
1850 return bfd_reloc_ok
;
1853 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1855 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1856 if (ret == bfd_reloc_ok) \
1858 ret = loongarch_pop (&op1); \
1859 if (ret == bfd_reloc_ok) \
1860 ret = loongarch_push (op3); \
1865 static bfd_reloc_status_type
1866 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela
*rel
,
1867 const asection
*input_section ATTRIBUTE_UNUSED
,
1868 reloc_howto_type
*howto
, bfd
*input_bfd
,
1869 bfd_byte
*contents
, bfd_vma reloc_val
)
1871 int bits
= bfd_get_reloc_size (howto
) * 8;
1872 uint32_t insn
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1874 if (!loongarch_adjust_reloc_bitsfield(howto
, &reloc_val
))
1875 return bfd_reloc_overflow
;
1877 insn
= (insn
& (uint32_t)howto
->src_mask
)
1878 | ((insn
& (~(uint32_t)howto
->dst_mask
)) | reloc_val
);
1880 bfd_put (bits
, input_bfd
, insn
, contents
+ rel
->r_offset
);
1882 return bfd_reloc_ok
;
1885 static bfd_reloc_status_type
1886 perform_relocation (const Elf_Internal_Rela
*rel
, asection
*input_section
,
1887 reloc_howto_type
*howto
, bfd_vma value
,
1888 bfd
*input_bfd
, bfd_byte
*contents
)
1890 int64_t opr1
, opr2
, opr3
;
1891 bfd_reloc_status_type r
= bfd_reloc_ok
;
1892 int bits
= bfd_get_reloc_size (howto
) * 8;
1894 switch (ELFNN_R_TYPE (rel
->r_info
))
1896 case R_LARCH_SOP_PUSH_PCREL
:
1897 case R_LARCH_SOP_PUSH_ABSOLUTE
:
1898 case R_LARCH_SOP_PUSH_GPREL
:
1899 case R_LARCH_SOP_PUSH_TLS_TPREL
:
1900 case R_LARCH_SOP_PUSH_TLS_GOT
:
1901 case R_LARCH_SOP_PUSH_TLS_GD
:
1902 case R_LARCH_SOP_PUSH_PLT_PCREL
:
1903 r
= loongarch_push (value
);
1906 case R_LARCH_SOP_PUSH_DUP
:
1907 r
= loongarch_pop (&opr1
);
1908 if (r
== bfd_reloc_ok
)
1910 r
= loongarch_push (opr1
);
1911 if (r
== bfd_reloc_ok
)
1912 r
= loongarch_push (opr1
);
1916 case R_LARCH_SOP_ASSERT
:
1917 r
= loongarch_pop (&opr1
);
1918 if (r
!= bfd_reloc_ok
|| !opr1
)
1919 r
= bfd_reloc_notsupported
;
1922 case R_LARCH_SOP_NOT
:
1923 r
= loongarch_pop (&opr1
);
1924 if (r
== bfd_reloc_ok
)
1925 r
= loongarch_push (!opr1
);
1928 case R_LARCH_SOP_SUB
:
1929 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
- opr2
);
1932 case R_LARCH_SOP_SL
:
1933 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
<< opr2
);
1936 case R_LARCH_SOP_SR
:
1937 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
>> opr2
);
1940 case R_LARCH_SOP_AND
:
1941 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
& opr2
);
1944 case R_LARCH_SOP_ADD
:
1945 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
+ opr2
);
1948 case R_LARCH_SOP_IF_ELSE
:
1949 r
= loongarch_pop (&opr3
);
1950 if (r
== bfd_reloc_ok
)
1952 r
= loongarch_pop (&opr2
);
1953 if (r
== bfd_reloc_ok
)
1955 r
= loongarch_pop (&opr1
);
1956 if (r
== bfd_reloc_ok
)
1957 r
= loongarch_push (opr1
? opr2
: opr3
);
1962 case R_LARCH_SOP_POP_32_S_10_5
:
1963 case R_LARCH_SOP_POP_32_S_10_12
:
1964 case R_LARCH_SOP_POP_32_S_10_16
:
1965 case R_LARCH_SOP_POP_32_S_10_16_S2
:
1966 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2
:
1967 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2
:
1968 case R_LARCH_SOP_POP_32_S_5_20
:
1969 case R_LARCH_SOP_POP_32_U_10_12
:
1970 case R_LARCH_SOP_POP_32_U
:
1971 r
= loongarch_pop (&opr1
);
1972 if (r
!= bfd_reloc_ok
)
1974 r
= loongarch_check_offset (rel
, input_section
);
1975 if (r
!= bfd_reloc_ok
)
1978 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
1980 contents
, (bfd_vma
)opr1
);
1983 case R_LARCH_TLS_DTPREL32
:
1985 case R_LARCH_TLS_DTPREL64
:
1987 r
= loongarch_check_offset (rel
, input_section
);
1988 if (r
!= bfd_reloc_ok
)
1991 bfd_put (bits
, input_bfd
, value
, contents
+ rel
->r_offset
);
1999 r
= loongarch_check_offset (rel
, input_section
);
2000 if (r
!= bfd_reloc_ok
)
2003 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
2004 bfd_put (bits
, input_bfd
, opr1
+ value
, contents
+ rel
->r_offset
);
2012 r
= loongarch_check_offset (rel
, input_section
);
2013 if (r
!= bfd_reloc_ok
)
2016 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
2017 bfd_put (bits
, input_bfd
, opr1
- value
, contents
+ rel
->r_offset
);
2020 /* For eh_frame and debug info. */
2021 case R_LARCH_32_PCREL
:
2022 value
-= sec_addr (input_section
) + rel
->r_offset
;
2023 value
+= rel
->r_addend
;
2024 bfd_vma word
= bfd_get (howto
->bitsize
, input_bfd
,
2025 contents
+ rel
->r_offset
);
2026 word
= (word
& ~howto
->dst_mask
) | (value
& howto
->dst_mask
);
2027 bfd_put (howto
->bitsize
, input_bfd
, word
, contents
+ rel
->r_offset
);
2032 R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */
2036 case R_LARCH_ABS_HI20
:
2037 case R_LARCH_ABS_LO12
:
2038 case R_LARCH_ABS64_LO20
:
2039 case R_LARCH_ABS64_HI12
:
2040 case R_LARCH_PCALA_HI20
:
2041 case R_LARCH_PCALA_LO12
:
2042 case R_LARCH_PCALA64_LO20
:
2043 case R_LARCH_PCALA64_HI12
:
2044 case R_LARCH_GOT_PC_HI20
:
2045 case R_LARCH_GOT_PC_LO12
:
2046 case R_LARCH_GOT64_PC_LO20
:
2047 case R_LARCH_GOT64_PC_HI12
:
2048 case R_LARCH_GOT_HI20
:
2049 case R_LARCH_GOT_LO12
:
2050 case R_LARCH_GOT64_LO20
:
2051 case R_LARCH_GOT64_HI12
:
2052 case R_LARCH_TLS_LE_HI20
:
2053 case R_LARCH_TLS_LE_LO12
:
2054 case R_LARCH_TLS_LE64_LO20
:
2055 case R_LARCH_TLS_LE64_HI12
:
2056 case R_LARCH_TLS_IE_PC_HI20
:
2057 case R_LARCH_TLS_IE_PC_LO12
:
2058 case R_LARCH_TLS_IE64_PC_LO20
:
2059 case R_LARCH_TLS_IE64_PC_HI12
:
2060 case R_LARCH_TLS_IE_HI20
:
2061 case R_LARCH_TLS_IE_LO12
:
2062 case R_LARCH_TLS_IE64_LO20
:
2063 case R_LARCH_TLS_IE64_HI12
:
2064 case R_LARCH_TLS_LD_PC_HI20
:
2065 case R_LARCH_TLS_LD_HI20
:
2066 case R_LARCH_TLS_GD_PC_HI20
:
2067 case R_LARCH_TLS_GD_HI20
:
2068 r
= loongarch_check_offset (rel
, input_section
);
2069 if (r
!= bfd_reloc_ok
)
2072 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
2081 r
= bfd_reloc_notsupported
;
2086 #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
2094 Elf_Internal_Sym
*sym
;
2095 struct elf_link_hash_entry
*h
;
2098 } larch_reloc_queue
[LARCH_RECENT_RELOC_QUEUE_LENGTH
];
2099 static size_t larch_reloc_queue_head
= 0;
2100 static size_t larch_reloc_queue_tail
= 0;
2103 loongarch_sym_name (bfd
*input_bfd
, struct elf_link_hash_entry
*h
,
2104 Elf_Internal_Sym
*sym
)
2106 const char *ret
= NULL
;
2108 ret
= bfd_elf_string_from_elf_section (input_bfd
,
2109 elf_symtab_hdr (input_bfd
).sh_link
,
2112 ret
= h
->root
.root
.string
;
2114 if (ret
== NULL
|| *ret
== '\0')
2120 loongarch_record_one_reloc (bfd
*abfd
, asection
*section
, int r_type
,
2121 bfd_vma r_offset
, Elf_Internal_Sym
*sym
,
2122 struct elf_link_hash_entry
*h
, bfd_vma addend
)
2124 if ((larch_reloc_queue_head
== 0
2125 && larch_reloc_queue_tail
== LARCH_RECENT_RELOC_QUEUE_LENGTH
- 1)
2126 || larch_reloc_queue_head
== larch_reloc_queue_tail
+ 1)
2127 larch_reloc_queue_head
=
2128 (larch_reloc_queue_head
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
2129 larch_reloc_queue
[larch_reloc_queue_tail
].bfd
= abfd
;
2130 larch_reloc_queue
[larch_reloc_queue_tail
].section
= section
;
2131 larch_reloc_queue
[larch_reloc_queue_tail
].r_offset
= r_offset
;
2132 larch_reloc_queue
[larch_reloc_queue_tail
].r_type
= r_type
;
2133 larch_reloc_queue
[larch_reloc_queue_tail
].sym
= sym
;
2134 larch_reloc_queue
[larch_reloc_queue_tail
].h
= h
;
2135 larch_reloc_queue
[larch_reloc_queue_tail
].addend
= addend
;
2136 loongarch_top (&larch_reloc_queue
[larch_reloc_queue_tail
].top_then
);
2137 larch_reloc_queue_tail
=
2138 (larch_reloc_queue_tail
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
2142 loongarch_dump_reloc_record (void (*p
) (const char *fmt
, ...))
2144 size_t i
= larch_reloc_queue_head
;
2146 asection
*section
= NULL
;
2147 bfd_vma r_offset
= 0;
2149 p ("Dump relocate record:\n");
2150 p ("stack top\t\trelocation name\t\tsymbol");
2151 while (i
!= larch_reloc_queue_tail
)
2153 if (a_bfd
!= larch_reloc_queue
[i
].bfd
2154 || section
!= larch_reloc_queue
[i
].section
2155 || r_offset
!= larch_reloc_queue
[i
].r_offset
)
2157 a_bfd
= larch_reloc_queue
[i
].bfd
;
2158 section
= larch_reloc_queue
[i
].section
;
2159 r_offset
= larch_reloc_queue
[i
].r_offset
;
2160 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue
[i
].bfd
,
2161 larch_reloc_queue
[i
].section
, larch_reloc_queue
[i
].r_offset
);
2165 inited
= 1, p ("...\n");
2167 reloc_howto_type
*howto
=
2168 loongarch_elf_rtype_to_howto (larch_reloc_queue
[i
].bfd
,
2169 larch_reloc_queue
[i
].r_type
);
2170 p ("0x%V %s\t`%s'", (bfd_vma
) larch_reloc_queue
[i
].top_then
,
2171 howto
? howto
->name
: "<unknown reloc>",
2172 loongarch_sym_name (larch_reloc_queue
[i
].bfd
, larch_reloc_queue
[i
].h
,
2173 larch_reloc_queue
[i
].sym
));
2175 long addend
= larch_reloc_queue
[i
].addend
;
2177 p (" - %ld", -addend
);
2178 else if (0 < addend
)
2179 p (" + %ld(0x%v)", addend
, larch_reloc_queue
[i
].addend
);
2182 i
= (i
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
2185 "-- Record dump end --\n\n");
2189 loongarch_reloc_is_fatal (struct bfd_link_info
*info
,
2191 asection
*input_section
,
2192 Elf_Internal_Rela
*rel
,
2193 reloc_howto_type
*howto
,
2194 bfd_reloc_status_type rtype
,
2202 /* 'dangerous' means we do it but can't promise it's ok
2203 'unsupport' means out of ability of relocation type
2204 'undefined' means we can't deal with the undefined symbol. */
2205 case bfd_reloc_undefined
:
2206 info
->callbacks
->undefined_symbol (info
, name
, input_bfd
, input_section
,
2207 rel
->r_offset
, true);
2208 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2209 input_bfd
, input_section
, rel
->r_offset
,
2211 is_undefweak
? "[undefweak] " : "", name
, msg
);
2213 case bfd_reloc_dangerous
:
2214 info
->callbacks
->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
2215 input_bfd
, input_section
, rel
->r_offset
,
2217 is_undefweak
? "[undefweak] " : "", name
, msg
);
2220 case bfd_reloc_notsupported
:
2221 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2222 input_bfd
, input_section
, rel
->r_offset
,
2224 is_undefweak
? "[undefweak] " : "", name
, msg
);
2232 #define RELOCATE_CALC_PC32_HI20(relocation, pc) \
2234 bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2235 pc = pc & (~(bfd_vma)0xfff); \
2238 relocation += 0x1000; \
2240 relocation &= ~(bfd_vma)0xfff; \
2244 #define RELOCATE_CALC_PC64_HI32(relocation, pc) \
2246 bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2249 relocation -= 0x100000000; \
2251 relocation -= (pc & ~(bfd_vma)0xffffffff); \
2255 loongarch_elf_relocate_section (bfd
*output_bfd
, struct bfd_link_info
*info
,
2256 bfd
*input_bfd
, asection
*input_section
,
2257 bfd_byte
*contents
, Elf_Internal_Rela
*relocs
,
2258 Elf_Internal_Sym
*local_syms
,
2259 asection
**local_sections
)
2261 Elf_Internal_Rela
*rel
;
2262 Elf_Internal_Rela
*relend
;
2264 asection
*sreloc
= elf_section_data (input_section
)->sreloc
;
2265 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
2266 Elf_Internal_Shdr
*symtab_hdr
= &elf_symtab_hdr (input_bfd
);
2267 struct elf_link_hash_entry
**sym_hashes
= elf_sym_hashes (input_bfd
);
2268 bfd_vma
*local_got_offsets
= elf_local_got_offsets (input_bfd
);
2269 bool is_pic
= bfd_link_pic (info
);
2270 bool is_dyn
= elf_hash_table (info
)->dynamic_sections_created
;
2271 asection
*plt
= htab
->elf
.splt
? htab
->elf
.splt
: htab
->elf
.iplt
;
2272 asection
*got
= htab
->elf
.sgot
;
2274 relend
= relocs
+ input_section
->reloc_count
;
2275 for (rel
= relocs
; rel
< relend
; rel
++)
2277 int r_type
= ELFNN_R_TYPE (rel
->r_info
);
2278 unsigned long r_symndx
= ELFNN_R_SYM (rel
->r_info
);
2279 bfd_vma pc
= sec_addr (input_section
) + rel
->r_offset
;
2280 reloc_howto_type
*howto
= NULL
;
2281 asection
*sec
= NULL
;
2282 Elf_Internal_Sym
*sym
= NULL
;
2283 struct elf_link_hash_entry
*h
= NULL
;
2285 bfd_reloc_status_type r
= bfd_reloc_ok
;
2286 bool is_ie
, is_undefweak
, unresolved_reloc
, defined_local
;
2287 bool resolved_local
, resolved_dynly
, resolved_to_const
;
2289 bfd_vma relocation
, off
, ie_off
;
2292 howto
= loongarch_elf_rtype_to_howto (input_bfd
, r_type
);
2293 if (howto
== NULL
|| r_type
== R_LARCH_GNU_VTINHERIT
2294 || r_type
== R_LARCH_GNU_VTENTRY
)
2297 /* This is a final link. */
2298 if (r_symndx
< symtab_hdr
->sh_info
)
2300 is_undefweak
= false;
2301 unresolved_reloc
= false;
2302 sym
= local_syms
+ r_symndx
;
2303 sec
= local_sections
[r_symndx
];
2304 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
2306 /* Relocate against local STT_GNU_IFUNC symbol. */
2307 if (!bfd_link_relocatable (info
)
2308 && ELF_ST_TYPE (sym
->st_info
) == STT_GNU_IFUNC
)
2310 h
= elfNN_loongarch_get_local_sym_hash (htab
, input_bfd
, rel
,
2315 /* Set STT_GNU_IFUNC symbol value. */
2316 h
->root
.u
.def
.value
= sym
->st_value
;
2317 h
->root
.u
.def
.section
= sec
;
2319 defined_local
= true;
2320 resolved_local
= true;
2321 resolved_dynly
= false;
2322 resolved_to_const
= false;
2324 /* Calc in funtion elf_link_input_bfd,
2325 * if #define elf_backend_rela_normal to 1. */
2326 if (bfd_link_relocatable (info
)
2327 && ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
2332 bool warned
, ignored
;
2334 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
2335 r_symndx
, symtab_hdr
, sym_hashes
,
2337 unresolved_reloc
, warned
, ignored
);
2338 /* Here means symbol isn't local symbol only and 'h != NULL'. */
2340 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
2341 symbol. And 'dynamic_undefined_weak' specify what to do when
2342 meeting undefweak. */
2344 if ((is_undefweak
= h
->root
.type
== bfd_link_hash_undefweak
))
2346 defined_local
= false;
2347 resolved_local
= false;
2348 resolved_to_const
= (!is_dyn
|| h
->dynindx
== -1
2349 || UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
));
2350 resolved_dynly
= !resolved_local
&& !resolved_to_const
;
2354 /* Symbol undefined offen means failed already. I don't know why
2355 'warned' here but I guess it want to continue relocating as if
2356 no error occures to find other errors as more as possible. */
2358 /* To avoid generating warning messages about truncated
2359 relocations, set the relocation's address to be the same as
2360 the start of this section. */
2361 relocation
= (input_section
->output_section
2362 ? input_section
->output_section
->vma
2365 defined_local
= relocation
!= 0;
2366 resolved_local
= defined_local
;
2367 resolved_to_const
= !resolved_local
;
2368 resolved_dynly
= false;
2372 defined_local
= !unresolved_reloc
&& !ignored
;
2374 defined_local
&& SYMBOL_REFERENCES_LOCAL (info
, h
);
2375 resolved_dynly
= !resolved_local
;
2376 resolved_to_const
= !resolved_local
&& !resolved_dynly
;
2380 name
= loongarch_sym_name (input_bfd
, h
, sym
);
2382 if (sec
!= NULL
&& discarded_section (sec
))
2383 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
, rel
,
2384 1, relend
, howto
, 0, contents
);
2386 if (bfd_link_relocatable (info
))
2389 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2390 from removed linkonce sections, or sections discarded by a linker
2391 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2392 if (r_symndx
== STN_UNDEF
|| bfd_is_abs_section (sec
))
2394 defined_local
= false;
2395 resolved_local
= false;
2396 resolved_dynly
= false;
2397 resolved_to_const
= true;
2400 /* The ifunc reference generate plt. */
2401 if (h
&& h
->type
== STT_GNU_IFUNC
&& h
->plt
.offset
!= MINUS_ONE
)
2403 defined_local
= true;
2404 resolved_local
= true;
2405 resolved_dynly
= false;
2406 resolved_to_const
= false;
2407 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2410 unresolved_reloc
= resolved_dynly
;
2412 BFD_ASSERT (resolved_local
+ resolved_dynly
+ resolved_to_const
== 1);
2414 /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));. */
2416 BFD_ASSERT (!resolved_local
|| defined_local
);
2421 case R_LARCH_MARK_PCREL
:
2422 case R_LARCH_MARK_LA
:
2424 r
= bfd_reloc_continue
;
2425 unresolved_reloc
= false;
2430 if (resolved_dynly
|| (is_pic
&& resolved_local
))
2432 Elf_Internal_Rela outrel
;
2434 /* When generating a shared object, these relocations are copied
2435 into the output file to be resolved at run time. */
2437 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2441 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2442 && (input_section
->flags
& SEC_ALLOC
));
2444 outrel
.r_offset
+= sec_addr (input_section
);
2446 /* A pointer point to a ifunc symbol. */
2447 if (h
&& h
->type
== STT_GNU_IFUNC
)
2449 if (h
->dynindx
== -1)
2451 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
2452 outrel
.r_addend
= (h
->root
.u
.def
.value
2453 + h
->root
.u
.def
.section
->output_section
->vma
2454 + h
->root
.u
.def
.section
->output_offset
);
2458 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
2459 outrel
.r_addend
= 0;
2462 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2465 if (htab
->elf
.splt
!= NULL
)
2466 sreloc
= htab
->elf
.srelgot
;
2468 sreloc
= htab
->elf
.irelplt
;
2473 if (bfd_link_pic (info
))
2474 sreloc
= htab
->elf
.irelifunc
;
2475 else if (htab
->elf
.splt
!= NULL
)
2476 sreloc
= htab
->elf
.srelgot
;
2478 sreloc
= htab
->elf
.irelplt
;
2481 else if (resolved_dynly
)
2483 if (h
->dynindx
== -1)
2485 if (h
->root
.type
== bfd_link_hash_undefined
)
2486 (*info
->callbacks
->undefined_symbol
)
2487 (info
, name
, input_bfd
, input_section
,
2488 rel
->r_offset
, true);
2490 outrel
.r_info
= ELFNN_R_INFO (0, r_type
);
2493 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2495 outrel
.r_addend
= rel
->r_addend
;
2499 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2500 outrel
.r_addend
= relocation
+ rel
->r_addend
;
2503 /* No alloc space of func allocate_dynrelocs. */
2504 if (unresolved_reloc
2505 && !(h
&& (h
->is_weakalias
|| !h
->dyn_relocs
)))
2506 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2509 relocation
+= rel
->r_addend
;
2523 fatal
= (loongarch_reloc_is_fatal
2524 (info
, input_bfd
, input_section
, rel
, howto
,
2525 bfd_reloc_undefined
, is_undefweak
, name
,
2526 "Can't be resolved dynamically. "
2527 "If this procedure is hand-written assembly,\n"
2528 "there must be something like '.dword sym1 - sym2' "
2529 "to generate these relocs\n"
2530 "and we can't get known link-time address of "
2533 relocation
+= rel
->r_addend
;
2536 case R_LARCH_TLS_DTPREL32
:
2537 case R_LARCH_TLS_DTPREL64
:
2540 Elf_Internal_Rela outrel
;
2542 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2545 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2546 && (input_section
->flags
& SEC_ALLOC
));
2547 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2548 outrel
.r_offset
+= sec_addr (input_section
);
2549 outrel
.r_addend
= rel
->r_addend
;
2550 if (unresolved_reloc
)
2551 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2555 if (resolved_to_const
)
2556 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
, input_section
,
2558 bfd_reloc_notsupported
,
2563 if (!elf_hash_table (info
)->tls_sec
)
2565 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
,
2566 input_section
, rel
, howto
, bfd_reloc_notsupported
,
2567 is_undefweak
, name
, "TLS section not be created");
2570 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
2574 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
,
2575 input_section
, rel
, howto
, bfd_reloc_undefined
,
2577 "TLS LE just can be resolved local only.");
2582 case R_LARCH_SOP_PUSH_TLS_TPREL
:
2585 if (!elf_hash_table (info
)->tls_sec
)
2586 fatal
= (loongarch_reloc_is_fatal
2587 (info
, input_bfd
, input_section
, rel
, howto
,
2588 bfd_reloc_notsupported
, is_undefweak
, name
,
2589 "TLS section not be created"));
2591 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
2594 fatal
= (loongarch_reloc_is_fatal
2595 (info
, input_bfd
, input_section
, rel
, howto
,
2596 bfd_reloc_undefined
, is_undefweak
, name
,
2597 "TLS LE just can be resolved local only."));
2600 case R_LARCH_SOP_PUSH_ABSOLUTE
:
2604 fatal
= (loongarch_reloc_is_fatal
2605 (info
, input_bfd
, input_section
, rel
, howto
,
2606 bfd_reloc_dangerous
, is_undefweak
, name
,
2607 "Someone require us to resolve undefweak "
2608 "symbol dynamically. \n"
2609 "But this reloc can't be done. "
2610 "I think I can't throw error "
2612 "so I resolved it to 0. "
2613 "I suggest to re-compile with '-fpic'."));
2616 unresolved_reloc
= false;
2620 if (resolved_to_const
)
2622 relocation
+= rel
->r_addend
;
2628 fatal
= (loongarch_reloc_is_fatal
2629 (info
, input_bfd
, input_section
, rel
, howto
,
2630 bfd_reloc_notsupported
, is_undefweak
, name
,
2631 "Under PIC we don't know load address. Re-compile "
2638 if (!(plt
&& h
&& h
->plt
.offset
!= MINUS_ONE
))
2640 fatal
= (loongarch_reloc_is_fatal
2641 (info
, input_bfd
, input_section
, rel
, howto
,
2642 bfd_reloc_undefined
, is_undefweak
, name
,
2643 "Can't be resolved dynamically. Try to re-compile "
2648 if (rel
->r_addend
!= 0)
2650 fatal
= (loongarch_reloc_is_fatal
2651 (info
, input_bfd
, input_section
, rel
, howto
,
2652 bfd_reloc_notsupported
, is_undefweak
, name
,
2653 "Shouldn't be with r_addend."));
2657 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2658 unresolved_reloc
= false;
2664 relocation
+= rel
->r_addend
;
2670 case R_LARCH_SOP_PUSH_PCREL
:
2671 case R_LARCH_SOP_PUSH_PLT_PCREL
:
2672 unresolved_reloc
= false;
2680 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
2683 fatal
= (loongarch_reloc_is_fatal
2684 (info
, input_bfd
, input_section
, rel
, howto
,
2685 bfd_reloc_dangerous
, is_undefweak
, name
,
2686 "Undefweak need to be resolved dynamically, "
2687 "but PLT stub doesn't represent."));
2692 if (!(defined_local
|| (h
&& h
->plt
.offset
!= MINUS_ONE
)))
2694 fatal
= (loongarch_reloc_is_fatal
2695 (info
, input_bfd
, input_section
, rel
, howto
,
2696 bfd_reloc_undefined
, is_undefweak
, name
,
2697 "PLT stub does not represent and "
2698 "symbol not defined."));
2704 else /* if (resolved_dynly) */
2706 if (!(h
&& h
->plt
.offset
!= MINUS_ONE
))
2707 fatal
= (loongarch_reloc_is_fatal
2708 (info
, input_bfd
, input_section
, rel
, howto
,
2709 bfd_reloc_dangerous
, is_undefweak
, name
,
2710 "Internal: PLT stub doesn't represent. "
2711 "Resolve it with pcrel"));
2718 if ((i
& 1) == 0 && defined_local
)
2721 relocation
+= rel
->r_addend
;
2725 if ((i
& 1) && h
&& h
->plt
.offset
!= MINUS_ONE
)
2727 if (rel
->r_addend
!= 0)
2729 fatal
= (loongarch_reloc_is_fatal
2730 (info
, input_bfd
, input_section
, rel
, howto
,
2731 bfd_reloc_notsupported
, is_undefweak
, name
,
2732 "PLT shouldn't be with r_addend."));
2735 relocation
= sec_addr (plt
) + h
->plt
.offset
- pc
;
2741 case R_LARCH_SOP_PUSH_GPREL
:
2742 unresolved_reloc
= false;
2744 if (rel
->r_addend
!= 0)
2746 fatal
= (loongarch_reloc_is_fatal
2747 (info
, input_bfd
, input_section
, rel
, howto
,
2748 bfd_reloc_notsupported
, is_undefweak
, name
,
2749 "Shouldn't be with r_addend."));
2755 off
= h
->got
.offset
& (~1);
2757 if (h
->got
.offset
== MINUS_ONE
&& h
->type
!= STT_GNU_IFUNC
)
2759 fatal
= (loongarch_reloc_is_fatal
2760 (info
, input_bfd
, input_section
, rel
, howto
,
2761 bfd_reloc_notsupported
, is_undefweak
, name
,
2762 "Internal: GOT entry doesn't represent."));
2766 /* Hidden symbol not has .got entry, only .got.plt entry
2767 so gprel is (plt - got). */
2768 if (h
->got
.offset
== MINUS_ONE
&& h
->type
== STT_GNU_IFUNC
)
2770 if (h
->plt
.offset
== (bfd_vma
) -1)
2775 bfd_vma plt_index
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
2776 off
= plt_index
* GOT_ENTRY_SIZE
;
2778 if (htab
->elf
.splt
!= NULL
)
2780 /* Section .plt header is 2 times of plt entry. */
2781 off
= sec_addr (htab
->elf
.sgotplt
) + off
2782 - sec_addr (htab
->elf
.sgot
);
2786 /* Section iplt not has plt header. */
2787 off
= sec_addr (htab
->elf
.igotplt
) + off
2788 - sec_addr (htab
->elf
.sgot
);
2792 if ((h
->got
.offset
& 1) == 0)
2794 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn
,
2795 bfd_link_pic (info
), h
)
2796 && ((bfd_link_pic (info
)
2797 && SYMBOL_REFERENCES_LOCAL (info
, h
))))
2799 /* This is actually a static link, or it is a
2800 -Bsymbolic link and the symbol is defined
2801 locally, or the symbol was forced to be local
2802 because of a version file. We must initialize
2803 this entry in the global offset table. Since the
2804 offset must always be a multiple of the word size,
2805 we use the least significant bit to record whether
2806 we have initialized it already.
2808 When doing a dynamic link, we create a rela.got
2809 relocation entry to initialize the value. This
2810 is done in the finish_dynamic_symbol routine. */
2814 fatal
= (loongarch_reloc_is_fatal
2815 (info
, input_bfd
, input_section
, rel
, howto
,
2816 bfd_reloc_dangerous
, is_undefweak
, name
,
2817 "Internal: here shouldn't dynamic."));
2820 if (!(defined_local
|| resolved_to_const
))
2822 fatal
= (loongarch_reloc_is_fatal
2823 (info
, input_bfd
, input_section
, rel
, howto
,
2824 bfd_reloc_undefined
, is_undefweak
, name
,
2830 Elf_Internal_Rela outrel
;
2831 /* We need to generate a R_LARCH_RELATIVE reloc
2832 for the dynamic linker. */
2833 s
= htab
->elf
.srelgot
;
2836 fatal
= loongarch_reloc_is_fatal
2838 input_section
, rel
, howto
,
2839 bfd_reloc_notsupported
, is_undefweak
, name
,
2840 "Internal: '.rel.got' not represent");
2844 outrel
.r_offset
= sec_addr (got
) + off
;
2845 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2846 outrel
.r_addend
= relocation
; /* Link-time addr. */
2847 loongarch_elf_append_rela (output_bfd
, s
, &outrel
);
2849 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2855 if (!local_got_offsets
)
2857 fatal
= (loongarch_reloc_is_fatal
2858 (info
, input_bfd
, input_section
, rel
, howto
,
2859 bfd_reloc_notsupported
, is_undefweak
, name
,
2860 "Internal: local got offsets not reporesent."));
2864 off
= local_got_offsets
[r_symndx
] & (~1);
2866 if (local_got_offsets
[r_symndx
] == MINUS_ONE
)
2868 fatal
= (loongarch_reloc_is_fatal
2869 (info
, input_bfd
, input_section
, rel
, howto
,
2870 bfd_reloc_notsupported
, is_undefweak
, name
,
2871 "Internal: GOT entry doesn't represent."));
2875 /* The offset must always be a multiple of the word size.
2876 So, we can use the least significant bit to record
2877 whether we have already processed this entry. */
2878 if (local_got_offsets
[r_symndx
] == 0)
2883 Elf_Internal_Rela outrel
;
2884 /* We need to generate a R_LARCH_RELATIVE reloc
2885 for the dynamic linker. */
2886 s
= htab
->elf
.srelgot
;
2889 fatal
= (loongarch_reloc_is_fatal
2890 (info
, input_bfd
, input_section
, rel
, howto
,
2891 bfd_reloc_notsupported
, is_undefweak
, name
,
2892 "Internal: '.rel.got' not represent"));
2896 outrel
.r_offset
= sec_addr (got
) + off
;
2897 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2898 outrel
.r_addend
= relocation
; /* Link-time addr. */
2899 loongarch_elf_append_rela (output_bfd
, s
, &outrel
);
2902 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2903 local_got_offsets
[r_symndx
] |= 1;
2910 case R_LARCH_SOP_PUSH_TLS_GOT
:
2911 case R_LARCH_SOP_PUSH_TLS_GD
:
2913 unresolved_reloc
= false;
2914 if (r_type
== R_LARCH_SOP_PUSH_TLS_GOT
)
2917 bfd_vma got_off
= 0;
2920 got_off
= h
->got
.offset
;
2925 got_off
= local_got_offsets
[r_symndx
];
2926 local_got_offsets
[r_symndx
] |= 1;
2929 BFD_ASSERT (got_off
!= MINUS_ONE
);
2932 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
2933 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
2934 ie_off
= 2 * GOT_ENTRY_SIZE
;
2936 if ((got_off
& 1) == 0)
2938 Elf_Internal_Rela rela
;
2939 asection
*srel
= htab
->elf
.srelgot
;
2940 bfd_vma tls_block_off
= 0;
2942 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2944 BFD_ASSERT (elf_hash_table (info
)->tls_sec
);
2945 tls_block_off
= relocation
2946 - elf_hash_table (info
)->tls_sec
->vma
;
2949 if (tls_type
& GOT_TLS_GD
)
2951 rela
.r_offset
= sec_addr (got
) + got_off
;
2953 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2955 /* Local sym, used in exec, set module id 1. */
2956 if (bfd_link_executable (info
))
2957 bfd_put_NN (output_bfd
, 1, got
->contents
+ got_off
);
2960 rela
.r_info
= ELFNN_R_INFO (0,
2961 R_LARCH_TLS_DTPMODNN
);
2962 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2965 bfd_put_NN (output_bfd
, tls_block_off
,
2966 got
->contents
+ got_off
+ GOT_ENTRY_SIZE
);
2968 /* Dynamic resolved. */
2971 /* Dynamic relocate module id. */
2972 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
2973 R_LARCH_TLS_DTPMODNN
);
2974 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2976 /* Dynamic relocate offset of block. */
2977 rela
.r_offset
+= GOT_ENTRY_SIZE
;
2978 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
2979 R_LARCH_TLS_DTPRELNN
);
2980 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2983 if (tls_type
& GOT_TLS_IE
)
2985 rela
.r_offset
= sec_addr (got
) + got_off
+ ie_off
;
2986 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2988 /* Local sym, used in exec, set module id 1. */
2989 if (!bfd_link_executable (info
))
2991 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN
);
2992 rela
.r_addend
= tls_block_off
;
2993 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2996 bfd_put_NN (output_bfd
, tls_block_off
,
2997 got
->contents
+ got_off
+ ie_off
);
2999 /* Dynamic resolved. */
3002 /* Dynamic relocate offset of block. */
3003 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3004 R_LARCH_TLS_TPRELNN
);
3006 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
3011 relocation
= (got_off
& (~(bfd_vma
)1)) + (is_ie
? ie_off
: 0);
3015 /* New reloc types. */
3019 unresolved_reloc
= false;
3028 relocation
+= rel
->r_addend
;
3030 else if (resolved_dynly
)
3033 && (h
->plt
.offset
!= MINUS_ONE
3034 || ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
)
3035 && rel
->r_addend
== 0);
3036 if (h
&& h
->plt
.offset
== MINUS_ONE
3037 && ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
)
3040 relocation
+= rel
->r_addend
;
3043 relocation
= sec_addr (plt
) + h
->plt
.offset
- pc
;
3048 case R_LARCH_ABS_HI20
:
3049 case R_LARCH_ABS_LO12
:
3050 case R_LARCH_ABS64_LO20
:
3051 case R_LARCH_ABS64_HI12
:
3052 BFD_ASSERT (!is_pic
);
3056 BFD_ASSERT (resolved_dynly
);
3060 else if (resolved_to_const
|| resolved_local
)
3062 relocation
+= rel
->r_addend
;
3064 else if (resolved_dynly
)
3066 unresolved_reloc
= false;
3067 BFD_ASSERT ((plt
&& h
&& h
->plt
.offset
!= MINUS_ONE
)
3068 && rel
->r_addend
== 0);
3069 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3074 case R_LARCH_PCALA_HI20
:
3075 unresolved_reloc
= false;
3076 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
3077 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3079 relocation
+= rel
->r_addend
;
3081 RELOCATE_CALC_PC32_HI20 (relocation
, pc
);
3085 case R_LARCH_PCALA_LO12
:
3086 /* Not support if sym_addr in 2k page edge.
3087 pcalau12i pc_hi20 (sym_addr)
3088 ld.w/d pc_lo12 (sym_addr)
3089 ld.w/d pc_lo12 (sym_addr + x)
3091 can not calc correct address
3092 if sym_addr < 0x800 && sym_addr + x >= 0x800. */
3094 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
3095 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3097 relocation
+= rel
->r_addend
;
3099 relocation
&= 0xfff;
3100 /* Signed extend. */
3101 relocation
= (relocation
^ 0x800) - 0x800;
3103 /* For 2G jump, generate pcalau12i, jirl. */
3104 /* If use jirl, turns to R_LARCH_B16. */
3105 uint32_t insn
= bfd_get (32, input_bfd
, contents
+ rel
->r_offset
);
3106 if ((insn
& 0x4c000000) == 0x4c000000)
3108 rel
->r_info
= ELFNN_R_INFO (r_symndx
, R_LARCH_B16
);
3109 howto
= loongarch_elf_rtype_to_howto (input_bfd
, R_LARCH_B16
);
3113 case R_LARCH_PCALA64_LO20
:
3114 case R_LARCH_PCALA64_HI12
:
3115 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
3116 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3118 relocation
+= rel
->r_addend
;
3120 RELOCATE_CALC_PC64_HI32 (relocation
, pc
);
3124 case R_LARCH_GOT_PC_HI20
:
3125 case R_LARCH_GOT_HI20
:
3126 /* Calc got offset. */
3128 unresolved_reloc
= false;
3129 BFD_ASSERT (rel
->r_addend
== 0);
3131 bfd_vma got_off
= 0;
3134 /* GOT ref or ifunc. */
3135 BFD_ASSERT (h
->got
.offset
!= MINUS_ONE
3136 || h
->type
== STT_GNU_IFUNC
);
3138 got_off
= h
->got
.offset
& (~(bfd_vma
)1);
3139 /* Hidden symbol not has got entry,
3140 * only got.plt entry so it is (plt - got). */
3141 if (h
->got
.offset
== MINUS_ONE
&& h
->type
== STT_GNU_IFUNC
)
3144 if (htab
->elf
.splt
!= NULL
)
3146 idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
)
3148 got_off
= sec_addr (htab
->elf
.sgotplt
)
3149 + GOTPLT_HEADER_SIZE
3150 + (idx
* GOT_ENTRY_SIZE
)
3151 - sec_addr (htab
->elf
.sgot
);
3155 idx
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
3156 got_off
= sec_addr (htab
->elf
.sgotplt
)
3157 + (idx
* GOT_ENTRY_SIZE
)
3158 - sec_addr (htab
->elf
.sgot
);
3162 if ((h
->got
.offset
& 1) == 0)
3164 /* We need to generate a R_LARCH_RELATIVE reloc once
3165 * in loongarch_elf_finish_dynamic_symbol or now,
3166 * call finish_dyn && nopic
3167 * or !call finish_dyn && pic. */
3168 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn
,
3169 bfd_link_pic (info
),
3171 && bfd_link_pic (info
)
3172 && SYMBOL_REFERENCES_LOCAL (info
, h
))
3174 Elf_Internal_Rela rela
;
3175 rela
.r_offset
= sec_addr (got
) + got_off
;
3176 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
3177 rela
.r_addend
= relocation
;
3178 loongarch_elf_append_rela (output_bfd
,
3179 htab
->elf
.srelgot
, &rela
);
3182 bfd_put_NN (output_bfd
, relocation
,
3183 got
->contents
+ got_off
);
3188 BFD_ASSERT (local_got_offsets
3189 && local_got_offsets
[r_symndx
] != MINUS_ONE
);
3191 got_off
= local_got_offsets
[r_symndx
] & (~(bfd_vma
)1);
3192 if ((local_got_offsets
[r_symndx
] & 1) == 0)
3194 if (bfd_link_pic (info
))
3196 Elf_Internal_Rela rela
;
3197 rela
.r_offset
= sec_addr (got
) + got_off
;
3198 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
3199 rela
.r_addend
= relocation
;
3200 loongarch_elf_append_rela (output_bfd
,
3201 htab
->elf
.srelgot
, &rela
);
3203 local_got_offsets
[r_symndx
] |= 1;
3205 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ got_off
);
3208 relocation
= got_off
+ sec_addr (got
);
3211 if (r_type
== R_LARCH_GOT_PC_HI20
)
3212 RELOCATE_CALC_PC32_HI20 (relocation
, pc
);
3216 case R_LARCH_GOT_PC_LO12
:
3217 case R_LARCH_GOT64_PC_LO20
:
3218 case R_LARCH_GOT64_PC_HI12
:
3219 case R_LARCH_GOT_LO12
:
3220 case R_LARCH_GOT64_LO20
:
3221 case R_LARCH_GOT64_HI12
:
3223 unresolved_reloc
= false;
3226 got_off
= h
->got
.offset
& (~(bfd_vma
)1);
3228 got_off
= local_got_offsets
[r_symndx
] & (~(bfd_vma
)1);
3230 if (h
&& h
->got
.offset
== MINUS_ONE
&& h
->type
== STT_GNU_IFUNC
)
3233 if (htab
->elf
.splt
!= NULL
)
3234 idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
) / PLT_ENTRY_SIZE
;
3236 idx
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
3238 got_off
= sec_addr (htab
->elf
.sgotplt
)
3239 + GOTPLT_HEADER_SIZE
3240 + (idx
* GOT_ENTRY_SIZE
)
3241 - sec_addr (htab
->elf
.sgot
);
3243 relocation
= got_off
+ sec_addr (got
);
3246 if (r_type
== R_LARCH_GOT_PC_LO12
)
3247 relocation
&= (bfd_vma
)0xfff;
3248 else if (r_type
== R_LARCH_GOT64_PC_LO20
3249 || r_type
== R_LARCH_GOT64_PC_HI12
)
3250 RELOCATE_CALC_PC64_HI32 (relocation
, pc
);
3254 case R_LARCH_TLS_LE_HI20
:
3255 case R_LARCH_TLS_LE_LO12
:
3256 case R_LARCH_TLS_LE64_LO20
:
3257 case R_LARCH_TLS_LE64_HI12
:
3258 BFD_ASSERT (resolved_local
&& elf_hash_table (info
)->tls_sec
);
3260 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
3263 /* TLS IE LD/GD process separately is troublesome.
3264 When a symbol is both ie and LD/GD, h->got.off |= 1
3265 make only one type be relocated. We must use
3266 h->got.offset |= 1 and h->got.offset |= 2
3267 diff IE and LD/GD. And all (got_off & (~(bfd_vma)1))
3268 (IE LD/GD and reusable GOT reloc) must change to
3269 (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
3271 Now, LD and GD is both GOT_TLS_GD type, LD seems to
3273 case R_LARCH_TLS_IE_PC_HI20
:
3274 case R_LARCH_TLS_IE_HI20
:
3275 case R_LARCH_TLS_LD_PC_HI20
:
3276 case R_LARCH_TLS_LD_HI20
:
3277 case R_LARCH_TLS_GD_PC_HI20
:
3278 case R_LARCH_TLS_GD_HI20
:
3279 BFD_ASSERT (rel
->r_addend
== 0);
3280 unresolved_reloc
= false;
3282 if (r_type
== R_LARCH_TLS_IE_PC_HI20
3283 || r_type
== R_LARCH_TLS_IE_HI20
)
3286 bfd_vma got_off
= 0;
3289 got_off
= h
->got
.offset
;
3294 got_off
= local_got_offsets
[r_symndx
];
3295 local_got_offsets
[r_symndx
] |= 1;
3298 BFD_ASSERT (got_off
!= MINUS_ONE
);
3301 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
3302 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
3303 ie_off
= 2 * GOT_ENTRY_SIZE
;
3305 if ((got_off
& 1) == 0)
3307 Elf_Internal_Rela rela
;
3308 asection
*relgot
= htab
->elf
.srelgot
;
3309 bfd_vma tls_block_off
= 0;
3311 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3313 BFD_ASSERT (elf_hash_table (info
)->tls_sec
);
3314 tls_block_off
= relocation
3315 - elf_hash_table (info
)->tls_sec
->vma
;
3318 if (tls_type
& GOT_TLS_GD
)
3320 rela
.r_offset
= sec_addr (got
) + got_off
;
3322 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3324 /* Local sym, used in exec, set module id 1. */
3325 if (bfd_link_executable (info
))
3326 bfd_put_NN (output_bfd
, 1, got
->contents
+ got_off
);
3329 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN
);
3330 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3333 bfd_put_NN (output_bfd
, tls_block_off
,
3334 got
->contents
+ got_off
+ GOT_ENTRY_SIZE
);
3336 /* Dynamic resolved. */
3339 /* Dynamic relocate module id. */
3340 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3341 R_LARCH_TLS_DTPMODNN
);
3342 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3344 /* Dynamic relocate offset of block. */
3345 rela
.r_offset
+= GOT_ENTRY_SIZE
;
3346 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3347 R_LARCH_TLS_DTPRELNN
);
3348 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3351 if (tls_type
& GOT_TLS_IE
)
3353 rela
.r_offset
= sec_addr (got
) + got_off
+ ie_off
;
3354 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3356 /* Local sym, used in exec, set module id 1. */
3357 if (!bfd_link_executable (info
))
3359 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN
);
3360 rela
.r_addend
= tls_block_off
;
3361 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3364 bfd_put_NN (output_bfd
, tls_block_off
,
3365 got
->contents
+ got_off
+ ie_off
);
3367 /* Dynamic resolved. */
3370 /* Dynamic relocate offset of block. */
3371 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3372 R_LARCH_TLS_TPRELNN
);
3374 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3378 relocation
= (got_off
& (~(bfd_vma
)1)) + sec_addr (got
)
3379 + (is_ie
? ie_off
: 0);
3381 if (r_type
== R_LARCH_TLS_LD_PC_HI20
3382 || r_type
== R_LARCH_TLS_GD_PC_HI20
3383 || r_type
== R_LARCH_TLS_IE_PC_HI20
)
3384 RELOCATE_CALC_PC32_HI20 (relocation
, pc
);
3388 case R_LARCH_TLS_IE_PC_LO12
:
3389 case R_LARCH_TLS_IE64_PC_LO20
:
3390 case R_LARCH_TLS_IE64_PC_HI12
:
3391 case R_LARCH_TLS_IE_LO12
:
3392 case R_LARCH_TLS_IE64_LO20
:
3393 case R_LARCH_TLS_IE64_HI12
:
3394 unresolved_reloc
= false;
3397 relocation
= sec_addr (got
) + (h
->got
.offset
& (~(bfd_vma
)3));
3399 relocation
= sec_addr (got
)
3400 + (local_got_offsets
[r_symndx
] & (~(bfd_vma
)3));
3402 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
3403 /* Use both TLS_GD and TLS_IE. */
3404 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
3405 relocation
+= 2 * GOT_ENTRY_SIZE
;
3407 if (r_type
== R_LARCH_TLS_IE_PC_LO12
)
3408 relocation
&= (bfd_vma
)0xfff;
3409 else if (r_type
== R_LARCH_TLS_IE64_PC_LO20
3410 || r_type
== R_LARCH_TLS_IE64_PC_HI12
)
3411 RELOCATE_CALC_PC64_HI32 (relocation
, pc
);
3427 /* 'unresolved_reloc' means we haven't done it yet.
3428 We need help of dynamic linker to fix this memory location up. */
3429 if (!unresolved_reloc
)
3432 if (_bfd_elf_section_offset (output_bfd
, info
, input_section
,
3433 rel
->r_offset
) == MINUS_ONE
)
3434 /* WHY? May because it's invalid so skip checking.
3435 But why dynamic reloc a invalid section? */
3438 if (input_section
->output_section
->flags
& SEC_DEBUGGING
)
3440 fatal
= (loongarch_reloc_is_fatal
3441 (info
, input_bfd
, input_section
, rel
, howto
,
3442 bfd_reloc_dangerous
, is_undefweak
, name
,
3443 "Seems dynamic linker not process "
3444 "sections 'SEC_DEBUGGING'."));
3449 if ((info
->flags
& DF_TEXTREL
) == 0)
3450 if (input_section
->output_section
->flags
& SEC_READONLY
)
3451 info
->flags
|= DF_TEXTREL
;
3458 loongarch_record_one_reloc (input_bfd
, input_section
, r_type
,
3459 rel
->r_offset
, sym
, h
, rel
->r_addend
);
3461 if (r
!= bfd_reloc_continue
)
3462 r
= perform_relocation (rel
, input_section
, howto
, relocation
,
3463 input_bfd
, contents
);
3467 case bfd_reloc_dangerous
:
3468 case bfd_reloc_continue
:
3472 case bfd_reloc_overflow
:
3473 /* Overflow value can't be filled in. */
3474 loongarch_dump_reloc_record (info
->callbacks
->info
);
3475 info
->callbacks
->reloc_overflow
3476 (info
, h
? &h
->root
: NULL
, name
, howto
->name
, rel
->r_addend
,
3477 input_bfd
, input_section
, rel
->r_offset
);
3480 case bfd_reloc_outofrange
:
3481 /* Stack state incorrect. */
3482 loongarch_dump_reloc_record (info
->callbacks
->info
);
3483 info
->callbacks
->info
3484 ("%X%H: Internal stack state is incorrect.\n"
3485 "Want to push to full stack or pop from empty stack?\n",
3486 input_bfd
, input_section
, rel
->r_offset
);
3489 case bfd_reloc_notsupported
:
3490 info
->callbacks
->info ("%X%H: Unknown relocation type.\n", input_bfd
,
3491 input_section
, rel
->r_offset
);
3495 info
->callbacks
->info ("%X%H: Internal: unknown error.\n", input_bfd
,
3496 input_section
, rel
->r_offset
);
3506 /* Finish up dynamic symbol handling. We set the contents of various
3507 dynamic sections here. */
3510 loongarch_elf_finish_dynamic_symbol (bfd
*output_bfd
,
3511 struct bfd_link_info
*info
,
3512 struct elf_link_hash_entry
*h
,
3513 Elf_Internal_Sym
*sym
)
3515 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
3516 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
3517 asection
*rela_dyn
= bfd_get_section_by_name (output_bfd
, ".rela.dyn");
3518 struct bfd_link_order
*lo
= NULL
;
3519 Elf_Internal_Rela
*slot
= NULL
, *last_slot
= NULL
;
3522 lo
= rela_dyn
->map_head
.link_order
;
3524 if (h
->plt
.offset
!= MINUS_ONE
)
3527 asection
*plt
, *gotplt
, *relplt
;
3528 bfd_vma got_address
;
3529 uint32_t plt_entry
[PLT_ENTRY_INSNS
];
3531 Elf_Internal_Rela rela
;
3532 asection
*rela_sec
= NULL
;
3536 BFD_ASSERT ((h
->type
== STT_GNU_IFUNC
3537 && SYMBOL_REFERENCES_LOCAL (info
, h
))
3538 || h
->dynindx
!= -1);
3540 plt
= htab
->elf
.splt
;
3541 gotplt
= htab
->elf
.sgotplt
;
3542 if (h
->type
== STT_GNU_IFUNC
&& SYMBOL_REFERENCES_LOCAL (info
, h
))
3543 relplt
= htab
->elf
.srelgot
;
3545 relplt
= htab
->elf
.srelplt
;
3546 plt_idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
) / PLT_ENTRY_SIZE
;
3548 sec_addr (gotplt
) + GOTPLT_HEADER_SIZE
+ plt_idx
* GOT_ENTRY_SIZE
;
3550 else /* if (htab->elf.iplt) */
3552 BFD_ASSERT (h
->type
== STT_GNU_IFUNC
3553 && SYMBOL_REFERENCES_LOCAL (info
, h
));
3555 plt
= htab
->elf
.iplt
;
3556 gotplt
= htab
->elf
.igotplt
;
3557 relplt
= htab
->elf
.irelplt
;
3558 plt_idx
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
3559 got_address
= sec_addr (gotplt
) + plt_idx
* GOT_ENTRY_SIZE
;
3562 /* Find out where the .plt entry should go. */
3563 loc
= plt
->contents
+ h
->plt
.offset
;
3565 /* Fill in the PLT entry itself. */
3566 if (!loongarch_make_plt_entry (got_address
,
3567 sec_addr (plt
) + h
->plt
.offset
,
3571 for (i
= 0; i
< PLT_ENTRY_INSNS
; i
++)
3572 bfd_put_32 (output_bfd
, plt_entry
[i
], loc
+ 4 * i
);
3574 /* Fill in the initial value of the got.plt entry. */
3575 loc
= gotplt
->contents
+ (got_address
- sec_addr (gotplt
));
3576 bfd_put_NN (output_bfd
, sec_addr (plt
), loc
);
3578 rela
.r_offset
= got_address
;
3580 /* TRUE if this is a PLT reference to a local IFUNC. */
3581 if (PLT_LOCAL_IFUNC_P (info
, h
)
3582 && (relplt
== htab
->elf
.srelgot
3583 || relplt
== htab
->elf
.irelplt
))
3585 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
3586 rela
.r_addend
= (h
->root
.u
.def
.value
3587 + h
->root
.u
.def
.section
->output_section
->vma
3588 + h
->root
.u
.def
.section
->output_offset
);
3590 /* Find the space after dyn sort. */
3591 while (slot
== last_slot
|| slot
->r_offset
!= 0)
3593 if (slot
!= last_slot
)
3599 BFD_ASSERT (lo
!= NULL
);
3600 rela_sec
= lo
->u
.indirect
.section
;
3603 slot
= (Elf_Internal_Rela
*)rela_sec
->contents
;
3604 last_slot
= (Elf_Internal_Rela
*)(rela_sec
->contents
+
3608 bed
->s
->swap_reloca_out (output_bfd
, &rela
, (bfd_byte
*)slot
);
3609 rela_sec
->reloc_count
++;
3613 /* Fill in the entry in the rela.plt section. */
3614 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_JUMP_SLOT
);
3616 loc
= relplt
->contents
+ plt_idx
* sizeof (ElfNN_External_Rela
);
3617 bed
->s
->swap_reloca_out (output_bfd
, &rela
, loc
);
3620 if (!h
->def_regular
)
3622 /* Mark the symbol as undefined, rather than as defined in
3623 the .plt section. Leave the value alone. */
3624 sym
->st_shndx
= SHN_UNDEF
;
3625 /* If the symbol is weak, we do need to clear the value.
3626 Otherwise, the PLT entry would provide a definition for
3627 the symbol even if the symbol wasn't defined anywhere,
3628 and so the symbol would never be NULL. */
3629 if (!h
->ref_regular_nonweak
)
3634 if (h
->got
.offset
!= MINUS_ONE
3635 /* TLS got entry have been handled in elf_relocate_section. */
3636 && !(loongarch_elf_hash_entry (h
)->tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
3637 /* Have allocated got entry but not allocated rela before. */
3638 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
3640 asection
*sgot
, *srela
;
3641 Elf_Internal_Rela rela
;
3642 bfd_vma off
= h
->got
.offset
& ~(bfd_vma
)1;
3644 /* This symbol has an entry in the GOT. Set it up. */
3645 sgot
= htab
->elf
.sgot
;
3646 srela
= htab
->elf
.srelgot
;
3647 BFD_ASSERT (sgot
&& srela
);
3649 rela
.r_offset
= sec_addr (sgot
) + off
;
3652 && h
->type
== STT_GNU_IFUNC
)
3654 if(h
->plt
.offset
== MINUS_ONE
)
3656 if (htab
->elf
.splt
== NULL
)
3657 srela
= htab
->elf
.irelplt
;
3659 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3661 asection
*sec
= h
->root
.u
.def
.section
;
3662 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
3663 rela
.r_addend
= h
->root
.u
.def
.value
+ sec
->output_section
->vma
3664 + sec
->output_offset
;
3665 bfd_put_NN (output_bfd
, 0, sgot
->contents
+ off
);
3669 BFD_ASSERT (h
->dynindx
!= -1);
3670 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
3672 bfd_put_NN (output_bfd
, (bfd_vma
) 0, sgot
->contents
+ off
);
3675 else if(bfd_link_pic (info
))
3677 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
3679 bfd_put_NN (output_bfd
, rela
.r_addend
, sgot
->contents
+ off
);
3684 /* For non-shared object, we can't use .got.plt, which
3685 contains the real function address if we need pointer
3686 equality. We load the GOT entry with the PLT entry. */
3687 plt
= htab
->elf
.splt
? htab
->elf
.splt
: htab
->elf
.iplt
;
3688 bfd_put_NN (output_bfd
,
3689 (plt
->output_section
->vma
3690 + plt
->output_offset
3692 sgot
->contents
+ off
);
3696 else if (bfd_link_pic (info
) && SYMBOL_REFERENCES_LOCAL (info
, h
))
3698 asection
*sec
= h
->root
.u
.def
.section
;
3699 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
3700 rela
.r_addend
= (h
->root
.u
.def
.value
+ sec
->output_section
->vma
3701 + sec
->output_offset
);
3705 BFD_ASSERT (h
->dynindx
!= -1);
3706 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
3710 loongarch_elf_append_rela (output_bfd
, srela
, &rela
);
3713 /* Mark some specially defined symbols as absolute. */
3714 if (h
== htab
->elf
.hdynamic
|| h
== htab
->elf
.hgot
|| h
== htab
->elf
.hplt
)
3715 sym
->st_shndx
= SHN_ABS
;
3720 /* Finish up the dynamic sections. */
3723 loongarch_finish_dyn (bfd
*output_bfd
, struct bfd_link_info
*info
, bfd
*dynobj
,
3726 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
3727 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
3728 size_t dynsize
= bed
->s
->sizeof_dyn
, skipped_size
= 0;
3729 bfd_byte
*dyncon
, *dynconend
;
3731 dynconend
= sdyn
->contents
+ sdyn
->size
;
3732 for (dyncon
= sdyn
->contents
; dyncon
< dynconend
; dyncon
+= dynsize
)
3734 Elf_Internal_Dyn dyn
;
3738 bed
->s
->swap_dyn_in (dynobj
, dyncon
, &dyn
);
3743 s
= htab
->elf
.sgotplt
;
3744 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3747 s
= htab
->elf
.srelplt
;
3748 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3751 s
= htab
->elf
.srelplt
;
3752 dyn
.d_un
.d_val
= s
->size
;
3755 if ((info
->flags
& DF_TEXTREL
) == 0)
3759 if ((info
->flags
& DF_TEXTREL
) == 0)
3760 dyn
.d_un
.d_val
&= ~DF_TEXTREL
;
3764 skipped_size
+= dynsize
;
3766 bed
->s
->swap_dyn_out (output_bfd
, &dyn
, dyncon
- skipped_size
);
3768 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
3769 memset (dyncon
- skipped_size
, 0, skipped_size
);
3773 /* Finish up local dynamic symbol handling. We set the contents of
3774 various dynamic sections here. */
3777 elfNN_loongarch_finish_local_dynamic_symbol (void **slot
, void *inf
)
3779 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
3780 struct bfd_link_info
*info
= (struct bfd_link_info
*) inf
;
3782 return loongarch_elf_finish_dynamic_symbol (info
->output_bfd
, info
, h
, NULL
);
3786 loongarch_elf_finish_dynamic_sections (bfd
*output_bfd
,
3787 struct bfd_link_info
*info
)
3790 asection
*sdyn
, *plt
, *gotplt
= NULL
;
3791 struct loongarch_elf_link_hash_table
*htab
;
3793 htab
= loongarch_elf_hash_table (info
);
3795 dynobj
= htab
->elf
.dynobj
;
3796 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
3798 if (elf_hash_table (info
)->dynamic_sections_created
)
3800 BFD_ASSERT (htab
->elf
.splt
&& sdyn
);
3802 if (!loongarch_finish_dyn (output_bfd
, info
, dynobj
, sdyn
))
3806 plt
= htab
->elf
.splt
;
3807 gotplt
= htab
->elf
.sgotplt
;
3809 if (plt
&& 0 < plt
->size
)
3812 uint32_t plt_header
[PLT_HEADER_INSNS
];
3813 if (!loongarch_make_plt_header (sec_addr (gotplt
), sec_addr (plt
),
3817 for (i
= 0; i
< PLT_HEADER_INSNS
; i
++)
3818 bfd_put_32 (output_bfd
, plt_header
[i
], plt
->contents
+ 4 * i
);
3820 elf_section_data (plt
->output_section
)->this_hdr
.sh_entsize
=
3824 if (htab
->elf
.sgotplt
)
3826 asection
*output_section
= htab
->elf
.sgotplt
->output_section
;
3828 if (bfd_is_abs_section (output_section
))
3830 _bfd_error_handler (_("discarded output section: `%pA'"),
3835 if (0 < htab
->elf
.sgotplt
->size
)
3837 /* Write the first two entries in .got.plt, needed for the dynamic
3839 bfd_put_NN (output_bfd
, MINUS_ONE
, htab
->elf
.sgotplt
->contents
);
3841 bfd_put_NN (output_bfd
, (bfd_vma
) 0,
3842 htab
->elf
.sgotplt
->contents
+ GOT_ENTRY_SIZE
);
3845 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
3850 asection
*output_section
= htab
->elf
.sgot
->output_section
;
3852 if (0 < htab
->elf
.sgot
->size
)
3854 /* Set the first entry in the global offset table to the address of
3855 the dynamic section. */
3856 bfd_vma val
= sdyn
? sec_addr (sdyn
) : 0;
3857 bfd_put_NN (output_bfd
, val
, htab
->elf
.sgot
->contents
);
3860 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
3863 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
3864 htab_traverse (htab
->loc_hash_table
,
3865 (void *) elfNN_loongarch_finish_local_dynamic_symbol
, info
);
3870 /* Return address for Ith PLT stub in section PLT, for relocation REL
3871 or (bfd_vma) -1 if it should not be included. */
3874 loongarch_elf_plt_sym_val (bfd_vma i
, const asection
*plt
,
3875 const arelent
*rel ATTRIBUTE_UNUSED
)
3877 return plt
->vma
+ PLT_HEADER_SIZE
+ i
* PLT_ENTRY_SIZE
;
3880 static enum elf_reloc_type_class
3881 loongarch_reloc_type_class (const struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
3882 const asection
*rel_sec ATTRIBUTE_UNUSED
,
3883 const Elf_Internal_Rela
*rela
)
3885 struct loongarch_elf_link_hash_table
*htab
;
3886 htab
= loongarch_elf_hash_table (info
);
3888 if (htab
->elf
.dynsym
!= NULL
&& htab
->elf
.dynsym
->contents
!= NULL
)
3890 /* Check relocation against STT_GNU_IFUNC symbol if there are
3892 bfd
*abfd
= info
->output_bfd
;
3893 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
3894 unsigned long r_symndx
= ELFNN_R_SYM (rela
->r_info
);
3895 if (r_symndx
!= STN_UNDEF
)
3897 Elf_Internal_Sym sym
;
3898 if (!bed
->s
->swap_symbol_in (abfd
,
3899 htab
->elf
.dynsym
->contents
3900 + r_symndx
* bed
->s
->sizeof_sym
,
3903 /* xgettext:c-format */
3904 _bfd_error_handler (_("%pB symbol number %lu references"
3905 " nonexistent SHT_SYMTAB_SHNDX section"),
3907 /* Ideally an error class should be returned here. */
3909 else if (ELF_ST_TYPE (sym
.st_info
) == STT_GNU_IFUNC
)
3910 return reloc_class_ifunc
;
3914 switch (ELFNN_R_TYPE (rela
->r_info
))
3916 case R_LARCH_IRELATIVE
:
3917 return reloc_class_ifunc
;
3918 case R_LARCH_RELATIVE
:
3919 return reloc_class_relative
;
3920 case R_LARCH_JUMP_SLOT
:
3921 return reloc_class_plt
;
3923 return reloc_class_copy
;
3925 return reloc_class_normal
;
3929 /* Copy the extra info we tack onto an elf_link_hash_entry. */
3932 loongarch_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
3933 struct elf_link_hash_entry
*dir
,
3934 struct elf_link_hash_entry
*ind
)
3936 struct elf_link_hash_entry
*edir
, *eind
;
3941 if (eind
->dyn_relocs
!= NULL
)
3943 if (edir
->dyn_relocs
!= NULL
)
3945 struct elf_dyn_relocs
**pp
;
3946 struct elf_dyn_relocs
*p
;
3948 /* Add reloc counts against the indirect sym to the direct sym
3949 list. Merge any entries against the same section. */
3950 for (pp
= &eind
->dyn_relocs
; (p
= *pp
) != NULL
;)
3952 struct elf_dyn_relocs
*q
;
3954 for (q
= edir
->dyn_relocs
; q
!= NULL
; q
= q
->next
)
3955 if (q
->sec
== p
->sec
)
3957 q
->pc_count
+= p
->pc_count
;
3958 q
->count
+= p
->count
;
3965 *pp
= edir
->dyn_relocs
;
3968 edir
->dyn_relocs
= eind
->dyn_relocs
;
3969 eind
->dyn_relocs
= NULL
;
3972 if (ind
->root
.type
== bfd_link_hash_indirect
&& dir
->got
.refcount
< 0)
3974 loongarch_elf_hash_entry(edir
)->tls_type
3975 = loongarch_elf_hash_entry(eind
)->tls_type
;
3976 loongarch_elf_hash_entry(eind
)->tls_type
= GOT_UNKNOWN
;
3978 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
3981 #define PRSTATUS_SIZE 0x1d8
3982 #define PRSTATUS_OFFSET_PR_CURSIG 0xc
3983 #define PRSTATUS_OFFSET_PR_PID 0x20
3984 #define ELF_GREGSET_T_SIZE 0x168
3985 #define PRSTATUS_OFFSET_PR_REG 0x70
3987 /* Support for core dump NOTE sections. */
3990 loongarch_elf_grok_prstatus (bfd
*abfd
, Elf_Internal_Note
*note
)
3992 switch (note
->descsz
)
3997 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
4000 elf_tdata (abfd
)->core
->signal
=
4001 bfd_get_16 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_CURSIG
);
4004 elf_tdata (abfd
)->core
->lwpid
=
4005 bfd_get_32 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_PID
);
4009 /* Make a ".reg/999" section. */
4010 return _bfd_elfcore_make_pseudosection (abfd
, ".reg", ELF_GREGSET_T_SIZE
,
4012 + PRSTATUS_OFFSET_PR_REG
);
4015 #define PRPSINFO_SIZE 0x88
4016 #define PRPSINFO_OFFSET_PR_PID 0x18
4017 #define PRPSINFO_OFFSET_PR_FNAME 0x28
4018 #define PRPSINFO_SIZEOF_PR_FNAME 0x10
4019 #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
4020 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
4023 loongarch_elf_grok_psinfo (bfd
*abfd
, Elf_Internal_Note
*note
)
4025 switch (note
->descsz
)
4030 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
4033 elf_tdata (abfd
)->core
->pid
=
4034 bfd_get_32 (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PID
);
4037 elf_tdata (abfd
)->core
->program
=
4038 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_FNAME
,
4039 PRPSINFO_SIZEOF_PR_FNAME
);
4042 elf_tdata (abfd
)->core
->command
=
4043 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PS_ARGS
,
4044 PRPSINFO_SIZEOF_PR_PS_ARGS
);
4048 /* Note that for some reason, a spurious space is tacked
4049 onto the end of the args in some (at least one anyway)
4050 implementations, so strip it off if it exists. */
4053 char *command
= elf_tdata (abfd
)->core
->command
;
4054 int n
= strlen (command
);
4056 if (0 < n
&& command
[n
- 1] == ' ')
4057 command
[n
- 1] = '\0';
4063 /* Set the right mach type. */
4065 loongarch_elf_object_p (bfd
*abfd
)
4067 /* There are only two mach types in LoongArch currently. */
4068 if (strcmp (abfd
->xvec
->name
, "elf64-loongarch") == 0)
4069 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch64
);
4071 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch32
);
4076 loongarch_elf_gc_mark_hook (asection
*sec
, struct bfd_link_info
*info
,
4077 Elf_Internal_Rela
*rel
,
4078 struct elf_link_hash_entry
*h
,
4079 Elf_Internal_Sym
*sym
)
4082 switch (ELFNN_R_TYPE (rel
->r_info
))
4084 case R_LARCH_GNU_VTINHERIT
:
4085 case R_LARCH_GNU_VTENTRY
:
4089 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
4092 /* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For
4093 executable PLT slots where the executable never takes the address of those
4094 functions, the function symbols are not added to the hash table. */
4097 elf_loongarch64_hash_symbol (struct elf_link_hash_entry
*h
)
4099 if (h
->plt
.offset
!= (bfd_vma
) -1
4101 && !h
->pointer_equality_needed
)
4104 return _bfd_elf_hash_symbol (h
);
4107 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
4108 #define TARGET_LITTLE_NAME "elfNN-loongarch"
4109 #define ELF_ARCH bfd_arch_loongarch
4110 #define ELF_TARGET_ID LARCH_ELF_DATA
4111 #define ELF_MACHINE_CODE EM_LOONGARCH
4112 #define ELF_MAXPAGESIZE 0x4000
4113 #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
4114 #define bfd_elfNN_bfd_link_hash_table_create \
4115 loongarch_elf_link_hash_table_create
4116 #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
4117 #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
4118 #define elf_info_to_howto loongarch_info_to_howto_rela
4119 #define bfd_elfNN_bfd_merge_private_bfd_data \
4120 elfNN_loongarch_merge_private_bfd_data
4122 #define elf_backend_reloc_type_class loongarch_reloc_type_class
4123 #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
4124 #define elf_backend_create_dynamic_sections \
4125 loongarch_elf_create_dynamic_sections
4126 #define elf_backend_check_relocs loongarch_elf_check_relocs
4127 #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
4128 #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
4129 #define elf_backend_relocate_section loongarch_elf_relocate_section
4130 #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
4131 #define elf_backend_finish_dynamic_sections \
4132 loongarch_elf_finish_dynamic_sections
4133 #define elf_backend_object_p loongarch_elf_object_p
4134 #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
4135 #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
4136 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
4137 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
4138 #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
4140 #include "elfNN-target.h"