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
;
45 /* Track dynamic relocs copied for this symbol. */
46 struct elf_dyn_relocs
*dyn_relocs
;
56 #define loongarch_elf_hash_entry(ent) \
57 ((struct loongarch_elf_link_hash_entry *) (ent))
59 struct _bfd_loongarch_elf_obj_tdata
61 struct elf_obj_tdata root
;
63 /* The tls_type for each local got entry. */
64 char *local_got_tls_type
;
67 #define _bfd_loongarch_elf_tdata(abfd) \
68 ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
70 #define _bfd_loongarch_elf_local_got_tls_type(abfd) \
71 (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
73 #define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
75 ? &loongarch_elf_hash_entry (h)->tls_type \
76 : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
78 #define is_loongarch_elf(bfd) \
79 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
80 && elf_tdata (bfd) != NULL \
81 && elf_object_id (bfd) == LARCH_ELF_DATA)
83 struct loongarch_elf_link_hash_table
85 struct elf_link_hash_table elf
;
87 /* Short-cuts to get to dynamic linker sections. */
90 /* Small local sym to section mapping cache. */
91 struct sym_cache sym_cache
;
93 /* Used by local STT_GNU_IFUNC symbols. */
94 htab_t loc_hash_table
;
95 void *loc_hash_memory
;
97 /* The max alignment of output sections. */
98 bfd_vma max_alignment
;
101 /* Get the LoongArch ELF linker hash table from a link_info structure. */
102 #define loongarch_elf_hash_table(p) \
103 (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
104 ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
107 #define MINUS_ONE ((bfd_vma) 0 - 1)
109 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
111 #define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
112 #define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
114 #define PLT_HEADER_INSNS 8
115 #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
117 #define PLT_ENTRY_INSNS 4
118 #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
120 #define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
122 #define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
124 #define elf_backend_want_got_plt 1
126 #define elf_backend_plt_readonly 1
128 #define elf_backend_want_plt_sym 0
129 #define elf_backend_plt_alignment 4
130 #define elf_backend_can_gc_sections 1
131 /* #define elf_backend_can_refcount 1 */
132 #define elf_backend_want_got_sym 1
134 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
136 #define elf_backend_want_dynrelro 1
137 /* #define elf_backend_rela_normal 1
138 #define elf_backend_default_execstack 0 */
140 /* Generate a PLT header. */
143 loongarch_make_plt_header (bfd_vma got_plt_addr
, bfd_vma plt_header_addr
,
146 bfd_vma pcrel
= got_plt_addr
- plt_header_addr
;
149 if (pcrel
+ 0x80000800 > 0xffffffff)
151 _bfd_error_handler (_("%#" PRIx64
" invaild imm"), (uint64_t) pcrel
);
152 bfd_set_error (bfd_error_bad_value
);
155 hi
= ((pcrel
+ 0x800) >> 12) & 0xfffff;
158 /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
159 sub.[wd] $t1, $t1, $t3
160 ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
161 addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
162 addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
163 srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
164 ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
167 if (GOT_ENTRY_SIZE
== 8)
169 entry
[0] = 0x1c00000e | (hi
& 0xfffff) << 5;
170 entry
[1] = 0x0011bdad;
171 entry
[2] = 0x28c001cf | (lo
& 0xfff) << 10;
172 entry
[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE
+ 12)) & 0xfff) << 10;
173 entry
[4] = 0x02c001cc | (lo
& 0xfff) << 10;
174 entry
[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES
) << 10;
175 entry
[6] = 0x28c0018c | GOT_ENTRY_SIZE
<< 10;
176 entry
[7] = 0x4c0001e0;
180 entry
[0] = 0x1c00000e | (hi
& 0xfffff) << 5;
181 entry
[1] = 0x00113dad;
182 entry
[2] = 0x288001cf | (lo
& 0xfff) << 10;
183 entry
[3] = 0x028001ad | ((-(PLT_HEADER_SIZE
+ 12)) & 0xfff) << 10;
184 entry
[4] = 0x028001cc | (lo
& 0xfff) << 10;
185 entry
[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES
) << 10;
186 entry
[6] = 0x2880018c | GOT_ENTRY_SIZE
<< 10;
187 entry
[7] = 0x4c0001e0;
192 /* Generate a PLT entry. */
195 loongarch_make_plt_entry (bfd_vma got_plt_entry_addr
, bfd_vma plt_entry_addr
,
198 bfd_vma pcrel
= got_plt_entry_addr
- plt_entry_addr
;
201 if (pcrel
+ 0x80000800 > 0xffffffff)
203 _bfd_error_handler (_("%#" PRIx64
" invaild imm"), (uint64_t) pcrel
);
204 bfd_set_error (bfd_error_bad_value
);
207 hi
= ((pcrel
+ 0x800) >> 12) & 0xfffff;
210 entry
[0] = 0x1c00000f | (hi
& 0xfffff) << 5;
211 entry
[1] = ((GOT_ENTRY_SIZE
== 8 ? 0x28c001ef : 0x288001ef)
212 | (lo
& 0xfff) << 10);
213 entry
[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
214 entry
[3] = 0x03400000; /* nop */
219 /* Create an entry in an LoongArch ELF linker hash table. */
221 static struct bfd_hash_entry
*
222 link_hash_newfunc (struct bfd_hash_entry
*entry
, struct bfd_hash_table
*table
,
225 struct loongarch_elf_link_hash_entry
*eh
;
227 /* Allocate the structure if it has not already been allocated by a
231 entry
= bfd_hash_allocate (table
, sizeof (*eh
));
236 /* Call the allocation method of the superclass. */
237 entry
= _bfd_elf_link_hash_newfunc (entry
, table
, string
);
240 eh
= (struct loongarch_elf_link_hash_entry
*) entry
;
241 eh
->dyn_relocs
= NULL
;
242 eh
->tls_type
= GOT_UNKNOWN
;
248 /* Compute a hash of a local hash entry. We use elf_link_hash_entry
249 for local symbol so that we can handle local STT_GNU_IFUNC symbols
250 as global symbol. We reuse indx and dynstr_index for local symbol
251 hash since they aren't used by global symbols in this backend. */
254 elfNN_loongarch_local_htab_hash (const void *ptr
)
256 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) ptr
;
257 return ELF_LOCAL_SYMBOL_HASH (h
->indx
, h
->dynstr_index
);
260 /* Compare local hash entries. */
263 elfNN_loongarch_local_htab_eq (const void *ptr1
, const void *ptr2
)
265 struct elf_link_hash_entry
*h1
= (struct elf_link_hash_entry
*) ptr1
;
266 struct elf_link_hash_entry
*h2
= (struct elf_link_hash_entry
*) ptr2
;
268 return h1
->indx
== h2
->indx
&& h1
->dynstr_index
== h2
->dynstr_index
;
271 /* Find and/or create a hash entry for local symbol. */
272 static struct elf_link_hash_entry
*
273 elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table
*htab
,
274 bfd
*abfd
, const Elf_Internal_Rela
*rel
,
277 struct loongarch_elf_link_hash_entry e
, *ret
;
278 asection
*sec
= abfd
->sections
;
279 hashval_t h
= ELF_LOCAL_SYMBOL_HASH (sec
->id
, ELFNN_R_SYM (rel
->r_info
));
282 e
.elf
.indx
= sec
->id
;
283 e
.elf
.dynstr_index
= ELFNN_R_SYM (rel
->r_info
);
284 slot
= htab_find_slot_with_hash (htab
->loc_hash_table
, &e
, h
,
285 create
? INSERT
: NO_INSERT
);
292 ret
= (struct loongarch_elf_link_hash_entry
*) *slot
;
296 ret
= ((struct loongarch_elf_link_hash_entry
*)
297 objalloc_alloc ((struct objalloc
*) htab
->loc_hash_memory
,
298 sizeof (struct loongarch_elf_link_hash_entry
)));
301 memset (ret
, 0, sizeof (*ret
));
302 ret
->elf
.indx
= sec
->id
;
303 ret
->elf
.pointer_equality_needed
= 0;
304 ret
->elf
.dynstr_index
= ELFNN_R_SYM (rel
->r_info
);
305 ret
->elf
.dynindx
= -1;
306 ret
->elf
.needs_plt
= 0;
307 ret
->elf
.plt
.refcount
= -1;
308 ret
->elf
.got
.refcount
= -1;
309 ret
->elf
.def_dynamic
= 0;
310 ret
->elf
.def_regular
= 1;
311 ret
->elf
.ref_dynamic
= 0; /* This should be always 0 for local. */
312 ret
->elf
.ref_regular
= 0;
313 ret
->elf
.forced_local
= 1;
314 ret
->elf
.root
.type
= bfd_link_hash_defined
;
320 /* Destroy an LoongArch elf linker hash table. */
323 elfNN_loongarch_link_hash_table_free (bfd
*obfd
)
325 struct loongarch_elf_link_hash_table
*ret
;
326 ret
= (struct loongarch_elf_link_hash_table
*) obfd
->link
.hash
;
328 if (ret
->loc_hash_table
)
329 htab_delete (ret
->loc_hash_table
);
330 if (ret
->loc_hash_memory
)
331 objalloc_free ((struct objalloc
*) ret
->loc_hash_memory
);
333 _bfd_elf_link_hash_table_free (obfd
);
336 /* Create a LoongArch ELF linker hash table. */
338 static struct bfd_link_hash_table
*
339 loongarch_elf_link_hash_table_create (bfd
*abfd
)
341 struct loongarch_elf_link_hash_table
*ret
;
342 bfd_size_type amt
= sizeof (struct loongarch_elf_link_hash_table
);
344 ret
= (struct loongarch_elf_link_hash_table
*) bfd_zmalloc (amt
);
348 if (!_bfd_elf_link_hash_table_init
349 (&ret
->elf
, abfd
, link_hash_newfunc
,
350 sizeof (struct loongarch_elf_link_hash_entry
), LARCH_ELF_DATA
))
356 ret
->max_alignment
= MINUS_ONE
;
358 ret
->loc_hash_table
= htab_try_create (1024, elfNN_loongarch_local_htab_hash
,
359 elfNN_loongarch_local_htab_eq
, NULL
);
360 ret
->loc_hash_memory
= objalloc_create ();
361 if (!ret
->loc_hash_table
|| !ret
->loc_hash_memory
)
363 elfNN_loongarch_link_hash_table_free (abfd
);
366 ret
->elf
.root
.hash_table_free
= elfNN_loongarch_link_hash_table_free
;
368 return &ret
->elf
.root
;
371 /* Merge backend specific data from an object file to the output
372 object file when linking. */
375 elfNN_loongarch_merge_private_bfd_data (bfd
*ibfd
, struct bfd_link_info
*info
)
377 bfd
*obfd
= info
->output_bfd
;
378 flagword in_flags
= elf_elfheader (ibfd
)->e_flags
;
379 flagword out_flags
= elf_elfheader (obfd
)->e_flags
;
381 if (!is_loongarch_elf (ibfd
) || !is_loongarch_elf (obfd
))
384 if (strcmp (bfd_get_target (ibfd
), bfd_get_target (obfd
)) != 0)
386 _bfd_error_handler (_("%pB: ABI is incompatible with that of "
387 "the selected emulation:\n"
388 " target emulation `%s' does not match `%s'"),
389 ibfd
, bfd_get_target (ibfd
), bfd_get_target (obfd
));
393 if (!_bfd_elf_merge_object_attributes (ibfd
, info
))
396 if (!elf_flags_init (obfd
))
398 elf_flags_init (obfd
) = true;
399 elf_elfheader (obfd
)->e_flags
= in_flags
;
403 /* Disallow linking different ABIs. */
404 if ((out_flags
^ in_flags
) & EF_LOONGARCH_ABI
)
406 _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd
);
413 bfd_set_error (bfd_error_bad_value
);
417 /* Create the .got section. */
420 loongarch_elf_create_got_section (bfd
*abfd
, struct bfd_link_info
*info
)
425 struct elf_link_hash_entry
*h
;
426 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
427 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
429 /* This function may be called more than once. */
430 if (htab
->sgot
!= NULL
)
433 flags
= bed
->dynamic_sec_flags
;
434 name
= bed
->rela_plts_and_copies_p
? ".rela.got" : ".rel.got";
435 s
= bfd_make_section_anyway_with_flags (abfd
, name
, flags
| SEC_READONLY
);
437 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
441 s
= s_got
= bfd_make_section_anyway_with_flags (abfd
, ".got", flags
);
442 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
446 /* The first bit of the global offset table is the header. */
447 s
->size
+= bed
->got_header_size
;
449 if (bed
->want_got_plt
)
451 s
= bfd_make_section_anyway_with_flags (abfd
, ".got.plt", flags
);
452 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
456 /* Reserve room for the header. */
457 s
->size
= GOTPLT_HEADER_SIZE
;
460 if (bed
->want_got_sym
)
462 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
463 section. We don't do this in the linker script because we don't want
464 to define the symbol if we are not creating a global offset table. */
465 h
= _bfd_elf_define_linkage_sym (abfd
, info
, s_got
,
466 "_GLOBAL_OFFSET_TABLE_");
467 elf_hash_table (info
)->hgot
= h
;
474 /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
475 .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
479 loongarch_elf_create_dynamic_sections (bfd
*dynobj
, struct bfd_link_info
*info
)
481 struct loongarch_elf_link_hash_table
*htab
;
483 htab
= loongarch_elf_hash_table (info
);
484 BFD_ASSERT (htab
!= NULL
);
486 if (!loongarch_elf_create_got_section (dynobj
, info
))
489 if (!_bfd_elf_create_dynamic_sections (dynobj
, info
))
492 if (!bfd_link_pic (info
))
494 = bfd_make_section_anyway_with_flags (dynobj
, ".tdata.dyn",
495 SEC_ALLOC
| SEC_THREAD_LOCAL
);
497 if (!htab
->elf
.splt
|| !htab
->elf
.srelplt
|| !htab
->elf
.sdynbss
498 || (!bfd_link_pic (info
) && (!htab
->elf
.srelbss
|| !htab
->sdyntdata
)))
505 loongarch_elf_record_tls_and_got_reference (bfd
*abfd
,
506 struct bfd_link_info
*info
,
507 struct elf_link_hash_entry
*h
,
508 unsigned long symndx
,
511 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
512 Elf_Internal_Shdr
*symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
514 /* This is a global offset table entry for a local symbol. */
515 if (elf_local_got_refcounts (abfd
) == NULL
)
518 symtab_hdr
->sh_info
* (sizeof (bfd_vma
) + sizeof (tls_type
));
519 if (!(elf_local_got_refcounts (abfd
) = bfd_zalloc (abfd
, size
)))
521 _bfd_loongarch_elf_local_got_tls_type (abfd
) =
522 (char *) (elf_local_got_refcounts (abfd
) + symtab_hdr
->sh_info
);
531 if (htab
->elf
.sgot
== NULL
532 && !loongarch_elf_create_got_section (htab
->elf
.dynobj
, info
))
536 if (h
->got
.refcount
< 0)
541 elf_local_got_refcounts (abfd
)[symndx
]++;
544 /* No need for GOT. */
547 _bfd_error_handler (_("Internal error: unreachable."));
551 char *new_tls_type
= &_bfd_loongarch_elf_tls_type (abfd
, h
, symndx
);
552 *new_tls_type
|= tls_type
;
553 if ((*new_tls_type
& GOT_NORMAL
) && (*new_tls_type
& ~GOT_NORMAL
))
555 _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
556 "thread local symbol"),
558 h
? h
->root
.root
.string
: "<local>");
565 /* Look through the relocs for a section during the first phase, and
566 allocate space in the global offset table or procedure linkage
570 loongarch_elf_check_relocs (bfd
*abfd
, struct bfd_link_info
*info
,
571 asection
*sec
, const Elf_Internal_Rela
*relocs
)
573 struct loongarch_elf_link_hash_table
*htab
;
574 Elf_Internal_Shdr
*symtab_hdr
;
575 struct elf_link_hash_entry
**sym_hashes
;
576 const Elf_Internal_Rela
*rel
;
577 asection
*sreloc
= NULL
;
579 if (bfd_link_relocatable (info
))
582 htab
= loongarch_elf_hash_table (info
);
583 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
584 sym_hashes
= elf_sym_hashes (abfd
);
586 if (htab
->elf
.dynobj
== NULL
)
587 htab
->elf
.dynobj
= abfd
;
589 for (rel
= relocs
; rel
< relocs
+ sec
->reloc_count
; rel
++)
592 unsigned int r_symndx
;
593 struct elf_link_hash_entry
*h
;
594 Elf_Internal_Sym
*isym
= NULL
;
599 r_symndx
= ELFNN_R_SYM (rel
->r_info
);
600 r_type
= ELFNN_R_TYPE (rel
->r_info
);
602 if (r_symndx
>= NUM_SHDR_ENTRIES (symtab_hdr
))
604 _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd
, r_symndx
);
608 if (r_symndx
< symtab_hdr
->sh_info
)
610 /* A local symbol. */
611 isym
= bfd_sym_from_r_symndx (&htab
->sym_cache
, abfd
, r_symndx
);
615 if (ELF_ST_TYPE (isym
->st_info
) == STT_GNU_IFUNC
)
617 h
= elfNN_loongarch_get_local_sym_hash (htab
, abfd
, rel
, true);
621 h
->type
= STT_GNU_IFUNC
;
629 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
630 while (h
->root
.type
== bfd_link_hash_indirect
631 || h
->root
.type
== bfd_link_hash_warning
)
632 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
635 if (h
&& h
->type
== STT_GNU_IFUNC
)
637 if (htab
->elf
.dynobj
== NULL
)
638 htab
->elf
.dynobj
= abfd
;
641 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
642 /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
645 if (h
->plt
.refcount
< 0)
650 elf_tdata (info
->output_bfd
)->has_gnu_osabi
|= elf_gnu_osabi_ifunc
;
657 case R_LARCH_SOP_PUSH_GPREL
:
658 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
664 case R_LARCH_SOP_PUSH_TLS_GD
:
665 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
671 case R_LARCH_SOP_PUSH_TLS_GOT
:
672 if (bfd_link_pic (info
))
673 /* May fail for lazy-bind. */
674 info
->flags
|= DF_STATIC_TLS
;
676 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
682 case R_LARCH_SOP_PUSH_TLS_TPREL
:
683 if (!bfd_link_executable (info
))
686 info
->flags
|= DF_STATIC_TLS
;
688 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
694 case R_LARCH_SOP_PUSH_ABSOLUTE
:
696 /* If this reloc is in a read-only section, we might
697 need a copy reloc. We can't check reliably at this
698 stage whether the section is read-only, as input
699 sections have not yet been mapped to output sections.
700 Tentatively set the flag for now, and correct in
701 adjust_dynamic_symbol. */
705 case R_LARCH_SOP_PUSH_PCREL
:
710 /* We try to create PLT stub for all non-local function. */
711 if (h
->plt
.refcount
< 0)
717 case R_LARCH_SOP_PUSH_PLT_PCREL
:
718 /* This symbol requires a procedure linkage table entry. We
719 actually build the entry in adjust_dynamic_symbol,
720 because this might be a case of linking PIC code without
721 linking in any dynamic objects, in which case we don't
722 need to generate a procedure linkage table after all. */
726 if (h
->plt
.refcount
< 0)
732 case R_LARCH_TLS_DTPREL32
:
733 case R_LARCH_TLS_DTPREL64
:
738 case R_LARCH_JUMP_SLOT
:
743 /* If resolved symbol is defined in this object,
744 1. Under pie, the symbol is known. We convert it
745 into R_LARCH_RELATIVE and need load-addr still.
746 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
747 3. Under dll, R_LARCH_NN can't be changed normally, since
748 its defination could be covered by the one in executable.
749 For symbolic, we convert it into R_LARCH_RELATIVE.
750 Thus, only under pde, it needs pcrel only. We discard it. */
751 only_need_pcrel
= bfd_link_pde (info
);
757 case R_LARCH_GNU_VTINHERIT
:
758 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
762 case R_LARCH_GNU_VTENTRY
:
763 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
771 /* Record some info for sizing and allocating dynamic entry. */
772 if (need_dynreloc
&& (sec
->flags
& SEC_ALLOC
))
774 /* When creating a shared object, we must copy these
775 relocs into the output file. We create a reloc
776 section in dynobj and make room for the reloc. */
777 struct elf_dyn_relocs
*p
;
778 struct elf_dyn_relocs
**head
;
783 = _bfd_elf_make_dynamic_reloc_section (sec
, htab
->elf
.dynobj
,
784 LARCH_ELF_LOG_WORD_BYTES
,
785 abfd
, /*rela?*/ true);
790 /* If this is a global symbol, we count the number of
791 relocations we need for this symbol. */
793 head
= &((struct loongarch_elf_link_hash_entry
*) h
)->dyn_relocs
;
796 /* Track dynamic relocs needed for local syms too.
797 We really need local syms available to do this
803 s
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
807 vpp
= &elf_section_data (s
)->local_dynrel
;
808 head
= (struct elf_dyn_relocs
**) vpp
;
812 if (p
== NULL
|| p
->sec
!= sec
)
814 bfd_size_type amt
= sizeof *p
;
815 p
= (struct elf_dyn_relocs
*) bfd_alloc (htab
->elf
.dynobj
, amt
);
826 p
->pc_count
+= only_need_pcrel
;
833 /* Find dynamic relocs for H that apply to read-only sections. */
836 readonly_dynrelocs (struct elf_link_hash_entry
*h
)
838 struct elf_dyn_relocs
*p
;
840 for (p
= loongarch_elf_hash_entry (h
)->dyn_relocs
; p
!= NULL
; p
= p
->next
)
842 asection
*s
= p
->sec
->output_section
;
844 if (s
!= NULL
&& (s
->flags
& SEC_READONLY
) != 0)
850 /* Adjust a symbol defined by a dynamic object and referenced by a
851 regular object. The current definition is in some section of the
852 dynamic object, but we're not including those sections. We have to
853 change the definition to something the rest of the link can
856 loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info
*info
,
857 struct elf_link_hash_entry
*h
)
859 struct loongarch_elf_link_hash_table
*htab
;
860 struct loongarch_elf_link_hash_entry
*eh
;
864 htab
= loongarch_elf_hash_table (info
);
865 BFD_ASSERT (htab
!= NULL
);
867 dynobj
= htab
->elf
.dynobj
;
869 /* Make sure we know what is going on here. */
870 BFD_ASSERT (dynobj
!= NULL
871 && (h
->needs_plt
|| h
->type
== STT_GNU_IFUNC
|| h
->is_weakalias
872 || (h
->def_dynamic
&& h
->ref_regular
&& !h
->def_regular
)));
874 /* If this is a function, put it in the procedure linkage table. We
875 will fill in the contents of the procedure linkage table later
876 (although we could actually do it here). */
877 if (h
->type
== STT_FUNC
|| h
->type
== STT_GNU_IFUNC
|| h
->needs_plt
)
879 if (h
->plt
.refcount
< 0
880 || (h
->type
!= STT_GNU_IFUNC
881 && (SYMBOL_REFERENCES_LOCAL (info
, h
)
882 || (ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
883 && h
->root
.type
== bfd_link_hash_undefweak
))))
885 /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
886 in an input file, but the symbol was never referred to by a
887 dynamic object, or if all references were garbage collected.
888 In such a case, we don't actually need to build a PLT entry. */
889 h
->plt
.offset
= MINUS_ONE
;
898 h
->plt
.offset
= MINUS_ONE
;
900 /* If this is a weak symbol, and there is a real definition, the
901 processor independent code will have arranged for us to see the
902 real definition first, and we can just use the same value. */
905 struct elf_link_hash_entry
*def
= weakdef (h
);
906 BFD_ASSERT (def
->root
.type
== bfd_link_hash_defined
);
907 h
->root
.u
.def
.section
= def
->root
.u
.def
.section
;
908 h
->root
.u
.def
.value
= def
->root
.u
.def
.value
;
912 /* This is a reference to a symbol defined by a dynamic object which
913 is not a function. */
915 /* If we are creating a shared library, we must presume that the
916 only references to the symbol are via the global offset table.
917 For such cases we need not do anything here; the relocations will
918 be handled correctly by relocate_section. */
919 if (bfd_link_dll (info
))
922 /* If there are no references to this symbol that do not use the
923 GOT, we don't need to generate a copy reloc. */
927 /* If -z nocopyreloc was given, we won't generate them either. */
928 if (info
->nocopyreloc
)
934 /* If we don't find any dynamic relocs in read-only sections, then
935 we'll be keeping the dynamic relocs and avoiding the copy reloc. */
936 if (!readonly_dynrelocs (h
))
942 /* We must allocate the symbol in our .dynbss section, which will
943 become part of the .bss section of the executable. There will be
944 an entry for this symbol in the .dynsym section. The dynamic
945 object will contain position independent code, so all references
946 from the dynamic object to this symbol will go through the global
947 offset table. The dynamic linker will use the .dynsym entry to
948 determine the address it must put in the global offset table, so
949 both the dynamic object and the regular object will refer to the
950 same memory location for the variable. */
952 /* We must generate a R_LARCH_COPY reloc to tell the dynamic linker
953 to copy the initial value out of the dynamic object and into the
954 runtime process image. We need to remember the offset into the
955 .rel.bss section we are going to use. */
956 eh
= (struct loongarch_elf_link_hash_entry
*) h
;
957 if (eh
->tls_type
& ~GOT_NORMAL
)
960 srel
= htab
->elf
.srelbss
;
962 else if ((h
->root
.u
.def
.section
->flags
& SEC_READONLY
) != 0)
964 s
= htab
->elf
.sdynrelro
;
965 srel
= htab
->elf
.sreldynrelro
;
969 s
= htab
->elf
.sdynbss
;
970 srel
= htab
->elf
.srelbss
;
972 if ((h
->root
.u
.def
.section
->flags
& SEC_ALLOC
) != 0 && h
->size
!= 0)
974 srel
->size
+= sizeof (ElfNN_External_Rela
);
978 return _bfd_elf_adjust_dynamic_copy (info
, h
, s
);
981 /* Allocate space in .plt, .got and associated reloc sections for
985 allocate_dynrelocs (struct elf_link_hash_entry
*h
, void *inf
)
987 struct bfd_link_info
*info
;
988 struct loongarch_elf_link_hash_table
*htab
;
989 struct loongarch_elf_link_hash_entry
*eh
;
990 struct elf_dyn_relocs
*p
;
992 if (h
->root
.type
== bfd_link_hash_indirect
)
995 eh
= (struct loongarch_elf_link_hash_entry
*) h
;
996 info
= (struct bfd_link_info
*) inf
;
997 htab
= loongarch_elf_hash_table (info
);
998 BFD_ASSERT (htab
!= NULL
);
1002 asection
*plt
, *gotplt
, *relplt
;
1011 if (h
->dynindx
== -1 && !h
->forced_local
1012 && !bfd_elf_link_record_dynamic_symbol (info
, h
))
1015 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info
), h
)
1016 && h
->type
!= STT_GNU_IFUNC
)
1019 plt
= htab
->elf
.splt
;
1020 gotplt
= htab
->elf
.sgotplt
;
1021 relplt
= htab
->elf
.srelplt
;
1023 else if (htab
->elf
.iplt
)
1025 /* .iplt only for IFUNC. */
1026 if (h
->type
!= STT_GNU_IFUNC
)
1029 plt
= htab
->elf
.iplt
;
1030 gotplt
= htab
->elf
.igotplt
;
1031 relplt
= htab
->elf
.irelplt
;
1037 plt
->size
= PLT_HEADER_SIZE
;
1039 h
->plt
.offset
= plt
->size
;
1040 plt
->size
+= PLT_ENTRY_SIZE
;
1041 gotplt
->size
+= GOT_ENTRY_SIZE
;
1042 relplt
->size
+= sizeof (ElfNN_External_Rela
);
1049 h
->plt
.offset
= MINUS_ONE
;
1051 if (0 < h
->got
.refcount
)
1055 int tls_type
= loongarch_elf_hash_entry (h
)->tls_type
;
1057 /* Make sure this symbol is output as a dynamic symbol.
1058 Undefined weak syms won't yet be marked as dynamic. */
1059 if (h
->dynindx
== -1 && !h
->forced_local
1060 && !bfd_elf_link_record_dynamic_symbol (info
, h
))
1064 h
->got
.offset
= s
->size
;
1065 dyn
= htab
->elf
.dynamic_sections_created
;
1066 if (tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
1068 /* TLS_GD needs two dynamic relocs and two GOT slots. */
1069 if (tls_type
& GOT_TLS_GD
)
1071 s
->size
+= 2 * GOT_ENTRY_SIZE
;
1072 htab
->elf
.srelgot
->size
+= 2 * sizeof (ElfNN_External_Rela
);
1075 /* TLS_IE needs one dynamic reloc and one GOT slot. */
1076 if (tls_type
& GOT_TLS_IE
)
1078 s
->size
+= GOT_ENTRY_SIZE
;
1079 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1084 s
->size
+= GOT_ENTRY_SIZE
;
1085 if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn
, bfd_link_pic (info
), h
)
1086 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
1087 || h
->type
== STT_GNU_IFUNC
)
1088 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1092 h
->got
.offset
= MINUS_ONE
;
1094 if (eh
->dyn_relocs
== NULL
)
1097 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
1099 struct elf_dyn_relocs
**pp
;
1101 for (pp
= &eh
->dyn_relocs
; (p
= *pp
) != NULL
;)
1103 p
->count
-= p
->pc_count
;
1112 if (h
->root
.type
== bfd_link_hash_undefweak
)
1114 if (UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
1115 eh
->dyn_relocs
= NULL
;
1116 else if (h
->dynindx
== -1 && !h
->forced_local
1117 /* Make sure this symbol is output as a dynamic symbol.
1118 Undefined weak syms won't yet be marked as dynamic. */
1119 && !bfd_elf_link_record_dynamic_symbol (info
, h
))
1123 for (p
= eh
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
1125 asection
*sreloc
= elf_section_data (p
->sec
)->sreloc
;
1126 sreloc
->size
+= p
->count
* sizeof (ElfNN_External_Rela
);
1133 elfNN_loongarch_allocate_local_dynrelocs (void **slot
, void *inf
)
1135 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
1137 if (!h
->def_regular
|| !h
->ref_regular
|| !h
->forced_local
1138 || h
->root
.type
!= bfd_link_hash_defined
)
1141 return allocate_dynrelocs (h
, inf
);
1144 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
1145 read-only sections. */
1148 maybe_set_textrel (struct elf_link_hash_entry
*h
, void *info_p
)
1152 if (h
->root
.type
== bfd_link_hash_indirect
)
1155 sec
= readonly_dynrelocs (h
);
1158 struct bfd_link_info
*info
= (struct bfd_link_info
*) info_p
;
1160 info
->flags
|= DF_TEXTREL
;
1161 info
->callbacks
->minfo (_("%pB: dynamic relocation against `%pT' in "
1162 "read-only section `%pA'\n"),
1163 sec
->owner
, h
->root
.root
.string
, sec
);
1165 /* Not an error, just cut short the traversal. */
1172 loongarch_elf_size_dynamic_sections (bfd
*output_bfd
,
1173 struct bfd_link_info
*info
)
1175 struct loongarch_elf_link_hash_table
*htab
;
1180 htab
= loongarch_elf_hash_table (info
);
1181 BFD_ASSERT (htab
!= NULL
);
1182 dynobj
= htab
->elf
.dynobj
;
1183 BFD_ASSERT (dynobj
!= NULL
);
1185 if (htab
->elf
.dynamic_sections_created
)
1187 /* Set the contents of the .interp section to the interpreter. */
1188 if (bfd_link_executable (info
) && !info
->nointerp
)
1190 const char *interpreter
;
1191 flagword flags
= elf_elfheader (output_bfd
)->e_flags
;
1192 s
= bfd_get_linker_section (dynobj
, ".interp");
1193 BFD_ASSERT (s
!= NULL
);
1194 if (EF_LOONGARCH_IS_ILP32 (flags
))
1195 interpreter
= "/lib32/ld.so.1";
1196 else if (EF_LOONGARCH_IS_LP64 (flags
))
1197 interpreter
= "/lib64/ld.so.1";
1199 interpreter
= "/lib/ld.so.1";
1200 s
->contents
= (unsigned char *) interpreter
;
1201 s
->size
= strlen (interpreter
) + 1;
1205 /* Set up .got offsets for local syms, and space for local dynamic
1207 for (ibfd
= info
->input_bfds
; ibfd
!= NULL
; ibfd
= ibfd
->link
.next
)
1209 bfd_signed_vma
*local_got
;
1210 bfd_signed_vma
*end_local_got
;
1211 char *local_tls_type
;
1212 bfd_size_type locsymcount
;
1213 Elf_Internal_Shdr
*symtab_hdr
;
1216 if (!is_loongarch_elf (ibfd
))
1219 for (s
= ibfd
->sections
; s
!= NULL
; s
= s
->next
)
1221 struct elf_dyn_relocs
*p
;
1223 for (p
= elf_section_data (s
)->local_dynrel
; p
!= NULL
; p
= p
->next
)
1225 p
->count
-= p
->pc_count
;
1226 if (!bfd_is_abs_section (p
->sec
)
1227 && bfd_is_abs_section (p
->sec
->output_section
))
1229 /* Input section has been discarded, either because
1230 it is a copy of a linkonce section or due to
1231 linker script /DISCARD/, so we'll be discarding
1234 else if (0 < p
->count
)
1236 srel
= elf_section_data (p
->sec
)->sreloc
;
1237 srel
->size
+= p
->count
* sizeof (ElfNN_External_Rela
);
1238 if ((p
->sec
->output_section
->flags
& SEC_READONLY
) != 0)
1239 info
->flags
|= DF_TEXTREL
;
1244 local_got
= elf_local_got_refcounts (ibfd
);
1248 symtab_hdr
= &elf_symtab_hdr (ibfd
);
1249 locsymcount
= symtab_hdr
->sh_info
;
1250 end_local_got
= local_got
+ locsymcount
;
1251 local_tls_type
= _bfd_loongarch_elf_local_got_tls_type (ibfd
);
1253 srel
= htab
->elf
.srelgot
;
1254 for (; local_got
< end_local_got
; ++local_got
, ++local_tls_type
)
1258 *local_got
= s
->size
;
1259 s
->size
+= GOT_ENTRY_SIZE
;
1261 if (*local_tls_type
& GOT_TLS_GD
)
1262 s
->size
+= GOT_ENTRY_SIZE
;
1264 /* If R_LARCH_RELATIVE. */
1265 if (bfd_link_pic (info
)
1266 /* Or R_LARCH_TLS_DTPRELNN or R_LARCH_TLS_TPRELNN. */
1267 || (*local_tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
)))
1268 srel
->size
+= sizeof (ElfNN_External_Rela
);
1271 *local_got
= MINUS_ONE
;
1275 /* Allocate global sym .plt and .got entries, and space for global
1276 sym dynamic relocs. */
1277 elf_link_hash_traverse (&htab
->elf
, allocate_dynrelocs
, info
);
1278 /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1279 htab_traverse (htab
->loc_hash_table
,
1280 (void *) elfNN_loongarch_allocate_local_dynrelocs
, info
);
1282 /* Don't allocate .got.plt section if there are no PLT. */
1283 if (htab
->elf
.sgotplt
&& htab
->elf
.sgotplt
->size
== GOTPLT_HEADER_SIZE
1284 && (htab
->elf
.splt
== NULL
|| htab
->elf
.splt
->size
== 0))
1285 htab
->elf
.sgotplt
->size
= 0;
1287 /* The check_relocs and adjust_dynamic_symbol entry points have
1288 determined the sizes of the various dynamic sections. Allocate
1290 for (s
= dynobj
->sections
; s
!= NULL
; s
= s
->next
)
1292 if ((s
->flags
& SEC_LINKER_CREATED
) == 0)
1295 if (s
== htab
->elf
.splt
|| s
== htab
->elf
.iplt
|| s
== htab
->elf
.sgot
1296 || s
== htab
->elf
.sgotplt
|| s
== htab
->elf
.igotplt
1297 || s
== htab
->elf
.sdynbss
|| s
== htab
->elf
.sdynrelro
)
1299 /* Strip this section if we don't need it; see the
1302 else if (strncmp (s
->name
, ".rela", 5) == 0)
1306 /* We use the reloc_count field as a counter if we need
1307 to copy relocs into the output file. */
1313 /* It's not one of our sections. */
1319 /* If we don't need this section, strip it from the
1320 output file. This is mostly to handle .rela.bss and
1321 .rela.plt. We must create both sections in
1322 create_dynamic_sections, because they must be created
1323 before the linker maps input sections to output
1324 sections. The linker does that before
1325 adjust_dynamic_symbol is called, and it is that
1326 function which decides whether anything needs to go
1327 into these sections. */
1328 s
->flags
|= SEC_EXCLUDE
;
1332 if ((s
->flags
& SEC_HAS_CONTENTS
) == 0)
1335 /* Allocate memory for the section contents. Zero the memory
1336 for the benefit of .rela.plt, which has 4 unused entries
1337 at the beginning, and we don't want garbage. */
1338 s
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, s
->size
);
1339 if (s
->contents
== NULL
)
1343 if (elf_hash_table (info
)->dynamic_sections_created
)
1345 /* Add some entries to the .dynamic section. We fill in the
1346 values later, in loongarch_elf_finish_dynamic_sections, but we
1347 must add the entries now so that we get the correct size for
1348 the .dynamic section. The DT_DEBUG entry is filled in by the
1349 dynamic linker and used by the debugger. */
1350 #define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1352 if (bfd_link_executable (info
))
1354 if (!add_dynamic_entry (DT_DEBUG
, 0))
1358 if (htab
->elf
.srelplt
->size
!= 0)
1360 if (!add_dynamic_entry (DT_PLTGOT
, 0)
1361 || !add_dynamic_entry (DT_PLTRELSZ
, 0)
1362 || !add_dynamic_entry (DT_PLTREL
, DT_RELA
)
1363 || !add_dynamic_entry (DT_JMPREL
, 0))
1367 if (!add_dynamic_entry (DT_RELA
, 0)
1368 || !add_dynamic_entry (DT_RELASZ
, 0)
1369 || !add_dynamic_entry (DT_RELAENT
, sizeof (ElfNN_External_Rela
)))
1372 /* If any dynamic relocs apply to a read-only section,
1373 then we need a DT_TEXTREL entry. */
1374 if ((info
->flags
& DF_TEXTREL
) == 0)
1375 elf_link_hash_traverse (&htab
->elf
, maybe_set_textrel
, info
);
1377 if (info
->flags
& DF_TEXTREL
)
1379 if (!add_dynamic_entry (DT_TEXTREL
, 0))
1381 /* Clear the DF_TEXTREL flag. It will be set again if we
1382 write out an actual text relocation; we may not, because
1383 at this point we do not know whether e.g. any .eh_frame
1384 absolute relocations have been converted to PC-relative. */
1385 info
->flags
&= ~DF_TEXTREL
;
1388 #undef add_dynamic_entry
1393 #define LARCH_LD_STACK_DEPTH 16
1394 static int64_t larch_opc_stack
[LARCH_LD_STACK_DEPTH
];
1395 static size_t larch_stack_top
= 0;
1397 static bfd_reloc_status_type
1398 loongarch_push (int64_t val
)
1400 if (LARCH_LD_STACK_DEPTH
<= larch_stack_top
)
1401 return bfd_reloc_outofrange
;
1402 larch_opc_stack
[larch_stack_top
++] = val
;
1403 return bfd_reloc_ok
;
1406 static bfd_reloc_status_type
1407 loongarch_pop (int64_t *val
)
1409 if (larch_stack_top
== 0)
1410 return bfd_reloc_outofrange
;
1412 *val
= larch_opc_stack
[--larch_stack_top
];
1413 return bfd_reloc_ok
;
1416 static bfd_reloc_status_type
1417 loongarch_top (int64_t *val
)
1419 if (larch_stack_top
== 0)
1420 return bfd_reloc_outofrange
;
1422 *val
= larch_opc_stack
[larch_stack_top
- 1];
1423 return bfd_reloc_ok
;
1427 loongarch_elf_append_rela (bfd
*abfd
, asection
*s
, Elf_Internal_Rela
*rel
)
1429 const struct elf_backend_data
*bed
;
1432 bed
= get_elf_backend_data (abfd
);
1433 loc
= s
->contents
+ (s
->reloc_count
++ * bed
->s
->sizeof_rela
);
1434 bed
->s
->swap_reloca_out (abfd
, rel
, loc
);
1437 /* Check rel->r_offset in range of contents. */
1438 static bfd_reloc_status_type
1439 loongarch_check_offset (const Elf_Internal_Rela
*rel
,
1440 const asection
*input_section
)
1442 if (0 == strcmp(input_section
->name
, ".text")
1443 && rel
->r_offset
> input_section
->size
)
1444 return bfd_reloc_overflow
;
1446 return bfd_reloc_ok
;
1450 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1452 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1453 if (ret == bfd_reloc_ok) \
1455 ret = loongarch_pop (&op1); \
1456 if (ret == bfd_reloc_ok) \
1457 ret = loongarch_push (op3); \
1462 #define LARCH_RELOC_UINT32_BIT_MASK(bitsize) \
1463 (~((0x1U << (bitsize)) - 1))
1465 static bfd_reloc_status_type
1466 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela
*rel
,
1467 const asection
*input_section ATTRIBUTE_UNUSED
,
1468 reloc_howto_type
*howto
, bfd
*input_bfd
,
1469 bfd_byte
*contents
, int64_t op
,
1472 /* Check op low bits if rightshift != 0, before rightshift */
1473 if (howto
->rightshift
1474 && (((0x1U
<< howto
->rightshift
) - 1) & op
))
1475 return bfd_reloc_overflow
;
1477 uint32_t imm
= (uint32_t)(int32_t)(op
>> howto
->rightshift
);
1483 if (LARCH_RELOC_UINT32_BIT_MASK (howto
->bitsize
- 1) & imm
)
1484 return bfd_reloc_overflow
;
1488 if ((LARCH_RELOC_UINT32_BIT_MASK (howto
->bitsize
- 1) & imm
)
1489 != LARCH_RELOC_UINT32_BIT_MASK (howto
->bitsize
- 1))
1490 return bfd_reloc_overflow
;
1495 if (LARCH_RELOC_UINT32_BIT_MASK (howto
->bitsize
) & imm
)
1496 return bfd_reloc_overflow
;
1499 int bits
= bfd_get_reloc_size (howto
) * 8;
1500 uint32_t insn
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1502 imm
= imm
& ((0x1U
<< howto
->bitsize
) - 1);
1503 imm
<<= howto
->bitpos
;
1504 insn
= ((insn
& howto
->src_mask
)
1505 | ((insn
& (~(uint32_t) howto
->dst_mask
)) | imm
));
1506 bfd_put (bits
, input_bfd
, insn
, contents
+ rel
->r_offset
);
1508 return bfd_reloc_ok
;
1511 /* Emplace a static relocation. */
1513 static bfd_reloc_status_type
1514 perform_relocation (const Elf_Internal_Rela
*rel
, asection
*input_section
,
1515 reloc_howto_type
*howto
, bfd_vma value
,
1516 bfd
*input_bfd
, bfd_byte
*contents
)
1519 int64_t opr1
, opr2
, opr3
;
1520 bfd_reloc_status_type r
= bfd_reloc_ok
;
1521 int bits
= bfd_get_reloc_size (howto
) * 8;
1524 switch (ELFNN_R_TYPE (rel
->r_info
))
1526 case R_LARCH_SOP_PUSH_PCREL
:
1527 case R_LARCH_SOP_PUSH_ABSOLUTE
:
1528 case R_LARCH_SOP_PUSH_GPREL
:
1529 case R_LARCH_SOP_PUSH_TLS_TPREL
:
1530 case R_LARCH_SOP_PUSH_TLS_GOT
:
1531 case R_LARCH_SOP_PUSH_TLS_GD
:
1532 case R_LARCH_SOP_PUSH_PLT_PCREL
:
1533 r
= loongarch_push (value
);
1536 case R_LARCH_SOP_PUSH_DUP
:
1537 r
= loongarch_pop (&opr1
);
1538 if (r
== bfd_reloc_ok
)
1540 r
= loongarch_push (opr1
);
1541 if (r
== bfd_reloc_ok
)
1542 r
= loongarch_push (opr1
);
1546 case R_LARCH_SOP_ASSERT
:
1547 r
= loongarch_pop (&opr1
);
1548 if (r
!= bfd_reloc_ok
|| !opr1
)
1549 r
= bfd_reloc_notsupported
;
1552 case R_LARCH_SOP_NOT
:
1553 r
= loongarch_pop (&opr1
);
1554 if (r
== bfd_reloc_ok
)
1555 r
= loongarch_push (!opr1
);
1558 case R_LARCH_SOP_SUB
:
1559 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
- opr2
);
1562 case R_LARCH_SOP_SL
:
1563 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
<< opr2
);
1566 case R_LARCH_SOP_SR
:
1567 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
>> opr2
);
1570 case R_LARCH_SOP_AND
:
1571 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
& opr2
);
1574 case R_LARCH_SOP_ADD
:
1575 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
+ opr2
);
1578 case R_LARCH_SOP_IF_ELSE
:
1579 r
= loongarch_pop (&opr3
);
1580 if (r
== bfd_reloc_ok
)
1582 r
= loongarch_pop (&opr2
);
1583 if (r
== bfd_reloc_ok
)
1585 r
= loongarch_pop (&opr1
);
1586 if (r
== bfd_reloc_ok
)
1587 r
= loongarch_push (opr1
? opr2
: opr3
);
1592 case R_LARCH_SOP_POP_32_S_10_5
:
1593 case R_LARCH_SOP_POP_32_S_10_12
:
1594 case R_LARCH_SOP_POP_32_S_10_16
:
1595 case R_LARCH_SOP_POP_32_S_10_16_S2
:
1596 case R_LARCH_SOP_POP_32_S_5_20
:
1597 r
= loongarch_pop (&opr1
);
1598 if (r
!= bfd_reloc_ok
)
1600 r
= loongarch_check_offset (rel
, input_section
);
1601 if (r
!= bfd_reloc_ok
)
1604 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
1606 contents
, opr1
, true);
1609 case R_LARCH_SOP_POP_32_U_10_12
:
1610 r
= loongarch_pop (&opr1
);
1611 if (r
!= bfd_reloc_ok
)
1613 r
= loongarch_check_offset (rel
, input_section
);
1614 if (r
!= bfd_reloc_ok
)
1617 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
1619 contents
, opr1
, false);
1622 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2
:
1624 r
= loongarch_pop (&opr1
);
1625 if (r
!= bfd_reloc_ok
)
1628 if ((opr1
& 0x3) != 0)
1630 r
= bfd_reloc_overflow
;
1634 uint32_t imm
= opr1
>> howto
->rightshift
;
1635 if ((imm
& (~0xfffffU
)) && ((imm
& (~0xfffffU
)) != (~0xfffffU
)))
1637 r
= bfd_reloc_overflow
;
1641 r
= loongarch_check_offset (rel
, input_section
);
1642 if (r
!= bfd_reloc_ok
)
1645 insn1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1646 insn1
= ((insn1
& howto
->src_mask
)
1647 | ((imm
& 0xffffU
) << 10)
1648 | ((imm
& 0x1f0000U
) >> 16));
1649 bfd_put (bits
, input_bfd
, insn1
, contents
+ rel
->r_offset
);
1653 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2
:
1655 r
= loongarch_pop (&opr1
);
1656 if (r
!= bfd_reloc_ok
)
1659 if ((opr1
& 0x3) != 0)
1661 r
= bfd_reloc_overflow
;
1665 uint32_t imm
= opr1
>> howto
->rightshift
;
1666 if ((imm
& (~0x1ffffffU
)) && (imm
& (~0x1ffffffU
)) != (~0x1ffffffU
))
1668 r
= bfd_reloc_overflow
;
1672 r
= loongarch_check_offset (rel
, input_section
);
1673 if (r
!= bfd_reloc_ok
)
1676 insn1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1677 insn1
= ((insn1
& howto
->src_mask
)
1678 | ((imm
& 0xffffU
) << 10)
1679 | ((imm
& 0x3ff0000U
) >> 16));
1680 bfd_put (bits
, input_bfd
, insn1
, contents
+ rel
->r_offset
);
1684 case R_LARCH_SOP_POP_32_U
:
1685 r
= loongarch_pop (&opr1
);
1686 if (r
!= bfd_reloc_ok
)
1688 if ((uint64_t)opr1
& ~(uint64_t) 0xffffffff)
1689 r
= bfd_reloc_overflow
;
1690 if (r
!= bfd_reloc_ok
)
1692 r
= loongarch_check_offset (rel
, input_section
);
1693 if (r
!= bfd_reloc_ok
)
1696 bfd_put (bits
, input_bfd
, opr1
, contents
+ rel
->r_offset
);
1699 case R_LARCH_TLS_DTPREL32
:
1701 case R_LARCH_TLS_DTPREL64
:
1703 r
= loongarch_check_offset (rel
, input_section
);
1704 if (r
!= bfd_reloc_ok
)
1707 bfd_put (bits
, input_bfd
, value
, contents
+ rel
->r_offset
);
1715 r
= loongarch_check_offset (rel
, input_section
);
1716 if (r
!= bfd_reloc_ok
)
1719 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1720 bfd_put (bits
, input_bfd
, opr1
+ value
, contents
+ rel
->r_offset
);
1728 r
= loongarch_check_offset (rel
, input_section
);
1729 if (r
!= bfd_reloc_ok
)
1732 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1733 bfd_put (bits
, input_bfd
, opr1
- value
, contents
+ rel
->r_offset
);
1737 r
= bfd_reloc_notsupported
;
1742 #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
1750 Elf_Internal_Sym
*sym
;
1751 struct elf_link_hash_entry
*h
;
1754 } larch_reloc_queue
[LARCH_RECENT_RELOC_QUEUE_LENGTH
];
1755 static size_t larch_reloc_queue_head
= 0;
1756 static size_t larch_reloc_queue_tail
= 0;
1759 loongarch_sym_name (bfd
*input_bfd
, struct elf_link_hash_entry
*h
,
1760 Elf_Internal_Sym
*sym
)
1762 const char *ret
= NULL
;
1764 ret
= bfd_elf_string_from_elf_section (input_bfd
,
1765 elf_symtab_hdr (input_bfd
).sh_link
,
1768 ret
= h
->root
.root
.string
;
1770 if (ret
== NULL
|| *ret
== '\0')
1776 loongarch_record_one_reloc (bfd
*abfd
, asection
*section
, int r_type
,
1777 bfd_vma r_offset
, Elf_Internal_Sym
*sym
,
1778 struct elf_link_hash_entry
*h
, bfd_vma addend
)
1780 if ((larch_reloc_queue_head
== 0
1781 && larch_reloc_queue_tail
== LARCH_RECENT_RELOC_QUEUE_LENGTH
- 1)
1782 || larch_reloc_queue_head
== larch_reloc_queue_tail
+ 1)
1783 larch_reloc_queue_head
=
1784 (larch_reloc_queue_head
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
1785 larch_reloc_queue
[larch_reloc_queue_tail
].bfd
= abfd
;
1786 larch_reloc_queue
[larch_reloc_queue_tail
].section
= section
;
1787 larch_reloc_queue
[larch_reloc_queue_tail
].r_offset
= r_offset
;
1788 larch_reloc_queue
[larch_reloc_queue_tail
].r_type
= r_type
;
1789 larch_reloc_queue
[larch_reloc_queue_tail
].sym
= sym
;
1790 larch_reloc_queue
[larch_reloc_queue_tail
].h
= h
;
1791 larch_reloc_queue
[larch_reloc_queue_tail
].addend
= addend
;
1792 loongarch_top (&larch_reloc_queue
[larch_reloc_queue_tail
].top_then
);
1793 larch_reloc_queue_tail
=
1794 (larch_reloc_queue_tail
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
1798 loongarch_dump_reloc_record (void (*p
) (const char *fmt
, ...))
1800 size_t i
= larch_reloc_queue_head
;
1802 asection
*section
= NULL
;
1803 bfd_vma r_offset
= 0;
1805 p ("Dump relocate record:\n");
1806 p ("stack top\t\trelocation name\t\tsymbol");
1807 while (i
!= larch_reloc_queue_tail
)
1809 if (a_bfd
!= larch_reloc_queue
[i
].bfd
1810 || section
!= larch_reloc_queue
[i
].section
1811 || r_offset
!= larch_reloc_queue
[i
].r_offset
)
1813 a_bfd
= larch_reloc_queue
[i
].bfd
;
1814 section
= larch_reloc_queue
[i
].section
;
1815 r_offset
= larch_reloc_queue
[i
].r_offset
;
1816 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue
[i
].bfd
,
1817 larch_reloc_queue
[i
].section
, larch_reloc_queue
[i
].r_offset
);
1821 inited
= 1, p ("...\n");
1823 reloc_howto_type
*howto
=
1824 loongarch_elf_rtype_to_howto (larch_reloc_queue
[i
].bfd
,
1825 larch_reloc_queue
[i
].r_type
);
1826 p ("0x%V %s\t`%s'", (bfd_vma
) larch_reloc_queue
[i
].top_then
,
1827 howto
? howto
->name
: "<unknown reloc>",
1828 loongarch_sym_name (larch_reloc_queue
[i
].bfd
, larch_reloc_queue
[i
].h
,
1829 larch_reloc_queue
[i
].sym
));
1831 long addend
= larch_reloc_queue
[i
].addend
;
1833 p (" - %ld", -addend
);
1834 else if (0 < addend
)
1835 p (" + %ld(0x%v)", addend
, larch_reloc_queue
[i
].addend
);
1838 i
= (i
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
1841 "-- Record dump end --\n\n");
1846 loongarch_reloc_is_fatal (struct bfd_link_info
*info
,
1848 asection
*input_section
,
1849 Elf_Internal_Rela
*rel
,
1850 reloc_howto_type
*howto
,
1851 bfd_reloc_status_type rtype
,
1859 /* 'dangerous' means we do it but can't promise it's ok
1860 'unsupport' means out of ability of relocation type
1861 'undefined' means we can't deal with the undefined symbol. */
1862 case bfd_reloc_undefined
:
1863 info
->callbacks
->undefined_symbol (info
, name
, input_bfd
, input_section
,
1864 rel
->r_offset
, true);
1865 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1866 input_bfd
, input_section
, rel
->r_offset
,
1868 is_undefweak
? "[undefweak] " : "", name
, msg
);
1870 case bfd_reloc_dangerous
:
1871 info
->callbacks
->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
1872 input_bfd
, input_section
, rel
->r_offset
,
1874 is_undefweak
? "[undefweak] " : "", name
, msg
);
1877 case bfd_reloc_notsupported
:
1878 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1879 input_bfd
, input_section
, rel
->r_offset
,
1881 is_undefweak
? "[undefweak] " : "", name
, msg
);
1893 loongarch_elf_relocate_section (bfd
*output_bfd
, struct bfd_link_info
*info
,
1894 bfd
*input_bfd
, asection
*input_section
,
1895 bfd_byte
*contents
, Elf_Internal_Rela
*relocs
,
1896 Elf_Internal_Sym
*local_syms
,
1897 asection
**local_sections
)
1899 Elf_Internal_Rela
*rel
;
1900 Elf_Internal_Rela
*relend
;
1902 asection
*sreloc
= elf_section_data (input_section
)->sreloc
;
1903 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
1904 Elf_Internal_Shdr
*symtab_hdr
= &elf_symtab_hdr (input_bfd
);
1905 struct elf_link_hash_entry
**sym_hashes
= elf_sym_hashes (input_bfd
);
1906 bfd_vma
*local_got_offsets
= elf_local_got_offsets (input_bfd
);
1907 bool is_pic
= bfd_link_pic (info
);
1908 bool is_dyn
= elf_hash_table (info
)->dynamic_sections_created
;
1909 asection
*plt
= htab
->elf
.splt
? htab
->elf
.splt
: htab
->elf
.iplt
;
1910 asection
*got
= htab
->elf
.sgot
;
1912 relend
= relocs
+ input_section
->reloc_count
;
1913 for (rel
= relocs
; rel
< relend
; rel
++)
1915 int r_type
= ELFNN_R_TYPE (rel
->r_info
);
1916 unsigned long r_symndx
= ELFNN_R_SYM (rel
->r_info
);
1917 bfd_vma pc
= sec_addr (input_section
) + rel
->r_offset
;
1918 reloc_howto_type
*howto
= NULL
;
1919 asection
*sec
= NULL
;
1920 Elf_Internal_Sym
*sym
= NULL
;
1921 struct elf_link_hash_entry
*h
= NULL
;
1923 bfd_reloc_status_type r
= bfd_reloc_ok
;
1924 bool is_ie
, is_undefweak
, unresolved_reloc
, defined_local
;
1925 bool resolved_local
, resolved_dynly
, resolved_to_const
;
1928 bfd_vma off
, ie_off
;
1931 howto
= loongarch_elf_rtype_to_howto (input_bfd
, r_type
);
1932 if (howto
== NULL
|| r_type
== R_LARCH_GNU_VTINHERIT
1933 || r_type
== R_LARCH_GNU_VTENTRY
)
1936 /* This is a final link. */
1937 if (r_symndx
< symtab_hdr
->sh_info
)
1939 is_undefweak
= false;
1940 unresolved_reloc
= false;
1941 sym
= local_syms
+ r_symndx
;
1942 sec
= local_sections
[r_symndx
];
1943 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
1945 /* Relocate against local STT_GNU_IFUNC symbol. */
1946 if (!bfd_link_relocatable (info
)
1947 && ELF_ST_TYPE (sym
->st_info
) == STT_GNU_IFUNC
)
1949 h
= elfNN_loongarch_get_local_sym_hash (htab
, input_bfd
, rel
,
1954 /* Set STT_GNU_IFUNC symbol value. */
1955 h
->root
.u
.def
.value
= sym
->st_value
;
1956 h
->root
.u
.def
.section
= sec
;
1958 defined_local
= true;
1959 resolved_local
= true;
1960 resolved_dynly
= false;
1961 resolved_to_const
= false;
1962 if (bfd_link_relocatable (info
)
1963 && ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
1964 rel
->r_addend
+= sec
->output_offset
;
1968 bool warned
, ignored
;
1970 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
1971 r_symndx
, symtab_hdr
, sym_hashes
,
1973 unresolved_reloc
, warned
, ignored
);
1974 /* Here means symbol isn't local symbol only and 'h != NULL'. */
1976 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
1977 symbol. And 'dynamic_undefined_weak' specify what to do when
1978 meeting undefweak. */
1980 if ((is_undefweak
= h
->root
.type
== bfd_link_hash_undefweak
))
1982 defined_local
= false;
1983 resolved_local
= false;
1984 resolved_to_const
= (!is_dyn
|| h
->dynindx
== -1
1985 || UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
));
1986 resolved_dynly
= !resolved_local
&& !resolved_to_const
;
1990 /* Symbol undefined offen means failed already. I don't know why
1991 'warned' here but I guess it want to continue relocating as if
1992 no error occures to find other errors as more as possible. */
1994 /* To avoid generating warning messages about truncated
1995 relocations, set the relocation's address to be the same as
1996 the start of this section. */
1997 relocation
= (input_section
->output_section
1998 ? input_section
->output_section
->vma
2001 defined_local
= relocation
!= 0;
2002 resolved_local
= defined_local
;
2003 resolved_to_const
= !resolved_local
;
2004 resolved_dynly
= false;
2008 defined_local
= !unresolved_reloc
&& !ignored
;
2010 defined_local
&& SYMBOL_REFERENCES_LOCAL (info
, h
);
2011 resolved_dynly
= !resolved_local
;
2012 resolved_to_const
= !resolved_local
&& !resolved_dynly
;
2016 name
= loongarch_sym_name (input_bfd
, h
, sym
);
2018 if (sec
!= NULL
&& discarded_section (sec
))
2019 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
, rel
,
2020 1, relend
, howto
, 0, contents
);
2022 if (bfd_link_relocatable (info
))
2025 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2026 from removed linkonce sections, or sections discarded by a linker
2027 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2028 if (r_symndx
== STN_UNDEF
|| bfd_is_abs_section (sec
))
2030 defined_local
= false;
2031 resolved_local
= false;
2032 resolved_dynly
= false;
2033 resolved_to_const
= true;
2036 if (h
&& h
->type
== STT_GNU_IFUNC
)
2038 if (h
->plt
.offset
== MINUS_ONE
)
2039 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against `%s':\n"
2040 "STT_GNU_IFUNC must have PLT stub"
2042 input_bfd
, input_section
,
2043 (bfd_vma
) rel
->r_offset
, howto
->name
, name
);
2044 defined_local
= true;
2045 resolved_local
= true;
2046 resolved_dynly
= false;
2047 resolved_to_const
= false;
2048 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2051 unresolved_reloc
= resolved_dynly
;
2053 BFD_ASSERT (resolved_local
+ resolved_dynly
+ resolved_to_const
== 1);
2055 BFD_ASSERT (!resolved_dynly
|| (h
&& h
->dynindx
!= -1));
2057 BFD_ASSERT (!resolved_local
|| defined_local
);
2062 case R_LARCH_MARK_PCREL
:
2063 case R_LARCH_MARK_LA
:
2065 r
= bfd_reloc_continue
;
2066 unresolved_reloc
= false;
2071 if (resolved_dynly
|| (is_pic
&& resolved_local
))
2073 Elf_Internal_Rela outrel
;
2075 /* When generating a shared object, these relocations are copied
2076 into the output file to be resolved at run time. */
2078 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2082 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2083 && (input_section
->flags
& SEC_ALLOC
));
2085 outrel
.r_offset
+= sec_addr (input_section
);
2088 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2089 outrel
.r_addend
= rel
->r_addend
;
2093 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2094 outrel
.r_addend
= relocation
+ rel
->r_addend
;
2097 if (unresolved_reloc
)
2098 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2101 relocation
+= rel
->r_addend
;
2115 fatal
= (loongarch_reloc_is_fatal
2116 (info
, input_bfd
, input_section
, rel
, howto
,
2117 bfd_reloc_undefined
, is_undefweak
, name
,
2118 "Can't be resolved dynamically. "
2119 "If this procedure is hand-written assembly,\n"
2120 "there must be something like '.dword sym1 - sym2' "
2121 "to generate these relocs\n"
2122 "and we can't get known link-time address of "
2125 relocation
+= rel
->r_addend
;
2128 case R_LARCH_TLS_DTPREL32
:
2129 case R_LARCH_TLS_DTPREL64
:
2132 Elf_Internal_Rela outrel
;
2134 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2137 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2138 && (input_section
->flags
& SEC_ALLOC
));
2139 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2140 outrel
.r_offset
+= sec_addr (input_section
);
2141 outrel
.r_addend
= rel
->r_addend
;
2142 if (unresolved_reloc
)
2143 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2147 if (resolved_to_const
)
2148 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
, input_section
,
2150 bfd_reloc_notsupported
,
2155 case R_LARCH_SOP_PUSH_TLS_TPREL
:
2158 if (!elf_hash_table (info
)->tls_sec
)
2159 fatal
= (loongarch_reloc_is_fatal
2160 (info
, input_bfd
, input_section
, rel
, howto
,
2161 bfd_reloc_notsupported
, is_undefweak
, name
,
2162 "TLS section not be created"));
2164 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
2167 fatal
= (loongarch_reloc_is_fatal
2168 (info
, input_bfd
, input_section
, rel
, howto
,
2169 bfd_reloc_undefined
, is_undefweak
, name
,
2170 "TLS LE just can be resolved local only."));
2173 case R_LARCH_SOP_PUSH_ABSOLUTE
:
2177 fatal
= (loongarch_reloc_is_fatal
2178 (info
, input_bfd
, input_section
, rel
, howto
,
2179 bfd_reloc_dangerous
, is_undefweak
, name
,
2180 "Someone require us to resolve undefweak "
2181 "symbol dynamically. \n"
2182 "But this reloc can't be done. "
2183 "I think I can't throw error "
2185 "so I resolved it to 0. "
2186 "I suggest to re-compile with '-fpic'."));
2189 unresolved_reloc
= false;
2193 if (resolved_to_const
)
2195 relocation
+= rel
->r_addend
;
2201 fatal
= (loongarch_reloc_is_fatal
2202 (info
, input_bfd
, input_section
, rel
, howto
,
2203 bfd_reloc_notsupported
, is_undefweak
, name
,
2204 "Under PIC we don't know load address. Re-compile "
2211 if (!(plt
&& h
&& h
->plt
.offset
!= MINUS_ONE
))
2213 fatal
= (loongarch_reloc_is_fatal
2214 (info
, input_bfd
, input_section
, rel
, howto
,
2215 bfd_reloc_undefined
, is_undefweak
, name
,
2216 "Can't be resolved dynamically. Try to re-compile "
2221 if (rel
->r_addend
!= 0)
2223 fatal
= (loongarch_reloc_is_fatal
2224 (info
, input_bfd
, input_section
, rel
, howto
,
2225 bfd_reloc_notsupported
, is_undefweak
, name
,
2226 "Shouldn't be with r_addend."));
2230 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2231 unresolved_reloc
= false;
2237 relocation
+= rel
->r_addend
;
2243 case R_LARCH_SOP_PUSH_PCREL
:
2244 case R_LARCH_SOP_PUSH_PLT_PCREL
:
2245 unresolved_reloc
= false;
2247 if (resolved_to_const
)
2249 relocation
+= rel
->r_addend
;
2252 else if (is_undefweak
)
2258 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
2261 fatal
= (loongarch_reloc_is_fatal
2262 (info
, input_bfd
, input_section
, rel
, howto
,
2263 bfd_reloc_dangerous
, is_undefweak
, name
,
2264 "Undefweak need to be resolved dynamically, "
2265 "but PLT stub doesn't represent."));
2270 if (!(defined_local
|| (h
&& h
->plt
.offset
!= MINUS_ONE
)))
2272 fatal
= (loongarch_reloc_is_fatal
2273 (info
, input_bfd
, input_section
, rel
, howto
,
2274 bfd_reloc_undefined
, is_undefweak
, name
,
2275 "PLT stub does not represent and "
2276 "symbol not defined."));
2282 else /* if (resolved_dynly) */
2284 if (!(h
&& h
->plt
.offset
!= MINUS_ONE
))
2285 fatal
= (loongarch_reloc_is_fatal
2286 (info
, input_bfd
, input_section
, rel
, howto
,
2287 bfd_reloc_dangerous
, is_undefweak
, name
,
2288 "Internal: PLT stub doesn't represent. "
2289 "Resolve it with pcrel"));
2296 if ((i
& 1) == 0 && defined_local
)
2299 relocation
+= rel
->r_addend
;
2303 if ((i
& 1) && h
&& h
->plt
.offset
!= MINUS_ONE
)
2305 if (rel
->r_addend
!= 0)
2307 fatal
= (loongarch_reloc_is_fatal
2308 (info
, input_bfd
, input_section
, rel
, howto
,
2309 bfd_reloc_notsupported
, is_undefweak
, name
,
2310 "PLT shouldn't be with r_addend."));
2313 relocation
= sec_addr (plt
) + h
->plt
.offset
- pc
;
2319 case R_LARCH_SOP_PUSH_GPREL
:
2320 unresolved_reloc
= false;
2322 if (rel
->r_addend
!= 0)
2324 fatal
= (loongarch_reloc_is_fatal
2325 (info
, input_bfd
, input_section
, rel
, howto
,
2326 bfd_reloc_notsupported
, is_undefweak
, name
,
2327 "Shouldn't be with r_addend."));
2333 off
= h
->got
.offset
;
2335 if (off
== MINUS_ONE
)
2337 fatal
= (loongarch_reloc_is_fatal
2338 (info
, input_bfd
, input_section
, rel
, howto
,
2339 bfd_reloc_notsupported
, is_undefweak
, name
,
2340 "Internal: GOT entry doesn't represent."));
2344 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn
, is_pic
, h
)
2345 || (is_pic
&& SYMBOL_REFERENCES_LOCAL (info
, h
)))
2347 /* This is actually a static link, or it is a
2348 -Bsymbolic link and the symbol is defined
2349 locally, or the symbol was forced to be local
2350 because of a version file. We must initialize
2351 this entry in the global offset table. Since the
2352 offset must always be a multiple of the word size,
2353 we use the least significant bit to record whether
2354 we have initialized it already.
2356 When doing a dynamic link, we create a .rela.got
2357 relocation entry to initialize the value. This
2358 is done in the finish_dynamic_symbol routine. */
2362 fatal
= (loongarch_reloc_is_fatal
2363 (info
, input_bfd
, input_section
, rel
, howto
,
2364 bfd_reloc_dangerous
, is_undefweak
, name
,
2365 "Internal: here shouldn't dynamic."));
2368 if (!(defined_local
|| resolved_to_const
))
2370 fatal
= (loongarch_reloc_is_fatal
2371 (info
, input_bfd
, input_section
, rel
, howto
,
2372 bfd_reloc_undefined
, is_undefweak
, name
,
2381 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2388 if (!local_got_offsets
)
2390 fatal
= (loongarch_reloc_is_fatal
2391 (info
, input_bfd
, input_section
, rel
, howto
,
2392 bfd_reloc_notsupported
, is_undefweak
, name
,
2393 "Internal: local got offsets not reporesent."));
2397 off
= local_got_offsets
[r_symndx
];
2399 if (off
== MINUS_ONE
)
2401 fatal
= (loongarch_reloc_is_fatal
2402 (info
, input_bfd
, input_section
, rel
, howto
,
2403 bfd_reloc_notsupported
, is_undefweak
, name
,
2404 "Internal: GOT entry doesn't represent."));
2408 /* The offset must always be a multiple of the word size.
2409 So, we can use the least significant bit to record
2410 whether we have already processed this entry. */
2418 Elf_Internal_Rela outrel
;
2419 /* We need to generate a R_LARCH_RELATIVE reloc
2420 for the dynamic linker. */
2421 s
= htab
->elf
.srelgot
;
2424 fatal
= (loongarch_reloc_is_fatal
2425 (info
, input_bfd
, input_section
, rel
, howto
,
2426 bfd_reloc_notsupported
, is_undefweak
, name
,
2427 "Internal: '.rel.got' not represent"));
2431 outrel
.r_offset
= sec_addr (got
) + off
;
2432 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2433 outrel
.r_addend
= relocation
; /* Link-time addr. */
2434 loongarch_elf_append_rela (output_bfd
, s
, &outrel
);
2437 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2438 local_got_offsets
[r_symndx
] |= 1;
2444 case R_LARCH_SOP_PUSH_TLS_GOT
:
2445 case R_LARCH_SOP_PUSH_TLS_GD
:
2446 if (r_type
== R_LARCH_SOP_PUSH_TLS_GOT
)
2448 unresolved_reloc
= false;
2450 if (rel
->r_addend
!= 0)
2452 fatal
= (loongarch_reloc_is_fatal
2453 (info
, input_bfd
, input_section
, rel
, howto
,
2454 bfd_reloc_notsupported
, is_undefweak
, name
,
2455 "Shouldn't be with r_addend."));
2460 if (resolved_to_const
&& is_undefweak
&& h
->dynindx
!= -1)
2462 /* What if undefweak? Let rtld make a decision. */
2463 resolved_to_const
= resolved_local
= false;
2464 resolved_dynly
= true;
2467 if (resolved_to_const
)
2469 fatal
= (loongarch_reloc_is_fatal
2470 (info
, input_bfd
, input_section
, rel
, howto
,
2471 bfd_reloc_notsupported
, is_undefweak
, name
,
2472 "Internal: Shouldn't be resolved to const."));
2478 off
= h
->got
.offset
;
2483 off
= local_got_offsets
[r_symndx
];
2484 local_got_offsets
[r_symndx
] |= 1;
2487 if (off
== MINUS_ONE
)
2489 fatal
= (loongarch_reloc_is_fatal
2490 (info
, input_bfd
, input_section
, rel
, howto
,
2491 bfd_reloc_notsupported
, is_undefweak
, name
,
2492 "Internal: TLS GOT entry doesn't represent."));
2496 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
2498 /* If this symbol is referenced by both GD and IE TLS, the IE
2499 reference's GOT slot follows the GD reference's slots. */
2501 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
2502 ie_off
= 2 * GOT_ENTRY_SIZE
;
2508 bfd_vma tls_block_off
= 0;
2509 Elf_Internal_Rela outrel
;
2513 if (!elf_hash_table (info
)->tls_sec
)
2515 fatal
= (loongarch_reloc_is_fatal
2516 (info
, input_bfd
, input_section
, rel
, howto
,
2517 bfd_reloc_notsupported
, is_undefweak
, name
,
2518 "Internal: TLS sec not represent."));
2522 relocation
- elf_hash_table (info
)->tls_sec
->vma
;
2525 if (tls_type
& GOT_TLS_GD
)
2527 outrel
.r_offset
= sec_addr (got
) + off
;
2528 outrel
.r_addend
= 0;
2529 bfd_put_NN (output_bfd
, 0, got
->contents
+ off
);
2530 if (resolved_local
&& bfd_link_executable (info
))
2531 bfd_put_NN (output_bfd
, 1, got
->contents
+ off
);
2532 else if (resolved_local
/* && !bfd_link_executable (info) */)
2534 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN
);
2535 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2538 else /* if (resolved_dynly) */
2541 ELFNN_R_INFO (h
->dynindx
, R_LARCH_TLS_DTPMODNN
);
2542 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2546 outrel
.r_offset
+= GOT_ENTRY_SIZE
;
2547 bfd_put_NN (output_bfd
, tls_block_off
,
2548 got
->contents
+ off
+ GOT_ENTRY_SIZE
);
2550 /* DTPREL known. */;
2551 else /* if (resolved_dynly) */
2554 ELFNN_R_INFO (h
->dynindx
, R_LARCH_TLS_DTPRELNN
);
2555 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2560 if (tls_type
& GOT_TLS_IE
)
2562 outrel
.r_offset
= sec_addr (got
) + off
+ ie_off
;
2563 bfd_put_NN (output_bfd
, tls_block_off
,
2564 got
->contents
+ off
+ ie_off
);
2565 if (resolved_local
&& bfd_link_executable (info
))
2567 else if (resolved_local
/* && !bfd_link_executable (info) */)
2569 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN
);
2570 outrel
.r_addend
= tls_block_off
;
2571 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2574 else /* if (resolved_dynly) */
2577 ELFNN_R_INFO (h
->dynindx
, R_LARCH_TLS_TPRELNN
);
2578 outrel
.r_addend
= 0;
2579 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2585 relocation
= off
+ (is_ie
? ie_off
: 0);
2597 /* 'unresolved_reloc' means we haven't done it yet.
2598 We need help of dynamic linker to fix this memory location up. */
2599 if (!unresolved_reloc
)
2602 if (_bfd_elf_section_offset (output_bfd
, info
, input_section
,
2603 rel
->r_offset
) == MINUS_ONE
)
2604 /* WHY? May because it's invalid so skip checking.
2605 But why dynamic reloc a invalid section? */
2608 if (input_section
->output_section
->flags
& SEC_DEBUGGING
)
2610 fatal
= (loongarch_reloc_is_fatal
2611 (info
, input_bfd
, input_section
, rel
, howto
,
2612 bfd_reloc_dangerous
, is_undefweak
, name
,
2613 "Seems dynamic linker not process "
2614 "sections 'SEC_DEBUGGING'."));
2619 if ((info
->flags
& DF_TEXTREL
) == 0)
2620 if (input_section
->output_section
->flags
& SEC_READONLY
)
2621 info
->flags
|= DF_TEXTREL
;
2628 loongarch_record_one_reloc (input_bfd
, input_section
, r_type
,
2629 rel
->r_offset
, sym
, h
, rel
->r_addend
);
2631 if (r
!= bfd_reloc_continue
)
2632 r
= perform_relocation (rel
, input_section
, howto
, relocation
,
2633 input_bfd
, contents
);
2637 case bfd_reloc_dangerous
:
2638 case bfd_reloc_continue
:
2642 case bfd_reloc_overflow
:
2643 /* Overflow value can't be filled in. */
2644 loongarch_dump_reloc_record (info
->callbacks
->info
);
2645 info
->callbacks
->reloc_overflow
2646 (info
, h
? &h
->root
: NULL
, name
, howto
->name
, rel
->r_addend
,
2647 input_bfd
, input_section
, rel
->r_offset
);
2650 case bfd_reloc_outofrange
:
2651 /* Stack state incorrect. */
2652 loongarch_dump_reloc_record (info
->callbacks
->info
);
2653 info
->callbacks
->info
2654 ("%X%H: Internal stack state is incorrect.\n"
2655 "Want to push to full stack or pop from empty stack?\n",
2656 input_bfd
, input_section
, rel
->r_offset
);
2659 case bfd_reloc_notsupported
:
2660 info
->callbacks
->info ("%X%H: Unknown relocation type.\n", input_bfd
,
2661 input_section
, rel
->r_offset
);
2665 info
->callbacks
->info ("%X%H: Internal: unknown error.\n", input_bfd
,
2666 input_section
, rel
->r_offset
);
2677 /* Finish up dynamic symbol handling. We set the contents of various
2678 dynamic sections here. */
2681 loongarch_elf_finish_dynamic_symbol (bfd
*output_bfd
,
2682 struct bfd_link_info
*info
,
2683 struct elf_link_hash_entry
*h
,
2684 Elf_Internal_Sym
*sym
)
2686 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
2687 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
2688 asection
*plt
= NULL
;
2690 if (h
->plt
.offset
!= MINUS_ONE
)
2693 asection
*gotplt
, *relplt
;
2694 bfd_vma got_address
;
2695 uint32_t plt_entry
[PLT_ENTRY_INSNS
];
2697 Elf_Internal_Rela rela
;
2699 plt_idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
) / PLT_ENTRY_SIZE
;
2701 /* One of '.plt' and '.iplt' represents. */
2702 BFD_ASSERT (!!htab
->elf
.splt
^ !!htab
->elf
.iplt
);
2706 BFD_ASSERT ((h
->type
== STT_GNU_IFUNC
2707 && SYMBOL_REFERENCES_LOCAL (info
, h
))
2708 || h
->dynindx
!= -1);
2710 plt
= htab
->elf
.splt
;
2711 gotplt
= htab
->elf
.sgotplt
;
2712 relplt
= htab
->elf
.srelplt
;
2714 sec_addr (gotplt
) + GOTPLT_HEADER_SIZE
+ plt_idx
* GOT_ENTRY_SIZE
;
2716 else /* if (htab->elf.iplt) */
2718 BFD_ASSERT (h
->type
== STT_GNU_IFUNC
2719 && SYMBOL_REFERENCES_LOCAL (info
, h
));
2721 plt
= htab
->elf
.iplt
;
2722 gotplt
= htab
->elf
.igotplt
;
2723 relplt
= htab
->elf
.irelplt
;
2724 got_address
= sec_addr (gotplt
) + plt_idx
* GOT_ENTRY_SIZE
;
2727 /* Find out where the .plt entry should go. */
2728 loc
= plt
->contents
+ h
->plt
.offset
;
2730 /* Fill in the PLT entry itself. */
2731 if (!loongarch_make_plt_entry (got_address
,
2732 sec_addr (plt
) + h
->plt
.offset
,
2736 for (i
= 0; i
< PLT_ENTRY_INSNS
; i
++)
2737 bfd_put_32 (output_bfd
, plt_entry
[i
], loc
+ 4 * i
);
2739 /* Fill in the initial value of the .got.plt entry. */
2740 loc
= gotplt
->contents
+ (got_address
- sec_addr (gotplt
));
2741 bfd_put_NN (output_bfd
, sec_addr (plt
), loc
);
2743 rela
.r_offset
= got_address
;
2744 if (h
->type
== STT_GNU_IFUNC
&& SYMBOL_REFERENCES_LOCAL (info
, h
))
2746 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
2747 rela
.r_addend
= (h
->root
.u
.def
.value
2748 + h
->root
.u
.def
.section
->output_section
->vma
2749 + h
->root
.u
.def
.section
->output_offset
);
2753 /* Fill in the entry in the .rela.plt section. */
2754 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_JUMP_SLOT
);
2758 loc
= relplt
->contents
+ plt_idx
* sizeof (ElfNN_External_Rela
);
2759 bed
->s
->swap_reloca_out (output_bfd
, &rela
, loc
);
2761 if (!h
->def_regular
)
2763 /* Mark the symbol as undefined, rather than as defined in
2764 the .plt section. Leave the value alone. */
2765 sym
->st_shndx
= SHN_UNDEF
;
2766 /* If the symbol is weak, we do need to clear the value.
2767 Otherwise, the PLT entry would provide a definition for
2768 the symbol even if the symbol wasn't defined anywhere,
2769 and so the symbol would never be NULL. */
2770 if (!h
->ref_regular_nonweak
)
2775 if (h
->got
.offset
!= MINUS_ONE
2776 /* TLS got entry have been handled in elf_relocate_section. */
2777 && !(loongarch_elf_hash_entry (h
)->tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
2778 /* have allocated got entry but not allocated rela before. */
2779 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
2781 asection
*sgot
, *srela
;
2782 Elf_Internal_Rela rela
;
2783 bfd_vma off
= h
->got
.offset
& ~(bfd_vma
) 1;
2785 /* This symbol has an entry in the GOT. Set it up. */
2787 sgot
= htab
->elf
.sgot
;
2788 srela
= htab
->elf
.srelgot
;
2789 BFD_ASSERT (sgot
&& srela
);
2791 rela
.r_offset
= sec_addr (sgot
) + off
;
2793 if (h
->type
== STT_GNU_IFUNC
)
2795 if (elf_hash_table (info
)->dynamic_sections_created
2796 && SYMBOL_REFERENCES_LOCAL (info
, h
))
2798 asection
*sec
= h
->root
.u
.def
.section
;
2799 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
2800 rela
.r_addend
= (h
->root
.u
.def
.value
+ sec
->output_section
->vma
2801 + sec
->output_offset
);
2802 bfd_put_NN (output_bfd
, 0, sgot
->contents
+ off
);
2808 = ELFNN_R_INFO (0, (bfd_link_pic (info
)
2809 ? R_LARCH_RELATIVE
: R_LARCH_NONE
));
2811 plt
->output_section
->vma
+ plt
->output_offset
+ h
->plt
.offset
;
2812 bfd_put_NN (output_bfd
, rela
.r_addend
, sgot
->contents
+ off
);
2815 else if (bfd_link_pic (info
) && SYMBOL_REFERENCES_LOCAL (info
, h
))
2817 BFD_ASSERT (h
->got
.offset
& 1 /* Has been filled in addr. */);
2818 asection
*sec
= h
->root
.u
.def
.section
;
2819 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2820 rela
.r_addend
= (h
->root
.u
.def
.value
+ sec
->output_section
->vma
2821 + sec
->output_offset
);
2825 BFD_ASSERT ((h
->got
.offset
& 1) == 0);
2826 BFD_ASSERT (h
->dynindx
!= -1);
2827 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
2831 loongarch_elf_append_rela (output_bfd
, srela
, &rela
);
2836 Elf_Internal_Rela rela
;
2839 /* This symbols needs a copy reloc. Set it up. */
2840 BFD_ASSERT (h
->dynindx
!= -1);
2842 rela
.r_offset
= sec_addr (h
->root
.u
.def
.section
) + h
->root
.u
.def
.value
;
2843 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_COPY
);
2845 if (h
->root
.u
.def
.section
== htab
->elf
.sdynrelro
)
2846 s
= htab
->elf
.sreldynrelro
;
2848 s
= htab
->elf
.srelbss
;
2849 loongarch_elf_append_rela (output_bfd
, s
, &rela
);
2852 /* Mark some specially defined symbols as absolute. */
2853 if (h
== htab
->elf
.hdynamic
|| h
== htab
->elf
.hgot
|| h
== htab
->elf
.hplt
)
2854 sym
->st_shndx
= SHN_ABS
;
2859 /* Finish up the dynamic sections. */
2862 loongarch_finish_dyn (bfd
*output_bfd
, struct bfd_link_info
*info
, bfd
*dynobj
,
2865 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
2866 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
2867 size_t dynsize
= bed
->s
->sizeof_dyn
, skipped_size
= 0;
2868 bfd_byte
*dyncon
, *dynconend
;
2870 dynconend
= sdyn
->contents
+ sdyn
->size
;
2871 for (dyncon
= sdyn
->contents
; dyncon
< dynconend
; dyncon
+= dynsize
)
2873 Elf_Internal_Dyn dyn
;
2877 bed
->s
->swap_dyn_in (dynobj
, dyncon
, &dyn
);
2882 s
= htab
->elf
.sgotplt
;
2883 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
2886 s
= htab
->elf
.srelplt
;
2887 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
2890 s
= htab
->elf
.srelplt
;
2891 dyn
.d_un
.d_val
= s
->size
;
2894 if ((info
->flags
& DF_TEXTREL
) == 0)
2898 if ((info
->flags
& DF_TEXTREL
) == 0)
2899 dyn
.d_un
.d_val
&= ~DF_TEXTREL
;
2903 skipped_size
+= dynsize
;
2905 bed
->s
->swap_dyn_out (output_bfd
, &dyn
, dyncon
- skipped_size
);
2907 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
2908 memset (dyncon
- skipped_size
, 0, skipped_size
);
2912 /* Finish up local dynamic symbol handling. We set the contents of
2913 various dynamic sections here. */
2916 elfNN_loongarch_finish_local_dynamic_symbol (void **slot
, void *inf
)
2918 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
2919 struct bfd_link_info
*info
= (struct bfd_link_info
*) inf
;
2921 return loongarch_elf_finish_dynamic_symbol (info
->output_bfd
, info
, h
, NULL
);
2925 loongarch_elf_finish_dynamic_sections (bfd
*output_bfd
,
2926 struct bfd_link_info
*info
)
2929 asection
*sdyn
, *plt
, *gotplt
= NULL
;
2930 struct loongarch_elf_link_hash_table
*htab
;
2932 htab
= loongarch_elf_hash_table (info
);
2934 dynobj
= htab
->elf
.dynobj
;
2935 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
2937 if (elf_hash_table (info
)->dynamic_sections_created
)
2939 BFD_ASSERT (htab
->elf
.splt
&& sdyn
);
2941 if (!loongarch_finish_dyn (output_bfd
, info
, dynobj
, sdyn
))
2945 if ((plt
= htab
->elf
.splt
))
2946 gotplt
= htab
->elf
.sgotplt
;
2947 else if ((plt
= htab
->elf
.iplt
))
2948 gotplt
= htab
->elf
.igotplt
;
2950 if (plt
&& 0 < plt
->size
)
2953 uint32_t plt_header
[PLT_HEADER_INSNS
];
2954 if (!loongarch_make_plt_header (sec_addr (gotplt
), sec_addr (plt
),
2958 for (i
= 0; i
< PLT_HEADER_INSNS
; i
++)
2959 bfd_put_32 (output_bfd
, plt_header
[i
], plt
->contents
+ 4 * i
);
2961 elf_section_data (plt
->output_section
)->this_hdr
.sh_entsize
=
2965 if (htab
->elf
.sgotplt
)
2967 asection
*output_section
= htab
->elf
.sgotplt
->output_section
;
2969 if (bfd_is_abs_section (output_section
))
2971 _bfd_error_handler (_("discarded output section: `%pA'"),
2976 if (0 < htab
->elf
.sgotplt
->size
)
2978 /* Write the first two entries in .got.plt, needed for the dynamic
2980 bfd_put_NN (output_bfd
, MINUS_ONE
, htab
->elf
.sgotplt
->contents
);
2982 bfd_put_NN (output_bfd
, (bfd_vma
) 0,
2983 htab
->elf
.sgotplt
->contents
+ GOT_ENTRY_SIZE
);
2986 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
2991 asection
*output_section
= htab
->elf
.sgot
->output_section
;
2993 if (0 < htab
->elf
.sgot
->size
)
2995 /* Set the first entry in the global offset table to the address of
2996 the dynamic section. */
2997 bfd_vma val
= sdyn
? sec_addr (sdyn
) : 0;
2998 bfd_put_NN (output_bfd
, val
, htab
->elf
.sgot
->contents
);
3001 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
3004 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
3005 htab_traverse (htab
->loc_hash_table
,
3006 (void *) elfNN_loongarch_finish_local_dynamic_symbol
, info
);
3011 /* Return address for Ith PLT stub in section PLT, for relocation REL
3012 or (bfd_vma) -1 if it should not be included. */
3015 loongarch_elf_plt_sym_val (bfd_vma i
, const asection
*plt
,
3016 const arelent
*rel ATTRIBUTE_UNUSED
)
3018 return plt
->vma
+ PLT_HEADER_SIZE
+ i
* PLT_ENTRY_SIZE
;
3021 static enum elf_reloc_type_class
3022 loongarch_reloc_type_class (const struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
3023 const asection
*rel_sec ATTRIBUTE_UNUSED
,
3024 const Elf_Internal_Rela
*rela
)
3026 struct loongarch_elf_link_hash_table
*htab
;
3027 htab
= loongarch_elf_hash_table (info
);
3029 if (htab
->elf
.dynsym
!= NULL
&& htab
->elf
.dynsym
->contents
!= NULL
)
3031 /* Check relocation against STT_GNU_IFUNC symbol if there are
3033 bfd
*abfd
= info
->output_bfd
;
3034 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
3035 unsigned long r_symndx
= ELFNN_R_SYM (rela
->r_info
);
3036 if (r_symndx
!= STN_UNDEF
)
3038 Elf_Internal_Sym sym
;
3039 if (!bed
->s
->swap_symbol_in (abfd
,
3040 htab
->elf
.dynsym
->contents
3041 + r_symndx
* bed
->s
->sizeof_sym
,
3044 /* xgettext:c-format */
3045 _bfd_error_handler (_("%pB symbol number %lu references"
3046 " nonexistent SHT_SYMTAB_SHNDX section"),
3048 /* Ideally an error class should be returned here. */
3050 else if (ELF_ST_TYPE (sym
.st_info
) == STT_GNU_IFUNC
)
3051 return reloc_class_ifunc
;
3055 switch (ELFNN_R_TYPE (rela
->r_info
))
3057 case R_LARCH_IRELATIVE
:
3058 return reloc_class_ifunc
;
3059 case R_LARCH_RELATIVE
:
3060 return reloc_class_relative
;
3061 case R_LARCH_JUMP_SLOT
:
3062 return reloc_class_plt
;
3064 return reloc_class_copy
;
3066 return reloc_class_normal
;
3070 /* Copy the extra info we tack onto an elf_link_hash_entry. */
3073 loongarch_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
3074 struct elf_link_hash_entry
*dir
,
3075 struct elf_link_hash_entry
*ind
)
3077 struct loongarch_elf_link_hash_entry
*edir
, *eind
;
3079 edir
= (struct loongarch_elf_link_hash_entry
*) dir
;
3080 eind
= (struct loongarch_elf_link_hash_entry
*) ind
;
3082 if (eind
->dyn_relocs
!= NULL
)
3084 if (edir
->dyn_relocs
!= NULL
)
3086 struct elf_dyn_relocs
**pp
;
3087 struct elf_dyn_relocs
*p
;
3089 /* Add reloc counts against the indirect sym to the direct sym
3090 list. Merge any entries against the same section. */
3091 for (pp
= &eind
->dyn_relocs
; (p
= *pp
) != NULL
;)
3093 struct elf_dyn_relocs
*q
;
3095 for (q
= edir
->dyn_relocs
; q
!= NULL
; q
= q
->next
)
3096 if (q
->sec
== p
->sec
)
3098 q
->pc_count
+= p
->pc_count
;
3099 q
->count
+= p
->count
;
3106 *pp
= edir
->dyn_relocs
;
3109 edir
->dyn_relocs
= eind
->dyn_relocs
;
3110 eind
->dyn_relocs
= NULL
;
3113 if (ind
->root
.type
== bfd_link_hash_indirect
&& dir
->got
.refcount
< 0)
3115 edir
->tls_type
= eind
->tls_type
;
3116 eind
->tls_type
= GOT_UNKNOWN
;
3118 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
3121 #define PRSTATUS_SIZE 0x1d8
3122 #define PRSTATUS_OFFSET_PR_CURSIG 0xc
3123 #define PRSTATUS_OFFSET_PR_PID 0x20
3124 #define ELF_GREGSET_T_SIZE 0x168
3125 #define PRSTATUS_OFFSET_PR_REG 0x70
3127 /* Support for core dump NOTE sections. */
3130 loongarch_elf_grok_prstatus (bfd
*abfd
, Elf_Internal_Note
*note
)
3132 switch (note
->descsz
)
3137 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
3140 elf_tdata (abfd
)->core
->signal
=
3141 bfd_get_16 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_CURSIG
);
3144 elf_tdata (abfd
)->core
->lwpid
=
3145 bfd_get_32 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_PID
);
3149 /* Make a ".reg/999" section. */
3150 return _bfd_elfcore_make_pseudosection (abfd
, ".reg", ELF_GREGSET_T_SIZE
,
3152 + PRSTATUS_OFFSET_PR_REG
);
3155 #define PRPSINFO_SIZE 0x88
3156 #define PRPSINFO_OFFSET_PR_PID 0x18
3157 #define PRPSINFO_OFFSET_PR_FNAME 0x28
3158 #define PRPSINFO_SIZEOF_PR_FNAME 0x10
3159 #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
3160 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
3164 loongarch_elf_grok_psinfo (bfd
*abfd
, Elf_Internal_Note
*note
)
3166 switch (note
->descsz
)
3171 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
3174 elf_tdata (abfd
)->core
->pid
=
3175 bfd_get_32 (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PID
);
3178 elf_tdata (abfd
)->core
->program
=
3179 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_FNAME
,
3180 PRPSINFO_SIZEOF_PR_FNAME
);
3183 elf_tdata (abfd
)->core
->command
=
3184 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PS_ARGS
,
3185 PRPSINFO_SIZEOF_PR_PS_ARGS
);
3189 /* Note that for some reason, a spurious space is tacked
3190 onto the end of the args in some (at least one anyway)
3191 implementations, so strip it off if it exists. */
3194 char *command
= elf_tdata (abfd
)->core
->command
;
3195 int n
= strlen (command
);
3197 if (0 < n
&& command
[n
- 1] == ' ')
3198 command
[n
- 1] = '\0';
3204 /* Set the right mach type. */
3206 loongarch_elf_object_p (bfd
*abfd
)
3208 /* There are only two mach types in LoongArch currently. */
3209 if (strcmp (abfd
->xvec
->name
, "elf64-loongarch") == 0)
3210 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch64
);
3212 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch32
);
3217 loongarch_elf_gc_mark_hook (asection
*sec
, struct bfd_link_info
*info
,
3218 Elf_Internal_Rela
*rel
,
3219 struct elf_link_hash_entry
*h
,
3220 Elf_Internal_Sym
*sym
)
3223 switch (ELFNN_R_TYPE (rel
->r_info
))
3225 case R_LARCH_GNU_VTINHERIT
:
3226 case R_LARCH_GNU_VTENTRY
:
3230 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
3233 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
3234 #define TARGET_LITTLE_NAME "elfNN-loongarch"
3235 #define ELF_ARCH bfd_arch_loongarch
3236 #define ELF_TARGET_ID LARCH_ELF_DATA
3237 #define ELF_MACHINE_CODE EM_LOONGARCH
3238 #define ELF_MAXPAGESIZE 0x4000
3239 #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
3240 #define bfd_elfNN_bfd_link_hash_table_create \
3241 loongarch_elf_link_hash_table_create
3242 #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
3243 #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
3244 #define elf_info_to_howto loongarch_info_to_howto_rela
3245 #define bfd_elfNN_bfd_merge_private_bfd_data \
3246 elfNN_loongarch_merge_private_bfd_data
3248 #define elf_backend_reloc_type_class loongarch_reloc_type_class
3249 #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
3250 #define elf_backend_create_dynamic_sections \
3251 loongarch_elf_create_dynamic_sections
3252 #define elf_backend_check_relocs loongarch_elf_check_relocs
3253 #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
3254 #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
3255 #define elf_backend_relocate_section loongarch_elf_relocate_section
3256 #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
3257 #define elf_backend_finish_dynamic_sections \
3258 loongarch_elf_finish_dynamic_sections
3259 #define elf_backend_object_p loongarch_elf_object_p
3260 #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
3261 #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
3262 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
3263 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
3265 #include "elfNN-target.h"