#ifndef DYNSO_INTERNAL_H_ #define DYNSO_INTERNAL_H_ #include #include #include #include #include #include #include // glibc stuff... struct link_map_priv1 { // SVR4 ElfW(Addr) l_addr; char* l_name; ElfW(Dyn)* l_ld; struct link_map_priv1* l_next, *l_prev; // glibc-specific struct link_map_priv1* l_real; Lmid_t l_ns; struct libname_list* l_libname; ElfW(Dyn)* l_info[]; }; struct libname_list; struct r_found_version; struct r_search_path_elem; struct r_file_id { dev_t dev; ino64_t ino; }; struct r_scope_elem { struct link_map_priv1** r_list; unsigned int r_nlist; }; struct r_search_path_struct { struct r_search_path_elem** dirs; int malloced; }; struct link_map_priv2 { const ElfW(Phdr)* l_phdr; ElfW(Addr) l_entry; ElfW(Half) l_phnum; ElfW(Half) l_ldnum; struct r_scope_elem l_searchlist, l_symbolic_searchlist; struct link_map* l_loader; struct r_found_version* l_versions; unsigned int l_nversions; Elf_Symndx l_nbuckets; Elf32_Word l_gnu_bitmask_idxbits; Elf32_Word l_gnu_shift; const ElfW(Addr)* l_gnu_bitmask; union { const Elf32_Word* l_gnu_buckets; const Elf_Symndx* l_chain; }; union { const Elf32_Word* l_gnu_chain_zero; const Elf_Symndx* l_buckets; }; unsigned int l_direct_opencount; enum { lt_executable, lt_library, lt_loaded } l_type : 2; unsigned int l_relocated : 1; unsigned int l_init_called : 1; unsigned int l_global : 1; unsigned int l_reserved : 2; unsigned int l_phdr_allocated : 1; unsigned int l_soname_added : 1; unsigned int l_faked : 1; unsigned int l_need_tls_init : 1; unsigned int l_auditing : 1; unsigned int l_audit_any_plt : 1; unsigned int l_removed : 1; unsigned int l_contiguous : 1; unsigned int l_symbolic_in_local_scope : 1; unsigned int l_free_initfini : 1; //bool l_nodelete_active, l_nodelete_pending; // FIXME // ^ these two are added somewhere between glibc 2.30 (the one on my // system) and now (current master), I should probably add a priv3 thing // to accomodate for this, but EFFORT /*#if defined(__i386__) || defined(__x86_64__) enum { lc_unknown = 0, lc_none = 1<<0, lc_ibt = 1<<1, lc_shstk = 1<<2, lc_ibt_and_shstk = lc_ibt | lc_shstk } l_cet : 3; #endif*/ }; struct link_map_priv3 { struct r_search_path_struct l_rpath_dirs; struct reloc_result { ElfW(Addr) addr; struct link_map_priv1* bound; unsigned int boundndx; uint32_t enterexit; unsigned int flags; unsigned int init; } *l_reloc_result; ElfW(Versym)* l_versyms; const char* l_origin; ElfW(Addr) l_map_start, l_map_end; ElfW(Addr) l_text_end; struct r_scope_elem* l_scope_mem[4]; size_t l_scope_max; struct r_scope_elem** l_scope; struct r_scope_elem* l_local_scope[2]; struct r_file_id l_file_id; struct r_search_path_struct l_runpath_dirs; struct link_map** l_initfini; struct link_map_reldeps { unsigned int act; struct link_map* list[]; } *l_reldeps; unsigned int l_reldepsmax; unsigned int l_used; ElfW(Word) l_feature_1, l_flags_1, l_flags; int l_idx; // more stuff... }; typedef struct link_map_priv1* (*dl_new_object_f)(char* realname, const char* libname, int type, struct link_map* loader, int mode, Lmid_t nsid); typedef void (*dl_add_to_namespace_list_f)(struct link_map_priv1 *new, Lmid_t nsid); typedef void (*dl_setup_hash_f)(struct link_map_priv1* map); // actual stuff internal for this lib now struct rtldinfo { ElfW(Addr) base; ElfW(Sym)* symtab; char* strtab; size_t strsz; size_t shsz; ptrdiff_t syment; bool sym_malloc, str_malloc; }; struct inject_undo_info { struct r_scope_elem** dest; struct r_scope_elem* old; struct r_scope_elem* alloced; //struct link_map_priv1** rlist; }; struct dynso_sym { const char* name; void* value; size_t size; int type; }; struct dynso_lib { struct inject_undo_info undoinf; dl_new_object_f _dl_new_object; dl_add_to_namespace_list_f _dl_add_to_namespace_list; dl_setup_hash_f _dl_setup_hash; ElfW(Dyn)* dyn; ElfW(Sym)* sym; Elf_Symndx* idx; char* str; struct link_map_priv1* caller; struct link_map_priv1* fake1; struct link_map_priv2* fake2; struct link_map_priv3* fake3; struct dynso_sym* syms; size_t address; size_t nsyms; size_t syms_cap; Lmid_t ns; bool added; bool removed; bool alloc_syms; }; //extern void _start(void) __attribute__((__noreturn__)); static ptrdiff_t get_priv1_priv2_offset(void); static ptrdiff_t get_priv2_priv3_offset(void); static struct link_map_priv2* priv1_to_priv2(struct link_map_priv1* lm); static struct link_map_priv3* priv2_to_priv3(struct link_map_priv2* l2); inline static struct link_map_priv3* priv1_to_priv3(struct link_map_priv1* lm) { return priv2_to_priv3(priv1_to_priv2(lm)); } static enum dynso_err get_rtld_symtab(struct rtldinfo* inf); static enum dynso_err link_private_rtld_syms(struct dynso_lib* l); static enum dynso_err inject_in_scope_of(struct inject_undo_info* r, struct link_map_priv3* victim, struct link_map_priv1* add); static void inject_undo(const struct inject_undo_info* inf); #endif