(base_os): Linux is based on unix/sysv, not unix/sysv/sysv4.
[glibc.git] / elf / dl-load.c
blob6cacd3e3b6d68ac064b04c94e005cdf1e9789cc2
1 /* _dl_map_object -- Map in a shared object's segments from the file.
2 Copyright (C) 1995 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 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.
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.
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. */
20 #include <link.h>
21 #include <sys/types.h>
22 #include <sys/mman.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include "dynamic-link.h"
31 #include <endian.h>
32 #if BYTE_ORDER == BIG_ENDIAN
33 #define byteorder ELFDATA2MSB
34 #define byteorder_name "big-endian"
35 #elif BYTE_ORDER == LITTLE_ENDIAN
36 #define byteorder ELFDATA2LSB
37 #define byteorder_name "little-endian"
38 #else
39 #error "Unknown BYTE_ORDER " BYTE_ORDER
40 #define byteorder ELFDATANONE
41 #endif
43 #define STRING(x) #x
45 int _dl_zerofd = -1;
48 /* Try to open NAME in one of the directories in DIRPATH.
49 Return the fd, or -1. If successful, fill in *REALNAME
50 with the malloc'd full directory name. */
52 static int
53 open_path (const char *name, size_t namelen,
54 const char *dirpath,
55 char **realname)
57 char *buf;
58 const char *p;
59 int fd;
61 p = dirpath;
62 if (p == NULL || *p == '\0')
64 errno = ENOENT;
65 return -1;
68 buf = alloca (strlen (dirpath) + 1 + namelen);
71 dirpath = p;
72 p = strpbrk (dirpath, ":;");
73 if (p == NULL)
74 p = strchr (dirpath, '\0');
76 if (p == dirpath)
77 /* Two adjacent colons, or a colon at the beginning or the end of
78 the path means to search the current directory. */
79 (void) memcpy (buf, name, namelen);
80 else
82 /* Construct the pathname to try. */
83 (void) memcpy (buf, dirpath, p - dirpath);
84 buf[p - dirpath] = '/';
85 (void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
88 fd = open (buf, O_RDONLY);
89 if (fd != -1)
91 *realname = strdup (buf);
92 return fd;
94 if (errno != ENOENT && errno != EACCES)
95 /* The file exists and is readable, but something went wrong. */
96 return -1;
98 while (*p++ != '\0');
100 return -1;
104 /* Map in the shared object file NAME. */
106 struct link_map *
107 _dl_map_object (struct link_map *loader, const char *name,
108 Elf32_Addr *entry_point)
110 int fd;
111 struct link_map *l = NULL;
112 char *realname;
113 const size_t pagesize = getpagesize ();
114 void *file_mapping = NULL;
115 size_t mapping_size = 0;
117 void lose (int code, const char *msg)
119 (void) close (fd);
120 if (file_mapping)
121 munmap (file_mapping, mapping_size);
122 _dl_signal_error (code, l ? l->l_name : name, msg);
125 /* Make sure LOCATION is mapped in. */
126 void *map (off_t location, size_t size)
128 if ((off_t) mapping_size <= location + (off_t) size)
130 void *result;
131 if (file_mapping)
132 munmap (file_mapping, mapping_size);
133 mapping_size = (location + size + 1 + pagesize - 1);
134 mapping_size &= ~(pagesize - 1);
135 result = mmap (file_mapping, mapping_size, PROT_READ,
136 MAP_COPY|MAP_FILE, fd, 0);
137 if (result == (void *) -1)
138 lose (errno, "cannot map file data");
139 file_mapping = result;
141 return file_mapping + location;
144 const Elf32_Ehdr *header;
146 /* Look for this name among those already loaded. */
147 for (l = _dl_loaded; l; l = l->l_next)
148 if (! strcmp (name, l->l_libname))
150 /* The object is already loaded.
151 Just bump its reference count and return it. */
152 ++l->l_opencount;
153 return l;
156 if (strchr (name, '/') == NULL)
158 /* Search for NAME in several places. */
160 size_t namelen = strlen (name) + 1;
162 inline void trypath (const char *dirpath)
164 fd = open_path (name, namelen, dirpath, &realname);
167 fd = -1;
168 if (loader && loader->l_info[DT_RPATH])
169 trypath ((const char *) (loader->l_addr +
170 loader->l_info[DT_STRTAB]->d_un.d_ptr +
171 loader->l_info[DT_RPATH]->d_un.d_val));
172 if (fd == -1 && ! _dl_secure)
173 trypath (getenv ("LD_LIBRARY_PATH"));
174 if (fd == -1)
175 trypath ("/lib:/usr/lib");
177 else
179 fd = open (name, O_RDONLY);
180 if (fd != -1)
181 realname = strdup (name);
184 if (fd == -1)
185 lose (errno, "cannot open shared object file");
187 /* Look again to see if the real name matched another already loaded. */
188 for (l = _dl_loaded; l; l = l->l_next)
189 if (! strcmp (realname, l->l_name))
191 /* The object is already loaded.
192 Just bump its reference count and return it. */
193 close (fd);
194 ++l->l_opencount;
195 return l;
199 /* Map in the first page to read the header. */
200 header = map (0, sizeof *header);
202 #undef LOSE
203 #define LOSE(s) lose (0, (s))
204 /* Check the header for basic validity. */
205 if (*(Elf32_Word *) &header->e_ident != ((ELFMAG0 << (EI_MAG0 * 8)) |
206 (ELFMAG1 << (EI_MAG1 * 8)) |
207 (ELFMAG2 << (EI_MAG2 * 8)) |
208 (ELFMAG3 << (EI_MAG3 * 8))))
209 LOSE ("invalid ELF header");
210 if (header->e_ident[EI_CLASS] != ELFCLASS32)
211 LOSE ("ELF file class not 32-bit");
212 if (header->e_ident[EI_DATA] != byteorder)
213 LOSE ("ELF file data encoding not " byteorder_name);
214 if (header->e_ident[EI_VERSION] != EV_CURRENT)
215 LOSE ("ELF file version ident not " STRING(EV_CURRENT));
216 if (header->e_version != EV_CURRENT)
217 LOSE ("ELF file version not " STRING(EV_CURRENT));
218 if (! elf_machine_matches_host (header->e_machine))
219 LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
220 if (header->e_phentsize != sizeof (Elf32_Phdr))
221 LOSE ("ELF file's phentsize not the expected size");
223 /* Enter the new object in the list of loaded objects. */
224 l = _dl_new_object (realname, name, lt_loaded);
225 l->l_opencount = 1;
227 if (_dl_zerofd == -1)
229 _dl_zerofd = _dl_sysdep_open_zero_fill ();
230 if (_dl_zerofd == -1)
231 _dl_signal_error (errno, NULL, "cannot open zero fill device");
235 /* Copy the program header table into stack space so we can then unmap
236 the headers. */
237 Elf32_Phdr phdr[header->e_phnum];
238 const Elf32_Phdr *ph;
239 int anywhere;
241 ph = map (header->e_phoff, header->e_phnum * sizeof (Elf32_Phdr));
242 memcpy (phdr, ph, sizeof phdr);
243 l->l_phnum = header->e_phnum;
245 anywhere = header->e_type == ET_DYN || header->e_type == ET_REL;
247 if (entry_point)
248 *entry_point = header->e_entry;
250 /* We are done reading the file's headers now. Unmap them. */
251 munmap (file_mapping, mapping_size);
253 /* Scan the program header table, processing its load commands. */
254 l->l_addr = 0;
255 l->l_ld = 0;
256 for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
257 switch (ph->p_type)
259 /* These entries tell us where to find things once the file's
260 segments are mapped in. We record the addresses it says
261 verbatim, and later correct for the run-time load address. */
262 case PT_DYNAMIC:
263 l->l_ld = (void *) ph->p_vaddr;
264 break;
265 case PT_PHDR:
266 l->l_phdr = (void *) ph->p_vaddr;
267 break;
269 case PT_LOAD:
270 /* A load command tells us to map in part of the file. */
271 if (ph->p_align % pagesize != 0)
272 LOSE ("ELF load command alignment not page-aligned");
273 if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
274 LOSE ("ELF load command address/offset not properly aligned");
276 Elf32_Addr mapstart = ph->p_vaddr & ~(ph->p_align - 1);
277 Elf32_Addr mapend = ((ph->p_vaddr + ph->p_filesz + ph->p_align - 1)
278 & ~(ph->p_align - 1));
279 off_t mapoff = ph->p_offset & ~(ph->p_align - 1);
280 caddr_t mapat;
281 int prot = 0;
282 if (ph->p_flags & PF_R)
283 prot |= PROT_READ;
284 if (ph->p_flags & PF_W)
285 prot |= PROT_WRITE;
286 if (ph->p_flags & PF_X)
287 prot |= PROT_EXEC;
289 if (anywhere)
291 /* XXX this loses if the first segment mmap call puts
292 it someplace where the later segments cannot fit. */
293 mapat = mmap ((caddr_t) (l->l_addr + mapstart),
294 mapend - mapstart,
295 prot, MAP_COPY|MAP_FILE|MAP_INHERIT |
296 /* Let the system choose any convenient
297 location if this is the first segment.
298 Following segments must be contiguous in
299 virtual space with the first. */
300 (l->l_addr == 0 ? 0 : MAP_FIXED),
301 fd, mapoff);
302 if (l->l_addr == 0)
303 /* This was the first segment mapped, so MAPAT is
304 the address the system chose for us. Record it. */
305 l->l_addr = (Elf32_Addr) mapat - mapstart;
307 else
309 mapat = mmap ((caddr_t) mapstart, mapend - mapstart,
310 prot, MAP_COPY|MAP_FILE|MAP_INHERIT|MAP_FIXED,
311 fd, mapoff);
312 /* This file refers to absolute addresses. So consider its
313 "load base" to be zero, since that is what we add to the
314 file's addresses to find them in our memory. */
315 l->l_addr = 0;
317 if (mapat == (caddr_t) -1)
318 lose (errno, "failed to map segment from shared object");
320 if (ph->p_memsz > ph->p_filesz)
322 /* Extra zero pages should appear at the end of this segment,
323 after the data mapped from the file. */
324 caddr_t zero, zeroend, zeropage;
326 mapat += ph->p_vaddr - mapstart;
327 zero = mapat + ph->p_filesz;
328 zeroend = mapat + ph->p_memsz;
329 zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
330 & ~(pagesize - 1));
332 if (zeroend < zeropage)
333 /* All the extra data is in the last page of the segment.
334 We can just zero it. */
335 zeropage = zeroend;
336 if (zeropage > zero)
338 /* Zero the final part of the last page of the segment. */
339 if ((prot & PROT_WRITE) == 0)
341 /* Dag nab it. */
342 if (mprotect ((caddr_t) ((Elf32_Addr) zero
343 & ~(pagesize - 1)),
344 pagesize,
345 prot|PROT_WRITE) < 0)
346 lose (errno, "cannot change memory protections");
348 memset (zero, 0, zeropage - zero);
349 if ((prot & PROT_WRITE) == 0)
350 mprotect ((caddr_t) ((Elf32_Addr) zero
351 & ~(pagesize - 1)),
352 pagesize, prot);
355 if (zeroend > zeropage)
356 /* Map the remaining zero pages in from the zero fill FD. */
357 mapat = mmap (zeropage, zeroend - zeropage, prot,
358 MAP_ANON|MAP_PRIVATE|MAP_FIXED|MAP_INHERIT,
359 _dl_zerofd, 0);
364 if (l->l_ld == 0)
365 LOSE ("object file has no dynamic section");
366 (Elf32_Addr) l->l_ld += l->l_addr;
368 if (l->l_phdr == 0)
369 l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
370 (Elf32_Addr) l->l_phdr += l->l_addr;
373 elf_get_dynamic_info (l->l_ld, l->l_info);
374 if (l->l_info[DT_HASH])
375 _dl_setup_hash (l);
377 return l;