blob: c7effc588e76c1d52f63710ce35c6e85a9ea116b [file] [log] [blame]
/* vi: set sw=4 ts=4: */
/*
* Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
*
* GNU Lesser General Public License version 2.1 or later.
*/
#ifndef _LD_HASH_H_
#define _LD_HASH_H_
#ifndef RTLD_NEXT
#define RTLD_NEXT ((void*)-1)
#endif
struct init_fini {
struct elf_resolve **init_fini;
unsigned long nlist; /* Number of entries in init_fini */
};
struct dyn_elf {
struct elf_resolve * dyn;
struct dyn_elf * next_handle; /* Used by dlopen et al. */
struct init_fini init_fini;
struct dyn_elf * next;
struct dyn_elf * prev;
};
struct symbol_ref {
const ElfW(Sym) *sym;
struct elf_resolve *tpnt;
};
/* Structure to describe a single list of scope elements. The lookup
functions get passed an array of pointers to such structures. */
struct r_scope_elem {
struct elf_resolve **r_list; /* Array of maps for the scope. */
unsigned int r_nlist; /* Number of entries in the scope. */
struct r_scope_elem *next;
};
struct elf_resolve {
/* These entries must be in this order to be compatible with the interface used
by gdb to obtain the list of symbols. */
DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */
char *libname; /* Absolute file name object was found in. */
ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */
struct elf_resolve * next;
struct elf_resolve * prev;
/* Nothing after this address is used by gdb. */
#if defined(USE_TLS) && USE_TLS
/* Thread-local storage related info. */
/* Start of the initialization image. */
void *l_tls_initimage;
/* Size of the initialization image. */
size_t l_tls_initimage_size;
/* Size of the TLS block. */
size_t l_tls_blocksize;
/* Alignment requirement of the TLS block. */
size_t l_tls_align;
/* Offset of first byte module alignment. */
size_t l_tls_firstbyte_offset;
# ifndef NO_TLS_OFFSET
# define NO_TLS_OFFSET 0
# endif
/* For objects present at startup time: offset in the static TLS block. */
ptrdiff_t l_tls_offset;
/* Index of the module in the dtv array. */
size_t l_tls_modid;
/* Nonzero if _dl_init_static_tls should be called for this module */
unsigned int l_need_tls_init:1;
#endif
ElfW(Addr) mapaddr;
#ifdef __LDSO_STANDALONE_SUPPORT__
/* Store the entry point from the ELF header (e_entry) */
ElfW(Addr) l_entry;
#endif
enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype;
/* This is the local scope of the shared object */
struct r_scope_elem symbol_scope;
unsigned short usage_count;
unsigned short int init_flag;
unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
Elf_Symndx nbucket;
#ifdef __LDSO_GNU_HASH_SUPPORT__
/* Data needed to support GNU hash style */
Elf32_Word l_gnu_bitmask_idxbits;
Elf32_Word l_gnu_shift;
const ElfW(Addr) *l_gnu_bitmask;
union
{
const Elf32_Word *l_gnu_chain_zero;
const Elf_Symndx *elf_buckets;
};
#else
Elf_Symndx *elf_buckets;
#endif
struct init_fini_list *init_fini;
struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */
/*
* These are only used with ELF style shared libraries
*/
Elf_Symndx nchain;
#ifdef __LDSO_GNU_HASH_SUPPORT__
union
{
const Elf32_Word *l_gnu_buckets;
const Elf_Symndx *chains;
};
#else
Elf_Symndx *chains;
#endif
unsigned long dynamic_info[DYNAMIC_SIZE];
unsigned long n_phent;
ElfW(Phdr) * ppnt;
ElfW(Addr) relro_addr;
size_t relro_size;
dev_t st_dev; /* device */
ino_t st_ino; /* inode */
#ifdef __powerpc__
/* this is used to store the address of relocation data words, so
* we don't have to calculate it every time, which requires a divide */
unsigned long data_words;
#endif
#ifdef __FDPIC__
/* Every loaded module holds a hashtable of function descriptors of
functions defined in it, such that it's easy to release the
memory when the module is dlclose()d. */
struct funcdesc_ht *funcdesc_ht;
#endif
};
#define RELOCS_DONE 0x000001
#define JMP_RELOCS_DONE 0x000002
#define INIT_FUNCS_CALLED 0x000004
#define FINI_FUNCS_CALLED 0x000008
#define DL_OPENED 0x000010
#define DL_RESERVED 0x000020
extern struct dyn_elf * _dl_symbol_tables;
extern struct elf_resolve * _dl_loaded_modules;
extern struct dyn_elf * _dl_handles;
extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info,
unsigned long dynamic_addr, unsigned long dynamic_size);
extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
struct elf_resolve *mytpnt, int type_class,
struct symbol_ref *symbol);
extern int _dl_linux_dynamic_link(void);
extern char * _dl_library_path;
extern char * _dl_not_lazy;
static __inline__ int _dl_symbol(char * name)
{
if (name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_')
return 0;
return 1;
}
#define LD_ERROR_NOFILE 1
#define LD_ERROR_NOZERO 2
#define LD_ERROR_NOTELF 3
#define LD_ERROR_NOTMAGIC 4
#define LD_ERROR_NOTDYN 5
#define LD_ERROR_MMAP_FAILED 6
#define LD_ERROR_NODYNAMIC 7
#define LD_ERROR_TLS_FAILED 8
#define LD_WRONG_RELOCS 9
#define LD_BAD_HANDLE 10
#define LD_NO_SYMBOL 11
#endif /* _LD_HASH_H_ */