aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c133
1 files changed, 82 insertions, 51 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 8103c7af2a..c6acc8c222 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -60,6 +60,7 @@ Cambridge, MA 02139, USA. */
#define STRING(x) #x
int _dl_zerofd = -1;
+size_t _dl_pagesize;
/* Try to open NAME in one of the directories in DIRPATH.
@@ -82,31 +83,48 @@ open_path (const char *name, size_t namelen,
return -1;
}
- buf = alloca (strlen (dirpath) + 1 + namelen);
+ buf = __alloca (strlen (dirpath) + 1 + namelen);
do
{
+ size_t buflen;
+
dirpath = p;
p = strpbrk (dirpath, ":;");
if (p == NULL)
p = strchr (dirpath, '\0');
if (p == dirpath)
- /* Two adjacent colons, or a colon at the beginning or the end of
- the path means to search the current directory. */
- (void) memcpy (buf, name, namelen);
+ {
+ /* Two adjacent colons, or a colon at the beginning or the end of
+ the path means to search the current directory. */
+ (void) memcpy (buf, name, namelen);
+ buflen = namelen;
+ }
else
{
/* Construct the pathname to try. */
(void) memcpy (buf, dirpath, p - dirpath);
buf[p - dirpath] = '/';
(void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
+ buflen = p - dirpath + 1 + namelen;
}
- fd = open (buf, O_RDONLY);
+ fd = __open (buf, O_RDONLY);
if (fd != -1)
{
- *realname = strdup (buf);
- return fd;
+ *realname = malloc (buflen);
+ if (*realname)
+ {
+ memcpy (*realname, buf, buflen);
+ return fd;
+ }
+ else
+ {
+ /* No memory for the name, we certainly won't be able
+ to load and link it. */
+ __close (fd);
+ return -1;
+ }
}
if (errno != ENOENT && errno != EACCES)
/* The file exists and is readable, but something went wrong. */
@@ -117,7 +135,6 @@ open_path (const char *name, size_t namelen,
return -1;
}
-
/* Map in the shared object file NAME. */
struct link_map *
@@ -163,9 +180,19 @@ _dl_map_object (struct link_map *loader, const char *name)
}
else
{
- fd = open (name, O_RDONLY);
+ fd = __open (name, O_RDONLY);
if (fd != -1)
- realname = strdup (name);
+ {
+ size_t len = strlen (name) + 1;
+ realname = malloc (len);
+ if (realname)
+ memcpy (realname, name, len);
+ else
+ {
+ __close (fd);
+ fd = -1;
+ }
+ }
}
if (fd == -1)
@@ -182,25 +209,24 @@ struct link_map *
_dl_map_object_from_fd (const char *name, int fd, char *realname)
{
struct link_map *l = NULL;
- const size_t pagesize = getpagesize ();
void *file_mapping = NULL;
size_t mapping_size = 0;
#define LOSE(s) lose (0, (s))
void lose (int code, const char *msg)
{
- (void) close (fd);
+ (void) __close (fd);
if (file_mapping)
- munmap (file_mapping, mapping_size);
+ __munmap (file_mapping, mapping_size);
_dl_signal_error (code, l ? l->l_name : name, msg);
}
- inline caddr_t map_segment (Elf32_Addr mapstart, size_t len,
+ inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len,
int prot, int fixed, off_t offset)
{
- caddr_t mapat = mmap ((caddr_t) mapstart, len, prot,
- fixed|MAP_COPY|MAP_FILE,
- fd, offset);
+ caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot,
+ fixed|MAP_COPY|MAP_FILE,
+ fd, offset);
if (mapat == (caddr_t) -1)
lose (errno, "failed to map segment from shared object");
return mapat;
@@ -213,11 +239,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
{
void *result;
if (file_mapping)
- munmap (file_mapping, mapping_size);
- mapping_size = (location + size + 1 + pagesize - 1);
- mapping_size &= ~(pagesize - 1);
- result = mmap (file_mapping, mapping_size, PROT_READ,
- MAP_COPY|MAP_FILE, fd, 0);
+ __munmap (file_mapping, mapping_size);
+ mapping_size = (location + size + 1 + _dl_pagesize - 1);
+ mapping_size &= ~(_dl_pagesize - 1);
+ result = __mmap (file_mapping, mapping_size, PROT_READ,
+ MAP_COPY|MAP_FILE, fd, 0);
if (result == (void *) -1)
lose (errno, "cannot map file data");
file_mapping = result;
@@ -225,9 +251,9 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
return file_mapping + location;
}
- const Elf32_Ehdr *header;
- const Elf32_Phdr *phdr;
- const Elf32_Phdr *ph;
+ const ElfW(Ehdr) *header;
+ const ElfW(Phdr) *phdr;
+ const ElfW(Phdr) *ph;
int type;
/* Look again to see if the real name matched another already loaded. */
@@ -236,12 +262,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
{
/* The object is already loaded.
Just bump its reference count and return it. */
- close (fd);
+ __close (fd);
free (realname);
++l->l_opencount;
return l;
}
+ if (_dl_pagesize == 0)
+ _dl_pagesize = __getpagesize ();
+
/* Map in the first page to read the header. */
header = map (0, sizeof *header);
@@ -260,8 +289,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
#endif
)
LOSE ("invalid ELF header");
- if (header->e_ident[EI_CLASS] != ELFCLASS32)
- LOSE ("ELF file class not 32-bit");
+#define ELF32_CLASS ELFCLASS32
+#define ELF64_CLASS ELFCLASS64
+ if (header->e_ident[EI_CLASS] != ELFW(CLASS))
+ LOSE ("ELF file class not " STRING(__ELF_WORDSIZE) "-bit");
if (header->e_ident[EI_DATA] != byteorder)
LOSE ("ELF file data encoding not " byteorder_name);
if (header->e_ident[EI_VERSION] != EV_CURRENT)
@@ -270,7 +301,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
LOSE ("ELF file version not " STRING(EV_CURRENT));
if (! elf_machine_matches_host (header->e_machine))
LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
- if (header->e_phentsize != sizeof (Elf32_Phdr))
+ if (header->e_phentsize != sizeof (ElfW(Phdr)))
LOSE ("ELF file's phentsize not the expected size");
/* Enter the new object in the list of loaded objects. */
@@ -289,13 +320,13 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
l->l_entry = header->e_entry;
type = header->e_type;
l->l_phnum = header->e_phnum;
- phdr = map (header->e_phoff, l->l_phnum * sizeof (Elf32_Phdr));
+ phdr = map (header->e_phoff, l->l_phnum * sizeof (ElfW(Phdr)));
{
/* Scan the program header table, collecting its load commands. */
struct loadcmd
{
- Elf32_Addr mapstart, mapend, dataend, allocend;
+ ElfW(Addr) mapstart, mapend, dataend, allocend;
off_t mapoff;
int prot;
} loadcmds[l->l_phnum], *c;
@@ -320,15 +351,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
case PT_LOAD:
/* A load command tells us to map in part of the file.
We record the load commands and process them all later. */
- if (ph->p_align % pagesize != 0)
+ if (ph->p_align % _dl_pagesize != 0)
LOSE ("ELF load command alignment not page-aligned");
if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
LOSE ("ELF load command address/offset not properly aligned");
{
struct loadcmd *c = &loadcmds[nloadcmds++];
c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
- c->mapend = ((ph->p_vaddr + ph->p_filesz + pagesize - 1)
- & ~(pagesize - 1));
+ c->mapend = ((ph->p_vaddr + ph->p_filesz + _dl_pagesize - 1)
+ & ~(_dl_pagesize - 1));
c->dataend = ph->p_vaddr + ph->p_filesz;
c->allocend = ph->p_vaddr + ph->p_memsz;
c->mapoff = ph->p_offset & ~(ph->p_align - 1);
@@ -344,7 +375,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
}
/* We are done reading the file's headers now. Unmap them. */
- munmap (file_mapping, mapping_size);
+ __munmap (file_mapping, mapping_size);
/* Now process the load commands and map segments into memory. */
c = loadcmds;
@@ -362,16 +393,16 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
mapat = map_segment (c->mapstart,
loadcmds[nloadcmds - 1].allocend - c->mapstart,
c->prot, 0, c->mapoff);
- l->l_addr = (Elf32_Addr) mapat - c->mapstart;
+ l->l_addr = (ElfW(Addr)) mapat - c->mapstart;
/* Change protection on the excess portion to disallow all access;
the portions we do not remap later will be inaccessible as if
unallocated. Then jump into the normal segment-mapping loop to
handle the portion of the segment past the end of the file
mapping. */
- mprotect (mapat + c->mapend,
- loadcmds[nloadcmds - 1].allocend - c->mapend,
- 0);
+ __mprotect (mapat + c->mapend,
+ loadcmds[nloadcmds - 1].allocend - c->mapend,
+ 0);
goto postmap;
}
@@ -387,11 +418,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
{
/* Extra zero pages should appear at the end of this segment,
after the data mapped from the file. */
- Elf32_Addr zero, zeroend, zeropage;
+ ElfW(Addr) zero, zeroend, zeropage;
zero = l->l_addr + c->dataend;
zeroend = l->l_addr + c->allocend;
- zeropage = (zero + pagesize - 1) & ~(pagesize - 1);
+ zeropage = (zero + _dl_pagesize - 1) & ~(_dl_pagesize - 1);
if (zeroend < zeropage)
/* All the extra data is in the last page of the segment.
@@ -404,23 +435,23 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
if ((c->prot & PROT_WRITE) == 0)
{
/* Dag nab it. */
- if (mprotect ((caddr_t) (zero & ~(pagesize - 1)),
- pagesize, c->prot|PROT_WRITE) < 0)
+ if (__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
+ _dl_pagesize, c->prot|PROT_WRITE) < 0)
lose (errno, "cannot change memory protections");
}
memset ((void *) zero, 0, zeropage - zero);
if ((c->prot & PROT_WRITE) == 0)
- mprotect ((caddr_t) (zero & ~(pagesize - 1)),
- pagesize, c->prot);
+ __mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
+ _dl_pagesize, c->prot);
}
if (zeroend > zeropage)
{
/* Map the remaining zero pages in from the zero fill FD. */
caddr_t mapat;
- mapat = mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
- MAP_ANON|MAP_PRIVATE|MAP_FIXED,
- _dl_zerofd, 0);
+ mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
+ c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+ _dl_zerofd, 0);
if (mapat == (caddr_t) -1)
lose (errno, "cannot map zero-fill pages");
}
@@ -441,11 +472,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
LOSE ("object file has no dynamic section");
}
else
- (Elf32_Addr) l->l_ld += l->l_addr;
+ (ElfW(Addr)) l->l_ld += l->l_addr;
if (l->l_phdr == 0)
- l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
- (Elf32_Addr) l->l_phdr += l->l_addr;
+ l->l_phdr = (void *) ((const ElfW(Ehdr) *) l->l_addr)->e_phoff;
+ (ElfW(Addr)) l->l_phdr += l->l_addr;
elf_get_dynamic_info (l->l_ld, l->l_info);
if (l->l_info[DT_HASH])