(open_path): Don't do strlen on DIRPATH if it's null.
[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                 Elf32_Addr *entry_point)
109 {
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;
116
117   void lose (int code, const char *msg)
118     {
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);
123     }
124
125   /* Make sure LOCATION is mapped in.  */
126   void *map (off_t location, size_t size)
127     {
128       if ((off_t) mapping_size <= location + (off_t) size)
129         {
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;
140         }
141       return file_mapping + location;
142     }
143
144   const Elf32_Ehdr *header;
145
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))
149       {
150         /* The object is already loaded.
151            Just bump its reference count and return it.  */
152         ++l->l_opencount;
153         return l;
154       }
155
156   if (strchr (name, '/') == NULL)
157     {
158       /* Search for NAME in several places.  */
159
160       size_t namelen = strlen (name) + 1;
161
162       inline void trypath (const char *dirpath)
163         {
164           fd = open_path (name, namelen, dirpath, &realname);
165         }
166
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");
176     }
177   else
178     {
179       fd = open (name, O_RDONLY);
180       if (fd != -1)
181         realname = strdup (name);
182     }
183
184   if (fd == -1)
185     lose (errno, "cannot open shared object file");
186
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))
190       {
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;
196       }
197
198
199   /* Map in the first page to read the header.  */
200   header = map (0, sizeof *header);
201
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");
222
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;
226
227   if (_dl_zerofd == -1)
228     {
229       _dl_zerofd = _dl_sysdep_open_zero_fill ();
230       if (_dl_zerofd == -1)
231         _dl_signal_error (errno, NULL, "cannot open zero fill device");
232     }
233
234   {
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;
240
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;
244
245     anywhere = header->e_type == ET_DYN || header->e_type == ET_REL;
246
247     if (entry_point)
248       *entry_point = header->e_entry;
249
250     /* We are done reading the file's headers now.  Unmap them.  */
251     munmap (file_mapping, mapping_size);
252
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)
258         {
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;
268
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");
275           {
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;
288
289             if (anywhere)
290               {
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;
306               }
307             else
308               {
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;
316               }
317             if (mapat == (caddr_t) -1)
318               lose (errno, "failed to map segment from shared object");
319
320             if (ph->p_memsz > ph->p_filesz)
321               {
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;
325
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));
331
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)
337                   {
338                     /* Zero the final part of the last page of the segment.  */
339                     if ((prot & PROT_WRITE) == 0)
340                       {
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");
347                       }
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);
353                   }
354
355                 if (zeroend > zeropage)
356                   /* Map the remaining zero pages in from the zero fill FD.  */
357                   mapat = mmap (zeropage, zeroend - zeropage,
358                                 prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
359                                 _dl_zerofd, 0);
360               }
361           }
362         }
363
364     if (l->l_ld == 0)
365       LOSE ("object file has no dynamic section");
366     (Elf32_Addr) l->l_ld += l->l_addr;
367
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;
371   }
372
373   elf_get_dynamic_info (l->l_ld, l->l_info);
374   if (l->l_info[DT_HASH])
375     _dl_setup_hash (l);
376
377   return l;
378 }