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 (EF_LOONGARCH_ABI(out_flags
^ in_flags
) & EF_LOONGARCH_ABI_MASK
)
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
;
1449 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1451 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1452 if (ret == bfd_reloc_ok) \
1454 ret = loongarch_pop (&op1); \
1455 if (ret == bfd_reloc_ok) \
1456 ret = loongarch_push (op3); \
1461 static bfd_reloc_status_type
1462 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela
*rel
,
1463 const asection
*input_section ATTRIBUTE_UNUSED
,
1464 reloc_howto_type
*howto
, bfd
*input_bfd
,
1465 bfd_byte
*contents
, bfd_vma reloc_val
)
1467 int bits
= bfd_get_reloc_size (howto
) * 8;
1468 uint32_t insn
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1470 if (!loongarch_adjust_reloc_bitsfield(howto
, &reloc_val
))
1471 return bfd_reloc_overflow
;
1473 insn
= (insn
& (uint32_t)howto
->src_mask
)
1474 | ((insn
& (~(uint32_t)howto
->dst_mask
)) | reloc_val
);
1476 bfd_put (bits
, input_bfd
, insn
, contents
+ rel
->r_offset
);
1478 return bfd_reloc_ok
;
1481 /* Emplace a static relocation. */
1483 static bfd_reloc_status_type
1484 perform_relocation (const Elf_Internal_Rela
*rel
, asection
*input_section
,
1485 reloc_howto_type
*howto
, bfd_vma value
,
1486 bfd
*input_bfd
, bfd_byte
*contents
)
1489 int64_t opr1
, opr2
, opr3
;
1490 bfd_reloc_status_type r
= bfd_reloc_ok
;
1491 int bits
= bfd_get_reloc_size (howto
) * 8;
1494 switch (ELFNN_R_TYPE (rel
->r_info
))
1496 case R_LARCH_SOP_PUSH_PCREL
:
1497 case R_LARCH_SOP_PUSH_ABSOLUTE
:
1498 case R_LARCH_SOP_PUSH_GPREL
:
1499 case R_LARCH_SOP_PUSH_TLS_TPREL
:
1500 case R_LARCH_SOP_PUSH_TLS_GOT
:
1501 case R_LARCH_SOP_PUSH_TLS_GD
:
1502 case R_LARCH_SOP_PUSH_PLT_PCREL
:
1503 r
= loongarch_push (value
);
1506 case R_LARCH_SOP_PUSH_DUP
:
1507 r
= loongarch_pop (&opr1
);
1508 if (r
== bfd_reloc_ok
)
1510 r
= loongarch_push (opr1
);
1511 if (r
== bfd_reloc_ok
)
1512 r
= loongarch_push (opr1
);
1516 case R_LARCH_SOP_ASSERT
:
1517 r
= loongarch_pop (&opr1
);
1518 if (r
!= bfd_reloc_ok
|| !opr1
)
1519 r
= bfd_reloc_notsupported
;
1522 case R_LARCH_SOP_NOT
:
1523 r
= loongarch_pop (&opr1
);
1524 if (r
== bfd_reloc_ok
)
1525 r
= loongarch_push (!opr1
);
1528 case R_LARCH_SOP_SUB
:
1529 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
- opr2
);
1532 case R_LARCH_SOP_SL
:
1533 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
<< opr2
);
1536 case R_LARCH_SOP_SR
:
1537 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
>> opr2
);
1540 case R_LARCH_SOP_AND
:
1541 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
& opr2
);
1544 case R_LARCH_SOP_ADD
:
1545 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
+ opr2
);
1548 case R_LARCH_SOP_IF_ELSE
:
1549 r
= loongarch_pop (&opr3
);
1550 if (r
== bfd_reloc_ok
)
1552 r
= loongarch_pop (&opr2
);
1553 if (r
== bfd_reloc_ok
)
1555 r
= loongarch_pop (&opr1
);
1556 if (r
== bfd_reloc_ok
)
1557 r
= loongarch_push (opr1
? opr2
: opr3
);
1562 case R_LARCH_SOP_POP_32_S_10_5
:
1563 case R_LARCH_SOP_POP_32_S_10_12
:
1564 case R_LARCH_SOP_POP_32_S_10_16
:
1565 case R_LARCH_SOP_POP_32_S_10_16_S2
:
1566 case R_LARCH_SOP_POP_32_S_5_20
:
1567 case R_LARCH_SOP_POP_32_U_10_12
:
1568 case R_LARCH_SOP_POP_32_U
:
1569 r
= loongarch_pop (&opr1
);
1570 if (r
!= bfd_reloc_ok
)
1572 r
= loongarch_check_offset (rel
, input_section
);
1573 if (r
!= bfd_reloc_ok
)
1576 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
1578 contents
, (bfd_vma
)opr1
);
1581 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2
:
1583 r
= loongarch_pop (&opr1
);
1584 if (r
!= bfd_reloc_ok
)
1587 if ((opr1
& 0x3) != 0)
1589 r
= bfd_reloc_overflow
;
1593 uint32_t imm
= opr1
>> howto
->rightshift
;
1594 if ((imm
& (~0xfffffU
)) && ((imm
& (~0xfffffU
)) != (~0xfffffU
)))
1596 r
= bfd_reloc_overflow
;
1599 r
= loongarch_check_offset (rel
, input_section
);
1600 if (r
!= bfd_reloc_ok
)
1603 insn1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1604 insn1
= (insn1
& howto
->src_mask
)
1605 | ((imm
& 0xffffU
) << 10)
1606 | ((imm
& 0x1f0000U
) >> 16);
1607 bfd_put (bits
, input_bfd
, insn1
, contents
+ rel
->r_offset
);
1611 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2
:
1613 r
= loongarch_pop (&opr1
);
1614 if (r
!= bfd_reloc_ok
)
1617 if ((opr1
& 0x3) != 0)
1619 r
= bfd_reloc_overflow
;
1623 uint32_t imm
= opr1
>> howto
->rightshift
;
1624 if ((imm
& (~0x1ffffffU
)) && (imm
& (~0x1ffffffU
)) != (~0x1ffffffU
))
1626 r
= bfd_reloc_overflow
;
1630 r
= loongarch_check_offset (rel
, input_section
);
1631 if (r
!= bfd_reloc_ok
)
1634 insn1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1635 insn1
= ((insn1
& howto
->src_mask
)
1636 | ((imm
& 0xffffU
) << 10)
1637 | ((imm
& 0x3ff0000U
) >> 16));
1638 bfd_put (bits
, input_bfd
, insn1
, contents
+ rel
->r_offset
);
1642 case R_LARCH_TLS_DTPREL32
:
1644 case R_LARCH_TLS_DTPREL64
:
1646 r
= loongarch_check_offset (rel
, input_section
);
1647 if (r
!= bfd_reloc_ok
)
1650 bfd_put (bits
, input_bfd
, value
, contents
+ rel
->r_offset
);
1658 r
= loongarch_check_offset (rel
, input_section
);
1659 if (r
!= bfd_reloc_ok
)
1662 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1663 bfd_put (bits
, input_bfd
, opr1
+ value
, contents
+ rel
->r_offset
);
1671 r
= loongarch_check_offset (rel
, input_section
);
1672 if (r
!= bfd_reloc_ok
)
1675 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1676 bfd_put (bits
, input_bfd
, opr1
- value
, contents
+ rel
->r_offset
);
1680 r
= bfd_reloc_notsupported
;
1685 #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
1693 Elf_Internal_Sym
*sym
;
1694 struct elf_link_hash_entry
*h
;
1697 } larch_reloc_queue
[LARCH_RECENT_RELOC_QUEUE_LENGTH
];
1698 static size_t larch_reloc_queue_head
= 0;
1699 static size_t larch_reloc_queue_tail
= 0;
1702 loongarch_sym_name (bfd
*input_bfd
, struct elf_link_hash_entry
*h
,
1703 Elf_Internal_Sym
*sym
)
1705 const char *ret
= NULL
;
1707 ret
= bfd_elf_string_from_elf_section (input_bfd
,
1708 elf_symtab_hdr (input_bfd
).sh_link
,
1711 ret
= h
->root
.root
.string
;
1713 if (ret
== NULL
|| *ret
== '\0')
1719 loongarch_record_one_reloc (bfd
*abfd
, asection
*section
, int r_type
,
1720 bfd_vma r_offset
, Elf_Internal_Sym
*sym
,
1721 struct elf_link_hash_entry
*h
, bfd_vma addend
)
1723 if ((larch_reloc_queue_head
== 0
1724 && larch_reloc_queue_tail
== LARCH_RECENT_RELOC_QUEUE_LENGTH
- 1)
1725 || larch_reloc_queue_head
== larch_reloc_queue_tail
+ 1)
1726 larch_reloc_queue_head
=
1727 (larch_reloc_queue_head
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
1728 larch_reloc_queue
[larch_reloc_queue_tail
].bfd
= abfd
;
1729 larch_reloc_queue
[larch_reloc_queue_tail
].section
= section
;
1730 larch_reloc_queue
[larch_reloc_queue_tail
].r_offset
= r_offset
;
1731 larch_reloc_queue
[larch_reloc_queue_tail
].r_type
= r_type
;
1732 larch_reloc_queue
[larch_reloc_queue_tail
].sym
= sym
;
1733 larch_reloc_queue
[larch_reloc_queue_tail
].h
= h
;
1734 larch_reloc_queue
[larch_reloc_queue_tail
].addend
= addend
;
1735 loongarch_top (&larch_reloc_queue
[larch_reloc_queue_tail
].top_then
);
1736 larch_reloc_queue_tail
=
1737 (larch_reloc_queue_tail
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
1741 loongarch_dump_reloc_record (void (*p
) (const char *fmt
, ...))
1743 size_t i
= larch_reloc_queue_head
;
1745 asection
*section
= NULL
;
1746 bfd_vma r_offset
= 0;
1748 p ("Dump relocate record:\n");
1749 p ("stack top\t\trelocation name\t\tsymbol");
1750 while (i
!= larch_reloc_queue_tail
)
1752 if (a_bfd
!= larch_reloc_queue
[i
].bfd
1753 || section
!= larch_reloc_queue
[i
].section
1754 || r_offset
!= larch_reloc_queue
[i
].r_offset
)
1756 a_bfd
= larch_reloc_queue
[i
].bfd
;
1757 section
= larch_reloc_queue
[i
].section
;
1758 r_offset
= larch_reloc_queue
[i
].r_offset
;
1759 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue
[i
].bfd
,
1760 larch_reloc_queue
[i
].section
, larch_reloc_queue
[i
].r_offset
);
1764 inited
= 1, p ("...\n");
1766 reloc_howto_type
*howto
=
1767 loongarch_elf_rtype_to_howto (larch_reloc_queue
[i
].bfd
,
1768 larch_reloc_queue
[i
].r_type
);
1769 p ("0x%V %s\t`%s'", (bfd_vma
) larch_reloc_queue
[i
].top_then
,
1770 howto
? howto
->name
: "<unknown reloc>",
1771 loongarch_sym_name (larch_reloc_queue
[i
].bfd
, larch_reloc_queue
[i
].h
,
1772 larch_reloc_queue
[i
].sym
));
1774 long addend
= larch_reloc_queue
[i
].addend
;
1776 p (" - %ld", -addend
);
1777 else if (0 < addend
)
1778 p (" + %ld(0x%v)", addend
, larch_reloc_queue
[i
].addend
);
1781 i
= (i
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
1784 "-- Record dump end --\n\n");
1789 loongarch_reloc_is_fatal (struct bfd_link_info
*info
,
1791 asection
*input_section
,
1792 Elf_Internal_Rela
*rel
,
1793 reloc_howto_type
*howto
,
1794 bfd_reloc_status_type rtype
,
1802 /* 'dangerous' means we do it but can't promise it's ok
1803 'unsupport' means out of ability of relocation type
1804 'undefined' means we can't deal with the undefined symbol. */
1805 case bfd_reloc_undefined
:
1806 info
->callbacks
->undefined_symbol (info
, name
, input_bfd
, input_section
,
1807 rel
->r_offset
, true);
1808 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1809 input_bfd
, input_section
, rel
->r_offset
,
1811 is_undefweak
? "[undefweak] " : "", name
, msg
);
1813 case bfd_reloc_dangerous
:
1814 info
->callbacks
->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
1815 input_bfd
, input_section
, rel
->r_offset
,
1817 is_undefweak
? "[undefweak] " : "", name
, msg
);
1820 case bfd_reloc_notsupported
:
1821 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1822 input_bfd
, input_section
, rel
->r_offset
,
1824 is_undefweak
? "[undefweak] " : "", name
, msg
);
1836 loongarch_elf_relocate_section (bfd
*output_bfd
, struct bfd_link_info
*info
,
1837 bfd
*input_bfd
, asection
*input_section
,
1838 bfd_byte
*contents
, Elf_Internal_Rela
*relocs
,
1839 Elf_Internal_Sym
*local_syms
,
1840 asection
**local_sections
)
1842 Elf_Internal_Rela
*rel
;
1843 Elf_Internal_Rela
*relend
;
1845 asection
*sreloc
= elf_section_data (input_section
)->sreloc
;
1846 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
1847 Elf_Internal_Shdr
*symtab_hdr
= &elf_symtab_hdr (input_bfd
);
1848 struct elf_link_hash_entry
**sym_hashes
= elf_sym_hashes (input_bfd
);
1849 bfd_vma
*local_got_offsets
= elf_local_got_offsets (input_bfd
);
1850 bool is_pic
= bfd_link_pic (info
);
1851 bool is_dyn
= elf_hash_table (info
)->dynamic_sections_created
;
1852 asection
*plt
= htab
->elf
.splt
? htab
->elf
.splt
: htab
->elf
.iplt
;
1853 asection
*got
= htab
->elf
.sgot
;
1855 relend
= relocs
+ input_section
->reloc_count
;
1856 for (rel
= relocs
; rel
< relend
; rel
++)
1858 int r_type
= ELFNN_R_TYPE (rel
->r_info
);
1859 unsigned long r_symndx
= ELFNN_R_SYM (rel
->r_info
);
1860 bfd_vma pc
= sec_addr (input_section
) + rel
->r_offset
;
1861 reloc_howto_type
*howto
= NULL
;
1862 asection
*sec
= NULL
;
1863 Elf_Internal_Sym
*sym
= NULL
;
1864 struct elf_link_hash_entry
*h
= NULL
;
1866 bfd_reloc_status_type r
= bfd_reloc_ok
;
1867 bool is_ie
, is_undefweak
, unresolved_reloc
, defined_local
;
1868 bool resolved_local
, resolved_dynly
, resolved_to_const
;
1871 bfd_vma off
, ie_off
;
1874 howto
= loongarch_elf_rtype_to_howto (input_bfd
, r_type
);
1875 if (howto
== NULL
|| r_type
== R_LARCH_GNU_VTINHERIT
1876 || r_type
== R_LARCH_GNU_VTENTRY
)
1879 /* This is a final link. */
1880 if (r_symndx
< symtab_hdr
->sh_info
)
1882 is_undefweak
= false;
1883 unresolved_reloc
= false;
1884 sym
= local_syms
+ r_symndx
;
1885 sec
= local_sections
[r_symndx
];
1886 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
1888 /* Relocate against local STT_GNU_IFUNC symbol. */
1889 if (!bfd_link_relocatable (info
)
1890 && ELF_ST_TYPE (sym
->st_info
) == STT_GNU_IFUNC
)
1892 h
= elfNN_loongarch_get_local_sym_hash (htab
, input_bfd
, rel
,
1897 /* Set STT_GNU_IFUNC symbol value. */
1898 h
->root
.u
.def
.value
= sym
->st_value
;
1899 h
->root
.u
.def
.section
= sec
;
1901 defined_local
= true;
1902 resolved_local
= true;
1903 resolved_dynly
= false;
1904 resolved_to_const
= false;
1905 if (bfd_link_relocatable (info
)
1906 && ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
1907 rel
->r_addend
+= sec
->output_offset
;
1911 bool warned
, ignored
;
1913 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
1914 r_symndx
, symtab_hdr
, sym_hashes
,
1916 unresolved_reloc
, warned
, ignored
);
1917 /* Here means symbol isn't local symbol only and 'h != NULL'. */
1919 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
1920 symbol. And 'dynamic_undefined_weak' specify what to do when
1921 meeting undefweak. */
1923 if ((is_undefweak
= h
->root
.type
== bfd_link_hash_undefweak
))
1925 defined_local
= false;
1926 resolved_local
= false;
1927 resolved_to_const
= (!is_dyn
|| h
->dynindx
== -1
1928 || UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
));
1929 resolved_dynly
= !resolved_local
&& !resolved_to_const
;
1933 /* Symbol undefined offen means failed already. I don't know why
1934 'warned' here but I guess it want to continue relocating as if
1935 no error occures to find other errors as more as possible. */
1937 /* To avoid generating warning messages about truncated
1938 relocations, set the relocation's address to be the same as
1939 the start of this section. */
1940 relocation
= (input_section
->output_section
1941 ? input_section
->output_section
->vma
1944 defined_local
= relocation
!= 0;
1945 resolved_local
= defined_local
;
1946 resolved_to_const
= !resolved_local
;
1947 resolved_dynly
= false;
1951 defined_local
= !unresolved_reloc
&& !ignored
;
1953 defined_local
&& SYMBOL_REFERENCES_LOCAL (info
, h
);
1954 resolved_dynly
= !resolved_local
;
1955 resolved_to_const
= !resolved_local
&& !resolved_dynly
;
1959 name
= loongarch_sym_name (input_bfd
, h
, sym
);
1961 if (sec
!= NULL
&& discarded_section (sec
))
1962 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
, rel
,
1963 1, relend
, howto
, 0, contents
);
1965 if (bfd_link_relocatable (info
))
1968 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1969 from removed linkonce sections, or sections discarded by a linker
1970 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
1971 if (r_symndx
== STN_UNDEF
|| bfd_is_abs_section (sec
))
1973 defined_local
= false;
1974 resolved_local
= false;
1975 resolved_dynly
= false;
1976 resolved_to_const
= true;
1979 if (h
&& h
->type
== STT_GNU_IFUNC
)
1981 if (h
->plt
.offset
== MINUS_ONE
)
1982 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against `%s':\n"
1983 "STT_GNU_IFUNC must have PLT stub"
1985 input_bfd
, input_section
,
1986 (bfd_vma
) rel
->r_offset
, howto
->name
, name
);
1987 defined_local
= true;
1988 resolved_local
= true;
1989 resolved_dynly
= false;
1990 resolved_to_const
= false;
1991 relocation
= sec_addr (plt
) + h
->plt
.offset
;
1994 unresolved_reloc
= resolved_dynly
;
1996 BFD_ASSERT (resolved_local
+ resolved_dynly
+ resolved_to_const
== 1);
1998 BFD_ASSERT (!resolved_dynly
|| (h
&& h
->dynindx
!= -1));
2000 BFD_ASSERT (!resolved_local
|| defined_local
);
2005 case R_LARCH_MARK_PCREL
:
2006 case R_LARCH_MARK_LA
:
2008 r
= bfd_reloc_continue
;
2009 unresolved_reloc
= false;
2014 if (resolved_dynly
|| (is_pic
&& resolved_local
))
2016 Elf_Internal_Rela outrel
;
2018 /* When generating a shared object, these relocations are copied
2019 into the output file to be resolved at run time. */
2021 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2025 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2026 && (input_section
->flags
& SEC_ALLOC
));
2028 outrel
.r_offset
+= sec_addr (input_section
);
2031 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2032 outrel
.r_addend
= rel
->r_addend
;
2036 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2037 outrel
.r_addend
= relocation
+ rel
->r_addend
;
2040 if (unresolved_reloc
)
2041 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2044 relocation
+= rel
->r_addend
;
2058 fatal
= (loongarch_reloc_is_fatal
2059 (info
, input_bfd
, input_section
, rel
, howto
,
2060 bfd_reloc_undefined
, is_undefweak
, name
,
2061 "Can't be resolved dynamically. "
2062 "If this procedure is hand-written assembly,\n"
2063 "there must be something like '.dword sym1 - sym2' "
2064 "to generate these relocs\n"
2065 "and we can't get known link-time address of "
2068 relocation
+= rel
->r_addend
;
2071 case R_LARCH_TLS_DTPREL32
:
2072 case R_LARCH_TLS_DTPREL64
:
2075 Elf_Internal_Rela outrel
;
2077 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2080 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2081 && (input_section
->flags
& SEC_ALLOC
));
2082 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2083 outrel
.r_offset
+= sec_addr (input_section
);
2084 outrel
.r_addend
= rel
->r_addend
;
2085 if (unresolved_reloc
)
2086 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2090 if (resolved_to_const
)
2091 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
, input_section
,
2093 bfd_reloc_notsupported
,
2098 case R_LARCH_SOP_PUSH_TLS_TPREL
:
2101 if (!elf_hash_table (info
)->tls_sec
)
2102 fatal
= (loongarch_reloc_is_fatal
2103 (info
, input_bfd
, input_section
, rel
, howto
,
2104 bfd_reloc_notsupported
, is_undefweak
, name
,
2105 "TLS section not be created"));
2107 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
2110 fatal
= (loongarch_reloc_is_fatal
2111 (info
, input_bfd
, input_section
, rel
, howto
,
2112 bfd_reloc_undefined
, is_undefweak
, name
,
2113 "TLS LE just can be resolved local only."));
2116 case R_LARCH_SOP_PUSH_ABSOLUTE
:
2120 fatal
= (loongarch_reloc_is_fatal
2121 (info
, input_bfd
, input_section
, rel
, howto
,
2122 bfd_reloc_dangerous
, is_undefweak
, name
,
2123 "Someone require us to resolve undefweak "
2124 "symbol dynamically. \n"
2125 "But this reloc can't be done. "
2126 "I think I can't throw error "
2128 "so I resolved it to 0. "
2129 "I suggest to re-compile with '-fpic'."));
2132 unresolved_reloc
= false;
2136 if (resolved_to_const
)
2138 relocation
+= rel
->r_addend
;
2144 fatal
= (loongarch_reloc_is_fatal
2145 (info
, input_bfd
, input_section
, rel
, howto
,
2146 bfd_reloc_notsupported
, is_undefweak
, name
,
2147 "Under PIC we don't know load address. Re-compile "
2154 if (!(plt
&& h
&& h
->plt
.offset
!= MINUS_ONE
))
2156 fatal
= (loongarch_reloc_is_fatal
2157 (info
, input_bfd
, input_section
, rel
, howto
,
2158 bfd_reloc_undefined
, is_undefweak
, name
,
2159 "Can't be resolved dynamically. Try to re-compile "
2164 if (rel
->r_addend
!= 0)
2166 fatal
= (loongarch_reloc_is_fatal
2167 (info
, input_bfd
, input_section
, rel
, howto
,
2168 bfd_reloc_notsupported
, is_undefweak
, name
,
2169 "Shouldn't be with r_addend."));
2173 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2174 unresolved_reloc
= false;
2180 relocation
+= rel
->r_addend
;
2186 case R_LARCH_SOP_PUSH_PCREL
:
2187 case R_LARCH_SOP_PUSH_PLT_PCREL
:
2188 unresolved_reloc
= false;
2190 if (resolved_to_const
)
2192 relocation
+= rel
->r_addend
;
2195 else if (is_undefweak
)
2201 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
2204 fatal
= (loongarch_reloc_is_fatal
2205 (info
, input_bfd
, input_section
, rel
, howto
,
2206 bfd_reloc_dangerous
, is_undefweak
, name
,
2207 "Undefweak need to be resolved dynamically, "
2208 "but PLT stub doesn't represent."));
2213 if (!(defined_local
|| (h
&& h
->plt
.offset
!= MINUS_ONE
)))
2215 fatal
= (loongarch_reloc_is_fatal
2216 (info
, input_bfd
, input_section
, rel
, howto
,
2217 bfd_reloc_undefined
, is_undefweak
, name
,
2218 "PLT stub does not represent and "
2219 "symbol not defined."));
2225 else /* if (resolved_dynly) */
2227 if (!(h
&& h
->plt
.offset
!= MINUS_ONE
))
2228 fatal
= (loongarch_reloc_is_fatal
2229 (info
, input_bfd
, input_section
, rel
, howto
,
2230 bfd_reloc_dangerous
, is_undefweak
, name
,
2231 "Internal: PLT stub doesn't represent. "
2232 "Resolve it with pcrel"));
2239 if ((i
& 1) == 0 && defined_local
)
2242 relocation
+= rel
->r_addend
;
2246 if ((i
& 1) && h
&& h
->plt
.offset
!= MINUS_ONE
)
2248 if (rel
->r_addend
!= 0)
2250 fatal
= (loongarch_reloc_is_fatal
2251 (info
, input_bfd
, input_section
, rel
, howto
,
2252 bfd_reloc_notsupported
, is_undefweak
, name
,
2253 "PLT shouldn't be with r_addend."));
2256 relocation
= sec_addr (plt
) + h
->plt
.offset
- pc
;
2262 case R_LARCH_SOP_PUSH_GPREL
:
2263 unresolved_reloc
= false;
2265 if (rel
->r_addend
!= 0)
2267 fatal
= (loongarch_reloc_is_fatal
2268 (info
, input_bfd
, input_section
, rel
, howto
,
2269 bfd_reloc_notsupported
, is_undefweak
, name
,
2270 "Shouldn't be with r_addend."));
2276 off
= h
->got
.offset
;
2278 if (off
== MINUS_ONE
)
2280 fatal
= (loongarch_reloc_is_fatal
2281 (info
, input_bfd
, input_section
, rel
, howto
,
2282 bfd_reloc_notsupported
, is_undefweak
, name
,
2283 "Internal: GOT entry doesn't represent."));
2287 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn
, is_pic
, h
)
2288 || (is_pic
&& SYMBOL_REFERENCES_LOCAL (info
, h
)))
2290 /* This is actually a static link, or it is a
2291 -Bsymbolic link and the symbol is defined
2292 locally, or the symbol was forced to be local
2293 because of a version file. We must initialize
2294 this entry in the global offset table. Since the
2295 offset must always be a multiple of the word size,
2296 we use the least significant bit to record whether
2297 we have initialized it already.
2299 When doing a dynamic link, we create a .rela.got
2300 relocation entry to initialize the value. This
2301 is done in the finish_dynamic_symbol routine. */
2305 fatal
= (loongarch_reloc_is_fatal
2306 (info
, input_bfd
, input_section
, rel
, howto
,
2307 bfd_reloc_dangerous
, is_undefweak
, name
,
2308 "Internal: here shouldn't dynamic."));
2311 if (!(defined_local
|| resolved_to_const
))
2313 fatal
= (loongarch_reloc_is_fatal
2314 (info
, input_bfd
, input_section
, rel
, howto
,
2315 bfd_reloc_undefined
, is_undefweak
, name
,
2324 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2331 if (!local_got_offsets
)
2333 fatal
= (loongarch_reloc_is_fatal
2334 (info
, input_bfd
, input_section
, rel
, howto
,
2335 bfd_reloc_notsupported
, is_undefweak
, name
,
2336 "Internal: local got offsets not reporesent."));
2340 off
= local_got_offsets
[r_symndx
];
2342 if (off
== MINUS_ONE
)
2344 fatal
= (loongarch_reloc_is_fatal
2345 (info
, input_bfd
, input_section
, rel
, howto
,
2346 bfd_reloc_notsupported
, is_undefweak
, name
,
2347 "Internal: GOT entry doesn't represent."));
2351 /* The offset must always be a multiple of the word size.
2352 So, we can use the least significant bit to record
2353 whether we have already processed this entry. */
2361 Elf_Internal_Rela outrel
;
2362 /* We need to generate a R_LARCH_RELATIVE reloc
2363 for the dynamic linker. */
2364 s
= htab
->elf
.srelgot
;
2367 fatal
= (loongarch_reloc_is_fatal
2368 (info
, input_bfd
, input_section
, rel
, howto
,
2369 bfd_reloc_notsupported
, is_undefweak
, name
,
2370 "Internal: '.rel.got' not represent"));
2374 outrel
.r_offset
= sec_addr (got
) + off
;
2375 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2376 outrel
.r_addend
= relocation
; /* Link-time addr. */
2377 loongarch_elf_append_rela (output_bfd
, s
, &outrel
);
2380 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2381 local_got_offsets
[r_symndx
] |= 1;
2387 case R_LARCH_SOP_PUSH_TLS_GOT
:
2388 case R_LARCH_SOP_PUSH_TLS_GD
:
2389 if (r_type
== R_LARCH_SOP_PUSH_TLS_GOT
)
2391 unresolved_reloc
= false;
2393 if (rel
->r_addend
!= 0)
2395 fatal
= (loongarch_reloc_is_fatal
2396 (info
, input_bfd
, input_section
, rel
, howto
,
2397 bfd_reloc_notsupported
, is_undefweak
, name
,
2398 "Shouldn't be with r_addend."));
2403 if (resolved_to_const
&& is_undefweak
&& h
->dynindx
!= -1)
2405 /* What if undefweak? Let rtld make a decision. */
2406 resolved_to_const
= resolved_local
= false;
2407 resolved_dynly
= true;
2410 if (resolved_to_const
)
2412 fatal
= (loongarch_reloc_is_fatal
2413 (info
, input_bfd
, input_section
, rel
, howto
,
2414 bfd_reloc_notsupported
, is_undefweak
, name
,
2415 "Internal: Shouldn't be resolved to const."));
2421 off
= h
->got
.offset
;
2426 off
= local_got_offsets
[r_symndx
];
2427 local_got_offsets
[r_symndx
] |= 1;
2430 if (off
== MINUS_ONE
)
2432 fatal
= (loongarch_reloc_is_fatal
2433 (info
, input_bfd
, input_section
, rel
, howto
,
2434 bfd_reloc_notsupported
, is_undefweak
, name
,
2435 "Internal: TLS GOT entry doesn't represent."));
2439 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
2441 /* If this symbol is referenced by both GD and IE TLS, the IE
2442 reference's GOT slot follows the GD reference's slots. */
2444 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
2445 ie_off
= 2 * GOT_ENTRY_SIZE
;
2451 bfd_vma tls_block_off
= 0;
2452 Elf_Internal_Rela outrel
;
2456 if (!elf_hash_table (info
)->tls_sec
)
2458 fatal
= (loongarch_reloc_is_fatal
2459 (info
, input_bfd
, input_section
, rel
, howto
,
2460 bfd_reloc_notsupported
, is_undefweak
, name
,
2461 "Internal: TLS sec not represent."));
2465 relocation
- elf_hash_table (info
)->tls_sec
->vma
;
2468 if (tls_type
& GOT_TLS_GD
)
2470 outrel
.r_offset
= sec_addr (got
) + off
;
2471 outrel
.r_addend
= 0;
2472 bfd_put_NN (output_bfd
, 0, got
->contents
+ off
);
2473 if (resolved_local
&& bfd_link_executable (info
))
2474 bfd_put_NN (output_bfd
, 1, got
->contents
+ off
);
2475 else if (resolved_local
/* && !bfd_link_executable (info) */)
2477 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN
);
2478 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2481 else /* if (resolved_dynly) */
2484 ELFNN_R_INFO (h
->dynindx
, R_LARCH_TLS_DTPMODNN
);
2485 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2489 outrel
.r_offset
+= GOT_ENTRY_SIZE
;
2490 bfd_put_NN (output_bfd
, tls_block_off
,
2491 got
->contents
+ off
+ GOT_ENTRY_SIZE
);
2493 /* DTPREL known. */;
2494 else /* if (resolved_dynly) */
2497 ELFNN_R_INFO (h
->dynindx
, R_LARCH_TLS_DTPRELNN
);
2498 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2503 if (tls_type
& GOT_TLS_IE
)
2505 outrel
.r_offset
= sec_addr (got
) + off
+ ie_off
;
2506 bfd_put_NN (output_bfd
, tls_block_off
,
2507 got
->contents
+ off
+ ie_off
);
2508 if (resolved_local
&& bfd_link_executable (info
))
2510 else if (resolved_local
/* && !bfd_link_executable (info) */)
2512 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN
);
2513 outrel
.r_addend
= tls_block_off
;
2514 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2517 else /* if (resolved_dynly) */
2520 ELFNN_R_INFO (h
->dynindx
, R_LARCH_TLS_TPRELNN
);
2521 outrel
.r_addend
= 0;
2522 loongarch_elf_append_rela (output_bfd
, htab
->elf
.srelgot
,
2528 relocation
= off
+ (is_ie
? ie_off
: 0);
2540 /* 'unresolved_reloc' means we haven't done it yet.
2541 We need help of dynamic linker to fix this memory location up. */
2542 if (!unresolved_reloc
)
2545 if (_bfd_elf_section_offset (output_bfd
, info
, input_section
,
2546 rel
->r_offset
) == MINUS_ONE
)
2547 /* WHY? May because it's invalid so skip checking.
2548 But why dynamic reloc a invalid section? */
2551 if (input_section
->output_section
->flags
& SEC_DEBUGGING
)
2553 fatal
= (loongarch_reloc_is_fatal
2554 (info
, input_bfd
, input_section
, rel
, howto
,
2555 bfd_reloc_dangerous
, is_undefweak
, name
,
2556 "Seems dynamic linker not process "
2557 "sections 'SEC_DEBUGGING'."));
2562 if ((info
->flags
& DF_TEXTREL
) == 0)
2563 if (input_section
->output_section
->flags
& SEC_READONLY
)
2564 info
->flags
|= DF_TEXTREL
;
2571 loongarch_record_one_reloc (input_bfd
, input_section
, r_type
,
2572 rel
->r_offset
, sym
, h
, rel
->r_addend
);
2574 if (r
!= bfd_reloc_continue
)
2575 r
= perform_relocation (rel
, input_section
, howto
, relocation
,
2576 input_bfd
, contents
);
2580 case bfd_reloc_dangerous
:
2581 case bfd_reloc_continue
:
2585 case bfd_reloc_overflow
:
2586 /* Overflow value can't be filled in. */
2587 loongarch_dump_reloc_record (info
->callbacks
->info
);
2588 info
->callbacks
->reloc_overflow
2589 (info
, h
? &h
->root
: NULL
, name
, howto
->name
, rel
->r_addend
,
2590 input_bfd
, input_section
, rel
->r_offset
);
2593 case bfd_reloc_outofrange
:
2594 /* Stack state incorrect. */
2595 loongarch_dump_reloc_record (info
->callbacks
->info
);
2596 info
->callbacks
->info
2597 ("%X%H: Internal stack state is incorrect.\n"
2598 "Want to push to full stack or pop from empty stack?\n",
2599 input_bfd
, input_section
, rel
->r_offset
);
2602 case bfd_reloc_notsupported
:
2603 info
->callbacks
->info ("%X%H: Unknown relocation type.\n", input_bfd
,
2604 input_section
, rel
->r_offset
);
2608 info
->callbacks
->info ("%X%H: Internal: unknown error.\n", input_bfd
,
2609 input_section
, rel
->r_offset
);
2620 /* Finish up dynamic symbol handling. We set the contents of various
2621 dynamic sections here. */
2624 loongarch_elf_finish_dynamic_symbol (bfd
*output_bfd
,
2625 struct bfd_link_info
*info
,
2626 struct elf_link_hash_entry
*h
,
2627 Elf_Internal_Sym
*sym
)
2629 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
2630 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
2631 asection
*plt
= NULL
;
2633 if (h
->plt
.offset
!= MINUS_ONE
)
2636 asection
*gotplt
, *relplt
;
2637 bfd_vma got_address
;
2638 uint32_t plt_entry
[PLT_ENTRY_INSNS
];
2640 Elf_Internal_Rela rela
;
2642 plt_idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
) / PLT_ENTRY_SIZE
;
2644 /* One of '.plt' and '.iplt' represents. */
2645 BFD_ASSERT (!!htab
->elf
.splt
^ !!htab
->elf
.iplt
);
2649 BFD_ASSERT ((h
->type
== STT_GNU_IFUNC
2650 && SYMBOL_REFERENCES_LOCAL (info
, h
))
2651 || h
->dynindx
!= -1);
2653 plt
= htab
->elf
.splt
;
2654 gotplt
= htab
->elf
.sgotplt
;
2655 relplt
= htab
->elf
.srelplt
;
2657 sec_addr (gotplt
) + GOTPLT_HEADER_SIZE
+ plt_idx
* GOT_ENTRY_SIZE
;
2659 else /* if (htab->elf.iplt) */
2661 BFD_ASSERT (h
->type
== STT_GNU_IFUNC
2662 && SYMBOL_REFERENCES_LOCAL (info
, h
));
2664 plt
= htab
->elf
.iplt
;
2665 gotplt
= htab
->elf
.igotplt
;
2666 relplt
= htab
->elf
.irelplt
;
2667 got_address
= sec_addr (gotplt
) + plt_idx
* GOT_ENTRY_SIZE
;
2670 /* Find out where the .plt entry should go. */
2671 loc
= plt
->contents
+ h
->plt
.offset
;
2673 /* Fill in the PLT entry itself. */
2674 if (!loongarch_make_plt_entry (got_address
,
2675 sec_addr (plt
) + h
->plt
.offset
,
2679 for (i
= 0; i
< PLT_ENTRY_INSNS
; i
++)
2680 bfd_put_32 (output_bfd
, plt_entry
[i
], loc
+ 4 * i
);
2682 /* Fill in the initial value of the .got.plt entry. */
2683 loc
= gotplt
->contents
+ (got_address
- sec_addr (gotplt
));
2684 bfd_put_NN (output_bfd
, sec_addr (plt
), loc
);
2686 rela
.r_offset
= got_address
;
2687 if (h
->type
== STT_GNU_IFUNC
&& SYMBOL_REFERENCES_LOCAL (info
, h
))
2689 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
2690 rela
.r_addend
= (h
->root
.u
.def
.value
2691 + h
->root
.u
.def
.section
->output_section
->vma
2692 + h
->root
.u
.def
.section
->output_offset
);
2696 /* Fill in the entry in the .rela.plt section. */
2697 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_JUMP_SLOT
);
2701 loc
= relplt
->contents
+ plt_idx
* sizeof (ElfNN_External_Rela
);
2702 bed
->s
->swap_reloca_out (output_bfd
, &rela
, loc
);
2704 if (!h
->def_regular
)
2706 /* Mark the symbol as undefined, rather than as defined in
2707 the .plt section. Leave the value alone. */
2708 sym
->st_shndx
= SHN_UNDEF
;
2709 /* If the symbol is weak, we do need to clear the value.
2710 Otherwise, the PLT entry would provide a definition for
2711 the symbol even if the symbol wasn't defined anywhere,
2712 and so the symbol would never be NULL. */
2713 if (!h
->ref_regular_nonweak
)
2718 if (h
->got
.offset
!= MINUS_ONE
2719 /* TLS got entry have been handled in elf_relocate_section. */
2720 && !(loongarch_elf_hash_entry (h
)->tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
2721 /* have allocated got entry but not allocated rela before. */
2722 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
2724 asection
*sgot
, *srela
;
2725 Elf_Internal_Rela rela
;
2726 bfd_vma off
= h
->got
.offset
& ~(bfd_vma
) 1;
2728 /* This symbol has an entry in the GOT. Set it up. */
2730 sgot
= htab
->elf
.sgot
;
2731 srela
= htab
->elf
.srelgot
;
2732 BFD_ASSERT (sgot
&& srela
);
2734 rela
.r_offset
= sec_addr (sgot
) + off
;
2736 if (h
->type
== STT_GNU_IFUNC
)
2738 if (elf_hash_table (info
)->dynamic_sections_created
2739 && SYMBOL_REFERENCES_LOCAL (info
, h
))
2741 asection
*sec
= h
->root
.u
.def
.section
;
2742 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
2743 rela
.r_addend
= (h
->root
.u
.def
.value
+ sec
->output_section
->vma
2744 + sec
->output_offset
);
2745 bfd_put_NN (output_bfd
, 0, sgot
->contents
+ off
);
2751 = ELFNN_R_INFO (0, (bfd_link_pic (info
)
2752 ? R_LARCH_RELATIVE
: R_LARCH_NONE
));
2754 plt
->output_section
->vma
+ plt
->output_offset
+ h
->plt
.offset
;
2755 bfd_put_NN (output_bfd
, rela
.r_addend
, sgot
->contents
+ off
);
2758 else if (bfd_link_pic (info
) && SYMBOL_REFERENCES_LOCAL (info
, h
))
2760 BFD_ASSERT (h
->got
.offset
& 1 /* Has been filled in addr. */);
2761 asection
*sec
= h
->root
.u
.def
.section
;
2762 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2763 rela
.r_addend
= (h
->root
.u
.def
.value
+ sec
->output_section
->vma
2764 + sec
->output_offset
);
2768 BFD_ASSERT ((h
->got
.offset
& 1) == 0);
2769 BFD_ASSERT (h
->dynindx
!= -1);
2770 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
2774 loongarch_elf_append_rela (output_bfd
, srela
, &rela
);
2779 Elf_Internal_Rela rela
;
2782 /* This symbols needs a copy reloc. Set it up. */
2783 BFD_ASSERT (h
->dynindx
!= -1);
2785 rela
.r_offset
= sec_addr (h
->root
.u
.def
.section
) + h
->root
.u
.def
.value
;
2786 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_COPY
);
2788 if (h
->root
.u
.def
.section
== htab
->elf
.sdynrelro
)
2789 s
= htab
->elf
.sreldynrelro
;
2791 s
= htab
->elf
.srelbss
;
2792 loongarch_elf_append_rela (output_bfd
, s
, &rela
);
2795 /* Mark some specially defined symbols as absolute. */
2796 if (h
== htab
->elf
.hdynamic
|| h
== htab
->elf
.hgot
|| h
== htab
->elf
.hplt
)
2797 sym
->st_shndx
= SHN_ABS
;
2802 /* Finish up the dynamic sections. */
2805 loongarch_finish_dyn (bfd
*output_bfd
, struct bfd_link_info
*info
, bfd
*dynobj
,
2808 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
2809 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
2810 size_t dynsize
= bed
->s
->sizeof_dyn
, skipped_size
= 0;
2811 bfd_byte
*dyncon
, *dynconend
;
2813 dynconend
= sdyn
->contents
+ sdyn
->size
;
2814 for (dyncon
= sdyn
->contents
; dyncon
< dynconend
; dyncon
+= dynsize
)
2816 Elf_Internal_Dyn dyn
;
2820 bed
->s
->swap_dyn_in (dynobj
, dyncon
, &dyn
);
2825 s
= htab
->elf
.sgotplt
;
2826 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
2829 s
= htab
->elf
.srelplt
;
2830 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
2833 s
= htab
->elf
.srelplt
;
2834 dyn
.d_un
.d_val
= s
->size
;
2837 if ((info
->flags
& DF_TEXTREL
) == 0)
2841 if ((info
->flags
& DF_TEXTREL
) == 0)
2842 dyn
.d_un
.d_val
&= ~DF_TEXTREL
;
2846 skipped_size
+= dynsize
;
2848 bed
->s
->swap_dyn_out (output_bfd
, &dyn
, dyncon
- skipped_size
);
2850 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
2851 memset (dyncon
- skipped_size
, 0, skipped_size
);
2855 /* Finish up local dynamic symbol handling. We set the contents of
2856 various dynamic sections here. */
2859 elfNN_loongarch_finish_local_dynamic_symbol (void **slot
, void *inf
)
2861 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
2862 struct bfd_link_info
*info
= (struct bfd_link_info
*) inf
;
2864 return loongarch_elf_finish_dynamic_symbol (info
->output_bfd
, info
, h
, NULL
);
2868 loongarch_elf_finish_dynamic_sections (bfd
*output_bfd
,
2869 struct bfd_link_info
*info
)
2872 asection
*sdyn
, *plt
, *gotplt
= NULL
;
2873 struct loongarch_elf_link_hash_table
*htab
;
2875 htab
= loongarch_elf_hash_table (info
);
2877 dynobj
= htab
->elf
.dynobj
;
2878 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
2880 if (elf_hash_table (info
)->dynamic_sections_created
)
2882 BFD_ASSERT (htab
->elf
.splt
&& sdyn
);
2884 if (!loongarch_finish_dyn (output_bfd
, info
, dynobj
, sdyn
))
2888 if ((plt
= htab
->elf
.splt
))
2889 gotplt
= htab
->elf
.sgotplt
;
2890 else if ((plt
= htab
->elf
.iplt
))
2891 gotplt
= htab
->elf
.igotplt
;
2893 if (plt
&& 0 < plt
->size
)
2896 uint32_t plt_header
[PLT_HEADER_INSNS
];
2897 if (!loongarch_make_plt_header (sec_addr (gotplt
), sec_addr (plt
),
2901 for (i
= 0; i
< PLT_HEADER_INSNS
; i
++)
2902 bfd_put_32 (output_bfd
, plt_header
[i
], plt
->contents
+ 4 * i
);
2904 elf_section_data (plt
->output_section
)->this_hdr
.sh_entsize
=
2908 if (htab
->elf
.sgotplt
)
2910 asection
*output_section
= htab
->elf
.sgotplt
->output_section
;
2912 if (bfd_is_abs_section (output_section
))
2914 _bfd_error_handler (_("discarded output section: `%pA'"),
2919 if (0 < htab
->elf
.sgotplt
->size
)
2921 /* Write the first two entries in .got.plt, needed for the dynamic
2923 bfd_put_NN (output_bfd
, MINUS_ONE
, htab
->elf
.sgotplt
->contents
);
2925 bfd_put_NN (output_bfd
, (bfd_vma
) 0,
2926 htab
->elf
.sgotplt
->contents
+ GOT_ENTRY_SIZE
);
2929 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
2934 asection
*output_section
= htab
->elf
.sgot
->output_section
;
2936 if (0 < htab
->elf
.sgot
->size
)
2938 /* Set the first entry in the global offset table to the address of
2939 the dynamic section. */
2940 bfd_vma val
= sdyn
? sec_addr (sdyn
) : 0;
2941 bfd_put_NN (output_bfd
, val
, htab
->elf
.sgot
->contents
);
2944 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
2947 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
2948 htab_traverse (htab
->loc_hash_table
,
2949 (void *) elfNN_loongarch_finish_local_dynamic_symbol
, info
);
2954 /* Return address for Ith PLT stub in section PLT, for relocation REL
2955 or (bfd_vma) -1 if it should not be included. */
2958 loongarch_elf_plt_sym_val (bfd_vma i
, const asection
*plt
,
2959 const arelent
*rel ATTRIBUTE_UNUSED
)
2961 return plt
->vma
+ PLT_HEADER_SIZE
+ i
* PLT_ENTRY_SIZE
;
2964 static enum elf_reloc_type_class
2965 loongarch_reloc_type_class (const struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
2966 const asection
*rel_sec ATTRIBUTE_UNUSED
,
2967 const Elf_Internal_Rela
*rela
)
2969 struct loongarch_elf_link_hash_table
*htab
;
2970 htab
= loongarch_elf_hash_table (info
);
2972 if (htab
->elf
.dynsym
!= NULL
&& htab
->elf
.dynsym
->contents
!= NULL
)
2974 /* Check relocation against STT_GNU_IFUNC symbol if there are
2976 bfd
*abfd
= info
->output_bfd
;
2977 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
2978 unsigned long r_symndx
= ELFNN_R_SYM (rela
->r_info
);
2979 if (r_symndx
!= STN_UNDEF
)
2981 Elf_Internal_Sym sym
;
2982 if (!bed
->s
->swap_symbol_in (abfd
,
2983 htab
->elf
.dynsym
->contents
2984 + r_symndx
* bed
->s
->sizeof_sym
,
2987 /* xgettext:c-format */
2988 _bfd_error_handler (_("%pB symbol number %lu references"
2989 " nonexistent SHT_SYMTAB_SHNDX section"),
2991 /* Ideally an error class should be returned here. */
2993 else if (ELF_ST_TYPE (sym
.st_info
) == STT_GNU_IFUNC
)
2994 return reloc_class_ifunc
;
2998 switch (ELFNN_R_TYPE (rela
->r_info
))
3000 case R_LARCH_IRELATIVE
:
3001 return reloc_class_ifunc
;
3002 case R_LARCH_RELATIVE
:
3003 return reloc_class_relative
;
3004 case R_LARCH_JUMP_SLOT
:
3005 return reloc_class_plt
;
3007 return reloc_class_copy
;
3009 return reloc_class_normal
;
3013 /* Copy the extra info we tack onto an elf_link_hash_entry. */
3016 loongarch_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
3017 struct elf_link_hash_entry
*dir
,
3018 struct elf_link_hash_entry
*ind
)
3020 struct loongarch_elf_link_hash_entry
*edir
, *eind
;
3022 edir
= (struct loongarch_elf_link_hash_entry
*) dir
;
3023 eind
= (struct loongarch_elf_link_hash_entry
*) ind
;
3025 if (eind
->dyn_relocs
!= NULL
)
3027 if (edir
->dyn_relocs
!= NULL
)
3029 struct elf_dyn_relocs
**pp
;
3030 struct elf_dyn_relocs
*p
;
3032 /* Add reloc counts against the indirect sym to the direct sym
3033 list. Merge any entries against the same section. */
3034 for (pp
= &eind
->dyn_relocs
; (p
= *pp
) != NULL
;)
3036 struct elf_dyn_relocs
*q
;
3038 for (q
= edir
->dyn_relocs
; q
!= NULL
; q
= q
->next
)
3039 if (q
->sec
== p
->sec
)
3041 q
->pc_count
+= p
->pc_count
;
3042 q
->count
+= p
->count
;
3049 *pp
= edir
->dyn_relocs
;
3052 edir
->dyn_relocs
= eind
->dyn_relocs
;
3053 eind
->dyn_relocs
= NULL
;
3056 if (ind
->root
.type
== bfd_link_hash_indirect
&& dir
->got
.refcount
< 0)
3058 edir
->tls_type
= eind
->tls_type
;
3059 eind
->tls_type
= GOT_UNKNOWN
;
3061 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
3064 #define PRSTATUS_SIZE 0x1d8
3065 #define PRSTATUS_OFFSET_PR_CURSIG 0xc
3066 #define PRSTATUS_OFFSET_PR_PID 0x20
3067 #define ELF_GREGSET_T_SIZE 0x168
3068 #define PRSTATUS_OFFSET_PR_REG 0x70
3070 /* Support for core dump NOTE sections. */
3073 loongarch_elf_grok_prstatus (bfd
*abfd
, Elf_Internal_Note
*note
)
3075 switch (note
->descsz
)
3080 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
3083 elf_tdata (abfd
)->core
->signal
=
3084 bfd_get_16 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_CURSIG
);
3087 elf_tdata (abfd
)->core
->lwpid
=
3088 bfd_get_32 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_PID
);
3092 /* Make a ".reg/999" section. */
3093 return _bfd_elfcore_make_pseudosection (abfd
, ".reg", ELF_GREGSET_T_SIZE
,
3095 + PRSTATUS_OFFSET_PR_REG
);
3098 #define PRPSINFO_SIZE 0x88
3099 #define PRPSINFO_OFFSET_PR_PID 0x18
3100 #define PRPSINFO_OFFSET_PR_FNAME 0x28
3101 #define PRPSINFO_SIZEOF_PR_FNAME 0x10
3102 #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
3103 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
3107 loongarch_elf_grok_psinfo (bfd
*abfd
, Elf_Internal_Note
*note
)
3109 switch (note
->descsz
)
3114 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
3117 elf_tdata (abfd
)->core
->pid
=
3118 bfd_get_32 (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PID
);
3121 elf_tdata (abfd
)->core
->program
=
3122 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_FNAME
,
3123 PRPSINFO_SIZEOF_PR_FNAME
);
3126 elf_tdata (abfd
)->core
->command
=
3127 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PS_ARGS
,
3128 PRPSINFO_SIZEOF_PR_PS_ARGS
);
3132 /* Note that for some reason, a spurious space is tacked
3133 onto the end of the args in some (at least one anyway)
3134 implementations, so strip it off if it exists. */
3137 char *command
= elf_tdata (abfd
)->core
->command
;
3138 int n
= strlen (command
);
3140 if (0 < n
&& command
[n
- 1] == ' ')
3141 command
[n
- 1] = '\0';
3147 /* Set the right mach type. */
3149 loongarch_elf_object_p (bfd
*abfd
)
3151 /* There are only two mach types in LoongArch currently. */
3152 if (strcmp (abfd
->xvec
->name
, "elf64-loongarch") == 0)
3153 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch64
);
3155 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch32
);
3160 loongarch_elf_gc_mark_hook (asection
*sec
, struct bfd_link_info
*info
,
3161 Elf_Internal_Rela
*rel
,
3162 struct elf_link_hash_entry
*h
,
3163 Elf_Internal_Sym
*sym
)
3166 switch (ELFNN_R_TYPE (rel
->r_info
))
3168 case R_LARCH_GNU_VTINHERIT
:
3169 case R_LARCH_GNU_VTENTRY
:
3173 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
3176 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
3177 #define TARGET_LITTLE_NAME "elfNN-loongarch"
3178 #define ELF_ARCH bfd_arch_loongarch
3179 #define ELF_TARGET_ID LARCH_ELF_DATA
3180 #define ELF_MACHINE_CODE EM_LOONGARCH
3181 #define ELF_MAXPAGESIZE 0x4000
3182 #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
3183 #define bfd_elfNN_bfd_link_hash_table_create \
3184 loongarch_elf_link_hash_table_create
3185 #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
3186 #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
3187 #define elf_info_to_howto loongarch_info_to_howto_rela
3188 #define bfd_elfNN_bfd_merge_private_bfd_data \
3189 elfNN_loongarch_merge_private_bfd_data
3191 #define elf_backend_reloc_type_class loongarch_reloc_type_class
3192 #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
3193 #define elf_backend_create_dynamic_sections \
3194 loongarch_elf_create_dynamic_sections
3195 #define elf_backend_check_relocs loongarch_elf_check_relocs
3196 #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
3197 #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
3198 #define elf_backend_relocate_section loongarch_elf_relocate_section
3199 #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
3200 #define elf_backend_finish_dynamic_sections \
3201 loongarch_elf_finish_dynamic_sections
3202 #define elf_backend_object_p loongarch_elf_object_p
3203 #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
3204 #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
3205 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
3206 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
3208 #include "elfNN-target.h"