[uClibc-cvs] uClibc/ldso/include .cvsignore, NONE, 1.1 dlfcn.h, NONE, 1.1 ld_elf.h, NONE, 1.1 ld_hash.h, NONE, 1.1 ld_string.h, NONE, 1.1 ld_syscall.h, NONE, 1.1 ldso.h, NONE, 1.1

Erik Andersen andersen at uclibc.org
Tue Aug 19 06:05:33 UTC 2003


Update of /var/cvs/uClibc/ldso/include
In directory winder:/tmp/cvs-serv5232/include

Added Files:
	.cvsignore dlfcn.h ld_elf.h ld_hash.h ld_string.h ld_syscall.h 
	ldso.h 
Log Message:
Phase one of my evil plan to clean up ld.so...


--- NEW FILE: ld_syscall.h ---
#ifndef _LD_SYSCALL_H_
#define _LD_SYSCALL_H_

/* Pull in the arch specific syscall implementation */
#include <ld_syscalls.h>
/*  For MAP_ANONYMOUS -- differs between platforms */
#include <asm/mman.h>			
/* Pull in whatever this particular arch's kernel thinks the kernel version of
 * struct stat should look like.  It turns out that each arch has a different
 * opinion on the subject, and different kernel revs use different names... */
#define kernel_stat stat
#include <bits/kernel_stat.h>


/* Encoding of the file mode.  */
#define	S_IFMT		0170000	/* These bits determine file type.  */

/* File types.  */
#define	S_IFDIR		0040000	/* Directory.  */
#define	S_IFCHR		0020000	/* Character device.  */
#define	S_IFBLK		0060000	/* Block device.  */
#define	S_IFREG		0100000	/* Regular file.  */
#define	S_IFIFO		0010000	/* FIFO.  */
#define	S_IFLNK		0120000	/* Symbolic link.  */
#define	S_IFSOCK	0140000	/* Socket.  */

/* Protection bits.  */

#define	S_ISUID		04000	/* Set user ID on execution.  */
#define	S_ISGID		02000	/* Set group ID on execution.  */
#define	S_ISVTX		01000	/* Save swapped text after use (sticky).  */
#define	S_IREAD		0400	/* Read by owner.  */
#define	S_IWRITE	0200	/* Write by owner.  */
#define	S_IEXEC		0100	/* Execute by owner.  */


/* Here are the definitions for some syscalls that are used
   by the dynamic linker.  The idea is that we want to be able
   to call these before the errno symbol is dynamicly linked, so
   we use our own version here.  Note that we cannot assume any
   dynamic linking at all, so we cannot return any error codes.
   We just punt if there is an error. */


#define __NR__dl_exit __NR_exit
static inline _syscall1(void, _dl_exit, int, status);


#define __NR__dl_close __NR_close
static inline _syscall1(int, _dl_close, int, fd);


#if defined(__powerpc__) || defined(__mips__) || defined(__sh__)
/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */
#define __NR__dl_mmap __NR_mmap
static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
		int, prot, int, flags, int, fd, off_t, offset);
#else
#define __NR__dl_mmap_real __NR_mmap
static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);

static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
		int flags, int fd, unsigned long offset)
{
	unsigned long buffer[6];

	buffer[0] = (unsigned long) addr;
	buffer[1] = (unsigned long) size;
	buffer[2] = (unsigned long) prot;
	buffer[3] = (unsigned long) flags;
	buffer[4] = (unsigned long) fd;
	buffer[5] = (unsigned long) offset;
	return (void *) _dl_mmap_real(buffer);
}
#endif

#ifndef _dl_MAX_ERRNO
#define _dl_MAX_ERRNO 4096
#endif
#define _dl_mmap_check_error(__res)	\
	(((int)__res) < 0 && ((int)__res) >= -_dl_MAX_ERRNO)
#ifndef MAP_ANONYMOUS
#ifdef __sparc__
#define MAP_ANONYMOUS 0x20
#else
#error MAP_ANONYMOUS not defined and suplementary value not known
#endif
#endif


#define __NR__dl_open __NR_open
#define O_RDONLY        0x0000
#define O_WRONLY	     01
#define O_RDWR		     02
#define O_CREAT		   0100	/* not fcntl */
static inline _syscall2(int, _dl_open, const char *, fn, int, flags);

#define __NR__dl_write __NR_write
static inline _syscall3(unsigned long, _dl_write, int, fd, 
	    const void *, buf, unsigned long, count);


#define __NR__dl_read __NR_read
static inline _syscall3(unsigned long, _dl_read, int, fd, 
	    const void *, buf, unsigned long, count);

#define __NR__dl_mprotect __NR_mprotect
static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot);



#define __NR__dl_stat __NR_stat
static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);


#define __NR__dl_munmap __NR_munmap
static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);

#define __NR__dl_getuid __NR_getuid
static inline _syscall0(uid_t, _dl_getuid);

#define __NR__dl_geteuid __NR_geteuid
static inline _syscall0(uid_t, _dl_geteuid);

#define __NR__dl_getgid __NR_getgid
static inline _syscall0(gid_t, _dl_getgid);

#define __NR__dl_getegid __NR_getegid
static inline _syscall0(gid_t, _dl_getegid);

#define __NR__dl_getpid __NR_getpid
static inline _syscall0(gid_t, _dl_getpid);

/*
 * Not an actual syscall, but we need something in assembly to say whether
 * this is OK or not.
 */
static inline int _dl_suid_ok(void)
{
    uid_t uid, euid, gid, egid;

    uid = _dl_getuid();
    euid = _dl_geteuid();
    gid = _dl_getgid();
    egid = _dl_getegid();

    if(uid == euid && gid == egid)
	return 1;
    else
	return 0;
}

#define __NR__dl_readlink __NR_readlink
static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);

#endif /* _LD_SYSCALL_H_ */


--- NEW FILE: ld_elf.h ---
#ifndef LINUXELF_H
#define LINUXELF_H

#include <ld_sysdep.h> /* before elf.h to get ELF_USES_RELOCA right */
#include <elf.h>
#include <link.h>

#ifdef DEBUG
#  define LDSO_CONF  "../util/ld.so.conf"
#  define LDSO_CACHE "../util/ld.so.cache"
#  define LDSO_PRELOAD "../util/ld.so.preload"
#else
#  define LDSO_CONF  UCLIBC_TARGET_PREFIX "etc/ld.so.conf"
#  define LDSO_CACHE UCLIBC_TARGET_PREFIX "etc/ld.so.cache"
#  define LDSO_PRELOAD UCLIBC_TARGET_PREFIX "etc/ld.so.preload"
#endif


#define LIB_ANY	     -1
#define LIB_DLL       0
#define LIB_ELF       1
#define LIB_ELF_LIBC5 2
#define LIB_ELF_LIBC6 3
#define LIB_ELF64     0x80

/* Forward declarations for stuff defined in ld_hash.h */
struct dyn_elf;
struct elf_resolve;


/* Definitions and prototypes for cache stuff */
#ifdef USE_CACHE
extern int _dl_map_cache(void);
extern int _dl_unmap_cache(void);

#define LDSO_CACHE_MAGIC "ld.so-"
#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1)
#define LDSO_CACHE_VER "1.7.0"
#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1)

typedef struct {
	char magic   [LDSO_CACHE_MAGIC_LEN];
	char version [LDSO_CACHE_VER_LEN];
	int nlibs;
} header_t;

typedef struct {
	int flags;
	int sooffset;
	int liboffset;
} libentry_t;

#else
static inline void _dl_map_cache(void) { }
static inline void _dl_unmap_cache(void) { }
#endif	


/* Function prototypes for non-static stuff in readelflib1.c */
int _dl_copy_fixups(struct dyn_elf * tpnt);
extern int _dl_parse_copy_information(struct dyn_elf *rpnt,
	unsigned long rel_addr, unsigned long rel_size, int type);
extern void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
	unsigned long rel_addr, unsigned long rel_size, int type);
extern int _dl_parse_relocation_information(struct elf_resolve *tpnt,
	unsigned long rel_addr, unsigned long rel_size, int type);
extern struct elf_resolve * _dl_load_shared_library(int secure, 
	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname);
extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
	struct dyn_elf **rpnt, char *libname);
extern int _dl_linux_resolve(void);


/*
 * Datatype of a relocation on this platform
 */
#ifdef ELF_USES_RELOCA
# define ELF_RELOC	ElfW(Rela)
#else
# define ELF_RELOC	ElfW(Rel)
#endif


/* Convert between the Linux flags for page protections and the
   ones specified in the ELF standard. */
#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \
		    (((X) & PF_W) ? PROT_WRITE : 0) | \
		    (((X) & PF_X) ? PROT_EXEC : 0))


#endif	/* LINUXELF_H */

--- NEW FILE: ld_hash.h ---
#ifndef _LD_HASH_H_
#define _LD_HASH_H_

#ifndef RTLD_NEXT
#define RTLD_NEXT	((void*)-1)
#endif

struct dyn_elf{
  unsigned long flags;
  struct elf_resolve * dyn;
  struct dyn_elf * next_handle;  /* Used by dlopen et al. */
  struct dyn_elf * next;
  struct dyn_elf * prev;
};
 
struct elf_resolve{
  /* These entries must be in this order to be compatible with the interface used
     by gdb to obtain the list of symbols. */
  char * loadaddr;
  char * libname;
  unsigned long dynamic_addr;
  struct elf_resolve * next;
  struct elf_resolve * prev;
  /* Nothing after this address is used by gdb. */
  enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype;
  struct dyn_elf * symbol_scope;
  unsigned short usage_count;
  unsigned short int init_flag;
  unsigned int nbucket;
  unsigned long * elf_buckets;
  /*
   * These are only used with ELF style shared libraries
   */
  unsigned long nchain;
  unsigned long * chains;
  unsigned long dynamic_info[24];

  unsigned long dynamic_size;
  unsigned long n_phent;
  Elf32_Phdr * ppnt;

#if defined(__mips__)
  /* Needed for MIPS relocation */
  unsigned long mips_gotsym;
  unsigned long mips_local_gotno;
  unsigned long mips_symtabno;
#endif

#ifdef __powerpc__
  /* this is used to store the address of relocation data words, so
   * we don't have to calculate it every time, which requires a divide */
  unsigned long data_words;
#endif
};

#if 0
/*
 * The DT_DEBUG entry in the .dynamic section is given the address of this structure.
 * gdb can pick this up to obtain the correct list of loaded modules.
 */

struct r_debug{
  int r_version;
  struct elf_resolve * link_map;
  unsigned long brk_fun;
  enum {RT_CONSISTENT, RT_ADD, RT_DELETE};
  unsigned long ldbase;
};
#endif

#define COPY_RELOCS_DONE 1
#define RELOCS_DONE 2
#define JMP_RELOCS_DONE 4
#define INIT_FUNCS_CALLED 8

extern struct dyn_elf     * _dl_symbol_tables;
extern struct elf_resolve * _dl_loaded_modules;
extern struct dyn_elf 	  * _dl_handles;

extern struct elf_resolve * _dl_check_hashed_files(const char * libname);
extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, 
	char * loadaddr, unsigned long * dynamic_info, 
	unsigned long dynamic_addr, unsigned long dynamic_size);

enum caller_type{symbolrel=0,copyrel=1,resolver=2};
extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, 
	struct elf_resolve * f_tpnt, enum caller_type);

extern int _dl_linux_dynamic_link(void);

extern char * _dl_library_path;
extern char * _dl_not_lazy;
extern unsigned long _dl_elf_hash(const char * name);

static inline int _dl_symbol(char * name)
{
  if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_')
    return 0;
  return 1;
}


#define LD_ERROR_NOFILE 1
#define LD_ERROR_NOZERO 2
#define LD_ERROR_NOTELF 3
#define LD_ERROR_NOTMAGIC 4
#define LD_ERROR_NOTDYN 5
#define LD_ERROR_MMAP_FAILED 6
#define LD_ERROR_NODYNAMIC 7
#define LD_WRONG_RELOCS 8
#define LD_BAD_HANDLE 9
#define LD_NO_SYMBOL 10



#endif /* _LD_HASH_H_ */



--- NEW FILE: ld_string.h ---
#ifndef _LINUX_STRING_H_
#define _LINUX_STRING_H_

extern void *_dl_malloc(int size);
extern char *_dl_getenv(const char *symbol, char **envp);
extern void _dl_unsetenv(const char *symbol, char **envp);
extern char *_dl_strdup(const char *string);
extern void _dl_dprintf(int, const char *, ...);


static size_t _dl_strlen(const char * str);
static char *_dl_strcat(char *dst, const char *src);
static char * _dl_strcpy(char * dst,const char *src);
static int _dl_strcmp(const char * s1,const char * s2);
static int _dl_strncmp(const char * s1,const char * s2,size_t len);
static char * _dl_strchr(const char * str,int c);
static char *_dl_strrchr(const char *str, int c);
static char *_dl_strstr(const char *s1, const char *s2);
static void * _dl_memcpy(void * dst, const void * src, size_t len);
static int _dl_memcmp(const void * s1,const void * s2,size_t len);
static void *_dl_memset(void * str,int c,size_t len);
static char *_dl_get_last_path_component(char *path);
static char *_dl_simple_ltoa(char * local, unsigned long i);
static char *_dl_simple_ltoahex(char * local, unsigned long i);

#ifndef NULL
#define NULL ((void *) 0)
#endif

static inline size_t _dl_strlen(const char * str)
{
	register char *ptr = (char *) str;

	while (*ptr)
		ptr++;
	return (ptr - str);
}

static inline char *_dl_strcat(char *dst, const char *src)
{
	register char *ptr = dst;

	while (*ptr)
		ptr++;

	while (*src)
		*ptr++ = *src++;
	*ptr = '\0';

	return dst;
}

static inline char * _dl_strcpy(char * dst,const char *src)
{
	register char *ptr = dst;

	while (*src)
		*dst++ = *src++;
	*dst = '\0';

	return ptr;
}
 
static inline int _dl_strcmp(const char * s1,const char * s2)
{
	register unsigned char c1, c2;

	do {
		c1 = (unsigned char) *s1++;
		c2 = (unsigned char) *s2++;
		if (c1 == '\0')
			return c1 - c2;
	}
	while (c1 == c2);

	return c1 - c2;
}

static inline int _dl_strncmp(const char * s1,const char * s2,size_t len)
{
	register unsigned char c1 = '\0';
	register unsigned char c2 = '\0';

	while (len > 0) {
		c1 = (unsigned char) *s1++;
		c2 = (unsigned char) *s2++;
		if (c1 == '\0' || c1 != c2)
			return c1 - c2;
		len--;
	}

	return c1 - c2;
}

static inline char * _dl_strchr(const char * str,int c)
{
	register char ch;

	do {
		if ((ch = *str) == c)
			return (char *) str;
		str++;
	}
	while (ch);

	return 0;
}

static inline char *_dl_strrchr(const char *str, int c)
{
    register char *prev = 0;
    register char *ptr = (char *) str;

    while (*ptr != '\0') {
	if (*ptr == c)
	    prev = ptr;
	ptr++;  
    }   
    if (c == '\0')
	return(ptr);
    return(prev);
}


static inline char *_dl_strstr(const char *s1, const char *s2)
{
    register const char *s = s1;
    register const char *p = s2;
    
    do {
        if (!*p) {
	    return (char *) s1;;
	}
	if (*p == *s) {
	    ++p;
	    ++s;
	} else {
	    p = s2;
	    if (!*s) {
	      return NULL;
	    }
	    s = ++s1;
	}
    } while (1);
}

static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
{
	register char *a = dst;
	register const char *b = src;

	while (len--)
		*a++ = *b++;

	return dst;
}


static inline int _dl_memcmp(const void * s1,const void * s2,size_t len)
{
	unsigned char *c1 = (unsigned char *)s1;
	unsigned char *c2 = (unsigned char *)s2;

	while (len--) {
		if (*c1 != *c2) 
			return *c1 - *c2;
		c1++;
		c2++;
	}
	return 0;
}

static inline void * _dl_memset(void * str,int c,size_t len)
{
	register char *a = str;

	while (len--)
		*a++ = c;

	return str;
}

static inline char *_dl_get_last_path_component(char *path)
{
	char *s;
	register char *ptr = path;
	register char *prev = 0;

	while (*ptr)
		ptr++;
	s = ptr - 1;

	/* strip trailing slashes */
	while (s != path && *s == '/') {
		*s-- = '\0';
	}

	/* find last component */
	ptr = path;
	while (*ptr != '\0') {
	    if (*ptr == '/')
		prev = ptr;
	    ptr++;  
	}   
	s = prev;

	if (s == NULL || s[1] == '\0')
		return path;
	else
		return s+1;
}

/* Early on, we can't call printf, so use this to print out
 * numbers using the SEND_STDERR() macro */
static inline char *_dl_simple_ltoa(char * local, unsigned long i)
{
	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
	char *p = &local[22];
	*p-- = '\0';
	do {
		*p-- = '0' + i % 10;
		i /= 10;
	} while (i > 0);
	return p + 1;
}

static inline char *_dl_simple_ltoahex(char * local, unsigned long i)
{
	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
	char *p = &local[22];
	*p-- = '\0';
	do {
		char temp = i % 0x10;
		if (temp <= 0x09)
		    *p-- = '0' + temp;
		else
		    *p-- = 'a' - 0x0a + temp;
		i /= 0x10;
	} while (i > 0);
	*p-- = 'x';
	*p-- = '0';
	return p + 1;
}


#if defined mc68000 || defined __arm__ || defined __mips__ || defined __sh__
/* On some arches constant strings are referenced through the GOT. */
/* XXX Requires load_addr to be defined. */
#define SEND_STDERR(X)				\
  { const char *__s = (X);			\
    if (__s < (const char *) load_addr) __s += load_addr;	\
    _dl_write (2, __s, _dl_strlen (__s));	\
  }
#else
#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X));
#endif

#define SEND_ADDRESS_STDERR(X, add_a_newline) { \
    char tmp[22], *tmp1; \
    _dl_memset(tmp, 0, sizeof(tmp)); \
    tmp1=_dl_simple_ltoahex( tmp, (unsigned long)(X)); \
    _dl_write(2, tmp1, _dl_strlen(tmp1)); \
    if (add_a_newline) { \
	tmp[0]='\n'; \
	_dl_write(2, tmp, 1); \
    } \
};

#define SEND_NUMBER_STDERR(X, add_a_newline) { \
    char tmp[22], *tmp1; \
    _dl_memset(tmp, 0, sizeof(tmp)); \
    tmp1=_dl_simple_ltoa( tmp, (unsigned long)(X)); \
    _dl_write(2, tmp1, _dl_strlen(tmp1)); \
    if (add_a_newline) { \
	tmp[0]='\n'; \
	_dl_write(2, tmp, 1); \
    } \
};


#endif

--- NEW FILE: ldso.h ---
#include <features.h>
/* Pull in compiler and arch stuff */
#include <stdlib.h>
#include <stdarg.h>
/* Pull in the arch specific type information */
#include <sys/types.h>
/* Now the ldso specific headers */
#include <ld_elf.h>
#include <ld_syscall.h>
#include <ld_hash.h>
#include <ld_string.h>

--- NEW FILE: .cvsignore ---
elf.h
ld_syscalls.h
ld_sysdep.h
boot1_arch.h

--- NEW FILE: dlfcn.h ---
/* User functions for run-time dynamic loading.  libdl version */
#ifndef	_DLFCN_H
#define	_DLFCN_H 1

#include <features.h>
#include <bits/dlfcn.h>

#define RTLD_NEXT	((void *) -1l)
#define RTLD_DEFAULT	((void *) 0)

/* Structure containing information about object searched using
   `dladdr'.  */
typedef struct
{
	__const char *dli_fname;	/* File name of defining object.  */
	void *dli_fbase;		/* Load address of that object.  */
	__const char *dli_sname;	/* Name of nearest symbol.  */
	void *dli_saddr;		/* Exact value of nearest symbol.  */
} Dl_info;


#endif	/* dlfcn.h */




More information about the uClibc-cvs mailing list