1 /* Machine-dependent ELF dynamic relocation inline functions. MIPS version.
2 Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 /* FIXME: Profiling of shared libraries is not implemented yet. */
25 #define ELF_MACHINE_NAME "MIPS"
27 #define ELF_MACHINE_NO_PLT
32 #error ENTRY_POINT needs to be defined for MIPS.
37 /* The offset of gp from GOT might be system-dependent. It's set by
38 ld. The same value is also */
39 #define OFFSET_GP_GOT 0x7ff0
41 #ifndef _RTLD_PROLOGUE
42 # define _RTLD_PROLOGUE(entry) \
43 ".globl\t" __STRING(entry) "\n\t" \
44 ".ent\t" __STRING(entry) "\n\t" \
45 ".type\t" __STRING(entry) ", @function\n" \
46 __STRING(entry) ":\n\t"
49 #ifndef _RTLD_EPILOGUE
50 # define _RTLD_EPILOGUE(entry) \
51 ".end\t" __STRING(entry) "\n\t" \
52 ".size\t" __STRING(entry) ", . - " __STRING(entry) "\n\t"
55 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.
56 This makes no sense on MIPS but we have to define this to R_MIPS_REL32
57 to avoid the asserts in dl-lookup.c from blowing. */
58 #define ELF_MACHINE_JMP_SLOT R_MIPS_REL32
59 #define elf_machine_type_class(type) ELF_RTYPE_CLASS_PLT
61 /* Translate a processor specific dynamic tag to the index
63 #define DT_MIPS(x) (DT_MIPS_##x - DT_LOPROC + DT_NUM)
65 /* If there is a DT_MIPS_RLD_MAP entry in the dynamic section, fill it in
66 with the run-time address of the r_debug structure */
67 #define ELF_MACHINE_DEBUG_SETUP(l,r) \
68 do { if ((l)->l_info[DT_MIPS (RLD_MAP)]) \
69 *(ElfW(Addr) *)((l)->l_info[DT_MIPS (RLD_MAP)]->d_un.d_ptr) = \
73 /* Return nonzero iff ELF header is compatible with the running host. */
74 static inline int __attribute_used__
75 elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
77 #if _MIPS_SIM == _MIPS_SIM_ABI32 || _MIPS_SIM == _MIPS_SIM_NABI32
78 /* Don't link o32 and n32 together. */
79 if (((ehdr->e_flags & EF_MIPS_ABI2) != 0)
80 != (_MIPS_SIM != _MIPS_SIM_ABI32))
84 switch (ehdr->e_machine)
94 static inline ElfW(Addr) *
95 elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
97 /* FIXME: the offset of gp from GOT may be system-dependent. */
98 return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT);
101 /* Return the link-time address of _DYNAMIC. Conveniently, this is the
102 first element of the GOT. This must be inlined in a function which
103 uses global data. We assume its $gp points to the primary GOT. */
104 static inline ElfW(Addr)
105 elf_machine_dynamic (void)
107 register ElfW(Addr) gp __asm__ ("$28");
108 return *elf_mips_got_from_gpreg (gp);
111 #define STRINGXP(X) __STRING(X)
112 #define STRINGXV(X) STRINGV_(X)
113 #define STRINGV_(...) # __VA_ARGS__
115 /* Return the run-time load address of the shared object. */
116 static inline ElfW(Addr)
117 elf_machine_load_address (void)
120 asm (" .set noreorder\n"
121 " " STRINGXP (PTR_LA) " %0, 0f\n"
124 "0: " STRINGXP (PTR_SUBU) " %0, $31, %0\n"
132 /* The MSB of got[1] of a gnu object is set to identify gnu objects. */
133 #if _MIPS_SIM == _MIPS_SIM_ABI64
134 # define ELF_MIPS_GNU_GOT1_MASK 0x8000000000000000L
136 # define ELF_MIPS_GNU_GOT1_MASK 0x80000000L
139 /* We can't rely on elf_machine_got_rel because _dl_object_relocation_scope
140 fiddles with global data. */
141 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) \
143 struct link_map *map = &bootstrap_map; \
148 got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]); \
150 if (__builtin_expect (map->l_addr == 0, 1)) \
153 /* got[0] is reserved. got[1] is also reserved for the dynamic object \
154 generated by gnu ld. Skip these reserved entries from \
156 i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1; \
157 n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
159 /* Add the run-time displacement to all local got entries. */ \
161 got[i++] += map->l_addr; \
163 /* Handle global got entries. */ \
165 sym = (ElfW(Sym) *) D_PTR(map, l_info[DT_SYMTAB]) \
166 + map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
167 i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val \
168 - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val); \
172 if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_COMMON) \
173 *got = map->l_addr + sym->st_value; \
174 else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC \
175 && *got != sym->st_value) \
176 *got += map->l_addr; \
177 else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION) \
179 if (sym->st_other == 0) \
180 *got += map->l_addr; \
183 *got = map->l_addr + sym->st_value; \
191 /* Get link map for callers object containing STUB_PC. */
192 static inline struct link_map *
193 elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
195 extern int _dl_mips_gnu_objects;
197 /* got[1] is reserved to keep its link map address for the shared
198 object generated by the gnu linker. If all are such objects, we
199 can find the link map from current GPREG simply. If not so, get
200 the link map for caller's object containing STUB_PC. */
202 if (_dl_mips_gnu_objects)
204 ElfW(Addr) *got = elf_mips_got_from_gpreg (gpreg);
207 g1 = ((ElfW(Word) *) got)[1];
209 if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
212 (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
213 ElfW(Addr) base, limit;
214 const ElfW(Phdr) *p = l->l_phdr;
215 ElfW(Half) this, nent = l->l_phnum;
217 /* For the common case of a stub being called from the containing
218 object, STUB_PC will point to somewhere within the object that
219 is described by the link map fetched via got[1]. Otherwise we
220 have to scan all maps. */
221 for (this = 0; this < nent; this++)
223 if (p[this].p_type == PT_LOAD)
225 base = p[this].p_vaddr + l->l_addr;
226 limit = base + p[this].p_memsz;
227 if (stub_pc >= base && stub_pc < limit)
235 struct link_map *l = GL(dl_loaded);
239 ElfW(Addr) base, limit;
240 const ElfW(Phdr) *p = l->l_phdr;
241 ElfW(Half) this, nent = l->l_phnum;
243 for (this = 0; this < nent; ++this)
245 if (p[this].p_type == PT_LOAD)
247 base = p[this].p_vaddr + l->l_addr;
248 limit = base + p[this].p_memsz;
249 if (stub_pc >= base && stub_pc < limit)
257 _dl_signal_error (0, NULL, NULL, "cannot find runtime link map");
261 #if _MIPS_SIM == _MIPS_SIM_ABI32
262 #define ELF_DL_FRAME_SIZE 40
264 #define ELF_DL_SAVE_ARG_REGS "\
272 #define ELF_DL_RESTORE_ARG_REGS "\
280 #define IFABIO32(X) X
282 #else /* _MIPS_SIM == _MIPS_SIM_NABI32 || _MIPS_SIM == _MIPS_SIM_ABI64 */
284 #define ELF_DL_FRAME_SIZE 80
286 #define ELF_DL_SAVE_ARG_REGS "\
298 #define ELF_DL_RESTORE_ARG_REGS "\
314 /* Define mips specific runtime resolver. The function __dl_runtime_resolve
315 is called from assembler function _dl_runtime_resolve which converts
316 special argument registers t7 ($15) and t8 ($24):
317 t7 address to return to the caller of the function
318 t8 index for this function symbol in .dynsym
319 to usual c arguments.
321 Other architectures call fixup from dl-runtime.c in
322 _dl_runtime_resolve. MIPS instead calls __dl_runtime_resolve. We
323 have to use our own version because of the way the got section is
324 treated on MIPS (we've also got ELF_MACHINE_PLT defined). */
326 #define ELF_MACHINE_RUNTIME_TRAMPOLINE \
327 /* The flag _dl_mips_gnu_objects is set if all dynamic objects are \
328 generated by the gnu linker. */ \
329 int _dl_mips_gnu_objects = 1; \
331 /* This is called from assembly stubs below which the compiler can't see. */ \
333 __dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr)) \
334 __attribute_used__; \
337 __dl_runtime_resolve (ElfW(Word) sym_index, \
338 ElfW(Word) return_address, \
339 ElfW(Addr) old_gpreg, \
340 ElfW(Addr) stub_pc) \
342 struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc); \
343 const ElfW(Sym) *const symtab \
344 = (const ElfW(Sym) *) D_PTR (l, l_info[DT_SYMTAB]); \
345 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); \
347 = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]); \
348 const ElfW(Word) local_gotno \
349 = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
350 const ElfW(Word) gotsym \
351 = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
352 const ElfW(Sym) *sym = &symtab[sym_index]; \
355 /* FIXME: The symbol versioning stuff is not tested yet. */ \
356 if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) \
358 switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) \
362 const ElfW(Half) *vernum = \
363 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); \
364 ElfW(Half) ndx = vernum[sym_index] & 0x7fff; \
365 const struct r_found_version *version = &l->l_versions[ndx]; \
367 if (version->hash != 0) \
369 value = _dl_lookup_symbol_x (strtab + sym->st_name, l, \
370 &sym, l->l_scope, version, \
371 ELF_RTYPE_CLASS_PLT, 0, 0); \
374 /* Fall through. */ \
377 value = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, \
378 l->l_scope, 0, ELF_RTYPE_CLASS_PLT, \
379 DL_LOOKUP_ADD_DEPENDENCY, 0); \
382 /* Currently value contains the base load address of the object \
383 that defines sym. Now add in the symbol offset. */ \
384 value = (sym ? value + sym->st_value : 0); \
387 /* We already found the symbol. The module (and therefore its load \
388 address) is also known. */ \
389 value = l->l_addr + sym->st_value; \
391 /* Apply the relocation with that value. */ \
392 *(got + local_gotno + sym_index - gotsym) = value; \
400 .globl _dl_runtime_resolve\n \
401 .type _dl_runtime_resolve,@function\n \
402 .ent _dl_runtime_resolve\n \
403 _dl_runtime_resolve:\n \
404 .frame $29, " STRINGXP(ELF_DL_FRAME_SIZE) ", $31\n \
408 # Save arguments and sp value in stack.\n \
409 " STRINGXP(PTR_SUBIU) " $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n \
410 # Modify t9 ($25) so as to point .cpload instruction.\n \
411 " IFABIO32(STRINGXP(PTR_ADDIU) " $25, 12\n") " \
413 " STRINGXP(SETUP_GP) "\n \
414 " STRINGXV(SETUP_GP64 (0, _dl_runtime_resolve)) "\n \
416 # Save slot call pc.\n \
418 " IFABIO32(STRINGXP(CPRESTORE(32))) "\n \
419 " ELF_DL_SAVE_ARG_REGS " \
424 jal __dl_runtime_resolve\n \
425 " ELF_DL_RESTORE_ARG_REGS " \
426 " STRINGXP(RESTORE_GP64) "\n \
427 " STRINGXP(PTR_ADDIU) " $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n \
430 .end _dl_runtime_resolve\n \
434 /* Mask identifying addresses reserved for the user program,
435 where the dynamic linker should not map anything. */
436 #define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL
439 /* Initial entry point code for the dynamic linker.
440 The C function `_dl_start' is the real entry point;
441 its return value is the user program's entry point.
442 Note how we have to be careful about two things:
444 1) That we allocate a minimal stack of 24 bytes for
445 every function call, the MIPS ABI states that even
446 if all arguments are passed in registers the procedure
447 called can use the 16 byte area pointed to by $sp
448 when it is called to store away the arguments passed
451 2) That under Linux the entry is named __start
452 and not just plain _start. */
454 #define RTLD_START asm (\
456 _RTLD_PROLOGUE(ENTRY_POINT) "\
457 " STRINGXV(SETUP_GPX($25)) "\n\
458 " STRINGXV(SETUP_GPX64($18,$25)) "\n\
459 # i386 ABI book says that the first entry of GOT holds\n\
460 # the address of the dynamic structure. Though MIPS ABI\n\
461 # doesn't say nothing about this, I emulate this here.\n\
462 " STRINGXP(PTR_LA) " $4, _DYNAMIC\n\
463 # Subtract OFFSET_GP_GOT\n\
464 " STRINGXP(PTR_S) " $4, -0x7ff0($28)\n\
466 " STRINGXP(PTR_SUBIU) " $29, 16\n\
468 " STRINGXP(PTR_LA) " $8, .Lcoff\n\
470 .Lcoff: " STRINGXP(PTR_SUBU) " $8, $31, $8\n\
472 " STRINGXP(PTR_LA) " $25, _dl_start\n\
473 " STRINGXP(PTR_ADDU) " $25, $8\n\
476 " STRINGXP(PTR_ADDIU) " $29, 16\n\
477 # Get the value of label '_dl_start_user' in t9 ($25).\n\
478 " STRINGXP(PTR_LA) " $25, _dl_start_user\n\
479 .globl _dl_start_user\n\
480 .type _dl_start_user,@function\n\
481 .aent _dl_start_user\n\
483 " STRINGXP(SETUP_GP) "\n\
484 " STRINGXV(SETUP_GP64($18,_dl_start_user)) "\n\
486 # Save the user entry point address in a saved register.\n\
488 # Store the highest stack address\n\
489 " STRINGXP(PTR_S) " $29, __libc_stack_end\n\
490 # See if we were run as a command with the executable file\n\
491 # name as an extra leading argument.\n\
492 lw $2, _dl_skip_args\n\
494 # Load the original argument count.\n\
495 " STRINGXP(PTR_L) " $4, 0($29)\n\
496 # Subtract _dl_skip_args from it.\n\
498 # Adjust the stack pointer to skip _dl_skip_args words.\n\
499 sll $2, " STRINGXP (PTRLOG) "\n\
500 " STRINGXP(PTR_ADDU) " $29, $2\n\
501 # Save back the modified argument count.\n\
502 " STRINGXP(PTR_S) " $4, 0($29)\n\
503 1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
504 " STRINGXP(PTR_L) " $4, _rtld_local\n\
505 " STRINGXP(PTR_L) /* or lw??? fixme */ " $5, 0($29)\n\
506 " STRINGXP(PTR_LA) " $6, " STRINGXP (PTRSIZE) "($29)\n\
507 sll $7, $5, " STRINGXP (PTRLOG) "\n\
508 " STRINGXP(PTR_ADDU) " $7, $7, $6\n\
509 " STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
510 " STRINGXP(PTR_SUBIU) " $29, 32\n\
511 " STRINGXP(SAVE_GP(16)) "\n\
512 # Call the function to run the initializers.\n\
513 jal _dl_init_internal\n\
514 " STRINGXP(PTR_ADDIU) " $29, 32\n\
515 # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
516 " STRINGXP(PTR_LA) " $2, _dl_fini\n\
517 # Jump to the user entry point.\n\
520 _RTLD_EPILOGUE(ENTRY_POINT)\
524 /* The MIPS never uses Elfxx_Rela relocations. */
525 #define ELF_MACHINE_NO_RELA 1
527 #endif /* !dl_machine_h */
531 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
532 MAP is the object containing the reloc. */
535 #ifdef RTLD_BOOTSTRAP
536 __attribute__ ((always_inline))
538 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
539 const ElfW(Sym) *sym, const struct r_found_version *version,
540 void *const reloc_addr)
542 const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
544 #if !defined RTLD_BOOTSTRAP && !defined SHARED
545 /* This is defined in rtld.c, but nowhere in the static libc.a;
546 make the reference weak so static programs can still link. This
547 declaration cannot be done when compiling rtld.c (i.e. #ifdef
548 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
549 _dl_rtld_map, which is incompatible with a weak decl in the same
551 weak_extern (GL(dl_rtld_map));
556 #if _MIPS_SIM == _MIPS_SIM_ABI64
557 case (R_MIPS_64 << 8) | R_MIPS_REL32:
562 int symidx = ELFW(R_SYM) (reloc->r_info);
563 ElfW(Addr) reloc_value;
565 /* Support relocations on mis-aligned offsets. Should we ever
566 implement RELA, this should be replaced with an assignment
567 from reloc->r_addend. */
568 __builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
572 const ElfW(Word) gotsym
573 = (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
575 if ((ElfW(Word))symidx < gotsym)
577 /* This wouldn't work for a symbol imported from other
578 libraries for which there's no GOT entry, but MIPS
579 requires every symbol referenced in a dynamic
580 relocation to have a GOT entry in the primary GOT,
581 so we only get here for locally-defined symbols.
582 For section symbols, we should *NOT* be adding
583 sym->st_value (per the definition of the meaning of
584 S in reloc expressions in the ELF64 MIPS ABI),
585 since it should have already been added to
586 reloc_value by the linker, but older versions of
587 GNU ld didn't add it, and newer versions don't emit
588 useless relocations to section symbols any more, so
589 it is safe to keep on adding sym->st_value, even
590 though it's not ABI compliant. Some day we should
591 bite the bullet and stop doing this. */
592 #ifndef RTLD_BOOTSTRAP
593 if (map != &GL(dl_rtld_map))
595 reloc_value += sym->st_value + map->l_addr;
599 #ifndef RTLD_BOOTSTRAP
600 const ElfW(Addr) *got
601 = (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
602 const ElfW(Word) local_gotno
604 map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
606 reloc_value += got[symidx + local_gotno - gotsym];
611 #ifndef RTLD_BOOTSTRAP
612 if (map != &GL(dl_rtld_map))
614 reloc_value += map->l_addr;
616 __builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
619 case R_MIPS_NONE: /* Alright, Wilbur. */
621 #if _MIPS_SIM == _MIPS_SIM_ABI64
623 /* For full compliance with the ELF64 ABI, one must precede the
624 _REL32/_64 pair of relocations with a _64 relocation, such
625 that the in-place addend is read as a 64-bit value. IRIX
626 didn't pick up on this requirement, so we treat the
627 _REL32/_64 relocation as a 64-bit relocation even if it's by
628 itself. For ABI compliance, we ignore such _64 dummy
629 relocations. For RELA, this may be simply removed, since
630 it's totally unnecessary. */
631 if (ELFW(R_SYM) (reloc->r_info) == 0)
636 _dl_reloc_bad_type (map, r_type, 0);
642 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
643 void *const reloc_addr)
645 /* XXX Nothing to do. There is no relative relocation, right? */
649 elf_machine_lazy_rel (struct link_map *map,
650 ElfW(Addr) l_addr, const ElfW(Rel) *reloc)
655 #ifndef RTLD_BOOTSTRAP
658 elf_machine_got_rel (struct link_map *map, int lazy)
662 const ElfW(Half) *vernum;
665 #define RESOLVE_GOTSYM(sym,vernum,sym_index) \
667 const ElfW(Sym) *ref = sym; \
668 const struct r_found_version *version \
669 = vernum ? &map->l_versions[vernum[sym_index] & 0x7fff] : NULL; \
671 value = RESOLVE (&ref, version, R_MIPS_REL32); \
672 (ref)? value + ref->st_value: 0; \
675 if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
676 vernum = (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
680 got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
682 n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
683 /* The dynamic linker's local got entries have already been relocated. */
684 if (map != &GL(dl_rtld_map))
686 /* got[0] is reserved. got[1] is also reserved for the dynamic object
687 generated by gnu ld. Skip these reserved entries from relocation. */
688 i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1;
690 /* Add the run-time displacement to all local got entries if
692 if (__builtin_expect (map->l_addr != 0, 0))
695 got[i++] += map->l_addr;
699 /* Handle global got entries. */
701 /* Keep track of the symbol index. */
702 symidx = map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
703 sym = (ElfW(Sym) *) D_PTR (map, l_info[DT_SYMTAB]) + symidx;
704 i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val
705 - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val);
707 /* This loop doesn't handle Quickstart. */
710 if (sym->st_shndx == SHN_UNDEF)
712 if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
713 && sym->st_value && lazy)
714 *got = sym->st_value + map->l_addr;
716 *got = RESOLVE_GOTSYM (sym, vernum, symidx);
718 else if (sym->st_shndx == SHN_COMMON)
719 *got = RESOLVE_GOTSYM (sym, vernum, symidx);
720 else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
721 && *got != sym->st_value
724 else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION)
726 if (sym->st_other == 0)
730 *got = RESOLVE_GOTSYM (sym, vernum, symidx);
737 #undef RESOLVE_GOTSYM
741 /* Set up the loaded object described by L so its stub function
742 will jump to the on-demand fixup code __dl_runtime_resolve. */
745 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
747 # ifndef RTLD_BOOTSTRAP
749 extern void _dl_runtime_resolve (ElfW(Word));
750 extern int _dl_mips_gnu_objects;
754 /* The GOT entries for functions have not yet been filled in.
755 Their initial contents will arrange when called to put an
756 offset into the .dynsym section in t8, the return address
757 in t7 and then jump to _GLOBAL_OFFSET_TABLE[0]. */
758 got = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
760 /* This function will get called to fix up the GOT entry indicated by
761 the register t8, and then jump to the resolved address. */
762 got[0] = (ElfW(Addr)) &_dl_runtime_resolve;
764 /* Store l to _GLOBAL_OFFSET_TABLE[1] for gnu object. The MSB
765 of got[1] of a gnu object is set to identify gnu objects.
766 Where we can store l for non gnu objects? XXX */
767 if ((got[1] & ELF_MIPS_GNU_GOT1_MASK) != 0)
768 got[1] = ((ElfW(Addr)) l | ELF_MIPS_GNU_GOT1_MASK);
770 _dl_mips_gnu_objects = 0;
773 /* Relocate global offset table. */
774 elf_machine_got_rel (l, lazy);