blob: e9692c69876b750bf30e08e10ea77cb794dd437a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2013,2014 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
/*
* This module implements reading and caching of ELF files.
*/
#ifndef D_elf
#define D_elf
#include <tcf/config.h>
#if ENABLE_ELF
#if !ENABLE_ContextProxy && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__APPLE__)
# define INCLUDE_NATIVE_ELF_H 1
# include <elf.h>
#endif
#include <tcf/framework/context.h>
#if !defined(INCLUDE_NATIVE_ELF_H)
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_ABIVERSION 8
#define EI_PAD 9
#define EI_NIDENT 16
#define ELFMAG0 0x7F
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFMAG "\177ELF"
#define SELFMAG 4
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define EM_NONE 0
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* Intel Architecture */
#define EM_68K 4 /* Motorola 68000 */
#define EM_88K 5 /* Motorola 88000 */
#define EM_860 7 /* Intel 80860 */
#define EM_MIPS 8 /* MIPS RS3000 Big-Endian */
#define EM_MIPS_RS4_BE 10 /* MIPS RS4000 Big-Endian */
#define EM_PPC 20 /* PowerPC */
#define EM_PPC64 21 /* PowerPC64 */
#define EM_ARM 40 /* ARM */
#define EM_SH 42 /* Hitachi Super-H */
#define EM_SPARCV9 43 /* SPARC Version 9 */
#define EM_IA_64 50 /* HP/Intel IA-64 */
#define EM_MIPS_X 51 /* Stanford MIPS-X */
#define EM_COLDFIRE 52 /* Motorola Coldfire */
#define EM_X86_64 62 /* AMD x86-64 architecture */
#define EM_V850 87 /* NEC/Renesas RH850 */
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
#define ET_LOOS 0xFE00
#define ET_HIOS 0xFEFF
#define ET_LOPROC 0xFF00
#define ET_HIPROC 0xFFFF
#define EV_CURRENT 1
#define SHN_UNDEF 0
#define SHN_ABS 0xfff1
#define SHN_COMMON 0xfff2
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define STN_UNDEF 0
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_LOPROC 13
#define STT_HIPROC 15
#define STT_ARM_TFUNC STT_LOPROC
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_TLS 7
#define PF_X (1 << 0)
#define PF_W (1 << 1)
#define PF_R (1 << 2)
#define DT_NULL 0
#define DT_NEEDED 1
#define DT_PLTRELSZ 2
#define DT_PLTGOT 3
#define DT_HASH 4
#define DT_STRTAB 5
#define DT_SYMTAB 6
#define DT_RELA 7
#define DT_RELASZ 8
#define DT_RELAENT 9
#define DT_STRSZ 10
#define DT_SYMENT 11
#define DT_INIT 12
#define DT_FINI 13
#define DT_SONAME 14
#define DT_RPATH 15
#define DT_SYMBOLIC 16
#define DT_REL 17
#define DT_RELSZ 18
#define DT_RELENT 19
#define DT_PLTREL 20
#define DT_DEBUG 21
#define DT_TEXTREL 22
#define DT_JMPREL 23
#define DT_BIND_NOW 24
#define DT_INIT_ARRAY 25
#define DT_FINI_ARRAY 26
#define DT_INIT_ARRAYSZ 27
#define DT_FINI_ARRAYSZ 28
#define DT_RUNPATH 29
#define DT_FLAGS 30
#define DT_ENCODING 32
#define DT_PREINIT_ARRAY 32
#define DT_PREINIT_ARRAYSZ 33
#define DT_NUM 34
#define DT_LOOS 0x6000000d
#define DT_HIOS 0x6ffff000
#define DT_LOPROC 0x70000000
#define DT_HIPROC 0x7fffffff
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
typedef struct Elf32_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct Elf32_Shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
#define SHF_WRITE 0x00000001
#define SHF_ALLOC 0x00000002
#define SHF_EXECINSTR 0x00000004
typedef struct Elf32_Phdr {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct Elf32_Sym {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
#define ELF32_ST_BIND(i) ((i)>>4)
#define ELF32_ST_TYPE(i) ((i)&0xf)
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((uint8_t)(i))
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
#endif
#if !defined(INCLUDE_NATIVE_ELF_H) || \
(defined(_WRS_KERNEL) && !defined(EM_X86_64))
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
typedef uint64_t Elf64_Off;
typedef uint16_t Elf64_Section;
typedef Elf64_Half Elf64_Versym;
typedef uint16_t Elf64_Quarter;
typedef struct {
uint8_t e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
typedef struct {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
typedef struct {
Elf64_Word st_name;
uint8_t st_info;
uint8_t st_other;
Elf64_Section st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
} Elf64_Rel;
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
#define ELF64_R_SYM(i) ((uint32_t)((i) >> 32))
#define ELF64_R_TYPE(i) ((uint32_t)(i))
typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
typedef struct {
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;
#endif
#ifndef EM_ARM
#define EM_ARM 40
#endif
#ifndef EM_X86_64
#define EM_X86_64 62
#endif
#ifndef EM_PPC
#define EM_PPC 20
#endif
#ifndef EM_PPC64
#define EM_PPC64 21
#endif
#ifndef EM_V850
#define EM_V850 87 /* NEC/Renesas RH850 */
#endif
#ifndef EM_MICROBLAZE
#define EM_MICROBLAZE 189
#endif
#ifndef STT_GNU_IFUNC
#define STT_GNU_IFUNC 10
#endif
typedef struct ElfX_Sym {
union {
Elf32_Sym Elf32;
Elf64_Sym Elf64;
} u;
} ElfX_Sym;
typedef uint8_t U1_T;
typedef int8_t I1_T;
typedef uint16_t U2_T;
typedef int16_t I2_T;
typedef uint32_t U4_T;
typedef int32_t I4_T;
typedef uint64_t U8_T;
typedef int64_t I8_T;
typedef struct ELF_File ELF_File;
typedef struct ELF_Section ELF_Section;
typedef struct ELF_SecSymbol ELF_SecSymbol;
typedef struct ELF_SymbolInfo ELF_SymbolInfo;
typedef struct ELF_PHeader ELF_PHeader;
/* TODO: fp_abi - value of Tag_GNU_Power_ABI_FP in gnu.attributes section */
struct ELF_File {
ELF_File * next;
char * name;
dev_t dev;
ino_t ino;
int64_t mtime;
int64_t size;
int mtime_changed;
ErrorReport * error;
unsigned lock_cnt;
int fd;
/* Other names of the file, e.g. symbolic links */
char ** names;
unsigned names_cnt;
unsigned names_max;
#if defined(_WIN32) || defined(__CYGWIN__)
HANDLE mmap_handle;
#endif
uint8_t big_endian; /* 0 - least significant first, 1 - most significat first */
uint8_t byte_swap; /* > 0 if file endianness not same as the agent endianness */
uint8_t elf64;
uint16_t type;
uint16_t machine;
uint8_t os_abi;
ContextAddress entry_address;
unsigned section_cnt;
ELF_Section * sections;
char * str_pool;
unsigned pheader_cnt;
ELF_PHeader * pheaders;
void * dwarf_io_cache;
void * dwarf_dt_cache;
unsigned age; /* Seconds since last time the file was accessed */
int listed;
int debug_info_file; /* 1 means this file contains debug info only - no code */
char * debug_info_file_name;
char * dwz_file_name;
ELF_File * dwz_file;
int vxworks_got;
};
struct ELF_SecSymbol {
ELF_Section * section;
unsigned index;
U8_T address;
};
struct ELF_SymbolInfo {
ELF_Section * sym_section;
U4_T sym_index;
unsigned addr_index;
ELF_Section * section;
U4_T section_index;
char * name;
U1_T bind;
U1_T type;
U8_T value;
U8_T size;
};
struct ELF_Section {
ELF_File * file;
U4_T index;
unsigned name_offset;
char * name;
void * data;
U4_T type;
U4_T flags;
U4_T alignment;
U8_T offset;
U8_T size;
U8_T addr;
U4_T link;
U4_T info;
U4_T entsize;
void * mmap_addr;
size_t mmap_size;
ELF_Section * relocate;
unsigned sym_count;
/* Symbol by address search index */
ELF_SecSymbol * sym_addr_table;
unsigned sym_addr_cnt;
unsigned sym_addr_max;
/* Symbol by name search index */
unsigned sym_names_hash_size;
unsigned * sym_names_hash;
unsigned * sym_names_next;
/* Relocations blocks */
unsigned reloc_num_zones;
unsigned * reloc_zones_bondaries;
};
struct ELF_PHeader {
U4_T type;
U8_T offset;
U8_T address;
U8_T physical_address;
U8_T file_size;
U8_T mem_size;
U4_T flags;
U4_T align;
};
/*
* Open ELF file for reading.
* Same file can be opened mutiple times.
* Returns the file descriptior on success. If error, returns NULL and sets errno.
* The file descriptor is valid only during single dispatch cycle.
*/
extern ELF_File * elf_open(const char * file_name);
/*
* Open ELF file that is mapped in the given memory region.
*/
extern ELF_File * elf_open_memory_region_file(MemoryRegion * module, int * error);
/*
* Load section data into memory.
* section->data is set to section data address in memory.
* Data will stay in memory at least until file is closed.
* Returns zero on success. If error, returns -1 and sets errno.
*/
extern int elf_load(ELF_Section * section);
/*
* Register ELF file close callback.
* The callback is called each time an ELF file data is about to be disposed.
* Service implementation can use the callback to deallocate
* cached data related to the file.
*/
typedef void (*ELFCloseListener)(ELF_File *);
extern void elf_add_close_listener(ELFCloseListener listener);
/*
* Return ELF file that contains DWARF info for given file.
* On some systems, DWARF is kept in a separate file.
* If such file is not available, return 'file'.
*/
extern ELF_File * get_dwarf_file(ELF_File * file);
#if ENABLE_DebugContext
/*
* Open ELF file for reading for given device and inode.
* Same file can be opened mutiple times.
* Returns the file descriptior on success. If error, returns NULL and sets errno.
* The file descriptor is valid only during single dispatch cycle.
*/
extern ELF_File * elf_open_inode(Context * ctx, dev_t dev, ino_t ino, int64_t mtime);
/*
* Iterate context ELF files that are mapped in context memory in given address range (inclusive).
* Returns the file descriptior on success. If error, returns NULL and sets errno.
*/
extern ELF_File * elf_list_first(Context * ctx, ContextAddress addr0, ContextAddress addr1);
extern ELF_File * elf_list_next(Context * ctx);
/*
* Finish iteration of context ELF files.
* Clients should always call elf_list_done() after calling elf_list_first().
*/
extern void elf_list_done(Context * ctx);
/*
* Get info about ELF files mapped or loaded in the given memory address range.
* 'addr0' and 'addr1' are run-time addresses.
* The range is inclusive.
*/
extern int elf_get_map(Context * ctx, ContextAddress addr0, ContextAddress addr1, MemoryMap * map);
/*
* Map link-time address in an ELF file to run-time address in a context.
* Clear errno if no errors found, otherwise set errno and return 0.
*/
extern ContextAddress elf_map_to_run_time_address(Context * ctx, ELF_File * file, ELF_Section * section, ContextAddress addr);
/*
* Return run-time address for link-time address 'addr' in a file 'file' (and optional section 'sec'),
* which is mapped to memory context 'ctx' at memory region 'region'.
* Clear errno if no errors found, otherwise set errno and return 0.
*/
extern ContextAddress elf_run_time_address_in_region(Context * ctx, MemoryRegion * region, ELF_File * file, ELF_Section * sec, ContextAddress addr);
/*
* Map run-time address in a context to link time address in an ELF file.
* Return 0 if the address is not currently mapped.
*/
extern ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr, ELF_File ** file, ELF_Section ** sec);
/*
* Read a word from context memory. Word size and endianess are determened by ELF file.
*/
extern int elf_read_memory_word(Context * ctx, ELF_File * file, ContextAddress addr, ContextAddress * word);
#endif
/* Return symbol name hash. The hash is used to build sym_names_hash table. */
extern unsigned calc_symbol_name_hash(const char * s);
/* Compare symbol names. */
extern int cmp_symbol_names(const char * x, const char * y);
/*
* Get ELF_SymbolInfo.
* Call exception() on error.
*/
extern void unpack_elf_symbol_info(ELF_Section * section, U4_T index, ELF_SymbolInfo * info);
/*
* Find ELF symbol by link-time address in a section.
* Return info for nearest symbol at or before given address.
* If not found, set all 'info' fields to zeros.
* Call exception() on error.
*/
extern void elf_find_symbol_by_address(ELF_Section * section, ContextAddress addr, ELF_SymbolInfo * info);
/*
* Get prev/next ELF symbol by link-time address in a section.
* If not found, set all 'info' fields to zeros.
* Call exception() on error.
*/
extern void elf_prev_symbol_by_address(ELF_SymbolInfo * info);
extern void elf_next_symbol_by_address(ELF_SymbolInfo * info);
/*
* Find link-time address of GOT entry for given symbol name and assign it to *addr.
* Returns 0 on success.
* If entry not found, sets *addr = 0 and returns 0.
* If error, sets errno and returns -1.
*/
extern int elf_find_got_entry(ELF_File * file, const char * name, ContextAddress * addr);
/*
* Find target symbol for a PLT entry.
*/
extern int elf_find_plt_dynsym(ELF_Section * plt, unsigned entry,
ELF_SymbolInfo * sym_info, ContextAddress * offs);
/*
* Get size of PLT enries.
*/
extern int elf_get_plt_entry_size(ELF_File * file, unsigned * first_size, unsigned * entry_size);
/*
* Invalidate and dispose cached ELF data.
*/
extern void elf_invalidate(void);
/*
* Initialize ELF support module.
*/
extern void ini_elf(void);
#endif /* ENABLE_ELF */
#endif /* D_elf */