wordexp: Fix the usage of the internal _itoa function
[uclibc-ng.git] / ldso / ldso / fdpic / dl-inlines.h
blob89e7a9a68582b4402d99d322b119dc3bfa6d41b3
1 /* Copyright (C) 2003, 2004 Red Hat, Inc.
2 * Contributed by Alexandre Oliva <aoliva@redhat.com>
3 * Copyright (C) 2006-2011 Analog Devices, Inc.
5 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
6 */
8 #include <inline-hashtab.h>
10 static __always_inline void htab_delete(struct funcdesc_ht *htab);
12 /* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete load map. */
13 static __always_inline void
14 __dl_init_loadaddr_map(struct elf32_fdpic_loadaddr *loadaddr, Elf32_Addr dl_boot_got_pointer,
15 struct elf32_fdpic_loadmap *map)
17 if (map->version != 0) {
18 SEND_EARLY_STDERR("Invalid loadmap version number\n");
19 _dl_exit(-1);
21 if (map->nsegs == 0) {
22 SEND_EARLY_STDERR("Invalid segment count in loadmap\n");
23 _dl_exit(-1);
25 loadaddr->got_value = (void *)dl_boot_got_pointer;
26 loadaddr->map = map;
30 * Figure out how many LOAD segments there are in the given headers,
31 * and allocate a block for the load map big enough for them.
32 * got_value will be properly initialized later on, with INIT_GOT.
34 static __always_inline int
35 __dl_init_loadaddr(struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt,
36 int pcnt)
38 int count = 0, i;
39 size_t size;
41 for (i = 0; i < pcnt; i++)
42 if (ppnt[i].p_type == PT_LOAD)
43 count++;
45 loadaddr->got_value = 0;
47 size = sizeof(struct elf32_fdpic_loadmap) +
48 (sizeof(struct elf32_fdpic_loadseg) * count);
49 loadaddr->map = _dl_malloc(size);
50 if (!loadaddr->map)
51 _dl_exit(-1);
53 loadaddr->map->version = 0;
54 loadaddr->map->nsegs = 0;
56 return count;
59 /* Incrementally initialize a load map. */
60 static __always_inline void
61 __dl_init_loadaddr_hdr(struct elf32_fdpic_loadaddr loadaddr, void *addr,
62 Elf32_Phdr *phdr, int maxsegs)
64 struct elf32_fdpic_loadseg *segdata;
66 if (loadaddr.map->nsegs == maxsegs)
67 _dl_exit(-1);
69 segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
70 segdata->addr = (Elf32_Addr)addr;
71 segdata->p_vaddr = phdr->p_vaddr;
72 segdata->p_memsz = phdr->p_memsz;
74 #if defined(__SUPPORT_LD_DEBUG__)
75 if (_dl_debug)
76 _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
77 loadaddr.map->nsegs - 1,
78 segdata->p_vaddr, segdata->addr, segdata->p_memsz);
79 #endif
82 /* Replace an existing entry in the load map. */
83 static __always_inline void
84 __dl_update_loadaddr_hdr(struct elf32_fdpic_loadaddr loadaddr, void *addr,
85 Elf32_Phdr *phdr)
87 struct elf32_fdpic_loadseg *segdata;
88 void *oldaddr;
89 int i;
91 for (i = 0; i < loadaddr.map->nsegs; i++)
92 if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr &&
93 loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
94 break;
95 if (i == loadaddr.map->nsegs)
96 _dl_exit(-1);
98 segdata = loadaddr.map->segs + i;
99 oldaddr = (void *)segdata->addr;
100 _dl_munmap(oldaddr, segdata->p_memsz);
101 segdata->addr = (Elf32_Addr)addr;
103 #if defined (__SUPPORT_LD_DEBUG__)
104 if (_dl_debug)
105 _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size %x\n",
106 loadaddr.map->nsegs - 1,
107 segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
108 #endif
112 #ifndef __dl_loadaddr_unmap
113 static __always_inline void
114 __dl_loadaddr_unmap(struct elf32_fdpic_loadaddr loadaddr,
115 struct funcdesc_ht *funcdesc_ht)
117 int i;
119 for (i = 0; i < loadaddr.map->nsegs; i++)
120 _dl_munmap((void *)loadaddr.map->segs[i].addr,
121 loadaddr.map->segs[i].p_memsz);
124 * _dl_unmap is only called for dlopen()ed libraries, for which
125 * calling free() is safe, or before we've completed the initial
126 * relocation, in which case calling free() is probably pointless,
127 * but still safe.
129 _dl_free(loadaddr.map);
130 if (funcdesc_ht)
131 htab_delete(funcdesc_ht);
133 #endif
135 /* Figure out whether the given address is in one of the mapped segments. */
136 static __always_inline int
137 __dl_addr_in_loadaddr(void *p, struct elf32_fdpic_loadaddr loadaddr)
139 struct elf32_fdpic_loadmap *map = loadaddr.map;
140 int c;
142 for (c = 0; c < map->nsegs; c++)
143 if ((void *)map->segs[c].addr <= p &&
144 (char *)p < (char *)map->segs[c].addr + map->segs[c].p_memsz)
145 return 1;
147 return 0;
150 static int
151 hash_pointer(void *p)
153 return (int) ((long)p >> 3);
156 static int
157 eq_pointer(void *p, void *q)
159 struct funcdesc_value *entry = p;
161 return entry->entry_point == q;
164 static __always_inline void *
165 _dl_funcdesc_for (void *entry_point, void *got_value)
167 struct elf_resolve *tpnt = ((void**)got_value)[2];
168 struct funcdesc_ht *ht = tpnt->funcdesc_ht;
169 struct funcdesc_value **entry;
171 _dl_assert(got_value == tpnt->loadaddr.got_value);
173 if (!ht) {
174 ht = htab_create();
175 if (!ht)
176 return (void*)-1;
177 tpnt->funcdesc_ht = ht;
180 entry = htab_find_slot(ht, entry_point, 1, hash_pointer, eq_pointer);
182 if (entry == NULL)
183 _dl_exit(1);
185 if (*entry) {
186 _dl_assert((*entry)->entry_point == entry_point);
187 return _dl_stabilize_funcdesc(*entry);
190 *entry = _dl_malloc(sizeof(**entry));
191 (*entry)->entry_point = entry_point;
192 (*entry)->got_value = got_value;
194 return _dl_stabilize_funcdesc(*entry);
197 static __always_inline void const *
198 _dl_lookup_address(void const *address)
200 struct elf_resolve *rpnt;
201 struct funcdesc_value const *fd;
203 /* Make sure we don't make assumptions about its alignment. */
204 __asm__ ("" : "+r" (address));
206 if ((Elf32_Addr)address & 7)
207 /* It's not a function descriptor. */
208 return address;
210 fd = address;
212 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
213 if (!rpnt->funcdesc_ht)
214 continue;
216 if (fd->got_value != rpnt->loadaddr.got_value)
217 continue;
219 address = htab_find_slot(rpnt->funcdesc_ht, (void *)fd->entry_point, 0,
220 hash_pointer, eq_pointer);
222 if (address && *(struct funcdesc_value *const*)address == fd) {
223 address = (*(struct funcdesc_value *const*)address)->entry_point;
224 break;
225 } else
226 address = fd;
229 return address;