blob: e341325cf328a1cc74411e0d0a0b673cf6eacca9 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2020 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_H
#define MODULE_H
/* used only in our own routines here which use PF_* converted to MEMPROT_* */
#define OS_IMAGE_READ (MEMPROT_READ)
#define OS_IMAGE_WRITE (MEMPROT_WRITE)
#define OS_IMAGE_EXECUTE (MEMPROT_EXEC)
/* i#160/PR 562667: support non-contiguous library mappings. While we're at
* it we go ahead and store info on each segment whether contiguous or not.
*/
typedef struct _module_segment_t {
/* start and end are page-aligned beyond the section alignment */
app_pc start;
app_pc end;
uint prot;
bool shared; /* not unique to this module */
uint64 offset;
} module_segment_t;
typedef struct _os_module_data_t {
/* To compute the base address, one determines the memory address associated with
* the lowest p_vaddr value for a PT_LOAD segment. One then obtains the base
* address by truncating the memory load address to the nearest multiple of the
* maximum page size and subtracting the truncated lowest p_vaddr value.
* Thus, this is not the load address but the base address used in
* address references within the file.
*/
app_pc base_address;
/* XXX: All segments are expected to have the same alignment, even though that it is
* not a requirement for ELF. To allow a different alignment for each segment we will
* need to move this field in the module_segment_t struct.
*/
size_t alignment; /* the alignment between segments */
/* Fields for pcaches (PR 295534) */
size_t checksum;
size_t timestamp;
#ifdef LINUX
/* i#112: Dynamic section info for exported symbol lookup. Not
* using elf types here to avoid having to export those.
*/
bool have_dynamic_info; /* are the fields below filled in yet? */
bool hash_is_gnu; /* gnu hash function? */
app_pc hashtab; /* absolute addr of .hash or .gnu.hash */
size_t num_buckets; /* number of bucket entries */
app_pc buckets; /* absolute addr of hash bucket table */
size_t num_chain; /* number of chain entries */
app_pc chain; /* absolute addr of hash chain table */
app_pc dynsym; /* absolute addr of .dynsym */
app_pc dynstr; /* absolute addr of .dynstr */
size_t dynstr_size; /* size of .dynstr */
size_t symentry_size; /* size of a .dynsym entry */
bool has_runpath; /* is DT_RUNPATH present? */
/* for .gnu.hash */
app_pc gnu_bitmask;
ptr_uint_t gnu_shift;
ptr_uint_t gnu_bitidx;
size_t gnu_symbias; /* .dynsym index of first export */
#else /* MACOS */
byte *exports; /* absolute addr of exports trie */
size_t exports_sz; /* size of exports trie */
byte *symtab;
uint num_syms;
byte *strtab;
size_t strtab_sz;
bool in_shared_cache;
uint current_version;
uint compatibility_version;
byte uuid[16];
#endif
/* i#160/PR 562667: support non-contiguous library mappings */
bool contiguous;
uint num_segments; /* number of valid entries in segments array */
uint alloc_segments; /* capacity of segments array */
module_segment_t *segments;
} os_module_data_t;
app_pc
module_entry_point(app_pc base, ptr_int_t load_delta);
bool
module_is_header(app_pc base, size_t size /*optional*/);
bool
module_is_executable(app_pc base);
bool
module_is_partial_map(app_pc base, size_t size, uint memprot);
bool
module_walk_program_headers(app_pc base, size_t view_size, bool at_map, bool dyn_reloc,
app_pc *out_base,
app_pc *out_first_end, /* first segment's end */
app_pc *out_max_end, char **out_soname,
os_module_data_t *out_data);
uint
module_num_program_headers(app_pc base);
void
os_module_update_dynamic_info(app_pc base, size_t size, bool at_map);
bool
module_file_has_module_header(const char *filename);
bool
module_file_is_module64(file_t f, bool *is64 DR_PARAM_OUT, bool *also32 DR_PARAM_OUT);
/* A Mach-O universal binary may have many bitwidths. The one used on execve will be
* returned in "platform" and the 2nd one in "alt_platform".
*/
bool
module_get_platform(file_t f, dr_platform_t *platform, dr_platform_t *alt_platform);
void
module_add_segment_data(DR_PARAM_OUT os_module_data_t *out_data,
uint num_segments /*hint only*/, app_pc segment_start,
size_t segment_size, uint segment_prot, size_t alignment,
bool shared, uint64 offset);
#if defined(MACOS) || defined(ANDROID)
typedef FILE stdfile_t;
# define STDFILE_FILENO _file
#elif defined(LINUX)
typedef struct _IO_FILE stdfile_t;
# ifdef __GLIBC__
# define STDFILE_FILENO _fileno
# endif
#endif
extern stdfile_t **privmod_stdout;
extern stdfile_t **privmod_stderr;
extern stdfile_t **privmod_stdin;
/* loader.c */
app_pc
get_private_library_address(app_pc modbase, const char *name);
bool
get_private_library_bounds(DR_PARAM_IN app_pc modbase, DR_PARAM_OUT byte **start,
DR_PARAM_OUT byte **end);
#ifdef MACOS
/* module_macho.c */
byte *
module_dynamorio_lib_base(void);
bool
module_dyld_shared_region(app_pc *start DR_PARAM_OUT, app_pc *end DR_PARAM_OUT);
void
module_walk_dyld_list(app_pc dyld_base);
#endif
#endif /* MODULE_H */