1 /* Machine-dependent ELF dynamic relocation inline functions. MIPS version.
2 Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 /* FIXME: Profiling of shared libraries is not implemented yet. */
26 #define ELF_MACHINE_NAME "MIPS"
31 #error ENTRY_POINT needs to be defined for MIPS.
38 /* The offset of gp from GOT might be system-dependent. It's set by
39 ld. The same value is also */
40 #define OFFSET_GP_GOT 0x7ff0
42 #ifndef _RTLD_PROLOGUE
43 # define _RTLD_PROLOGUE(entry) \
44 ".globl\t" __STRING(entry) "\n\t" \
45 ".ent\t" __STRING(entry) "\n\t" \
46 ".type\t" __STRING(entry) ", @function\n" \
47 __STRING(entry) ":\n\t"
50 #ifndef _RTLD_EPILOGUE
51 # define _RTLD_EPILOGUE(entry) \
52 ".end\t" __STRING(entry) "\n\t" \
53 ".size\t" __STRING(entry) ", . - " __STRING(entry) "\n\t"
56 /* Until elf/elf.h in glibc is updated. */
58 #define STO_MIPS_PLT 0x8
59 #define R_MIPS_COPY 126
60 #define R_MIPS_JUMP_SLOT 127
61 #define DT_MIPS_PLTGOT 0x70000032
64 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.
65 This only makes sense on MIPS when using PLTs, so choose the
66 PLT relocation (not encountered when not using PLTs). */
67 #define ELF_MACHINE_JMP_SLOT R_MIPS_JUMP_SLOT
68 #define elf_machine_type_class(type) \
69 ((((type) == ELF_MACHINE_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
70 | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
72 #define ELF_MACHINE_PLT_REL 1
74 /* Translate a processor specific dynamic tag to the index
76 #define DT_MIPS(x) (DT_MIPS_##x - DT_LOPROC + DT_NUM)
78 /* If there is a DT_MIPS_RLD_MAP entry in the dynamic section, fill it in
79 with the run-time address of the r_debug structure */
80 #define ELF_MACHINE_DEBUG_SETUP(l,r) \
81 do { if ((l)->l_info[DT_MIPS (RLD_MAP)]) \
82 *(ElfW(Addr) *)((l)->l_info[DT_MIPS (RLD_MAP)]->d_un.d_ptr) = \
86 /* Allow ABIVERSION == 1, meaning PLTs and copy relocations are
88 #define VALID_ELF_ABIVERSION(ver) (ver == 0 || ver == 2)
89 #define VALID_ELF_OSABI(osabi) (osabi == ELFOSABI_SYSV)
90 #define VALID_ELF_HEADER(hdr,exp,size) \
91 memcmp (hdr,exp,size-2) == 0 \
92 && VALID_ELF_OSABI (hdr[EI_OSABI]) \
93 && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION])
95 /* Return nonzero iff ELF header is compatible with the running host. */
96 static inline int __attribute_used__
97 elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
99 #if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32
100 /* Don't link o32 and n32 together. */
101 if (((ehdr->e_flags & EF_MIPS_ABI2) != 0) != (_MIPS_SIM == _ABIN32))
105 switch (ehdr->e_machine)
115 static inline ElfW(Addr) *
116 elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
118 /* FIXME: the offset of gp from GOT may be system-dependent. */
119 return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT);
122 /* Return the link-time address of _DYNAMIC. Conveniently, this is the
123 first element of the GOT. This must be inlined in a function which
124 uses global data. We assume its $gp points to the primary GOT. */
125 static inline ElfW(Addr)
126 elf_machine_dynamic (void)
128 register ElfW(Addr) gp __asm__ ("$28");
129 return *elf_mips_got_from_gpreg (gp);
132 #define STRINGXP(X) __STRING(X)
133 #define STRINGXV(X) STRINGV_(X)
134 #define STRINGV_(...) # __VA_ARGS__
136 /* Return the run-time load address of the shared object. */
137 static inline ElfW(Addr)
138 elf_machine_load_address (void)
141 asm (" .set noreorder\n"
142 " " STRINGXP (PTR_LA) " %0, 0f\n"
145 "0: " STRINGXP (PTR_SUBU) " %0, $31, %0\n"
153 /* The MSB of got[1] of a gnu object is set to identify gnu objects. */
154 #if _MIPS_SIM == _ABI64
155 # define ELF_MIPS_GNU_GOT1_MASK 0x8000000000000000L
157 # define ELF_MIPS_GNU_GOT1_MASK 0x80000000L
160 /* We can't rely on elf_machine_got_rel because _dl_object_relocation_scope
161 fiddles with global data. */
162 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) \
164 struct link_map *map = &bootstrap_map; \
169 got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]); \
171 if (__builtin_expect (map->l_addr == 0, 1)) \
174 /* got[0] is reserved. got[1] is also reserved for the dynamic object \
175 generated by gnu ld. Skip these reserved entries from \
177 i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1; \
178 n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
180 /* Add the run-time displacement to all local got entries. */ \
182 got[i++] += map->l_addr; \
184 /* Handle global got entries. */ \
186 sym = (ElfW(Sym) *) D_PTR(map, l_info[DT_SYMTAB]) \
187 + map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
188 i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val \
189 - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val); \
193 if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_COMMON) \
194 *got = map->l_addr + sym->st_value; \
195 else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC \
196 && *got != sym->st_value) \
197 *got += map->l_addr; \
198 else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION) \
200 if (sym->st_other == 0) \
201 *got += map->l_addr; \
204 *got = map->l_addr + sym->st_value; \
212 /* Mask identifying addresses reserved for the user program,
213 where the dynamic linker should not map anything. */
214 #define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL
217 /* Initial entry point code for the dynamic linker.
218 The C function `_dl_start' is the real entry point;
219 its return value is the user program's entry point.
220 Note how we have to be careful about two things:
222 1) That we allocate a minimal stack of 24 bytes for
223 every function call, the MIPS ABI states that even
224 if all arguments are passed in registers the procedure
225 called can use the 16 byte area pointed to by $sp
226 when it is called to store away the arguments passed
229 2) That under Linux the entry is named __start
230 and not just plain _start. */
232 #define RTLD_START asm (\
234 " _RTLD_PROLOGUE(ENTRY_POINT) "\
235 " STRINGXV(SETUP_GPX($25)) "\n\
236 " STRINGXV(SETUP_GPX64($18,$25)) "\n\
237 # i386 ABI book says that the first entry of GOT holds\n\
238 # the address of the dynamic structure. Though MIPS ABI\n\
239 # doesn't say nothing about this, I emulate this here.\n\
240 " STRINGXP(PTR_LA) " $4, _DYNAMIC\n\
241 # Subtract OFFSET_GP_GOT\n\
242 " STRINGXP(PTR_S) " $4, -0x7ff0($28)\n\
244 " STRINGXP(PTR_SUBIU) " $29, 16\n\
246 " STRINGXP(PTR_LA) " $8, .Lcoff\n\
248 .Lcoff: " STRINGXP(PTR_SUBU) " $8, $31, $8\n\
250 " STRINGXP(PTR_LA) " $25, _dl_start\n\
251 " STRINGXP(PTR_ADDU) " $25, $8\n\
254 " STRINGXP(PTR_ADDIU) " $29, 16\n\
255 # Get the value of label '_dl_start_user' in t9 ($25).\n\
256 " STRINGXP(PTR_LA) " $25, _dl_start_user\n\
257 " _RTLD_EPILOGUE(ENTRY_POINT) "\
260 " _RTLD_PROLOGUE(_dl_start_user) "\
261 " STRINGXP(SETUP_GP) "\n\
262 " STRINGXV(SETUP_GP64($18,_dl_start_user)) "\n\
264 # Save the user entry point address in a saved register.\n\
266 # See if we were run as a command with the executable file\n\
267 # name as an extra leading argument.\n\
268 lw $2, _dl_skip_args\n\
270 # Load the original argument count.\n\
271 " STRINGXP(PTR_L) " $4, 0($29)\n\
272 # Subtract _dl_skip_args from it.\n\
274 # Adjust the stack pointer to skip _dl_skip_args words.\n\
275 sll $2, " STRINGXP (PTRLOG) "\n\
276 " STRINGXP(PTR_ADDU) " $29, $2\n\
277 # Save back the modified argument count.\n\
278 " STRINGXP(PTR_S) " $4, 0($29)\n\
279 1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
280 " STRINGXP(PTR_L) " $4, _rtld_local\n\
281 " STRINGXP(PTR_L) /* or lw??? fixme */ " $5, 0($29)\n\
282 " STRINGXP(PTR_LA) " $6, " STRINGXP (PTRSIZE) "($29)\n\
283 sll $7, $5, " STRINGXP (PTRLOG) "\n\
284 " STRINGXP(PTR_ADDU) " $7, $7, $6\n\
285 " STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
286 # Make sure the stack pointer is aligned for _dl_init_internal.\n\
287 and $2, $29, -2 * " STRINGXP(SZREG) "\n\
288 " STRINGXP(PTR_S) " $29, -" STRINGXP(SZREG) "($2)\n\
289 " STRINGXP(PTR_SUBIU) " $29, $2, 32\n\
290 " STRINGXP(SAVE_GP(16)) "\n\
291 # Call the function to run the initializers.\n\
292 jal _dl_init_internal\n\
293 # Restore the stack pointer for _start.\n\
294 " STRINGXP(PTR_L) " $29, 32-" STRINGXP(SZREG) "($29)\n\
295 # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
296 " STRINGXP(PTR_LA) " $2, _dl_fini\n\
297 # Jump to the user entry point.\n\
300 _RTLD_EPILOGUE(_dl_start_user)\
304 /* Names of the architecture-specific auditing callback functions. */
305 # if _MIPS_SIM == _ABIO32
306 # define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
307 # define ARCH_LA_PLTEXIT mips_o32_gnu_pltexit
308 # elif _MIPS_SIM == _ABIN32
309 # define ARCH_LA_PLTENTER mips_n32_gnu_pltenter
310 # define ARCH_LA_PLTEXIT mips_n32_gnu_pltexit
312 # define ARCH_LA_PLTENTER mips_n64_gnu_pltenter
313 # define ARCH_LA_PLTEXIT mips_n64_gnu_pltexit
316 /* For a non-writable PLT, rewrite the .got.plt entry at RELOC_ADDR to
317 point at the symbol with address VALUE. For a writable PLT, rewrite
318 the corresponding PLT entry instead. */
319 static inline ElfW(Addr)
320 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
321 const ElfW(Rel) *reloc,
322 ElfW(Addr) *reloc_addr, ElfW(Addr) value)
324 return *reloc_addr = value;
327 static inline ElfW(Addr)
328 elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
334 #endif /* !dl_machine_h */
338 /* Perform a relocation described by R_INFO at the location pointed to
339 by RELOC_ADDR. SYM is the relocation symbol specified by R_INFO and
340 MAP is the object containing the reloc. */
343 __attribute__ ((always_inline))
344 elf_machine_reloc (struct link_map *map, ElfW(Addr) r_info,
345 const ElfW(Sym) *sym, const struct r_found_version *version,
346 void *reloc_addr, ElfW(Addr) r_addend, int inplace_p)
348 const unsigned long int r_type = ELFW(R_TYPE) (r_info);
349 ElfW(Addr) *addr_field = (ElfW(Addr) *) reloc_addr;
351 #if !defined RTLD_BOOTSTRAP && !defined SHARED
352 /* This is defined in rtld.c, but nowhere in the static libc.a;
353 make the reference weak so static programs can still link. This
354 declaration cannot be done when compiling rtld.c (i.e. #ifdef
355 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
356 _dl_rtld_map, which is incompatible with a weak decl in the same
358 weak_extern (GL(dl_rtld_map));
363 #if defined (USE_TLS) && !defined (RTLD_BOOTSTRAP)
364 # if _MIPS_SIM == _ABI64
365 case R_MIPS_TLS_DTPMOD64:
366 case R_MIPS_TLS_DTPREL64:
367 case R_MIPS_TLS_TPREL64:
369 case R_MIPS_TLS_DTPMOD32:
370 case R_MIPS_TLS_DTPREL32:
371 case R_MIPS_TLS_TPREL32:
374 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
378 case R_MIPS_TLS_DTPMOD64:
379 case R_MIPS_TLS_DTPMOD32:
381 *addr_field = sym_map->l_tls_modid;
384 case R_MIPS_TLS_DTPREL64:
385 case R_MIPS_TLS_DTPREL32:
389 r_addend = *addr_field;
390 *addr_field = r_addend + TLS_DTPREL_VALUE (sym);
394 case R_MIPS_TLS_TPREL32:
395 case R_MIPS_TLS_TPREL64:
398 CHECK_STATIC_TLS (map, sym_map);
400 r_addend = *addr_field;
401 *addr_field = r_addend + TLS_TPREL_VALUE (sym_map, sym);
410 #if _MIPS_SIM == _ABI64
411 case (R_MIPS_64 << 8) | R_MIPS_REL32:
416 int symidx = ELFW(R_SYM) (r_info);
417 ElfW(Addr) reloc_value;
420 /* Support relocations on mis-aligned offsets. */
421 __builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
423 reloc_value = r_addend;
427 const ElfW(Word) gotsym
428 = (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
430 if ((ElfW(Word))symidx < gotsym)
432 /* This wouldn't work for a symbol imported from other
433 libraries for which there's no GOT entry, but MIPS
434 requires every symbol referenced in a dynamic
435 relocation to have a GOT entry in the primary GOT,
436 so we only get here for locally-defined symbols.
437 For section symbols, we should *NOT* be adding
438 sym->st_value (per the definition of the meaning of
439 S in reloc expressions in the ELF64 MIPS ABI),
440 since it should have already been added to
441 reloc_value by the linker, but older versions of
442 GNU ld didn't add it, and newer versions don't emit
443 useless relocations to section symbols any more, so
444 it is safe to keep on adding sym->st_value, even
445 though it's not ABI compliant. Some day we should
446 bite the bullet and stop doing this. */
447 #ifndef RTLD_BOOTSTRAP
448 if (map != &GL(dl_rtld_map))
450 reloc_value += sym->st_value + map->l_addr;
454 #ifndef RTLD_BOOTSTRAP
455 const ElfW(Addr) *got
456 = (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
457 const ElfW(Word) local_gotno
459 map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
461 reloc_value += got[symidx + local_gotno - gotsym];
466 #ifndef RTLD_BOOTSTRAP
467 if (map != &GL(dl_rtld_map))
469 reloc_value += map->l_addr;
471 __builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
474 #ifndef RTLD_BOOTSTRAP
475 #if _MIPS_SIM == _ABI64
476 case (R_MIPS_64 << 8) | R_MIPS_GLOB_DAT:
478 case R_MIPS_GLOB_DAT:
481 int symidx = ELFW(R_SYM) (r_info);
482 const ElfW(Word) gotsym
483 = (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
485 if (__builtin_expect ((ElfW(Word)) symidx >= gotsym, 1))
487 const ElfW(Addr) *got
488 = (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
489 const ElfW(Word) local_gotno
490 = ((const ElfW(Word))
491 map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val);
493 ElfW(Addr) reloc_value = got[symidx + local_gotno - gotsym];
494 __builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
499 case R_MIPS_NONE: /* Alright, Wilbur. */
502 case R_MIPS_JUMP_SLOT:
504 struct link_map *sym_map;
507 /* The addend for a jump slot relocation must always be zero:
508 calls via the PLT always branch to the symbol's address and
509 not to the address plus a non-zero offset. */
511 _dl_signal_error (0, map->l_name, NULL,
512 "found jump slot relocation with non-zero addend");
514 sym_map = RESOLVE_MAP (&sym, version, r_type);
515 value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
523 const ElfW(Sym) *const refsym = sym;
524 struct link_map *sym_map;
527 /* Calculate the address of the symbol. */
528 sym_map = RESOLVE_MAP (&sym, version, r_type);
529 value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
531 if (__builtin_expect (sym == NULL, 0))
532 /* This can happen in trace mode if an object could not be
535 if (__builtin_expect (sym->st_size > refsym->st_size, 0)
536 || (__builtin_expect (sym->st_size < refsym->st_size, 0)
537 && GLRO(dl_verbose)))
541 strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
543 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
544 rtld_progname ?: "<program name unknown>",
545 strtab + refsym->st_name);
547 memcpy (reloc_addr, (void *) value,
548 MIN (sym->st_size, refsym->st_size));
552 #if _MIPS_SIM == _ABI64
554 /* For full compliance with the ELF64 ABI, one must precede the
555 _REL32/_64 pair of relocations with a _64 relocation, such
556 that the in-place addend is read as a 64-bit value. IRIX
557 didn't pick up on this requirement, so we treat the
558 _REL32/_64 relocation as a 64-bit relocation even if it's by
559 itself. For ABI compliance, we ignore such _64 dummy
560 relocations. For RELA, this may be simply removed, since
561 it's totally unnecessary. */
562 if (ELFW(R_SYM) (r_info) == 0)
567 _dl_reloc_bad_type (map, r_type, 0);
572 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
573 MAP is the object containing the reloc. */
576 __attribute__ ((always_inline))
577 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
578 const ElfW(Sym) *sym, const struct r_found_version *version,
579 void *const reloc_addr)
581 elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr, 0, 1);
585 __attribute__((always_inline))
586 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
587 void *const reloc_addr)
589 /* XXX Nothing to do. There is no relative relocation, right? */
593 __attribute__((always_inline))
594 elf_machine_lazy_rel (struct link_map *map,
595 ElfW(Addr) l_addr, const ElfW(Rel) *reloc)
597 ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
598 const unsigned int r_type = ELFW(R_TYPE) (reloc->r_info);
599 /* Check for unexpected PLT reloc type. */
600 if (__builtin_expect (r_type == R_MIPS_JUMP_SLOT, 1))
602 if (__builtin_expect (map->l_mach.plt, 0) == 0)
604 /* Nothing is required here since we only support lazy
605 relocation in executables. */
608 *reloc_addr = map->l_mach.plt;
611 _dl_reloc_bad_type (map, r_type, 1);
615 __attribute__ ((always_inline))
616 elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
617 const ElfW(Sym) *sym, const struct r_found_version *version,
618 void *const reloc_addr)
620 elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr,
625 __attribute__((always_inline))
626 elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
627 void *const reloc_addr)
631 #ifndef RTLD_BOOTSTRAP
634 __attribute__((always_inline))
635 elf_machine_got_rel (struct link_map *map, int lazy)
639 const ElfW(Half) *vernum;
642 #define RESOLVE_GOTSYM(sym,vernum,sym_index,reloc) \
644 const ElfW(Sym) *ref = sym; \
645 const struct r_found_version *version \
646 = vernum ? &map->l_versions[vernum[sym_index] & 0x7fff] : NULL; \
647 struct link_map *sym_map; \
648 sym_map = RESOLVE_MAP (&ref, version, reloc); \
649 ref ? sym_map->l_addr + ref->st_value : 0; \
652 if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
653 vernum = (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
657 got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
659 n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
660 /* The dynamic linker's local got entries have already been relocated. */
661 if (map != &GL(dl_rtld_map))
663 /* got[0] is reserved. got[1] is also reserved for the dynamic object
664 generated by gnu ld. Skip these reserved entries from relocation. */
665 i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1;
667 /* Add the run-time displacement to all local got entries if
669 if (__builtin_expect (map->l_addr != 0, 0))
672 got[i++] += map->l_addr;
676 /* Handle global got entries. */
678 /* Keep track of the symbol index. */
679 symidx = map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
680 sym = (ElfW(Sym) *) D_PTR (map, l_info[DT_SYMTAB]) + symidx;
681 i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val
682 - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val);
684 /* This loop doesn't handle Quickstart. */
687 if (sym->st_shndx == SHN_UNDEF)
689 if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC && sym->st_value
690 && !(sym->st_other & STO_MIPS_PLT))
693 *got = sym->st_value + map->l_addr;
695 /* This is a lazy-binding stub, so we don't need the
696 canonical address. */
697 *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_JUMP_SLOT);
700 *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_32);
702 else if (sym->st_shndx == SHN_COMMON)
703 *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_32);
704 else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
705 && *got != sym->st_value)
710 /* This is a lazy-binding stub, so we don't need the
711 canonical address. */
712 *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_JUMP_SLOT);
714 else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION)
716 if (sym->st_other == 0)
720 *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_32);
727 #undef RESOLVE_GOTSYM
731 /* Set up the loaded object described by L so its stub function
732 will jump to the on-demand fixup code __dl_runtime_resolve. */
735 __attribute__((always_inline))
736 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
738 # ifndef RTLD_BOOTSTRAP
740 extern void _dl_runtime_resolve (ElfW(Word));
741 extern void _dl_runtime_pltresolve (void);
742 extern int _dl_mips_gnu_objects;
746 /* The GOT entries for functions have not yet been filled in.
747 Their initial contents will arrange when called to put an
748 offset into the .dynsym section in t8, the return address
749 in t7 and then jump to _GLOBAL_OFFSET_TABLE[0]. */
750 got = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
752 /* This function will get called to fix up the GOT entry indicated by
753 the register t8, and then jump to the resolved address. */
754 got[0] = (ElfW(Addr)) &_dl_runtime_resolve;
756 /* Store l to _GLOBAL_OFFSET_TABLE[1] for gnu object. The MSB
757 of got[1] of a gnu object is set to identify gnu objects.
758 Where we can store l for non gnu objects? XXX */
759 if ((got[1] & ELF_MIPS_GNU_GOT1_MASK) != 0)
760 got[1] = ((ElfW(Addr)) l | ELF_MIPS_GNU_GOT1_MASK);
762 _dl_mips_gnu_objects = 0;
765 /* Relocate global offset table. */
766 elf_machine_got_rel (l, lazy);
768 /* If using PLTs, fill in the first two entries of .got.plt. */
769 if (l->l_info[DT_JMPREL] && lazy)
772 gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_MIPS (PLTGOT)]);
773 /* If a library is prelinked but we have to relocate anyway,
774 we have to be able to undo the prelinking of .got.plt.
775 The prelinker saved the address of .plt for us here. */
777 l->l_mach.plt = gotplt[1] + l->l_addr;
778 gotplt[0] = (ElfW(Addr)) &_dl_runtime_pltresolve;
779 gotplt[1] = (ElfW(Addr)) l;
786 #endif /* RESOLVE_MAP */