1 /* Do relocations for ELF dynamic linking.
2 Copyright (C) 1995,96,97,98,99,2000,2001 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 /* Perform the relocations in MAP on the running program image as specified
38 by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
39 relocations; they should be set up to call _dl_runtime_resolve, rather
40 than fully resolved now. */
43 elf_dynamic_do_rel (struct link_map
*map
,
44 ElfW(Addr
) reladdr
, ElfW(Addr
) relsize
,
47 const ElfW(Rel
) *r
= (const void *) reladdr
;
48 const ElfW(Rel
) *end
= (const void *) (reladdr
+ relsize
);
49 ElfW(Addr
) l_addr
= map
->l_addr
;
51 #ifndef RTLD_BOOTSTRAP
52 /* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
53 not clever enough to see through all the function calls to realize
57 /* Doing lazy PLT relocations; they need very little info. */
59 elf_machine_lazy_rel (map
, l_addr
, r
);
64 const ElfW(Sym
) *const symtab
=
65 (const void *) D_PTR (map
, l_info
[DT_SYMTAB
]);
66 ElfW(Word
) nrelative
= (map
->l_info
[RELCOUNT_IDX
] == NULL
67 ? 0 : map
->l_info
[RELCOUNT_IDX
]->d_un
.d_val
);
68 const ElfW(Rel
) *relative
= r
;
69 r
= MIN (r
+ nrelative
, end
);
71 #ifndef RTLD_BOOTSTRAP
72 /* This is defined in rtld.c, but nowhere in the static libc.a; make
73 the reference weak so static programs can still link. This
74 declaration cannot be done when compiling rtld.c (i.e. #ifdef
75 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
76 _dl_rtld_map, which is incompatible with a weak decl in the same
78 weak_extern (_dl_rtld_map
);
79 if (map
!= &_dl_rtld_map
) /* Already done in rtld itself. */
81 /* Rela platforms get the offset from r_addend and this must
82 be copied in the relocation address. Therefore we can skip
83 the relative relocations only if this is for rel
88 for (; relative
< r
; ++relative
)
89 elf_machine_rel_relative (l_addr
, relative
,
90 (void *) (l_addr
+ relative
->r_offset
));
92 if (map
->l_info
[VERSYMIDX (DT_VERSYM
)])
94 const ElfW(Half
) *const version
=
95 (const void *) D_PTR (map
, l_info
[VERSYMIDX (DT_VERSYM
)]);
99 ElfW(Half
) ndx
= version
[ELFW(R_SYM
) (r
->r_info
)];
100 elf_machine_rel (map
, r
, &symtab
[ELFW(R_SYM
) (r
->r_info
)],
101 &map
->l_versions
[ndx
],
102 (void *) (l_addr
+ r
->r_offset
));
107 elf_machine_rel (map
, r
, &symtab
[ELFW(R_SYM
) (r
->r_info
)], NULL
,
108 (void *) (l_addr
+ r
->r_offset
));
112 #undef elf_dynamic_do_rel
114 #undef elf_machine_rel
115 #undef elf_machine_rel_relative