5f5791686d5e1d16af724e2b2b52c3e6339f4b12
[kopensolaris-gnu/glibc.git] / elf / dl-load.c
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.
4
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.
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 Library General Public License for more details.
14
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.  */
19
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"
29
30
31 /* On some systems, no flag bits are given to specify file mapping.  */
32 #ifndef MAP_FILE
33 #define MAP_FILE        0
34 #endif
35
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
46
47
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
59
60 #define STRING(x) #x
61
62 int _dl_zerofd = -1;
63
64
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.  */
68
69 static int
70 open_path (const char *name, size_t namelen,
71            const char *dirpath,
72            char **realname)
73 {
74   char *buf;
75   const char *p;
76   int fd;
77
78   p = dirpath;
79   if (p == NULL || *p == '\0')
80     {
81       errno = ENOENT;
82       return -1;
83     }
84
85   buf = alloca (strlen (dirpath) + 1 + namelen);
86   do
87     {
88       dirpath = p;
89       p = strpbrk (dirpath, ":;");
90       if (p == NULL)
91         p = strchr (dirpath, '\0');
92
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
98         {
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);
103         }
104
105       fd = open (buf, O_RDONLY);
106       if (fd != -1)
107         {
108           *realname = strdup (buf);
109           return fd;
110         }
111       if (errno != ENOENT && errno != EACCES)
112         /* The file exists and is readable, but something went wrong.  */
113         return -1;
114     }
115   while (*p++ != '\0');
116
117   return -1;
118 }
119
120
121 /* Map in the shared object file NAME.  */
122
123 struct link_map *
124 _dl_map_object (struct link_map *loader, const char *name)
125 {
126   int fd;
127   char *realname;
128   struct link_map *l;
129
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))
133       {
134         /* The object is already loaded.
135            Just bump its reference count and return it.  */
136         ++l->l_opencount;
137         return l;
138       }
139
140   if (strchr (name, '/') == NULL)
141     {
142       /* Search for NAME in several places.  */
143
144       size_t namelen = strlen (name) + 1;
145
146       inline void trypath (const char *dirpath)
147         {
148           fd = open_path (name, namelen, dirpath, &realname);
149         }
150
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)
159         {
160           extern const char *_dl_rpath; /* Set in rtld.c. */
161           trypath (_dl_rpath);
162         }
163     }
164   else
165     {
166       fd = open (name, O_RDONLY);
167       if (fd != -1)
168         realname = strdup (name);
169     }
170
171   if (fd == -1)
172     _dl_signal_error (errno, name, "cannot open shared object file");
173
174   return _dl_map_object_from_fd (name, fd, realname);
175 }
176
177
178 /* Map in the shared object NAME, actually located in REALNAME, and already
179    opened on FD.  */
180
181 struct link_map *
182 _dl_map_object_from_fd (const char *name, int fd, char *realname)
183 {
184   struct link_map *l = NULL;
185   const size_t pagesize = getpagesize ();
186   void *file_mapping = NULL;
187   size_t mapping_size = 0;
188
189 #define LOSE(s) lose (0, (s))
190   void lose (int code, const char *msg)
191     {
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);
196     }
197
198   inline caddr_t map_segment (Elf32_Addr mapstart, size_t len,
199                               int prot, int fixed, off_t offset)
200     {
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;
207     }
208
209   /* Make sure LOCATION is mapped in.  */
210   void *map (off_t location, size_t size)
211     {
212       if ((off_t) mapping_size <= location + (off_t) size)
213         {
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;
224         }
225       return file_mapping + location;
226     }
227
228   const Elf32_Ehdr *header;
229   const Elf32_Phdr *phdr;
230   const Elf32_Phdr *ph;
231   int type;
232
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))
236       {
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;
243       }
244
245   /* Map in the first page to read the header.  */
246   header = map (0, sizeof *header);
247
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");
266
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;
270
271   if (_dl_zerofd == -1)
272     {
273       _dl_zerofd = _dl_sysdep_open_zero_fill ();
274       if (_dl_zerofd == -1)
275         _dl_signal_error (errno, NULL, "cannot open zero fill device");
276     }
277
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));
284
285   {
286     /* Scan the program header table, collecting its load commands.  */
287     struct loadcmd
288       {
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;
294
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)
300         {
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;
310
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");
318           {
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;
334           }
335         }
336
337     /* We are done reading the file's headers now.  Unmap them.  */
338     munmap (file_mapping, mapping_size);
339
340     /* Now process the load commands and map segments into memory.  */
341     c = loadcmds;
342
343     if (type == ET_DYN || type == ET_REL)
344       {
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;
357
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;
364       }
365
366     while (c < &loadcmds[nloadcmds])
367       {
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);
372
373       postmap:
374         if (c->allocend > c->dataend)
375           {
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;
379
380             zero = l->l_addr + c->dataend;
381             zeroend = l->l_addr + c->allocend;
382             zeropage = (zero + pagesize - 1) & ~(pagesize - 1);
383
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;
388
389             if (zeropage > zero)
390               {
391                 /* Zero the final part of the last page of the segment.  */
392                 if ((c->prot & PROT_WRITE) == 0)
393                   {
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");
398                   }
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);
403               }
404
405             if (zeroend > zeropage)
406               {
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");
414               }
415           }
416
417         ++c;
418       }
419   }
420
421   if (type == ET_EXEC)
422     l->l_type = lt_executable;
423
424   if (l->l_ld == 0)
425     {
426       if (type == ET_DYN)
427         LOSE ("object file has no dynamic section");
428     }
429   else
430     (Elf32_Addr) l->l_ld += l->l_addr;
431
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;
435
436   elf_get_dynamic_info (l->l_ld, l->l_info);
437   if (l->l_info[DT_HASH])
438     _dl_setup_hash (l);
439
440   return l;
441 }