]> sourceware.org Git - glibc.git/blame - sysdeps/i386/dl-runtime.c
Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[glibc.git] / sysdeps / i386 / dl-runtime.c
CommitLineData
d66e34cd
RM
1/* On-demand PLT fixup for shared objects. i386 version.
2Copyright (C) 1995 Free Software Foundation, Inc.
3This file is part of the GNU C Library.
4
5The GNU C Library is free software; you can redistribute it and/or
6modify it under the terms of the GNU Library General Public License as
7published by the Free Software Foundation; either version 2 of the
8License, or (at your option) any later version.
9
10The GNU C Library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13Library General Public License for more details.
14
15You should have received a copy of the GNU Library General Public
16License along with the GNU C Library; see the file COPYING.LIB. If
17not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18Cambridge, 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
33void
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}
This page took 0.034638 seconds and 5 git commands to generate.