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. */
21 #include <sys/types.h>
28 #include "dynamic-link.h"
31 /* On some systems, no flag bits are given to specify file mapping. */
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. */
44 #define MAP_COPY MAP_PRIVATE
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"
56 #error "Unknown BYTE_ORDER " BYTE_ORDER
57 #define byteorder ELFDATANONE
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. */
70 open_path (const char *name
, size_t namelen
,
79 if (p
== NULL
|| *p
== '\0')
85 buf
= alloca (strlen (dirpath
) + 1 + namelen
);
89 p
= strpbrk (dirpath
, ":;");
91 p
= strchr (dirpath
, '\0');
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
);
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
);
108 *realname
= strdup (buf
);
111 if (errno
!= ENOENT
&& errno
!= EACCES
)
112 /* The file exists and is readable, but something went wrong. */
115 while (*p
++ != '\0');
121 /* Map in the shared object file NAME. */
124 _dl_map_object (struct link_map
*loader
, const char *name
)
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. */
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
);
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"));
160 extern const char *_dl_rpath
; /* Set in rtld.c. */
166 fd
= open (name
, O_RDONLY
);
168 realname
= strdup (name
);
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
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
)
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
,
204 if (mapat
== (caddr_t
) -1)
205 lose (errno
, "failed to map segment from shared object");
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
)
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
;
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. */
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
);
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. */
289 Elf32_Addr mapstart
, mapend
, dataend
, allocend
;
292 } loadcmds
[l
->l_phnum
], *c
;
293 size_t nloadcmds
= 0;
298 for (ph
= phdr
; ph
< &phdr
[l
->l_phnum
]; ++ph
)
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. */
305 l
->l_ld
= (void *) ph
->p_vaddr
;
308 l
->l_phdr
= (void *) ph
->p_vaddr
;
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);
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
;
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. */
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. */
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
);
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
);
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. */
391 /* Zero the final part of the last page of the segment. */
392 if ((c
->prot
& PROT_WRITE
) == 0)
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)),
405 if (zeroend
> zeropage
)
407 /* Map the remaining zero pages in from the zero fill FD. */
409 mapat
= mmap ((caddr_t
) zeropage
, zeroend
- zeropage
, c
->prot
,
410 MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
,
412 if (mapat
== (caddr_t
) -1)
413 lose (errno
, "cannot map zero-fill pages");
422 l
->l_type
= lt_executable
;
427 LOSE ("object file has no dynamic section");
430 (Elf32_Addr
) l
->l_ld
+= l
->l_addr
;
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
])