Blame elf/dl-load.h

Packit 6c4009
/* Map in a shared object's segments from the file.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef _DL_LOAD_H
Packit 6c4009
#define _DL_LOAD_H	1
Packit 6c4009
Packit 6c4009
#include <link.h>
Packit 6c4009
#include <sys/mman.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* On some systems, no flag bits are given to specify file mapping.  */
Packit 6c4009
#ifndef MAP_FILE
Packit 6c4009
# define MAP_FILE       0
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* The right way to map in the shared library files is MAP_COPY, which
Packit 6c4009
   makes a virtual copy of the data at the time of the mmap call; this
Packit 6c4009
   guarantees the mapped pages will be consistent even if the file is
Packit 6c4009
   overwritten.  Some losing VM systems like Linux's lack MAP_COPY.  All we
Packit 6c4009
   get is MAP_PRIVATE, which copies each page when it is modified; this
Packit 6c4009
   means if the file is overwritten, we may at some point get some pages
Packit 6c4009
   from the new version after starting with pages from the old version.
Packit 6c4009
Packit 6c4009
   To make up for the lack and avoid the overwriting problem,
Packit 6c4009
   what Linux does have is MAP_DENYWRITE.  This prevents anyone
Packit 6c4009
   from modifying the file while we have it mapped.  */
Packit 6c4009
#ifndef MAP_COPY
Packit 6c4009
# ifdef MAP_DENYWRITE
Packit 6c4009
#  define MAP_COPY      (MAP_PRIVATE | MAP_DENYWRITE)
Packit 6c4009
# else
Packit 6c4009
#  define MAP_COPY      MAP_PRIVATE
Packit 6c4009
# endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Some systems link their relocatable objects for another base address
Packit 6c4009
   than 0.  We want to know the base address for these such that we can
Packit 6c4009
   subtract this address from the segment addresses during mapping.
Packit 6c4009
   This results in a more efficient address space usage.  Defaults to
Packit 6c4009
   zero for almost all systems.  */
Packit 6c4009
#ifndef MAP_BASE_ADDR
Packit 6c4009
# define MAP_BASE_ADDR(l)       0
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Handle situations where we have a preferred location in memory for
Packit 6c4009
   the shared objects.  */
Packit 6c4009
#ifdef ELF_PREFERRED_ADDRESS_DATA
Packit 6c4009
ELF_PREFERRED_ADDRESS_DATA;
Packit 6c4009
#endif
Packit 6c4009
#ifndef ELF_PREFERRED_ADDRESS
Packit 6c4009
# define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
Packit 6c4009
#endif
Packit 6c4009
#ifndef ELF_FIXED_ADDRESS
Packit 6c4009
# define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* This structure describes one PT_LOAD command.
Packit 6c4009
   Its details have been expanded out and converted.  */
Packit 6c4009
struct loadcmd
Packit 6c4009
{
Packit 6c4009
  ElfW(Addr) mapstart, mapend, dataend, allocend;
Packit 6c4009
  ElfW(Off) mapoff;
Packit 6c4009
  int prot;                             /* PROT_* bits.  */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* This is a subroutine of _dl_map_segments.  It should be called for each
Packit 6c4009
   load command, some time after L->l_addr has been set correctly.  It is
Packit 6c4009
   responsible for setting up the l_text_end and l_phdr fields.  */
Packit 6c4009
static void __always_inline
Packit 6c4009
_dl_postprocess_loadcmd (struct link_map *l, const ElfW(Ehdr) *header,
Packit 6c4009
                         const struct loadcmd *c)
Packit 6c4009
{
Packit 6c4009
  if (c->prot & PROT_EXEC)
Packit 6c4009
    l->l_text_end = l->l_addr + c->mapend;
Packit 6c4009
Packit 6c4009
  if (l->l_phdr == 0
Packit 6c4009
      && c->mapoff <= header->e_phoff
Packit 6c4009
      && ((size_t) (c->mapend - c->mapstart + c->mapoff)
Packit 6c4009
          >= header->e_phoff + header->e_phnum * sizeof (ElfW(Phdr))))
Packit 6c4009
    /* Found the program header in this segment.  */
Packit 6c4009
    l->l_phdr = (void *) (uintptr_t) (c->mapstart + header->e_phoff
Packit 6c4009
                                      - c->mapoff);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* This is a subroutine of _dl_map_object_from_fd.  It is responsible
Packit 6c4009
   for filling in several fields in *L: l_map_start, l_map_end, l_addr,
Packit 6c4009
   l_contiguous, l_text_end, l_phdr.  On successful return, all the
Packit 6c4009
   segments are mapped (or copied, or whatever) from the file into their
Packit 6c4009
   final places in the address space, with the correct page permissions,
Packit 6c4009
   and any bss-like regions already zeroed.  It returns a null pointer
Packit 6c4009
   on success, or an error message string (to be translated) on error
Packit 6c4009
   (having also set errno).
Packit 6c4009
Packit 6c4009
   The file <dl-map-segments.h> defines this function.  The canonical
Packit 6c4009
   implementation in elf/dl-map-segments.h might be replaced by a sysdeps
Packit 6c4009
   version.  */
Packit 6c4009
static const char *_dl_map_segments (struct link_map *l, int fd,
Packit 6c4009
                                     const ElfW(Ehdr) *header, int type,
Packit 6c4009
                                     const struct loadcmd loadcmds[],
Packit 6c4009
                                     size_t nloadcmds,
Packit 6c4009
                                     const size_t maplength,
Packit 6c4009
                                     bool has_holes,
Packit 6c4009
                                     struct link_map *loader);
Packit 6c4009
Packit 6c4009
/* All the error message strings _dl_map_segments might return are
Packit 6c4009
   listed here so that different implementations in different sysdeps
Packit 6c4009
   dl-map-segments.h files all use consistent strings that are
Packit 6c4009
   guaranteed to have translations.  */
Packit 6c4009
#define DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT \
Packit 6c4009
  N_("failed to map segment from shared object")
Packit 6c4009
#define DL_MAP_SEGMENTS_ERROR_MPROTECT \
Packit 6c4009
  N_("cannot change memory protections")
Packit 6c4009
#define DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL \
Packit 6c4009
  N_("cannot map zero-fill pages")
Packit 6c4009
Packit 6c4009
Packit 6c4009
#endif	/* dl-load.h */