ooff = _dl_find_symbol("atexit", _dl_objects, &sym, 0, 0);
ooff = _dl_find_symbol("atexit", _dl_objects, &sym, 0, 0, 1);
_dl_boot(const char **argv, char **envp, const long loff,	Elf_Dyn *dynp, long *dl_data){	struct elf_object *exe_obj;	/* Pointer to executable object */	struct elf_object *dyn_obj;	/* Pointer to executable object */	struct r_debug **map_link;	/* Where to put pointer for gdb */	struct r_debug *debug_map;	elf_object_t *dynobj;	Elf_Phdr *phdp;	char *us = "";	int n;	/*	 * Get paths to various things we are going to use.	 */	_dl_libpath = _dl_getenv("LD_LIBRARY_PATH", envp);	_dl_preload = _dl_getenv("LD_PRELOAD", envp);	_dl_bindnow = _dl_getenv("LD_BIND_NOW", envp);	_dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);	_dl_debug = _dl_getenv("LD_DEBUG", envp);	/*	 * Don't allow someone to change the search paths if he runs	 * a suid program without credentials high enough.	 */	if (_dl_issetugid()) {	/* Zap paths if s[ug]id... */		if (_dl_libpath) {			_dl_libpath = NULL;			_dl_unsetenv("LD_LIBRARY_PATH", envp);		}		if (_dl_preload) {			_dl_preload = NULL;			_dl_unsetenv("LD_PRELOAD", envp);		}		if (_dl_bindnow) {			_dl_bindnow = NULL;			_dl_unsetenv("LD_BIND_NOW", envp);		}		if (_dl_debug) {			_dl_debug = NULL;			_dl_unsetenv("LD_DEBUG", envp);		}	}	_dl_progname = argv[0];	if (dl_data[AUX_pagesz] != 0)		_dl_pagesz = dl_data[AUX_pagesz];	else		_dl_pagesz = 4096;	DL_DEB(("rtld loading: '%s'\n", _dl_progname));	exe_obj = NULL;	/*	 * Examine the user application and set up object information.	 */	phdp = (Elf_Phdr *)dl_data[AUX_phdr];	for (n = 0; n < dl_data[AUX_phnum]; n++) {		if (phdp->p_type == PT_DYNAMIC) {			exe_obj = _dl_add_object(argv[0],			    (Elf_Dyn *)phdp->p_vaddr, dl_data, OBJTYPE_EXE,			    0, 0);		}		if (phdp->p_type == PT_INTERP)			us = _dl_strdup((char *)phdp->p_vaddr);		phdp++;	}	if (_dl_preload != NULL)		_dl_dopreload(_dl_preload);	/*	 * Now, pick up and 'load' all libraries requierd. Start	 * with the first on the list and then do whatever gets	 * added along the tour.	 */	dynobj = _dl_objects;	while (dynobj) {		DL_DEB(("examining: '%s'\n", dynobj->load_name));		for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {			const char *libname;			if (dynp->d_tag != DT_NEEDED)				continue;			libname = dynobj->dyn.strtab;			libname += dynp->d_un.d_val;			DL_DEB(("needs: '%s'\n", libname));			if (_dl_load_shlib(libname, dynobj, OBJTYPE_LIB) == 0) {				_dl_printf("%s: can't load library '%s'\n",				    _dl_progname, libname);				_dl_exit(4);			}		}		dynobj = dynobj->next;	}	/*	 * Now add the dynamic loader itself last in the object list	 * so we can use the _dl_ code when serving dl.... calls.	 */	dynp = (Elf_Dyn *)((void *)_DYNAMIC);	dyn_obj = _dl_add_object(us, dynp, 0, OBJTYPE_LDR, dl_data[AUX_base], loff);	dyn_obj->status |= STAT_RELOC_DONE;	/*	 * Everything should be in place now for doing the relocation	 * and binding. Call _dl_rtld to do the job. Fingers crossed.	 */	if (_dl_traceld == NULL)		_dl_rtld(_dl_objects);	/*	 * The first object is the executable itself,	 * it is responsible for running it's own ctors/dtors	 * thus do NOT run the ctors for the executable, all of	 * the shared libraries which follow.	 * Do not run init code if run from ldd.	 */	if ((_dl_traceld == NULL) && (_dl_objects->next != NULL))		_dl_call_init(_dl_objects->next);	/*	 * Schedule a routine to be run at shutdown, by using atexit.	 * Cannot call atexit directly from ld.so?	 * Do not schedule destructors if run from ldd.	 */	if (_dl_traceld == NULL) {		const Elf_Sym *sym;		Elf_Addr ooff;		sym = NULL;		ooff = _dl_find_symbol("atexit", _dl_objects, &sym, 0, 0);		if (sym == NULL) {			_dl_printf("cannot find atexit, destructors will not be run!\n");		} else {			(*(void (*)(Elf_Addr))(sym->st_value + ooff))((Elf_Addr)_dl_dtors);		}	}	/*	 * Finally make something to help gdb when poking around in the code.	 */#ifdef __mips__	map_link = (struct r_debug **)(exe_obj->Dyn.info[DT_MIPS_RLD_MAP - DT_LOPROC + DT_NUM]);#else	map_link = NULL;	for (dynp = exe_obj->load_dyn; dynp->d_tag; dynp++) {		if (dynp->d_tag == DT_DEBUG) {			map_link = (struct r_debug **)&dynp->d_un.d_ptr;			break;		}	}	if (dynp->d_tag != DT_DEBUG) {		DL_DEB(("failed to mark DTDEBUG\n"));	}#endif	if (map_link) {		debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map));		debug_map->r_version = 1;		debug_map->r_map = (struct link_map *)_dl_objects;		debug_map->r_brk = (Elf_Addr)_dl_debug_state;		debug_map->r_state = RT_CONSISTENT;		debug_map->r_ldbase = loff;		_dl_debug_map = debug_map;		*map_link = _dl_debug_map;	}	_dl_debug_state();	if (_dl_debug || _dl_traceld) {		_dl_show_objects();		DL_DEB(("dynamic loading done.\n"));	}	if (_dl_traceld)		_dl_exit(0);	DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry]));	/*	 * Return the entry point.	 */	return(dl_data[AUX_entry]);}