Changeset View
Changeset View
Standalone View
Standalone View
head/libexec/rtld-elf/map_object.c
Show All 34 Lines | |||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "rtld.h" | #include "rtld.h" | ||||
static Elf_Ehdr *get_elf_header(int, const char *, const struct stat *); | static Elf_Ehdr *get_elf_header(int, const char *, const struct stat *, | ||||
Elf_Phdr **phdr); | |||||
static int convert_flags(int); /* Elf flags -> mmap flags */ | static int convert_flags(int); /* Elf flags -> mmap flags */ | ||||
int __getosreldate(void); | int __getosreldate(void); | ||||
static bool | |||||
phdr_in_zero_page(const Elf_Ehdr *hdr) | |||||
{ | |||||
return (hdr->e_phoff + hdr->e_phnum * sizeof(Elf_Phdr) < | |||||
(size_t)PAGE_SIZE); | |||||
} | |||||
/* | /* | ||||
* Map a shared object into memory. The "fd" argument is a file descriptor, | * Map a shared object into memory. The "fd" argument is a file descriptor, | ||||
* which must be open on the object and positioned at its beginning. | * which must be open on the object and positioned at its beginning. | ||||
* The "path" argument is a pathname that is used only for error messages. | * The "path" argument is a pathname that is used only for error messages. | ||||
* | * | ||||
* The return value is a pointer to a newly-allocated Obj_Entry structure | * The return value is a pointer to a newly-allocated Obj_Entry structure | ||||
* for the shared object. Returns NULL on failure. | * for the shared object. Returns NULL on failure. | ||||
*/ | */ | ||||
Show All 34 Lines | map_object(int fd, const char *path, const struct stat *sb) | ||||
Elf_Addr relro_page; | Elf_Addr relro_page; | ||||
size_t relro_size; | size_t relro_size; | ||||
Elf_Addr note_start; | Elf_Addr note_start; | ||||
Elf_Addr note_end; | Elf_Addr note_end; | ||||
char *note_map; | char *note_map; | ||||
size_t note_map_len; | size_t note_map_len; | ||||
Elf_Addr text_end; | Elf_Addr text_end; | ||||
hdr = get_elf_header(fd, path, sb); | hdr = get_elf_header(fd, path, sb, &phdr); | ||||
if (hdr == NULL) | if (hdr == NULL) | ||||
return (NULL); | return (NULL); | ||||
/* | /* | ||||
* Scan the program header entries, and save key information. | * Scan the program header entries, and save key information. | ||||
* | |||||
* We expect that the loadable segments are ordered by load address. | * We expect that the loadable segments are ordered by load address. | ||||
*/ | */ | ||||
phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff); | |||||
phsize = hdr->e_phnum * sizeof (phdr[0]); | phsize = hdr->e_phnum * sizeof(phdr[0]); | ||||
phlimit = phdr + hdr->e_phnum; | phlimit = phdr + hdr->e_phnum; | ||||
nsegs = -1; | nsegs = -1; | ||||
phdyn = phinterp = phtls = NULL; | phdyn = phinterp = phtls = NULL; | ||||
phdr_vaddr = 0; | phdr_vaddr = 0; | ||||
relro_page = 0; | relro_page = 0; | ||||
relro_size = 0; | relro_size = 0; | ||||
note_start = 0; | note_start = 0; | ||||
note_end = 0; | note_end = 0; | ||||
▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | munmap(note_map, note_map_len); | ||||
munmap(hdr, PAGE_SIZE); | munmap(hdr, PAGE_SIZE); | ||||
return (obj); | return (obj); | ||||
error1: | error1: | ||||
munmap(mapbase, mapsize); | munmap(mapbase, mapsize); | ||||
error: | error: | ||||
if (note_map != NULL && note_map != MAP_FAILED) | if (note_map != NULL && note_map != MAP_FAILED) | ||||
munmap(note_map, note_map_len); | munmap(note_map, note_map_len); | ||||
if (!phdr_in_zero_page(hdr)) | |||||
munmap(phdr, hdr->e_phnum * sizeof(phdr[0])); | |||||
munmap(hdr, PAGE_SIZE); | munmap(hdr, PAGE_SIZE); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
static Elf_Ehdr * | static Elf_Ehdr * | ||||
get_elf_header(int fd, const char *path, const struct stat *sbp) | get_elf_header(int fd, const char *path, const struct stat *sbp, | ||||
Elf_Phdr **phdr_p) | |||||
{ | { | ||||
Elf_Ehdr *hdr; | Elf_Ehdr *hdr; | ||||
Elf_Phdr *phdr; | |||||
/* Make sure file has enough data for the ELF header */ | /* Make sure file has enough data for the ELF header */ | ||||
if (sbp != NULL && sbp->st_size < (off_t)sizeof(Elf_Ehdr)) { | if (sbp != NULL && sbp->st_size < (off_t)sizeof(Elf_Ehdr)) { | ||||
_rtld_error("%s: invalid file format", path); | _rtld_error("%s: invalid file format", path); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, | hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, | ||||
Show All 32 Lines | get_elf_header(int fd, const char *path, const struct stat *sbp, | ||||
* not strictly required by the ABI specification, but it seems to | * not strictly required by the ABI specification, but it seems to | ||||
* always true in practice. And, it simplifies things considerably. | * always true in practice. And, it simplifies things considerably. | ||||
*/ | */ | ||||
if (hdr->e_phentsize != sizeof(Elf_Phdr)) { | if (hdr->e_phentsize != sizeof(Elf_Phdr)) { | ||||
_rtld_error( | _rtld_error( | ||||
"%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path); | "%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path); | ||||
goto error; | goto error; | ||||
} | } | ||||
if (hdr->e_phoff + hdr->e_phnum * sizeof(Elf_Phdr) > | if (phdr_in_zero_page(hdr)) { | ||||
(size_t)PAGE_SIZE) { | phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff); | ||||
_rtld_error("%s: program header too large", path); | } else { | ||||
phdr = mmap(NULL, hdr->e_phnum * sizeof(phdr[0]), | |||||
PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, fd, | |||||
hdr->e_phoff); | |||||
if (phdr == MAP_FAILED) { | |||||
_rtld_error("%s: error mapping phdr: %s", path, | |||||
rtld_strerror(errno)); | |||||
goto error; | goto error; | ||||
} | } | ||||
} | |||||
*phdr_p = phdr; | |||||
return (hdr); | return (hdr); | ||||
error: | error: | ||||
munmap(hdr, PAGE_SIZE); | munmap(hdr, PAGE_SIZE); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
void | void | ||||
▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines |