]>
sourceware.org Git - glibc.git/blob - elf/dl-load.c
f8b37ba34672e92ac73c097a6e095d171cd5e0b5
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"
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"
39 #error "Unknown BYTE_ORDER " BYTE_ORDER
40 #define byteorder ELFDATANONE
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. */
53 open_path (const char *name
, size_t namelen
,
57 char buf
[strlen (dirpath
) + 1 + namelen
];
62 if (p
== NULL
|| *p
== '\0')
71 p
= strpbrk (dirpath
, ":;");
73 p
= strchr (dirpath
, '\0');
76 /* Two adjacent colons, or a colon at the beginning or the end of
77 the path means to search the current directory. */
78 (void) memcpy (buf
, name
, namelen
);
81 /* Construct the pathname to try. */
82 (void) memcpy (buf
, dirpath
, p
- dirpath
);
83 buf
[p
- dirpath
] = '/';
84 (void) memcpy (&buf
[(p
- dirpath
) + 1], name
, namelen
);
87 fd
= open (buf
, O_RDONLY
);
90 *realname
= strdup (buf
);
93 if (errno
!= ENOENT
&& errno
!= EACCES
)
94 /* The file exists and is readable, but something went wrong. */
103 /* Map in the shared object file NAME. */
106 _dl_map_object (struct link_map
*loader
, const char *name
,
107 Elf32_Addr
*entry_point
)
110 struct link_map
*l
= NULL
;
112 const size_t pagesize
= getpagesize ();
113 void *file_mapping
= NULL
;
114 size_t mapping_size
= 0;
116 void lose (int code
, const char *msg
)
120 munmap (file_mapping
, mapping_size
);
121 _dl_signal_error (code
, l
? l
->l_name
: name
, msg
);
124 /* Make sure LOCATION is mapped in. */
125 void *map (off_t location
, size_t size
)
127 if ((off_t
) mapping_size
<= location
+ (off_t
) size
)
131 munmap (file_mapping
, mapping_size
);
132 mapping_size
= (location
+ size
+ 1 + pagesize
- 1);
133 mapping_size
&= ~(pagesize
- 1);
134 result
= mmap (file_mapping
, mapping_size
, PROT_READ
,
135 MAP_COPY
|MAP_FILE
, fd
, 0);
136 if (result
== (void *) -1)
137 lose (errno
, "cannot map file data");
138 file_mapping
= result
;
140 return file_mapping
+ location
;
143 const Elf32_Ehdr
*header
;
145 /* Look for this name among those already loaded. */
146 for (l
= _dl_loaded
; l
; l
= l
->l_next
)
147 if (! strcmp (name
, l
->l_libname
))
149 /* The object is already loaded.
150 Just bump its reference count and return it. */
155 if (strchr (name
, '/') == NULL
)
157 /* Search for NAME in several places. */
159 size_t namelen
= strlen (name
) + 1;
161 void trypath (const char *dirpath
)
163 fd
= open_path (name
, namelen
, dirpath
, &realname
);
166 if (loader
&& loader
->l_info
[DT_RPATH
])
167 trypath ((const char *) (loader
->l_addr
+
168 loader
->l_info
[DT_RPATH
]->d_un
.d_ptr
));
169 if (fd
== -1 && ! _dl_secure
)
170 trypath (getenv ("LD_LIBRARY_PATH"));
172 trypath ("/lib:/usr/lib");
176 fd
= open (name
, O_RDONLY
);
178 realname
= strdup (name
);
182 lose (errno
, "cannot open shared object file");
184 /* Look again to see if the real name matched another already loaded. */
185 for (l
= _dl_loaded
; l
; l
= l
->l_next
)
186 if (! strcmp (realname
, l
->l_name
))
188 /* The object is already loaded.
189 Just bump its reference count and return it. */
196 /* Map in the first page to read the header. */
197 header
= map (0, sizeof *header
);
200 #define LOSE(s) lose (0, (s))
201 /* Check the header for basic validity. */
202 if (*(Elf32_Word
*) &header
->e_ident
!= ((ELFMAG0
<< (EI_MAG0
* 8)) |
203 (ELFMAG1
<< (EI_MAG1
* 8)) |
204 (ELFMAG2
<< (EI_MAG2
* 8)) |
205 (ELFMAG3
<< (EI_MAG3
* 8))))
206 LOSE ("invalid ELF header");
207 if (header
->e_ident
[EI_CLASS
] != ELFCLASS32
)
208 LOSE ("ELF file class not 32-bit");
209 if (header
->e_ident
[EI_DATA
] != byteorder
)
210 LOSE ("ELF file data encoding not " byteorder_name
);
211 if (header
->e_ident
[EI_VERSION
] != EV_CURRENT
)
212 LOSE ("ELF file version ident not " STRING(EV_CURRENT
));
213 if (header
->e_version
!= EV_CURRENT
)
214 LOSE ("ELF file version not " STRING(EV_CURRENT
));
215 if (! elf_machine_matches_host (header
->e_machine
))
216 LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME
);
217 if (header
->e_phentsize
!= sizeof (Elf32_Phdr
))
218 LOSE ("ELF file's phentsize not the expected size");
220 /* Enter the new object in the list of loaded objects. */
221 l
= _dl_new_object (realname
, name
, lt_loaded
);
224 if (_dl_zerofd
== -1)
226 _dl_zerofd
= _dl_sysdep_open_zero_fill ();
227 if (_dl_zerofd
== -1)
228 _dl_signal_error (errno
, NULL
, "cannot open zero fill device");
232 /* Copy the program header table into stack space so we can then unmap
234 Elf32_Phdr phdr
[header
->e_phnum
];
235 const Elf32_Phdr
*ph
;
238 ph
= map (header
->e_phoff
, header
->e_phnum
* sizeof (Elf32_Phdr
));
239 memcpy (phdr
, ph
, sizeof phdr
);
240 l
->l_phnum
= header
->e_phnum
;
242 anywhere
= header
->e_type
== ET_DYN
|| header
->e_type
== ET_REL
;
245 *entry_point
= header
->e_entry
;
247 /* We are done reading the file's headers now. Unmap them. */
248 munmap (file_mapping
, mapping_size
);
250 /* Scan the program header table, processing its load commands. */
253 for (ph
= phdr
; ph
< &phdr
[l
->l_phnum
]; ++ph
)
256 /* These entries tell us where to find things once the file's
257 segments are mapped in. We record the addresses it says
258 verbatim, and later correct for the run-time load address. */
260 l
->l_ld
= (void *) ph
->p_vaddr
;
263 l
->l_phdr
= (void *) ph
->p_vaddr
;
267 /* A load command tells us to map in part of the file. */
268 if (ph
->p_align
% pagesize
!= 0)
269 LOSE ("ELF load command alignment not page-aligned");
270 if ((ph
->p_vaddr
- ph
->p_offset
) % ph
->p_align
)
271 LOSE ("ELF load command address/offset not properly aligned");
273 Elf32_Addr mapstart
= ph
->p_vaddr
& ~(ph
->p_align
- 1);
274 Elf32_Addr mapend
= ((ph
->p_vaddr
+ ph
->p_filesz
+ ph
->p_align
- 1)
275 & ~(ph
->p_align
- 1));
276 off_t mapoff
= ph
->p_offset
& ~(ph
->p_align
- 1);
279 if (ph
->p_flags
& PF_R
)
281 if (ph
->p_flags
& PF_W
)
283 if (ph
->p_flags
& PF_X
)
288 /* XXX this loses if the first segment mmap call puts
289 it someplace where the later segments cannot fit. */
290 mapat
= mmap ((caddr_t
) (l
->l_addr
+ mapstart
),
292 prot
, MAP_COPY
|MAP_FILE
|MAP_INHERIT
|
293 /* Let the system choose any convenient
294 location if this is the first segment.
295 Following segments must be contiguous in
296 virtual space with the first. */
297 (l
->l_addr
== 0 ? 0 : MAP_FIXED
),
300 /* This was the first segment mapped, so MAPAT is
301 the address the system chose for us. Record it. */
302 l
->l_addr
= (Elf32_Addr
) mapat
- mapstart
;
306 mapat
= mmap ((caddr_t
) mapstart
, mapend
- mapstart
,
307 prot
, MAP_COPY
|MAP_FILE
|MAP_INHERIT
|MAP_FIXED
,
309 /* This file refers to absolute addresses. So consider its
310 "load base" to be zero, since that is what we add to the
311 file's addresses to find them in our memory. */
314 if (mapat
== (caddr_t
) -1)
315 lose (errno
, "failed to map segment from shared object");
317 if (ph
->p_memsz
> ph
->p_filesz
)
319 /* Extra zero pages should appear at the end of this segment,
320 after the data mapped from the file. Adjust MAPEND to map
321 only the data from the file. We will later allocate zero
322 pages following the data mapping. */
323 caddr_t zero
= mapat
- mapstart
+ ph
->p_filesz
;
324 caddr_t zeroend
= mapat
- mapstart
+ ph
->p_memsz
;
326 = (caddr_t
) ((Elf32_Addr
) (zero
+ pagesize
- 1)
329 if (zeroend
< zeropage
)
330 /* All the extra data is in the last page of the segment.
331 We can just zero it. */
335 /* Zero the final part of the last page of the segment. */
336 if ((prot
& PROT_WRITE
) == 0)
339 if (mprotect ((caddr_t
) ((Elf32_Addr
) zero
342 prot
|PROT_WRITE
) < 0)
343 lose (errno
, "cannot change memory protections");
345 memset (zero
, 0, zeroend
- zero
);
346 if ((prot
& PROT_WRITE
) == 0)
347 mprotect ((caddr_t
) ((Elf32_Addr
) zero
352 if (zeroend
> zeropage
)
353 /* Map the remaining zero pages in from the zero fill FD. */
354 mapat
= mmap (zeropage
, zeroend
- zeropage
,
355 prot
, MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
,
362 LOSE ("object file has no dynamic section");
363 (Elf32_Addr
) l
->l_ld
+= l
->l_addr
;
366 l
->l_phdr
= (void *) ((const Elf32_Ehdr
*) l
->l_addr
)->e_phoff
;
367 (Elf32_Addr
) l
->l_phdr
+= l
->l_addr
;
370 elf_get_dynamic_info (l
->l_ld
, l
->l_info
);
371 if (l
->l_info
[DT_HASH
])
This page took 0.052216 seconds and 4 git commands to generate.