1 /* Do relocations for ELF dynamic linking.
2 Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* This file may be included twice, to define both
21 `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
24 # define elf_dynamic_do_rel elf_dynamic_do_rela
25 # define RELCOUNT_IDX VERSYMIDX (DT_RELACOUNT)
27 # define elf_machine_rel elf_machine_rela
28 # define elf_machine_rel_relative elf_machine_rela_relative
30 # define RELCOUNT_IDX VERSYMIDX (DT_RELCOUNT)
34 # define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
37 # define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
38 + DT_EXTRANUM + DT_VALTAGIDX (tag))
41 /* Perform the relocations in MAP on the running program image as specified
42 by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
43 relocations; they should be set up to call _dl_runtime_resolve, rather
44 than fully resolved now. */
47 elf_dynamic_do_rel (struct link_map
*map
,
48 ElfW(Addr
) reladdr
, ElfW(Addr
) relsize
,
51 const ElfW(Rel
) *r
= (const void *) reladdr
;
52 const ElfW(Rel
) *end
= (const void *) (reladdr
+ relsize
);
53 ElfW(Addr
) l_addr
= map
->l_addr
;
55 #if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
56 /* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
57 not clever enough to see through all the function calls to realize
61 /* Doing lazy PLT relocations; they need very little info. */
63 elf_machine_lazy_rel (map
, l_addr
, r
);
68 const ElfW(Sym
) *const symtab
=
69 (const void *) D_PTR (map
, l_info
[DT_SYMTAB
]);
70 ElfW(Word
) nrelative
= (map
->l_info
[RELCOUNT_IDX
] == NULL
71 ? 0 : map
->l_info
[RELCOUNT_IDX
]->d_un
.d_val
);
72 const ElfW(Rel
) *relative
= r
;
73 r
= MIN (r
+ nrelative
, end
);
75 #ifndef RTLD_BOOTSTRAP
76 /* This is defined in rtld.c, but nowhere in the static libc.a; make
77 the reference weak so static programs can still link. This
78 declaration cannot be done when compiling rtld.c (i.e. #ifdef
79 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
80 _dl_rtld_map, which is incompatible with a weak decl in the same
83 weak_extern (GL(dl_rtld_map
));
85 if (map
!= &GL(dl_rtld_map
)) /* Already done in rtld itself. */
87 /* Rela platforms get the offset from r_addend and this must
88 be copied in the relocation address. Therefore we can skip
89 the relative relocations only if this is for rel
93 /* ...or we know the object has been prelinked. */
94 if (l_addr
!= 0 || ! map
->l_info
[VALIDX(DT_GNU_PRELINKED
)])
97 for (; relative
< r
; ++relative
)
98 elf_machine_rel_relative (l_addr
, relative
,
99 (void *) (l_addr
+ relative
->r_offset
));
101 if (map
->l_info
[VERSYMIDX (DT_VERSYM
)])
103 const ElfW(Half
) *const version
=
104 (const void *) D_PTR (map
, l_info
[VERSYMIDX (DT_VERSYM
)]);
108 ElfW(Half
) ndx
= version
[ELFW(R_SYM
) (r
->r_info
)];
109 elf_machine_rel (map
, r
, &symtab
[ELFW(R_SYM
) (r
->r_info
)],
110 &map
->l_versions
[ndx
],
111 (void *) (l_addr
+ r
->r_offset
));
116 elf_machine_rel (map
, r
, &symtab
[ELFW(R_SYM
) (r
->r_info
)], NULL
,
117 (void *) (l_addr
+ r
->r_offset
));
121 #undef elf_dynamic_do_rel
123 #undef elf_machine_rel
124 #undef elf_machine_rel_relative