(_dl_map_object_from_fd): Do all accesses to HEADER before unmapping the
[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 #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
42
43 #define STRING(x) #x
44
45 int _dl_zerofd = -1;
46
47
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.  */
51
52 static int
53 open_path (const char *name, size_t namelen,
54            const char *dirpath,
55            char **realname)
56 {
57   char *buf;
58   const char *p;
59   int fd;
60
61   p = dirpath;
62   if (p == NULL || *p == '\0')
63     {
64       errno = ENOENT;
65       return -1;
66     }
67
68   buf = alloca (strlen (dirpath) + 1 + namelen);
69   do
70     {
71       dirpath = p;
72       p = strpbrk (dirpath, ":;");
73       if (p == NULL)
74         p = strchr (dirpath, '\0');
75
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
81         {
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);
86         }
87
88       fd = open (buf, O_RDONLY);
89       if (fd != -1)
90         {
91           *realname = strdup (buf);
92           return fd;
93         }
94       if (errno != ENOENT && errno != EACCES)
95         /* The file exists and is readable, but something went wrong.  */
96         return -1;
97     }
98   while (*p++ != '\0');
99
100   return -1;
101 }
102
103
104 /* Map in the shared object file NAME.  */
105
106 struct link_map *
107 _dl_map_object (struct link_map *loader, const char *name)
108 {
109   int fd;
110   char *realname;
111   struct link_map *l;
112
113   /* Look for this name among those already loaded.  */
114   for (l = _dl_loaded; l; l = l->l_next)
115     if (! strcmp (name, l->l_libname))
116       {
117         /* The object is already loaded.
118            Just bump its reference count and return it.  */
119         ++l->l_opencount;
120         return l;
121       }
122
123   if (strchr (name, '/') == NULL)
124     {
125       /* Search for NAME in several places.  */
126
127       size_t namelen = strlen (name) + 1;
128
129       inline void trypath (const char *dirpath)
130         {
131           fd = open_path (name, namelen, dirpath, &realname);
132         }
133
134       fd = -1;
135       if (loader && loader->l_info[DT_RPATH])
136         trypath ((const char *) (loader->l_addr +
137                                  loader->l_info[DT_STRTAB]->d_un.d_ptr +
138                                  loader->l_info[DT_RPATH]->d_un.d_val));
139       if (fd == -1 && ! _dl_secure)
140         trypath (getenv ("LD_LIBRARY_PATH"));
141       if (fd == -1)
142         trypath ("/lib:/usr/lib");
143     }
144   else
145     {
146       fd = open (name, O_RDONLY);
147       if (fd != -1)
148         realname = strdup (name);
149     }
150
151   if (fd == -1)
152     _dl_signal_error (errno, name, "cannot open shared object file");
153
154   return _dl_map_object_from_fd (name, fd, realname);
155 }
156
157
158 /* Map in the shared object NAME, actually located in REALNAME, and already
159    opened on FD.  */
160
161 struct link_map *
162 _dl_map_object_from_fd (const char *name, int fd, char *realname)
163 {
164   struct link_map *l = NULL;
165   const size_t pagesize = getpagesize ();
166   void *file_mapping = NULL;
167   size_t mapping_size = 0;
168
169   void lose (int code, const char *msg)
170     {
171       (void) close (fd);
172       if (file_mapping)
173         munmap (file_mapping, mapping_size);
174       _dl_signal_error (code, l ? l->l_name : name, msg);
175     }
176
177   /* Make sure LOCATION is mapped in.  */
178   void *map (off_t location, size_t size)
179     {
180       if ((off_t) mapping_size <= location + (off_t) size)
181         {
182           void *result;
183           if (file_mapping)
184             munmap (file_mapping, mapping_size);
185           mapping_size = (location + size + 1 + pagesize - 1);
186           mapping_size &= ~(pagesize - 1);
187           result = mmap (file_mapping, mapping_size, PROT_READ,
188                          MAP_COPY|MAP_FILE, fd, 0);
189           if (result == (void *) -1)
190             lose (errno, "cannot map file data");
191           file_mapping = result;
192         }
193       return file_mapping + location;
194     }
195
196   const Elf32_Ehdr *header;
197
198   /* Look again to see if the real name matched another already loaded.  */
199   for (l = _dl_loaded; l; l = l->l_next)
200     if (! strcmp (realname, l->l_name))
201       {
202         /* The object is already loaded.
203            Just bump its reference count and return it.  */
204         close (fd);
205         free (realname);
206         ++l->l_opencount;
207         return l;
208       }
209
210   /* Map in the first page to read the header.  */
211   header = map (0, sizeof *header);
212
213 #undef LOSE
214 #define LOSE(s) lose (0, (s))
215   /* Check the header for basic validity.  */
216   if (*(Elf32_Word *) &header->e_ident != ((ELFMAG0 << (EI_MAG0 * 8)) |
217                                            (ELFMAG1 << (EI_MAG1 * 8)) |
218                                            (ELFMAG2 << (EI_MAG2 * 8)) |
219                                            (ELFMAG3 << (EI_MAG3 * 8))))
220     LOSE ("invalid ELF header");
221   if (header->e_ident[EI_CLASS] != ELFCLASS32)
222     LOSE ("ELF file class not 32-bit");
223   if (header->e_ident[EI_DATA] != byteorder)
224     LOSE ("ELF file data encoding not " byteorder_name);
225   if (header->e_ident[EI_VERSION] != EV_CURRENT)
226     LOSE ("ELF file version ident not " STRING(EV_CURRENT));
227   if (header->e_version != EV_CURRENT)
228     LOSE ("ELF file version not " STRING(EV_CURRENT));
229   if (! elf_machine_matches_host (header->e_machine))
230     LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
231   if (header->e_phentsize != sizeof (Elf32_Phdr))
232     LOSE ("ELF file's phentsize not the expected size");
233
234   /* Enter the new object in the list of loaded objects.  */
235   l = _dl_new_object (realname, name, lt_loaded);
236   l->l_opencount = 1;
237
238   if (_dl_zerofd == -1)
239     {
240       _dl_zerofd = _dl_sysdep_open_zero_fill ();
241       if (_dl_zerofd == -1)
242         _dl_signal_error (errno, NULL, "cannot open zero fill device");
243     }
244
245   {
246     /* Copy the program header table into stack space so we can then unmap
247        the headers.  */
248     Elf32_Phdr phdr[header->e_phnum];
249     const Elf32_Phdr *ph;
250     int anywhere, type;
251
252     type = header->e_type;
253     anywhere = type == ET_DYN || type == ET_REL;
254     l->l_entry = header->e_entry;
255
256     ph = map (header->e_phoff, header->e_phnum * sizeof (Elf32_Phdr));
257     memcpy (phdr, ph, sizeof phdr);
258     l->l_phnum = header->e_phnum;
259
260     /* We are done reading the file's headers now.  Unmap them.  */
261     munmap (file_mapping, mapping_size);
262
263     /* Scan the program header table, processing its load commands.  */
264     l->l_addr = 0;
265     l->l_ld = 0;
266     for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
267       switch (ph->p_type)
268         {
269           /* These entries tell us where to find things once the file's
270              segments are mapped in.  We record the addresses it says
271              verbatim, and later correct for the run-time load address.  */
272         case PT_DYNAMIC:
273           l->l_ld = (void *) ph->p_vaddr;
274           break;
275         case PT_PHDR:
276           l->l_phdr = (void *) ph->p_vaddr;
277           break;
278
279         case PT_LOAD:
280           /* A load command tells us to map in part of the file.  */
281           if (ph->p_align % pagesize != 0)
282             LOSE ("ELF load command alignment not page-aligned");
283           if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
284             LOSE ("ELF load command address/offset not properly aligned");
285           {
286             Elf32_Addr mapstart = ph->p_vaddr & ~(ph->p_align - 1);
287             Elf32_Addr mapend = ((ph->p_vaddr + ph->p_filesz + ph->p_align - 1)
288                                  & ~(ph->p_align - 1));
289             off_t mapoff = ph->p_offset & ~(ph->p_align - 1);
290             caddr_t mapat;
291             int prot = 0;
292             if (ph->p_flags & PF_R)
293               prot |= PROT_READ;
294             if (ph->p_flags & PF_W)
295               prot |= PROT_WRITE;
296             if (ph->p_flags & PF_X)
297               prot |= PROT_EXEC;
298
299             if (anywhere)
300               {
301                 /* XXX this loses if the first segment mmap call puts
302                    it someplace where the later segments cannot fit.  */
303                 mapat = mmap ((caddr_t) (l->l_addr + mapstart),
304                               mapend - mapstart,
305                               prot, MAP_COPY|MAP_FILE|MAP_INHERIT |
306                               /* Let the system choose any convenient
307                                  location if this is the first segment.
308                                  Following segments must be contiguous in
309                                  virtual space with the first.  */
310                               (l->l_addr == 0 ? 0 : MAP_FIXED),
311                               fd, mapoff);
312                 if (l->l_addr == 0)
313                   /* This was the first segment mapped, so MAPAT is
314                      the address the system chose for us.  Record it.  */
315                   l->l_addr = (Elf32_Addr) mapat - mapstart;
316               }
317             else
318               {
319                 mapat = mmap ((caddr_t) mapstart, mapend - mapstart,
320                               prot, MAP_COPY|MAP_FILE|MAP_INHERIT|MAP_FIXED,
321                               fd, mapoff);
322                 /* This file refers to absolute addresses.  So consider its
323                    "load base" to be zero, since that is what we add to the
324                    file's addresses to find them in our memory.  */
325                 l->l_addr = 0;
326               }
327             if (mapat == (caddr_t) -1)
328               lose (errno, "failed to map segment from shared object");
329
330             if (ph->p_memsz > ph->p_filesz)
331               {
332                 /* Extra zero pages should appear at the end of this segment,
333                    after the data mapped from the file.   */
334                 caddr_t zero, zeroend, zeropage;
335
336                 mapat += ph->p_vaddr - mapstart;
337                 zero = mapat + ph->p_filesz;
338                 zeroend = mapat + ph->p_memsz;
339                 zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
340                                       & ~(pagesize - 1));
341
342                 if (zeroend < zeropage)
343                   /* All the extra data is in the last page of the segment.
344                      We can just zero it.  */
345                   zeropage = zeroend;
346                 if (zeropage > zero)
347                   {
348                     /* Zero the final part of the last page of the segment.  */
349                     if ((prot & PROT_WRITE) == 0)
350                       {
351                         /* Dag nab it.  */
352                         if (mprotect ((caddr_t) ((Elf32_Addr) zero
353                                                  & ~(pagesize - 1)),
354                                       pagesize,
355                                       prot|PROT_WRITE) < 0)
356                           lose (errno, "cannot change memory protections");
357                       }
358                     memset (zero, 0, zeropage - zero);
359                     if ((prot & PROT_WRITE) == 0)
360                       mprotect ((caddr_t) ((Elf32_Addr) zero
361                                            & ~(pagesize - 1)),
362                                 pagesize, prot);
363                   }
364
365                 if (zeroend > zeropage)
366                   /* Map the remaining zero pages in from the zero fill FD.  */
367                   mapat = mmap (zeropage, zeroend - zeropage, prot,
368                                 MAP_ANON|MAP_PRIVATE|MAP_FIXED|MAP_INHERIT,
369                                 _dl_zerofd, 0);
370               }
371           }
372         }
373
374     if (l->l_ld == 0)
375       {
376         if (type == ET_DYN)
377           LOSE ("object file has no dynamic section");
378       }
379     else
380       (Elf32_Addr) l->l_ld += l->l_addr;
381
382     if (l->l_phdr == 0)
383       l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
384     (Elf32_Addr) l->l_phdr += l->l_addr;
385
386     l->l_entry += l->l_addr;
387   }
388
389   elf_get_dynamic_info (l->l_ld, l->l_info);
390   if (l->l_info[DT_HASH])
391     _dl_setup_hash (l);
392
393   return l;
394 }