]>
sourceware.org Git - glibc.git/blob - 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.
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 inline void trypath (const char *dirpath
)
163 fd
= open_path (name
, namelen
, dirpath
, &realname
);
167 if (loader
&& loader
->l_info
[DT_RPATH
])
168 trypath ((const char *) (loader
->l_addr
+
169 loader
->l_info
[DT_RPATH
]->d_un
.d_ptr
));
170 if (fd
== -1 && ! _dl_secure
)
171 trypath (getenv ("LD_LIBRARY_PATH"));
173 trypath ("/lib:/usr/lib");
177 fd
= open (name
, O_RDONLY
);
179 realname
= strdup (name
);
183 lose (errno
, "cannot open shared object file");
185 /* Look again to see if the real name matched another already loaded. */
186 for (l
= _dl_loaded
; l
; l
= l
->l_next
)
187 if (! strcmp (realname
, l
->l_name
))
189 /* The object is already loaded.
190 Just bump its reference count and return it. */
197 /* Map in the first page to read the header. */
198 header
= map (0, sizeof *header
);
201 #define LOSE(s) lose (0, (s))
202 /* Check the header for basic validity. */
203 if (*(Elf32_Word
*) &header
->e_ident
!= ((ELFMAG0
<< (EI_MAG0
* 8)) |
204 (ELFMAG1
<< (EI_MAG1
* 8)) |
205 (ELFMAG2
<< (EI_MAG2
* 8)) |
206 (ELFMAG3
<< (EI_MAG3
* 8))))
207 LOSE ("invalid ELF header");
208 if (header
->e_ident
[EI_CLASS
] != ELFCLASS32
)
209 LOSE ("ELF file class not 32-bit");
210 if (header
->e_ident
[EI_DATA
] != byteorder
)
211 LOSE ("ELF file data encoding not " byteorder_name
);
212 if (header
->e_ident
[EI_VERSION
] != EV_CURRENT
)
213 LOSE ("ELF file version ident not " STRING(EV_CURRENT
));
214 if (header
->e_version
!= EV_CURRENT
)
215 LOSE ("ELF file version not " STRING(EV_CURRENT
));
216 if (! elf_machine_matches_host (header
->e_machine
))
217 LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME
);
218 if (header
->e_phentsize
!= sizeof (Elf32_Phdr
))
219 LOSE ("ELF file's phentsize not the expected size");
221 /* Enter the new object in the list of loaded objects. */
222 l
= _dl_new_object (realname
, name
, lt_loaded
);
225 if (_dl_zerofd
== -1)
227 _dl_zerofd
= _dl_sysdep_open_zero_fill ();
228 if (_dl_zerofd
== -1)
229 _dl_signal_error (errno
, NULL
, "cannot open zero fill device");
233 /* Copy the program header table into stack space so we can then unmap
235 Elf32_Phdr phdr
[header
->e_phnum
];
236 const Elf32_Phdr
*ph
;
239 ph
= map (header
->e_phoff
, header
->e_phnum
* sizeof (Elf32_Phdr
));
240 memcpy (phdr
, ph
, sizeof phdr
);
241 l
->l_phnum
= header
->e_phnum
;
243 anywhere
= header
->e_type
== ET_DYN
|| header
->e_type
== ET_REL
;
246 *entry_point
= header
->e_entry
;
248 /* We are done reading the file's headers now. Unmap them. */
249 munmap (file_mapping
, mapping_size
);
251 /* Scan the program header table, processing its load commands. */
254 for (ph
= phdr
; ph
< &phdr
[l
->l_phnum
]; ++ph
)
257 /* These entries tell us where to find things once the file's
258 segments are mapped in. We record the addresses it says
259 verbatim, and later correct for the run-time load address. */
261 l
->l_ld
= (void *) ph
->p_vaddr
;
264 l
->l_phdr
= (void *) ph
->p_vaddr
;
268 /* A load command tells us to map in part of the file. */
269 if (ph
->p_align
% pagesize
!= 0)
270 LOSE ("ELF load command alignment not page-aligned");
271 if ((ph
->p_vaddr
- ph
->p_offset
) % ph
->p_align
)
272 LOSE ("ELF load command address/offset not properly aligned");
274 Elf32_Addr mapstart
= ph
->p_vaddr
& ~(ph
->p_align
- 1);
275 Elf32_Addr mapend
= ((ph
->p_vaddr
+ ph
->p_filesz
+ ph
->p_align
- 1)
276 & ~(ph
->p_align
- 1));
277 off_t mapoff
= ph
->p_offset
& ~(ph
->p_align
- 1);
280 if (ph
->p_flags
& PF_R
)
282 if (ph
->p_flags
& PF_W
)
284 if (ph
->p_flags
& PF_X
)
289 /* XXX this loses if the first segment mmap call puts
290 it someplace where the later segments cannot fit. */
291 mapat
= mmap ((caddr_t
) (l
->l_addr
+ mapstart
),
293 prot
, MAP_COPY
|MAP_FILE
|MAP_INHERIT
|
294 /* Let the system choose any convenient
295 location if this is the first segment.
296 Following segments must be contiguous in
297 virtual space with the first. */
298 (l
->l_addr
== 0 ? 0 : MAP_FIXED
),
301 /* This was the first segment mapped, so MAPAT is
302 the address the system chose for us. Record it. */
303 l
->l_addr
= (Elf32_Addr
) mapat
- mapstart
;
307 mapat
= mmap ((caddr_t
) mapstart
, mapend
- mapstart
,
308 prot
, MAP_COPY
|MAP_FILE
|MAP_INHERIT
|MAP_FIXED
,
310 /* This file refers to absolute addresses. So consider its
311 "load base" to be zero, since that is what we add to the
312 file's addresses to find them in our memory. */
315 if (mapat
== (caddr_t
) -1)
316 lose (errno
, "failed to map segment from shared object");
318 if (ph
->p_memsz
> ph
->p_filesz
)
320 /* Extra zero pages should appear at the end of this segment,
321 after the data mapped from the file. */
322 caddr_t zero
, zeroend
, zeropage
;
324 mapat
+= ph
->p_vaddr
- mapstart
;
325 zero
= mapat
+ ph
->p_filesz
;
326 zeroend
= mapat
+ ph
->p_memsz
;
327 zeropage
= (caddr_t
) ((Elf32_Addr
) (zero
+ pagesize
- 1)
330 if (zeroend
< zeropage
)
331 /* All the extra data is in the last page of the segment.
332 We can just zero it. */
336 /* Zero the final part of the last page of the segment. */
337 if ((prot
& PROT_WRITE
) == 0)
340 if (mprotect ((caddr_t
) ((Elf32_Addr
) zero
343 prot
|PROT_WRITE
) < 0)
344 lose (errno
, "cannot change memory protections");
346 memset (zero
, 0, zeropage
- zero
);
347 if ((prot
& PROT_WRITE
) == 0)
348 mprotect ((caddr_t
) ((Elf32_Addr
) zero
353 if (zeroend
> zeropage
)
354 /* Map the remaining zero pages in from the zero fill FD. */
355 mapat
= mmap (zeropage
, zeroend
- zeropage
,
356 prot
, MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
,
363 LOSE ("object file has no dynamic section");
364 (Elf32_Addr
) l
->l_ld
+= l
->l_addr
;
367 l
->l_phdr
= (void *) ((const Elf32_Ehdr
*) l
->l_addr
)->e_phoff
;
368 (Elf32_Addr
) l
->l_phdr
+= l
->l_addr
;
371 elf_get_dynamic_info (l
->l_ld
, l
->l_info
);
372 if (l
->l_info
[DT_HASH
])
This page took 0.055424 seconds and 5 git commands to generate.