#ifndef RTLD_H
#define RTLD_H 1
#include <machine/elf.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <elf-hints.h>
#include <link.h>
#include <stdarg.h>
#include <stdbool.h>
#include <setjmp.h>
#include <stddef.h>
#include "rtld_lock.h"
#include "rtld_machdep.h"
#define NEW(type) ((type *) xmalloc(sizeof(type)))
#define CNEW(type) ((type *) xcalloc(1, sizeof(type)))
extern size_t tls_last_offset;
extern size_t tls_last_size;
extern size_t tls_static_space;
extern Elf_Addr tls_dtv_generation;
extern int tls_max_index;
extern size_t ld_static_tls_extra;
extern int npagesizes;
extern size_t *pagesizes;
extern size_t page_size;
extern int main_argc;
extern char **main_argv;
extern char **environ;
struct stat;
struct Struct_Obj_Entry;
typedef struct Struct_Objlist_Entry {
STAILQ_ENTRY(Struct_Objlist_Entry) link;
struct Struct_Obj_Entry *obj;
} Objlist_Entry;
typedef STAILQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
typedef void (*InitFunc)(void);
typedef void (*InitArrFunc)(int, char **, char **);
typedef struct Struct_Needed_Entry {
struct Struct_Needed_Entry *next;
struct Struct_Obj_Entry *obj;
unsigned long name;
} Needed_Entry;
typedef struct Struct_Name_Entry {
STAILQ_ENTRY(Struct_Name_Entry) link;
char name[1];
} Name_Entry;
typedef struct Struct_LockInfo {
void *context;
void *thelock;
volatile int rcount;
volatile int wcount;
void *(*lock_create)(void *context);
void (*rlock_acquire)(void *lock);
void (*wlock_acquire)(void *lock);
void (*rlock_release)(void *lock);
void (*wlock_release)(void *lock);
void (*lock_destroy)(void *lock);
void (*context_destroy)(void *context);
} LockInfo;
typedef struct Struct_Ver_Entry {
Elf_Word hash;
unsigned int flags;
const char *name;
const char *file;
} Ver_Entry;
typedef struct Struct_Sym_Match_Result {
const Elf_Sym *sym_out;
const Elf_Sym *vsymp;
int vcount;
} Sym_Match_Result;
#define VER_INFO_HIDDEN 0x01
typedef struct Struct_Obj_Entry {
Elf_Size magic;
Elf_Size version;
TAILQ_ENTRY(Struct_Obj_Entry) next;
char *path;
char *origin_path;
int refcount;
int holdcount;
int dl_refcount;
caddr_t mapbase;
size_t mapsize;
Elf_Addr vaddrbase;
caddr_t relocbase;
const Elf_Dyn *dynamic;
caddr_t entry;
const Elf_Phdr *phdr;
size_t phnum;
const char *interp;
Elf_Word stack_flags;
int tlsindex;
void *tlsinit;
size_t tlsinitsize;
size_t tlssize;
size_t tlsoffset;
size_t tlsalign;
size_t tlspoffset;
Elf_Addr *pltgot;
const Elf_Rel *rel;
unsigned long relsize;
const Elf_Rela *rela;
unsigned long relasize;
const Elf_Relr *relr;
unsigned long relrsize;
const Elf_Rel *pltrel;
unsigned long pltrelsize;
const Elf_Rela *pltrela;
unsigned long pltrelasize;
const Elf_Sym *symtab;
const char *strtab;
unsigned long strsize;
const Elf_Verneed *verneed;
Elf_Word verneednum;
const Elf_Verdef *verdef;
Elf_Word verdefnum;
const Elf_Versym *versyms;
const Elf_Hashelt *buckets;
unsigned long nbuckets;
const Elf_Hashelt *chains;
unsigned long nchains;
Elf32_Word nbuckets_gnu;
Elf32_Word symndx_gnu;
Elf32_Word maskwords_bm_gnu;
Elf32_Word shift2_gnu;
Elf32_Word dynsymcount;
const Elf_Addr *bloom_gnu;
const Elf_Hashelt *buckets_gnu;
const Elf_Hashelt *chain_zero_gnu;
const char *rpath;
const char *runpath;
Needed_Entry *needed;
Needed_Entry *needed_filtees;
Needed_Entry *needed_aux_filtees;
STAILQ_HEAD(, Struct_Name_Entry) names;
Ver_Entry *vertab;
int vernum;
uintptr_t init;
uintptr_t fini;
uintptr_t *preinit_array;
uintptr_t *init_array;
uintptr_t *fini_array;
int preinit_array_num;
int init_array_num;
int fini_array_num;
int32_t osrel;
uint32_t fctl0;
bool mainprog : 1;
bool rtld : 1;
bool relocated : 1;
bool ver_checked : 1;
bool textrel : 1;
bool symbolic : 1;
bool deepbind : 1;
bool bind_now : 1;
bool traced : 1;
bool jmpslots_done : 1;
bool init_done : 1;
bool tls_static : 1;
bool tls_dynamic : 1;
bool phdr_alloc : 1;
bool z_origin : 1;
bool z_nodelete : 1;
bool z_noopen : 1;
bool z_loadfltr : 1;
bool z_interpose : 1;
bool z_nodeflib : 1;
bool z_global : 1;
bool z_pie : 1;
bool z_initfirst : 1;
bool static_tls : 1;
bool static_tls_copied : 1;
bool ref_nodel : 1;
bool init_scanned: 1;
bool on_fini_list: 1;
bool dag_inited : 1;
bool filtees_loaded : 1;
bool filtees_loading : 1;
bool irelative : 1;
bool irelative_nonplt : 1;
bool gnu_ifunc : 1;
bool non_plt_gnu_ifunc : 1;
bool ifuncs_resolved : 1;
bool crt_no_init : 1;
bool valid_hash_sysv : 1;
bool valid_hash_gnu : 1;
bool dlopened : 1;
bool marker : 1;
bool unholdfree : 1;
bool doomed : 1;
MD_OBJ_ENTRY
struct link_map linkmap;
Objlist dldags;
Objlist dagmembers;
dev_t dev;
ino_t ino;
void *priv;
} Obj_Entry;
#define RTLD_MAGIC 0xd550b87a
#define RTLD_VERSION 1
TAILQ_HEAD(obj_entry_q, Struct_Obj_Entry);
#define RTLD_STATIC_TLS_EXTRA 128
#define SYMLOOK_IN_PLT 0x01
#define SYMLOOK_DLSYM 0x02
#define SYMLOOK_EARLY 0x04
#define SYMLOOK_IFUNC 0x08
#define RTLD_LO_NOLOAD 0x01
#define RTLD_LO_DLOPEN 0x02
#define RTLD_LO_TRACE 0x04
#define RTLD_LO_NODELETE 0x08
#define RTLD_LO_FILTEES 0x10
#define RTLD_LO_EARLY 0x20
#define RTLD_LO_IGNSTLS 0x40
#define RTLD_LO_DEEPBIND 0x80
typedef struct Struct_SymCache {
const Elf_Sym *sym;
const Obj_Entry *obj;
} SymCache;
typedef struct Struct_DoneList {
const Obj_Entry **objs;
unsigned int num_alloc;
unsigned int num_used;
} DoneList;
struct Struct_RtldLockState {
int lockstate;
sigjmp_buf env;
};
struct fill_search_info_args {
int request;
unsigned int flags;
struct dl_serinfo *serinfo;
struct dl_serpath *serpath;
char *strspace;
};
typedef struct Struct_SymLook {
const char *name;
unsigned long hash;
uint32_t hash_gnu;
const Ver_Entry *ventry;
int flags;
const Obj_Entry *defobj_out;
const Elf_Sym *sym_out;
struct Struct_RtldLockState *lockstate;
} SymLook;
enum {
LD_BIND_NOW = 0,
LD_PRELOAD,
LD_LIBMAP,
LD_LIBRARY_PATH,
LD_LIBRARY_PATH_FDS,
LD_LIBMAP_DISABLE,
LD_BIND_NOT,
LD_DEBUG,
LD_ELF_HINTS_PATH,
LD_LOADFLTR,
LD_LIBRARY_PATH_RPATH,
LD_PRELOAD_FDS,
LD_DYNAMIC_WEAK,
LD_TRACE_LOADED_OBJECTS,
LD_UTRACE,
LD_DUMP_REL_PRE,
LD_DUMP_REL_POST,
LD_TRACE_LOADED_OBJECTS_PROGNAME,
LD_TRACE_LOADED_OBJECTS_FMT1,
LD_TRACE_LOADED_OBJECTS_FMT2,
LD_TRACE_LOADED_OBJECTS_ALL,
LD_SHOW_AUXV,
LD_STATIC_TLS_EXTRA,
LD_NO_DL_ITERATE_PHDR_AFTER_FORK,
};
void _rtld_error(const char *, ...) __printflike(1, 2) __exported;
void rtld_die(void) __dead2;
const char *rtld_strerror(int);
Obj_Entry *map_object(int, const char *, const struct stat *, bool);
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
char *xstrdup(const char *);
void *xmalloc_aligned(size_t size, size_t align, size_t offset);
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Sym sym_zero;
extern bool ld_bind_not;
extern bool ld_fast_sigblock;
void dump_relocations(Obj_Entry *);
void dump_obj_relocations(Obj_Entry *);
void dump_Elf_Rel(Obj_Entry *, const Elf_Rel *, u_long);
void dump_Elf_Rela(Obj_Entry *, const Elf_Rela *, u_long);
const char *ld_get_env_var(int idx);
uintptr_t rtld_round_page(uintptr_t);
uintptr_t rtld_trunc_page(uintptr_t);
Elf32_Word elf_hash(const char *);
const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *,
const Obj_Entry **, int, SymCache *, struct Struct_RtldLockState *);
void lockdflt_init(void);
void digest_notes(Obj_Entry *, Elf_Addr, Elf_Addr);
Obj_Entry *globallist_curr(const Obj_Entry *obj);
Obj_Entry *globallist_next(const Obj_Entry *obj);
void obj_free(Obj_Entry *);
Obj_Entry *obj_new(void);
Obj_Entry *obj_from_addr(const void *);
void _rtld_bind_start(void);
void *rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def);
void symlook_init(SymLook *, const char *);
int symlook_obj(SymLook *, const Obj_Entry *);
void *tls_get_addr_common(struct tcb *tcb, int index, size_t offset);
void *allocate_tls(Obj_Entry *, void *, size_t, size_t);
void free_tls(void *, size_t, size_t);
void *allocate_module_tls(struct tcb *tcb, int index);
bool allocate_tls_offset(Obj_Entry *obj);
void free_tls_offset(Obj_Entry *obj);
const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long);
int convert_prot(int elfflags);
bool check_elf_headers(const Elf_Ehdr *hdr, const char *path);
int do_copy_relocations(Obj_Entry *);
int reloc_non_plt(Obj_Entry *, Obj_Entry *, int flags,
struct Struct_RtldLockState *);
int reloc_plt(Obj_Entry *, int flags, struct Struct_RtldLockState *);
int reloc_jmpslots(Obj_Entry *, int flags, struct Struct_RtldLockState *);
int reloc_iresolve(Obj_Entry *, struct Struct_RtldLockState *);
int reloc_iresolve_nonplt(Obj_Entry *, struct Struct_RtldLockState *);
int reloc_gnu_ifunc(Obj_Entry *, int flags, struct Struct_RtldLockState *);
void ifunc_init(Elf_Auxinfo *[__min_size(AT_COUNT)]);
void init_pltgot(Obj_Entry *);
void allocate_initial_tls(Obj_Entry *);
#endif