blob: ddad805ca2b9e332f5ea895d3d059bcd3df07e89 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* Copyright (c) 2008-2010 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef MODULE_ELF_H
#define MODULE_ELF_H
#include <elf.h> /* for ELF types */
/* XXX i#1345: support mixed-mode 32-bit and 64-bit in one process.
* There is no official support for that on Linux or Mac and for now we do
* not support it either, especially not mixing libraries.
*/
#ifdef X64
# define ELF_HEADER_TYPE Elf64_Ehdr
# define ELF_ALTARCH_HEADER_TYPE Elf32_Ehdr
# define ELF_PROGRAM_HEADER_TYPE Elf64_Phdr
# define ELF_SECTION_HEADER_TYPE Elf64_Shdr
# define ELF_DYNAMIC_ENTRY_TYPE Elf64_Dyn
# define ELF_ADDR Elf64_Addr
# define ELF_WORD Elf64_Xword
# define ELF_HALF Elf64_Half
# define ELF_SYM_TYPE Elf64_Sym
# define ELF_ST_TYPE ELF64_ST_TYPE
# define ELF_WORD_SIZE 64 /* __ELF_NATIVE_CLASS */
# define ELF_ST_BIND ELF64_ST_BIND
# define ELF_ST_VISIBILITY ELF64_ST_VISIBILITY
# define ELF_REL_TYPE Elf64_Rel
# define ELF_RELA_TYPE Elf64_Rela
# define ELF_AUXV_TYPE Elf64_auxv_t
#else
# define ELF_HEADER_TYPE Elf32_Ehdr
# define ELF_ALTARCH_HEADER_TYPE Elf64_Ehdr
# define ELF_PROGRAM_HEADER_TYPE Elf32_Phdr
# define ELF_SECTION_HEADER_TYPE Elf32_Shdr
# define ELF_DYNAMIC_ENTRY_TYPE Elf32_Dyn
# define ELF_ADDR Elf32_Addr
# define ELF_WORD Elf32_Word
# define ELF_HALF Elf32_Half
# define ELF_SYM_TYPE Elf32_Sym
# define ELF_ST_TYPE ELF32_ST_TYPE
# define ELF_WORD_SIZE 32 /* __ELF_NATIVE_CLASS */
# define ELF_ST_BIND ELF32_ST_BIND
# define ELF_ST_VISIBILITY ELF32_ST_VISIBILITY
# define ELF_REL_TYPE Elf32_Rel
# define ELF_RELA_TYPE Elf32_Rela
# define ELF_AUXV_TYPE Elf32_auxv_t
#endif
#ifdef X64
/* AMD x86-64 relocations. */
# define ELF_R_TYPE ELF64_R_TYPE
# define ELF_R_SYM ELF64_R_SYM
# define ELF_R_INFO ELF64_R_INFO
/* relocation type */
# define ELF_R_NONE R_X86_64_NONE /* No reloc */
# define ELF_R_DIRECT R_X86_64_64 /* Direct 64 bit */
# define ELF_R_PC32 R_X86_64_PC32 /* PC relative 32-bit signed */
# define ELF_R_COPY R_X86_64_COPY /* copy symbol at runtime */
# define ELF_R_GLOB_DAT R_X86_64_GLOB_DAT /* GOT entry */
# define ELF_R_JUMP_SLOT R_X86_64_JUMP_SLOT /* PLT entry */
# define ELF_R_RELATIVE R_X86_64_RELATIVE /* Adjust by program delta */
# ifndef R_X86_64_IRELATIVE
# define R_X86_64_IRELATIVE 37
# endif
# define ELF_R_IRELATIVE R_X86_64_IRELATIVE /* Adjust indirectly by program base */
/* TLS hanlding */
# define ELF_R_TLS_DTPMOD R_X86_64_DTPMOD64 /* Module ID */
# define ELF_R_TLS_TPOFF R_X86_64_TPOFF64 /* Offset in module's TLS block */
# define ELF_R_TLS_DTPOFF R_X86_64_DTPOFF64 /* Offset in initial TLS block */
# ifndef R_X86_64_TLSDESC
# define R_X86_64_TLSDESC 36
# endif
# define ELF_R_TLS_DESC R_X86_64_TLSDESC /* TLS descriptor containing
* pointer to code and to
* argument, returning the TLS
* offset for the symbol.
*/
#else /* 32-bit */
# define ELF_R_TYPE ELF32_R_TYPE
# define ELF_R_SYM ELF32_R_SYM
# define ELF_R_INFO ELF32_R_INFO
/* relocation type */
# define ELF_R_NONE R_386_NONE /* No reloc */
# define ELF_R_DIRECT R_386_32 /* Direct 32 bit */
# define ELF_R_PC32 R_386_PC32 /* PC relative 32 bit */
# define ELF_R_COPY R_386_COPY /* Copy symbol at runtime */
# define ELF_R_GLOB_DAT R_386_GLOB_DAT /* GOT entry */
# define ELF_R_JUMP_SLOT R_386_JMP_SLOT /* PLT entry */
# define ELF_R_RELATIVE R_386_RELATIVE /* Adjust by program delta */
# ifndef R_386_IRELATIVE
# define R_386_IRELATIVE 42
# endif
# define ELF_R_IRELATIVE R_386_IRELATIVE /* Adjust indirectly by program base */
/* tls related */
# define ELF_R_TLS_DTPMOD R_386_TLS_DTPMOD32 /* Module ID */
# define ELF_R_TLS_TPOFF R_386_TLS_TPOFF /* Negated offsets in static TLS block */
# define ELF_R_TLS_DTPOFF R_386_TLS_DTPOFF32 /* Offset in TLS block */
# ifndef R_386_TLS_DESC
# define R_386_TLS_DESC 41
# endif
# define ELF_R_TLS_DESC R_386_TLS_DESC /* TLS descriptor containing
* pointer to code and to
* argument, returning the TLS
* offset for the symbol.
*/
#endif
bool
get_elf_platform(file_t f, dr_platform_t *platform);
bool
is_elf_so_header(app_pc base, size_t size);
bool
is_elf_partial_map(app_pc base, size_t size, uint memprot);
app_pc
module_vaddr_from_prog_header(app_pc prog_header, uint num_segments,
OUT app_pc *first_end, /* first segment's end */
OUT app_pc *max_end);
bool
module_read_program_header(app_pc base,
uint segment_num,
OUT app_pc *segment_base,
OUT app_pc *segment_end,
OUT uint *segment_prot,
OUT size_t *segment_align);
ELF_ADDR
module_get_section_with_name(app_pc image, size_t img_size,
const char *sec_name);
void
module_relocate_rel(app_pc modbase,
os_privmod_data_t *pd,
ELF_REL_TYPE *start,
ELF_REL_TYPE *end);
void
module_relocate_rela(app_pc modbase,
os_privmod_data_t *pd,
ELF_RELA_TYPE *start,
ELF_RELA_TYPE *end);
bool
module_get_relro(app_pc base, OUT app_pc *relro_base, OUT size_t *relro_size);
bool
module_read_os_data(app_pc base,
OUT ptr_int_t *delta,
OUT os_module_data_t *os_data,
OUT char **soname);
uint
module_segment_prot_to_osprot(ELF_PROGRAM_HEADER_TYPE *prog_hdr);
/* Data structure for loading an ELF.
*/
typedef struct elf_loader_t {
const char *filename;
file_t fd;
ELF_HEADER_TYPE *ehdr; /* Points into buf. */
ELF_PROGRAM_HEADER_TYPE *phdrs; /* Points into buf or file_map. */
app_pc load_base; /* Load base. */
ptr_int_t load_delta; /* Delta from preferred base. */
size_t image_size; /* Size of the mapped image. */
void *file_map; /* Whole file map, if needed. */
size_t file_size; /* Size of the file map. */
/* Static buffer sized to hold most headers in a single read. A typical ELF
* file has an ELF header followed by program headers. On my workstation,
* most ELFs in /usr/lib have 7 phdrs, and the maximum is 9. We choose 12
* as a good upper bound and to allow for padding. If the headers don't
* fit, we fall back to file mapping.
*/
byte buf[sizeof(ELF_HEADER_TYPE) + sizeof(ELF_PROGRAM_HEADER_TYPE) * 12];
} elf_loader_t;
/* Initialized an ELF loader for use with the given file. */
bool
elf_loader_init(elf_loader_t *elf, const char *filename);
/* Frees resources needed to load the ELF, not the mapped image itself. */
void
elf_loader_destroy(elf_loader_t *elf);
/* Reads the main ELF header. */
ELF_HEADER_TYPE *
elf_loader_read_ehdr(elf_loader_t *elf);
/* Reads the ELF program headers, via read() or mmap() syscalls. */
ELF_PROGRAM_HEADER_TYPE *
elf_loader_read_phdrs(elf_loader_t *elf);
/* Shorthand to initialize the loader and read the ELF and program headers. */
bool
elf_loader_read_headers(elf_loader_t *elf, const char *filename);
/* Maps in the entire ELF file, including unmapped portions such as section
* headers and debug info. Does not re-map the same file if called twice.
*/
app_pc
elf_loader_map_file(elf_loader_t *elf, bool reachable);
/* Maps in the PT_LOAD segments of an ELF file, returning the base. Must be
* called after reading program headers with elf_loader_read_phdrs() or the
* elf_loader_read_headers() shortcut. All image mappings are done via the
* provided function pointers.
*
* XXX: fixed is only a hint as PIEs with a base of 0 should not use MAP_FIXED,
* should we remove it?
*/
app_pc
elf_loader_map_phdrs(elf_loader_t *elf, bool fixed, map_fn_t map_func,
unmap_fn_t unmap_func, prot_fn_t prot_func, bool reachable);
/* Iterate program headers of a mapped ELF image and find the string that
* PT_INTERP points to. Typically this comes early in the file and is always
* included in PT_LOAD segments, so we safely do this after the initial
* mapping.
*/
const char *
elf_loader_find_pt_interp(elf_loader_t *elf);
#endif /* MODULE_ELF_H */