glibc/elf/dl-misc.c
Roland McGrath ce460d04a5 * sysdeps/generic/bits/libc-tsd.h [USE___THREAD]: Conditional
changed from [USE_TLS && HAVE___THREAD].

	* sysdeps/i386/dl-machine.h (elf_machine_type_class, elf_machine_rel):
	Disable TLS relocs if [RTLD_BOOTSTRAP && !USE___THREAD].
	* sysdeps/x86_64/dl-machine.h
	(elf_machine_type_class, elf_machine_rela): Likewise.
	* sysdeps/sh/dl-machine.h (elf_machine_type_class, elf_machine_rela):
	Likewise.

	* include/link.h (struct link_map): Remove member l_tls_tp_initialized.
	* elf/rtld.c (_dl_start_final, dl_main): Don't use it.
	(_dl_start): Conditionalize PT_TLS check on [USE___THREAD].

	* sysdeps/i386/dl-tls.h (__TLS_GET_ADDR): Use ___tls_get_addr_internal
	instead of ___tls_get_addr.
	(___tls_get_addr_internal): Add attribute_hidden to decl.

	* sysdeps/generic/ldsodefs.h (struct rtld_global): New variable
	_dl_error_catch_tsd.
	* elf/rtld.c (startup_error_tsd): New function.
	(dl_main): Point _dl_error_catch_tsd at that.
	* elf/dl-error.c: Don't use libc-tsd.h for DL_ERROR,
	use new function pointer instead.
	* elf/dl-tsd.c: New file.
	* elf/Makefile (routines): Add it.

2002-10-07  Roland McGrath  <roland@redhat.com>

	* elf/dl-misc.c (_dl_debug_vdprintf): Use INTERNAL_SYSCALL macro for
	writev if it's available.  Otherwise if [RTLD_PRIVATE_ERRNO] then
	take _dl_load_lock around calling __writev.

	* sysdeps/unix/sysv/linux/i386/sysdep.h (INTERNAL_SYSCALL): New macro.
	(INLINE_SYSCALL): Use that.

	* sysdeps/generic/dl-sysdep.h: New file.
	* sysdeps/mach/hurd/dl-sysdep.h: New file.
	* sysdeps/generic/ldsodefs.h: Include <dl-sysdep.h>.
	* include/errno.h [IS_IN_rtld]: Include <dl-sysdep.h> to define ...
	[RTLD_PRIVATE_ERRNO]: Use a hidden global variable for errno and
	access it directly.
	* elf/dl-minimal.c (__errno_location): Removed.
	* sysdeps/unix/i386/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]:
	Use GOTOFF access for errno.
	* sysdeps/unix/sysv/linux/i386/sysdep.h
	[RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise.

	* sysdeps/unix/x86_64/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]:
	Use PC-relative access for errno.
	* sysdeps/unix/sysv/linux/x86_64/sysdep.h
	[RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise.

	* include/tls.h: New file.
	(USE___THREAD): New macro.
	Define to 1 under [USE_TLS && HAVE___THREAD] and only when compiling
	libc or libpthread.
	* sysdeps/unix/sysv/linux/i386/sysdep.h [USE___THREAD]: Conditional
	changed from [USE_TLS && HAVE___THREAD].
	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
	* sysdeps/unix/i386/sysdep.S: Likewise.
	* sysdeps/unix/x86_64/sysdep.S: Likewise.
	* include/errno.h: Likewise.
	* include/netdb.h: Likewise.
	* include/resolv.h: Likewise.

	* sysdeps/generic/errno.c: New file.
	* csu/Makefile (aux): New variable, list errno.
	* sysdeps/unix/sysv/linux/i386/sysdep.S (errno, _errno): Remove defns.
	* sysdeps/unix/sysv/linux/m68k/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/arm/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/cris/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/hppa/sysdep.c: Likewise.
	* sysdeps/unix/sysv/linux/ia64/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/sysdep.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sysdep.S: Likewise.
	* sysdeps/unix/sysv/linux/sh/sysdep.S: Likewise.
	* sysdeps/unix/alpha/sysdep.S: Likewise.
	* sysdeps/generic/start.c: Likewise.
	* sysdeps/unix/start.c: Likewise.
	* sysdeps/unix/arm/start.c: Likewise.
	* sysdeps/unix/bsd/ultrix4/mips/start.S: Likewise.
	* sysdeps/unix/sparc/start.c: Likewise.
	* sysdeps/unix/sysv/irix4/start.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/sysdep.S: File removed.

	* manual/search.texi (Tree Search Function, Hash Search Function):
	Mention search.h clearly.

2002-10-05  Roland McGrath  <roland@redhat.com>

	* elf/dl-fxstat64.c: File removed.
	* elf/dl-xstat64.c: File removed.
	* elf/Makefile (rtld-routines): Remove them.
	* sysdeps/unix/sysv/linux/xstat64.c: Remove RTLD_STAT64 conditionals.
	Instead, use strong_alias instead of versioned_symbol in the
	!SHLIB_COMPAT case.
	* sysdeps/unix/sysv/linux/fxstat64.c: Likewise.
	* sysdeps/unix/sysv/linux/lxstat64.c: Likewise.

	* include/shlib-compat.h
	(SHLIB_COMPAT): Require that IS_IN_##lib be defined nonzero.
	[! NOT_IN_libc] (IS_IN_libc): Define it.
	* cppflags-iterator.mk (CPPFLAGS-$(cpp-src)): Use -Dx=1 not just -Dx.
	* elf/Makefile (CPPFLAGS-.os): Likewise.

	* sunrpc/rpc_main.c (main): Don't declare with noreturn attribute.
	Return the status instead of calling exit.

	* Makeconfig (CFLAGS): Prepend -std=gnu99.
	* Makerules (+make-deps): Use $(CFLAGS) only for .c sources.
	Remove superfluous rm command, whose @ plus make bugs hid
	all these commands from the make output.

	* include/stubs-prologue.h: New file.  Give #error under #ifdef _LIBC.
	* Makefile ($(inst_includedir)/gnu/stubs.h): Depend on it.
	Use that file's contents instead of literal echo's for the prologue.
	* include/features.h: Include <gnu/stubs.h> unconditionally.
	* include/gnu/stubs.h: New file.

2002-09-30  Roland McGrath  <roland@redhat.com>

	* elf/rtld-Rules: New file.
	* elf/Makefile ($(objpfx)librtld.map, $(objpfx)librtld.mk,
	$(objpfx)rtld-libc.a): New targets.
	(generated): Add them.
	(reloc-link): Remove -o $@ from the variable.
	($(objpfx)dl-allobjs.os): Add -o $@ after $(reloc-link).
	(distribute): Add rtld-Rules.
	(CPPFLAGS-.os): Define this instead of CFLAGS-.os.
	* Makerules ($(+sysdir_pfx)sysd-rules): Emit rules for rtld-% targets.
	(common-mostlyclean, common-clean): Clean up rtld-* files.
	* sysdeps/unix/make-syscalls.sh: Add rtld-*.os target name to rules.
2002-10-11 10:52:20 +00:00

298 lines
7.1 KiB
C

/* Miscellaneous support functions for dynamic linker
Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <fcntl.h>
#include <ldsodefs.h>
#include <limits.h>
#include <link.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <stdio-common/_itoa.h>
#include <bits/libc-lock.h>
#ifndef MAP_ANON
/* This is the only dl-sysdep.c function that is actually needed at run-time
by _dl_map_object. */
int
_dl_sysdep_open_zero_fill (void)
{
return __open ("/dev/zero", O_RDONLY);
}
#endif
/* Read the whole contents of FILE into new mmap'd space with given
protections. *SIZEP gets the size of the file. On error MAP_FAILED
is returned. */
void *
internal_function
_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
{
void *result = MAP_FAILED;
struct stat64 st;
int fd = __open (file, O_RDONLY);
if (fd >= 0)
{
if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
{
*sizep = st.st_size;
/* No need to map the file if it is empty. */
if (*sizep != 0)
/* Map a copy of the file contents. */
result = __mmap (NULL, *sizep, prot,
#ifdef MAP_COPY
MAP_COPY
#else
MAP_PRIVATE
#endif
#ifdef MAP_FILE
| MAP_FILE
#endif
, fd, 0);
}
__close (fd);
}
return result;
}
/* Bare-bone printf implementation. This function only knows about
the formats and flags needed and can handle only up to 64 stripes in
the output. */
static void
_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
{
const int niovmax = 64;
struct iovec iov[niovmax];
int niov = 0;
pid_t pid = 0;
char pidbuf[7];
while (*fmt != '\0')
{
const char *startp = fmt;
if (tag_p > 0)
{
/* Generate the tag line once. It consists of the PID and a
colon followed by a tab. */
if (pid == 0)
{
char *p;
pid = __getpid ();
assert (pid >= 0 && pid < 100000);
p = _itoa (pid, &pidbuf[5], 10, 0);
while (p > pidbuf)
*--p = '0';
pidbuf[5] = ':';
pidbuf[6] = '\t';
}
/* Append to the output. */
assert (niov < niovmax);
iov[niov].iov_len = 7;
iov[niov++].iov_base = pidbuf;
/* No more tags until we see the next newline. */
tag_p = -1;
}
/* Skip everything except % and \n (if tags are needed). */
while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
++fmt;
/* Append constant string. */
assert (niov < niovmax);
if ((iov[niov].iov_len = fmt - startp) != 0)
iov[niov++].iov_base = (char *) startp;
if (*fmt == '%')
{
/* It is a format specifier. */
char fill = ' ';
int width = -1;
int prec = -1;
#if LONG_MAX != INT_MAX
int long_mod = 0;
#endif
/* Recognize zero-digit fill flag. */
if (*++fmt == '0')
{
fill = '0';
++fmt;
}
/* See whether with comes from a parameter. Note that no other
way to specify the width is implemented. */
if (*fmt == '*')
{
width = va_arg (arg, int);
++fmt;
}
/* Handle precision. */
if (*fmt == '.' && fmt[1] == '*')
{
prec = va_arg (arg, int);
fmt += 2;
}
/* Recognize the l modifier. It is only important on some
platforms where long and int have a different size. We
can use the same code for size_t. */
if (*fmt == 'l' || *fmt == 'Z')
{
#if LONG_MAX != INT_MAX
long_mod = 1;
#endif
++fmt;
}
switch (*fmt)
{
/* Integer formatting. */
case 'u':
case 'x':
{
/* We have to make a difference if long and int have a
different size. */
#if LONG_MAX != INT_MAX
unsigned long int num = (long_mod
? va_arg (arg, unsigned long int)
: va_arg (arg, unsigned int));
#else
unsigned long int num = va_arg (arg, unsigned int);
#endif
/* We use alloca() to allocate the buffer with the most
pessimistic guess for the size. Using alloca() allows
having more than one integer formatting in a call. */
char *buf = (char *) alloca (3 * sizeof (unsigned long int));
char *endp = &buf[3 * sizeof (unsigned long int)];
char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
/* Pad to the width the user specified. */
if (width != -1)
while (endp - cp < width)
*--cp = fill;
iov[niov].iov_base = cp;
iov[niov].iov_len = endp - cp;
++niov;
}
break;
case 's':
/* Get the string argument. */
iov[niov].iov_base = va_arg (arg, char *);
iov[niov].iov_len = strlen (iov[niov].iov_base);
if (prec != -1)
iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
++niov;
break;
case '%':
iov[niov].iov_base = (void *) fmt;
iov[niov].iov_len = 1;
++niov;
break;
default:
assert (! "invalid format specifier");
}
++fmt;
}
else if (*fmt == '\n')
{
/* See whether we have to print a single newline character. */
if (fmt == startp)
{
iov[niov].iov_base = (char *) startp;
iov[niov++].iov_len = 1;
}
else
/* No, just add it to the rest of the string. */
++iov[niov - 1].iov_len;
/* Next line, print a tag again. */
tag_p = 1;
++fmt;
}
}
/* Finally write the result. */
#ifdef INTERNAL_SYSCALL
INTERNAL_SYSCALL (writev, 3, fd, iov, niov);
#elif RTLD_PRIVATE_ERRNO
/* We have to take this lock just to be sure we don't clobber the private
errno when it's being used by another thread that cares about it. */
__libc_lock_lock_recursive (GL(dl_load_lock));
__writev (fd, iov, niov);
__libc_lock_unlock_recursive (GL(dl_load_lock));
#else
__writev (fd, iov, niov);
#endif
}
/* Write to debug file. */
void
_dl_debug_printf (const char *fmt, ...)
{
va_list arg;
va_start (arg, fmt);
_dl_debug_vdprintf (GL(dl_debug_fd), 1, fmt, arg);
va_end (arg);
}
INTDEF(_dl_debug_printf)
/* Write to debug file but don't start with a tag. */
void
_dl_debug_printf_c (const char *fmt, ...)
{
va_list arg;
va_start (arg, fmt);
_dl_debug_vdprintf (GL(dl_debug_fd), -1, fmt, arg);
va_end (arg);
}
/* Write the given file descriptor. */
void
_dl_dprintf (int fd, const char *fmt, ...)
{
va_list arg;
va_start (arg, fmt);
_dl_debug_vdprintf (fd, 0, fmt, arg);
va_end (arg);
}