]>
Commit | Line | Data |
---|---|---|
d66e34cd RM |
1 | /* On-demand PLT fixup for shared objects. i386 version. |
2 | Copyright (C) 1995 Free Software Foundation, Inc. | |
3 | This file is part of the GNU C Library. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Library General Public License as | |
7 | published by the Free Software Foundation; either version 2 of the | |
8 | License, or (at your option) any later version. | |
9 | ||
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 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with the GNU C Library; see the file COPYING.LIB. If | |
17 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, | |
18 | Cambridge, MA 02139, USA. */ | |
19 | ||
d66e34cd RM |
20 | #include <link.h> |
21 | #include "dynamic-link.h" | |
22 | ||
23 | /* This function is not called in the normal way. The PLT jumps here, not | |
24 | using a call. The stack looks like this: | |
25 | ||
26 | -->8(%esp) address to return to the caller of the function in the PLT | |
27 | 4(%esp) relocation offset for this PLT entry | |
28 | 0(%esp) identifier for this shared object (struct link_map *) | |
29 | ||
30 | The user expects the real function the PLT refers to to be entered | |
421f82e5 | 31 | with 8(%esp) as the top of stack. */ |
d66e34cd RM |
32 | |
33 | void | |
34 | _dl_runtime_resolve (Elf32_Word reloc_offset) | |
35 | { | |
36 | __label__ return_insn; | |
a1a9d215 | 37 | struct link_map *l = (void *) (&reloc_offset)[-1]; |
d66e34cd RM |
38 | |
39 | const Elf32_Sym *const symtab | |
a1a9d215 RM |
40 | = (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr); |
41 | const char *strtab = | |
42 | (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); | |
d66e34cd | 43 | |
a1a9d215 RM |
44 | const Elf32_Rel *const reloc |
45 | = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr + | |
46 | reloc_offset); | |
d66e34cd RM |
47 | |
48 | const Elf32_Sym *definer; | |
49 | Elf32_Addr loadbase; | |
50 | struct link_map *scope, *real_next; | |
51 | ||
52 | /* Look up the symbol's run-time value. */ | |
53 | ||
54 | real_next = l->l_next; | |
55 | if (l->l_info[DT_SYMBOLIC]) | |
56 | { | |
57 | l->l_prev->l_next = real_next; | |
58 | l->l_next = _dl_loaded; | |
59 | scope = l; | |
60 | } | |
61 | else | |
62 | scope = _dl_loaded; | |
63 | ||
64 | definer = &symtab[ELF32_R_SYM (reloc->r_info)]; | |
421f82e5 RM |
65 | loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer, |
66 | scope, l->l_name); | |
d66e34cd RM |
67 | |
68 | /* Restore list frobnication done above for DT_SYMBOLIC. */ | |
69 | l->l_next = real_next; | |
70 | l->l_prev->l_next = l; | |
71 | ||
72 | /* Apply the relocation with that value. */ | |
421f82e5 | 73 | elf_machine_rel (l, reloc, loadbase, definer); |
d66e34cd RM |
74 | |
75 | /* The top of the stack is the word we set L from; but this location | |
76 | holds the address we will return to. Store there the address of a | |
77 | "ret" instruction, which will pop the stack and run the code at the | |
78 | address in the next stack word. */ | |
79 | (&reloc_offset)[-1] = (Elf32_Word) &&return_insn; | |
80 | ||
81 | /* The next stack word is our argument RELOC_OFFSET; but that "ret" will | |
82 | pop and jump to this location, and the next stack word is the user's | |
83 | return address. So store here the resolved address of the function | |
84 | referred to by this PLT entry; once "ret" pops this address, the | |
85 | function in the shared object will run with the stack arranged just as | |
86 | when the user entered the PLT. */ | |
a1a9d215 | 87 | (&reloc_offset)[0] = *(Elf32_Word *) (l->l_addr + reloc->r_offset); |
d66e34cd RM |
88 | |
89 | return; | |
90 | ||
91 | return_insn: asm volatile ("ret"); | |
92 | } |