elfnn-loongarch.c revision 1.1.1.1 1 1.1 christos /* LoongArch-specific support for NN-bit ELF.
2 1.1 christos Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 1.1 christos Contributed by Loongson Ltd.
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; see the file COPYING3. If not,
19 1.1 christos see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos #include "ansidecl.h"
22 1.1 christos #include "sysdep.h"
23 1.1 christos #include "bfd.h"
24 1.1 christos #include "libbfd.h"
25 1.1 christos #define ARCH_SIZE NN
26 1.1 christos #include "elf-bfd.h"
27 1.1 christos #include "objalloc.h"
28 1.1 christos #include "elf/loongarch.h"
29 1.1 christos #include "elfxx-loongarch.h"
30 1.1 christos
31 1.1 christos static bool
32 1.1 christos loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
33 1.1 christos Elf_Internal_Rela *dst)
34 1.1 christos {
35 1.1 christos cache_ptr->howto = loongarch_elf_rtype_to_howto (abfd,
36 1.1 christos ELFNN_R_TYPE (dst->r_info));
37 1.1 christos return cache_ptr->howto != NULL;
38 1.1 christos }
39 1.1 christos
40 1.1 christos /* LoongArch ELF linker hash entry. */
41 1.1 christos struct loongarch_elf_link_hash_entry
42 1.1 christos {
43 1.1 christos struct elf_link_hash_entry elf;
44 1.1 christos
45 1.1 christos #define GOT_UNKNOWN 0
46 1.1 christos #define GOT_NORMAL 1
47 1.1 christos #define GOT_TLS_GD 2
48 1.1 christos #define GOT_TLS_IE 4
49 1.1 christos #define GOT_TLS_LE 8
50 1.1 christos char tls_type;
51 1.1 christos };
52 1.1 christos
53 1.1 christos #define loongarch_elf_hash_entry(ent) \
54 1.1 christos ((struct loongarch_elf_link_hash_entry *) (ent))
55 1.1 christos
56 1.1 christos struct _bfd_loongarch_elf_obj_tdata
57 1.1 christos {
58 1.1 christos struct elf_obj_tdata root;
59 1.1 christos
60 1.1 christos /* The tls_type for each local got entry. */
61 1.1 christos char *local_got_tls_type;
62 1.1 christos };
63 1.1 christos
64 1.1 christos #define _bfd_loongarch_elf_tdata(abfd) \
65 1.1 christos ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
66 1.1 christos
67 1.1 christos #define _bfd_loongarch_elf_local_got_tls_type(abfd) \
68 1.1 christos (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
69 1.1 christos
70 1.1 christos #define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
71 1.1 christos (*((h) != NULL \
72 1.1 christos ? &loongarch_elf_hash_entry (h)->tls_type \
73 1.1 christos : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
74 1.1 christos
75 1.1 christos #define is_loongarch_elf(bfd) \
76 1.1 christos (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
77 1.1 christos && elf_tdata (bfd) != NULL \
78 1.1 christos && elf_object_id (bfd) == LARCH_ELF_DATA)
79 1.1 christos
80 1.1 christos struct loongarch_elf_link_hash_table
81 1.1 christos {
82 1.1 christos struct elf_link_hash_table elf;
83 1.1 christos
84 1.1 christos /* Short-cuts to get to dynamic linker sections. */
85 1.1 christos asection *sdyntdata;
86 1.1 christos
87 1.1 christos /* Small local sym to section mapping cache. */
88 1.1 christos struct sym_cache sym_cache;
89 1.1 christos
90 1.1 christos /* Used by local STT_GNU_IFUNC symbols. */
91 1.1 christos htab_t loc_hash_table;
92 1.1 christos void *loc_hash_memory;
93 1.1 christos
94 1.1 christos /* The max alignment of output sections. */
95 1.1 christos bfd_vma max_alignment;
96 1.1 christos };
97 1.1 christos
98 1.1 christos /* Get the LoongArch ELF linker hash table from a link_info structure. */
99 1.1 christos #define loongarch_elf_hash_table(p) \
100 1.1 christos (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
101 1.1 christos ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
102 1.1 christos : NULL)
103 1.1 christos
104 1.1 christos #define MINUS_ONE ((bfd_vma) 0 - 1)
105 1.1 christos
106 1.1 christos #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
107 1.1 christos
108 1.1 christos #define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
109 1.1 christos #define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
110 1.1 christos
111 1.1 christos #define PLT_HEADER_INSNS 8
112 1.1 christos #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
113 1.1 christos
114 1.1 christos #define PLT_ENTRY_INSNS 4
115 1.1 christos #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
116 1.1 christos
117 1.1 christos #define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
118 1.1 christos
119 1.1 christos #define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
120 1.1 christos
121 1.1 christos #define elf_backend_want_got_plt 1
122 1.1 christos
123 1.1 christos #define elf_backend_plt_readonly 1
124 1.1 christos
125 1.1 christos #define elf_backend_want_plt_sym 1
126 1.1 christos #define elf_backend_plt_alignment 4
127 1.1 christos #define elf_backend_can_gc_sections 1
128 1.1 christos #define elf_backend_can_refcount 1
129 1.1 christos #define elf_backend_want_got_sym 1
130 1.1 christos
131 1.1 christos #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
132 1.1 christos
133 1.1 christos #define elf_backend_want_dynrelro 1
134 1.1 christos #define elf_backend_rela_normal 1
135 1.1 christos #define elf_backend_default_execstack 0
136 1.1 christos
137 1.1 christos /* Generate a PLT header. */
138 1.1 christos
139 1.1 christos static bool
140 1.1 christos loongarch_make_plt_header (bfd_vma got_plt_addr, bfd_vma plt_header_addr,
141 1.1 christos uint32_t *entry)
142 1.1 christos {
143 1.1 christos bfd_vma pcrel = got_plt_addr - plt_header_addr;
144 1.1 christos bfd_vma hi, lo;
145 1.1 christos
146 1.1 christos if (pcrel + 0x80000800 > 0xffffffff)
147 1.1 christos {
148 1.1 christos _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
149 1.1 christos bfd_set_error (bfd_error_bad_value);
150 1.1 christos return false;
151 1.1 christos }
152 1.1 christos hi = ((pcrel + 0x800) >> 12) & 0xfffff;
153 1.1 christos lo = pcrel & 0xfff;
154 1.1 christos
155 1.1 christos /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
156 1.1 christos sub.[wd] $t1, $t1, $t3
157 1.1 christos ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
158 1.1 christos addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
159 1.1 christos addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
160 1.1 christos srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
161 1.1 christos ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
162 1.1 christos jirl $r0, $t3, 0 */
163 1.1 christos
164 1.1 christos if (GOT_ENTRY_SIZE == 8)
165 1.1 christos {
166 1.1 christos entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
167 1.1 christos entry[1] = 0x0011bdad;
168 1.1 christos entry[2] = 0x28c001cf | (lo & 0xfff) << 10;
169 1.1 christos entry[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
170 1.1 christos entry[4] = 0x02c001cc | (lo & 0xfff) << 10;
171 1.1 christos entry[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
172 1.1 christos entry[6] = 0x28c0018c | GOT_ENTRY_SIZE << 10;
173 1.1 christos entry[7] = 0x4c0001e0;
174 1.1 christos }
175 1.1 christos else
176 1.1 christos {
177 1.1 christos entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
178 1.1 christos entry[1] = 0x00113dad;
179 1.1 christos entry[2] = 0x288001cf | (lo & 0xfff) << 10;
180 1.1 christos entry[3] = 0x028001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
181 1.1 christos entry[4] = 0x028001cc | (lo & 0xfff) << 10;
182 1.1 christos entry[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
183 1.1 christos entry[6] = 0x2880018c | GOT_ENTRY_SIZE << 10;
184 1.1 christos entry[7] = 0x4c0001e0;
185 1.1 christos }
186 1.1 christos return true;
187 1.1 christos }
188 1.1 christos
189 1.1 christos /* Generate a PLT entry. */
190 1.1 christos
191 1.1 christos static bool
192 1.1 christos loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, bfd_vma plt_entry_addr,
193 1.1 christos uint32_t *entry)
194 1.1 christos {
195 1.1 christos bfd_vma pcrel = got_plt_entry_addr - plt_entry_addr;
196 1.1 christos bfd_vma hi, lo;
197 1.1 christos
198 1.1 christos if (pcrel + 0x80000800 > 0xffffffff)
199 1.1 christos {
200 1.1 christos _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
201 1.1 christos bfd_set_error (bfd_error_bad_value);
202 1.1 christos return false;
203 1.1 christos }
204 1.1 christos hi = ((pcrel + 0x800) >> 12) & 0xfffff;
205 1.1 christos lo = pcrel & 0xfff;
206 1.1 christos
207 1.1 christos entry[0] = 0x1c00000f | (hi & 0xfffff) << 5;
208 1.1 christos entry[1] = ((GOT_ENTRY_SIZE == 8 ? 0x28c001ef : 0x288001ef)
209 1.1 christos | (lo & 0xfff) << 10);
210 1.1 christos entry[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
211 1.1 christos entry[3] = 0x03400000; /* nop */
212 1.1 christos
213 1.1 christos return true;
214 1.1 christos }
215 1.1 christos
216 1.1 christos /* Create an entry in an LoongArch ELF linker hash table. */
217 1.1 christos
218 1.1 christos static struct bfd_hash_entry *
219 1.1 christos link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
220 1.1 christos const char *string)
221 1.1 christos {
222 1.1 christos struct loongarch_elf_link_hash_entry *eh;
223 1.1 christos
224 1.1 christos /* Allocate the structure if it has not already been allocated by a
225 1.1 christos subclass. */
226 1.1 christos if (entry == NULL)
227 1.1 christos {
228 1.1 christos entry = bfd_hash_allocate (table, sizeof (*eh));
229 1.1 christos if (entry == NULL)
230 1.1 christos return entry;
231 1.1 christos }
232 1.1 christos
233 1.1 christos /* Call the allocation method of the superclass. */
234 1.1 christos entry = _bfd_elf_link_hash_newfunc (entry, table, string);
235 1.1 christos if (entry != NULL)
236 1.1 christos {
237 1.1 christos eh = (struct loongarch_elf_link_hash_entry *) entry;
238 1.1 christos eh->tls_type = GOT_UNKNOWN;
239 1.1 christos }
240 1.1 christos
241 1.1 christos return entry;
242 1.1 christos }
243 1.1 christos
244 1.1 christos /* Compute a hash of a local hash entry. We use elf_link_hash_entry
245 1.1 christos for local symbol so that we can handle local STT_GNU_IFUNC symbols
246 1.1 christos as global symbol. We reuse indx and dynstr_index for local symbol
247 1.1 christos hash since they aren't used by global symbols in this backend. */
248 1.1 christos
249 1.1 christos static hashval_t
250 1.1 christos elfNN_loongarch_local_htab_hash (const void *ptr)
251 1.1 christos {
252 1.1 christos struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr;
253 1.1 christos return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
254 1.1 christos }
255 1.1 christos
256 1.1 christos /* Compare local hash entries. */
257 1.1 christos
258 1.1 christos static int
259 1.1 christos elfNN_loongarch_local_htab_eq (const void *ptr1, const void *ptr2)
260 1.1 christos {
261 1.1 christos struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1;
262 1.1 christos struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2;
263 1.1 christos
264 1.1 christos return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
265 1.1 christos }
266 1.1 christos
267 1.1 christos /* Find and/or create a hash entry for local symbol. */
268 1.1 christos static struct elf_link_hash_entry *
269 1.1 christos elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table *htab,
270 1.1 christos bfd *abfd, const Elf_Internal_Rela *rel,
271 1.1 christos bool create)
272 1.1 christos {
273 1.1 christos struct loongarch_elf_link_hash_entry e, *ret;
274 1.1 christos asection *sec = abfd->sections;
275 1.1 christos hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, ELFNN_R_SYM (rel->r_info));
276 1.1 christos void **slot;
277 1.1 christos
278 1.1 christos e.elf.indx = sec->id;
279 1.1 christos e.elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
280 1.1 christos slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
281 1.1 christos create ? INSERT : NO_INSERT);
282 1.1 christos
283 1.1 christos if (!slot)
284 1.1 christos return NULL;
285 1.1 christos
286 1.1 christos if (*slot)
287 1.1 christos {
288 1.1 christos ret = (struct loongarch_elf_link_hash_entry *) *slot;
289 1.1 christos return &ret->elf;
290 1.1 christos }
291 1.1 christos
292 1.1 christos ret = ((struct loongarch_elf_link_hash_entry *)
293 1.1 christos objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
294 1.1 christos sizeof (struct loongarch_elf_link_hash_entry)));
295 1.1 christos if (ret)
296 1.1 christos {
297 1.1 christos memset (ret, 0, sizeof (*ret));
298 1.1 christos ret->elf.indx = sec->id;
299 1.1 christos ret->elf.pointer_equality_needed = 0;
300 1.1 christos ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
301 1.1 christos ret->elf.dynindx = -1;
302 1.1 christos ret->elf.needs_plt = 0;
303 1.1 christos ret->elf.plt.refcount = -1;
304 1.1 christos ret->elf.got.refcount = -1;
305 1.1 christos ret->elf.def_dynamic = 0;
306 1.1 christos ret->elf.def_regular = 1;
307 1.1 christos ret->elf.ref_dynamic = 0; /* This should be always 0 for local. */
308 1.1 christos ret->elf.ref_regular = 0;
309 1.1 christos ret->elf.forced_local = 1;
310 1.1 christos ret->elf.root.type = bfd_link_hash_defined;
311 1.1 christos *slot = ret;
312 1.1 christos }
313 1.1 christos return &ret->elf;
314 1.1 christos }
315 1.1 christos
316 1.1 christos /* Destroy an LoongArch elf linker hash table. */
317 1.1 christos
318 1.1 christos static void
319 1.1 christos elfNN_loongarch_link_hash_table_free (bfd *obfd)
320 1.1 christos {
321 1.1 christos struct loongarch_elf_link_hash_table *ret;
322 1.1 christos ret = (struct loongarch_elf_link_hash_table *) obfd->link.hash;
323 1.1 christos
324 1.1 christos if (ret->loc_hash_table)
325 1.1 christos htab_delete (ret->loc_hash_table);
326 1.1 christos if (ret->loc_hash_memory)
327 1.1 christos objalloc_free ((struct objalloc *) ret->loc_hash_memory);
328 1.1 christos
329 1.1 christos _bfd_elf_link_hash_table_free (obfd);
330 1.1 christos }
331 1.1 christos
332 1.1 christos /* Create a LoongArch ELF linker hash table. */
333 1.1 christos
334 1.1 christos static struct bfd_link_hash_table *
335 1.1 christos loongarch_elf_link_hash_table_create (bfd *abfd)
336 1.1 christos {
337 1.1 christos struct loongarch_elf_link_hash_table *ret;
338 1.1 christos bfd_size_type amt = sizeof (struct loongarch_elf_link_hash_table);
339 1.1 christos
340 1.1 christos ret = (struct loongarch_elf_link_hash_table *) bfd_zmalloc (amt);
341 1.1 christos if (ret == NULL)
342 1.1 christos return NULL;
343 1.1 christos
344 1.1 christos if (!_bfd_elf_link_hash_table_init
345 1.1 christos (&ret->elf, abfd, link_hash_newfunc,
346 1.1 christos sizeof (struct loongarch_elf_link_hash_entry), LARCH_ELF_DATA))
347 1.1 christos {
348 1.1 christos free (ret);
349 1.1 christos return NULL;
350 1.1 christos }
351 1.1 christos
352 1.1 christos ret->max_alignment = MINUS_ONE;
353 1.1 christos
354 1.1 christos ret->loc_hash_table = htab_try_create (1024, elfNN_loongarch_local_htab_hash,
355 1.1 christos elfNN_loongarch_local_htab_eq, NULL);
356 1.1 christos ret->loc_hash_memory = objalloc_create ();
357 1.1 christos if (!ret->loc_hash_table || !ret->loc_hash_memory)
358 1.1 christos {
359 1.1 christos elfNN_loongarch_link_hash_table_free (abfd);
360 1.1 christos return NULL;
361 1.1 christos }
362 1.1 christos ret->elf.root.hash_table_free = elfNN_loongarch_link_hash_table_free;
363 1.1 christos
364 1.1 christos return &ret->elf.root;
365 1.1 christos }
366 1.1 christos
367 1.1 christos /* Merge backend specific data from an object file to the output
368 1.1 christos object file when linking. */
369 1.1 christos
370 1.1 christos static bool
371 1.1 christos elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
372 1.1 christos {
373 1.1 christos bfd *obfd = info->output_bfd;
374 1.1 christos flagword in_flags = elf_elfheader (ibfd)->e_flags;
375 1.1 christos flagword out_flags = elf_elfheader (obfd)->e_flags;
376 1.1 christos
377 1.1 christos if (!is_loongarch_elf (ibfd) || !is_loongarch_elf (obfd))
378 1.1 christos return true;
379 1.1 christos
380 1.1 christos if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
381 1.1 christos {
382 1.1 christos _bfd_error_handler (_("%pB: ABI is incompatible with that of "
383 1.1 christos "the selected emulation:\n"
384 1.1 christos " target emulation `%s' does not match `%s'"),
385 1.1 christos ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
386 1.1 christos return false;
387 1.1 christos }
388 1.1 christos
389 1.1 christos if (!_bfd_elf_merge_object_attributes (ibfd, info))
390 1.1 christos return false;
391 1.1 christos
392 1.1 christos /* If the input BFD is not a dynamic object and it does not contain any
393 1.1 christos non-data sections, do not account its ABI. For example, various
394 1.1 christos packages produces such data-only relocatable objects with
395 1.1 christos `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
396 1.1 christos But they are compatible with all ABIs. */
397 1.1 christos if (!(ibfd->flags & DYNAMIC))
398 1.1 christos {
399 1.1 christos asection *sec;
400 1.1 christos bool have_code_sections = false;
401 1.1 christos for (sec = ibfd->sections; sec != NULL; sec = sec->next)
402 1.1 christos if ((bfd_section_flags (sec)
403 1.1 christos & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
404 1.1 christos == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
405 1.1 christos {
406 1.1 christos have_code_sections = true;
407 1.1 christos break;
408 1.1 christos }
409 1.1 christos if (!have_code_sections)
410 1.1 christos return true;
411 1.1 christos }
412 1.1 christos
413 1.1 christos if (!elf_flags_init (obfd))
414 1.1 christos {
415 1.1 christos elf_flags_init (obfd) = true;
416 1.1 christos elf_elfheader (obfd)->e_flags = in_flags;
417 1.1 christos return true;
418 1.1 christos }
419 1.1 christos else if (out_flags != in_flags)
420 1.1 christos {
421 1.1 christos if ((EF_LOONGARCH_IS_OBJ_V0 (out_flags)
422 1.1 christos && EF_LOONGARCH_IS_OBJ_V1 (in_flags))
423 1.1 christos || (EF_LOONGARCH_IS_OBJ_V0 (in_flags)
424 1.1 christos && EF_LOONGARCH_IS_OBJ_V1 (out_flags)))
425 1.1 christos {
426 1.1 christos elf_elfheader (obfd)->e_flags |= EF_LOONGARCH_OBJABI_V1;
427 1.1 christos out_flags = elf_elfheader (obfd)->e_flags;
428 1.1 christos in_flags = out_flags;
429 1.1 christos }
430 1.1 christos }
431 1.1 christos
432 1.1 christos /* Disallow linking different ABIs. */
433 1.1 christos /* Only check relocation version.
434 1.1 christos The obj_v0 is compatible with obj_v1. */
435 1.1 christos if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
436 1.1 christos {
437 1.1 christos _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd);
438 1.1 christos goto fail;
439 1.1 christos }
440 1.1 christos
441 1.1 christos return true;
442 1.1 christos
443 1.1 christos fail:
444 1.1 christos bfd_set_error (bfd_error_bad_value);
445 1.1 christos return false;
446 1.1 christos }
447 1.1 christos
448 1.1 christos /* Create the .got section. */
449 1.1 christos
450 1.1 christos static bool
451 1.1 christos loongarch_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
452 1.1 christos {
453 1.1 christos flagword flags;
454 1.1 christos char *name;
455 1.1 christos asection *s, *s_got;
456 1.1 christos struct elf_link_hash_entry *h;
457 1.1 christos const struct elf_backend_data *bed = get_elf_backend_data (abfd);
458 1.1 christos struct elf_link_hash_table *htab = elf_hash_table (info);
459 1.1 christos
460 1.1 christos /* This function may be called more than once. */
461 1.1 christos if (htab->sgot != NULL)
462 1.1 christos return true;
463 1.1 christos
464 1.1 christos flags = bed->dynamic_sec_flags;
465 1.1 christos name = bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got";
466 1.1 christos s = bfd_make_section_anyway_with_flags (abfd, name, flags | SEC_READONLY);
467 1.1 christos
468 1.1 christos if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
469 1.1 christos return false;
470 1.1 christos htab->srelgot = s;
471 1.1 christos
472 1.1 christos s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
473 1.1 christos if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
474 1.1 christos return false;
475 1.1 christos htab->sgot = s;
476 1.1 christos
477 1.1 christos /* The first bit of the global offset table is the header. */
478 1.1 christos s->size += bed->got_header_size;
479 1.1 christos
480 1.1 christos if (bed->want_got_plt)
481 1.1 christos {
482 1.1 christos s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
483 1.1 christos if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
484 1.1 christos return false;
485 1.1 christos htab->sgotplt = s;
486 1.1 christos
487 1.1 christos /* Reserve room for the header. */
488 1.1 christos s->size = GOTPLT_HEADER_SIZE;
489 1.1 christos }
490 1.1 christos
491 1.1 christos if (bed->want_got_sym)
492 1.1 christos {
493 1.1 christos /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
494 1.1 christos section. We don't do this in the linker script because we don't want
495 1.1 christos to define the symbol if we are not creating a global offset table. */
496 1.1 christos h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
497 1.1 christos "_GLOBAL_OFFSET_TABLE_");
498 1.1 christos elf_hash_table (info)->hgot = h;
499 1.1 christos if (h == NULL)
500 1.1 christos return false;
501 1.1 christos }
502 1.1 christos return true;
503 1.1 christos }
504 1.1 christos
505 1.1 christos /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
506 1.1 christos .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
507 1.1 christos hash table. */
508 1.1 christos
509 1.1 christos static bool
510 1.1 christos loongarch_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
511 1.1 christos {
512 1.1 christos struct loongarch_elf_link_hash_table *htab;
513 1.1 christos
514 1.1 christos htab = loongarch_elf_hash_table (info);
515 1.1 christos BFD_ASSERT (htab != NULL);
516 1.1 christos
517 1.1 christos if (!loongarch_elf_create_got_section (dynobj, info))
518 1.1 christos return false;
519 1.1 christos
520 1.1 christos if (!_bfd_elf_create_dynamic_sections (dynobj, info))
521 1.1 christos return false;
522 1.1 christos
523 1.1 christos if (!bfd_link_pic (info))
524 1.1 christos htab->sdyntdata
525 1.1 christos = bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
526 1.1 christos SEC_ALLOC | SEC_THREAD_LOCAL);
527 1.1 christos
528 1.1 christos if (!htab->elf.splt || !htab->elf.srelplt || !htab->elf.sdynbss
529 1.1 christos || (!bfd_link_pic (info) && (!htab->elf.srelbss || !htab->sdyntdata)))
530 1.1 christos abort ();
531 1.1 christos
532 1.1 christos return true;
533 1.1 christos }
534 1.1 christos
535 1.1 christos static bool
536 1.1 christos loongarch_elf_record_tls_and_got_reference (bfd *abfd,
537 1.1 christos struct bfd_link_info *info,
538 1.1 christos struct elf_link_hash_entry *h,
539 1.1 christos unsigned long symndx,
540 1.1 christos char tls_type)
541 1.1 christos {
542 1.1 christos struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
543 1.1 christos Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
544 1.1 christos
545 1.1 christos /* This is a global offset table entry for a local symbol. */
546 1.1 christos if (elf_local_got_refcounts (abfd) == NULL)
547 1.1 christos {
548 1.1 christos bfd_size_type size =
549 1.1 christos symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (tls_type));
550 1.1 christos if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
551 1.1 christos return false;
552 1.1 christos _bfd_loongarch_elf_local_got_tls_type (abfd) =
553 1.1 christos (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
554 1.1 christos }
555 1.1 christos
556 1.1 christos switch (tls_type)
557 1.1 christos {
558 1.1 christos case GOT_NORMAL:
559 1.1 christos case GOT_TLS_GD:
560 1.1 christos case GOT_TLS_IE:
561 1.1 christos /* Need GOT. */
562 1.1 christos if (htab->elf.sgot == NULL
563 1.1 christos && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
564 1.1 christos return false;
565 1.1 christos if (h)
566 1.1 christos {
567 1.1 christos if (h->got.refcount < 0)
568 1.1 christos h->got.refcount = 0;
569 1.1 christos h->got.refcount++;
570 1.1 christos }
571 1.1 christos else
572 1.1 christos elf_local_got_refcounts (abfd)[symndx]++;
573 1.1 christos break;
574 1.1 christos case GOT_TLS_LE:
575 1.1 christos /* No need for GOT. */
576 1.1 christos break;
577 1.1 christos default:
578 1.1 christos _bfd_error_handler (_("Internal error: unreachable."));
579 1.1 christos return false;
580 1.1 christos }
581 1.1 christos
582 1.1 christos char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
583 1.1 christos *new_tls_type |= tls_type;
584 1.1 christos if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
585 1.1 christos {
586 1.1 christos _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
587 1.1 christos "thread local symbol"),
588 1.1 christos abfd,
589 1.1 christos h ? h->root.root.string : "<local>");
590 1.1 christos return false;
591 1.1 christos }
592 1.1 christos
593 1.1 christos return true;
594 1.1 christos }
595 1.1 christos
596 1.1 christos /* Look through the relocs for a section during the first phase, and
597 1.1 christos allocate space in the global offset table or procedure linkage
598 1.1 christos table. */
599 1.1 christos
600 1.1 christos static bool
601 1.1 christos loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
602 1.1 christos asection *sec, const Elf_Internal_Rela *relocs)
603 1.1 christos {
604 1.1 christos struct loongarch_elf_link_hash_table *htab;
605 1.1 christos Elf_Internal_Shdr *symtab_hdr;
606 1.1 christos struct elf_link_hash_entry **sym_hashes;
607 1.1 christos const Elf_Internal_Rela *rel;
608 1.1 christos asection *sreloc = NULL;
609 1.1 christos
610 1.1 christos if (bfd_link_relocatable (info))
611 1.1 christos return true;
612 1.1 christos
613 1.1 christos htab = loongarch_elf_hash_table (info);
614 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
615 1.1 christos sym_hashes = elf_sym_hashes (abfd);
616 1.1 christos
617 1.1 christos if (htab->elf.dynobj == NULL)
618 1.1 christos htab->elf.dynobj = abfd;
619 1.1 christos
620 1.1 christos for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
621 1.1 christos {
622 1.1 christos unsigned int r_type;
623 1.1 christos unsigned int r_symndx;
624 1.1 christos struct elf_link_hash_entry *h;
625 1.1 christos Elf_Internal_Sym *isym = NULL;
626 1.1 christos
627 1.1 christos r_symndx = ELFNN_R_SYM (rel->r_info);
628 1.1 christos r_type = ELFNN_R_TYPE (rel->r_info);
629 1.1 christos
630 1.1 christos if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
631 1.1 christos {
632 1.1 christos _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx);
633 1.1 christos return false;
634 1.1 christos }
635 1.1 christos
636 1.1 christos if (r_symndx < symtab_hdr->sh_info)
637 1.1 christos {
638 1.1 christos /* A local symbol. */
639 1.1 christos isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
640 1.1 christos if (isym == NULL)
641 1.1 christos return false;
642 1.1 christos
643 1.1 christos if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
644 1.1 christos {
645 1.1 christos h = elfNN_loongarch_get_local_sym_hash (htab, abfd, rel, true);
646 1.1 christos if (h == NULL)
647 1.1 christos return false;
648 1.1 christos
649 1.1 christos h->type = STT_GNU_IFUNC;
650 1.1 christos h->ref_regular = 1;
651 1.1 christos }
652 1.1 christos else
653 1.1 christos h = NULL;
654 1.1 christos }
655 1.1 christos else
656 1.1 christos {
657 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info];
658 1.1 christos while (h->root.type == bfd_link_hash_indirect
659 1.1 christos || h->root.type == bfd_link_hash_warning)
660 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
661 1.1 christos }
662 1.1 christos
663 1.1 christos /* It is referenced by a non-shared object. */
664 1.1 christos if (h != NULL)
665 1.1 christos h->ref_regular = 1;
666 1.1 christos
667 1.1 christos if (h && h->type == STT_GNU_IFUNC)
668 1.1 christos {
669 1.1 christos if (htab->elf.dynobj == NULL)
670 1.1 christos htab->elf.dynobj = abfd;
671 1.1 christos
672 1.1 christos /* Create 'irelifunc' in PIC object. */
673 1.1 christos if (bfd_link_pic (info)
674 1.1 christos && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
675 1.1 christos return false;
676 1.1 christos /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
677 1.1 christos else if (!htab->elf.splt
678 1.1 christos && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
679 1.1 christos return false;
680 1.1 christos /* Create the ifunc sections, iplt and ipltgot, for static
681 1.1 christos executables. */
682 1.1 christos if ((r_type == R_LARCH_64 || r_type == R_LARCH_32)
683 1.1 christos && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
684 1.1 christos return false;
685 1.1 christos
686 1.1 christos if (h->plt.refcount < 0)
687 1.1 christos h->plt.refcount = 0;
688 1.1 christos h->plt.refcount++;
689 1.1 christos h->needs_plt = 1;
690 1.1 christos
691 1.1 christos elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
692 1.1 christos }
693 1.1 christos
694 1.1 christos int need_dynreloc = 0;
695 1.1 christos int only_need_pcrel = 0;
696 1.1 christos
697 1.1 christos switch (r_type)
698 1.1 christos {
699 1.1 christos case R_LARCH_GOT_PC_HI20:
700 1.1 christos case R_LARCH_GOT_HI20:
701 1.1 christos case R_LARCH_SOP_PUSH_GPREL:
702 1.1 christos /* For la.global. */
703 1.1 christos if (h)
704 1.1 christos h->pointer_equality_needed = 1;
705 1.1 christos if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
706 1.1 christos r_symndx,
707 1.1 christos GOT_NORMAL))
708 1.1 christos return false;
709 1.1 christos break;
710 1.1 christos
711 1.1 christos case R_LARCH_TLS_LD_PC_HI20:
712 1.1 christos case R_LARCH_TLS_LD_HI20:
713 1.1 christos case R_LARCH_TLS_GD_PC_HI20:
714 1.1 christos case R_LARCH_TLS_GD_HI20:
715 1.1 christos case R_LARCH_SOP_PUSH_TLS_GD:
716 1.1 christos if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
717 1.1 christos r_symndx,
718 1.1 christos GOT_TLS_GD))
719 1.1 christos return false;
720 1.1 christos break;
721 1.1 christos
722 1.1 christos case R_LARCH_TLS_IE_PC_HI20:
723 1.1 christos case R_LARCH_TLS_IE_HI20:
724 1.1 christos case R_LARCH_SOP_PUSH_TLS_GOT:
725 1.1 christos if (bfd_link_pic (info))
726 1.1 christos /* May fail for lazy-bind. */
727 1.1 christos info->flags |= DF_STATIC_TLS;
728 1.1 christos
729 1.1 christos if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
730 1.1 christos r_symndx,
731 1.1 christos GOT_TLS_IE))
732 1.1 christos return false;
733 1.1 christos break;
734 1.1 christos
735 1.1 christos case R_LARCH_TLS_LE_HI20:
736 1.1 christos case R_LARCH_SOP_PUSH_TLS_TPREL:
737 1.1 christos if (!bfd_link_executable (info))
738 1.1 christos return false;
739 1.1 christos
740 1.1 christos info->flags |= DF_STATIC_TLS;
741 1.1 christos
742 1.1 christos if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
743 1.1 christos r_symndx,
744 1.1 christos GOT_TLS_LE))
745 1.1 christos return false;
746 1.1 christos break;
747 1.1 christos
748 1.1 christos case R_LARCH_ABS_HI20:
749 1.1 christos case R_LARCH_SOP_PUSH_ABSOLUTE:
750 1.1 christos if (h != NULL)
751 1.1 christos /* If this reloc is in a read-only section, we might
752 1.1 christos need a copy reloc. We can't check reliably at this
753 1.1 christos stage whether the section is read-only, as input
754 1.1 christos sections have not yet been mapped to output sections.
755 1.1 christos Tentatively set the flag for now, and correct in
756 1.1 christos adjust_dynamic_symbol. */
757 1.1 christos h->non_got_ref = 1;
758 1.1 christos break;
759 1.1 christos
760 1.1 christos case R_LARCH_PCALA_HI20:
761 1.1 christos if (h != NULL)
762 1.1 christos {
763 1.1 christos /* For pcalau12i + jirl. */
764 1.1 christos h->needs_plt = 1;
765 1.1 christos if (h->plt.refcount < 0)
766 1.1 christos h->plt.refcount = 0;
767 1.1 christos h->plt.refcount++;
768 1.1 christos
769 1.1 christos h->non_got_ref = 1;
770 1.1 christos h->pointer_equality_needed = 1;
771 1.1 christos }
772 1.1 christos
773 1.1 christos break;
774 1.1 christos
775 1.1 christos case R_LARCH_B21:
776 1.1 christos case R_LARCH_B16:
777 1.1 christos case R_LARCH_B26:
778 1.1 christos if (h != NULL)
779 1.1 christos {
780 1.1 christos h->needs_plt = 1;
781 1.1 christos if (!bfd_link_pic (info))
782 1.1 christos h->non_got_ref = 1;
783 1.1 christos
784 1.1 christos /* We try to create PLT stub for all non-local function. */
785 1.1 christos if (h->plt.refcount < 0)
786 1.1 christos h->plt.refcount = 0;
787 1.1 christos h->plt.refcount++;
788 1.1 christos }
789 1.1 christos
790 1.1 christos break;
791 1.1 christos
792 1.1 christos case R_LARCH_SOP_PUSH_PCREL:
793 1.1 christos if (h != NULL)
794 1.1 christos {
795 1.1 christos if (!bfd_link_pic (info))
796 1.1 christos h->non_got_ref = 1;
797 1.1 christos
798 1.1 christos /* We try to create PLT stub for all non-local function. */
799 1.1 christos if (h->plt.refcount < 0)
800 1.1 christos h->plt.refcount = 0;
801 1.1 christos h->plt.refcount++;
802 1.1 christos h->pointer_equality_needed = 1;
803 1.1 christos }
804 1.1 christos
805 1.1 christos break;
806 1.1 christos
807 1.1 christos case R_LARCH_SOP_PUSH_PLT_PCREL:
808 1.1 christos /* This symbol requires a procedure linkage table entry. We
809 1.1 christos actually build the entry in adjust_dynamic_symbol,
810 1.1 christos because this might be a case of linking PIC code without
811 1.1 christos linking in any dynamic objects, in which case we don't
812 1.1 christos need to generate a procedure linkage table after all. */
813 1.1 christos if (h != NULL)
814 1.1 christos {
815 1.1 christos h->needs_plt = 1;
816 1.1 christos if (h->plt.refcount < 0)
817 1.1 christos h->plt.refcount = 0;
818 1.1 christos h->plt.refcount++;
819 1.1 christos }
820 1.1 christos break;
821 1.1 christos
822 1.1 christos case R_LARCH_TLS_DTPREL32:
823 1.1 christos case R_LARCH_TLS_DTPREL64:
824 1.1 christos need_dynreloc = 1;
825 1.1 christos only_need_pcrel = 1;
826 1.1 christos break;
827 1.1 christos
828 1.1 christos case R_LARCH_JUMP_SLOT:
829 1.1 christos case R_LARCH_32:
830 1.1 christos case R_LARCH_64:
831 1.1 christos
832 1.1 christos need_dynreloc = 1;
833 1.1 christos
834 1.1 christos /* If resolved symbol is defined in this object,
835 1.1 christos 1. Under pie, the symbol is known. We convert it
836 1.1 christos into R_LARCH_RELATIVE and need load-addr still.
837 1.1 christos 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
838 1.1 christos 3. Under dll, R_LARCH_NN can't be changed normally, since
839 1.1 christos its defination could be covered by the one in executable.
840 1.1 christos For symbolic, we convert it into R_LARCH_RELATIVE.
841 1.1 christos Thus, only under pde, it needs pcrel only. We discard it. */
842 1.1 christos only_need_pcrel = bfd_link_pde (info);
843 1.1 christos
844 1.1 christos if (h != NULL
845 1.1 christos && (!bfd_link_pic (info)
846 1.1 christos || h->type == STT_GNU_IFUNC))
847 1.1 christos {
848 1.1 christos /* This reloc might not bind locally. */
849 1.1 christos h->non_got_ref = 1;
850 1.1 christos h->pointer_equality_needed = 1;
851 1.1 christos
852 1.1 christos if (!h->def_regular
853 1.1 christos || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
854 1.1 christos {
855 1.1 christos /* We may need a .plt entry if the symbol is a function
856 1.1 christos defined in a shared lib or is a function referenced
857 1.1 christos from the code or read-only section. */
858 1.1 christos h->plt.refcount += 1;
859 1.1 christos }
860 1.1 christos }
861 1.1 christos break;
862 1.1 christos
863 1.1 christos case R_LARCH_GNU_VTINHERIT:
864 1.1 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
865 1.1 christos return false;
866 1.1 christos break;
867 1.1 christos
868 1.1 christos case R_LARCH_GNU_VTENTRY:
869 1.1 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
870 1.1 christos return false;
871 1.1 christos break;
872 1.1 christos
873 1.1 christos default:
874 1.1 christos break;
875 1.1 christos }
876 1.1 christos
877 1.1 christos /* Record some info for sizing and allocating dynamic entry. */
878 1.1 christos if (need_dynreloc && (sec->flags & SEC_ALLOC))
879 1.1 christos {
880 1.1 christos /* When creating a shared object, we must copy these
881 1.1 christos relocs into the output file. We create a reloc
882 1.1 christos section in dynobj and make room for the reloc. */
883 1.1 christos struct elf_dyn_relocs *p;
884 1.1 christos struct elf_dyn_relocs **head;
885 1.1 christos
886 1.1 christos if (sreloc == NULL)
887 1.1 christos {
888 1.1 christos sreloc
889 1.1 christos = _bfd_elf_make_dynamic_reloc_section (sec, htab->elf.dynobj,
890 1.1 christos LARCH_ELF_LOG_WORD_BYTES,
891 1.1 christos abfd, /*rela?*/ true);
892 1.1 christos if (sreloc == NULL)
893 1.1 christos return false;
894 1.1 christos }
895 1.1 christos
896 1.1 christos /* If this is a global symbol, we count the number of
897 1.1 christos relocations we need for this symbol. */
898 1.1 christos if (h != NULL)
899 1.1 christos head = &h->dyn_relocs;
900 1.1 christos else
901 1.1 christos {
902 1.1 christos /* Track dynamic relocs needed for local syms too.
903 1.1 christos We really need local syms available to do this
904 1.1 christos easily. Oh well. */
905 1.1 christos
906 1.1 christos asection *s;
907 1.1 christos void *vpp;
908 1.1 christos
909 1.1 christos s = bfd_section_from_elf_index (abfd, isym->st_shndx);
910 1.1 christos if (s == NULL)
911 1.1 christos s = sec;
912 1.1 christos
913 1.1 christos vpp = &elf_section_data (s)->local_dynrel;
914 1.1 christos head = (struct elf_dyn_relocs **) vpp;
915 1.1 christos }
916 1.1 christos
917 1.1 christos p = *head;
918 1.1 christos if (p == NULL || p->sec != sec)
919 1.1 christos {
920 1.1 christos bfd_size_type amt = sizeof *p;
921 1.1 christos p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt);
922 1.1 christos if (p == NULL)
923 1.1 christos return false;
924 1.1 christos p->next = *head;
925 1.1 christos *head = p;
926 1.1 christos p->sec = sec;
927 1.1 christos p->count = 0;
928 1.1 christos p->pc_count = 0;
929 1.1 christos }
930 1.1 christos
931 1.1 christos p->count++;
932 1.1 christos p->pc_count += only_need_pcrel;
933 1.1 christos }
934 1.1 christos }
935 1.1 christos
936 1.1 christos return true;
937 1.1 christos }
938 1.1 christos
939 1.1 christos /* Find dynamic relocs for H that apply to read-only sections. */
940 1.1 christos
941 1.1 christos static asection *
942 1.1 christos readonly_dynrelocs (struct elf_link_hash_entry *h)
943 1.1 christos {
944 1.1 christos struct elf_dyn_relocs *p;
945 1.1 christos
946 1.1 christos for (p = h->dyn_relocs; p != NULL; p = p->next)
947 1.1 christos {
948 1.1 christos asection *s = p->sec->output_section;
949 1.1 christos
950 1.1 christos if (s != NULL && (s->flags & SEC_READONLY) != 0)
951 1.1 christos return p->sec;
952 1.1 christos }
953 1.1 christos return NULL;
954 1.1 christos }
955 1.1 christos
956 1.1 christos /* Adjust a symbol defined by a dynamic object and referenced by a
957 1.1 christos regular object. The current definition is in some section of the
958 1.1 christos dynamic object, but we're not including those sections. We have to
959 1.1 christos change the definition to something the rest of the link can
960 1.1 christos understand. */
961 1.1 christos static bool
962 1.1 christos loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
963 1.1 christos struct elf_link_hash_entry *h)
964 1.1 christos {
965 1.1 christos struct loongarch_elf_link_hash_table *htab;
966 1.1 christos bfd *dynobj;
967 1.1 christos
968 1.1 christos htab = loongarch_elf_hash_table (info);
969 1.1 christos BFD_ASSERT (htab != NULL);
970 1.1 christos
971 1.1 christos dynobj = htab->elf.dynobj;
972 1.1 christos
973 1.1 christos /* Make sure we know what is going on here. */
974 1.1 christos BFD_ASSERT (dynobj != NULL
975 1.1 christos && (h->needs_plt || h->type == STT_GNU_IFUNC || h->is_weakalias
976 1.1 christos || (h->def_dynamic && h->ref_regular && !h->def_regular)));
977 1.1 christos
978 1.1 christos /* If this is a function, put it in the procedure linkage table. We
979 1.1 christos will fill in the contents of the procedure linkage table later
980 1.1 christos (although we could actually do it here). */
981 1.1 christos if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
982 1.1 christos {
983 1.1 christos if (h->plt.refcount < 0
984 1.1 christos || (h->type != STT_GNU_IFUNC
985 1.1 christos && (SYMBOL_REFERENCES_LOCAL (info, h)
986 1.1 christos || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
987 1.1 christos && h->root.type == bfd_link_hash_undefweak))))
988 1.1 christos {
989 1.1 christos /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
990 1.1 christos in an input file, but the symbol was never referred to by a
991 1.1 christos dynamic object, or if all references were garbage collected.
992 1.1 christos In such a case, we don't actually need to build a PLT entry. */
993 1.1 christos h->plt.offset = MINUS_ONE;
994 1.1 christos h->needs_plt = 0;
995 1.1 christos }
996 1.1 christos else
997 1.1 christos h->needs_plt = 1;
998 1.1 christos
999 1.1 christos return true;
1000 1.1 christos }
1001 1.1 christos else
1002 1.1 christos h->plt.offset = MINUS_ONE;
1003 1.1 christos
1004 1.1 christos /* If this is a weak symbol, and there is a real definition, the
1005 1.1 christos processor independent code will have arranged for us to see the
1006 1.1 christos real definition first, and we can just use the same value. */
1007 1.1 christos if (h->is_weakalias)
1008 1.1 christos {
1009 1.1 christos struct elf_link_hash_entry *def = weakdef (h);
1010 1.1 christos BFD_ASSERT (def->root.type == bfd_link_hash_defined);
1011 1.1 christos h->root.u.def.section = def->root.u.def.section;
1012 1.1 christos h->root.u.def.value = def->root.u.def.value;
1013 1.1 christos return true;
1014 1.1 christos }
1015 1.1 christos
1016 1.1 christos /* R_LARCH_COPY is not adept glibc, not to generate. */
1017 1.1 christos /* Can not print anything, because make check ld. */
1018 1.1 christos return true;
1019 1.1 christos }
1020 1.1 christos
1021 1.1 christos /* Allocate space in .plt, .got and associated reloc sections for
1022 1.1 christos dynamic relocs. */
1023 1.1 christos
1024 1.1 christos static bool
1025 1.1 christos allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1026 1.1 christos {
1027 1.1 christos struct bfd_link_info *info;
1028 1.1 christos struct loongarch_elf_link_hash_table *htab;
1029 1.1 christos struct elf_dyn_relocs *p;
1030 1.1 christos
1031 1.1 christos if (h->root.type == bfd_link_hash_indirect)
1032 1.1 christos return true;
1033 1.1 christos
1034 1.1 christos if (h->type == STT_GNU_IFUNC
1035 1.1 christos && h->def_regular)
1036 1.1 christos return true;
1037 1.1 christos
1038 1.1 christos info = (struct bfd_link_info *) inf;
1039 1.1 christos htab = loongarch_elf_hash_table (info);
1040 1.1 christos bool dyn = htab->elf.dynamic_sections_created;
1041 1.1 christos BFD_ASSERT (htab != NULL);
1042 1.1 christos
1043 1.1 christos do
1044 1.1 christos {
1045 1.1 christos asection *plt, *gotplt, *relplt;
1046 1.1 christos
1047 1.1 christos if (!h->needs_plt)
1048 1.1 christos break;
1049 1.1 christos
1050 1.1 christos h->needs_plt = 0;
1051 1.1 christos
1052 1.1 christos if (htab->elf.splt)
1053 1.1 christos {
1054 1.1 christos if (h->dynindx == -1 && !h->forced_local && dyn
1055 1.1 christos && h->root.type == bfd_link_hash_undefweak)
1056 1.1 christos {
1057 1.1 christos if (!bfd_elf_link_record_dynamic_symbol (info, h))
1058 1.1 christos return false;
1059 1.1 christos }
1060 1.1 christos
1061 1.1 christos if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
1062 1.1 christos && h->type != STT_GNU_IFUNC)
1063 1.1 christos break;
1064 1.1 christos
1065 1.1 christos plt = htab->elf.splt;
1066 1.1 christos gotplt = htab->elf.sgotplt;
1067 1.1 christos relplt = htab->elf.srelplt;
1068 1.1 christos }
1069 1.1 christos else if (htab->elf.iplt)
1070 1.1 christos {
1071 1.1 christos /* .iplt only for IFUNC. */
1072 1.1 christos if (h->type != STT_GNU_IFUNC)
1073 1.1 christos break;
1074 1.1 christos
1075 1.1 christos plt = htab->elf.iplt;
1076 1.1 christos gotplt = htab->elf.igotplt;
1077 1.1 christos relplt = htab->elf.irelplt;
1078 1.1 christos }
1079 1.1 christos else
1080 1.1 christos break;
1081 1.1 christos
1082 1.1 christos if (plt->size == 0)
1083 1.1 christos plt->size = PLT_HEADER_SIZE;
1084 1.1 christos
1085 1.1 christos h->plt.offset = plt->size;
1086 1.1 christos plt->size += PLT_ENTRY_SIZE;
1087 1.1 christos gotplt->size += GOT_ENTRY_SIZE;
1088 1.1 christos relplt->size += sizeof (ElfNN_External_Rela);
1089 1.1 christos
1090 1.1 christos /* If this symbol is not defined in a regular file, and we are
1091 1.1 christos not generating a shared library, then set the symbol to this
1092 1.1 christos location in the .plt. This is required to make function
1093 1.1 christos pointers compare as equal between the normal executable and
1094 1.1 christos the shared library. */
1095 1.1 christos if (!bfd_link_pic (info)
1096 1.1 christos && !h->def_regular)
1097 1.1 christos {
1098 1.1 christos h->root.u.def.section = plt;
1099 1.1 christos h->root.u.def.value = h->plt.offset;
1100 1.1 christos }
1101 1.1 christos
1102 1.1 christos h->needs_plt = 1;
1103 1.1 christos }
1104 1.1 christos while (0);
1105 1.1 christos
1106 1.1 christos if (!h->needs_plt)
1107 1.1 christos h->plt.offset = MINUS_ONE;
1108 1.1 christos
1109 1.1 christos if (0 < h->got.refcount)
1110 1.1 christos {
1111 1.1 christos asection *s;
1112 1.1 christos int tls_type = loongarch_elf_hash_entry (h)->tls_type;
1113 1.1 christos
1114 1.1 christos /* Make sure this symbol is output as a dynamic symbol.
1115 1.1 christos Undefined weak syms won't yet be marked as dynamic. */
1116 1.1 christos if (h->dynindx == -1 && !h->forced_local && dyn
1117 1.1 christos && h->root.type == bfd_link_hash_undefweak)
1118 1.1 christos {
1119 1.1 christos if (!bfd_elf_link_record_dynamic_symbol (info, h))
1120 1.1 christos return false;
1121 1.1 christos }
1122 1.1 christos
1123 1.1 christos s = htab->elf.sgot;
1124 1.1 christos h->got.offset = s->size;
1125 1.1 christos if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
1126 1.1 christos {
1127 1.1 christos /* TLS_GD needs two dynamic relocs and two GOT slots. */
1128 1.1 christos if (tls_type & GOT_TLS_GD)
1129 1.1 christos {
1130 1.1 christos s->size += 2 * GOT_ENTRY_SIZE;
1131 1.1 christos if (bfd_link_executable (info))
1132 1.1 christos {
1133 1.1 christos /* Link exe and not defined local. */
1134 1.1 christos if (!SYMBOL_REFERENCES_LOCAL (info, h))
1135 1.1 christos htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1136 1.1 christos }
1137 1.1 christos else
1138 1.1 christos {
1139 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
1140 1.1 christos htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1141 1.1 christos else
1142 1.1 christos htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1143 1.1 christos }
1144 1.1 christos }
1145 1.1 christos
1146 1.1 christos /* TLS_IE needs one dynamic reloc and one GOT slot. */
1147 1.1 christos if (tls_type & GOT_TLS_IE)
1148 1.1 christos {
1149 1.1 christos s->size += GOT_ENTRY_SIZE;
1150 1.1 christos
1151 1.1 christos if (bfd_link_executable (info))
1152 1.1 christos {
1153 1.1 christos /* Link exe and not defined local. */
1154 1.1 christos if (!SYMBOL_REFERENCES_LOCAL (info, h))
1155 1.1 christos htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1156 1.1 christos }
1157 1.1 christos else
1158 1.1 christos {
1159 1.1 christos htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1160 1.1 christos }
1161 1.1 christos }
1162 1.1 christos }
1163 1.1 christos else
1164 1.1 christos {
1165 1.1 christos s->size += GOT_ENTRY_SIZE;
1166 1.1 christos if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1167 1.1 christos || h->root.type != bfd_link_hash_undefweak)
1168 1.1 christos && (bfd_link_pic (info)
1169 1.1 christos || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
1170 1.1 christos h))
1171 1.1 christos && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
1172 1.1 christos /* Undefined weak symbol in static PIE resolves to 0 without
1173 1.1 christos any dynamic relocations. */
1174 1.1 christos htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1175 1.1 christos }
1176 1.1 christos }
1177 1.1 christos else
1178 1.1 christos h->got.offset = MINUS_ONE;
1179 1.1 christos
1180 1.1 christos if (h->dyn_relocs == NULL)
1181 1.1 christos return true;
1182 1.1 christos
1183 1.1 christos /* Extra dynamic relocate,
1184 1.1 christos * R_LARCH_64
1185 1.1 christos * R_LARCH_TLS_DTPRELNN
1186 1.1 christos * R_LARCH_JUMP_SLOT
1187 1.1 christos * R_LARCH_NN. */
1188 1.1 christos
1189 1.1 christos if (SYMBOL_CALLS_LOCAL (info, h))
1190 1.1 christos {
1191 1.1 christos struct elf_dyn_relocs **pp;
1192 1.1 christos
1193 1.1 christos for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
1194 1.1 christos {
1195 1.1 christos p->count -= p->pc_count;
1196 1.1 christos p->pc_count = 0;
1197 1.1 christos if (p->count == 0)
1198 1.1 christos *pp = p->next;
1199 1.1 christos else
1200 1.1 christos pp = &p->next;
1201 1.1 christos }
1202 1.1 christos }
1203 1.1 christos
1204 1.1 christos if (h->root.type == bfd_link_hash_undefweak)
1205 1.1 christos {
1206 1.1 christos if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
1207 1.1 christos || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
1208 1.1 christos || (!bfd_link_pic (info) && h->non_got_ref))
1209 1.1 christos h->dyn_relocs = NULL;
1210 1.1 christos else if (h->dynindx == -1 && !h->forced_local)
1211 1.1 christos {
1212 1.1 christos /* Make sure this symbol is output as a dynamic symbol.
1213 1.1 christos Undefined weak syms won't yet be marked as dynamic. */
1214 1.1 christos if (!bfd_elf_link_record_dynamic_symbol (info, h))
1215 1.1 christos return false;
1216 1.1 christos
1217 1.1 christos if (h->dynindx == -1)
1218 1.1 christos h->dyn_relocs = NULL;
1219 1.1 christos }
1220 1.1 christos }
1221 1.1 christos
1222 1.1 christos for (p = h->dyn_relocs; p != NULL; p = p->next)
1223 1.1 christos {
1224 1.1 christos asection *sreloc = elf_section_data (p->sec)->sreloc;
1225 1.1 christos sreloc->size += p->count * sizeof (ElfNN_External_Rela);
1226 1.1 christos }
1227 1.1 christos
1228 1.1 christos return true;
1229 1.1 christos }
1230 1.1 christos
1231 1.1 christos /* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
1232 1.1 christos For local def and ref ifunc,
1233 1.1 christos dynamic relocations are stored in
1234 1.1 christos 1. rela.srelgot section in dynamic object (dll or exec).
1235 1.1 christos 2. rela.irelplt section in static executable.
1236 1.1 christos Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
1237 1.1 christos instead of rela.srelplt. Glibc ELF loader will not support
1238 1.1 christos R_LARCH_IRELATIVE relocation in rela.plt. */
1239 1.1 christos
1240 1.1 christos static bool
1241 1.1 christos local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
1242 1.1 christos struct elf_link_hash_entry *h,
1243 1.1 christos struct elf_dyn_relocs **head,
1244 1.1 christos unsigned int plt_entry_size,
1245 1.1 christos unsigned int plt_header_size,
1246 1.1 christos unsigned int got_entry_size,
1247 1.1 christos bool avoid_plt)
1248 1.1 christos {
1249 1.1 christos asection *plt, *gotplt, *relplt;
1250 1.1 christos struct elf_dyn_relocs *p;
1251 1.1 christos unsigned int sizeof_reloc;
1252 1.1 christos const struct elf_backend_data *bed;
1253 1.1 christos struct elf_link_hash_table *htab;
1254 1.1 christos /* If AVOID_PLT is TRUE, don't use PLT if possible. */
1255 1.1 christos bool use_plt = !avoid_plt || h->plt.refcount > 0;
1256 1.1 christos bool need_dynreloc = !use_plt || bfd_link_pic (info);
1257 1.1 christos
1258 1.1 christos /* When a PIC object references a STT_GNU_IFUNC symbol defined
1259 1.1 christos in executable or it isn't referenced via PLT, the address of
1260 1.1 christos the resolved function may be used. But in non-PIC executable,
1261 1.1 christos the address of its plt slot may be used. Pointer equality may
1262 1.1 christos not work correctly. PIE or non-PLT reference should be used if
1263 1.1 christos pointer equality is required here.
1264 1.1 christos
1265 1.1 christos If STT_GNU_IFUNC symbol is defined in position-dependent executable,
1266 1.1 christos backend should change it to the normal function and set its address
1267 1.1 christos to its PLT entry which should be resolved by R_*_IRELATIVE at
1268 1.1 christos run-time. All external references should be resolved to its PLT in
1269 1.1 christos executable. */
1270 1.1 christos if (!need_dynreloc
1271 1.1 christos && !(bfd_link_pde (info) && h->def_regular)
1272 1.1 christos && (h->dynindx != -1
1273 1.1 christos || info->export_dynamic)
1274 1.1 christos && h->pointer_equality_needed)
1275 1.1 christos {
1276 1.1 christos info->callbacks->einfo
1277 1.1 christos /* xgettext:c-format. */
1278 1.1 christos (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
1279 1.1 christos "equality in `%pB' can not be used when making an "
1280 1.1 christos "executable; recompile with -fPIE and relink with -pie\n"),
1281 1.1 christos h->root.root.string,
1282 1.1 christos h->root.u.def.section->owner);
1283 1.1 christos bfd_set_error (bfd_error_bad_value);
1284 1.1 christos return false;
1285 1.1 christos }
1286 1.1 christos
1287 1.1 christos htab = elf_hash_table (info);
1288 1.1 christos
1289 1.1 christos /* When the symbol is marked with regular reference, if PLT isn't used
1290 1.1 christos or we are building a PIC object, we must keep dynamic relocation
1291 1.1 christos if there is non-GOT reference and use PLT if there is PC-relative
1292 1.1 christos reference. */
1293 1.1 christos if (need_dynreloc && h->ref_regular)
1294 1.1 christos {
1295 1.1 christos bool keep = false;
1296 1.1 christos for (p = *head; p != NULL; p = p->next)
1297 1.1 christos if (p->count)
1298 1.1 christos {
1299 1.1 christos h->non_got_ref = 1;
1300 1.1 christos /* Need dynamic relocations for non-GOT reference. */
1301 1.1 christos keep = true;
1302 1.1 christos if (p->pc_count)
1303 1.1 christos {
1304 1.1 christos /* Must use PLT for PC-relative reference. */
1305 1.1 christos use_plt = true;
1306 1.1 christos need_dynreloc = bfd_link_pic (info);
1307 1.1 christos break;
1308 1.1 christos }
1309 1.1 christos }
1310 1.1 christos if (keep)
1311 1.1 christos goto keep;
1312 1.1 christos }
1313 1.1 christos
1314 1.1 christos /* Support garbage collection against STT_GNU_IFUNC symbols. */
1315 1.1 christos if (h->plt.refcount <= 0 && h->got.refcount <= 0)
1316 1.1 christos {
1317 1.1 christos h->got = htab->init_got_offset;
1318 1.1 christos h->plt = htab->init_plt_offset;
1319 1.1 christos *head = NULL;
1320 1.1 christos return true;
1321 1.1 christos }
1322 1.1 christos
1323 1.1 christos /* Return and discard space for dynamic relocations against it if
1324 1.1 christos it is never referenced. */
1325 1.1 christos if (!h->ref_regular)
1326 1.1 christos {
1327 1.1 christos if (h->plt.refcount > 0
1328 1.1 christos || h->got.refcount > 0)
1329 1.1 christos abort ();
1330 1.1 christos h->got = htab->init_got_offset;
1331 1.1 christos h->plt = htab->init_plt_offset;
1332 1.1 christos *head = NULL;
1333 1.1 christos return true;
1334 1.1 christos }
1335 1.1 christos
1336 1.1 christos keep:
1337 1.1 christos bed = get_elf_backend_data (info->output_bfd);
1338 1.1 christos if (bed->rela_plts_and_copies_p)
1339 1.1 christos sizeof_reloc = bed->s->sizeof_rela;
1340 1.1 christos else
1341 1.1 christos sizeof_reloc = bed->s->sizeof_rel;
1342 1.1 christos
1343 1.1 christos /* When building a static executable, use iplt, igot.plt and
1344 1.1 christos rela.iplt sections for STT_GNU_IFUNC symbols. */
1345 1.1 christos if (htab->splt != NULL)
1346 1.1 christos {
1347 1.1 christos plt = htab->splt;
1348 1.1 christos gotplt = htab->sgotplt;
1349 1.1 christos /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */
1350 1.1 christos relplt = htab->srelgot;
1351 1.1 christos
1352 1.1 christos /* If this is the first plt entry and PLT is used, make room for
1353 1.1 christos the special first entry. */
1354 1.1 christos if (plt->size == 0 && use_plt)
1355 1.1 christos plt->size += plt_header_size;
1356 1.1 christos }
1357 1.1 christos else
1358 1.1 christos {
1359 1.1 christos plt = htab->iplt;
1360 1.1 christos gotplt = htab->igotplt;
1361 1.1 christos relplt = htab->irelplt;
1362 1.1 christos }
1363 1.1 christos
1364 1.1 christos if (use_plt)
1365 1.1 christos {
1366 1.1 christos /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
1367 1.1 christos the original value for R_*_IRELATIVE. */
1368 1.1 christos h->plt.offset = plt->size;
1369 1.1 christos
1370 1.1 christos /* Make room for this entry in the plt/iplt section. */
1371 1.1 christos plt->size += plt_entry_size;
1372 1.1 christos
1373 1.1 christos /* We also need to make an entry in the got.plt/got.iplt section,
1374 1.1 christos which will be placed in the got section by the linker script. */
1375 1.1 christos gotplt->size += got_entry_size;
1376 1.1 christos }
1377 1.1 christos
1378 1.1 christos /* We also need to make an entry in the rela.plt/.rela.iplt
1379 1.1 christos section for GOTPLT relocation if PLT is used. */
1380 1.1 christos if (use_plt)
1381 1.1 christos {
1382 1.1 christos relplt->size += sizeof_reloc;
1383 1.1 christos relplt->reloc_count++;
1384 1.1 christos }
1385 1.1 christos
1386 1.1 christos /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
1387 1.1 christos there is a non-GOT reference in a PIC object or PLT isn't used. */
1388 1.1 christos if (!need_dynreloc || !h->non_got_ref)
1389 1.1 christos *head = NULL;
1390 1.1 christos
1391 1.1 christos /* Finally, allocate space. */
1392 1.1 christos p = *head;
1393 1.1 christos if (p != NULL)
1394 1.1 christos {
1395 1.1 christos bfd_size_type count = 0;
1396 1.1 christos do
1397 1.1 christos {
1398 1.1 christos count += p->count;
1399 1.1 christos p = p->next;
1400 1.1 christos }
1401 1.1 christos while (p != NULL);
1402 1.1 christos
1403 1.1 christos htab->ifunc_resolvers = count != 0;
1404 1.1 christos
1405 1.1 christos /* Dynamic relocations are stored in
1406 1.1 christos 1. rela.srelgot section in PIC object.
1407 1.1 christos 2. rela.srelgot section in dynamic executable.
1408 1.1 christos 3. rela.irelplt section in static executable. */
1409 1.1 christos if (htab->splt != NULL)
1410 1.1 christos htab->srelgot->size += count * sizeof_reloc;
1411 1.1 christos else
1412 1.1 christos {
1413 1.1 christos relplt->size += count * sizeof_reloc;
1414 1.1 christos relplt->reloc_count += count;
1415 1.1 christos }
1416 1.1 christos }
1417 1.1 christos
1418 1.1 christos /* For STT_GNU_IFUNC symbol, got.plt has the real function address
1419 1.1 christos and got has the PLT entry adddress. We will load the GOT entry
1420 1.1 christos with the PLT entry in finish_dynamic_symbol if it is used. For
1421 1.1 christos branch, it uses got.plt. For symbol value, if PLT is used,
1422 1.1 christos 1. Use got.plt in a PIC object if it is forced local or not
1423 1.1 christos dynamic.
1424 1.1 christos 2. Use got.plt in a non-PIC object if pointer equality isn't
1425 1.1 christos needed.
1426 1.1 christos 3. Use got.plt in PIE.
1427 1.1 christos 4. Use got.plt if got isn't used.
1428 1.1 christos 5. Otherwise use got so that it can be shared among different
1429 1.1 christos objects at run-time.
1430 1.1 christos If PLT isn't used, always use got for symbol value.
1431 1.1 christos We only need to relocate got entry in PIC object or in dynamic
1432 1.1 christos executable without PLT. */
1433 1.1 christos if (use_plt
1434 1.1 christos && (h->got.refcount <= 0
1435 1.1 christos || (bfd_link_pic (info)
1436 1.1 christos && (h->dynindx == -1
1437 1.1 christos || h->forced_local))
1438 1.1 christos || (
1439 1.1 christos !h->pointer_equality_needed)
1440 1.1 christos || htab->sgot == NULL))
1441 1.1 christos {
1442 1.1 christos /* Use got.plt. */
1443 1.1 christos h->got.offset = (bfd_vma) -1;
1444 1.1 christos }
1445 1.1 christos else
1446 1.1 christos {
1447 1.1 christos if (!use_plt)
1448 1.1 christos {
1449 1.1 christos /* PLT isn't used. */
1450 1.1 christos h->plt.offset = (bfd_vma) -1;
1451 1.1 christos }
1452 1.1 christos if (h->got.refcount <= 0)
1453 1.1 christos {
1454 1.1 christos /* GOT isn't need when there are only relocations for static
1455 1.1 christos pointers. */
1456 1.1 christos h->got.offset = (bfd_vma) -1;
1457 1.1 christos }
1458 1.1 christos else
1459 1.1 christos {
1460 1.1 christos h->got.offset = htab->sgot->size;
1461 1.1 christos htab->sgot->size += got_entry_size;
1462 1.1 christos /* Need to relocate the GOT entry in a PIC object or PLT isn't
1463 1.1 christos used. Otherwise, the GOT entry will be filled with the PLT
1464 1.1 christos entry and dynamic GOT relocation isn't needed. */
1465 1.1 christos if (need_dynreloc)
1466 1.1 christos {
1467 1.1 christos /* For non-static executable, dynamic GOT relocation is in
1468 1.1 christos rela.got section, but for static executable, it is
1469 1.1 christos in rela.iplt section. */
1470 1.1 christos if (htab->splt != NULL)
1471 1.1 christos htab->srelgot->size += sizeof_reloc;
1472 1.1 christos else
1473 1.1 christos {
1474 1.1 christos relplt->size += sizeof_reloc;
1475 1.1 christos relplt->reloc_count++;
1476 1.1 christos }
1477 1.1 christos }
1478 1.1 christos }
1479 1.1 christos }
1480 1.1 christos
1481 1.1 christos return true;
1482 1.1 christos }
1483 1.1 christos
1484 1.1 christos /* Allocate space in .plt, .got and associated reloc sections for
1485 1.1 christos ifunc dynamic relocs. */
1486 1.1 christos
1487 1.1 christos static bool
1488 1.1 christos elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1489 1.1 christos {
1490 1.1 christos struct bfd_link_info *info;
1491 1.1 christos /* An example of a bfd_link_hash_indirect symbol is versioned
1492 1.1 christos symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
1493 1.1 christos -> __gxx_personality_v0(bfd_link_hash_defined)
1494 1.1 christos
1495 1.1 christos There is no need to process bfd_link_hash_indirect symbols here
1496 1.1 christos because we will also be presented with the concrete instance of
1497 1.1 christos the symbol and loongarch_elf_copy_indirect_symbol () will have been
1498 1.1 christos called to copy all relevant data from the generic to the concrete
1499 1.1 christos symbol instance. */
1500 1.1 christos if (h->root.type == bfd_link_hash_indirect)
1501 1.1 christos return true;
1502 1.1 christos
1503 1.1 christos if (h->root.type == bfd_link_hash_warning)
1504 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
1505 1.1 christos
1506 1.1 christos info = (struct bfd_link_info *) inf;
1507 1.1 christos
1508 1.1 christos /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
1509 1.1 christos here if it is defined and referenced in a non-shared object. */
1510 1.1 christos if (h->type == STT_GNU_IFUNC && h->def_regular)
1511 1.1 christos {
1512 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
1513 1.1 christos return local_allocate_ifunc_dyn_relocs (info, h,
1514 1.1 christos &h->dyn_relocs,
1515 1.1 christos PLT_ENTRY_SIZE,
1516 1.1 christos PLT_HEADER_SIZE,
1517 1.1 christos GOT_ENTRY_SIZE,
1518 1.1 christos false);
1519 1.1 christos else
1520 1.1 christos return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
1521 1.1 christos &h->dyn_relocs,
1522 1.1 christos PLT_ENTRY_SIZE,
1523 1.1 christos PLT_HEADER_SIZE,
1524 1.1 christos GOT_ENTRY_SIZE,
1525 1.1 christos false);
1526 1.1 christos }
1527 1.1 christos
1528 1.1 christos return true;
1529 1.1 christos }
1530 1.1 christos
1531 1.1 christos /* Allocate space in .plt, .got and associated reloc sections for
1532 1.1 christos ifunc dynamic relocs. */
1533 1.1 christos
1534 1.1 christos static bool
1535 1.1 christos elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
1536 1.1 christos {
1537 1.1 christos struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
1538 1.1 christos
1539 1.1 christos if (h->type != STT_GNU_IFUNC
1540 1.1 christos || !h->def_regular
1541 1.1 christos || !h->ref_regular
1542 1.1 christos || !h->forced_local
1543 1.1 christos || h->root.type != bfd_link_hash_defined)
1544 1.1 christos abort ();
1545 1.1 christos
1546 1.1 christos return elfNN_allocate_ifunc_dynrelocs (h, inf);
1547 1.1 christos }
1548 1.1 christos
1549 1.1 christos /* Set DF_TEXTREL if we find any dynamic relocs that apply to
1550 1.1 christos read-only sections. */
1551 1.1 christos
1552 1.1 christos static bool
1553 1.1 christos maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
1554 1.1 christos {
1555 1.1 christos asection *sec;
1556 1.1 christos
1557 1.1 christos if (h->root.type == bfd_link_hash_indirect)
1558 1.1 christos return true;
1559 1.1 christos
1560 1.1 christos sec = readonly_dynrelocs (h);
1561 1.1 christos if (sec != NULL)
1562 1.1 christos {
1563 1.1 christos struct bfd_link_info *info = (struct bfd_link_info *) info_p;
1564 1.1 christos
1565 1.1 christos info->flags |= DF_TEXTREL;
1566 1.1 christos info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' in "
1567 1.1 christos "read-only section `%pA'\n"),
1568 1.1 christos sec->owner, h->root.root.string, sec);
1569 1.1 christos
1570 1.1 christos /* Not an error, just cut short the traversal. */
1571 1.1 christos return false;
1572 1.1 christos }
1573 1.1 christos return true;
1574 1.1 christos }
1575 1.1 christos
1576 1.1 christos static bool
1577 1.1 christos loongarch_elf_size_dynamic_sections (bfd *output_bfd,
1578 1.1 christos struct bfd_link_info *info)
1579 1.1 christos {
1580 1.1 christos struct loongarch_elf_link_hash_table *htab;
1581 1.1 christos bfd *dynobj;
1582 1.1 christos asection *s;
1583 1.1 christos bfd *ibfd;
1584 1.1 christos
1585 1.1 christos htab = loongarch_elf_hash_table (info);
1586 1.1 christos BFD_ASSERT (htab != NULL);
1587 1.1 christos dynobj = htab->elf.dynobj;
1588 1.1 christos BFD_ASSERT (dynobj != NULL);
1589 1.1 christos
1590 1.1 christos if (htab->elf.dynamic_sections_created)
1591 1.1 christos {
1592 1.1 christos /* Set the contents of the .interp section to the interpreter. */
1593 1.1 christos if (bfd_link_executable (info) && !info->nointerp)
1594 1.1 christos {
1595 1.1 christos const char *interpreter;
1596 1.1 christos s = bfd_get_linker_section (dynobj, ".interp");
1597 1.1 christos BFD_ASSERT (s != NULL);
1598 1.1 christos
1599 1.1 christos if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS32)
1600 1.1 christos interpreter = "/lib32/ld.so.1";
1601 1.1 christos else if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS64)
1602 1.1 christos interpreter = "/lib64/ld.so.1";
1603 1.1 christos else
1604 1.1 christos interpreter = "/lib/ld.so.1";
1605 1.1 christos
1606 1.1 christos s->contents = (unsigned char *) interpreter;
1607 1.1 christos s->size = strlen (interpreter) + 1;
1608 1.1 christos }
1609 1.1 christos }
1610 1.1 christos
1611 1.1 christos /* Set up .got offsets for local syms, and space for local dynamic
1612 1.1 christos relocs. */
1613 1.1 christos for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
1614 1.1 christos {
1615 1.1 christos bfd_signed_vma *local_got;
1616 1.1 christos bfd_signed_vma *end_local_got;
1617 1.1 christos char *local_tls_type;
1618 1.1 christos bfd_size_type locsymcount;
1619 1.1 christos Elf_Internal_Shdr *symtab_hdr;
1620 1.1 christos asection *srel;
1621 1.1 christos
1622 1.1 christos if (!is_loongarch_elf (ibfd))
1623 1.1 christos continue;
1624 1.1 christos
1625 1.1 christos for (s = ibfd->sections; s != NULL; s = s->next)
1626 1.1 christos {
1627 1.1 christos struct elf_dyn_relocs *p;
1628 1.1 christos
1629 1.1 christos for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
1630 1.1 christos {
1631 1.1 christos p->count -= p->pc_count;
1632 1.1 christos if (!bfd_is_abs_section (p->sec)
1633 1.1 christos && bfd_is_abs_section (p->sec->output_section))
1634 1.1 christos {
1635 1.1 christos /* Input section has been discarded, either because
1636 1.1 christos it is a copy of a linkonce section or due to
1637 1.1 christos linker script /DISCARD/, so we'll be discarding
1638 1.1 christos the relocs too. */
1639 1.1 christos }
1640 1.1 christos else if (0 < p->count)
1641 1.1 christos {
1642 1.1 christos srel = elf_section_data (p->sec)->sreloc;
1643 1.1 christos srel->size += p->count * sizeof (ElfNN_External_Rela);
1644 1.1 christos if ((p->sec->output_section->flags & SEC_READONLY) != 0)
1645 1.1 christos info->flags |= DF_TEXTREL;
1646 1.1 christos }
1647 1.1 christos }
1648 1.1 christos }
1649 1.1 christos
1650 1.1 christos local_got = elf_local_got_refcounts (ibfd);
1651 1.1 christos if (!local_got)
1652 1.1 christos continue;
1653 1.1 christos
1654 1.1 christos symtab_hdr = &elf_symtab_hdr (ibfd);
1655 1.1 christos locsymcount = symtab_hdr->sh_info;
1656 1.1 christos end_local_got = local_got + locsymcount;
1657 1.1 christos local_tls_type = _bfd_loongarch_elf_local_got_tls_type (ibfd);
1658 1.1 christos s = htab->elf.sgot;
1659 1.1 christos srel = htab->elf.srelgot;
1660 1.1 christos for (; local_got < end_local_got; ++local_got, ++local_tls_type)
1661 1.1 christos {
1662 1.1 christos if (0 < *local_got)
1663 1.1 christos {
1664 1.1 christos *local_got = s->size;
1665 1.1 christos
1666 1.1 christos /* TLS gd use two got. */
1667 1.1 christos if (*local_tls_type & GOT_TLS_GD)
1668 1.1 christos s->size += GOT_ENTRY_SIZE * 2;
1669 1.1 christos else
1670 1.1 christos /* Normal got, tls ie/ld use one got. */
1671 1.1 christos s->size += GOT_ENTRY_SIZE;
1672 1.1 christos
1673 1.1 christos if (bfd_link_executable (info)
1674 1.1 christos && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
1675 1.1 christos ;/* Do nothing. */
1676 1.1 christos else
1677 1.1 christos {
1678 1.1 christos srel->size += sizeof (ElfNN_External_Rela);
1679 1.1 christos }
1680 1.1 christos }
1681 1.1 christos else
1682 1.1 christos *local_got = MINUS_ONE;
1683 1.1 christos }
1684 1.1 christos }
1685 1.1 christos
1686 1.1 christos /* Allocate global sym .plt and .got entries, and space for global
1687 1.1 christos sym dynamic relocs. */
1688 1.1 christos elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
1689 1.1 christos
1690 1.1 christos /* Allocate global ifunc sym .plt and .got entries, and space for global
1691 1.1 christos ifunc sym dynamic relocs. */
1692 1.1 christos elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info);
1693 1.1 christos
1694 1.1 christos /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1695 1.1 christos htab_traverse (htab->loc_hash_table,
1696 1.1 christos (void *) elfNN_allocate_local_ifunc_dynrelocs, info);
1697 1.1 christos
1698 1.1 christos /* Don't allocate .got.plt section if there are no PLT. */
1699 1.1 christos if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE
1700 1.1 christos && (htab->elf.splt == NULL || htab->elf.splt->size == 0))
1701 1.1 christos htab->elf.sgotplt->size = 0;
1702 1.1 christos
1703 1.1 christos /* The check_relocs and adjust_dynamic_symbol entry points have
1704 1.1 christos determined the sizes of the various dynamic sections. Allocate
1705 1.1 christos memory for them. */
1706 1.1 christos for (s = dynobj->sections; s != NULL; s = s->next)
1707 1.1 christos {
1708 1.1 christos if ((s->flags & SEC_LINKER_CREATED) == 0)
1709 1.1 christos continue;
1710 1.1 christos
1711 1.1 christos if (s == htab->elf.splt || s == htab->elf.iplt || s == htab->elf.sgot
1712 1.1 christos || s == htab->elf.sgotplt || s == htab->elf.igotplt
1713 1.1 christos || s == htab->elf.sdynbss || s == htab->elf.sdynrelro)
1714 1.1 christos {
1715 1.1 christos /* Strip this section if we don't need it; see the
1716 1.1 christos comment below. */
1717 1.1 christos }
1718 1.1 christos else if (strncmp (s->name, ".rela", 5) == 0)
1719 1.1 christos {
1720 1.1 christos if (s->size != 0)
1721 1.1 christos {
1722 1.1 christos /* We use the reloc_count field as a counter if we need
1723 1.1 christos to copy relocs into the output file. */
1724 1.1 christos s->reloc_count = 0;
1725 1.1 christos }
1726 1.1 christos }
1727 1.1 christos else
1728 1.1 christos {
1729 1.1 christos /* It's not one of our sections. */
1730 1.1 christos continue;
1731 1.1 christos }
1732 1.1 christos
1733 1.1 christos if (s->size == 0)
1734 1.1 christos {
1735 1.1 christos /* If we don't need this section, strip it from the
1736 1.1 christos output file. This is mostly to handle .rela.bss and
1737 1.1 christos .rela.plt. We must create both sections in
1738 1.1 christos create_dynamic_sections, because they must be created
1739 1.1 christos before the linker maps input sections to output
1740 1.1 christos sections. The linker does that before
1741 1.1 christos adjust_dynamic_symbol is called, and it is that
1742 1.1 christos function which decides whether anything needs to go
1743 1.1 christos into these sections. */
1744 1.1 christos s->flags |= SEC_EXCLUDE;
1745 1.1 christos continue;
1746 1.1 christos }
1747 1.1 christos
1748 1.1 christos if ((s->flags & SEC_HAS_CONTENTS) == 0)
1749 1.1 christos continue;
1750 1.1 christos
1751 1.1 christos /* Allocate memory for the section contents. Zero the memory
1752 1.1 christos for the benefit of .rela.plt, which has 4 unused entries
1753 1.1 christos at the beginning, and we don't want garbage. */
1754 1.1 christos s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
1755 1.1 christos if (s->contents == NULL)
1756 1.1 christos return false;
1757 1.1 christos }
1758 1.1 christos
1759 1.1 christos if (elf_hash_table (info)->dynamic_sections_created)
1760 1.1 christos {
1761 1.1 christos /* Add some entries to the .dynamic section. We fill in the
1762 1.1 christos values later, in loongarch_elf_finish_dynamic_sections, but we
1763 1.1 christos must add the entries now so that we get the correct size for
1764 1.1 christos the .dynamic section. The DT_DEBUG entry is filled in by the
1765 1.1 christos dynamic linker and used by the debugger. */
1766 1.1 christos #define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1767 1.1 christos
1768 1.1 christos if (bfd_link_executable (info))
1769 1.1 christos {
1770 1.1 christos if (!add_dynamic_entry (DT_DEBUG, 0))
1771 1.1 christos return false;
1772 1.1 christos }
1773 1.1 christos
1774 1.1 christos if (htab->elf.srelplt->size != 0)
1775 1.1 christos {
1776 1.1 christos if (!add_dynamic_entry (DT_PLTGOT, 0)
1777 1.1 christos || !add_dynamic_entry (DT_PLTRELSZ, 0)
1778 1.1 christos || !add_dynamic_entry (DT_PLTREL, DT_RELA)
1779 1.1 christos || !add_dynamic_entry (DT_JMPREL, 0))
1780 1.1 christos return false;
1781 1.1 christos }
1782 1.1 christos
1783 1.1 christos if (!add_dynamic_entry (DT_RELA, 0)
1784 1.1 christos || !add_dynamic_entry (DT_RELASZ, 0)
1785 1.1 christos || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
1786 1.1 christos return false;
1787 1.1 christos
1788 1.1 christos /* If any dynamic relocs apply to a read-only section,
1789 1.1 christos then we need a DT_TEXTREL entry. */
1790 1.1 christos if ((info->flags & DF_TEXTREL) == 0)
1791 1.1 christos elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
1792 1.1 christos
1793 1.1 christos if (info->flags & DF_TEXTREL)
1794 1.1 christos {
1795 1.1 christos if (!add_dynamic_entry (DT_TEXTREL, 0))
1796 1.1 christos return false;
1797 1.1 christos /* Clear the DF_TEXTREL flag. It will be set again if we
1798 1.1 christos write out an actual text relocation; we may not, because
1799 1.1 christos at this point we do not know whether e.g. any .eh_frame
1800 1.1 christos absolute relocations have been converted to PC-relative. */
1801 1.1 christos info->flags &= ~DF_TEXTREL;
1802 1.1 christos }
1803 1.1 christos }
1804 1.1 christos #undef add_dynamic_entry
1805 1.1 christos
1806 1.1 christos return true;
1807 1.1 christos }
1808 1.1 christos
1809 1.1 christos #define LARCH_LD_STACK_DEPTH 16
1810 1.1 christos static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
1811 1.1 christos static size_t larch_stack_top = 0;
1812 1.1 christos
1813 1.1 christos static bfd_reloc_status_type
1814 1.1 christos loongarch_push (int64_t val)
1815 1.1 christos {
1816 1.1 christos if (LARCH_LD_STACK_DEPTH <= larch_stack_top)
1817 1.1 christos return bfd_reloc_outofrange;
1818 1.1 christos larch_opc_stack[larch_stack_top++] = val;
1819 1.1 christos return bfd_reloc_ok;
1820 1.1 christos }
1821 1.1 christos
1822 1.1 christos static bfd_reloc_status_type
1823 1.1 christos loongarch_pop (int64_t *val)
1824 1.1 christos {
1825 1.1 christos if (larch_stack_top == 0)
1826 1.1 christos return bfd_reloc_outofrange;
1827 1.1 christos BFD_ASSERT (val);
1828 1.1 christos *val = larch_opc_stack[--larch_stack_top];
1829 1.1 christos return bfd_reloc_ok;
1830 1.1 christos }
1831 1.1 christos
1832 1.1 christos static bfd_reloc_status_type
1833 1.1 christos loongarch_top (int64_t *val)
1834 1.1 christos {
1835 1.1 christos if (larch_stack_top == 0)
1836 1.1 christos return bfd_reloc_outofrange;
1837 1.1 christos BFD_ASSERT (val);
1838 1.1 christos *val = larch_opc_stack[larch_stack_top - 1];
1839 1.1 christos return bfd_reloc_ok;
1840 1.1 christos }
1841 1.1 christos
1842 1.1 christos static void
1843 1.1 christos loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
1844 1.1 christos {
1845 1.1 christos BFD_ASSERT (s && s->contents);
1846 1.1 christos const struct elf_backend_data *bed;
1847 1.1 christos bfd_byte *loc;
1848 1.1 christos
1849 1.1 christos bed = get_elf_backend_data (abfd);
1850 1.1 christos if (!(s->size > s->reloc_count * bed->s->sizeof_rela))
1851 1.1 christos BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela);
1852 1.1 christos loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
1853 1.1 christos bed->s->swap_reloca_out (abfd, rel, loc);
1854 1.1 christos }
1855 1.1 christos
1856 1.1 christos /* Check rel->r_offset in range of contents. */
1857 1.1 christos static bfd_reloc_status_type
1858 1.1 christos loongarch_check_offset (const Elf_Internal_Rela *rel,
1859 1.1 christos const asection *input_section)
1860 1.1 christos {
1861 1.1 christos if (0 == strcmp(input_section->name, ".text")
1862 1.1 christos && rel->r_offset > input_section->size)
1863 1.1 christos return bfd_reloc_overflow;
1864 1.1 christos
1865 1.1 christos return bfd_reloc_ok;
1866 1.1 christos }
1867 1.1 christos
1868 1.1 christos #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1869 1.1 christos ({ \
1870 1.1 christos bfd_reloc_status_type ret = loongarch_pop (&op2); \
1871 1.1 christos if (ret == bfd_reloc_ok) \
1872 1.1 christos { \
1873 1.1 christos ret = loongarch_pop (&op1); \
1874 1.1 christos if (ret == bfd_reloc_ok) \
1875 1.1 christos ret = loongarch_push (op3); \
1876 1.1 christos } \
1877 1.1 christos ret; \
1878 1.1 christos })
1879 1.1 christos
1880 1.1 christos static bfd_reloc_status_type
1881 1.1 christos loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
1882 1.1 christos const asection *input_section ATTRIBUTE_UNUSED,
1883 1.1 christos reloc_howto_type *howto, bfd *input_bfd,
1884 1.1 christos bfd_byte *contents, bfd_vma reloc_val)
1885 1.1 christos {
1886 1.1 christos int bits = bfd_get_reloc_size (howto) * 8;
1887 1.1 christos uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
1888 1.1 christos
1889 1.1 christos if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
1890 1.1 christos return bfd_reloc_overflow;
1891 1.1 christos
1892 1.1 christos insn = (insn & (uint32_t)howto->src_mask)
1893 1.1 christos | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val);
1894 1.1 christos
1895 1.1 christos bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
1896 1.1 christos
1897 1.1 christos return bfd_reloc_ok;
1898 1.1 christos }
1899 1.1 christos
1900 1.1 christos static bfd_reloc_status_type
1901 1.1 christos perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
1902 1.1 christos reloc_howto_type *howto, bfd_vma value,
1903 1.1 christos bfd *input_bfd, bfd_byte *contents)
1904 1.1 christos {
1905 1.1 christos int64_t opr1, opr2, opr3;
1906 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok;
1907 1.1 christos int bits = bfd_get_reloc_size (howto) * 8;
1908 1.1 christos
1909 1.1 christos switch (ELFNN_R_TYPE (rel->r_info))
1910 1.1 christos {
1911 1.1 christos case R_LARCH_SOP_PUSH_PCREL:
1912 1.1 christos case R_LARCH_SOP_PUSH_ABSOLUTE:
1913 1.1 christos case R_LARCH_SOP_PUSH_GPREL:
1914 1.1 christos case R_LARCH_SOP_PUSH_TLS_TPREL:
1915 1.1 christos case R_LARCH_SOP_PUSH_TLS_GOT:
1916 1.1 christos case R_LARCH_SOP_PUSH_TLS_GD:
1917 1.1 christos case R_LARCH_SOP_PUSH_PLT_PCREL:
1918 1.1 christos r = loongarch_push (value);
1919 1.1 christos break;
1920 1.1 christos
1921 1.1 christos case R_LARCH_SOP_PUSH_DUP:
1922 1.1 christos r = loongarch_pop (&opr1);
1923 1.1 christos if (r == bfd_reloc_ok)
1924 1.1 christos {
1925 1.1 christos r = loongarch_push (opr1);
1926 1.1 christos if (r == bfd_reloc_ok)
1927 1.1 christos r = loongarch_push (opr1);
1928 1.1 christos }
1929 1.1 christos break;
1930 1.1 christos
1931 1.1 christos case R_LARCH_SOP_ASSERT:
1932 1.1 christos r = loongarch_pop (&opr1);
1933 1.1 christos if (r != bfd_reloc_ok || !opr1)
1934 1.1 christos r = bfd_reloc_notsupported;
1935 1.1 christos break;
1936 1.1 christos
1937 1.1 christos case R_LARCH_SOP_NOT:
1938 1.1 christos r = loongarch_pop (&opr1);
1939 1.1 christos if (r == bfd_reloc_ok)
1940 1.1 christos r = loongarch_push (!opr1);
1941 1.1 christos break;
1942 1.1 christos
1943 1.1 christos case R_LARCH_SOP_SUB:
1944 1.1 christos r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
1945 1.1 christos break;
1946 1.1 christos
1947 1.1 christos case R_LARCH_SOP_SL:
1948 1.1 christos r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
1949 1.1 christos break;
1950 1.1 christos
1951 1.1 christos case R_LARCH_SOP_SR:
1952 1.1 christos r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
1953 1.1 christos break;
1954 1.1 christos
1955 1.1 christos case R_LARCH_SOP_AND:
1956 1.1 christos r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
1957 1.1 christos break;
1958 1.1 christos
1959 1.1 christos case R_LARCH_SOP_ADD:
1960 1.1 christos r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
1961 1.1 christos break;
1962 1.1 christos
1963 1.1 christos case R_LARCH_SOP_IF_ELSE:
1964 1.1 christos r = loongarch_pop (&opr3);
1965 1.1 christos if (r == bfd_reloc_ok)
1966 1.1 christos {
1967 1.1 christos r = loongarch_pop (&opr2);
1968 1.1 christos if (r == bfd_reloc_ok)
1969 1.1 christos {
1970 1.1 christos r = loongarch_pop (&opr1);
1971 1.1 christos if (r == bfd_reloc_ok)
1972 1.1 christos r = loongarch_push (opr1 ? opr2 : opr3);
1973 1.1 christos }
1974 1.1 christos }
1975 1.1 christos break;
1976 1.1 christos
1977 1.1 christos case R_LARCH_SOP_POP_32_S_10_5:
1978 1.1 christos case R_LARCH_SOP_POP_32_S_10_12:
1979 1.1 christos case R_LARCH_SOP_POP_32_S_10_16:
1980 1.1 christos case R_LARCH_SOP_POP_32_S_10_16_S2:
1981 1.1 christos case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1982 1.1 christos case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1983 1.1 christos case R_LARCH_SOP_POP_32_S_5_20:
1984 1.1 christos case R_LARCH_SOP_POP_32_U_10_12:
1985 1.1 christos case R_LARCH_SOP_POP_32_U:
1986 1.1 christos r = loongarch_pop (&opr1);
1987 1.1 christos if (r != bfd_reloc_ok)
1988 1.1 christos break;
1989 1.1 christos r = loongarch_check_offset (rel, input_section);
1990 1.1 christos if (r != bfd_reloc_ok)
1991 1.1 christos break;
1992 1.1 christos
1993 1.1 christos r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
1994 1.1 christos howto, input_bfd,
1995 1.1 christos contents, (bfd_vma)opr1);
1996 1.1 christos break;
1997 1.1 christos
1998 1.1 christos case R_LARCH_TLS_DTPREL32:
1999 1.1 christos case R_LARCH_32:
2000 1.1 christos case R_LARCH_TLS_DTPREL64:
2001 1.1 christos case R_LARCH_64:
2002 1.1 christos r = loongarch_check_offset (rel, input_section);
2003 1.1 christos if (r != bfd_reloc_ok)
2004 1.1 christos break;
2005 1.1 christos
2006 1.1 christos bfd_put (bits, input_bfd, value, contents + rel->r_offset);
2007 1.1 christos break;
2008 1.1 christos
2009 1.1 christos case R_LARCH_ADD8:
2010 1.1 christos case R_LARCH_ADD16:
2011 1.1 christos case R_LARCH_ADD24:
2012 1.1 christos case R_LARCH_ADD32:
2013 1.1 christos case R_LARCH_ADD64:
2014 1.1 christos r = loongarch_check_offset (rel, input_section);
2015 1.1 christos if (r != bfd_reloc_ok)
2016 1.1 christos break;
2017 1.1 christos
2018 1.1 christos opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
2019 1.1 christos bfd_put (bits, input_bfd, opr1 + value, contents + rel->r_offset);
2020 1.1 christos break;
2021 1.1 christos
2022 1.1 christos case R_LARCH_SUB8:
2023 1.1 christos case R_LARCH_SUB16:
2024 1.1 christos case R_LARCH_SUB24:
2025 1.1 christos case R_LARCH_SUB32:
2026 1.1 christos case R_LARCH_SUB64:
2027 1.1 christos r = loongarch_check_offset (rel, input_section);
2028 1.1 christos if (r != bfd_reloc_ok)
2029 1.1 christos break;
2030 1.1 christos
2031 1.1 christos opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
2032 1.1 christos bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
2033 1.1 christos break;
2034 1.1 christos
2035 1.1 christos /* For eh_frame and debug info. */
2036 1.1 christos case R_LARCH_32_PCREL:
2037 1.1 christos value -= sec_addr (input_section) + rel->r_offset;
2038 1.1 christos value += rel->r_addend;
2039 1.1 christos bfd_vma word = bfd_get (howto->bitsize, input_bfd,
2040 1.1 christos contents + rel->r_offset);
2041 1.1 christos word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
2042 1.1 christos bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
2043 1.1 christos r = bfd_reloc_ok;
2044 1.1 christos break;
2045 1.1 christos
2046 1.1 christos /* New reloc type.
2047 1.1 christos R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */
2048 1.1 christos case R_LARCH_B16:
2049 1.1 christos case R_LARCH_B21:
2050 1.1 christos case R_LARCH_B26:
2051 1.1 christos case R_LARCH_ABS_HI20:
2052 1.1 christos case R_LARCH_ABS_LO12:
2053 1.1 christos case R_LARCH_ABS64_LO20:
2054 1.1 christos case R_LARCH_ABS64_HI12:
2055 1.1 christos case R_LARCH_PCALA_HI20:
2056 1.1 christos case R_LARCH_PCALA_LO12:
2057 1.1 christos case R_LARCH_PCALA64_LO20:
2058 1.1 christos case R_LARCH_PCALA64_HI12:
2059 1.1 christos case R_LARCH_GOT_PC_HI20:
2060 1.1 christos case R_LARCH_GOT_PC_LO12:
2061 1.1 christos case R_LARCH_GOT64_PC_LO20:
2062 1.1 christos case R_LARCH_GOT64_PC_HI12:
2063 1.1 christos case R_LARCH_GOT_HI20:
2064 1.1 christos case R_LARCH_GOT_LO12:
2065 1.1 christos case R_LARCH_GOT64_LO20:
2066 1.1 christos case R_LARCH_GOT64_HI12:
2067 1.1 christos case R_LARCH_TLS_LE_HI20:
2068 1.1 christos case R_LARCH_TLS_LE_LO12:
2069 1.1 christos case R_LARCH_TLS_LE64_LO20:
2070 1.1 christos case R_LARCH_TLS_LE64_HI12:
2071 1.1 christos case R_LARCH_TLS_IE_PC_HI20:
2072 1.1 christos case R_LARCH_TLS_IE_PC_LO12:
2073 1.1 christos case R_LARCH_TLS_IE64_PC_LO20:
2074 1.1 christos case R_LARCH_TLS_IE64_PC_HI12:
2075 1.1 christos case R_LARCH_TLS_IE_HI20:
2076 1.1 christos case R_LARCH_TLS_IE_LO12:
2077 1.1 christos case R_LARCH_TLS_IE64_LO20:
2078 1.1 christos case R_LARCH_TLS_IE64_HI12:
2079 1.1 christos case R_LARCH_TLS_LD_PC_HI20:
2080 1.1 christos case R_LARCH_TLS_LD_HI20:
2081 1.1 christos case R_LARCH_TLS_GD_PC_HI20:
2082 1.1 christos case R_LARCH_TLS_GD_HI20:
2083 1.1 christos r = loongarch_check_offset (rel, input_section);
2084 1.1 christos if (r != bfd_reloc_ok)
2085 1.1 christos break;
2086 1.1 christos
2087 1.1 christos r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
2088 1.1 christos howto, input_bfd,
2089 1.1 christos contents, value);
2090 1.1 christos break;
2091 1.1 christos
2092 1.1 christos case R_LARCH_RELAX:
2093 1.1 christos break;
2094 1.1 christos
2095 1.1 christos default:
2096 1.1 christos r = bfd_reloc_notsupported;
2097 1.1 christos }
2098 1.1 christos return r;
2099 1.1 christos }
2100 1.1 christos
2101 1.1 christos #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
2102 1.1 christos static struct
2103 1.1 christos {
2104 1.1 christos bfd *bfd;
2105 1.1 christos asection *section;
2106 1.1 christos bfd_vma r_offset;
2107 1.1 christos int r_type;
2108 1.1 christos bfd_vma relocation;
2109 1.1 christos Elf_Internal_Sym *sym;
2110 1.1 christos struct elf_link_hash_entry *h;
2111 1.1 christos bfd_vma addend;
2112 1.1 christos int64_t top_then;
2113 1.1 christos } larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
2114 1.1 christos static size_t larch_reloc_queue_head = 0;
2115 1.1 christos static size_t larch_reloc_queue_tail = 0;
2116 1.1 christos
2117 1.1 christos static const char *
2118 1.1 christos loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
2119 1.1 christos Elf_Internal_Sym *sym)
2120 1.1 christos {
2121 1.1 christos const char *ret = NULL;
2122 1.1 christos if (sym)
2123 1.1 christos ret = bfd_elf_string_from_elf_section (input_bfd,
2124 1.1 christos elf_symtab_hdr (input_bfd).sh_link,
2125 1.1 christos sym->st_name);
2126 1.1 christos else if (h)
2127 1.1 christos ret = h->root.root.string;
2128 1.1 christos
2129 1.1 christos if (ret == NULL || *ret == '\0')
2130 1.1 christos ret = "<nameless>";
2131 1.1 christos return ret;
2132 1.1 christos }
2133 1.1 christos
2134 1.1 christos static void
2135 1.1 christos loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
2136 1.1 christos bfd_vma r_offset, Elf_Internal_Sym *sym,
2137 1.1 christos struct elf_link_hash_entry *h, bfd_vma addend)
2138 1.1 christos {
2139 1.1 christos if ((larch_reloc_queue_head == 0
2140 1.1 christos && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
2141 1.1 christos || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
2142 1.1 christos larch_reloc_queue_head =
2143 1.1 christos (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2144 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
2145 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].section = section;
2146 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
2147 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
2148 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
2149 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].h = h;
2150 1.1 christos larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
2151 1.1 christos loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
2152 1.1 christos larch_reloc_queue_tail =
2153 1.1 christos (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2154 1.1 christos }
2155 1.1 christos
2156 1.1 christos static void
2157 1.1 christos loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
2158 1.1 christos {
2159 1.1 christos size_t i = larch_reloc_queue_head;
2160 1.1 christos bfd *a_bfd = NULL;
2161 1.1 christos asection *section = NULL;
2162 1.1 christos bfd_vma r_offset = 0;
2163 1.1 christos int inited = 0;
2164 1.1 christos p ("Dump relocate record:\n");
2165 1.1 christos p ("stack top\t\trelocation name\t\tsymbol");
2166 1.1 christos while (i != larch_reloc_queue_tail)
2167 1.1 christos {
2168 1.1 christos if (a_bfd != larch_reloc_queue[i].bfd
2169 1.1 christos || section != larch_reloc_queue[i].section
2170 1.1 christos || r_offset != larch_reloc_queue[i].r_offset)
2171 1.1 christos {
2172 1.1 christos a_bfd = larch_reloc_queue[i].bfd;
2173 1.1 christos section = larch_reloc_queue[i].section;
2174 1.1 christos r_offset = larch_reloc_queue[i].r_offset;
2175 1.1 christos p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
2176 1.1 christos larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
2177 1.1 christos }
2178 1.1 christos
2179 1.1 christos if (!inited)
2180 1.1 christos inited = 1, p ("...\n");
2181 1.1 christos
2182 1.1 christos reloc_howto_type *howto =
2183 1.1 christos loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
2184 1.1 christos larch_reloc_queue[i].r_type);
2185 1.1 christos p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
2186 1.1 christos howto ? howto->name : "<unknown reloc>",
2187 1.1 christos loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
2188 1.1 christos larch_reloc_queue[i].sym));
2189 1.1 christos
2190 1.1 christos long addend = larch_reloc_queue[i].addend;
2191 1.1 christos if (addend < 0)
2192 1.1 christos p (" - %ld", -addend);
2193 1.1 christos else if (0 < addend)
2194 1.1 christos p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
2195 1.1 christos
2196 1.1 christos p ("\n");
2197 1.1 christos i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2198 1.1 christos }
2199 1.1 christos p ("\n"
2200 1.1 christos "-- Record dump end --\n\n");
2201 1.1 christos }
2202 1.1 christos
2203 1.1 christos static bool
2204 1.1 christos loongarch_reloc_is_fatal (struct bfd_link_info *info,
2205 1.1 christos bfd *input_bfd,
2206 1.1 christos asection *input_section,
2207 1.1 christos Elf_Internal_Rela *rel,
2208 1.1 christos reloc_howto_type *howto,
2209 1.1 christos bfd_reloc_status_type rtype,
2210 1.1 christos bool is_undefweak,
2211 1.1 christos const char *name,
2212 1.1 christos const char *msg)
2213 1.1 christos {
2214 1.1 christos bool fatal = true;
2215 1.1 christos switch (rtype)
2216 1.1 christos {
2217 1.1 christos /* 'dangerous' means we do it but can't promise it's ok
2218 1.1 christos 'unsupport' means out of ability of relocation type
2219 1.1 christos 'undefined' means we can't deal with the undefined symbol. */
2220 1.1 christos case bfd_reloc_undefined:
2221 1.1 christos info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
2222 1.1 christos rel->r_offset, true);
2223 1.1 christos info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2224 1.1 christos input_bfd, input_section, rel->r_offset,
2225 1.1 christos howto->name,
2226 1.1 christos is_undefweak ? "[undefweak] " : "", name, msg);
2227 1.1 christos break;
2228 1.1 christos case bfd_reloc_dangerous:
2229 1.1 christos info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
2230 1.1 christos input_bfd, input_section, rel->r_offset,
2231 1.1 christos howto->name,
2232 1.1 christos is_undefweak ? "[undefweak] " : "", name, msg);
2233 1.1 christos fatal = false;
2234 1.1 christos break;
2235 1.1 christos case bfd_reloc_notsupported:
2236 1.1 christos info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2237 1.1 christos input_bfd, input_section, rel->r_offset,
2238 1.1 christos howto->name,
2239 1.1 christos is_undefweak ? "[undefweak] " : "", name, msg);
2240 1.1 christos break;
2241 1.1 christos default:
2242 1.1 christos break;
2243 1.1 christos }
2244 1.1 christos return fatal;
2245 1.1 christos }
2246 1.1 christos
2247 1.1 christos #define RELOCATE_CALC_PC32_HI20(relocation, pc) \
2248 1.1 christos ({ \
2249 1.1 christos bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2250 1.1 christos pc = pc & (~(bfd_vma)0xfff); \
2251 1.1 christos if (lo > 0x7ff) \
2252 1.1 christos { \
2253 1.1 christos relocation += 0x1000; \
2254 1.1 christos } \
2255 1.1 christos relocation &= ~(bfd_vma)0xfff; \
2256 1.1 christos relocation -= pc; \
2257 1.1 christos })
2258 1.1 christos
2259 1.1 christos #define RELOCATE_CALC_PC64_HI32(relocation, pc) \
2260 1.1 christos ({ \
2261 1.1 christos bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2262 1.1 christos if (lo > 0x7ff) \
2263 1.1 christos { \
2264 1.1 christos relocation -= 0x100000000; \
2265 1.1 christos } \
2266 1.1 christos relocation -= (pc & ~(bfd_vma)0xffffffff); \
2267 1.1 christos })
2268 1.1 christos
2269 1.1 christos static int
2270 1.1 christos loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
2271 1.1 christos bfd *input_bfd, asection *input_section,
2272 1.1 christos bfd_byte *contents, Elf_Internal_Rela *relocs,
2273 1.1 christos Elf_Internal_Sym *local_syms,
2274 1.1 christos asection **local_sections)
2275 1.1 christos {
2276 1.1 christos Elf_Internal_Rela *rel;
2277 1.1 christos Elf_Internal_Rela *relend;
2278 1.1 christos bool fatal = false;
2279 1.1 christos asection *sreloc = elf_section_data (input_section)->sreloc;
2280 1.1 christos struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2281 1.1 christos Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
2282 1.1 christos struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
2283 1.1 christos bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
2284 1.1 christos bool is_pic = bfd_link_pic (info);
2285 1.1 christos bool is_dyn = elf_hash_table (info)->dynamic_sections_created;
2286 1.1 christos asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
2287 1.1 christos asection *got = htab->elf.sgot;
2288 1.1 christos
2289 1.1 christos relend = relocs + input_section->reloc_count;
2290 1.1 christos for (rel = relocs; rel < relend; rel++)
2291 1.1 christos {
2292 1.1 christos int r_type = ELFNN_R_TYPE (rel->r_info);
2293 1.1 christos unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
2294 1.1 christos bfd_vma pc = sec_addr (input_section) + rel->r_offset;
2295 1.1 christos reloc_howto_type *howto = NULL;
2296 1.1 christos asection *sec = NULL;
2297 1.1 christos Elf_Internal_Sym *sym = NULL;
2298 1.1 christos struct elf_link_hash_entry *h = NULL;
2299 1.1 christos const char *name;
2300 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok;
2301 1.1 christos bool is_ie, is_undefweak, unresolved_reloc, defined_local;
2302 1.1 christos bool resolved_local, resolved_dynly, resolved_to_const;
2303 1.1 christos char tls_type;
2304 1.1 christos bfd_vma relocation, off, ie_off;
2305 1.1 christos int i, j;
2306 1.1 christos
2307 1.1 christos howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
2308 1.1 christos if (howto == NULL || r_type == R_LARCH_GNU_VTINHERIT
2309 1.1 christos || r_type == R_LARCH_GNU_VTENTRY)
2310 1.1 christos continue;
2311 1.1 christos
2312 1.1 christos /* This is a final link. */
2313 1.1 christos if (r_symndx < symtab_hdr->sh_info)
2314 1.1 christos {
2315 1.1 christos is_undefweak = false;
2316 1.1 christos unresolved_reloc = false;
2317 1.1 christos sym = local_syms + r_symndx;
2318 1.1 christos sec = local_sections[r_symndx];
2319 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
2320 1.1 christos
2321 1.1 christos /* Relocate against local STT_GNU_IFUNC symbol. */
2322 1.1 christos if (!bfd_link_relocatable (info)
2323 1.1 christos && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
2324 1.1 christos {
2325 1.1 christos h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
2326 1.1 christos false);
2327 1.1 christos if (h == NULL)
2328 1.1 christos abort ();
2329 1.1 christos
2330 1.1 christos /* Set STT_GNU_IFUNC symbol value. */
2331 1.1 christos h->root.u.def.value = sym->st_value;
2332 1.1 christos h->root.u.def.section = sec;
2333 1.1 christos }
2334 1.1 christos defined_local = true;
2335 1.1 christos resolved_local = true;
2336 1.1 christos resolved_dynly = false;
2337 1.1 christos resolved_to_const = false;
2338 1.1 christos
2339 1.1 christos /* Calc in funtion elf_link_input_bfd,
2340 1.1 christos * if #define elf_backend_rela_normal to 1. */
2341 1.1 christos if (bfd_link_relocatable (info)
2342 1.1 christos && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
2343 1.1 christos continue;
2344 1.1 christos }
2345 1.1 christos else
2346 1.1 christos {
2347 1.1 christos bool warned, ignored;
2348 1.1 christos
2349 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
2350 1.1 christos r_symndx, symtab_hdr, sym_hashes,
2351 1.1 christos h, sec, relocation,
2352 1.1 christos unresolved_reloc, warned, ignored);
2353 1.1 christos /* Here means symbol isn't local symbol only and 'h != NULL'. */
2354 1.1 christos
2355 1.1 christos /* The 'unresolved_syms_in_objects' specify how to deal with undefined
2356 1.1 christos symbol. And 'dynamic_undefined_weak' specify what to do when
2357 1.1 christos meeting undefweak. */
2358 1.1 christos
2359 1.1 christos if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
2360 1.1 christos {
2361 1.1 christos defined_local = false;
2362 1.1 christos resolved_local = false;
2363 1.1 christos resolved_to_const = (!is_dyn || h->dynindx == -1
2364 1.1 christos || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
2365 1.1 christos resolved_dynly = !resolved_local && !resolved_to_const;
2366 1.1 christos }
2367 1.1 christos else if (warned)
2368 1.1 christos {
2369 1.1 christos /* Symbol undefined offen means failed already. I don't know why
2370 1.1 christos 'warned' here but I guess it want to continue relocating as if
2371 1.1 christos no error occures to find other errors as more as possible. */
2372 1.1 christos
2373 1.1 christos /* To avoid generating warning messages about truncated
2374 1.1 christos relocations, set the relocation's address to be the same as
2375 1.1 christos the start of this section. */
2376 1.1 christos relocation = (input_section->output_section
2377 1.1 christos ? input_section->output_section->vma
2378 1.1 christos : 0);
2379 1.1 christos
2380 1.1 christos defined_local = relocation != 0;
2381 1.1 christos resolved_local = defined_local;
2382 1.1 christos resolved_to_const = !resolved_local;
2383 1.1 christos resolved_dynly = false;
2384 1.1 christos }
2385 1.1 christos else
2386 1.1 christos {
2387 1.1 christos defined_local = !unresolved_reloc && !ignored;
2388 1.1 christos resolved_local =
2389 1.1 christos defined_local && SYMBOL_REFERENCES_LOCAL (info, h);
2390 1.1 christos resolved_dynly = !resolved_local;
2391 1.1 christos resolved_to_const = !resolved_local && !resolved_dynly;
2392 1.1 christos }
2393 1.1 christos }
2394 1.1 christos
2395 1.1 christos name = loongarch_sym_name (input_bfd, h, sym);
2396 1.1 christos
2397 1.1 christos if (sec != NULL && discarded_section (sec))
2398 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
2399 1.1 christos 1, relend, howto, 0, contents);
2400 1.1 christos
2401 1.1 christos if (bfd_link_relocatable (info))
2402 1.1 christos continue;
2403 1.1 christos
2404 1.1 christos /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2405 1.1 christos from removed linkonce sections, or sections discarded by a linker
2406 1.1 christos script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2407 1.1 christos if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
2408 1.1 christos {
2409 1.1 christos defined_local = false;
2410 1.1 christos resolved_local = false;
2411 1.1 christos resolved_dynly = false;
2412 1.1 christos resolved_to_const = true;
2413 1.1 christos }
2414 1.1 christos
2415 1.1 christos /* The ifunc reference generate plt. */
2416 1.1 christos if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE)
2417 1.1 christos {
2418 1.1 christos defined_local = true;
2419 1.1 christos resolved_local = true;
2420 1.1 christos resolved_dynly = false;
2421 1.1 christos resolved_to_const = false;
2422 1.1 christos relocation = sec_addr (plt) + h->plt.offset;
2423 1.1 christos }
2424 1.1 christos
2425 1.1 christos unresolved_reloc = resolved_dynly;
2426 1.1 christos
2427 1.1 christos BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
2428 1.1 christos
2429 1.1 christos /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));. */
2430 1.1 christos
2431 1.1 christos BFD_ASSERT (!resolved_local || defined_local);
2432 1.1 christos
2433 1.1 christos is_ie = false;
2434 1.1 christos switch (r_type)
2435 1.1 christos {
2436 1.1 christos case R_LARCH_MARK_PCREL:
2437 1.1 christos case R_LARCH_MARK_LA:
2438 1.1 christos case R_LARCH_NONE:
2439 1.1 christos r = bfd_reloc_continue;
2440 1.1 christos unresolved_reloc = false;
2441 1.1 christos break;
2442 1.1 christos
2443 1.1 christos case R_LARCH_32:
2444 1.1 christos case R_LARCH_64:
2445 1.1 christos if (resolved_dynly || (is_pic && resolved_local))
2446 1.1 christos {
2447 1.1 christos Elf_Internal_Rela outrel;
2448 1.1 christos
2449 1.1 christos /* When generating a shared object, these relocations are copied
2450 1.1 christos into the output file to be resolved at run time. */
2451 1.1 christos
2452 1.1 christos outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2453 1.1 christos input_section,
2454 1.1 christos rel->r_offset);
2455 1.1 christos
2456 1.1 christos unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2457 1.1 christos && (input_section->flags & SEC_ALLOC));
2458 1.1 christos
2459 1.1 christos outrel.r_offset += sec_addr (input_section);
2460 1.1 christos
2461 1.1 christos /* A pointer point to a ifunc symbol. */
2462 1.1 christos if (h && h->type == STT_GNU_IFUNC)
2463 1.1 christos {
2464 1.1 christos if (h->dynindx == -1)
2465 1.1 christos {
2466 1.1 christos outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2467 1.1 christos outrel.r_addend = (h->root.u.def.value
2468 1.1 christos + h->root.u.def.section->output_section->vma
2469 1.1 christos + h->root.u.def.section->output_offset);
2470 1.1 christos }
2471 1.1 christos else
2472 1.1 christos {
2473 1.1 christos outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
2474 1.1 christos outrel.r_addend = 0;
2475 1.1 christos }
2476 1.1 christos
2477 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
2478 1.1 christos {
2479 1.1 christos
2480 1.1 christos if (htab->elf.splt != NULL)
2481 1.1 christos sreloc = htab->elf.srelgot;
2482 1.1 christos else
2483 1.1 christos sreloc = htab->elf.irelplt;
2484 1.1 christos }
2485 1.1 christos else
2486 1.1 christos {
2487 1.1 christos
2488 1.1 christos if (bfd_link_pic (info))
2489 1.1 christos sreloc = htab->elf.irelifunc;
2490 1.1 christos else if (htab->elf.splt != NULL)
2491 1.1 christos sreloc = htab->elf.srelgot;
2492 1.1 christos else
2493 1.1 christos sreloc = htab->elf.irelplt;
2494 1.1 christos }
2495 1.1 christos }
2496 1.1 christos else if (resolved_dynly)
2497 1.1 christos {
2498 1.1 christos if (h->dynindx == -1)
2499 1.1 christos {
2500 1.1 christos if (h->root.type == bfd_link_hash_undefined)
2501 1.1 christos (*info->callbacks->undefined_symbol)
2502 1.1 christos (info, name, input_bfd, input_section,
2503 1.1 christos rel->r_offset, true);
2504 1.1 christos
2505 1.1 christos outrel.r_info = ELFNN_R_INFO (0, r_type);
2506 1.1 christos }
2507 1.1 christos else
2508 1.1 christos outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2509 1.1 christos
2510 1.1 christos outrel.r_addend = rel->r_addend;
2511 1.1 christos }
2512 1.1 christos else
2513 1.1 christos {
2514 1.1 christos outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2515 1.1 christos outrel.r_addend = relocation + rel->r_addend;
2516 1.1 christos }
2517 1.1 christos
2518 1.1 christos /* No alloc space of func allocate_dynrelocs. */
2519 1.1 christos if (unresolved_reloc
2520 1.1 christos && !(h && (h->is_weakalias || !h->dyn_relocs)))
2521 1.1 christos loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2522 1.1 christos }
2523 1.1 christos
2524 1.1 christos relocation += rel->r_addend;
2525 1.1 christos break;
2526 1.1 christos
2527 1.1 christos case R_LARCH_ADD8:
2528 1.1 christos case R_LARCH_ADD16:
2529 1.1 christos case R_LARCH_ADD24:
2530 1.1 christos case R_LARCH_ADD32:
2531 1.1 christos case R_LARCH_ADD64:
2532 1.1 christos case R_LARCH_SUB8:
2533 1.1 christos case R_LARCH_SUB16:
2534 1.1 christos case R_LARCH_SUB24:
2535 1.1 christos case R_LARCH_SUB32:
2536 1.1 christos case R_LARCH_SUB64:
2537 1.1 christos if (resolved_dynly)
2538 1.1 christos fatal = (loongarch_reloc_is_fatal
2539 1.1 christos (info, input_bfd, input_section, rel, howto,
2540 1.1 christos bfd_reloc_undefined, is_undefweak, name,
2541 1.1 christos "Can't be resolved dynamically. "
2542 1.1 christos "If this procedure is hand-written assembly,\n"
2543 1.1 christos "there must be something like '.dword sym1 - sym2' "
2544 1.1 christos "to generate these relocs\n"
2545 1.1 christos "and we can't get known link-time address of "
2546 1.1 christos "these symbols."));
2547 1.1 christos else
2548 1.1 christos relocation += rel->r_addend;
2549 1.1 christos break;
2550 1.1 christos
2551 1.1 christos case R_LARCH_TLS_DTPREL32:
2552 1.1 christos case R_LARCH_TLS_DTPREL64:
2553 1.1 christos if (resolved_dynly)
2554 1.1 christos {
2555 1.1 christos Elf_Internal_Rela outrel;
2556 1.1 christos
2557 1.1 christos outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2558 1.1 christos input_section,
2559 1.1 christos rel->r_offset);
2560 1.1 christos unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2561 1.1 christos && (input_section->flags & SEC_ALLOC));
2562 1.1 christos outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2563 1.1 christos outrel.r_offset += sec_addr (input_section);
2564 1.1 christos outrel.r_addend = rel->r_addend;
2565 1.1 christos if (unresolved_reloc)
2566 1.1 christos loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2567 1.1 christos break;
2568 1.1 christos }
2569 1.1 christos
2570 1.1 christos if (resolved_to_const)
2571 1.1 christos fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
2572 1.1 christos rel, howto,
2573 1.1 christos bfd_reloc_notsupported,
2574 1.1 christos is_undefweak, name,
2575 1.1 christos "Internal:");
2576 1.1 christos if (resolved_local)
2577 1.1 christos {
2578 1.1 christos if (!elf_hash_table (info)->tls_sec)
2579 1.1 christos {
2580 1.1 christos fatal = loongarch_reloc_is_fatal (info, input_bfd,
2581 1.1 christos input_section, rel, howto, bfd_reloc_notsupported,
2582 1.1 christos is_undefweak, name, "TLS section not be created");
2583 1.1 christos }
2584 1.1 christos else
2585 1.1 christos relocation -= elf_hash_table (info)->tls_sec->vma;
2586 1.1 christos }
2587 1.1 christos else
2588 1.1 christos {
2589 1.1 christos fatal = loongarch_reloc_is_fatal (info, input_bfd,
2590 1.1 christos input_section, rel, howto, bfd_reloc_undefined,
2591 1.1 christos is_undefweak, name,
2592 1.1 christos "TLS LE just can be resolved local only.");
2593 1.1 christos }
2594 1.1 christos
2595 1.1 christos break;
2596 1.1 christos
2597 1.1 christos case R_LARCH_SOP_PUSH_TLS_TPREL:
2598 1.1 christos if (resolved_local)
2599 1.1 christos {
2600 1.1 christos if (!elf_hash_table (info)->tls_sec)
2601 1.1 christos fatal = (loongarch_reloc_is_fatal
2602 1.1 christos (info, input_bfd, input_section, rel, howto,
2603 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2604 1.1 christos "TLS section not be created"));
2605 1.1 christos else
2606 1.1 christos relocation -= elf_hash_table (info)->tls_sec->vma;
2607 1.1 christos }
2608 1.1 christos else
2609 1.1 christos fatal = (loongarch_reloc_is_fatal
2610 1.1 christos (info, input_bfd, input_section, rel, howto,
2611 1.1 christos bfd_reloc_undefined, is_undefweak, name,
2612 1.1 christos "TLS LE just can be resolved local only."));
2613 1.1 christos break;
2614 1.1 christos
2615 1.1 christos case R_LARCH_SOP_PUSH_ABSOLUTE:
2616 1.1 christos if (is_undefweak)
2617 1.1 christos {
2618 1.1 christos if (resolved_dynly)
2619 1.1 christos fatal = (loongarch_reloc_is_fatal
2620 1.1 christos (info, input_bfd, input_section, rel, howto,
2621 1.1 christos bfd_reloc_dangerous, is_undefweak, name,
2622 1.1 christos "Someone require us to resolve undefweak "
2623 1.1 christos "symbol dynamically. \n"
2624 1.1 christos "But this reloc can't be done. "
2625 1.1 christos "I think I can't throw error "
2626 1.1 christos "for this\n"
2627 1.1 christos "so I resolved it to 0. "
2628 1.1 christos "I suggest to re-compile with '-fpic'."));
2629 1.1 christos
2630 1.1 christos relocation = 0;
2631 1.1 christos unresolved_reloc = false;
2632 1.1 christos break;
2633 1.1 christos }
2634 1.1 christos
2635 1.1 christos if (resolved_to_const)
2636 1.1 christos {
2637 1.1 christos relocation += rel->r_addend;
2638 1.1 christos break;
2639 1.1 christos }
2640 1.1 christos
2641 1.1 christos if (is_pic)
2642 1.1 christos {
2643 1.1 christos fatal = (loongarch_reloc_is_fatal
2644 1.1 christos (info, input_bfd, input_section, rel, howto,
2645 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2646 1.1 christos "Under PIC we don't know load address. Re-compile "
2647 1.1 christos "with '-fpic'?"));
2648 1.1 christos break;
2649 1.1 christos }
2650 1.1 christos
2651 1.1 christos if (resolved_dynly)
2652 1.1 christos {
2653 1.1 christos if (!(plt && h && h->plt.offset != MINUS_ONE))
2654 1.1 christos {
2655 1.1 christos fatal = (loongarch_reloc_is_fatal
2656 1.1 christos (info, input_bfd, input_section, rel, howto,
2657 1.1 christos bfd_reloc_undefined, is_undefweak, name,
2658 1.1 christos "Can't be resolved dynamically. Try to re-compile "
2659 1.1 christos "with '-fpic'?"));
2660 1.1 christos break;
2661 1.1 christos }
2662 1.1 christos
2663 1.1 christos if (rel->r_addend != 0)
2664 1.1 christos {
2665 1.1 christos fatal = (loongarch_reloc_is_fatal
2666 1.1 christos (info, input_bfd, input_section, rel, howto,
2667 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2668 1.1 christos "Shouldn't be with r_addend."));
2669 1.1 christos break;
2670 1.1 christos }
2671 1.1 christos
2672 1.1 christos relocation = sec_addr (plt) + h->plt.offset;
2673 1.1 christos unresolved_reloc = false;
2674 1.1 christos break;
2675 1.1 christos }
2676 1.1 christos
2677 1.1 christos if (resolved_local)
2678 1.1 christos {
2679 1.1 christos relocation += rel->r_addend;
2680 1.1 christos break;
2681 1.1 christos }
2682 1.1 christos
2683 1.1 christos break;
2684 1.1 christos
2685 1.1 christos case R_LARCH_SOP_PUSH_PCREL:
2686 1.1 christos case R_LARCH_SOP_PUSH_PLT_PCREL:
2687 1.1 christos unresolved_reloc = false;
2688 1.1 christos
2689 1.1 christos if (is_undefweak)
2690 1.1 christos {
2691 1.1 christos i = 0, j = 0;
2692 1.1 christos relocation = 0;
2693 1.1 christos if (resolved_dynly)
2694 1.1 christos {
2695 1.1 christos if (h && h->plt.offset != MINUS_ONE)
2696 1.1 christos i = 1, j = 2;
2697 1.1 christos else
2698 1.1 christos fatal = (loongarch_reloc_is_fatal
2699 1.1 christos (info, input_bfd, input_section, rel, howto,
2700 1.1 christos bfd_reloc_dangerous, is_undefweak, name,
2701 1.1 christos "Undefweak need to be resolved dynamically, "
2702 1.1 christos "but PLT stub doesn't represent."));
2703 1.1 christos }
2704 1.1 christos }
2705 1.1 christos else
2706 1.1 christos {
2707 1.1 christos if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
2708 1.1 christos {
2709 1.1 christos fatal = (loongarch_reloc_is_fatal
2710 1.1 christos (info, input_bfd, input_section, rel, howto,
2711 1.1 christos bfd_reloc_undefined, is_undefweak, name,
2712 1.1 christos "PLT stub does not represent and "
2713 1.1 christos "symbol not defined."));
2714 1.1 christos break;
2715 1.1 christos }
2716 1.1 christos
2717 1.1 christos if (resolved_local)
2718 1.1 christos i = 0, j = 2;
2719 1.1 christos else /* if (resolved_dynly) */
2720 1.1 christos {
2721 1.1 christos if (!(h && h->plt.offset != MINUS_ONE))
2722 1.1 christos fatal = (loongarch_reloc_is_fatal
2723 1.1 christos (info, input_bfd, input_section, rel, howto,
2724 1.1 christos bfd_reloc_dangerous, is_undefweak, name,
2725 1.1 christos "Internal: PLT stub doesn't represent. "
2726 1.1 christos "Resolve it with pcrel"));
2727 1.1 christos i = 1, j = 3;
2728 1.1 christos }
2729 1.1 christos }
2730 1.1 christos
2731 1.1 christos for (; i < j; i++)
2732 1.1 christos {
2733 1.1 christos if ((i & 1) == 0 && defined_local)
2734 1.1 christos {
2735 1.1 christos relocation -= pc;
2736 1.1 christos relocation += rel->r_addend;
2737 1.1 christos break;
2738 1.1 christos }
2739 1.1 christos
2740 1.1 christos if ((i & 1) && h && h->plt.offset != MINUS_ONE)
2741 1.1 christos {
2742 1.1 christos if (rel->r_addend != 0)
2743 1.1 christos {
2744 1.1 christos fatal = (loongarch_reloc_is_fatal
2745 1.1 christos (info, input_bfd, input_section, rel, howto,
2746 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2747 1.1 christos "PLT shouldn't be with r_addend."));
2748 1.1 christos break;
2749 1.1 christos }
2750 1.1 christos relocation = sec_addr (plt) + h->plt.offset - pc;
2751 1.1 christos break;
2752 1.1 christos }
2753 1.1 christos }
2754 1.1 christos break;
2755 1.1 christos
2756 1.1 christos case R_LARCH_SOP_PUSH_GPREL:
2757 1.1 christos unresolved_reloc = false;
2758 1.1 christos
2759 1.1 christos if (rel->r_addend != 0)
2760 1.1 christos {
2761 1.1 christos fatal = (loongarch_reloc_is_fatal
2762 1.1 christos (info, input_bfd, input_section, rel, howto,
2763 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2764 1.1 christos "Shouldn't be with r_addend."));
2765 1.1 christos break;
2766 1.1 christos }
2767 1.1 christos
2768 1.1 christos if (h != NULL)
2769 1.1 christos {
2770 1.1 christos off = h->got.offset & (~1);
2771 1.1 christos
2772 1.1 christos if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC)
2773 1.1 christos {
2774 1.1 christos fatal = (loongarch_reloc_is_fatal
2775 1.1 christos (info, input_bfd, input_section, rel, howto,
2776 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2777 1.1 christos "Internal: GOT entry doesn't represent."));
2778 1.1 christos break;
2779 1.1 christos }
2780 1.1 christos
2781 1.1 christos /* Hidden symbol not has .got entry, only .got.plt entry
2782 1.1 christos so gprel is (plt - got). */
2783 1.1 christos if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
2784 1.1 christos {
2785 1.1 christos if (h->plt.offset == (bfd_vma) -1)
2786 1.1 christos {
2787 1.1 christos abort();
2788 1.1 christos }
2789 1.1 christos
2790 1.1 christos bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE;
2791 1.1 christos off = plt_index * GOT_ENTRY_SIZE;
2792 1.1 christos
2793 1.1 christos if (htab->elf.splt != NULL)
2794 1.1 christos {
2795 1.1 christos /* Section .plt header is 2 times of plt entry. */
2796 1.1 christos off = sec_addr (htab->elf.sgotplt) + off
2797 1.1 christos - sec_addr (htab->elf.sgot);
2798 1.1 christos }
2799 1.1 christos else
2800 1.1 christos {
2801 1.1 christos /* Section iplt not has plt header. */
2802 1.1 christos off = sec_addr (htab->elf.igotplt) + off
2803 1.1 christos - sec_addr (htab->elf.sgot);
2804 1.1 christos }
2805 1.1 christos }
2806 1.1 christos
2807 1.1 christos if ((h->got.offset & 1) == 0)
2808 1.1 christos {
2809 1.1 christos if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
2810 1.1 christos bfd_link_pic (info), h)
2811 1.1 christos && ((bfd_link_pic (info)
2812 1.1 christos && SYMBOL_REFERENCES_LOCAL (info, h))))
2813 1.1 christos {
2814 1.1 christos /* This is actually a static link, or it is a
2815 1.1 christos -Bsymbolic link and the symbol is defined
2816 1.1 christos locally, or the symbol was forced to be local
2817 1.1 christos because of a version file. We must initialize
2818 1.1 christos this entry in the global offset table. Since the
2819 1.1 christos offset must always be a multiple of the word size,
2820 1.1 christos we use the least significant bit to record whether
2821 1.1 christos we have initialized it already.
2822 1.1 christos
2823 1.1 christos When doing a dynamic link, we create a rela.got
2824 1.1 christos relocation entry to initialize the value. This
2825 1.1 christos is done in the finish_dynamic_symbol routine. */
2826 1.1 christos
2827 1.1 christos if (resolved_dynly)
2828 1.1 christos {
2829 1.1 christos fatal = (loongarch_reloc_is_fatal
2830 1.1 christos (info, input_bfd, input_section, rel, howto,
2831 1.1 christos bfd_reloc_dangerous, is_undefweak, name,
2832 1.1 christos "Internal: here shouldn't dynamic."));
2833 1.1 christos }
2834 1.1 christos
2835 1.1 christos if (!(defined_local || resolved_to_const))
2836 1.1 christos {
2837 1.1 christos fatal = (loongarch_reloc_is_fatal
2838 1.1 christos (info, input_bfd, input_section, rel, howto,
2839 1.1 christos bfd_reloc_undefined, is_undefweak, name,
2840 1.1 christos "Internal: "));
2841 1.1 christos break;
2842 1.1 christos }
2843 1.1 christos
2844 1.1 christos asection *s;
2845 1.1 christos Elf_Internal_Rela outrel;
2846 1.1 christos /* We need to generate a R_LARCH_RELATIVE reloc
2847 1.1 christos for the dynamic linker. */
2848 1.1 christos s = htab->elf.srelgot;
2849 1.1 christos if (!s)
2850 1.1 christos {
2851 1.1 christos fatal = loongarch_reloc_is_fatal
2852 1.1 christos (info, input_bfd,
2853 1.1 christos input_section, rel, howto,
2854 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2855 1.1 christos "Internal: '.rel.got' not represent");
2856 1.1 christos break;
2857 1.1 christos }
2858 1.1 christos
2859 1.1 christos outrel.r_offset = sec_addr (got) + off;
2860 1.1 christos outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2861 1.1 christos outrel.r_addend = relocation; /* Link-time addr. */
2862 1.1 christos loongarch_elf_append_rela (output_bfd, s, &outrel);
2863 1.1 christos }
2864 1.1 christos bfd_put_NN (output_bfd, relocation, got->contents + off);
2865 1.1 christos h->got.offset |= 1;
2866 1.1 christos }
2867 1.1 christos }
2868 1.1 christos else
2869 1.1 christos {
2870 1.1 christos if (!local_got_offsets)
2871 1.1 christos {
2872 1.1 christos fatal = (loongarch_reloc_is_fatal
2873 1.1 christos (info, input_bfd, input_section, rel, howto,
2874 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2875 1.1 christos "Internal: local got offsets not reporesent."));
2876 1.1 christos break;
2877 1.1 christos }
2878 1.1 christos
2879 1.1 christos off = local_got_offsets[r_symndx] & (~1);
2880 1.1 christos
2881 1.1 christos if (local_got_offsets[r_symndx] == MINUS_ONE)
2882 1.1 christos {
2883 1.1 christos fatal = (loongarch_reloc_is_fatal
2884 1.1 christos (info, input_bfd, input_section, rel, howto,
2885 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2886 1.1 christos "Internal: GOT entry doesn't represent."));
2887 1.1 christos break;
2888 1.1 christos }
2889 1.1 christos
2890 1.1 christos /* The offset must always be a multiple of the word size.
2891 1.1 christos So, we can use the least significant bit to record
2892 1.1 christos whether we have already processed this entry. */
2893 1.1 christos if ((local_got_offsets[r_symndx] & 1) == 0)
2894 1.1 christos {
2895 1.1 christos if (is_pic)
2896 1.1 christos {
2897 1.1 christos asection *s;
2898 1.1 christos Elf_Internal_Rela outrel;
2899 1.1 christos /* We need to generate a R_LARCH_RELATIVE reloc
2900 1.1 christos for the dynamic linker. */
2901 1.1 christos s = htab->elf.srelgot;
2902 1.1 christos if (!s)
2903 1.1 christos {
2904 1.1 christos fatal = (loongarch_reloc_is_fatal
2905 1.1 christos (info, input_bfd, input_section, rel, howto,
2906 1.1 christos bfd_reloc_notsupported, is_undefweak, name,
2907 1.1 christos "Internal: '.rel.got' not represent"));
2908 1.1 christos break;
2909 1.1 christos }
2910 1.1 christos
2911 1.1 christos outrel.r_offset = sec_addr (got) + off;
2912 1.1 christos outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2913 1.1 christos outrel.r_addend = relocation; /* Link-time addr. */
2914 1.1 christos loongarch_elf_append_rela (output_bfd, s, &outrel);
2915 1.1 christos }
2916 1.1 christos
2917 1.1 christos bfd_put_NN (output_bfd, relocation, got->contents + off);
2918 1.1 christos local_got_offsets[r_symndx] |= 1;
2919 1.1 christos }
2920 1.1 christos }
2921 1.1 christos relocation = off;
2922 1.1 christos
2923 1.1 christos break;
2924 1.1 christos
2925 1.1 christos case R_LARCH_SOP_PUSH_TLS_GOT:
2926 1.1 christos case R_LARCH_SOP_PUSH_TLS_GD:
2927 1.1 christos {
2928 1.1 christos unresolved_reloc = false;
2929 1.1 christos if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
2930 1.1 christos is_ie = true;
2931 1.1 christos
2932 1.1 christos bfd_vma got_off = 0;
2933 1.1 christos if (h != NULL)
2934 1.1 christos {
2935 1.1 christos got_off = h->got.offset;
2936 1.1 christos h->got.offset |= 1;
2937 1.1 christos }
2938 1.1 christos else
2939 1.1 christos {
2940 1.1 christos got_off = local_got_offsets[r_symndx];
2941 1.1 christos local_got_offsets[r_symndx] |= 1;
2942 1.1 christos }
2943 1.1 christos
2944 1.1 christos BFD_ASSERT (got_off != MINUS_ONE);
2945 1.1 christos
2946 1.1 christos ie_off = 0;
2947 1.1 christos tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
2948 1.1 christos if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
2949 1.1 christos ie_off = 2 * GOT_ENTRY_SIZE;
2950 1.1 christos
2951 1.1 christos if ((got_off & 1) == 0)
2952 1.1 christos {
2953 1.1 christos Elf_Internal_Rela rela;
2954 1.1 christos asection *srel = htab->elf.srelgot;
2955 1.1 christos bfd_vma tls_block_off = 0;
2956 1.1 christos
2957 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
2958 1.1 christos {
2959 1.1 christos BFD_ASSERT (elf_hash_table (info)->tls_sec);
2960 1.1 christos tls_block_off = relocation
2961 1.1 christos - elf_hash_table (info)->tls_sec->vma;
2962 1.1 christos }
2963 1.1 christos
2964 1.1 christos if (tls_type & GOT_TLS_GD)
2965 1.1 christos {
2966 1.1 christos rela.r_offset = sec_addr (got) + got_off;
2967 1.1 christos rela.r_addend = 0;
2968 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
2969 1.1 christos {
2970 1.1 christos /* Local sym, used in exec, set module id 1. */
2971 1.1 christos if (bfd_link_executable (info))
2972 1.1 christos bfd_put_NN (output_bfd, 1, got->contents + got_off);
2973 1.1 christos else
2974 1.1 christos {
2975 1.1 christos rela.r_info = ELFNN_R_INFO (0,
2976 1.1 christos R_LARCH_TLS_DTPMODNN);
2977 1.1 christos loongarch_elf_append_rela (output_bfd, srel, &rela);
2978 1.1 christos }
2979 1.1 christos
2980 1.1 christos bfd_put_NN (output_bfd, tls_block_off,
2981 1.1 christos got->contents + got_off + GOT_ENTRY_SIZE);
2982 1.1 christos }
2983 1.1 christos /* Dynamic resolved. */
2984 1.1 christos else
2985 1.1 christos {
2986 1.1 christos /* Dynamic relocate module id. */
2987 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx,
2988 1.1 christos R_LARCH_TLS_DTPMODNN);
2989 1.1 christos loongarch_elf_append_rela (output_bfd, srel, &rela);
2990 1.1 christos
2991 1.1 christos /* Dynamic relocate offset of block. */
2992 1.1 christos rela.r_offset += GOT_ENTRY_SIZE;
2993 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx,
2994 1.1 christos R_LARCH_TLS_DTPRELNN);
2995 1.1 christos loongarch_elf_append_rela (output_bfd, srel, &rela);
2996 1.1 christos }
2997 1.1 christos }
2998 1.1 christos if (tls_type & GOT_TLS_IE)
2999 1.1 christos {
3000 1.1 christos rela.r_offset = sec_addr (got) + got_off + ie_off;
3001 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
3002 1.1 christos {
3003 1.1 christos /* Local sym, used in exec, set module id 1. */
3004 1.1 christos if (!bfd_link_executable (info))
3005 1.1 christos {
3006 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
3007 1.1 christos rela.r_addend = tls_block_off;
3008 1.1 christos loongarch_elf_append_rela (output_bfd, srel, &rela);
3009 1.1 christos }
3010 1.1 christos
3011 1.1 christos bfd_put_NN (output_bfd, tls_block_off,
3012 1.1 christos got->contents + got_off + ie_off);
3013 1.1 christos }
3014 1.1 christos /* Dynamic resolved. */
3015 1.1 christos else
3016 1.1 christos {
3017 1.1 christos /* Dynamic relocate offset of block. */
3018 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx,
3019 1.1 christos R_LARCH_TLS_TPRELNN);
3020 1.1 christos rela.r_addend = 0;
3021 1.1 christos loongarch_elf_append_rela (output_bfd, srel, &rela);
3022 1.1 christos }
3023 1.1 christos }
3024 1.1 christos }
3025 1.1 christos
3026 1.1 christos relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0);
3027 1.1 christos }
3028 1.1 christos break;
3029 1.1 christos
3030 1.1 christos /* New reloc types. */
3031 1.1 christos case R_LARCH_B21:
3032 1.1 christos case R_LARCH_B26:
3033 1.1 christos case R_LARCH_B16:
3034 1.1 christos unresolved_reloc = false;
3035 1.1 christos if (is_undefweak)
3036 1.1 christos {
3037 1.1 christos relocation = 0;
3038 1.1 christos }
3039 1.1 christos
3040 1.1 christos if (resolved_local)
3041 1.1 christos {
3042 1.1 christos relocation -= pc;
3043 1.1 christos relocation += rel->r_addend;
3044 1.1 christos }
3045 1.1 christos else if (resolved_dynly)
3046 1.1 christos {
3047 1.1 christos BFD_ASSERT (h
3048 1.1 christos && (h->plt.offset != MINUS_ONE
3049 1.1 christos || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
3050 1.1 christos && rel->r_addend == 0);
3051 1.1 christos if (h && h->plt.offset == MINUS_ONE
3052 1.1 christos && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
3053 1.1 christos {
3054 1.1 christos relocation -= pc;
3055 1.1 christos relocation += rel->r_addend;
3056 1.1 christos }
3057 1.1 christos else
3058 1.1 christos relocation = sec_addr (plt) + h->plt.offset - pc;
3059 1.1 christos }
3060 1.1 christos
3061 1.1 christos break;
3062 1.1 christos
3063 1.1 christos case R_LARCH_ABS_HI20:
3064 1.1 christos case R_LARCH_ABS_LO12:
3065 1.1 christos case R_LARCH_ABS64_LO20:
3066 1.1 christos case R_LARCH_ABS64_HI12:
3067 1.1 christos BFD_ASSERT (!is_pic);
3068 1.1 christos
3069 1.1 christos if (is_undefweak)
3070 1.1 christos {
3071 1.1 christos BFD_ASSERT (resolved_dynly);
3072 1.1 christos relocation = 0;
3073 1.1 christos break;
3074 1.1 christos }
3075 1.1 christos else if (resolved_to_const || resolved_local)
3076 1.1 christos {
3077 1.1 christos relocation += rel->r_addend;
3078 1.1 christos }
3079 1.1 christos else if (resolved_dynly)
3080 1.1 christos {
3081 1.1 christos unresolved_reloc = false;
3082 1.1 christos BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE)
3083 1.1 christos && rel->r_addend == 0);
3084 1.1 christos relocation = sec_addr (plt) + h->plt.offset;
3085 1.1 christos }
3086 1.1 christos
3087 1.1 christos break;
3088 1.1 christos
3089 1.1 christos case R_LARCH_PCALA_HI20:
3090 1.1 christos unresolved_reloc = false;
3091 1.1 christos if (h && h->plt.offset != MINUS_ONE)
3092 1.1 christos relocation = sec_addr (plt) + h->plt.offset;
3093 1.1 christos else
3094 1.1 christos relocation += rel->r_addend;
3095 1.1 christos
3096 1.1 christos RELOCATE_CALC_PC32_HI20 (relocation, pc);
3097 1.1 christos
3098 1.1 christos break;
3099 1.1 christos
3100 1.1 christos case R_LARCH_PCALA_LO12:
3101 1.1 christos /* Not support if sym_addr in 2k page edge.
3102 1.1 christos pcalau12i pc_hi20 (sym_addr)
3103 1.1 christos ld.w/d pc_lo12 (sym_addr)
3104 1.1 christos ld.w/d pc_lo12 (sym_addr + x)
3105 1.1 christos ...
3106 1.1 christos can not calc correct address
3107 1.1 christos if sym_addr < 0x800 && sym_addr + x >= 0x800. */
3108 1.1 christos
3109 1.1 christos if (h && h->plt.offset != MINUS_ONE)
3110 1.1 christos relocation = sec_addr (plt) + h->plt.offset;
3111 1.1 christos else
3112 1.1 christos relocation += rel->r_addend;
3113 1.1 christos
3114 1.1 christos relocation &= 0xfff;
3115 1.1 christos /* Signed extend. */
3116 1.1 christos relocation = (relocation ^ 0x800) - 0x800;
3117 1.1 christos
3118 1.1 christos /* For 2G jump, generate pcalau12i, jirl. */
3119 1.1 christos /* If use jirl, turns to R_LARCH_B16. */
3120 1.1 christos uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
3121 1.1 christos if ((insn & 0x4c000000) == 0x4c000000)
3122 1.1 christos {
3123 1.1 christos rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
3124 1.1 christos howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
3125 1.1 christos }
3126 1.1 christos break;
3127 1.1 christos
3128 1.1 christos case R_LARCH_PCALA64_LO20:
3129 1.1 christos case R_LARCH_PCALA64_HI12:
3130 1.1 christos if (h && h->plt.offset != MINUS_ONE)
3131 1.1 christos relocation = sec_addr (plt) + h->plt.offset;
3132 1.1 christos else
3133 1.1 christos relocation += rel->r_addend;
3134 1.1 christos
3135 1.1 christos RELOCATE_CALC_PC64_HI32 (relocation, pc);
3136 1.1 christos
3137 1.1 christos break;
3138 1.1 christos
3139 1.1 christos case R_LARCH_GOT_PC_HI20:
3140 1.1 christos case R_LARCH_GOT_HI20:
3141 1.1 christos /* Calc got offset. */
3142 1.1 christos {
3143 1.1 christos unresolved_reloc = false;
3144 1.1 christos BFD_ASSERT (rel->r_addend == 0);
3145 1.1 christos
3146 1.1 christos bfd_vma got_off = 0;
3147 1.1 christos if (h != NULL)
3148 1.1 christos {
3149 1.1 christos /* GOT ref or ifunc. */
3150 1.1 christos BFD_ASSERT (h->got.offset != MINUS_ONE
3151 1.1 christos || h->type == STT_GNU_IFUNC);
3152 1.1 christos
3153 1.1 christos got_off = h->got.offset & (~(bfd_vma)1);
3154 1.1 christos /* Hidden symbol not has got entry,
3155 1.1 christos * only got.plt entry so it is (plt - got). */
3156 1.1 christos if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
3157 1.1 christos {
3158 1.1 christos bfd_vma idx;
3159 1.1 christos if (htab->elf.splt != NULL)
3160 1.1 christos {
3161 1.1 christos idx = (h->plt.offset - PLT_HEADER_SIZE)
3162 1.1 christos / PLT_ENTRY_SIZE;
3163 1.1 christos got_off = sec_addr (htab->elf.sgotplt)
3164 1.1 christos + GOTPLT_HEADER_SIZE
3165 1.1 christos + (idx * GOT_ENTRY_SIZE)
3166 1.1 christos - sec_addr (htab->elf.sgot);
3167 1.1 christos }
3168 1.1 christos else
3169 1.1 christos {
3170 1.1 christos idx = h->plt.offset / PLT_ENTRY_SIZE;
3171 1.1 christos got_off = sec_addr (htab->elf.sgotplt)
3172 1.1 christos + (idx * GOT_ENTRY_SIZE)
3173 1.1 christos - sec_addr (htab->elf.sgot);
3174 1.1 christos }
3175 1.1 christos }
3176 1.1 christos
3177 1.1 christos if ((h->got.offset & 1) == 0)
3178 1.1 christos {
3179 1.1 christos /* We need to generate a R_LARCH_RELATIVE reloc once
3180 1.1 christos * in loongarch_elf_finish_dynamic_symbol or now,
3181 1.1 christos * call finish_dyn && nopic
3182 1.1 christos * or !call finish_dyn && pic. */
3183 1.1 christos if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
3184 1.1 christos bfd_link_pic (info),
3185 1.1 christos h)
3186 1.1 christos && bfd_link_pic (info)
3187 1.1 christos && SYMBOL_REFERENCES_LOCAL (info, h))
3188 1.1 christos {
3189 1.1 christos Elf_Internal_Rela rela;
3190 1.1 christos rela.r_offset = sec_addr (got) + got_off;
3191 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3192 1.1 christos rela.r_addend = relocation;
3193 1.1 christos loongarch_elf_append_rela (output_bfd,
3194 1.1 christos htab->elf.srelgot, &rela);
3195 1.1 christos }
3196 1.1 christos h->got.offset |= 1;
3197 1.1 christos bfd_put_NN (output_bfd, relocation,
3198 1.1 christos got->contents + got_off);
3199 1.1 christos }
3200 1.1 christos }
3201 1.1 christos else
3202 1.1 christos {
3203 1.1 christos BFD_ASSERT (local_got_offsets
3204 1.1 christos && local_got_offsets[r_symndx] != MINUS_ONE);
3205 1.1 christos
3206 1.1 christos got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
3207 1.1 christos if ((local_got_offsets[r_symndx] & 1) == 0)
3208 1.1 christos {
3209 1.1 christos if (bfd_link_pic (info))
3210 1.1 christos {
3211 1.1 christos Elf_Internal_Rela rela;
3212 1.1 christos rela.r_offset = sec_addr (got) + got_off;
3213 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3214 1.1 christos rela.r_addend = relocation;
3215 1.1 christos loongarch_elf_append_rela (output_bfd,
3216 1.1 christos htab->elf.srelgot, &rela);
3217 1.1 christos }
3218 1.1 christos local_got_offsets[r_symndx] |= 1;
3219 1.1 christos }
3220 1.1 christos bfd_put_NN (output_bfd, relocation, got->contents + got_off);
3221 1.1 christos }
3222 1.1 christos
3223 1.1 christos relocation = got_off + sec_addr (got);
3224 1.1 christos }
3225 1.1 christos
3226 1.1 christos if (r_type == R_LARCH_GOT_PC_HI20)
3227 1.1 christos RELOCATE_CALC_PC32_HI20 (relocation, pc);
3228 1.1 christos
3229 1.1 christos break;
3230 1.1 christos
3231 1.1 christos case R_LARCH_GOT_PC_LO12:
3232 1.1 christos case R_LARCH_GOT64_PC_LO20:
3233 1.1 christos case R_LARCH_GOT64_PC_HI12:
3234 1.1 christos case R_LARCH_GOT_LO12:
3235 1.1 christos case R_LARCH_GOT64_LO20:
3236 1.1 christos case R_LARCH_GOT64_HI12:
3237 1.1 christos {
3238 1.1 christos unresolved_reloc = false;
3239 1.1 christos bfd_vma got_off;
3240 1.1 christos if (h)
3241 1.1 christos got_off = h->got.offset & (~(bfd_vma)1);
3242 1.1 christos else
3243 1.1 christos got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
3244 1.1 christos
3245 1.1 christos if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
3246 1.1 christos {
3247 1.1 christos bfd_vma idx;
3248 1.1 christos if (htab->elf.splt != NULL)
3249 1.1 christos idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
3250 1.1 christos else
3251 1.1 christos idx = h->plt.offset / PLT_ENTRY_SIZE;
3252 1.1 christos
3253 1.1 christos got_off = sec_addr (htab->elf.sgotplt)
3254 1.1 christos + GOTPLT_HEADER_SIZE
3255 1.1 christos + (idx * GOT_ENTRY_SIZE)
3256 1.1 christos - sec_addr (htab->elf.sgot);
3257 1.1 christos }
3258 1.1 christos relocation = got_off + sec_addr (got);
3259 1.1 christos }
3260 1.1 christos
3261 1.1 christos if (r_type == R_LARCH_GOT_PC_LO12)
3262 1.1 christos relocation &= (bfd_vma)0xfff;
3263 1.1 christos else if (r_type == R_LARCH_GOT64_PC_LO20
3264 1.1 christos || r_type == R_LARCH_GOT64_PC_HI12)
3265 1.1 christos RELOCATE_CALC_PC64_HI32 (relocation, pc);
3266 1.1 christos
3267 1.1 christos break;
3268 1.1 christos
3269 1.1 christos case R_LARCH_TLS_LE_HI20:
3270 1.1 christos case R_LARCH_TLS_LE_LO12:
3271 1.1 christos case R_LARCH_TLS_LE64_LO20:
3272 1.1 christos case R_LARCH_TLS_LE64_HI12:
3273 1.1 christos BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
3274 1.1 christos
3275 1.1 christos relocation -= elf_hash_table (info)->tls_sec->vma;
3276 1.1 christos break;
3277 1.1 christos
3278 1.1 christos /* TLS IE LD/GD process separately is troublesome.
3279 1.1 christos When a symbol is both ie and LD/GD, h->got.off |= 1
3280 1.1 christos make only one type be relocated. We must use
3281 1.1 christos h->got.offset |= 1 and h->got.offset |= 2
3282 1.1 christos diff IE and LD/GD. And all (got_off & (~(bfd_vma)1))
3283 1.1 christos (IE LD/GD and reusable GOT reloc) must change to
3284 1.1 christos (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
3285 1.1 christos as a tag.
3286 1.1 christos Now, LD and GD is both GOT_TLS_GD type, LD seems to
3287 1.1 christos can be omitted. */
3288 1.1 christos case R_LARCH_TLS_IE_PC_HI20:
3289 1.1 christos case R_LARCH_TLS_IE_HI20:
3290 1.1 christos case R_LARCH_TLS_LD_PC_HI20:
3291 1.1 christos case R_LARCH_TLS_LD_HI20:
3292 1.1 christos case R_LARCH_TLS_GD_PC_HI20:
3293 1.1 christos case R_LARCH_TLS_GD_HI20:
3294 1.1 christos BFD_ASSERT (rel->r_addend == 0);
3295 1.1 christos unresolved_reloc = false;
3296 1.1 christos
3297 1.1 christos if (r_type == R_LARCH_TLS_IE_PC_HI20
3298 1.1 christos || r_type == R_LARCH_TLS_IE_HI20)
3299 1.1 christos is_ie = true;
3300 1.1 christos
3301 1.1 christos bfd_vma got_off = 0;
3302 1.1 christos if (h != NULL)
3303 1.1 christos {
3304 1.1 christos got_off = h->got.offset;
3305 1.1 christos h->got.offset |= 1;
3306 1.1 christos }
3307 1.1 christos else
3308 1.1 christos {
3309 1.1 christos got_off = local_got_offsets[r_symndx];
3310 1.1 christos local_got_offsets[r_symndx] |= 1;
3311 1.1 christos }
3312 1.1 christos
3313 1.1 christos BFD_ASSERT (got_off != MINUS_ONE);
3314 1.1 christos
3315 1.1 christos ie_off = 0;
3316 1.1 christos tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
3317 1.1 christos if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3318 1.1 christos ie_off = 2 * GOT_ENTRY_SIZE;
3319 1.1 christos
3320 1.1 christos if ((got_off & 1) == 0)
3321 1.1 christos {
3322 1.1 christos Elf_Internal_Rela rela;
3323 1.1 christos asection *relgot = htab->elf.srelgot;
3324 1.1 christos bfd_vma tls_block_off = 0;
3325 1.1 christos
3326 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
3327 1.1 christos {
3328 1.1 christos BFD_ASSERT (elf_hash_table (info)->tls_sec);
3329 1.1 christos tls_block_off = relocation
3330 1.1 christos - elf_hash_table (info)->tls_sec->vma;
3331 1.1 christos }
3332 1.1 christos
3333 1.1 christos if (tls_type & GOT_TLS_GD)
3334 1.1 christos {
3335 1.1 christos rela.r_offset = sec_addr (got) + got_off;
3336 1.1 christos rela.r_addend = 0;
3337 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
3338 1.1 christos {
3339 1.1 christos /* Local sym, used in exec, set module id 1. */
3340 1.1 christos if (bfd_link_executable (info))
3341 1.1 christos bfd_put_NN (output_bfd, 1, got->contents + got_off);
3342 1.1 christos else
3343 1.1 christos {
3344 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
3345 1.1 christos loongarch_elf_append_rela (output_bfd, relgot, &rela);
3346 1.1 christos }
3347 1.1 christos
3348 1.1 christos bfd_put_NN (output_bfd, tls_block_off,
3349 1.1 christos got->contents + got_off + GOT_ENTRY_SIZE);
3350 1.1 christos }
3351 1.1 christos /* Dynamic resolved. */
3352 1.1 christos else
3353 1.1 christos {
3354 1.1 christos /* Dynamic relocate module id. */
3355 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx,
3356 1.1 christos R_LARCH_TLS_DTPMODNN);
3357 1.1 christos loongarch_elf_append_rela (output_bfd, relgot, &rela);
3358 1.1 christos
3359 1.1 christos /* Dynamic relocate offset of block. */
3360 1.1 christos rela.r_offset += GOT_ENTRY_SIZE;
3361 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx,
3362 1.1 christos R_LARCH_TLS_DTPRELNN);
3363 1.1 christos loongarch_elf_append_rela (output_bfd, relgot, &rela);
3364 1.1 christos }
3365 1.1 christos }
3366 1.1 christos if (tls_type & GOT_TLS_IE)
3367 1.1 christos {
3368 1.1 christos rela.r_offset = sec_addr (got) + got_off + ie_off;
3369 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
3370 1.1 christos {
3371 1.1 christos /* Local sym, used in exec, set module id 1. */
3372 1.1 christos if (!bfd_link_executable (info))
3373 1.1 christos {
3374 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
3375 1.1 christos rela.r_addend = tls_block_off;
3376 1.1 christos loongarch_elf_append_rela (output_bfd, relgot, &rela);
3377 1.1 christos }
3378 1.1 christos
3379 1.1 christos bfd_put_NN (output_bfd, tls_block_off,
3380 1.1 christos got->contents + got_off + ie_off);
3381 1.1 christos }
3382 1.1 christos /* Dynamic resolved. */
3383 1.1 christos else
3384 1.1 christos {
3385 1.1 christos /* Dynamic relocate offset of block. */
3386 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx,
3387 1.1 christos R_LARCH_TLS_TPRELNN);
3388 1.1 christos rela.r_addend = 0;
3389 1.1 christos loongarch_elf_append_rela (output_bfd, relgot, &rela);
3390 1.1 christos }
3391 1.1 christos }
3392 1.1 christos }
3393 1.1 christos relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
3394 1.1 christos + (is_ie ? ie_off : 0);
3395 1.1 christos
3396 1.1 christos if (r_type == R_LARCH_TLS_LD_PC_HI20
3397 1.1 christos || r_type == R_LARCH_TLS_GD_PC_HI20
3398 1.1 christos || r_type == R_LARCH_TLS_IE_PC_HI20)
3399 1.1 christos RELOCATE_CALC_PC32_HI20 (relocation, pc);
3400 1.1 christos
3401 1.1 christos break;
3402 1.1 christos
3403 1.1 christos case R_LARCH_TLS_IE_PC_LO12:
3404 1.1 christos case R_LARCH_TLS_IE64_PC_LO20:
3405 1.1 christos case R_LARCH_TLS_IE64_PC_HI12:
3406 1.1 christos case R_LARCH_TLS_IE_LO12:
3407 1.1 christos case R_LARCH_TLS_IE64_LO20:
3408 1.1 christos case R_LARCH_TLS_IE64_HI12:
3409 1.1 christos unresolved_reloc = false;
3410 1.1 christos
3411 1.1 christos if (h)
3412 1.1 christos relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
3413 1.1 christos else
3414 1.1 christos relocation = sec_addr (got)
3415 1.1 christos + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
3416 1.1 christos
3417 1.1 christos tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
3418 1.1 christos /* Use both TLS_GD and TLS_IE. */
3419 1.1 christos if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3420 1.1 christos relocation += 2 * GOT_ENTRY_SIZE;
3421 1.1 christos
3422 1.1 christos if (r_type == R_LARCH_TLS_IE_PC_LO12)
3423 1.1 christos relocation &= (bfd_vma)0xfff;
3424 1.1 christos else if (r_type == R_LARCH_TLS_IE64_PC_LO20
3425 1.1 christos || r_type == R_LARCH_TLS_IE64_PC_HI12)
3426 1.1 christos RELOCATE_CALC_PC64_HI32 (relocation, pc);
3427 1.1 christos
3428 1.1 christos break;
3429 1.1 christos
3430 1.1 christos case R_LARCH_RELAX:
3431 1.1 christos break;
3432 1.1 christos
3433 1.1 christos default:
3434 1.1 christos break;
3435 1.1 christos }
3436 1.1 christos
3437 1.1 christos if (fatal)
3438 1.1 christos break;
3439 1.1 christos
3440 1.1 christos do
3441 1.1 christos {
3442 1.1 christos /* 'unresolved_reloc' means we haven't done it yet.
3443 1.1 christos We need help of dynamic linker to fix this memory location up. */
3444 1.1 christos if (!unresolved_reloc)
3445 1.1 christos break;
3446 1.1 christos
3447 1.1 christos if (_bfd_elf_section_offset (output_bfd, info, input_section,
3448 1.1 christos rel->r_offset) == MINUS_ONE)
3449 1.1 christos /* WHY? May because it's invalid so skip checking.
3450 1.1 christos But why dynamic reloc a invalid section? */
3451 1.1 christos break;
3452 1.1 christos
3453 1.1 christos if (input_section->output_section->flags & SEC_DEBUGGING)
3454 1.1 christos {
3455 1.1 christos fatal = (loongarch_reloc_is_fatal
3456 1.1 christos (info, input_bfd, input_section, rel, howto,
3457 1.1 christos bfd_reloc_dangerous, is_undefweak, name,
3458 1.1 christos "Seems dynamic linker not process "
3459 1.1 christos "sections 'SEC_DEBUGGING'."));
3460 1.1 christos }
3461 1.1 christos if (!is_dyn)
3462 1.1 christos break;
3463 1.1 christos
3464 1.1 christos if ((info->flags & DF_TEXTREL) == 0)
3465 1.1 christos if (input_section->output_section->flags & SEC_READONLY)
3466 1.1 christos info->flags |= DF_TEXTREL;
3467 1.1 christos }
3468 1.1 christos while (0);
3469 1.1 christos
3470 1.1 christos if (fatal)
3471 1.1 christos break;
3472 1.1 christos
3473 1.1 christos loongarch_record_one_reloc (input_bfd, input_section, r_type,
3474 1.1 christos rel->r_offset, sym, h, rel->r_addend);
3475 1.1 christos
3476 1.1 christos if (r != bfd_reloc_continue)
3477 1.1 christos r = perform_relocation (rel, input_section, howto, relocation,
3478 1.1 christos input_bfd, contents);
3479 1.1 christos
3480 1.1 christos switch (r)
3481 1.1 christos {
3482 1.1 christos case bfd_reloc_dangerous:
3483 1.1 christos case bfd_reloc_continue:
3484 1.1 christos case bfd_reloc_ok:
3485 1.1 christos continue;
3486 1.1 christos
3487 1.1 christos case bfd_reloc_overflow:
3488 1.1 christos /* Overflow value can't be filled in. */
3489 1.1 christos loongarch_dump_reloc_record (info->callbacks->info);
3490 1.1 christos info->callbacks->reloc_overflow
3491 1.1 christos (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
3492 1.1 christos input_bfd, input_section, rel->r_offset);
3493 1.1 christos break;
3494 1.1 christos
3495 1.1 christos case bfd_reloc_outofrange:
3496 1.1 christos /* Stack state incorrect. */
3497 1.1 christos loongarch_dump_reloc_record (info->callbacks->info);
3498 1.1 christos info->callbacks->info
3499 1.1 christos ("%X%H: Internal stack state is incorrect.\n"
3500 1.1 christos "Want to push to full stack or pop from empty stack?\n",
3501 1.1 christos input_bfd, input_section, rel->r_offset);
3502 1.1 christos break;
3503 1.1 christos
3504 1.1 christos case bfd_reloc_notsupported:
3505 1.1 christos info->callbacks->info ("%X%H: Unknown relocation type.\n", input_bfd,
3506 1.1 christos input_section, rel->r_offset);
3507 1.1 christos break;
3508 1.1 christos
3509 1.1 christos default:
3510 1.1 christos info->callbacks->info ("%X%H: Internal: unknown error.\n", input_bfd,
3511 1.1 christos input_section, rel->r_offset);
3512 1.1 christos break;
3513 1.1 christos }
3514 1.1 christos
3515 1.1 christos fatal = true;
3516 1.1 christos }
3517 1.1 christos
3518 1.1 christos return !fatal;
3519 1.1 christos }
3520 1.1 christos
3521 1.1 christos /* Finish up dynamic symbol handling. We set the contents of various
3522 1.1 christos dynamic sections here. */
3523 1.1 christos
3524 1.1 christos static bool
3525 1.1 christos loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
3526 1.1 christos struct bfd_link_info *info,
3527 1.1 christos struct elf_link_hash_entry *h,
3528 1.1 christos Elf_Internal_Sym *sym)
3529 1.1 christos {
3530 1.1 christos struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
3531 1.1 christos const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
3532 1.1 christos asection *rela_dyn = bfd_get_section_by_name (output_bfd, ".rela.dyn");
3533 1.1 christos struct bfd_link_order *lo = NULL;
3534 1.1 christos Elf_Internal_Rela *slot = NULL, *last_slot = NULL;
3535 1.1 christos
3536 1.1 christos if (rela_dyn)
3537 1.1 christos lo = rela_dyn->map_head.link_order;
3538 1.1 christos
3539 1.1 christos if (h->plt.offset != MINUS_ONE)
3540 1.1 christos {
3541 1.1 christos size_t i, plt_idx;
3542 1.1 christos asection *plt, *gotplt, *relplt;
3543 1.1 christos bfd_vma got_address;
3544 1.1 christos uint32_t plt_entry[PLT_ENTRY_INSNS];
3545 1.1 christos bfd_byte *loc;
3546 1.1 christos Elf_Internal_Rela rela;
3547 1.1 christos asection *rela_sec = NULL;
3548 1.1 christos
3549 1.1 christos if (htab->elf.splt)
3550 1.1 christos {
3551 1.1 christos BFD_ASSERT ((h->type == STT_GNU_IFUNC
3552 1.1 christos && SYMBOL_REFERENCES_LOCAL (info, h))
3553 1.1 christos || h->dynindx != -1);
3554 1.1 christos
3555 1.1 christos plt = htab->elf.splt;
3556 1.1 christos gotplt = htab->elf.sgotplt;
3557 1.1 christos if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
3558 1.1 christos relplt = htab->elf.srelgot;
3559 1.1 christos else
3560 1.1 christos relplt = htab->elf.srelplt;
3561 1.1 christos plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
3562 1.1 christos got_address =
3563 1.1 christos sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
3564 1.1 christos }
3565 1.1 christos else /* if (htab->elf.iplt) */
3566 1.1 christos {
3567 1.1 christos BFD_ASSERT (h->type == STT_GNU_IFUNC
3568 1.1 christos && SYMBOL_REFERENCES_LOCAL (info, h));
3569 1.1 christos
3570 1.1 christos plt = htab->elf.iplt;
3571 1.1 christos gotplt = htab->elf.igotplt;
3572 1.1 christos relplt = htab->elf.irelplt;
3573 1.1 christos plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
3574 1.1 christos got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
3575 1.1 christos }
3576 1.1 christos
3577 1.1 christos /* Find out where the .plt entry should go. */
3578 1.1 christos loc = plt->contents + h->plt.offset;
3579 1.1 christos
3580 1.1 christos /* Fill in the PLT entry itself. */
3581 1.1 christos if (!loongarch_make_plt_entry (got_address,
3582 1.1 christos sec_addr (plt) + h->plt.offset,
3583 1.1 christos plt_entry))
3584 1.1 christos return false;
3585 1.1 christos
3586 1.1 christos for (i = 0; i < PLT_ENTRY_INSNS; i++)
3587 1.1 christos bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
3588 1.1 christos
3589 1.1 christos /* Fill in the initial value of the got.plt entry. */
3590 1.1 christos loc = gotplt->contents + (got_address - sec_addr (gotplt));
3591 1.1 christos bfd_put_NN (output_bfd, sec_addr (plt), loc);
3592 1.1 christos
3593 1.1 christos rela.r_offset = got_address;
3594 1.1 christos
3595 1.1 christos /* TRUE if this is a PLT reference to a local IFUNC. */
3596 1.1 christos if (PLT_LOCAL_IFUNC_P (info, h)
3597 1.1 christos && (relplt == htab->elf.srelgot
3598 1.1 christos || relplt == htab->elf.irelplt))
3599 1.1 christos {
3600 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
3601 1.1 christos rela.r_addend = (h->root.u.def.value
3602 1.1 christos + h->root.u.def.section->output_section->vma
3603 1.1 christos + h->root.u.def.section->output_offset);
3604 1.1 christos
3605 1.1 christos /* Find the space after dyn sort. */
3606 1.1 christos while (slot == last_slot || slot->r_offset != 0)
3607 1.1 christos {
3608 1.1 christos if (slot != last_slot)
3609 1.1 christos {
3610 1.1 christos slot++;
3611 1.1 christos continue;
3612 1.1 christos }
3613 1.1 christos
3614 1.1 christos BFD_ASSERT (lo != NULL);
3615 1.1 christos rela_sec = lo->u.indirect.section;
3616 1.1 christos lo = lo->next;
3617 1.1 christos
3618 1.1 christos slot = (Elf_Internal_Rela *)rela_sec->contents;
3619 1.1 christos last_slot = (Elf_Internal_Rela *)(rela_sec->contents +
3620 1.1 christos rela_sec->size);
3621 1.1 christos }
3622 1.1 christos
3623 1.1 christos bed->s->swap_reloca_out (output_bfd, &rela, (bfd_byte *)slot);
3624 1.1 christos rela_sec->reloc_count++;
3625 1.1 christos }
3626 1.1 christos else
3627 1.1 christos {
3628 1.1 christos /* Fill in the entry in the rela.plt section. */
3629 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
3630 1.1 christos rela.r_addend = 0;
3631 1.1 christos loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
3632 1.1 christos bed->s->swap_reloca_out (output_bfd, &rela, loc);
3633 1.1 christos }
3634 1.1 christos
3635 1.1 christos if (!h->def_regular)
3636 1.1 christos {
3637 1.1 christos /* Mark the symbol as undefined, rather than as defined in
3638 1.1 christos the .plt section. Leave the value alone. */
3639 1.1 christos sym->st_shndx = SHN_UNDEF;
3640 1.1 christos /* If the symbol is weak, we do need to clear the value.
3641 1.1 christos Otherwise, the PLT entry would provide a definition for
3642 1.1 christos the symbol even if the symbol wasn't defined anywhere,
3643 1.1 christos and so the symbol would never be NULL. */
3644 1.1 christos if (!h->ref_regular_nonweak)
3645 1.1 christos sym->st_value = 0;
3646 1.1 christos }
3647 1.1 christos }
3648 1.1 christos
3649 1.1 christos if (h->got.offset != MINUS_ONE
3650 1.1 christos /* TLS got entry have been handled in elf_relocate_section. */
3651 1.1 christos && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
3652 1.1 christos /* Have allocated got entry but not allocated rela before. */
3653 1.1 christos && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
3654 1.1 christos {
3655 1.1 christos asection *sgot, *srela;
3656 1.1 christos Elf_Internal_Rela rela;
3657 1.1 christos bfd_vma off = h->got.offset & ~(bfd_vma)1;
3658 1.1 christos
3659 1.1 christos /* This symbol has an entry in the GOT. Set it up. */
3660 1.1 christos sgot = htab->elf.sgot;
3661 1.1 christos srela = htab->elf.srelgot;
3662 1.1 christos BFD_ASSERT (sgot && srela);
3663 1.1 christos
3664 1.1 christos rela.r_offset = sec_addr (sgot) + off;
3665 1.1 christos
3666 1.1 christos if (h->def_regular
3667 1.1 christos && h->type == STT_GNU_IFUNC)
3668 1.1 christos {
3669 1.1 christos if(h->plt.offset == MINUS_ONE)
3670 1.1 christos {
3671 1.1 christos if (htab->elf.splt == NULL)
3672 1.1 christos srela = htab->elf.irelplt;
3673 1.1 christos
3674 1.1 christos if (SYMBOL_REFERENCES_LOCAL (info, h))
3675 1.1 christos {
3676 1.1 christos asection *sec = h->root.u.def.section;
3677 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
3678 1.1 christos rela.r_addend = h->root.u.def.value + sec->output_section->vma
3679 1.1 christos + sec->output_offset;
3680 1.1 christos bfd_put_NN (output_bfd, 0, sgot->contents + off);
3681 1.1 christos }
3682 1.1 christos else
3683 1.1 christos {
3684 1.1 christos BFD_ASSERT (h->dynindx != -1);
3685 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
3686 1.1 christos rela.r_addend = 0;
3687 1.1 christos bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off);
3688 1.1 christos }
3689 1.1 christos }
3690 1.1 christos else if(bfd_link_pic (info))
3691 1.1 christos {
3692 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
3693 1.1 christos rela.r_addend = 0;
3694 1.1 christos bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
3695 1.1 christos }
3696 1.1 christos else
3697 1.1 christos {
3698 1.1 christos asection *plt;
3699 1.1 christos /* For non-shared object, we can't use .got.plt, which
3700 1.1 christos contains the real function address if we need pointer
3701 1.1 christos equality. We load the GOT entry with the PLT entry. */
3702 1.1 christos plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
3703 1.1 christos bfd_put_NN (output_bfd,
3704 1.1 christos (plt->output_section->vma
3705 1.1 christos + plt->output_offset
3706 1.1 christos + h->plt.offset),
3707 1.1 christos sgot->contents + off);
3708 1.1 christos return true;
3709 1.1 christos }
3710 1.1 christos }
3711 1.1 christos else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
3712 1.1 christos {
3713 1.1 christos asection *sec = h->root.u.def.section;
3714 1.1 christos rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3715 1.1 christos rela.r_addend = (h->root.u.def.value + sec->output_section->vma
3716 1.1 christos + sec->output_offset);
3717 1.1 christos }
3718 1.1 christos else
3719 1.1 christos {
3720 1.1 christos BFD_ASSERT (h->dynindx != -1);
3721 1.1 christos rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
3722 1.1 christos rela.r_addend = 0;
3723 1.1 christos }
3724 1.1 christos
3725 1.1 christos loongarch_elf_append_rela (output_bfd, srela, &rela);
3726 1.1 christos }
3727 1.1 christos
3728 1.1 christos /* Mark some specially defined symbols as absolute. */
3729 1.1 christos if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
3730 1.1 christos sym->st_shndx = SHN_ABS;
3731 1.1 christos
3732 1.1 christos return true;
3733 1.1 christos }
3734 1.1 christos
3735 1.1 christos /* Finish up the dynamic sections. */
3736 1.1 christos
3737 1.1 christos static bool
3738 1.1 christos loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
3739 1.1 christos asection *sdyn)
3740 1.1 christos {
3741 1.1 christos struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
3742 1.1 christos const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
3743 1.1 christos size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
3744 1.1 christos bfd_byte *dyncon, *dynconend;
3745 1.1 christos
3746 1.1 christos dynconend = sdyn->contents + sdyn->size;
3747 1.1 christos for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
3748 1.1 christos {
3749 1.1 christos Elf_Internal_Dyn dyn;
3750 1.1 christos asection *s;
3751 1.1 christos int skipped = 0;
3752 1.1 christos
3753 1.1 christos bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
3754 1.1 christos
3755 1.1 christos switch (dyn.d_tag)
3756 1.1 christos {
3757 1.1 christos case DT_PLTGOT:
3758 1.1 christos s = htab->elf.sgotplt;
3759 1.1 christos dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3760 1.1 christos break;
3761 1.1 christos case DT_JMPREL:
3762 1.1 christos s = htab->elf.srelplt;
3763 1.1 christos dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3764 1.1 christos break;
3765 1.1 christos case DT_PLTRELSZ:
3766 1.1 christos s = htab->elf.srelplt;
3767 1.1 christos dyn.d_un.d_val = s->size;
3768 1.1 christos break;
3769 1.1 christos case DT_TEXTREL:
3770 1.1 christos if ((info->flags & DF_TEXTREL) == 0)
3771 1.1 christos skipped = 1;
3772 1.1 christos break;
3773 1.1 christos case DT_FLAGS:
3774 1.1 christos if ((info->flags & DF_TEXTREL) == 0)
3775 1.1 christos dyn.d_un.d_val &= ~DF_TEXTREL;
3776 1.1 christos break;
3777 1.1 christos }
3778 1.1 christos if (skipped)
3779 1.1 christos skipped_size += dynsize;
3780 1.1 christos else
3781 1.1 christos bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
3782 1.1 christos }
3783 1.1 christos /* Wipe out any trailing entries if we shifted down a dynamic tag. */
3784 1.1 christos memset (dyncon - skipped_size, 0, skipped_size);
3785 1.1 christos return true;
3786 1.1 christos }
3787 1.1 christos
3788 1.1 christos /* Finish up local dynamic symbol handling. We set the contents of
3789 1.1 christos various dynamic sections here. */
3790 1.1 christos
3791 1.1 christos static bool
3792 1.1 christos elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
3793 1.1 christos {
3794 1.1 christos struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
3795 1.1 christos struct bfd_link_info *info = (struct bfd_link_info *) inf;
3796 1.1 christos
3797 1.1 christos return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
3798 1.1 christos }
3799 1.1 christos
3800 1.1 christos static bool
3801 1.1 christos loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
3802 1.1 christos struct bfd_link_info *info)
3803 1.1 christos {
3804 1.1 christos bfd *dynobj;
3805 1.1 christos asection *sdyn, *plt, *gotplt = NULL;
3806 1.1 christos struct loongarch_elf_link_hash_table *htab;
3807 1.1 christos
3808 1.1 christos htab = loongarch_elf_hash_table (info);
3809 1.1 christos BFD_ASSERT (htab);
3810 1.1 christos dynobj = htab->elf.dynobj;
3811 1.1 christos sdyn = bfd_get_linker_section (dynobj, ".dynamic");
3812 1.1 christos
3813 1.1 christos if (elf_hash_table (info)->dynamic_sections_created)
3814 1.1 christos {
3815 1.1 christos BFD_ASSERT (htab->elf.splt && sdyn);
3816 1.1 christos
3817 1.1 christos if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
3818 1.1 christos return false;
3819 1.1 christos }
3820 1.1 christos
3821 1.1 christos plt = htab->elf.splt;
3822 1.1 christos gotplt = htab->elf.sgotplt;
3823 1.1 christos
3824 1.1 christos if (plt && 0 < plt->size)
3825 1.1 christos {
3826 1.1 christos size_t i;
3827 1.1 christos uint32_t plt_header[PLT_HEADER_INSNS];
3828 1.1 christos if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
3829 1.1 christos plt_header))
3830 1.1 christos return false;
3831 1.1 christos
3832 1.1 christos for (i = 0; i < PLT_HEADER_INSNS; i++)
3833 1.1 christos bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
3834 1.1 christos
3835 1.1 christos elf_section_data (plt->output_section)->this_hdr.sh_entsize =
3836 1.1 christos PLT_ENTRY_SIZE;
3837 1.1 christos }
3838 1.1 christos
3839 1.1 christos if (htab->elf.sgotplt)
3840 1.1 christos {
3841 1.1 christos asection *output_section = htab->elf.sgotplt->output_section;
3842 1.1 christos
3843 1.1 christos if (bfd_is_abs_section (output_section))
3844 1.1 christos {
3845 1.1 christos _bfd_error_handler (_("discarded output section: `%pA'"),
3846 1.1 christos htab->elf.sgotplt);
3847 1.1 christos return false;
3848 1.1 christos }
3849 1.1 christos
3850 1.1 christos if (0 < htab->elf.sgotplt->size)
3851 1.1 christos {
3852 1.1 christos /* Write the first two entries in .got.plt, needed for the dynamic
3853 1.1 christos linker. */
3854 1.1 christos bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
3855 1.1 christos
3856 1.1 christos bfd_put_NN (output_bfd, (bfd_vma) 0,
3857 1.1 christos htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
3858 1.1 christos }
3859 1.1 christos
3860 1.1 christos elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
3861 1.1 christos }
3862 1.1 christos
3863 1.1 christos if (htab->elf.sgot)
3864 1.1 christos {
3865 1.1 christos asection *output_section = htab->elf.sgot->output_section;
3866 1.1 christos
3867 1.1 christos if (0 < htab->elf.sgot->size)
3868 1.1 christos {
3869 1.1 christos /* Set the first entry in the global offset table to the address of
3870 1.1 christos the dynamic section. */
3871 1.1 christos bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
3872 1.1 christos bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
3873 1.1 christos }
3874 1.1 christos
3875 1.1 christos elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
3876 1.1 christos }
3877 1.1 christos
3878 1.1 christos /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
3879 1.1 christos htab_traverse (htab->loc_hash_table,
3880 1.1 christos (void *) elfNN_loongarch_finish_local_dynamic_symbol, info);
3881 1.1 christos
3882 1.1 christos return true;
3883 1.1 christos }
3884 1.1 christos
3885 1.1 christos /* Return address for Ith PLT stub in section PLT, for relocation REL
3886 1.1 christos or (bfd_vma) -1 if it should not be included. */
3887 1.1 christos
3888 1.1 christos static bfd_vma
3889 1.1 christos loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
3890 1.1 christos const arelent *rel ATTRIBUTE_UNUSED)
3891 1.1 christos {
3892 1.1 christos return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
3893 1.1 christos }
3894 1.1 christos
3895 1.1 christos static enum elf_reloc_type_class
3896 1.1 christos loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
3897 1.1 christos const asection *rel_sec ATTRIBUTE_UNUSED,
3898 1.1 christos const Elf_Internal_Rela *rela)
3899 1.1 christos {
3900 1.1 christos struct loongarch_elf_link_hash_table *htab;
3901 1.1 christos htab = loongarch_elf_hash_table (info);
3902 1.1 christos
3903 1.1 christos if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
3904 1.1 christos {
3905 1.1 christos /* Check relocation against STT_GNU_IFUNC symbol if there are
3906 1.1 christos dynamic symbols. */
3907 1.1 christos bfd *abfd = info->output_bfd;
3908 1.1 christos const struct elf_backend_data *bed = get_elf_backend_data (abfd);
3909 1.1 christos unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
3910 1.1 christos if (r_symndx != STN_UNDEF)
3911 1.1 christos {
3912 1.1 christos Elf_Internal_Sym sym;
3913 1.1 christos if (!bed->s->swap_symbol_in (abfd,
3914 1.1 christos htab->elf.dynsym->contents
3915 1.1 christos + r_symndx * bed->s->sizeof_sym,
3916 1.1 christos 0, &sym))
3917 1.1 christos {
3918 1.1 christos /* xgettext:c-format */
3919 1.1 christos _bfd_error_handler (_("%pB symbol number %lu references"
3920 1.1 christos " nonexistent SHT_SYMTAB_SHNDX section"),
3921 1.1 christos abfd, r_symndx);
3922 1.1 christos /* Ideally an error class should be returned here. */
3923 1.1 christos }
3924 1.1 christos else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
3925 1.1 christos return reloc_class_ifunc;
3926 1.1 christos }
3927 1.1 christos }
3928 1.1 christos
3929 1.1 christos switch (ELFNN_R_TYPE (rela->r_info))
3930 1.1 christos {
3931 1.1 christos case R_LARCH_IRELATIVE:
3932 1.1 christos return reloc_class_ifunc;
3933 1.1 christos case R_LARCH_RELATIVE:
3934 1.1 christos return reloc_class_relative;
3935 1.1 christos case R_LARCH_JUMP_SLOT:
3936 1.1 christos return reloc_class_plt;
3937 1.1 christos case R_LARCH_COPY:
3938 1.1 christos return reloc_class_copy;
3939 1.1 christos default:
3940 1.1 christos return reloc_class_normal;
3941 1.1 christos }
3942 1.1 christos }
3943 1.1 christos
3944 1.1 christos /* Copy the extra info we tack onto an elf_link_hash_entry. */
3945 1.1 christos
3946 1.1 christos static void
3947 1.1 christos loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
3948 1.1 christos struct elf_link_hash_entry *dir,
3949 1.1 christos struct elf_link_hash_entry *ind)
3950 1.1 christos {
3951 1.1 christos struct elf_link_hash_entry *edir, *eind;
3952 1.1 christos
3953 1.1 christos edir = dir;
3954 1.1 christos eind = ind;
3955 1.1 christos
3956 1.1 christos if (eind->dyn_relocs != NULL)
3957 1.1 christos {
3958 1.1 christos if (edir->dyn_relocs != NULL)
3959 1.1 christos {
3960 1.1 christos struct elf_dyn_relocs **pp;
3961 1.1 christos struct elf_dyn_relocs *p;
3962 1.1 christos
3963 1.1 christos /* Add reloc counts against the indirect sym to the direct sym
3964 1.1 christos list. Merge any entries against the same section. */
3965 1.1 christos for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
3966 1.1 christos {
3967 1.1 christos struct elf_dyn_relocs *q;
3968 1.1 christos
3969 1.1 christos for (q = edir->dyn_relocs; q != NULL; q = q->next)
3970 1.1 christos if (q->sec == p->sec)
3971 1.1 christos {
3972 1.1 christos q->pc_count += p->pc_count;
3973 1.1 christos q->count += p->count;
3974 1.1 christos *pp = p->next;
3975 1.1 christos break;
3976 1.1 christos }
3977 1.1 christos if (q == NULL)
3978 1.1 christos pp = &p->next;
3979 1.1 christos }
3980 1.1 christos *pp = edir->dyn_relocs;
3981 1.1 christos }
3982 1.1 christos
3983 1.1 christos edir->dyn_relocs = eind->dyn_relocs;
3984 1.1 christos eind->dyn_relocs = NULL;
3985 1.1 christos }
3986 1.1 christos
3987 1.1 christos if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
3988 1.1 christos {
3989 1.1 christos loongarch_elf_hash_entry(edir)->tls_type
3990 1.1 christos = loongarch_elf_hash_entry(eind)->tls_type;
3991 1.1 christos loongarch_elf_hash_entry(eind)->tls_type = GOT_UNKNOWN;
3992 1.1 christos }
3993 1.1 christos _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3994 1.1 christos }
3995 1.1 christos
3996 1.1 christos #define PRSTATUS_SIZE 0x1d8
3997 1.1 christos #define PRSTATUS_OFFSET_PR_CURSIG 0xc
3998 1.1 christos #define PRSTATUS_OFFSET_PR_PID 0x20
3999 1.1 christos #define ELF_GREGSET_T_SIZE 0x168
4000 1.1 christos #define PRSTATUS_OFFSET_PR_REG 0x70
4001 1.1 christos
4002 1.1 christos /* Support for core dump NOTE sections. */
4003 1.1 christos
4004 1.1 christos static bool
4005 1.1 christos loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
4006 1.1 christos {
4007 1.1 christos switch (note->descsz)
4008 1.1 christos {
4009 1.1 christos default:
4010 1.1 christos return false;
4011 1.1 christos
4012 1.1 christos /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
4013 1.1 christos case PRSTATUS_SIZE:
4014 1.1 christos /* pr_cursig */
4015 1.1 christos elf_tdata (abfd)->core->signal =
4016 1.1 christos bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
4017 1.1 christos
4018 1.1 christos /* pr_pid */
4019 1.1 christos elf_tdata (abfd)->core->lwpid =
4020 1.1 christos bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
4021 1.1 christos break;
4022 1.1 christos }
4023 1.1 christos
4024 1.1 christos /* Make a ".reg/999" section. */
4025 1.1 christos return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
4026 1.1 christos note->descpos
4027 1.1 christos + PRSTATUS_OFFSET_PR_REG);
4028 1.1 christos }
4029 1.1 christos
4030 1.1 christos #define PRPSINFO_SIZE 0x88
4031 1.1 christos #define PRPSINFO_OFFSET_PR_PID 0x18
4032 1.1 christos #define PRPSINFO_OFFSET_PR_FNAME 0x28
4033 1.1 christos #define PRPSINFO_SIZEOF_PR_FNAME 0x10
4034 1.1 christos #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
4035 1.1 christos #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
4036 1.1 christos
4037 1.1 christos static bool
4038 1.1 christos loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
4039 1.1 christos {
4040 1.1 christos switch (note->descsz)
4041 1.1 christos {
4042 1.1 christos default:
4043 1.1 christos return false;
4044 1.1 christos
4045 1.1 christos /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
4046 1.1 christos case PRPSINFO_SIZE:
4047 1.1 christos /* pr_pid */
4048 1.1 christos elf_tdata (abfd)->core->pid =
4049 1.1 christos bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
4050 1.1 christos
4051 1.1 christos /* pr_fname */
4052 1.1 christos elf_tdata (abfd)->core->program =
4053 1.1 christos _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
4054 1.1 christos PRPSINFO_SIZEOF_PR_FNAME);
4055 1.1 christos
4056 1.1 christos /* pr_psargs */
4057 1.1 christos elf_tdata (abfd)->core->command =
4058 1.1 christos _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
4059 1.1 christos PRPSINFO_SIZEOF_PR_PS_ARGS);
4060 1.1 christos break;
4061 1.1 christos }
4062 1.1 christos
4063 1.1 christos /* Note that for some reason, a spurious space is tacked
4064 1.1 christos onto the end of the args in some (at least one anyway)
4065 1.1 christos implementations, so strip it off if it exists. */
4066 1.1 christos
4067 1.1 christos {
4068 1.1 christos char *command = elf_tdata (abfd)->core->command;
4069 1.1 christos int n = strlen (command);
4070 1.1 christos
4071 1.1 christos if (0 < n && command[n - 1] == ' ')
4072 1.1 christos command[n - 1] = '\0';
4073 1.1 christos }
4074 1.1 christos
4075 1.1 christos return true;
4076 1.1 christos }
4077 1.1 christos
4078 1.1 christos /* Set the right mach type. */
4079 1.1 christos static bool
4080 1.1 christos loongarch_elf_object_p (bfd *abfd)
4081 1.1 christos {
4082 1.1 christos /* There are only two mach types in LoongArch currently. */
4083 1.1 christos if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
4084 1.1 christos bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
4085 1.1 christos else
4086 1.1 christos bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
4087 1.1 christos return true;
4088 1.1 christos }
4089 1.1 christos
4090 1.1 christos static asection *
4091 1.1 christos loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
4092 1.1 christos Elf_Internal_Rela *rel,
4093 1.1 christos struct elf_link_hash_entry *h,
4094 1.1 christos Elf_Internal_Sym *sym)
4095 1.1 christos {
4096 1.1 christos if (h != NULL)
4097 1.1 christos switch (ELFNN_R_TYPE (rel->r_info))
4098 1.1 christos {
4099 1.1 christos case R_LARCH_GNU_VTINHERIT:
4100 1.1 christos case R_LARCH_GNU_VTENTRY:
4101 1.1 christos return NULL;
4102 1.1 christos }
4103 1.1 christos
4104 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
4105 1.1 christos }
4106 1.1 christos
4107 1.1 christos /* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For
4108 1.1 christos executable PLT slots where the executable never takes the address of those
4109 1.1 christos functions, the function symbols are not added to the hash table. */
4110 1.1 christos
4111 1.1 christos static bool
4112 1.1 christos elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
4113 1.1 christos {
4114 1.1 christos if (h->plt.offset != (bfd_vma) -1
4115 1.1 christos && !h->def_regular
4116 1.1 christos && !h->pointer_equality_needed)
4117 1.1 christos return false;
4118 1.1 christos
4119 1.1 christos return _bfd_elf_hash_symbol (h);
4120 1.1 christos }
4121 1.1 christos
4122 1.1 christos #define TARGET_LITTLE_SYM loongarch_elfNN_vec
4123 1.1 christos #define TARGET_LITTLE_NAME "elfNN-loongarch"
4124 1.1 christos #define ELF_ARCH bfd_arch_loongarch
4125 1.1 christos #define ELF_TARGET_ID LARCH_ELF_DATA
4126 1.1 christos #define ELF_MACHINE_CODE EM_LOONGARCH
4127 1.1 christos #define ELF_MAXPAGESIZE 0x4000
4128 1.1 christos #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
4129 1.1 christos #define bfd_elfNN_bfd_link_hash_table_create \
4130 1.1 christos loongarch_elf_link_hash_table_create
4131 1.1 christos #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
4132 1.1 christos #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
4133 1.1 christos #define elf_info_to_howto loongarch_info_to_howto_rela
4134 1.1 christos #define bfd_elfNN_bfd_merge_private_bfd_data \
4135 1.1 christos elfNN_loongarch_merge_private_bfd_data
4136 1.1 christos
4137 1.1 christos #define elf_backend_reloc_type_class loongarch_reloc_type_class
4138 1.1 christos #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
4139 1.1 christos #define elf_backend_create_dynamic_sections \
4140 1.1 christos loongarch_elf_create_dynamic_sections
4141 1.1 christos #define elf_backend_check_relocs loongarch_elf_check_relocs
4142 1.1 christos #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
4143 1.1 christos #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
4144 1.1 christos #define elf_backend_relocate_section loongarch_elf_relocate_section
4145 1.1 christos #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
4146 1.1 christos #define elf_backend_finish_dynamic_sections \
4147 1.1 christos loongarch_elf_finish_dynamic_sections
4148 1.1 christos #define elf_backend_object_p loongarch_elf_object_p
4149 1.1 christos #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
4150 1.1 christos #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
4151 1.1 christos #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
4152 1.1 christos #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
4153 1.1 christos #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
4154 1.1 christos
4155 1.1 christos #include "elfNN-target.h"
4156