bool rtems_rtl_obj_load (rtems_rtl_obj_t* obj) { int fd; if (!rtems_rtl_obj_fname_valid (obj)) { rtems_rtl_set_error (ENOMEM, "invalid object file name path"); return false; } fd = open (rtems_rtl_obj_fname (obj), O_RDONLY); if (fd < 0) { rtems_rtl_set_error (ENOMEM, "opening for object file"); return false; } /* * Find the object file in the archive if it is an archive that * has been opened. */ if (rtems_rtl_obj_aname_valid (obj)) { if (!rtems_rtl_obj_archive_find (obj, fd)) { rtems_rtl_obj_caches_flush (); close (fd); return false; } } /* * Call the format specific loader. Currently this is a call to the ELF * loader. This call could be changed to allow probes then calls if more than * one format is supported. */ if (!rtems_rtl_obj_file_load (obj, fd)) { rtems_rtl_obj_caches_flush (); close (fd); return false; } if (!_rtld_linkmap_add (obj)) /* For GDB */ { close (fd); return false; } rtems_rtl_obj_caches_flush (); close (fd); return true; }
/* * Load a shared object into memory, if it is not already loaded. * * Returns a pointer to the Obj_Entry for the object. Returns NULL * on failure. */ Obj_Entry * _rtld_load_object(const char *filepath, int flags) { Obj_Entry *obj; int fd = -1; struct stat sb; size_t pathlen = strlen(filepath); for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) if (pathlen == obj->pathlen && !strcmp(obj->path, filepath)) break; /* * If we didn't find a match by pathname, open the file and check * again by device and inode. This avoids false mismatches caused * by multiple links or ".." in pathnames. * * To avoid a race, we open the file and use fstat() rather than * using stat(). */ if (obj == NULL) { if ((fd = open(filepath, O_RDONLY)) == -1) { _rtld_error("Cannot open \"%s\"", filepath); return NULL; } if (fstat(fd, &sb) == -1) { _rtld_error("Cannot fstat \"%s\"", filepath); close(fd); return NULL; } for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) { if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) { close(fd); break; } } } if (obj == NULL) { /* First use of this object, so we must map it in */ obj = _rtld_map_object(filepath, fd, &sb); (void)close(fd); if (obj == NULL) return NULL; _rtld_digest_dynamic(filepath, obj); if (flags & _RTLD_DLOPEN) { if (obj->z_noopen || (flags & _RTLD_NOLOAD)) { dbg(("refusing to load non-loadable \"%s\"", obj->path)); _rtld_error("Cannot dlopen non-loadable %s", obj->path); munmap(obj->mapbase, obj->mapsize); _rtld_obj_free(obj); return OBJ_ERR; } } *_rtld_objtail = obj; _rtld_objtail = &obj->next; _rtld_objcount++; _rtld_objloads++; #ifdef RTLD_LOADER _rtld_linkmap_add(obj); /* for GDB */ #endif dbg((" %p .. %p: %s", obj->mapbase, obj->mapbase + obj->mapsize - 1, obj->path)); if (obj->textrel) dbg((" WARNING: %s has impure text", obj->path)); } ++obj->refcount; #ifdef RTLD_LOADER if (flags & _RTLD_MAIN && !obj->mainref) { obj->mainref = 1; dbg(("adding %p (%s) to _rtld_list_main", obj, obj->path)); _rtld_objlist_push_tail(&_rtld_list_main, obj); } if (flags & _RTLD_GLOBAL && !obj->globalref) { obj->globalref = 1; dbg(("adding %p (%s) to _rtld_list_global", obj, obj->path)); _rtld_objlist_push_tail(&_rtld_list_global, obj); } #endif return obj; }