2a50daaef735fe6308a797f75df54cebff7cae6b
[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;
251
252     ph = map (header->e_phoff, header->e_phnum * sizeof (Elf32_Phdr));
253     memcpy (phdr, ph, sizeof phdr);
254     l->l_phnum = header->e_phnum;
255
256     anywhere = header->e_type == ET_DYN || header->e_type == ET_REL;
257     /* We are done reading the file's headers now.  Unmap them.  */
258     munmap (file_mapping, mapping_size);
259
260     /* Scan the program header table, processing its load commands.  */
261     l->l_addr = 0;
262     l->l_ld = 0;
263     for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
264       switch (ph->p_type)
265         {
266           /* These entries tell us where to find things once the file's
267              segments are mapped in.  We record the addresses it says
268              verbatim, and later correct for the run-time load address.  */
269         case PT_DYNAMIC:
270           l->l_ld = (void *) ph->p_vaddr;
271           break;
272         case PT_PHDR:
273           l->l_phdr = (void *) ph->p_vaddr;
274           break;
275
276         case PT_LOAD:
277           /* A load command tells us to map in part of the file.  */
278           if (ph->p_align % pagesize != 0)
279             LOSE ("ELF load command alignment not page-aligned");
280           if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
281             LOSE ("ELF load command address/offset not properly aligned");
282           {
283             Elf32_Addr mapstart = ph->p_vaddr & ~(ph->p_align - 1);
284             Elf32_Addr mapend = ((ph->p_vaddr + ph->p_filesz + ph->p_align - 1)
285                                  & ~(ph->p_align - 1));
286             off_t mapoff = ph->p_offset & ~(ph->p_align - 1);
287             caddr_t mapat;
288             int prot = 0;
289             if (ph->p_flags & PF_R)
290               prot |= PROT_READ;
291             if (ph->p_flags & PF_W)
292               prot |= PROT_WRITE;
293             if (ph->p_flags & PF_X)
294               prot |= PROT_EXEC;
295
296             if (anywhere)
297               {
298                 /* XXX this loses if the first segment mmap call puts
299                    it someplace where the later segments cannot fit.  */
300                 mapat = mmap ((caddr_t) (l->l_addr + mapstart),
301                               mapend - mapstart,
302                               prot, MAP_COPY|MAP_FILE|MAP_INHERIT |
303                               /* Let the system choose any convenient
304                                  location if this is the first segment.
305                                  Following segments must be contiguous in
306                                  virtual space with the first.  */
307                               (l->l_addr == 0 ? 0 : MAP_FIXED),
308                               fd, mapoff);
309                 if (l->l_addr == 0)
310                   /* This was the first segment mapped, so MAPAT is
311                      the address the system chose for us.  Record it.  */
312                   l->l_addr = (Elf32_Addr) mapat - mapstart;
313               }
314             else
315               {
316                 mapat = mmap ((caddr_t) mapstart, mapend - mapstart,
317                               prot, MAP_COPY|MAP_FILE|MAP_INHERIT|MAP_FIXED,
318                               fd, mapoff);
319                 /* This file refers to absolute addresses.  So consider its
320                    "load base" to be zero, since that is what we add to the
321                    file's addresses to find them in our memory.  */
322                 l->l_addr = 0;
323               }
324             if (mapat == (caddr_t) -1)
325               lose (errno, "failed to map segment from shared object");
326
327             if (ph->p_memsz > ph->p_filesz)
328               {
329                 /* Extra zero pages should appear at the end of this segment,
330                    after the data mapped from the file.   */
331                 caddr_t zero, zeroend, zeropage;
332
333                 mapat += ph->p_vaddr - mapstart;
334                 zero = mapat + ph->p_filesz;
335                 zeroend = mapat + ph->p_memsz;
336                 zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
337                                       & ~(pagesize - 1));
338
339                 if (zeroend < zeropage)
340                   /* All the extra data is in the last page of the segment.
341                      We can just zero it.  */
342                   zeropage = zeroend;
343                 if (zeropage > zero)
344                   {
345                     /* Zero the final part of the last page of the segment.  */
346                     if ((prot & PROT_WRITE) == 0)
347                       {
348                         /* Dag nab it.  */
349                         if (mprotect ((caddr_t) ((Elf32_Addr) zero
350                                                  & ~(pagesize - 1)),
351                                       pagesize,
352                                       prot|PROT_WRITE) < 0)
353                           lose (errno, "cannot change memory protections");
354                       }
355                     memset (zero, 0, zeropage - zero);
356                     if ((prot & PROT_WRITE) == 0)
357                       mprotect ((caddr_t) ((Elf32_Addr) zero
358                                            & ~(pagesize - 1)),
359                                 pagesize, prot);
360                   }
361
362                 if (zeroend > zeropage)
363                   /* Map the remaining zero pages in from the zero fill FD.  */
364                   mapat = mmap (zeropage, zeroend - zeropage, prot,
365                                 MAP_ANON|MAP_PRIVATE|MAP_FIXED|MAP_INHERIT,
366                                 _dl_zerofd, 0);
367               }
368           }
369         }
370
371     if (l->l_ld == 0)
372       {
373         if (header->e_type == ET_DYN)
374           LOSE ("object file has no dynamic section");
375       }
376     else
377       (Elf32_Addr) l->l_ld += l->l_addr;
378
379     if (l->l_phdr == 0)
380       l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
381     (Elf32_Addr) l->l_phdr += l->l_addr;
382
383     l->l_entry = l->l_addr + header->e_entry;
384   }
385
386   elf_get_dynamic_info (l->l_ld, l->l_info);
387   if (l->l_info[DT_HASH])
388     _dl_setup_hash (l);
389
390   return l;
391 }