📄 eshlibld.c
字号:
#define BUGVALUE_ABSSEG 0#define ABSSEG 2#define TEXTSEG 4#define DATASEG 6#define BSSSEG 8#define IS_UNDEF(x,syms) \ (((x) & 0x80000000) \ && (syms == NULL \ || SYMTYPE((syms)[SEGMENT(x)].symtyperaw) == UNKNOWN_SYM \ || (SYMTYPE((syms)[SEGMENT(x)].symtyperaw) >= WEAK_SYM \ && SYMTYPE((syms)[SEGMENT(x)].symtyperaw) <= WEAK_B_SYM)))#define IS_RESOLVED(x,syms) \ (((x) & 0x80000000) \ && (syms == NULL || SYMTYPE((syms)[SEGMENT(x)].symtyperaw) == ABS_SYM))#ifdef MARK_RELOC_DONE# define RELOC_OK(x) ((RELOCTYPE(x) & RELOC_32) == RELOC_32)#else# define RELOC_OK(x) (RELOCTYPE(x) == RELOC_32)#endif/* Check that nothing strange has crept in. Only used #ifdef SANITYCHECK_RELOC. */#define VALIDSEGSYM(segsym, symbols) \ ((IS_UNDEF(segsym, symbols) || IS_RESOLVED(segsym, symbols) \ || (((segsym) & 0xfcfffff0) == 0 \ && (SEGMENT(segsym) == TEXTSEG || SEGMENT(segsym) == DATASEG \ || SEGMENT(segsym) == ABSSEG \ || SEGMENT(segsym) == BUGVALUE_ABSSEG \ || SEGMENT(segsym) == BSSSEG))) \ /* Only 32-bit relocs for the moment, but use #3 internally. */ \ && RELOC_OK(segsym))/* File-format specific structures. *//* The file layout of each entry in the lib looks like this. */struct ar_header{ char ar_name[16]; /* name of this member */ char ar_date[12]; /* file mtime */ char ar_uid[6]; /* owner uid; printed as decimal */ char ar_gid[6]; /* owner gid; printed as decimal */ char ar_mode[8]; /* file mode, printed as octal */ char ar_size[10]; /* file size, printed as decimal */ char ar_fmag[2]; /* should contain ARFMAG */};/* Program-specific structures of all kinds. *//* When we access an libXXX.a file, this is what info we save about it (first one or two entries). */struct armap{ int libsize; /* Total file size of this archive. */ int firstobj; /* Location of first usable ar_header. */ char *extnames; /* Chunk with strings for "too-long" names. Null-terminated and indexed on offset. */ int extsize; /* Size of the chunk. */};/* For the libraries we're supposed to use, we take these notes. */struct libspec{ char path[PATH_MAX + 1 + NAME_MAX + 1]; /* Only present when needed. */ struct armap *map;#ifdef SHARE_LIB_CORE struct shliblist *shlib;#endif /* < -1 (as -2) = untried, -1 = exists, 0-N = fd. */ int fd_or_existsnote;#define LIBSPEC_UNCHECKED -2#define LIBSPEC_EXISTS -1};/* The "root" structure used when relocating/linking a program; holding anything that is not specific to an object-file or specific to a shared library. */struct progenv{ int env_flags;#define TRACE_LIB_FLAG (1 << 0)#define ALLOW_SHARE_FLAG (1 << 1)#define ALLOW_WRITE_DATA_FLAG (1 << 2)#define ALLOW_WRITE_DATA_SAME_UID_FLAG (1 << 3)#define EXPORT_PROGRAM_SYMBOLS_FLAG (1 << 4)#define PROG_FATAL_ERROR (1 << 5) char **libnames; /* Just the library names, as given. No paths. */ struct libspec *libs; /* \0-terminated libraries, at first with the first choice of library path, later (when accessed) adjusted to the correct one. */ char *libpath_first; int libpath_first_len; /* These look a little like much laziness. It is because we want to do as little as possible with the library paths (such as splitting at the ':':s) so we just store the pieces here. The one where libpath_first is extracted from (first non-null) just contains everything but the first piece. The default path "/usr/lib:/lib" is never here, just as (possibly) libpath_first. */ char *libpath_aout; char *libpath_lib; int euid; struct symlist *symbase; /* Symbols, starting with those for the program. */ int nlibs; /* Number of libraries. */ int nobjs; /* Number of objects. */ int n_loaded_objs; /* Number of loaded (non-placeholder) objects. */#if SHARE_LIB_CORE /* When dependencies on loaded objects are added, they should be added here. */ struct shlib_obj **nextshdep;#endif struct shlib_obj ***dlibsyms; /* This is where crt0 wants a pointer to the (null-terminated) ctor and dtor tables from libraries. Only one reference is allowed per object. */ void ***ctor_listp; void ***dtor_listp; /* Number of actual ctors and dtors in libraries. If we're lucky, this is 0, else we have to create a mmap for it (it cannot be shared). */ int n_ctors; int n_dtors; /* Looking up symbols can be very tedious without a hashtable. */ struct symhashentry *hashtable; /* For those entries colliding, we fall back to a linked list. */ /* Starting here. */ struct extended_hashentry *exthash_first; /* Put a pointer to the last one here. */ struct extended_hashentry **exthash_next;};/* The things used to relocate look like this; a.out external relocs. */struct reloctype{ unsigned long address; unsigned long segsym; unsigned long addend;};/* The things used to hold symbols look like this. */struct symtype{ unsigned long index; unsigned long symtyperaw; unsigned long value;};/* We need to keep track of which objects this object needed symbols from (the first level reference). Note that these references are not necessarily unique. */struct deplist{ struct deplist *next; /* This should satisfy 90%+ of all objects. */#define N_DEPCHUNK 32 struct symlist *dep[N_DEPCHUNK];};/* This is just to hide the real stuff inside a struct; it's all just a pointer to a NULL-terminated list (of pointers to shlib_objs). It's just data hiding from the rest of the kernel. ??? FIXME: Sometimes it's used for real, other times faking for shlibmod_exit and shlibmod_fork. Fix it better. */struct shlibdep{ struct shlib_obj **shdeps;};/* These two (three) are what we keep in the library shlib list. But first a common part, to confuse what is what. FIXME: It really does confuse, and maybe should be rewritten as it is not really needed. */struct shlibcommon{ char *name; struct shlibcommon *next;};struct shliblist{ struct shlibcommon common; struct shlib_obj *first_obj; struct shlib_obj **last_next;};struct shlib_obj{ struct shlibcommon common; /* I believe to include a back-pointer to the base library is the simplest way to get a handle to it, which is needed when to delete an object and when checking that dependencies are ok. */ struct shliblist *base_lib; /* Once for each user of any object. */ unsigned long usecount; unsigned long symslen; struct symtype *syms; unsigned long stringlen; char *strings; int euid; unsigned long text_data; unsigned long bss; /* In case this segment is not folded into code and data. */ struct shlibdep shdeps;};/* This is what we keep around about the symbols for an object. */struct symlist{ struct symtype *syms; unsigned long symslen; char *strings; unsigned long stringlen; struct symlist *next; unsigned long text; unsigned long textlen; unsigned long data; unsigned long datalen; unsigned long bss; unsigned long bsslen; /* Is < 0 if not a library, else index into penv->libs. */ long libindex;#if SHARE_LIB_CORE int n_odeps; struct deplist odeps; struct deplist *odeps_last; /* If we're about to turn this into an exported shared object, here's the representation of that (maybe minus correct dependencies). */ struct shlib_obj *as_shlib;#endif struct symtype *ctor; struct symtype *dtor; char *name; struct reloctype *relocs; unsigned long ntrelocs; unsigned long ndrelocs; unsigned long flags;#define SYML_IS_PRELOAD 1 /* This is something that *should be* preloaded. */#define SYML_DEP_UNKNOWN 2 /* Dunno yet. */#define SYML_DEP_VISITING 4 /* We're currently visiting this object (only used in update_dependencies). */#define SYML_DEP_CHEAT_SAME 8 /* Has cheated data or depends on cheated data from same UID. */#define SYML_DEP_CHEAT_OTHER 16 /* Maybe the above, and has cheated data or depends on cheated data from another UID. */#define SYML_DEP_BAD 32 /* Maybe the above, and this is a preloaded object or have/depends on non-cheated data or depends on symbols from an object not in a library in /usr/lib:/lib. */#define SYML_DEP_PROPAGATE_MASK \ (SYML_DEP_UNKNOWN + SYML_DEP_CHEAT_SAME + SYML_DEP_CHEAT_OTHER + SYML_DEP_BAD)#define SYML_IS_ALLOCATED 64 /* The relocs and symbol table for this object need to be free'd by itself. */#define SYML_IS_SHLIB 128 /* This is/has turned into a shared object. */#define SYML_WAS_PRELOAD 256 /* This is something that *was* preloaded. */#define SYML_DO_EXPORT 512#define MAX_FOLDED_BSS 500 /* Ad-hoc size in bytes. */#define SYML_BSS_FOLDED 2048 /* The bss segment was allocated together with the data and text segments). */};/* For symbols that are "magic", we have a special welcome-ceremony. */struct special_symbol_handling{ const char *symbol; int symbol_length; /* strlen (really: sizeof -1) of the above. */ int (*func)(struct symtype *, struct symlist *, struct progenv *);};/* A hashtable for the symbols is extremely helpful to cut lookup time. */struct symhashentry{ /* The slist member is NULL if the entry is unused. */ struct symlist *slist; struct symtype *sym;};/* Extended entries are pointed to by the slist member, with the sym member empty. They should be rare. */struct extended_hashentry{ struct symhashentry this; struct extended_hashentry *next; struct extended_hashentry *next_alloc;};/* I *know* this is theoretically better chosen a prime. But it seems reality wins (8191 is prime, and performance loses slightly). */#define N_HASHTABLE_ENTRIES 8192/* And here are the function prototypes (all should be here). */static intperform_cris_aout_list_relocations(struct symlist *slist, struct progenv *penv); static intget_sym(struct symtype *sym, struct symlist *slist, struct progenv *penv);static intperform_relocations(unsigned long text, unsigned long tlength, unsigned long data, unsigned long dlength, unsigned long baddr,#ifdef SANITYCHECK_RELOC unsigned long blength,#endif unsigned long segstart, unsigned char *rel, struct symlist *syms, struct progenv *penv);static char *ldso_getenv(const char *symbol, char **envp, int envc);static intmark_prog_sym_export(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intmark_cheated(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intadd_global_lib_ctor(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intadd_preload_main(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intadd_global_lib_dtor(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intset_global_lib_ctor_list(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intset_global_lib_dtor_list(struct symtype *symp, struct symlist *slist, struct progenv *penv);static intset_system_call(struct symtype *symp, struct symlist *slist, struct progenv *penv);/* Here are the (string and structure) constants. */static const char arfilenames[] = ARFILENAMES_NAME;static const char arfile_magic[] = ARFILE_MAGIC;static const char cheated_writable_data_symbol[] = CHEATED_WRITABLE_DATA_SYMBOL;static const char program_symbols_symbol[] = PROGRAM_SYMBOLS_SYMBOL;static const char system_call_symbol[] = SYSTEM_CALL_SYMBOL;static const char global_ctor_prefix[] = GLOBAL_CTOR_PREFIX;static const char global_dtor_prefix[] = GLOBAL_DTOR_PREFIX;static const char global_lib_ctor_list[] = GLOBAL_LIB_CTOR_LIST;static const char global_lib_dtor_list[] = GLOBAL_LIB_DTOR_LIST;static const char preload_main[] = PRELOAD_MAIN;/* I don't know how to assert that we work on on a char[] (as opposed to a char *). So just please don't break it. */#define SPECIAL_SYM_AND_LEN(x) x, sizeof(x) - 1/* Which symbol should need what special treatment. Not used for the main program. */static const struct special_symbol_handlingspecials[] ={ { SPECIAL_SYM_AND_LEN(program_symbols_symbol), mark_prog_sym_export }, { SPECIAL_SYM_AND_LEN(global_ctor_prefix), add_global_lib_ctor }, { SPECIAL_SYM_AND_LEN(global_dtor_prefix), add_global_lib_dtor }, { SPECIAL_SYM_AND_LEN(global_lib_ctor_list), set_global_lib_ctor_list }, { SPECIAL_SYM_AND_LEN(global_lib_dtor_list), set_global_lib_dtor_list }, { SPECIAL_SYM_AND_LEN(cheated_writable_data_symbol), mark_cheated }, { SPECIAL_SYM_AND_LEN(preload_main), add_preload_main }, { SPECIAL_SYM_AND_LEN(system_call_symbol), set_system_call }};#if SHARE_LIB_CORE/* VARIABLES */static struct local_vars{#ifdef RELOC_DEBUG /* Just the shared library chunks that are exported, so we can detect leaks for more than one exec. */ struct memdebug *alloclast;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -