Sun Dec 17 15:56:35 1995 Miles Bader <miles@gnu.ai.mit.edu>
[glibc.git] / elf / dl-load.c
blob5f5791686d5e1d16af724e2b2b52c3e6339f4b12
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 /* On some systems, no flag bits are given to specify file mapping. */
32 #ifndef MAP_FILE
33 #define MAP_FILE 0
34 #endif
36 /* The right way to map in the shared library files is MAP_COPY, which
37 makes a virtual copy of the data at the time of the mmap call; this
38 guarantees the mapped pages will be consistent even if the file is
39 overwritten. Some losing VM systems like Linux's lack MAP_COPY. All we
40 get is MAP_PRIVATE, which copies each page when it is modified; this
41 means if the file is overwritten, we may at some point get some pages
42 from the new version after starting with pages from the old version. */
43 #ifndef MAP_COPY
44 #define MAP_COPY MAP_PRIVATE
45 #endif
48 #include <endian.h>
49 #if BYTE_ORDER == BIG_ENDIAN
50 #define byteorder ELFDATA2MSB
51 #define byteorder_name "big-endian"
52 #elif BYTE_ORDER == LITTLE_ENDIAN
53 #define byteorder ELFDATA2LSB
54 #define byteorder_name "little-endian"
55 #else
56 #error "Unknown BYTE_ORDER " BYTE_ORDER
57 #define byteorder ELFDATANONE
58 #endif
60 #define STRING(x) #x
62 int _dl_zerofd = -1;
65 /* Try to open NAME in one of the directories in DIRPATH.
66 Return the fd, or -1. If successful, fill in *REALNAME
67 with the malloc'd full directory name. */
69 static int
70 open_path (const char *name, size_t namelen,
71 const char *dirpath,
72 char **realname)
74 char *buf;
75 const char *p;
76 int fd;
78 p = dirpath;
79 if (p == NULL || *p == '\0')
81 errno = ENOENT;
82 return -1;
85 buf = alloca (strlen (dirpath) + 1 + namelen);
88 dirpath = p;
89 p = strpbrk (dirpath, ":;");
90 if (p == NULL)
91 p = strchr (dirpath, '\0');
93 if (p == dirpath)
94 /* Two adjacent colons, or a colon at the beginning or the end of
95 the path means to search the current directory. */
96 (void) memcpy (buf, name, namelen);
97 else
99 /* Construct the pathname to try. */
100 (void) memcpy (buf, dirpath, p - dirpath);
101 buf[p - dirpath] = '/';
102 (void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
105 fd = open (buf, O_RDONLY);
106 if (fd != -1)
108 *realname = strdup (buf);
109 return fd;
111 if (errno != ENOENT && errno != EACCES)
112 /* The file exists and is readable, but something went wrong. */
113 return -1;
115 while (*p++ != '\0');
117 return -1;
121 /* Map in the shared object file NAME. */
123 struct link_map *
124 _dl_map_object (struct link_map *loader, const char *name)
126 int fd;
127 char *realname;
128 struct link_map *l;
130 /* Look for this name among those already loaded. */
131 for (l = _dl_loaded; l; l = l->l_next)
132 if (! strcmp (name, l->l_libname))
134 /* The object is already loaded.
135 Just bump its reference count and return it. */
136 ++l->l_opencount;
137 return l;
140 if (strchr (name, '/') == NULL)
142 /* Search for NAME in several places. */
144 size_t namelen = strlen (name) + 1;
146 inline void trypath (const char *dirpath)
148 fd = open_path (name, namelen, dirpath, &realname);
151 fd = -1;
152 if (loader && loader->l_info[DT_RPATH])
153 trypath ((const char *) (loader->l_addr +
154 loader->l_info[DT_STRTAB]->d_un.d_ptr +
155 loader->l_info[DT_RPATH]->d_un.d_val));
156 if (fd == -1 && ! _dl_secure)
157 trypath (getenv ("LD_LIBRARY_PATH"));
158 if (fd == -1)
160 extern const char *_dl_rpath; /* Set in rtld.c. */
161 trypath (_dl_rpath);
164 else
166 fd = open (name, O_RDONLY);
167 if (fd != -1)
168 realname = strdup (name);
171 if (fd == -1)
172 _dl_signal_error (errno, name, "cannot open shared object file");
174 return _dl_map_object_from_fd (name, fd, realname);
178 /* Map in the shared object NAME, actually located in REALNAME, and already
179 opened on FD. */
181 struct link_map *
182 _dl_map_object_from_fd (const char *name, int fd, char *realname)
184 struct link_map *l = NULL;
185 const size_t pagesize = getpagesize ();
186 void *file_mapping = NULL;
187 size_t mapping_size = 0;
189 #define LOSE(s) lose (0, (s))
190 void lose (int code, const char *msg)
192 (void) close (fd);
193 if (file_mapping)
194 munmap (file_mapping, mapping_size);
195 _dl_signal_error (code, l ? l->l_name : name, msg);
198 inline caddr_t map_segment (Elf32_Addr mapstart, size_t len,
199 int prot, int fixed, off_t offset)
201 caddr_t mapat = mmap ((caddr_t) mapstart, len, prot,
202 fixed|MAP_COPY|MAP_FILE,
203 fd, offset);
204 if (mapat == (caddr_t) -1)
205 lose (errno, "failed to map segment from shared object");
206 return mapat;
209 /* Make sure LOCATION is mapped in. */
210 void *map (off_t location, size_t size)
212 if ((off_t) mapping_size <= location + (off_t) size)
214 void *result;
215 if (file_mapping)
216 munmap (file_mapping, mapping_size);
217 mapping_size = (location + size + 1 + pagesize - 1);
218 mapping_size &= ~(pagesize - 1);
219 result = mmap (file_mapping, mapping_size, PROT_READ,
220 MAP_COPY|MAP_FILE, fd, 0);
221 if (result == (void *) -1)
222 lose (errno, "cannot map file data");
223 file_mapping = result;
225 return file_mapping + location;
228 const Elf32_Ehdr *header;
229 const Elf32_Phdr *phdr;
230 const Elf32_Phdr *ph;
231 int type;
233 /* Look again to see if the real name matched another already loaded. */
234 for (l = _dl_loaded; l; l = l->l_next)
235 if (! strcmp (realname, l->l_name))
237 /* The object is already loaded.
238 Just bump its reference count and return it. */
239 close (fd);
240 free (realname);
241 ++l->l_opencount;
242 return l;
245 /* Map in the first page to read the header. */
246 header = map (0, sizeof *header);
248 /* Check the header for basic validity. */
249 if (*(Elf32_Word *) &header->e_ident != ((ELFMAG0 << (EI_MAG0 * 8)) |
250 (ELFMAG1 << (EI_MAG1 * 8)) |
251 (ELFMAG2 << (EI_MAG2 * 8)) |
252 (ELFMAG3 << (EI_MAG3 * 8))))
253 LOSE ("invalid ELF header");
254 if (header->e_ident[EI_CLASS] != ELFCLASS32)
255 LOSE ("ELF file class not 32-bit");
256 if (header->e_ident[EI_DATA] != byteorder)
257 LOSE ("ELF file data encoding not " byteorder_name);
258 if (header->e_ident[EI_VERSION] != EV_CURRENT)
259 LOSE ("ELF file version ident not " STRING(EV_CURRENT));
260 if (header->e_version != EV_CURRENT)
261 LOSE ("ELF file version not " STRING(EV_CURRENT));
262 if (! elf_machine_matches_host (header->e_machine))
263 LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
264 if (header->e_phentsize != sizeof (Elf32_Phdr))
265 LOSE ("ELF file's phentsize not the expected size");
267 /* Enter the new object in the list of loaded objects. */
268 l = _dl_new_object (realname, name, lt_loaded);
269 l->l_opencount = 1;
271 if (_dl_zerofd == -1)
273 _dl_zerofd = _dl_sysdep_open_zero_fill ();
274 if (_dl_zerofd == -1)
275 _dl_signal_error (errno, NULL, "cannot open zero fill device");
278 /* Extract the remaining details we need from the ELF header
279 and then map in the program header table. */
280 l->l_entry = header->e_entry;
281 type = header->e_type;
282 l->l_phnum = header->e_phnum;
283 phdr = map (header->e_phoff, l->l_phnum * sizeof (Elf32_Phdr));
286 /* Scan the program header table, collecting its load commands. */
287 struct loadcmd
289 Elf32_Addr mapstart, mapend, dataend, allocend;
290 off_t mapoff;
291 int prot;
292 } loadcmds[l->l_phnum], *c;
293 size_t nloadcmds = 0;
295 l->l_ld = 0;
296 l->l_phdr = 0;
297 l->l_addr = 0;
298 for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
299 switch (ph->p_type)
301 /* These entries tell us where to find things once the file's
302 segments are mapped in. We record the addresses it says
303 verbatim, and later correct for the run-time load address. */
304 case PT_DYNAMIC:
305 l->l_ld = (void *) ph->p_vaddr;
306 break;
307 case PT_PHDR:
308 l->l_phdr = (void *) ph->p_vaddr;
309 break;
311 case PT_LOAD:
312 /* A load command tells us to map in part of the file.
313 We record the load commands and process them all later. */
314 if (ph->p_align % pagesize != 0)
315 LOSE ("ELF load command alignment not page-aligned");
316 if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
317 LOSE ("ELF load command address/offset not properly aligned");
319 struct loadcmd *c = &loadcmds[nloadcmds++];
320 c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
321 c->mapend = ((ph->p_vaddr + ph->p_filesz + ph->p_align - 1)
322 & ~(ph->p_align - 1));
323 c->dataend = ph->p_vaddr + ph->p_filesz;
324 c->allocend = ph->p_vaddr + ph->p_memsz;
325 c->mapoff = ph->p_offset & ~(ph->p_align - 1);
326 c->prot = 0;
327 if (ph->p_flags & PF_R)
328 c->prot |= PROT_READ;
329 if (ph->p_flags & PF_W)
330 c->prot |= PROT_WRITE;
331 if (ph->p_flags & PF_X)
332 c->prot |= PROT_EXEC;
333 break;
337 /* We are done reading the file's headers now. Unmap them. */
338 munmap (file_mapping, mapping_size);
340 /* Now process the load commands and map segments into memory. */
341 c = loadcmds;
343 if (type == ET_DYN || type == ET_REL)
345 /* This is a position-independent shared object. We can let the
346 kernel map it anywhere it likes, but we must have space for all
347 the segments in their specified positions relative to the first.
348 So we map the first segment without MAP_FIXED, but with its
349 extent increased to cover all the segments. Then we unmap the
350 excess portion, and there is known sufficient space there to map
351 the later segments. */
352 caddr_t mapat;
353 mapat = map_segment (c->mapstart,
354 loadcmds[nloadcmds - 1].allocend - c->mapstart,
355 c->prot, 0, c->mapoff);
356 l->l_addr = (Elf32_Addr) mapat - c->mapstart;
358 /* Unmap the excess portion, and then jump into the normal
359 segment-mapping loop to handle the portion of the segment past
360 the end of the file mapping. */
361 munmap (mapat + c->mapend,
362 loadcmds[nloadcmds - 1].allocend - c->mapend);
363 goto postmap;
366 while (c < &loadcmds[nloadcmds])
368 if (c->mapend > c->mapstart)
369 /* Map the segment contents from the file. */
370 map_segment (l->l_addr + c->mapstart, c->mapend - c->mapstart,
371 c->prot, MAP_FIXED, c->mapoff);
373 postmap:
374 if (c->allocend > c->dataend)
376 /* Extra zero pages should appear at the end of this segment,
377 after the data mapped from the file. */
378 Elf32_Addr zero, zeroend, zeropage;
380 zero = l->l_addr + c->dataend;
381 zeroend = l->l_addr + c->allocend;
382 zeropage = (zero + pagesize - 1) & ~(pagesize - 1);
384 if (zeroend < zeropage)
385 /* All the extra data is in the last page of the segment.
386 We can just zero it. */
387 zeropage = zeroend;
389 if (zeropage > zero)
391 /* Zero the final part of the last page of the segment. */
392 if ((c->prot & PROT_WRITE) == 0)
394 /* Dag nab it. */
395 if (mprotect ((caddr_t) (zero & ~(pagesize - 1)),
396 pagesize, c->prot|PROT_WRITE) < 0)
397 lose (errno, "cannot change memory protections");
399 memset ((void *) zero, 0, zeropage - zero);
400 if ((c->prot & PROT_WRITE) == 0)
401 mprotect ((caddr_t) (zero & ~(pagesize - 1)),
402 pagesize, c->prot);
405 if (zeroend > zeropage)
407 /* Map the remaining zero pages in from the zero fill FD. */
408 caddr_t mapat;
409 mapat = mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
410 MAP_ANON|MAP_PRIVATE|MAP_FIXED,
411 _dl_zerofd, 0);
412 if (mapat == (caddr_t) -1)
413 lose (errno, "cannot map zero-fill pages");
417 ++c;
421 if (type == ET_EXEC)
422 l->l_type = lt_executable;
424 if (l->l_ld == 0)
426 if (type == ET_DYN)
427 LOSE ("object file has no dynamic section");
429 else
430 (Elf32_Addr) l->l_ld += l->l_addr;
432 if (l->l_phdr == 0)
433 l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
434 (Elf32_Addr) l->l_phdr += l->l_addr;
436 elf_get_dynamic_info (l->l_ld, l->l_info);
437 if (l->l_info[DT_HASH])
438 _dl_setup_hash (l);
440 return l;