]>
Commit | Line | Data |
---|---|---|
0b3cf801 | 1 | /* Run-time dynamic linker data structures for loaded ELF shared objects. |
d4697bc9 | 2 | Copyright (C) 2005-2014 Free Software Foundation, Inc. |
0b3cf801 UD |
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 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. | |
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 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
0b3cf801 UD |
18 | |
19 | #ifndef _LDSODEFS_H | |
20 | ||
21 | /* Get the real definitions. */ | |
22 | #include_next <ldsodefs.h> | |
23 | ||
24 | /* Now define our stuff. */ | |
25 | ||
696caf1d UW |
26 | #if _CALL_ELF != 2 |
27 | ||
0b3cf801 UD |
28 | static __always_inline bool |
29 | _dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym) | |
30 | { | |
31 | return (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC | |
32 | && l->l_addr + sym->st_value >= (ElfW(Addr)) l->l_ld | |
33 | && l->l_addr + sym->st_value < l->l_map_end | |
34 | && sym->st_size != 0); | |
35 | } | |
36 | ||
37 | static __always_inline bool | |
38 | _dl_ppc64_addr_sym_match (const struct link_map *l, const ElfW(Sym) *sym, | |
39 | const ElfW(Sym) *matchsym, ElfW(Addr) addr) | |
40 | { | |
41 | ElfW(Addr) value = l->l_addr + sym->st_value; | |
42 | if (_dl_ppc64_is_opd_sym (l, sym)) | |
43 | { | |
44 | if (addr < value || addr >= value + 24) | |
45 | { | |
46 | value = *(ElfW(Addr) *) value; | |
47 | if (addr < value || addr >= value + sym->st_size) | |
48 | return false; | |
49 | } | |
50 | } | |
2ac9ca73 | 51 | else if (sym->st_shndx == SHN_UNDEF || sym->st_size == 0) |
0b3cf801 UD |
52 | { |
53 | if (addr != value) | |
54 | return false; | |
55 | } | |
56 | else if (addr < value || addr >= value + sym->st_size) | |
57 | return false; | |
58 | ||
59 | if (matchsym == NULL) | |
60 | return true; | |
61 | ||
62 | ElfW(Addr) matchvalue = l->l_addr + matchsym->st_value; | |
63 | if (_dl_ppc64_is_opd_sym (l, matchsym) | |
64 | && (addr < matchvalue || addr > matchvalue + 24)) | |
65 | matchvalue = *(ElfW(Addr) *) matchvalue; | |
66 | ||
67 | return matchvalue < value; | |
68 | } | |
69 | ||
70 | /* If this is a function symbol defined past the end of our dynamic | |
71 | section, then it must be a function descriptor. Allow these symbols | |
72 | to match their associated function code range as well as the | |
73 | descriptor addresses. */ | |
74 | #undef DL_ADDR_SYM_MATCH | |
75 | #define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \ | |
76 | _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR) | |
77 | ||
696caf1d UW |
78 | #endif |
79 | ||
0b3cf801 | 80 | #endif /* ldsodefs.h */ |