1 /* Copyright (C) 2006 CodeSourcery
2 Written by Richard Sandiford <richard@codesourcery.com>, 2006
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 The psABI defines R_MIPS_REL32 as A - EA + S, where the value of EA
21 depends on the symbol index. If the index is less than DT_MIPS_GOTSYM,
22 EA is the symbol's st_value "plus displacement". If the index is greater
23 than or equal to DT_MIPS_GOTSYM, EA is the original value of the
26 However, glibc's dynamic linker implements a different definition.
27 If the index is less than DT_MIPS_GOTSYM, the dynamic linker adds the
28 symbol's st_value and the base address to the addend. If the index
29 is greater than or equal to DT_MIPS_GOTSYM, the dynamic linker adds
30 the final symbol value to the addend.
32 MIPS GOTs are divided into three parts:
34 - Reserved entries (of which GNU objects have 2)
38 DT_MIPS_LOCAL_GOTNO gives the total number of reserved and local
39 entries. The local entries all hold virtual addresses and the
40 dynamic linker will add the base address to each one.
42 Unlike most other architectures, the MIPS ABI does not use
43 relocations to initialize the global GOT entries. Instead, global
44 GOT entry X is mapped to dynamic symbol DT_MIPS_GOTSYM + X, and there
45 are a total of DT_MIPS_SYMTABNO - DT_MIPS_GOTSYM global GOT entries.
47 The interpretation of a global GOT entry depends on the symbol entry
48 and the initial GOT contents. The psABI lists the following cases:
50 st_shndx st_type st_value initial GOT value
51 -------- ------- -------- -----------------
52 A: SHN_UNDEF STT_FUNC 0 st_value (== 0) / QS
53 B: SHN_UNDEF STT_FUNC stub address st_value / QS
54 C: SHN_UNDEF all others 0 st_value (== 0) / QS
55 D: SHN_COMMON any alignment 0 / QS
56 E: all others STT_FUNC value st_value / stub address
57 F: all others all others value st_value
59 (wording slightly modified from the psABI table). Here, QS denotes
62 The dynamic linker treats each case as follows:
64 - [A, B when not binding lazily, C, D, E when not binding lazily, F]
65 Resolve the symbol and store its value in the GOT.
67 - [B when binding lazily] Set the GOT entry to the st_value plus
70 - [E when binding lazily] If the GOT entry is different from the st_value,
71 add the base addreess to the GOT entry. Otherwise resolve the symbol
72 and store its value in the GOT (as for A, C, etc).
74 As the table shows, we can install Quickstart values for types A-D.
75 Installing Quickstart values for type F should be a no-op, because the
76 GOT should already hold the desired value. Installing Quickstart values
77 for type E would either be a no-op (if the GOT entry already contains
78 st_value) or would lose the address of the lazy binding stub. */
94 /* The thread pointer points 0x7000 past the first static TLS block. */
95 #define TLS_TP_OFFSET 0x7000
97 /* Dynamic thread vector pointers point 0x8000 past the start of each
99 #define TLS_DTV_OFFSET 0x8000
101 /* The number of reserved entries at the beginning of the GOT.
102 The dynamic linker points entry 0 to the resolver function
103 and entry 1 to the link_map. */
104 #define RESERVED_GOTNO 2
106 /* A structure for iterating over local GOT entries. */
107 struct mips_local_got_iterator {
108 /* The DSO containing the GOT. */
111 /* The size of a GOT entry. */
112 GElf_Word entry_size;
114 /* The index of the current GOT entry. */
117 /* A pointer to the current GOT entry. */
118 unsigned char *got_entry;
120 /* True if we failed to read an entry correctly. */
123 /* Used internally to obtain GOT_ENTRY. */
124 struct data_iterator got_iterator;
127 /* Set up LGI to iterate over DSO's local GOT. The caller should use
128 mips_get_local_got_entry to read the first entry. */
131 mips_init_local_got_iterator (struct mips_local_got_iterator *lgi, DSO *dso)
134 lgi->entry_size = gelf_fsize (dso->elf, ELF_T_WORD, 1, EV_CURRENT);
135 lgi->got_index = RESERVED_GOTNO - 1;
137 init_data_iterator (&lgi->got_iterator, dso,
139 + (lgi->got_index + 1) * lgi->entry_size);
142 /* Return true if LGI has not reached the end of the GOT and if the next
143 entry can be accessed. When returning true, use LGI's fields to
144 describe the next entry. */
147 mips_get_local_got_entry (struct mips_local_got_iterator *lgi)
150 if (lgi->got_index >= lgi->dso->info_DT_MIPS_LOCAL_GOTNO)
153 lgi->got_entry = get_data_from_iterator (&lgi->got_iterator,
155 if (lgi->got_entry == NULL)
157 error (0, 0, "%s: Malformed local GOT\n", lgi->dso->filename);
165 /* A structure for iterating over global GOT entries. */
166 struct mips_global_got_iterator {
167 /* The DSO containing the GOT. */
170 /* The size of a GOT entry. */
171 GElf_Word entry_size;
173 /* The virtual address of the current GOT entry. */
176 /* The index of the associated entry in the dynamic symbol table. */
179 /* A pointer to the current GOT entry. */
180 unsigned char *got_entry;
182 /* The symbol associated with the current GOT entry. */
185 /* True if we failed to read an entry correctly. */
188 /* Used internally to obtain GOT_ENTRY and SYM. */
189 struct data_iterator got_iterator;
190 struct data_iterator sym_iterator;
193 /* Set up GGI to iterate over DSO's global GOT. The caller should use
194 mips_get_global_got_entry to read the first entry. */
197 mips_init_global_got_iterator (struct mips_global_got_iterator *ggi, DSO *dso)
202 ggi->entry_size = gelf_fsize (dso->elf, ELF_T_WORD, 1, EV_CURRENT);
203 ggi->got_addr = (dso->info[DT_PLTGOT]
204 + (dso->info_DT_MIPS_LOCAL_GOTNO - 1) * ggi->entry_size);
205 ggi->sym_index = dso->info_DT_MIPS_GOTSYM - 1;
208 sym_size = gelf_fsize (dso->elf, ELF_T_SYM, 1, EV_CURRENT);
209 init_data_iterator (&ggi->got_iterator, dso,
210 ggi->got_addr + ggi->entry_size);
211 init_data_iterator (&ggi->sym_iterator, dso,
212 dso->info[DT_SYMTAB] + (ggi->sym_index + 1) * sym_size);
215 /* Return true if GGI has not reached the end of the GOT and if the next
216 entry can be accessed. When returning true, use GGI's fields to
217 describe the next entry. */
220 mips_get_global_got_entry (struct mips_global_got_iterator *ggi)
223 ggi->got_addr += ggi->entry_size;
224 if (ggi->sym_index >= ggi->dso->info_DT_MIPS_SYMTABNO)
227 ggi->got_entry = get_data_from_iterator (&ggi->got_iterator,
229 if (ggi->got_entry == NULL
230 || !get_sym_from_iterator (&ggi->sym_iterator, &ggi->sym))
232 error (0, 0, "%s: Malformed global GOT\n", ggi->dso->filename);
241 mips_arch_adjust (DSO *dso, GElf_Addr start, GElf_Addr adjust)
243 struct mips_local_got_iterator lgi;
244 struct mips_global_got_iterator ggi;
247 if (dso->info[DT_PLTGOT] == 0)
250 /* Adjust every local GOT entry by ADJUST. Every adjustment moves
251 the code and data, so we do not need to check START here. */
252 mips_init_local_got_iterator (&lgi, dso);
253 while (mips_get_local_got_entry (&lgi))
255 value = buf_read_une32 (dso, lgi.got_entry);
256 buf_write_ne32 (dso, lgi.got_entry, value + adjust);
259 /* Adjust every global GOT entry. Referring to the table above:
261 For [A, B, C]: Adjust the GOT entry if it contains st_value
262 and if the symbol's value will be adjusted.
264 For [D]: Do nothing. SHN_COMMON entries never need adjusting.
266 For [E, F]: Adjust the GOT entry if it does not contain st_value
267 -- in other words, if it is a type E entry that points to a lazy
268 binding stub -- or if the symbol's value will also be adjusted. */
269 mips_init_global_got_iterator (&ggi, dso);
270 while (mips_get_global_got_entry (&ggi))
272 value = buf_read_une32 (dso, ggi.got_entry);
273 if (ggi.sym.st_shndx != SHN_COMMON
275 && (value == ggi.sym.st_value
276 ? adjust_symbol_p (dso, &ggi.sym)
277 : ggi.sym.st_shndx != SHN_UNDEF))
278 buf_write_ne32 (dso, ggi.got_entry, value + adjust);
281 return lgi.failed || ggi.failed;
285 mips_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
290 case DT_MIPS_TIME_STAMP:
291 case DT_MIPS_ICHECKSUM:
292 case DT_MIPS_IVERSION:
293 case DT_MIPS_CONFLICT:
294 case DT_MIPS_CONFLICTNO:
295 case DT_MIPS_LIBLIST:
296 case DT_MIPS_LIBLISTNO:
297 error (0, 0, "%s: File contains QuickStart information", dso->filename);
300 case DT_MIPS_BASE_ADDRESS:
301 case DT_MIPS_RLD_MAP:
302 case DT_MIPS_OPTIONS:
303 if (dyn->d_un.d_ptr >= start)
304 dyn->d_un.d_ptr += adjust;
307 case DT_MIPS_LOCAL_GOTNO:
308 case DT_MIPS_UNREFEXTNO:
309 case DT_MIPS_SYMTABNO:
310 case DT_MIPS_HIPAGENO:
312 /* We don't change the layout of the GOT or symbol table. */
315 case DT_MIPS_RLD_VERSION:
317 /* We don't change these properties. */
323 /* Read the addend for a relocation in DSO. If RELA is nonnull,
324 use its r_addend, otherwise read a 32-bit in-place addend from
327 static inline uint32_t
328 mips_read_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela)
330 return rela ? rela->r_addend : read_une32 (dso, r_offset);
333 /* Like mips_read_addend, but change the addend to VALUE. */
336 mips_write_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela,
340 rela->r_addend = (int32_t) value;
342 write_ne32 (dso, r_offset, value);
345 /* There is a relocation of type R_INFO against address R_OFFSET in DSO.
346 Adjust it so that virtual addresses >= START are increased by ADJUST
347 If the relocation is in a RELA section, RELA points to the relocation,
348 otherwise it is null. */
351 mips_adjust_reloc (DSO *dso, GElf_Addr r_offset, GElf_Xword r_info,
352 GElf_Addr start, GElf_Addr adjust, GElf_Rela *rela)
357 if (GELF_R_TYPE (r_info) == R_MIPS_REL32)
359 r_sym = GELF_R_SYM (r_info);
360 if (r_sym < dso->info_DT_MIPS_GOTSYM)
362 /* glibc's dynamic linker adds the symbol's st_value and the
363 base address to the addend. It therefore treats all symbols
364 as being relative, even if they would normally be considered
365 absolute. For example, the special null symbol should always
366 have the value zero, even when the base address is nonzero,
367 but R_MIPS_REL32 relocations against the null symbol must
368 nevertheles be adjusted as if that symbol were relative.
369 The same would apply to SHN_ABS symbols too.
371 Thus the result of the relocation calculation must always
372 be adjusted by ADJUST. (We do not need to check START because
373 every adjustment requested by the caller will affect all
374 legitimate local relocation values.) This means that we
375 should add ADJUST to the addend if and only if the symbol's
376 value is not being adjusted.
378 In general, we can only check whether a symbol's value is
379 being adjusted by reading its entry in the dynamic symbol
380 table and then querying adjust_symbol_p. However, this
381 generality is fortunately not needed. Modern versions
382 of binutils will never generate R_MIPS_REL32 relocations
383 against symbols in the range [1, DT_MIPS_GOTSYM), so we
384 only need to handle relocations against the null symbol. */
387 error (0, 0, "%s: The prelinker does not support R_MIPS_REL32"
388 " relocs against local symbols", dso->filename);
391 value = mips_read_addend (dso, r_offset, rela);
392 mips_write_addend (dso, r_offset, rela, value + adjust);
399 mips_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, GElf_Addr adjust)
401 return mips_adjust_reloc (dso, rel->r_offset, rel->r_info,
402 start, adjust, NULL);
406 mips_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, GElf_Addr adjust)
408 return mips_adjust_reloc (dso, rela->r_offset, rela->r_info,
409 start, adjust, rela);
412 /* Calculate relocation RELA as A + VALUE and store the result in DSO. */
415 mips_prelink_32bit_reloc (DSO *dso, GElf_Rela *rela, GElf_Addr value)
417 assert (rela != NULL);
418 write_ne32 (dso, rela->r_offset, value + rela->r_addend);
421 /* There is a relocation of type R_INFO against address R_OFFSET in DSO.
422 Prelink the relocation field, using INFO to look up symbol values.
423 If the relocation is in a RELA section, RELA points to the relocation,
424 otherwise it is null. */
427 mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset,
428 GElf_Xword r_info, GElf_Rela *rela)
436 r_sym = GELF_R_SYM (r_info);
437 r_type = GELF_R_TYPE (r_info);
444 /* An in-place R_MIPS_REL32 relocation against symbol 0 needs no
446 if (rela != NULL || GELF_R_SYM (r_info) != 0)
448 value = info->resolve (info, r_sym, r_type);
449 mips_prelink_32bit_reloc (dso, rela, value);
453 case R_MIPS_GLOB_DAT:
454 write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type));
457 case R_MIPS_TLS_DTPMOD32:
458 if (dso->ehdr.e_type == ET_EXEC)
460 error (0, 0, "%s: R_MIPS_TLS_DTPMOD32 reloc in executable?",
464 /* These relocations will be resolved using a conflict. We need
465 not change the field value here. */
468 case R_MIPS_TLS_DTPREL32:
469 value = info->resolve (info, r_sym, r_type);
470 mips_prelink_32bit_reloc (dso, rela, value - TLS_DTV_OFFSET);
473 case R_MIPS_TLS_TPREL32:
474 /* Relocations in a shared library will be resolved using a conflict.
475 We need not change the relocation field here. */
476 if (dso->ehdr.e_type == ET_EXEC)
478 value = info->resolve (info, r_sym, r_type);
479 value += info->resolvetls->offset - TLS_TP_OFFSET;
480 mips_prelink_32bit_reloc (dso, rela, value);
485 error (0, 0, "%s: Unknown MIPS relocation type %d",
486 dso->filename, (int) GELF_R_TYPE (r_info));
493 mips_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
497 /* Convert R_MIPS_REL32 relocations against global symbols into
498 R_MIPS_GLOB_DAT if the addend is zero. */
500 if (GELF_R_TYPE (rel->r_info) == R_MIPS_REL32
501 && GELF_R_SYM (rel->r_info) >= dso->info_DT_MIPS_GOTSYM
502 && read_une32 (dso, rel->r_offset) == 0)
504 rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_GLOB_DAT);
505 write_ne32 (dso, rel->r_offset,
506 info->resolve (info, GELF_R_SYM (rel->r_info),
507 GELF_R_TYPE (rel->r_info)));
510 return mips_prelink_reloc (info, rel->r_offset, rel->r_info, NULL);
514 mips_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
517 return mips_prelink_reloc (info, rela->r_offset, rela->r_info, rela);
520 /* CONFLICT is a conflict returned by prelink_conflict for a symbol
521 belonging to DSO. Set *TLS_OUT to the associated TLS information.
522 Return 1 on failure. */
525 mips_get_tls (DSO *dso, struct prelink_conflict *conflict,
526 struct prelink_tls **tls_out)
528 if (conflict->reloc_class != RTYPE_CLASS_TLS
529 || conflict->lookup.tls == NULL)
531 error (0, 0, "%s: R_MIPS_TLS not resolving to STT_TLS symbol",
536 *tls_out = conflict->lookup.tls;
540 /* There is a relocation of type R_INFO against address R_OFFSET in DSO.
541 See if the relocation field must be adjusted by a conflict when DSO
542 is used in the context described by INFO. Add a conflict entry if so.
543 If the relocation is in a RELA section, RELA points to the relocation,
544 otherwise it is null. */
547 mips_prelink_conflict_reloc (DSO *dso, struct prelink_info *info,
548 GElf_Addr r_offset, GElf_Xword r_info,
552 struct prelink_conflict *conflict;
553 struct prelink_tls *tls = NULL;
556 if (info->dso == dso)
559 conflict = prelink_conflict (info, GELF_R_SYM (r_info),
560 GELF_R_TYPE (r_info));
561 if (conflict == NULL)
563 switch (GELF_R_TYPE (r_info))
565 case R_MIPS_TLS_DTPMOD32:
566 case R_MIPS_TLS_TPREL32:
570 /* A relocation against symbol 0. A shared library cannot
571 know what the final module IDs or TP-relative offsets are,
572 so the executable must always have a conflict for them. */
579 else if (conflict->ifunc)
581 error (0, 0, "%s: STT_GNU_IFUNC not handled on MIPS yet",
587 /* DTPREL32 relocations just involve the symbol value; no other
588 TLS information is needed. Ignore conflicts created from a
589 lookup of type RTYPE_CLASS_TLS if no real conflict exists. */
590 if (GELF_R_TYPE (r_info) == R_MIPS_TLS_DTPREL32
591 && conflict->lookup.tls == conflict->conflict.tls
592 && conflict->lookupval == conflict->conflictval)
595 value = conflict_lookup_value (conflict);
597 /* VALUE now contains the final symbol value. Change it to the
598 value we want to store at R_OFFSET. */
599 switch (GELF_R_TYPE (r_info))
602 value += mips_read_addend (dso, r_offset, rela);
605 case R_MIPS_GLOB_DAT:
608 case R_MIPS_TLS_DTPMOD32:
609 if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1)
614 case R_MIPS_TLS_DTPREL32:
615 value += mips_read_addend (dso, r_offset, rela) - TLS_DTV_OFFSET;
618 case R_MIPS_TLS_TPREL32:
619 if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1)
621 value += (mips_read_addend (dso, r_offset, rela)
622 + tls->offset - TLS_TP_OFFSET);
626 error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename,
627 (int) GELF_R_TYPE (r_info));
630 /* Create and initialize a conflict entry. */
631 entry = prelink_conflict_add_rela (info);
634 entry->r_addend = (int32_t) value;
635 entry->r_offset = r_offset;
636 entry->r_info = GELF_R_INFO (0, R_MIPS_REL32);
641 mips_prelink_conflict_rel (DSO *dso, struct prelink_info *info,
642 GElf_Rel *rel, GElf_Addr reladdr)
644 return mips_prelink_conflict_reloc (dso, info, rel->r_offset,
649 mips_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
650 GElf_Rela *rela, GElf_Addr relaaddr)
652 return mips_prelink_conflict_reloc (dso, info, rela->r_offset,
657 mips_arch_prelink_conflict (DSO *dso, struct prelink_info *info)
659 struct mips_global_got_iterator ggi;
661 struct prelink_conflict *conflict;
664 if (info->dso == dso || dso->info[DT_PLTGOT] == 0)
667 /* Add a conflict for every global GOT entry that does not hold the
668 right value, either because of a conflict, or because the DSO has
669 a lazy binding stub for a symbol that it also defines. */
670 mips_init_global_got_iterator (&ggi, dso);
671 while (mips_get_global_got_entry (&ggi))
673 conflict = prelink_conflict (info, ggi.sym_index, R_MIPS_REL32);
674 if (conflict != NULL)
675 value = conflict_lookup_value (conflict);
676 else if (ggi.sym.st_shndx != SHN_UNDEF
677 && ggi.sym.st_shndx != SHN_COMMON)
678 value = ggi.sym.st_value;
681 if (buf_read_une32 (dso, ggi.got_entry) != value)
683 entry = prelink_conflict_add_rela (info);
686 entry->r_addend = (int32_t) value;
687 entry->r_offset = ggi.got_addr;
688 entry->r_info = GELF_R_INFO (0, R_MIPS_REL32);
696 mips_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
697 char *buf, GElf_Addr dest_addr)
699 switch (GELF_R_TYPE (rela->r_info))
702 buf_write_ne32 (info->dso, buf, rela->r_addend);
711 /* BUF points to a 32-bit field in DSO that is subject to relocation.
712 If the relocation is in a RELA section, RELA points to the relocation,
713 otherwise it is null. Add the addend to ADJUSTMENT and install the
717 mips_apply_adjustment (DSO *dso, GElf_Rela *rela, char *buf,
718 GElf_Addr adjustment)
721 adjustment += rela->r_addend;
723 adjustment += buf_read_une32 (dso, buf);
724 buf_write_ne32 (dso, buf, adjustment);
728 mips_apply_reloc (struct prelink_info *info, GElf_Xword r_info,
729 GElf_Rela *rela, char *buf)
734 switch (GELF_R_TYPE (r_info))
740 mips_apply_adjustment (dso, rela, buf,
741 info->resolve (info, GELF_R_SYM (r_info),
742 GELF_R_TYPE (r_info)));
752 mips_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
754 return mips_apply_reloc (info, rel->r_info, NULL, buf);
758 mips_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
760 return mips_apply_reloc (info, rela->r_info, rela, buf);
764 mips_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
766 rela->r_offset = rel->r_offset;
767 rela->r_info = rel->r_info;
768 switch (GELF_R_TYPE (rel->r_info))
771 case R_MIPS_TLS_DTPREL32:
772 case R_MIPS_TLS_TPREL32:
773 /* These relocations have an in-place addend. */
774 rela->r_addend = (int32_t) read_une32 (dso, rel->r_offset);
778 case R_MIPS_GLOB_DAT:
779 case R_MIPS_TLS_DTPMOD32:
780 /* These relocations have no addend. */
785 error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename,
786 (int) GELF_R_TYPE (rel->r_info));
793 mips_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel)
795 rel->r_offset = rela->r_offset;
796 rel->r_info = rela->r_info;
797 switch (GELF_R_TYPE (rela->r_info))
803 case R_MIPS_TLS_DTPREL32:
804 case R_MIPS_TLS_TPREL32:
805 /* These relocations have an in-place addend. */
806 write_ne32 (dso, rela->r_offset, rela->r_addend);
809 case R_MIPS_GLOB_DAT:
810 case R_MIPS_TLS_DTPMOD32:
811 /* These relocations have no addend. */
812 write_ne32 (dso, rela->r_offset, 0);
816 error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename,
817 (int) GELF_R_TYPE (rela->r_info));
824 mips_need_rel_to_rela (DSO *dso, int first, int last)
828 Elf32_Rel *rel, *relend;
831 for (n = first; n <= last; n++)
835 while ((data = elf_getdata (scn, data)) != NULL)
837 rel = (Elf32_Rel *) data->d_buf;
838 relend = rel + data->d_size / sizeof (Elf32_Rel);
839 for (; rel < relend; rel++)
840 switch (ELF32_R_TYPE (rel->r_info))
846 /* The SVR4 definition was designed to allow exactly the
847 sort of prelinking we want to do here, in combination
848 with Quickstart. Unfortunately, glibc's definition
849 makes it impossible for relocations against anything
850 other than the null symbol. We get around this for
851 zero addends by using a R_MIPS_GLOB_DAT relocation
852 instead, where R_MIPS_GLOB_DAT is a GNU extension
853 added specifically for this purpose. */
854 if (ELF32_R_SYM (rel->r_info) != 0
855 && (ELF32_R_SYM (rel->r_info) < dso->info_DT_MIPS_GOTSYM
856 || read_une32 (dso, rel->r_offset) != 0))
860 case R_MIPS_GLOB_DAT:
861 /* This relocation has no addend. */
864 case R_MIPS_TLS_DTPMOD32:
865 /* The relocation will be resolved using a conflict. */
868 case R_MIPS_TLS_DTPREL32:
869 /* We can prelink these fields, and the addend is relative
870 to the symbol value. A RELA entry is needed. */
873 case R_MIPS_TLS_TPREL32:
874 /* Relocations in shared libraries will be resolved by a
875 conflict. Relocations in executables will not, and the
876 addend is relative to the symbol value. */
877 if (dso->ehdr.e_type == ET_EXEC)
882 error (0, 0, "%s: Unknown MIPS relocation type %d",
883 dso->filename, (int) GELF_R_TYPE (rel->r_info));
892 mips_reloc_size (int reloc_type)
898 mips_reloc_class (int reloc_type)
902 case R_MIPS_TLS_DTPMOD32:
903 case R_MIPS_TLS_DTPREL32:
904 case R_MIPS_TLS_TPREL32:
905 return RTYPE_CLASS_TLS;
907 /* MIPS lazy resolution stubs are local to the containing object,
908 so SHN_UNDEF symbols never participate in symbol lookup. */
909 return RTYPE_CLASS_PLT;
914 mips_arch_prelink (struct prelink_info *info)
916 struct mips_global_got_iterator ggi;
921 if (dso->info[DT_PLTGOT] == 0)
924 /* Install Quickstart values for all global GOT entries of type A-D
925 in the table above. */
926 mips_init_global_got_iterator (&ggi, dso);
927 while (mips_get_global_got_entry (&ggi))
929 value = info->resolve (info, ggi.sym_index, R_MIPS_REL32);
930 if (ggi.sym.st_shndx == SHN_UNDEF
931 || ggi.sym.st_shndx == SHN_COMMON)
932 buf_write_ne32 (dso, ggi.got_entry, value);
935 /* Type E and F in the table above. We cannot install Quickstart
936 values for type E, but we should never need to in executables,
937 because an executable should not use lazy binding stubs for
938 symbols it defines itself. Although we could in theory just
939 discard any such stub address, it goes against the principle
940 that prelinking should be reversible.
942 When type E entries occur in shared libraries, we can fix
943 them up using conflicts.
945 Type F entries should never need a Quickstart value -- the
946 current value should already be correct. However, the conflict
947 code will cope correctly with malformed type F entries in
948 shared libraries, so we only complain about executables here. */
949 if (dso->ehdr.e_type == ET_EXEC
950 && value != buf_read_une32 (dso, ggi.got_entry))
952 error (0, 0, "%s: The global GOT entries for defined symbols"
953 " do not match their st_values\n", dso->filename);
962 mips_arch_undo_prelink (DSO *dso)
964 struct mips_global_got_iterator ggi;
966 if (dso->info[DT_PLTGOT] == 0)
969 mips_init_global_got_iterator (&ggi, dso);
970 while (mips_get_global_got_entry (&ggi))
971 if (ggi.sym.st_shndx == SHN_UNDEF)
972 /* Types A-C in the table above. */
973 buf_write_ne32 (dso, ggi.got_entry, ggi.sym.st_value);
974 else if (ggi.sym.st_shndx == SHN_COMMON)
975 /* Type D in the table above. */
976 buf_write_ne32 (dso, ggi.got_entry, 0);
981 mips_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr)
983 /* Convert R_MIPS_GLOB_DAT relocations back into R_MIPS_REL32
984 relocations. Ideally we'd have some mechanism for recording
985 these changes in the undo section, but in the absence of that,
986 it's better to assume that the original relocation was
987 R_MIPS_REL32; R_MIPS_GLOB_DAT was added specifically for the
988 prelinker and shouldn't be used in non-prelinked binaries. */
989 if (GELF_R_TYPE (rel->r_info) == R_MIPS_GLOB_DAT)
991 write_ne32 (dso, rel->r_offset, 0);
992 rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_REL32);
1000 .class = ELFCLASS32,
1002 .max_reloc_size = 4,
1003 .dynamic_linker = "/lib/ld.so.1",
1004 /* MIPS does not use COPY relocs or jump slots. Pick a value outside
1005 the ELF32_R_TYPE range. */
1008 /* R_MIPS_REL32 relocations against symbol 0 do act as relative relocs,
1009 but those against other symbols don't. */
1011 .rtype_class_valid = RTYPE_CLASS_VALID,
1012 .arch_adjust = mips_arch_adjust,
1013 .adjust_dyn = mips_adjust_dyn,
1014 .adjust_rel = mips_adjust_rel,
1015 .adjust_rela = mips_adjust_rela,
1016 .prelink_rel = mips_prelink_rel,
1017 .prelink_rela = mips_prelink_rela,
1018 .prelink_conflict_rel = mips_prelink_conflict_rel,
1019 .prelink_conflict_rela = mips_prelink_conflict_rela,
1020 .arch_prelink_conflict = mips_arch_prelink_conflict,
1021 .apply_conflict_rela = mips_apply_conflict_rela,
1022 .apply_rel = mips_apply_rel,
1023 .apply_rela = mips_apply_rela,
1024 .rel_to_rela = mips_rel_to_rela,
1025 .rela_to_rel = mips_rela_to_rel,
1026 .need_rel_to_rela = mips_need_rel_to_rela,
1027 .reloc_size = mips_reloc_size,
1028 .reloc_class = mips_reloc_class,
1029 .arch_prelink = mips_arch_prelink,
1030 .arch_undo_prelink = mips_arch_undo_prelink,
1031 .undo_prelink_rel = mips_undo_prelink_rel,
1032 /* Although TASK_UNMAPPED_BASE is 0x2aaa8000, we leave some
1033 area so that mmap of /etc/ld.so.cache and ld.so's malloc
1034 does not take some library's VA slot.
1035 Also, if this guard area isn't too small, typically
1036 even dlopened libraries will get the slots they desire. */
1037 .mmap_base = 0x2c000000,
1038 .mmap_end = 0x3c000000,
1039 .max_page_size = 0x10000,