Implement dlinfo() function.
Introdice RTLD_SELF special handle and properly process it within dlsym() and dlinfo() functions. The intention is to improve our compatibility with Solaris and to make a Java port easier. Partially submitted by: phantom
This commit is contained in:
parent
92b0ec0832
commit
42d206e975
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110804
@ -36,7 +36,7 @@
|
|||||||
#ifndef _DLFCN_H_
|
#ifndef _DLFCN_H_
|
||||||
#define _DLFCN_H_
|
#define _DLFCN_H_
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/_types.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modes and flags for dlopen().
|
* Modes and flags for dlopen().
|
||||||
@ -49,12 +49,28 @@
|
|||||||
#define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */
|
#define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special handle arguments for dlsym().
|
* Request arguments for dlinfo().
|
||||||
|
*/
|
||||||
|
#define RTLD_DI_LINKMAP 2 /* Obtain link map. */
|
||||||
|
#define RTLD_DI_SERINFO 4 /* Obtain search path info. */
|
||||||
|
#define RTLD_DI_SERINFOSIZE 5 /* ... query for required space. */
|
||||||
|
#define RTLD_DI_ORIGIN 6 /* Obtain object origin */
|
||||||
|
#define RTLD_DI_MAX RTLD_DI_ORIGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special handle arguments for dlsym()/dlinfo().
|
||||||
*/
|
*/
|
||||||
#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
|
#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
|
||||||
#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
|
#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
|
||||||
|
#define RTLD_SELF ((void *) -3) /* Search the caller itself. */
|
||||||
|
|
||||||
#if __BSD_VISIBLE
|
#if __BSD_VISIBLE
|
||||||
|
|
||||||
|
#ifndef _SIZE_T_DECLARED
|
||||||
|
typedef __size_t size_t;
|
||||||
|
#define _SIZE_T_DECLARED
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure filled in by dladdr().
|
* Structure filled in by dladdr().
|
||||||
*/
|
*/
|
||||||
@ -80,6 +96,20 @@ struct __dlfunc_arg {
|
|||||||
|
|
||||||
typedef void (*dlfunc_t)(struct __dlfunc_arg);
|
typedef void (*dlfunc_t)(struct __dlfunc_arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structures, returned by the RTLD_DI_SERINFO dlinfo() request.
|
||||||
|
*/
|
||||||
|
typedef struct dl_serpath {
|
||||||
|
char * dls_name; /* single search path entry */
|
||||||
|
unsigned int dls_flags; /* path information */
|
||||||
|
} Dl_serpath;
|
||||||
|
|
||||||
|
typedef struct dl_serinfo {
|
||||||
|
size_t dls_size; /* total buffer size */
|
||||||
|
unsigned int dls_cnt; /* number of path entries */
|
||||||
|
Dl_serpath dls_serpath[1]; /* there may be more than one */
|
||||||
|
} Dl_serinfo;
|
||||||
|
|
||||||
#endif /* __BSD_VISIBLE */
|
#endif /* __BSD_VISIBLE */
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
@ -91,8 +121,9 @@ void *dlopen(const char *, int);
|
|||||||
void *dlsym(void * __restrict, const char * __restrict);
|
void *dlsym(void * __restrict, const char * __restrict);
|
||||||
|
|
||||||
#if __BSD_VISIBLE
|
#if __BSD_VISIBLE
|
||||||
int dladdr(const void *, Dl_info *);
|
int dladdr(const void * __restrict, Dl_info * __restrict);
|
||||||
dlfunc_t dlfunc(void * __restrict, const char * __restrict);
|
dlfunc_t dlfunc(void * __restrict, const char * __restrict);
|
||||||
|
int dlinfo(void * __restrict, int, void * __restrict);
|
||||||
void dllockinit(void *_context,
|
void dllockinit(void *_context,
|
||||||
void *(*_lock_create)(void *_context),
|
void *(*_lock_create)(void *_context),
|
||||||
void (*_rlock_acquire)(void *_lock),
|
void (*_rlock_acquire)(void *_lock),
|
||||||
|
@ -103,3 +103,11 @@ dlsym(void * __restrict handle, const char * __restrict name)
|
|||||||
_rtld_error(sorry);
|
_rtld_error(sorry);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma weak dlinfo
|
||||||
|
int
|
||||||
|
dlinfo(void * __restrict handle, int request, void * __restrict p)
|
||||||
|
{
|
||||||
|
_rtld_error(sorry);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
|
* Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
|
||||||
|
* Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -57,6 +58,7 @@
|
|||||||
|
|
||||||
/* Types. */
|
/* Types. */
|
||||||
typedef void (*func_ptr_type)();
|
typedef void (*func_ptr_type)();
|
||||||
|
typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure provides a reentrant way to keep a list of objects and
|
* This structure provides a reentrant way to keep a list of objects and
|
||||||
@ -76,9 +78,11 @@ static void die(void);
|
|||||||
static void digest_dynamic(Obj_Entry *, int);
|
static void digest_dynamic(Obj_Entry *, int);
|
||||||
static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
|
static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
|
||||||
static Obj_Entry *dlcheck(void *);
|
static Obj_Entry *dlcheck(void *);
|
||||||
|
static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
|
||||||
static bool donelist_check(DoneList *, const Obj_Entry *);
|
static bool donelist_check(DoneList *, const Obj_Entry *);
|
||||||
static void errmsg_restore(char *);
|
static void errmsg_restore(char *);
|
||||||
static char *errmsg_save(void);
|
static char *errmsg_save(void);
|
||||||
|
static void *fill_search_info(const char *, size_t, void *);
|
||||||
static char *find_library(const char *, const Obj_Entry *);
|
static char *find_library(const char *, const Obj_Entry *);
|
||||||
static const char *gethints(void);
|
static const char *gethints(void);
|
||||||
static void init_dag(Obj_Entry *);
|
static void init_dag(Obj_Entry *);
|
||||||
@ -104,7 +108,9 @@ static void objlist_push_head(Objlist *, Obj_Entry *);
|
|||||||
static void objlist_push_tail(Objlist *, Obj_Entry *);
|
static void objlist_push_tail(Objlist *, Obj_Entry *);
|
||||||
static void objlist_remove(Objlist *, Obj_Entry *);
|
static void objlist_remove(Objlist *, Obj_Entry *);
|
||||||
static void objlist_remove_unref(Objlist *);
|
static void objlist_remove_unref(Objlist *);
|
||||||
|
static void *path_enumerate(const char *, path_enum_proc, void *);
|
||||||
static int relocate_objects(Obj_Entry *, bool, Obj_Entry *);
|
static int relocate_objects(Obj_Entry *, bool, Obj_Entry *);
|
||||||
|
static int rtld_dirname(const char *, char *);
|
||||||
static void rtld_exit(void);
|
static void rtld_exit(void);
|
||||||
static char *search_library_path(const char *, const char *);
|
static char *search_library_path(const char *, const char *);
|
||||||
static const void **get_program_var_addr(const char *name);
|
static const void **get_program_var_addr(const char *name);
|
||||||
@ -123,7 +129,7 @@ void r_debug_state(struct r_debug*, struct link_map*);
|
|||||||
* Data declarations.
|
* Data declarations.
|
||||||
*/
|
*/
|
||||||
static char *error_message; /* Message for dlerror(), or NULL */
|
static char *error_message; /* Message for dlerror(), or NULL */
|
||||||
struct r_debug r_debug; /* for GDB; */
|
struct r_debug r_debug; /* for GDB; */
|
||||||
static bool trust; /* False for setuid and setgid programs */
|
static bool trust; /* False for setuid and setgid programs */
|
||||||
static char *ld_bind_now; /* Environment variable for immediate binding */
|
static char *ld_bind_now; /* Environment variable for immediate binding */
|
||||||
static char *ld_debug; /* Environment variable for debugging */
|
static char *ld_debug; /* Environment variable for debugging */
|
||||||
@ -166,6 +172,7 @@ static func_ptr_type exports[] = {
|
|||||||
(func_ptr_type) &dlsym,
|
(func_ptr_type) &dlsym,
|
||||||
(func_ptr_type) &dladdr,
|
(func_ptr_type) &dladdr,
|
||||||
(func_ptr_type) &dllockinit,
|
(func_ptr_type) &dllockinit,
|
||||||
|
(func_ptr_type) &dlinfo,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1193,7 +1200,7 @@ load_object(char *path)
|
|||||||
*obj_tail = obj;
|
*obj_tail = obj;
|
||||||
obj_tail = &obj->next;
|
obj_tail = &obj->next;
|
||||||
obj_count++;
|
obj_count++;
|
||||||
linkmap_add(obj); /* for GDB */
|
linkmap_add(obj); /* for GDB & dlinfo() */
|
||||||
|
|
||||||
dbg(" %p .. %p: %s", obj->mapbase,
|
dbg(" %p .. %p: %s", obj->mapbase,
|
||||||
obj->mapbase + obj->mapsize - 1, obj->path);
|
obj->mapbase + obj->mapsize - 1, obj->path);
|
||||||
@ -1462,40 +1469,83 @@ rtld_exit(void)
|
|||||||
/* No need to remove the items from the list, since we are exiting. */
|
/* No need to remove the items from the list, since we are exiting. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
path_enumerate(const char *path, path_enum_proc callback, void *arg)
|
||||||
|
{
|
||||||
|
if (path == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
path += strspn(path, ":;");
|
||||||
|
while (*path != '\0') {
|
||||||
|
size_t len;
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
len = strcspn(path, ":;");
|
||||||
|
res = callback(path, len, arg);
|
||||||
|
|
||||||
|
if (res != NULL)
|
||||||
|
return (res);
|
||||||
|
|
||||||
|
path += len;
|
||||||
|
path += strspn(path, ":;");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct try_library_args {
|
||||||
|
const char *name;
|
||||||
|
size_t namelen;
|
||||||
|
char *buffer;
|
||||||
|
size_t buflen;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
try_library_path(const char *dir, size_t dirlen, void *param)
|
||||||
|
{
|
||||||
|
struct try_library_args *arg;
|
||||||
|
|
||||||
|
arg = param;
|
||||||
|
if (*dir == '/' || trust) {
|
||||||
|
char *pathname;
|
||||||
|
|
||||||
|
if (dirlen + 1 + arg->namelen + 1 > arg->buflen)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
pathname = arg->buffer;
|
||||||
|
strncpy(pathname, dir, dirlen);
|
||||||
|
pathname[dirlen] = '/';
|
||||||
|
strcpy(pathname + dirlen + 1, arg->name);
|
||||||
|
|
||||||
|
dbg(" Trying \"%s\"", pathname);
|
||||||
|
if (access(pathname, F_OK) == 0) { /* We found it */
|
||||||
|
pathname = xmalloc(dirlen + 1 + arg->namelen + 1);
|
||||||
|
strcpy(pathname, arg->buffer);
|
||||||
|
return (pathname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
search_library_path(const char *name, const char *path)
|
search_library_path(const char *name, const char *path)
|
||||||
{
|
{
|
||||||
size_t namelen = strlen(name);
|
char *p;
|
||||||
const char *p = path;
|
struct try_library_args arg;
|
||||||
|
|
||||||
if (p == NULL)
|
if (path == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
p += strspn(p, ":;");
|
arg.name = name;
|
||||||
while (*p != '\0') {
|
arg.namelen = strlen(name);
|
||||||
size_t len = strcspn(p, ":;");
|
arg.buffer = xmalloc(PATH_MAX);
|
||||||
|
arg.buflen = PATH_MAX;
|
||||||
|
|
||||||
if (*p == '/' || trust) {
|
p = path_enumerate(path, try_library_path, &arg);
|
||||||
char *pathname;
|
|
||||||
const char *dir = p;
|
|
||||||
size_t dirlen = len;
|
|
||||||
|
|
||||||
pathname = xmalloc(dirlen + 1 + namelen + 1);
|
free(arg.buffer);
|
||||||
strncpy(pathname, dir, dirlen);
|
|
||||||
pathname[dirlen] = '/';
|
|
||||||
strcpy(pathname + dirlen + 1, name);
|
|
||||||
|
|
||||||
dbg(" Trying \"%s\"", pathname);
|
return (p);
|
||||||
if (access(pathname, F_OK) == 0) /* We found it */
|
|
||||||
return pathname;
|
|
||||||
|
|
||||||
free(pathname);
|
|
||||||
}
|
|
||||||
p += len;
|
|
||||||
p += strspn(p, ":;");
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1647,7 +1697,8 @@ dlsym(void *handle, const char *name)
|
|||||||
defobj = NULL;
|
defobj = NULL;
|
||||||
|
|
||||||
rlock_acquire();
|
rlock_acquire();
|
||||||
if (handle == NULL || handle == RTLD_NEXT || handle == RTLD_DEFAULT) {
|
if (handle == NULL || handle == RTLD_NEXT ||
|
||||||
|
handle == RTLD_DEFAULT || handle == RTLD_SELF) {
|
||||||
void *retaddr;
|
void *retaddr;
|
||||||
|
|
||||||
retaddr = __builtin_return_address(0); /* __GNUC__ only */
|
retaddr = __builtin_return_address(0); /* __GNUC__ only */
|
||||||
@ -1659,8 +1710,11 @@ dlsym(void *handle, const char *name)
|
|||||||
if (handle == NULL) { /* Just the caller's shared object. */
|
if (handle == NULL) { /* Just the caller's shared object. */
|
||||||
def = symlook_obj(name, hash, obj, true);
|
def = symlook_obj(name, hash, obj, true);
|
||||||
defobj = obj;
|
defobj = obj;
|
||||||
} else if (handle == RTLD_NEXT) { /* Objects after caller's */
|
} else if (handle == RTLD_NEXT || /* Objects after caller's */
|
||||||
while ((obj = obj->next) != NULL) {
|
handle == RTLD_SELF) { /* ... caller included */
|
||||||
|
if (handle == RTLD_NEXT)
|
||||||
|
obj = obj->next;
|
||||||
|
for (; obj != NULL; obj = obj->next) {
|
||||||
if ((def = symlook_obj(name, hash, obj, true)) != NULL) {
|
if ((def = symlook_obj(name, hash, obj, true)) != NULL) {
|
||||||
defobj = obj;
|
defobj = obj;
|
||||||
break;
|
break;
|
||||||
@ -1722,7 +1776,7 @@ dladdr(const void *addr, Dl_info *info)
|
|||||||
const Elf_Sym *def;
|
const Elf_Sym *def;
|
||||||
void *symbol_addr;
|
void *symbol_addr;
|
||||||
unsigned long symoffset;
|
unsigned long symoffset;
|
||||||
|
|
||||||
rlock_acquire();
|
rlock_acquire();
|
||||||
obj = obj_from_addr(addr);
|
obj = obj_from_addr(addr);
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
@ -1770,6 +1824,182 @@ dladdr(const void *addr, Dl_info *info)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dlinfo(void *handle, int request, void *p)
|
||||||
|
{
|
||||||
|
const Obj_Entry *obj;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
rlock_acquire();
|
||||||
|
|
||||||
|
if (handle == NULL || handle == RTLD_SELF) {
|
||||||
|
void *retaddr;
|
||||||
|
|
||||||
|
retaddr = __builtin_return_address(0); /* __GNUC__ only */
|
||||||
|
if ((obj = obj_from_addr(retaddr)) == NULL)
|
||||||
|
_rtld_error("Cannot determine caller's shared object");
|
||||||
|
} else
|
||||||
|
obj = dlcheck(handle);
|
||||||
|
|
||||||
|
if (obj == NULL) {
|
||||||
|
rlock_release();
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
switch (request) {
|
||||||
|
case RTLD_DI_LINKMAP:
|
||||||
|
*((struct link_map const **)p) = &obj->linkmap;
|
||||||
|
break;
|
||||||
|
case RTLD_DI_ORIGIN:
|
||||||
|
error = rtld_dirname(obj->path, p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTLD_DI_SERINFOSIZE:
|
||||||
|
case RTLD_DI_SERINFO:
|
||||||
|
error = do_search_info(obj, request, (struct dl_serinfo *)p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_rtld_error("Invalid request %d passed to dlinfo()", request);
|
||||||
|
error = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rlock_release();
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fill_search_info_args {
|
||||||
|
int request;
|
||||||
|
unsigned int flags;
|
||||||
|
Dl_serinfo *serinfo;
|
||||||
|
Dl_serpath *serpath;
|
||||||
|
char *strspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
fill_search_info(const char *dir, size_t dirlen, void *param)
|
||||||
|
{
|
||||||
|
struct fill_search_info_args *arg;
|
||||||
|
|
||||||
|
arg = param;
|
||||||
|
|
||||||
|
if (arg->request == RTLD_DI_SERINFOSIZE) {
|
||||||
|
arg->serinfo->dls_cnt ++;
|
||||||
|
arg->serinfo->dls_size += dirlen + 1;
|
||||||
|
} else {
|
||||||
|
struct dl_serpath *s_entry;
|
||||||
|
|
||||||
|
s_entry = arg->serpath;
|
||||||
|
s_entry->dls_name = arg->strspace;
|
||||||
|
s_entry->dls_flags = arg->flags;
|
||||||
|
|
||||||
|
strncpy(arg->strspace, dir, dirlen);
|
||||||
|
arg->strspace[dirlen] = '\0';
|
||||||
|
|
||||||
|
arg->strspace += dirlen + 1;
|
||||||
|
arg->serpath++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info)
|
||||||
|
{
|
||||||
|
struct dl_serinfo _info;
|
||||||
|
struct fill_search_info_args args;
|
||||||
|
|
||||||
|
args.request = RTLD_DI_SERINFOSIZE;
|
||||||
|
args.serinfo = &_info;
|
||||||
|
|
||||||
|
_info.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
|
||||||
|
_info.dls_cnt = 0;
|
||||||
|
|
||||||
|
path_enumerate(ld_library_path, fill_search_info, &args);
|
||||||
|
path_enumerate(obj->rpath, fill_search_info, &args);
|
||||||
|
path_enumerate(gethints(), fill_search_info, &args);
|
||||||
|
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args);
|
||||||
|
|
||||||
|
|
||||||
|
if (request == RTLD_DI_SERINFOSIZE) {
|
||||||
|
info->dls_size = _info.dls_size;
|
||||||
|
info->dls_cnt = _info.dls_cnt;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->dls_cnt != _info.dls_cnt || info->dls_size != _info.dls_size) {
|
||||||
|
_rtld_error("Uninitialized Dl_serinfo struct passed to dlinfo()");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.request = RTLD_DI_SERINFO;
|
||||||
|
args.serinfo = info;
|
||||||
|
args.serpath = &info->dls_serpath[0];
|
||||||
|
args.strspace = (char *)&info->dls_serpath[_info.dls_cnt];
|
||||||
|
|
||||||
|
args.flags = LA_SER_LIBPATH;
|
||||||
|
if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
args.flags = LA_SER_RUNPATH;
|
||||||
|
if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
args.flags = LA_SER_CONFIG;
|
||||||
|
if (path_enumerate(gethints(), fill_search_info, &args) != NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
args.flags = LA_SER_DEFAULT;
|
||||||
|
if (path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL)
|
||||||
|
return (-1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rtld_dirname(const char *path, char *bname)
|
||||||
|
{
|
||||||
|
const char *endp;
|
||||||
|
|
||||||
|
/* Empty or NULL string gets treated as "." */
|
||||||
|
if (path == NULL || *path == '\0') {
|
||||||
|
bname[0] = '.';
|
||||||
|
bname[1] = '0';
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip trailing slashes */
|
||||||
|
endp = path + strlen(path) - 1;
|
||||||
|
while (endp > path && *endp == '/')
|
||||||
|
endp--;
|
||||||
|
|
||||||
|
/* Find the start of the dir */
|
||||||
|
while (endp > path && *endp != '/')
|
||||||
|
endp--;
|
||||||
|
|
||||||
|
/* Either the dir is "/" or there are no slashes */
|
||||||
|
if (endp == path) {
|
||||||
|
bname[0] = *endp == '/' ? '/' : '.';
|
||||||
|
bname[1] = '\0';
|
||||||
|
return (0);
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
endp--;
|
||||||
|
} while (endp > path && *endp == '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endp - path + 2 > PATH_MAX)
|
||||||
|
{
|
||||||
|
_rtld_error("Filename is too long: %s", path);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(bname, path, endp - path + 1);
|
||||||
|
bname[endp - path + 1] = '\0';
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
linkmap_add(Obj_Entry *obj)
|
linkmap_add(Obj_Entry *obj)
|
||||||
{
|
{
|
||||||
@ -1788,7 +2018,7 @@ linkmap_add(Obj_Entry *obj)
|
|||||||
r_debug.r_map = l;
|
r_debug.r_map = l;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan to the end of the list, but not past the entry for the
|
* Scan to the end of the list, but not past the entry for the
|
||||||
* dynamic linker, which we want to keep at the very end.
|
* dynamic linker, which we want to keep at the very end.
|
||||||
|
@ -156,7 +156,7 @@ typedef struct Struct_Obj_Entry {
|
|||||||
bool jmpslots_done; /* Already have relocated the jump slots */
|
bool jmpslots_done; /* Already have relocated the jump slots */
|
||||||
bool init_done; /* Already have added object to init list */
|
bool init_done; /* Already have added object to init list */
|
||||||
|
|
||||||
struct link_map linkmap; /* for GDB */
|
struct link_map linkmap; /* for GDB and dlinfo() */
|
||||||
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
|
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
|
||||||
Objlist dagmembers; /* DAG has these members (%) */
|
Objlist dagmembers; /* DAG has these members (%) */
|
||||||
dev_t dev; /* Object's filesystem's device */
|
dev_t dev; /* Object's filesystem's device */
|
||||||
|
@ -43,7 +43,18 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
struct link_map {
|
/*
|
||||||
|
* Flags that describe the origin of the entries in Dl_serinfo.
|
||||||
|
* SunOS has these in <sys/link.h>, we follow the suit.
|
||||||
|
*/
|
||||||
|
#define LA_SER_ORIG 0x01 /* original (needed) name */
|
||||||
|
#define LA_SER_LIBPATH 0x02 /* LD_LIBRARY_PATH entry prepended */
|
||||||
|
#define LA_SER_RUNPATH 0x04 /* runpath entry prepended */
|
||||||
|
#define LA_SER_CONFIG 0x08 /* configuration entry prepended */
|
||||||
|
#define LA_SER_DEFAULT 0x40 /* default path prepended */
|
||||||
|
#define LA_SER_SECURE 0x80 /* default (secure) path prepended */
|
||||||
|
|
||||||
|
typedef struct link_map {
|
||||||
caddr_t l_addr; /* Base Address of library */
|
caddr_t l_addr; /* Base Address of library */
|
||||||
#ifdef __mips__
|
#ifdef __mips__
|
||||||
caddr_t l_offs; /* Load Offset of library */
|
caddr_t l_offs; /* Load Offset of library */
|
||||||
@ -51,7 +62,7 @@ struct link_map {
|
|||||||
const char *l_name; /* Absolute Path to Library */
|
const char *l_name; /* Absolute Path to Library */
|
||||||
const void *l_ld; /* Pointer to .dynamic in memory */
|
const void *l_ld; /* Pointer to .dynamic in memory */
|
||||||
struct link_map *l_next, *l_prev; /* linked list of of mapped libs */
|
struct link_map *l_next, *l_prev; /* linked list of of mapped libs */
|
||||||
};
|
} Link_map;
|
||||||
|
|
||||||
struct r_debug {
|
struct r_debug {
|
||||||
int r_version; /* not used */
|
int r_version; /* not used */
|
||||||
|
Loading…
Reference in New Issue
Block a user