1997-07-28 23:35  Ulrich Drepper  <drepper@cygnus.com>

	* csu/gmon-start.c (__gmon_start__): Call __monstartup not
	monstartup.
	* gmon/gmon.c: Rename moncontrol to __moncontrol and monstartup
	to __monstartup.
	* gmon/sys/gmon.h: Fix prototypes.
	* gmon/sys/gmon_out.h: Pretty print.

	* gmon/bb_exit_func.c (__bb_exit_func): Use memcpy instead of bcopy.
	* gmon/gmon.c (__monstartup): Likewise.
	(write_hist): Remove dependency on 32 int.
	(_mcleanup): Don't call perror, use fprintf.

	* elf/dl-load.c: Fix handling of current directory in search path.

	* elf/Makefile (dl-routines): Add dl-profile.
	* elf/dl-profile.c: New file.
	* elf/dl-runtime.c (fixup): Add new parameter with address to store
	relocation result in to elf_machine_relplt.
	(profile_fixup): New function.
	* elf/do-rel.h (elf_dynamic_do_rel): Add new parameter with address
	to store relocation result in to elf_machine_relplt.
	* elf/dl-support.c: Define _dl_profile and _dl_profile_map.
	* elf/dynamic-link.h (ELF_DYNAMIC_RELOCATE): Add new parameter and
	call elf_machine_runtime_setup with extra argument.
	* elf/dl-reloc.c (_dl_relocate_object): Add new argument to
	ELF_DYNAMIC_RELOCATE.
	* elf/link.h: Add prototypes for new functions and variables.
	* elf/rtld.c: Parse LD_PROFILE and LD_PROFILE_OUTPUT environment
	variables and call _dl_start_profile if necessary.
	* include/sys/gmon_out.h: New file.
	* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Add
	new parameter to enable profiling.
	(elf_machine_rela): Add new parameter to specify place to store
	result in.
	* sysdeps/m68k/dl-machine.h: Likewise.
	* sysdeps/mips/dl-machine.h: Likewise.
	* sysdeps/mips/mips64/dl-machine.h: Likewise.
	* sysdeps/powerpc/dl-machine.h: Likewise.
	* sysdeps/sparc/dl-machine.h: Likewise.
	* sysdeps/sparc64/dl-machine.h: Likewise.
	* sysdeps/i386/dl-machine.h: Likewise.
	(elf_machine_runtime_setup): Setup got[2] to _dl_runtime_resolve if
	we do profiling.
	(ELF_MACHINE_RUNTIME_TRAMPOLINE): Add code for _dl_runtime_profile.

	* nis/nss_compat/compat-grp.c (internal_setgrent): Set FD_CLOEXEC
	for stream on input file.
	* nis/nss_compat/compat-pwd.c (internal_setpwent): Likewise.
	* nis/nss_compat/compat-spwd.c (internal_setspent): Likewise.
	* nss/nss_db/db-XXX.c (internal_setent): Likewise.
	* nss/nss_db/db-alias.c (internal_setent): Likewise.
	* nss/nss_db/db-netgrp.c (internal_setent): Likewise.
	* nss/nss_files/files-XXX.c (internal_setent): Likewise.
	* nss/nss_files/files-alias.c (internal_setent): Likewise.
	* nss/nss_files/files-netgrp.c (internal_setent): Likewise.

	* string/string.h: Pretty print.

	* sysdeps/i386/fpu/bits/mathinline.h: Major update by John Bowman.
	Add float and long double versions.

1997-07-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* elf/rtld.c (print_unresolved): Replace empty object name by main
	program name.

1997-07-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/generic/htons.c (htons): Renamed from __htons.

1997-07-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/m68k/bits/byteswap.h: New file.

1997-07-27 23:50  Philip Blundell  <Philip.Blundell@pobox.com>

	* inet/netinet/icmp6.h: Update for new drafts of POSIX.1g and IPv6
	advanced API.
	* inet/netinet/in.h: Likewise.
	* inet/netinet/ip6.h: Likewise.
	* sysdeps/unix/sysv/linux/bits/socket.h: Likewise.
	* posix/sys/types.h: Add socklen_t.

	* manual/socket.texi: Document some more IPv6 things.
	* manual/libc.texinfo: Likewise.

1997-07-26  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* libc.map: Define missing symbol.

1997-07-27 14:31  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>

	* nis/Makefile: Add nis_findserv.
	* nis/lckcache.c: Fix typo.
	* nis/nis_call.c: Fix problems with multihomed servers.
	* nis/nis_findserv.c: New file.
	* nis/nis_intern.h: Add more prototypes.
	* nis/nis_lookup.c (nis_lookup): Don't try the next server if network
	is unreachable.
	* nis/nis_table.c (nis_list): Likewise.
	* nis/nis_ping.c (nis_ping): Use MASTER_ONLY, don't call abort()
	in error case.
	* nis/nis_util.c (__nis_finddirectory): Give the right error code
	back.
	* nis/ypclnt.c: Make sure, that all sockets are closed.
This commit is contained in:
Ulrich Drepper 1997-07-28 22:35:20 +00:00
parent 0a54e4010f
commit 3996f34b46
60 changed files with 2135 additions and 874 deletions

108
ChangeLog
View file

@ -1,3 +1,111 @@
1997-07-28 23:35 Ulrich Drepper <drepper@cygnus.com>
* csu/gmon-start.c (__gmon_start__): Call __monstartup not
monstartup.
* gmon/gmon.c: Rename moncontrol to __moncontrol and monstartup
to __monstartup.
* gmon/sys/gmon.h: Fix prototypes.
* gmon/sys/gmon_out.h: Pretty print.
* gmon/bb_exit_func.c (__bb_exit_func): Use memcpy instead of bcopy.
* gmon/gmon.c (__monstartup): Likewise.
(write_hist): Remove dependency on 32 int.
(_mcleanup): Don't call perror, use fprintf.
* elf/dl-load.c: Fix handling of current directory in search path.
* elf/Makefile (dl-routines): Add dl-profile.
* elf/dl-profile.c: New file.
* elf/dl-runtime.c (fixup): Add new parameter with address to store
relocation result in to elf_machine_relplt.
(profile_fixup): New function.
* elf/do-rel.h (elf_dynamic_do_rel): Add new parameter with address
to store relocation result in to elf_machine_relplt.
* elf/dl-support.c: Define _dl_profile and _dl_profile_map.
* elf/dynamic-link.h (ELF_DYNAMIC_RELOCATE): Add new parameter and
call elf_machine_runtime_setup with extra argument.
* elf/dl-reloc.c (_dl_relocate_object): Add new argument to
ELF_DYNAMIC_RELOCATE.
* elf/link.h: Add prototypes for new functions and variables.
* elf/rtld.c: Parse LD_PROFILE and LD_PROFILE_OUTPUT environment
variables and call _dl_start_profile if necessary.
* include/sys/gmon_out.h: New file.
* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Add
new parameter to enable profiling.
(elf_machine_rela): Add new parameter to specify place to store
result in.
* sysdeps/m68k/dl-machine.h: Likewise.
* sysdeps/mips/dl-machine.h: Likewise.
* sysdeps/mips/mips64/dl-machine.h: Likewise.
* sysdeps/powerpc/dl-machine.h: Likewise.
* sysdeps/sparc/dl-machine.h: Likewise.
* sysdeps/sparc64/dl-machine.h: Likewise.
* sysdeps/i386/dl-machine.h: Likewise.
(elf_machine_runtime_setup): Setup got[2] to _dl_runtime_resolve if
we do profiling.
(ELF_MACHINE_RUNTIME_TRAMPOLINE): Add code for _dl_runtime_profile.
* nis/nss_compat/compat-grp.c (internal_setgrent): Set FD_CLOEXEC
for stream on input file.
* nis/nss_compat/compat-pwd.c (internal_setpwent): Likewise.
* nis/nss_compat/compat-spwd.c (internal_setspent): Likewise.
* nss/nss_db/db-XXX.c (internal_setent): Likewise.
* nss/nss_db/db-alias.c (internal_setent): Likewise.
* nss/nss_db/db-netgrp.c (internal_setent): Likewise.
* nss/nss_files/files-XXX.c (internal_setent): Likewise.
* nss/nss_files/files-alias.c (internal_setent): Likewise.
* nss/nss_files/files-netgrp.c (internal_setent): Likewise.
* string/string.h: Pretty print.
* sysdeps/i386/fpu/bits/mathinline.h: Major update by John Bowman.
Add float and long double versions.
1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* elf/rtld.c (print_unresolved): Replace empty object name by main
program name.
1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* sysdeps/generic/htons.c (htons): Renamed from __htons.
1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* sysdeps/m68k/bits/byteswap.h: New file.
1997-07-27 23:50 Philip Blundell <Philip.Blundell@pobox.com>
* inet/netinet/icmp6.h: Update for new drafts of POSIX.1g and IPv6
advanced API.
* inet/netinet/in.h: Likewise.
* inet/netinet/ip6.h: Likewise.
* sysdeps/unix/sysv/linux/bits/socket.h: Likewise.
* posix/sys/types.h: Add socklen_t.
* manual/socket.texi: Document some more IPv6 things.
* manual/libc.texinfo: Likewise.
1997-07-26 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* libc.map: Define missing symbol.
1997-07-27 14:31 Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
* nis/Makefile: Add nis_findserv.
* nis/lckcache.c: Fix typo.
* nis/nis_call.c: Fix problems with multihomed servers.
* nis/nis_findserv.c: New file.
* nis/nis_intern.h: Add more prototypes.
* nis/nis_lookup.c (nis_lookup): Don't try the next server if network
is unreachable.
* nis/nis_table.c (nis_list): Likewise.
* nis/nis_ping.c (nis_ping): Use MASTER_ONLY, don't call abort()
in error case.
* nis/nis_util.c (__nis_finddirectory): Give the right error code
back.
* nis/ypclnt.c: Make sure, that all sockets are closed.
1997-07-26 04:14 Ulrich Drepper <drepper@cygnus.com>
* elf/Makefile (distribute): Add genrtldtbl.awk.

30
aout/Makefile Normal file
View file

@ -0,0 +1,30 @@
# Makefile for aout subdirectory of GNU C Library.
# Copyright (C) 1995, 1996, 1997 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 Library General Public License as
# published by the Free Software Foundation; either version 2 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
# Library General Public License for more details.
# You should have received a copy of the GNU Library General Public
# License along with the GNU C Library; see the file COPYING.LIB. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
subdir := aout
headers =
routines = enbl-secure
all: # Make this the default target; it will be defined in Rules.
include ../Makeconfig
include ../Rules

12
config.guess vendored
View file

@ -157,6 +157,18 @@ EOF
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit 0 ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit 0 ;;

View file

@ -1,5 +1,5 @@
/* Code to enable profiling at program startup.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997 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
@ -50,7 +50,7 @@ __gmon_start__ (void)
#endif
/* Start keeping profiling records. */
monstartup ((u_long) &_start, (u_long) &etext);
__monstartup ((u_long) &_start, (u_long) &etext);
/* Call _mcleanup before exiting; it will write out gmon.out from the
collected data. */

View file

@ -27,7 +27,8 @@ routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
dl-routines = $(addprefix dl-,load cache lookup object reloc deps \
runtime error init fini debug misc)
runtime error init fini debug misc \
profile)
# But they are absent from the shared libc, because that code is in ld.so.
elide-routines.so = $(dl-routines) dl-support enbl-secure

View file

@ -193,7 +193,10 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
"cannot create cache for search path");
dirp->dirnamelen = len;
dirp->dirstatus = unknown;
/* We have to make sure all the relative directories are never
ignored. The current directory might change and all our
saved information would be void. */
dirp->dirstatus = cp[0] != '/' ? existing : unknown;
/* Add the name of the machine dependent directory if a machine
is defined. */
@ -212,7 +215,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
tmp[len + _dl_platformlen + 1] = '\0';
dirp->dirname = tmp;
dirp->machdirstatus = unknown;
dirp->machdirstatus = dirp->dirstatus;
if (max_dirnamelen < dirp->machdirnamelen)
max_dirnamelen = dirp->machdirnamelen;

267
elf/dl-profile.c Normal file
View file

@ -0,0 +1,267 @@
/* Profiling of shared libraries.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/gmon.h>
#include <sys/gmon_out.h>
#include <sys/mman.h>
#include <sys/stat.h>
/* The LD_PROFILE feature has to be implemented different to the
normal profiling using the gmon/ functions. The problem is that an
arbitrary amount of processes simulataneously can be run using
profiling and all write the results in the same file. To provide
this mechanism one could implement a complicated mechanism to merge
the content of two profiling runs or one could extend the file
format to allow more than one data set. For the second solution we
would have the problem that the file can grow in size beyond any
limit and both solutions have the problem that the concurrency of
writing the results is a big problem.
Another much simpler method is to use mmap to map the same file in
all using programs and modify the data in the mmap'ed area and so
also automatically on the disk. Using the MAP_SHARED option of
mmap(2) this can be done without big problems in more than one
file.
This approach is very different from the normal profiling. We have
to use the profiling data in exactly the way they are expected to
be written to disk. */
extern char *_strerror_internal __P ((int, char *buf, size_t));
extern int __profile_frequency __P ((void));
static struct gmonparam param;
/* We define a special type to address the elements of the arc table.
This is basically the `gmon_cg_arc_record' format but it includes
the room for the tag and it uses real types. */
struct here_cg_arc_record
{
char tag;
uintptr_t from_pc __attribute__ ((packed));
uintptr_t self_pc __attribute__ ((packed));
uint32_t count __attribute__ ((packed));
};
static struct here_cg_arc_record *data;
void
_dl_start_profile (struct link_map *map, const char *output_dir)
{
char *filename;
int fd;
struct stat st;
const ElfW(Phdr) *ph;
ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
ElfW(Addr) mapend = 0;
off_t expected_size;
struct gmon_hdr gmon_hdr;
struct gmon_hist_hdr hist_hdr;
struct gmon_hdr *addr;
char *hist;
/* Compute the size of the sections which contain program code. */
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
{
ElfW(Addr) start = (ph->p_vaddr & ~(_dl_pagesize - 1));
ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
& ~(_dl_pagesize - 1));
if (start < mapstart)
mapstart = start;
if (end > mapend)
mapend = end;
}
/* Now we can compute the size of the profiling data. This is done
with the same formulars as in `monstartup' (see gmon.c). */
param.state = GMON_PROF_OFF;
param.lowpc = mapstart + map->l_addr;
param.highpc = mapend + map->l_addr;
param.textsize = mapend - mapstart;
param.kcountsize = param.textsize / HISTFRACTION;
param.hashfraction = HASHFRACTION;
param.log_hashfraction = -1;
if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
/* If HASHFRACTION is a power of two, mcount can use shifting
instead of integer division. Precompute shift amount. */
param.log_hashfraction = ffs (param.hashfraction
* sizeof (*param.froms)) - 1;
param.fromssize = param.textsize / HASHFRACTION;
param.tolimit = param.textsize * ARCDENSITY / 100;
if (param.tolimit < MINARCS)
param.tolimit = MINARCS;
if (param.tolimit > MAXARCS)
param.tolimit = MAXARCS;
param.tossize = param.tolimit * sizeof (struct tostruct);
expected_size = (sizeof (struct gmon_hdr)
+ 1 + sizeof (struct gmon_hist_hdr)
+ ((1 + sizeof (struct gmon_cg_arc_record))
* (param.fromssize / sizeof (*param.froms))));
/* Create the gmon_hdr we expect or write. */
memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
*(int32_t *) gmon_hdr.version = GMON_VERSION;
/* Create the hist_hdr we expect or write. */
*(char **) hist_hdr.low_pc = (char *) mapstart;
*(char **) hist_hdr.high_pc = (char *) mapend;
*(int32_t *) hist_hdr.hist_size = param.kcountsize / sizeof (HISTCOUNTER);
*(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
hist_hdr.dimen_abbrev = 's';
/* First determine the output name. We write in the directory
OUTPUT_DIR and the name is composed from the shared objects
soname (or the file name) and the ending ".profile". */
filename = (char *) alloca (strlen (output_dir) + 1 + strlen (_dl_profile)
+ sizeof ".profile");
__stpcpy (__stpcpy (__stpcpy (__stpcpy (filename, output_dir), "/"),
_dl_profile),
".profile");
fd = __open (filename, O_RDWR | O_CREAT, 0666);
if (fd == -1)
/* We cannot write the profiling data so don't do anthing. */
return;
if (fstat (fd, &st) < 0 || !S_ISREG (st.st_mode))
{
/* Not stat'able or not a regular file => don't use it. */
close (fd);
return;
}
/* Test the size. If it does not match what we expect from the size
values in the map MAP we don't use it and warn the user. */
if (st.st_size == 0)
{
/* We have to create the file. */
char buf[_dl_pagesize];
memset (buf, '\0', _dl_pagesize);
if (__lseek (fd, expected_size & ~(_dl_pagesize - 1), SEEK_SET) == -1)
{
char buf[400];
int errnum;
cannot_create:
errnum = errno;
__close (fd);
fprintf (stderr, "%s: cannot create file: %s\n", filename,
_strerror_internal (errnum, buf, sizeof buf));
return;
}
if (TEMP_FAILURE_RETRY (__write (fd, buf, (expected_size
& (_dl_pagesize - 1)))) < 0)
goto cannot_create;
}
else if (st.st_size != expected_size)
{
__close (fd);
wrong_format:
fprintf (stderr, "%s: file is no correct profile data file for `%s'\n",
filename, _dl_profile);
return;
}
addr = (void *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FILE, fd, 0);
if (addr == (void *) -1)
{
char buf[400];
int errnum = errno;
__close (fd);
fprintf (stderr, "%s: cannot map file: %s\n", filename,
_strerror_internal (errnum, buf, sizeof buf));
return;
}
/* We don't need the file desriptor anymore. */
__close (fd);
/* Pointer to data after the header. */
hist = (char *) (addr + 1);
/* Compute pointer to array of the arc information. */
data = (struct here_cg_arc_record *) (hist + 1
+ sizeof (struct gmon_hist_hdr));
if (st.st_size == 0)
{
/* Create the signature. */
size_t cnt;
memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));
*hist = GMON_TAG_TIME_HIST;
memcpy (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr));
for (cnt = 0; cnt < param.fromssize / sizeof (*param.froms); ++cnt)
data[cnt].tag = GMON_TAG_CG_ARC;
}
else
{
/* Test the signature in the file. */
if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
|| *hist != GMON_TAG_TIME_HIST
|| memcmp (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)) != 0)
goto wrong_format;
}
/* Turn on profiling. */
param.state = GMON_PROF_ON;
}
void
_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
{
if (param.state != GMON_PROF_ON)
return;
param.state = GMON_PROF_BUSY;
/* Compute relative addresses. The shared object can be loaded at
any address. The value of frompc could be anything. We cannot
restrict it in any way, just set to a fixed value (0) in case it
is outside the allowed range. These calls show up as calls from
<external> in the gprof output. */
frompc -= param.lowpc;
if (frompc >= param.textsize)
frompc = 0;
selfpc -= param.lowpc;
param.state = GMON_PROF_ON;
}

View file

@ -24,6 +24,7 @@
#include <errno.h>
#include "dynamic-link.h"
void
_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
{
@ -65,7 +66,7 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
l->l_name, (flags)))
#include "dynamic-link.h"
ELF_DYNAMIC_RELOCATE (l, lazy);
ELF_DYNAMIC_RELOCATE (l, lazy, 1);
}
/* Mark the object so we know this work has been done. */

View file

@ -137,17 +137,18 @@ fixup (
/* Perform the specified relocation. */
if (l->l_info[VERSYMIDX (DT_VERSYM)])
{
const ElfW(Half) * version =
const ElfW(Half) *version =
(const ElfW(Half) *) (l->l_addr +
l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
&l->l_versions[ndx]);
&l->l_versions[ndx],
(void *) (l->l_addr + reloc->r_offset));
}
else
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
NULL);
NULL, (void *) (l->l_addr + reloc->r_offset));
}
*_dl_global_scope_end = NULL;
@ -161,6 +162,70 @@ fixup (
}
#ifndef PROF
static ElfW(Addr)
profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
#endif
struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
const ElfW(Sym) *const symtab
= (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
const char *strtab =
(const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
const PLTREL *const reloc
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
reloc_offset);
ElfW(Addr) result;
/* Set up the scope to find symbols referenced by this object. */
struct link_map **scope = _dl_object_relocation_scope (l);
{
/* This macro is used as a callback from the elf_machine_relplt code. */
#define RESOLVE(ref, version, flags) \
((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \
l->l_name, (version), (flags)) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \
l->l_name, (flags)))
#include "dynamic-link.h"
/* Perform the specified relocation. */
if (l->l_info[VERSYMIDX (DT_VERSYM)])
{
const ElfW(Half) *version =
(const ElfW(Half) *) (l->l_addr +
l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
&l->l_versions[ndx], (void *) &result);
}
else
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
NULL, (void *) &result);
}
*_dl_global_scope_end = NULL;
/* Return the address that was written by the relocation. */
#ifdef ELF_FIXUP_RETURNS_ADDRESS
(*mcount_fct) (retaddr, result);
return &result; /* XXX This cannot work. What to do??? --drepper */
#else
(*mcount_fct) (retaddr, result);
return result;
#endif
}
#endif
/* This macro is defined in dl-machine.h to define the entry point called
by the PLT. The `fixup' function above does the real work, but a little
more twiddling is needed to get the stack right and jump to the address

View file

@ -42,6 +42,10 @@ int _dl_verbose;
/* Structure to store information about search paths. */
struct r_search_path *_dl_search_paths;
/* We never do profiling. */
const char *_dl_profile;
struct link_map *_dl_profile_map;
static void non_dynamic_init (void) __attribute__ ((unused));

View file

@ -63,12 +63,14 @@ elf_dynamic_do_rel (struct link_map *map,
{
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx]);
&map->l_versions[ndx],
(void *) (map->l_addr + r->r_offset));
}
}
else
for (; r < end; ++r)
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL);
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
(void *) (map->l_addr + r->r_offset));
}
}

View file

@ -102,11 +102,14 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
/* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */
#define ELF_DYNAMIC_RELOCATE(map, lazy) \
do { \
int edr_lazy = elf_machine_runtime_setup((map), (lazy)); \
ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
#define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
do { \
int profile = (consider_profile && _dl_profile != NULL \
&& _dl_name_match_p (_dl_profile, (map))); \
int edr_lazy = elf_machine_runtime_setup ((map), (lazy) || profile, \
profile); \
ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
} while (0)
#endif

View file

@ -225,6 +225,11 @@ extern size_t _dl_pagesize;
/* File descriptor referring to the zero-fill device. */
extern int _dl_zerofd;
/* Name of the shared object to be profiled (if any). */
extern const char *_dl_profile;
/* Map of shared object to be profiled. */
extern struct link_map *_dl_profile_map;
/* OS-dependent function to open the zero-fill device. */
extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
@ -430,8 +435,14 @@ extern void _dl_debug_state (void);
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
/* Initialize the basic data structure for the search paths. */
void _dl_init_paths (void);
extern void _dl_init_paths (void);
/* Gather the information needed to install the profiling tables and start
the timers. */
extern void _dl_start_profile (struct link_map *map, const char *output_dir);
/* The actual functions used to keep book on the calls. */
extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
__END_DECLS

View file

@ -61,6 +61,9 @@ int _dl_verbose;
const char *_dl_platform;
size_t _dl_platformlen;
struct r_search_path *_dl_search_paths;
const char *_dl_profile;
const char *_dl_profile_output;
struct link_map *_dl_profile_map;
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
@ -109,7 +112,7 @@ _dl_start (void *arg)
/* Relocate ourselves so we can do normal function calls and
data access using the global offset table. */
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
/* Now life is sane; we can call functions and access global data.
Set up to use the operating system facilities, and find out from
@ -269,6 +272,26 @@ dl_main (const ElfW(Phdr) *phdr,
else
lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
/* See whether we want to use profiling. */
_dl_profile = getenv ("LD_PROFILE");
if (_dl_profile != NULL)
if (_dl_profile[0] == '\0')
/* An empty string is of not much help. Disable profiling. */
_dl_profile = NULL;
else
{
/* OK, we have the name of a shared object we want to
profile. It's up to the user to provide a good name, it
must match the file name or soname of one of the loaded
objects. Now let's see where we are supposed to place the
result. */
_dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
/* This is the default place. */
_dl_profile_output = "/var/tmp";
}
/* Set up a flag which tells we are just starting. */
_dl_starting_up = 1;
@ -814,6 +837,11 @@ of this helper program; chances are you did not intend to run this program.\n",
_dl_debug_state ();
}
/* Now enable profiling if needed. */
if (_dl_profile_map != NULL)
/* We must prepare the profiling. */
_dl_start_profile (_dl_profile_map, _dl_profile_output);
/* Once we return, _dl_sysdep_start will invoke
the DT_INIT functions and then *USER_ENTRY. */
}
@ -824,6 +852,8 @@ static void
print_unresolved (int errcode __attribute__ ((unused)), const char *objname,
const char *errstring)
{
if (objname[0] == '\0')
objname = _dl_argv[0] ?: "<main program>";
_dl_sysdep_error (errstring, " (", objname, ")\n", NULL);
}

View file

@ -18,7 +18,7 @@
Boston, MA 02111-1307, USA. */
/* __bb_exit_func() dumps all the basic-block statistics linked into
the bb_head chain to .d files. */
the __bb_head chain to .d files. */
#include <sys/gmon_out.h>
#include <sys/types.h>
@ -55,8 +55,8 @@ __bb_exit_func (void)
perror (OUT_NAME);
return;
}
bcopy (GMON_MAGIC, &ghdr.cookie[0], 4);
bcopy (&version, &ghdr.version, sizeof (version));
memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
memcpy (&ghdr.version, &version, sizeof (version));
fwrite (&ghdr, sizeof (ghdr), 1, fp);
for (ptr = __bb_head; ptr != 0; ptr = ptr->next)

View file

@ -36,6 +36,7 @@
#include <sys/gmon_out.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
@ -60,6 +61,7 @@ static int s_scale;
#define ERR(s) write(2, s, sizeof(s) - 1)
void moncontrol __P ((int mode));
void __moncontrol __P ((int mode));
static void write_hist __P ((int fd));
static void write_call_graph __P ((int fd));
static void write_bb_counts __P ((int fd));
@ -70,7 +72,7 @@ static void write_bb_counts __P ((int fd));
* all the data structures are ready.
*/
void
moncontrol (mode)
__moncontrol (mode)
int mode;
{
struct gmonparam *p = &_gmonparam;
@ -91,7 +93,7 @@ moncontrol (mode)
void
monstartup (lowpc, highpc)
__monstartup (lowpc, highpc)
u_long lowpc;
u_long highpc;
{
@ -128,7 +130,7 @@ monstartup (lowpc, highpc)
ERR(_("monstartup: out of memory\n"));
return;
}
bzero(cp, p->kcountsize + p->fromssize + p->tossize);
memset (cp, '\0', p->kcountsize + p->fromssize + p->tossize);
p->tos = (struct tostruct *)cp;
cp += p->tossize;
p->kcount = (u_short *)cp;
@ -158,7 +160,7 @@ monstartup (lowpc, highpc)
} else
s_scale = SCALE_1_TO_1;
moncontrol(1);
__moncontrol(1);
}
@ -180,8 +182,9 @@ write_hist (fd)
*(char **) thdr.low_pc = (char *) _gmonparam.lowpc;
*(char **) thdr.high_pc = (char *) _gmonparam.highpc;
*(int *) thdr.hist_size = _gmonparam.kcountsize / sizeof (HISTCOUNTER);
*(int *) thdr.prof_rate = __profile_frequency ();
*(int32_t *) thdr.hist_size = (_gmonparam.kcountsize
/ sizeof (HISTCOUNTER));
*(int32_t *) thdr.prof_rate = __profile_frequency ();
strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen));
thdr.dimen_abbrev = 's';
@ -296,18 +299,21 @@ _mcleanup ()
struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
int fd;
moncontrol (0);
__moncontrol (0);
fd = __open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
if (fd < 0)
{
perror ("_mcleanup: gmon.out");
char buf[300];
int errnum = errno;
fprintf (stderr, "_mcleanup: gmon.out: %s\n",
_strerror_internal (errnum, buf, sizeof buf));
return;
}
/* write gmon.out header: */
memset (&ghdr, 0, sizeof (struct gmon_hdr));
memset (&ghdr, '\0', sizeof (struct gmon_hdr));
memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie));
*(int *) ghdr.version = GMON_VERSION;
*(int32_t *) ghdr.version = GMON_VERSION;
__write (fd, &ghdr, sizeof (struct gmon_hdr));
/* write PC histogram: */

View file

@ -169,10 +169,11 @@ extern struct gmonparam _gmonparam;
__BEGIN_DECLS
/* Set up data structures and start profiling. */
void monstartup __P ((u_long lowpc, u_long highpc));
extern void __monstartup __P ((u_long __lowpc, u_long __highpc));
extern void monstartup __P ((u_long __lowpc, u_long __highpc));
/* Clean up profiling and write out gmon.out. */
void _mcleanup __P ((void));
extern void _mcleanup __P ((void));
__END_DECLS

View file

@ -70,7 +70,7 @@ struct gmon_cg_arc_record
char from_pc[sizeof (char *)]; /* address within caller's body */
char self_pc[sizeof (char *)]; /* address within callee's body */
char count[4]; /* number of arc traversals */
};
};
__END_DECLS

1
include/sys/gmon_out.h Normal file
View file

@ -0,0 +1 @@
#include <gmon/sys/gmon_out.h>

View file

@ -19,6 +19,8 @@
#ifndef _NETINET_ICMP6_H
#define _NETINET_ICMP6_H 1
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
@ -29,160 +31,202 @@
#define ICMPV6_FILTER_BLOCKOTHERS 3
#define ICMPV6_FILTER_PASSONLY 4
struct icmpv6_filter
struct icmp6_filter
{
u_int32_t data[8];
uint32_t data[8];
};
struct icmpv6hdr
struct icmp6_hdr
{
u_int8_t icmpv6_type; /* type field */
u_int8_t icmpv6_code; /* code field */
u_int16_t icmpv6_cksum; /* checksum field */
union
uint8_t icmp6_type; /* type field */
uint8_t icmp6_code; /* code field */
uint16_t icmp6_cksum; /* checksum field */
union
{
u_int32_t un_data32[1]; /* type-specific field */
u_int16_t un_data16[2]; /* type-specific field */
u_int8_t un_data8[4]; /* type-specific field */
} icmpv6_dataun;
};
uint32_t icmp6_un_data32[1]; /* type-specific field */
uint16_t icmp6_un_data16[2]; /* type-specific field */
uint8_t icmp6_un_data8[4]; /* type-specific field */
} icmp6_dataun;
};
#define icmpv6_data32 icmpv6_dataun.un_data32
#define icmpv6_data16 icmpv6_dataun.un_data16
#define icmpv6_data8 icmpv6_dataun.un_data8
#define icmpv6_pptr icmpv6_data32[0] /* parameter prob */
#define icmpv6_mtu icmpv6_data32[0] /* packet too big */
#define icmpv6_id icmpv6_data16[0] /* echo request/reply */
#define icmpv6_seq icmpv6_data16[1] /* echo request/reply */
#define icmpv6_maxdelay icmpv6_data16[0] /* mcast group membership */
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
#define icmp6_mtu icmp6_data32[0] /* packet too big */
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
#define ICMPV6_DEST_UNREACH 1
#define ICMPV6_PACKET_TOOBIG 2
#define ICMPV6_TIME_EXCEEDED 3
#define ICMPV6_PARAMETER_PROBLEM 4
#define ICMPV6_INFOMSG_MASK 128 /* message is info if bit set */
#define ICMPV6_ECHOREQUEST 128
#define ICMPV6_ECHOREPLY 129
#define ICMPV6_MGM_QUERY 130
#define ICMPV6_MGM_REPORT 131
#define ICMPV6_MGM_REDUCTION 132
#define ICMP6_DST_UNREACH 1
#define ICMP6_PACKET_TOO_BIG 2
#define ICMP6_TIME_EXCEEDED 3
#define ICMP6_PARAM_PROB 4
#define ICMPV6_DEST_UNREACH_NOROUTE 0
#define ICMPV6_DEST_UNREACH_ADMIN 1 /* administratively prohibited */
#define ICMPV6_DEST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor (and must be) */
#define ICMPV6_DEST_UNREACH_ADDR 3
#define ICMPV6_DEST_UNREACH_NOPORT 4
#define ICMPV6_TIME_EXCEED_HOPS 0 /* Hop Limit == 0 in transit */
#define ICMPV6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
#define ICMPV6_PARAMPROB_HEADER 0 /* erroneous header field */
#define ICMPV6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
#define ICMPV6_PARAMPROB_OPTION 2 /* unrecognized option */
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
#define ICMPV6_FILTER_WILLPASS(type, filterp) \
#define ICMP6_ECHO_REQUEST 128
#define ICMP6_ECHO_REPLY 129
#define ICMP6_MEMBERSHIP_QUERY 130
#define ICMP6_MEMBERSHIP_REPORT 131
#define ICMP6_MEMBERSHIP_REDUCTION 132
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */
/* administratively prohibited */
#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor */
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */
#define ICMP6_FILTER_WILLPASS(type, filterp) \
((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) == 0)
#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \
#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) != 0)
#define ICMPV6_FILTER_SETPASS(type, filterp) \
#define ICMP6_FILTER_SETPASS(type, filterp) \
((((filterp)->data[(type) >> 5]) &= ~(1 << ((type) & 31))))
#define ICMPV6_FILTER_SETBLOCK(type, filterp) \
#define ICMP6_FILTER_SETBLOCK(type, filterp) \
((((filterp)->data[(type) >> 5]) |= (1 << ((type) & 31))))
#define ICMPV6_FILTER_SETPASSALL(filterp) \
memset (filterp, 0, sizeof (struct icmpv6_filter));
#define ICMP6_FILTER_SETPASSALL(filterp) \
memset (filterp, 0, sizeof (struct icmp6_filter));
#define ICMPV6_FILTER_SETBLOCKALL(filterp) \
memset (filterp, 0xFF, sizeof (struct icmpv6_filter));
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
memset (filterp, 0xFF, sizeof (struct icmp6_filter));
#define ND6_ROUTER_SOLICITATION 133
#define ND6_ROUTER_ADVERTISEMENT 134
#define ND6_NEIGHBOR_SOLICITATION 135
#define ND6_NEIGHBOR_ADVERTISEMENT 136
#define ND6_REDIRECT 137
#define ND_ROUTER_SOLICIT 133
#define ND_ROUTER_ADVERT 134
#define ND_NEIGHBOR_SOLICIT 135
#define ND_NEIGHBOR_ADVERT 136
#define ND_REDIRECT 137
enum nd6_option
struct nd_router_solicit /* router solicitation */
{
ND6_OPT_SOURCE_LINKADDR=1,
ND6_OPT_TARGET_LINKADDR=2,
ND6_OPT_PREFIX_INFORMATION=3,
ND6_OPT_REDIRECTED_HEADER=4,
ND6_OPT_MTU=5,
ND6_OPT_ENDOFLIST=256
struct icmp6_hdr nd_rs_hdr;
/* could be followed by options */
};
struct nd6_router_solicit /* router solicitation */
#define nd_rs_type nd_rs_hdr.icmp6_type
#define nd_rs_code nd_rs_hdr.icmp6_code
#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
struct nd_router_advert /* router advertisement */
{
struct icmpv6hdr rsol_hdr;
struct icmp6_hdr nd_ra_hdr;
uint32_t nd_ra_reachable; /* reachable time */
uint32_t nd_ra_retransmit; /* retransmit timer */
/* could be followed by options */
};
#define rsol_type rsol_hdr.icmpv6_type
#define rsol_code rsol_hdr.icmpv6_code
#define rsol_cksum rsol_hdr.icmpv6_cksum
#define rsol_reserved rsol_hdr.icmpv6_data32[0]
#define nd_ra_type nd_ra_hdr.icmp6_type
#define nd_ra_code nd_ra_hdr.icmp6_code
#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
#define ND_RA_FLAG_MANAGED 0x80
#define ND_RA_FLAG_OTHER 0x40
#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
struct nd6_router_advert
struct nd_neighbor_solicit /* neighbor solicitation */
{
struct icmpv6hdr radv_hdr;
u_int32_t radv_reachable; /* reachable time */
u_int32_t radv_retransmit; /* reachable retransmit time */
struct icmp6_hdr nd_ns_hdr;
struct in6_addr nd_ns_target; /* target address */
/* could be followed by options */
};
#define radv_type radv_hdr.icmpv6_type
#define radv_code radv_hdr.icmpv6_code
#define radv_cksum radv_hdr.icmpv6_cksum
#define radv_maxhoplimit radv_hdr.icmpv6_data8[0]
#define radv_m_o_res radv_hdr.icmpv6_data8[1]
#define ND6_RADV_M_BIT 0x80
#define ND6_RADV_O_BIT 0x40
#define radv_router_lifetime radv_hdr.icmpv6_data16[1]
#define nd_ns_type nd_ns_hdr.icmp6_type
#define nd_ns_code nd_ns_hdr.icmp6_code
#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
struct nd6_nsolicitation /* neighbor solicitation */
struct nd_neighbor_advert /* neighbor advertisement */
{
struct icmpv6hdr nsol6_hdr;
struct in6_addr nsol6_target;
struct icmp6_hdr nd_na_hdr;
struct in6_addr nd_na_target; /* target address */
/* could be followed by options */
};
struct nd6_nadvertisement /* neighbor advertisement */
#define nd_na_type nd_na_hdr.icmp6_type
#define nd_na_code nd_na_hdr.icmp6_code
#define nd_na_cksum nd_na_hdr.icmp6_cksum
#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
#if BYTE_ORDER == BIG_ENDIAN
#define ND_NA_FLAG_ROUTER 0x80000000
#define ND_NA_FLAG_SOLICITED 0x40000000
#define ND_NA_FLAG_OVERRIDE 0x20000000
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ND_NA_FLAG_ROUTER 0x00000080
#define ND_NA_FLAG_SOLICITED 0x00000040
#define ND_NA_FLAG_OVERRIDE 0x00000020
#endif
struct nd_redirect /* redirect */
{
struct icmpv6hdr nadv6_hdr;
struct in6_addr nadv6_target;
struct icmp6_hdr nd_rd_hdr;
struct in6_addr nd_rd_target; /* target address */
struct in6_addr nd_rd_dst; /* destination address */
/* could be followed by options */
};
#define nd_rd_type nd_rd_hdr.icmp6_type
#define nd_rd_code nd_rd_hdr.icmp6_code
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
struct nd_opt_hdr /* Neighbor discovery option header */
{
uint8_t nd_opt_type;
uint8_t nd_opt_len; /* in units of 8 octets */
/* followed by option specific data */
};
#define nadv6_flags nadv6_hdr.icmpv6_data32[0]
#define ND6_NADVERFLAG_ISROUTER 0x80
#define ND6_NADVERFLAG_SOLICITED 0x40
#define ND6_NADVERFLAG_OVERRIDE 0x20
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define ND_OPT_PREFIX_INFORMATION 3
#define ND_OPT_REDIRECTED_HEADER 4
#define ND_OPT_MTU 5
struct nd6_redirect /* redirect */
struct nd_opt_prefix_info /* prefix information */
{
struct icmpv6hdr redirect_hdr;
struct in6_addr redirect_target;
struct in6_addr redirect_destination;
uint8_t nd_opt_pi_type;
uint8_t nd_opt_pi_len;
uint8_t nd_opt_pi_prefix_len;
uint8_t nd_opt_pi_flags_reserved;
uint32_t nd_opt_pi_valid_time;
uint32_t nd_opt_pi_preferred_time;
uint32_t nd_opt_pi_reserved2;
struct in6_addr nd_opt_pi_prefix;
};
struct nd6_opt_prefix_info /* prefix information */
#define ND_OPT_PI_FLAG_ONLINK 0x80
#define ND_OPT_PI_FLAG_AUTO 0x40
struct nd_opt_rd_hdr /* redirected header */
{
u_int8_t opt_type;
u_int8_t opt_length;
u_int8_t opt_prefix_length;
u_int8_t opt_l_a_res;
u_int32_t opt_valid_life;
u_int32_t opt_preferred_life;
u_int32_t opt_reserved2;
struct in6_addr opt_prefix;
uint8_t nd_opt_rh_type;
uint8_t nd_opt_rh_len;
uint16_t nd_opt_rh_reserved1;
uint32_t nd_opt_rh_reserved2;
/* followed by IP header and data */
};
#define ND6_OPT_PI_L_BIT 0x80
#define ND6_OPT_PI_A_BIT 0x40
struct nd6_opt_mtu /* MTU option */
struct nd_opt_mtu /* MTU option */
{
u_int8_t opt_type;
u_int8_t opt_length;
u_int16_t opt_reserved;
u_int32_t opt_mtu;
uint8_t nd_opt_mtu_type;
uint8_t nd_opt_mtu_len;
uint16_t nd_opt_mtu_reserved;
uint32_t nd_opt_mtu_mtu;
};
#endif /* netinet/icmpv6.h */

View file

@ -20,6 +20,7 @@
#define _NETINET_IN_H 1
#include <features.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <sys/types.h>
@ -30,19 +31,25 @@ __BEGIN_DECLS
/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
IPPROTO_TCP = 6, /* Transmission Control Protocol. */
IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
IPPROTO_PUP = 12, /* PUP protocol. */
IPPROTO_UDP = 17, /* User Datagram Protocol. */
IPPROTO_IDP = 22, /* XNS IDP protocol. */
IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling. */
IPPROTO_ICMPV6 = 58, /* ICMPv6. */
IPPROTO_RAW = 255, /* Raw IP packets. */
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
IPPROTO_TCP = 6, /* Transmission Control Protocol. */
IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
IPPROTO_PUP = 12, /* PUP protocol. */
IPPROTO_UDP = 17, /* User Datagram Protocol. */
IPPROTO_IDP = 22, /* XNS IDP protocol. */
IPPROTO_IPV6 = 41, /* IPv6 header. */
IPPROTO_ROUTING = 43, /* IPv6 routing header. */
IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
IPPROTO_ESP = 50, /* encapsulating security payload. */
IPPROTO_AH = 51, /* authentication header. */
IPPROTO_ICMPV6 = 58, /* ICMPv6. */
IPPROTO_NONE = 59, /* IPv6 no next header. */
IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
IPPROTO_RAW = 255, /* Raw IP packets. */
IPPROTO_MAX
};
@ -90,7 +97,7 @@ enum
/* Internet address. */
struct in_addr
{
u_int32_t s_addr;
uint32_t s_addr;
};
@ -142,11 +149,11 @@ struct in6_addr
{
union
{
u_int8_t u6_addr8[16];
u_int16_t u6_addr16[8];
u_int32_t u6_addr32[4];
uint8_t u6_addr8[16];
uint16_t u6_addr16[8];
uint32_t u6_addr32[4];
#if (~0UL) > 0xffffffff
u_int64_t u6_addr64[2];
uint64_t u6_addr64[2];
#endif
} in6_u;
#define s6_addr in6_u.u6_addr8
@ -171,13 +178,13 @@ extern const struct in6_addr in6addr_loopback; /* ::1 */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
unsigned short int sin_port; /* Port number. */
uint16_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (unsigned short int) -
sizeof (uint16_t) -
sizeof (struct in_addr)];
};
@ -185,8 +192,8 @@ struct sockaddr_in
struct sockaddr_in6
{
__SOCKADDR_COMMON (sin6_);
u_int16_t sin6_port; /* Transport layer port # */
u_int32_t sin6_flowinfo; /* IPv6 flow information */
uint16_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
};
@ -196,8 +203,8 @@ struct ipv6_mreq
/* IPv6 multicast address of group */
struct in6_addr ipv6mr_multiaddr;
/* local IPv6 address of interface */
int ipv6mr_ifindex;
/* local interface */
unsigned int ipv6mr_ifindex;
};
/* Get system-specific definitions. */
@ -210,10 +217,10 @@ struct ipv6_mreq
this was a short-sighted decision since on different systems the types
may have different representations but the values are always the same. */
extern u_int32_t ntohl __P ((u_int32_t __netlong));
extern u_int16_t ntohs __P ((u_int16_t __netshort));
extern u_int32_t htonl __P ((u_int32_t __hostlong));
extern u_int16_t htons __P ((u_int16_t __hostshort));
extern uint32_t ntohl __P ((uint32_t __netlong));
extern uint16_t ntohs __P ((uint16_t __netshort));
extern uint32_t htonl __P ((uint32_t __hostlong));
extern uint16_t htons __P ((uint16_t __hostshort));
#include <endian.h>
@ -237,30 +244,35 @@ extern u_int16_t htons __P ((u_int16_t __hostshort));
#endif
#define IN6_IS_ADDR_UNSPECIFIED(a) \
((((u_int32_t *) (a))[0] == 0) && ((u_int32_t *) (a))[1] == 0) && \
(((u_int32_t *) (a))[2] == 0) && ((u_int32_t *) (a))[3] == 0))
((((uint32_t *) (a))[0] == 0) && ((uint32_t *) (a))[1] == 0) && \
(((uint32_t *) (a))[2] == 0) && ((uint32_t *) (a))[3] == 0))
#define IN6_IS_ADDR_LOOPBACK(a) \
((((u_int32_t *) (a))[0] == 0) && ((u_int32_t *) (a))[1] == 0) && \
(((u_int32_t *) (a))[2] == 0) && ((u_int32_t *) (a))[3] == htonl (1)))
((((uint32_t *) (a))[0] == 0) && ((uint32_t *) (a))[1] == 0) && \
(((uint32_t *) (a))[2] == 0) && ((uint32_t *) (a))[3] == htonl (1)))
#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
#define IN6_IS_ADDR_LINKLOCAL(a) \
((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
((((uint32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
#define IN6_IS_ADDR_SITELOCAL(a) \
((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfec00000))
((((uint32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfec00000))
#define IN6_IS_ADDR_V4MAPPED(a) \
((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
(((u_int32_t *) (a))[2] == htonl (0xffff)))
((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
(((uint32_t *) (a))[2] == htonl (0xffff)))
#define IN6_IS_ADDR_V4COMPAT(a) \
((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
(((u_int32_t *) (a))[2] == 0) && (ntohl (((u_int32_t *) (a))[3]) > 1))
((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
(((uint32_t *) (a))[2] == 0) && (ntohl (((uint32_t *) (a))[3]) > 1))
#define IN6_ARE_ADDR_EQUAL(a,b) \
((((uint32_t *) (a))[0] == ((uint32_t *) (b))[0]) && \
(((uint32_t *) (a))[1] == ((uint32_t *) (b))[2]) && \
(((uint32_t *) (a))[2] == ((uint32_t *) (b))[1]) && \
(((uint32_t *) (a))[3] == ((uint32_t *) (b))[3]))
/* Bind socket to a privileged IP port. */
extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
@ -268,8 +280,8 @@ extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
/* IPv6 packet information. */
struct in6_pktinfo
{
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
int ipi6_ifindex; /* send/recv interface index */
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
unsigned int ipi6_ifindex; /* send/recv interface index */
};
__END_DECLS

View file

@ -19,27 +19,88 @@
#ifndef _NETINET_IP6_H
#define _NETINET_IP6_H 1
#include <inttypes.h>
#include <netinet/in.h>
#include <endian.h>
struct ipv6hdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int8_t ipv6_version:4;
u_int8_t ipv6_priority:4; /* going away? */
u_int32_t ipv6_flowid:24;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int32_t ipv6_flowid:24;
u_int8_t ipv6_priority:4; /* going away? */
u_int8_t ipv6_version:4;
#else
# error Unknown endianness
struct ip6_hdr
{
union
{
struct ip6_hdrctl
{
uint32_t ip6_un1_flow; /* 24 bits of flow-ID */
uint16_t ip6_un1_plen; /* payload length */
uint8_t ip6_un1_nxt; /* next header */
uint8_t ip6_un1_hlim; /* hop limit */
} ip6_un1;
uint8_t ip6_un2_vfc; /* 4 bits version, 4 bits priority */
} ip6_ctlun;
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
};
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
/* Hop-by-Hop options header. */
struct ip6_hbh
{
uint8_t ip6h_nxt; /* next hesder. */
uint8_t ip6h_len; /* length in units of 8 octets. */
/* followed by options */
};
/* Destination options header */
struct ip6_dest
{
uint8_t ip6d_nxt; /* next header */
uint8_t ip6d_len; /* length in units of 8 octets */
/* followed by options */
};
/* Routing header */
struct ip6_rthdr
{
uint8_t ip6r_nxt; /* next header */
uint8_t ip6r_len; /* length in units of 8 octets */
uint8_t ip6r_type; /* routing type */
uint8_t ip6r_segleft; /* segments left */
/* followed by routing type specific data */
};
/* Type 0 Routing header */
struct ip6_rthdr0
{
uint8_t ip6r0_nxt; /* next header */
uint8_t ip6r0_len; /* length in units of 8 octets */
uint8_t ip6r0_type; /* always zero */
uint8_t ip6r0_segleft; /* segments left */
uint8_t ip6r0_reserved; /* reserved field */
uint8_t ip6r0_slmap[3]; /* strict/loose bit map */
struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */
};
/* Fragment header */
struct ip6_frag
{
uint8_t ip6f_nxt; /* next header */
uint8_t ip6f_reserved; /* reserved field */
uint16_t ip6f_offlg; /* offset, reserved, and flag */
uint32_t ip6f_ident; /* identification */
};
#if BYTE_ORDER == BIG_ENDIAN
#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
#endif
u_int16_t ipv6_len;
u_int8_t ipv6_nextheader;
u_int8_t ipv6_hoplimit;
struct in6_addr ipv6_src;
struct in6_addr ipv6_dst;
};
#endif /* netinet/ip6.h */

View file

@ -7,7 +7,7 @@ GLIBC_2.0 {
_nl_msg_cat_cntr; __environ; _environ; _res;
___brk_addr; __curbrk; _nl_current_LC_CTYPE; _libc_intl_domainname;
_sys_errlist; _sys_siglist; __progname; _nl_default_dirname;
__timezone; __daylight;
__timezone; __daylight; __tzname;
_nl_current_LC_COLLATE; __collate_element_hash;
__collate_element_strings; __collate_symbol_classes;
__collate_symbol_hash; __collate_symbol_strings;

View file

@ -514,7 +514,7 @@ Socket Addresses
Internet Domain
* Internet Address Format:: How socket addresses are specified in the
* Internet Address Formats:: How socket addresses are specified in the
Internet namespace.
* Host Addresses:: All about host addresses of Internet hosts.
* Protocols Database:: Referring to protocols by name.

View file

@ -323,7 +323,13 @@ This is a synonym for @code{AF_FILE}, for compatibility.
@vindex AF_INET
This designates the address format that goes with the Internet
namespace. (@code{PF_INET} is the name of that namespace.)
@xref{Internet Address Format}.
@xref{Internet Address Formats}.
@comment sys/socket.h
@comment IPv6 Basic API
@item AF_INET6
This is similar to @code{AF_INET}, but refers to the IPv6 protocol.
(@code{PF_INET6} is the name of the corresponding namespace.)
@comment sys/socket.h
@comment BSD
@ -566,7 +572,7 @@ A socket address for the Internet namespace includes the following components:
@item
The address of the machine you want to connect to. Internet addresses
can be specified in several ways; these are discussed in @ref{Internet
Address Format}, @ref{Host Addresses}, and @ref{Host Names}.
Address Formats}, @ref{Host Addresses}, and @ref{Host Names}.
@item
A port number for that machine. @xref{Ports}.
@ -577,7 +583,7 @@ canonical format called @dfn{network byte order}. @xref{Byte Order},
for information about this.
@menu
* Internet Address Format:: How socket addresses are specified in the
* Internet Address Formats:: How socket addresses are specified in the
Internet namespace.
* Host Addresses:: All about host addresses of internet host.
* Protocols Database:: Referring to protocols by name.
@ -589,16 +595,17 @@ for information about this.
* Inet Example:: Putting it all together.
@end menu
@node Internet Address Format
@subsection Internet Socket Address Format
@node Internet Address Formats
@subsection Internet Socket Address Formats
In the Internet namespace, a socket address consists of a host address
In the Internet namespace, for both IPv4 (@code{AF_INET}) and IPv6
(@code{AF_INET6}), a socket address consists of a host address
and a port on that host. In addition, the protocol you choose serves
effectively as a part of the address because local port numbers are
meaningful only within a particular protocol.
The data type for representing socket addresses in the Internet namespace
is defined in the header file @file{netinet/in.h}.
The data types for representing socket addresses in the Internet namespace
are defined in the header file @file{netinet/in.h}.
@pindex netinet/in.h
@comment netinet/in.h
@ -627,13 +634,39 @@ When you call @code{bind} or @code{getsockname}, you should specify
@code{sizeof (struct sockaddr_in)} as the @var{length} parameter if
you are using an Internet namespace socket address.
@deftp {Data Type} {struct sockaddr_in6}
This is the data type used to represent socket addresses in the IPv6
namespace. It has the following members:
@table @code
@item short int sin6_family
This identifies the address family or format of the socket address.
You should store the value of @code{AF_INET6} in this member.
@xref{Socket Addresses}.
@item struct in6_addr sin6_addr
This is the IPv6 address of the host machine. @xref{Host
Addresses}, and @ref{Host Names}, for how to get a value to store
here.
@item uint32_t sin6_flowinfo
This is a currently unimplemented field.
@item uint16_t sin6_port
This is the port number. @xref{Ports}.
@end table
@end deftp
@node Host Addresses
@subsection Host Addresses
Each computer on the Internet has one or more @dfn{Internet addresses},
numbers which identify that computer among all those on the Internet.
Users typically write numeric host addresses as sequences of four
numbers, separated by periods, as in @samp{128.52.46.32}.
Users typically write IPv4 numeric host addresses as sequences of four
numbers, separated by periods, as in @samp{128.52.46.32}, and IPv6
numeric host addresses as sequences of up to eight numbers seperated by
colons, as in @samp{5f03:1200:836f:c100::1}.
Each computer also has one or more @dfn{host names}, which are strings
of words separated by periods, as in @samp{churchy.gnu.ai.mit.edu}.
@ -660,6 +693,9 @@ Each computer on the Internet has one or more Internet addresses,
numbers which identify that computer among all those on the Internet.
@end ifinfo
@c I think this whole section could possibly be removed. It is slightly
@c misleading these days.
@cindex network number
@cindex local network address number
An Internet host address is a number containing four bytes of data.
@ -779,6 +815,31 @@ This constant is the address you use to send a broadcast message.
This constant is returned by some functions to indicate an error.
@end deftypevr
@comment netinet/in.h
@comment IPv6 basic API
@deftp {Data Type} {struct in6_addr}
This data type is used to store an IPv6 address. It stores 128 bits of
data, which can be accessed (via a union) in a variety of ways.
@end deftp
@comment netinet/in.h
@comment IPv6 basic API
@deftypevr Constant {struct in6_addr} in6addr_loopback.
This constant is the IPv6 address @samp{::1}, the loopback address. See
above for a description of what this means. The macro
@code{IN6ADDR_LOOPBACK_INIT} is provided to allow you to initialise your
own variables to this value.
@end deftypevr
@comment netinet/in.h
@comment IPv6 basic API
@deftypevr Constant {struct in6_addr} in6addr_any
This constant is the IPv6 address @samp{::}, the unspecified address. See
above for a description of what this means. The macro
@code{IN6ADDR_ANY_INIT} is provided to allow you to initialise your
own variables to this value.
@end deftypevr
@node Host Address Functions
@subsubsection Host Address Functions
@ -854,6 +915,30 @@ This function returns the network number part of the Internet host
address @var{addr}.
@end deftypefun
@comment arpa/inet.h
@comment IPv6 basic API
@deftypefun int inet_pton (int @var{af}, const char *@var{cp}, void
*@var{buf})
This function converts an Internet address (either IPv4 or IPv6) from
presentation (textual) to network (binary) format. @var{af} should be
either @code{AF_INET} or @code{AF_INET6}, as appropriate for the type of
address being converted. @var{cp} is a pointer to the input string, and
@var{buf} is a pointer to a buffer for the result. It is the caller's
responsibility to make sure the buffer is large enough.
@end deftypefun
@comment arpa/inet.h
@comment IPv6 basic API
@deftypefun char *inet_ntop(int @var{af}, const void *@var{cp}, char
*@var{buf}, size_t @var{len})
This function converts an Internet address (either IPv4 or IPv6) from
network (binary) to presentation (textual) form. @var{af} should be
either @code{AF_INET} or @code{AF_INET6}, as appropriate. @var{cp} is a
pointer to the address to be converted. @var{buf} should be a pointer
to a buffer to hold the result, and @var{len} is the length of this
buffer. The return value from the function will be this buffer address.
@end deftypefun
@node Host Names
@subsubsection Host Names
@cindex hosts database
@ -891,11 +976,12 @@ These are alternative names for the host, represented as a null-terminated
vector of strings.
@item int h_addrtype
This is the host address type; in practice, its value is always
@code{AF_INET}. In principle other kinds of addresses could be
represented in the data base as well as Internet addresses; if this were
done, you might find a value in this field other than @code{AF_INET}.
@xref{Socket Addresses}.
This is the host address type; in practice, its value is always either
@code{AF_INET} or @code{AF_INET6}, with the latter being used for IPv6
hosts. In principle other kinds of addresses could be represented in
the data base as well as Internet addresses; if this were done, you
might find a value in this field other than @code{AF_INET} or
@code{AF_INET6}. @xref{Socket Addresses}.
@item int h_length
This is the length, in bytes, of each address.
@ -917,10 +1003,12 @@ implicit assumption that you can convert this to a @code{struct in_addr} or
an @code{unsigned long int}. Host addresses in a @code{struct hostent}
structure are always given in network byte order; see @ref{Byte Order}.
You can use @code{gethostbyname} or @code{gethostbyaddr} to search the
hosts database for information about a particular host. The information
is returned in a statically-allocated structure; you must copy the
information if you need to save it across calls.
You can use @code{gethostbyname}, @code{gethostbyname2} or
@code{gethostbyaddr} to search the hosts database for information about
a particular host. The information is returned in a
statically-allocated structure; you must copy the information if you
need to save it across calls. You can also use @code{getaddrinfo} and
@code{getnameinfo} to obtain this information.
@comment netdb.h
@comment BSD
@ -929,6 +1017,14 @@ The @code{gethostbyname} function returns information about the host
named @var{name}. If the lookup fails, it returns a null pointer.
@end deftypefun
@comment netdb.h
@comment IPv6 Basic API
@deftypefun {struct hostent *} gethostbyname2 (const char *@var{name}, int @var{af})
The @code{gethostbyname2} function is like @code{gethostbyname}, but
allows the caller to specify the desired address family (e.g.@:
@code{AF_INET} or @code{AF_INET6}) for the result.
@end deftypefun
@comment netdb.h
@comment BSD
@deftypefun {struct hostent *} gethostbyaddr (const char *@var{addr}, int @var{length}, int @var{format})

View file

@ -1,5 +1,5 @@
%% TeX macros to handle Texinfo files.
%% $Id: texinfo.tex,v 2.210 1997/07/15 19:22:46 drepper Exp $
%% $Id: texinfo.tex,v 2.211 1997/07/28 21:55:24 drepper Exp $
% Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
% 94, 95, 96, 97 Free Software Foundation, Inc.
@ -36,7 +36,7 @@
% This automatically updates the version number based on RCS.
\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
\deftexinfoversion$Revision: 2.210 $
\deftexinfoversion$Revision: 2.211 $
\message{Loading texinfo package [Version \texinfoversion]:}
% If in a .fmt file, print the version number
@ -1406,14 +1406,12 @@ where each line of input produces a line of output.}
\else{\tclose{\kbdfont\look}}\fi
\else{\tclose{\kbdfont\look}}\fi}
% @url, @email. Quotes do not seem necessary.
\let\url=\code % perhaps include a hypertex \special eventually
% rms does not like the angle brackets --karl, 17may97.
%\def\email#1{$\langle${\tt #1}$\rangle$}
\let\email=\code
% @url. Quotes do not seem necessary, so use \code.
\let\url=\code
% @uref (abbreviation for `urlref') takes an optional second argument
% specifying the text to display. First (mandatory) arg is the url.
% Perhaps eventually put in a hypertex \special here.
%
\def\uref#1{\urefxxx #1,,\finish}
\def\urefxxx#1,#2,#3\finish{%
@ -1425,6 +1423,11 @@ where each line of input produces a line of output.}
\fi
}
% rms does not like the angle brackets --karl, 17may97.
% So now @email is just like @uref.
%\def\email#1{$\langle${\tt #1}$\rangle$}
\let\email=\uref
% Check if we are currently using a typewriter font. Since all the
% Computer Modern typewriter fonts have zero interword stretch (and
% shrink), and it is reasonable to expect all typewriter fonts to have

View file

@ -50,7 +50,8 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
nis_verifygroup nis_ismember nis_addmember nis_util\
nis_removemember nis_creategroup nis_destroygroup\
nis_print_group_entry nis_domain_of nis_domain_of_r\
nis_modify nis_remove nis_add nis_defaults lckcache
nis_modify nis_remove nis_add nis_defaults lckcache\
nis_findserv
libnsl-map = libnsl.map
libnss_compat-routines := $(addprefix compat-,grp pwd spwd) nisplus-parser

View file

@ -9,4 +9,3 @@
* Missing flags:
- FOLLOW_PATH (nis_list, not supported)
- ALL_RESULTS (nis_list, not supported, needs server callback)
- NO_CACHE (__do_niscall, cache not supported yet)

View file

@ -1,6 +1,6 @@
/* Handle locking of NIS+ cache file.
Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library and based on shadow/lckfile.c.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@ -30,7 +30,7 @@
/* How long to wait for getting the lock before returning with an
error. */
#define TIMEOUT 15 /* sec */
#define TIMEOUT 5 /* sec */
/* File descriptor for lock file. */
@ -141,7 +141,7 @@ __nis_lock_cache (void)
memset (&fl, '\0', sizeof (struct flock));
fl.l_type = F_RDLCK;
fl.l_whence = SEEK_SET;
result = fcntl (lock_fd, F_SETLK, &fl);
result = fcntl (lock_fd, F_SETLKW, &fl);
RETURN_CLEAR_ALARM (result);
}

View file

@ -29,30 +29,7 @@
static struct timeval TIMEOUT = {10, 0};
struct dir_binding
{
CLIENT *clnt; /* RPC CLIENT handle */
nis_server *server_val; /* List of servers */
u_int server_len; /* # of servers */
u_int server_used; /* Which server we are bind in the moment ? */
u_int trys; /* How many server have we tried ? */
bool_t master_only; /* Is only binded to the master */
bool_t use_auth; /* Do we use AUTH ? */
bool_t use_udp; /* Do we use UDP ? */
time_t create; /* Binding creation time */
struct sockaddr_in addr; /* Server's IP address */
int socket; /* Server's local socket */
unsigned short port; /* Local port */
};
typedef struct dir_binding dir_binding;
static inline u_int
__nis_ping (const nis_server *serv, u_int serv_len)
{
return 0;
}
static unsigned long
unsigned long
inetstr2int (const char *str)
{
char buffer[strlen (str) + 3];
@ -92,12 +69,7 @@ __bind_destroy (dir_binding *bind)
static nis_error
__bind_next (dir_binding *bind)
{
if (bind->trys >= bind->server_len)
return NIS_FAIL;
bind->server_used++;
if (bind->server_used >= bind->server_len)
bind->server_used = 0;
u_int j;
if (bind->clnt != NULL)
{
@ -106,8 +78,38 @@ __bind_next (dir_binding *bind)
clnt_destroy (bind->clnt);
bind->clnt = NULL;
}
return NIS_SUCCESS;
if (bind->trys >= bind->server_len)
return NIS_FAIL;
for (j = bind->current_ep + 1;
j < bind->server_val[bind->server_used].ep.ep_len; ++j)
if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
"inet") == 0)
if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
"-") == 0)
{
bind->current_ep = j;
return NIS_SUCCESS;
}
++bind->trys;
++bind->server_used;
if (bind->server_used >= bind->server_len)
bind->server_used = 0;
for (j = bind->current_ep + 1;
j < bind->server_val[bind->server_used].ep.ep_len; ++j)
if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
"inet") == 0)
if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
"-") == 0)
{
bind->current_ep = j;
return NIS_SUCCESS;
}
return NIS_FAIL;
}
static nis_error
@ -116,7 +118,6 @@ __bind_connect (dir_binding *dbp)
struct sockaddr_in check;
nis_server *serv;
int checklen;
u_int i;
if (dbp == NULL)
return NIS_FAIL;
@ -125,26 +126,10 @@ __bind_connect (dir_binding *dbp)
memset (&dbp->addr, '\0', sizeof (dbp->addr));
dbp->addr.sin_family = AF_INET;
for (i = 0; i < serv->ep.ep_len; ++i)
{
if (strcmp (serv->ep.ep_val[i].family, "inet") == 0)
{
if (dbp->use_udp)
{
if (strcmp (serv->ep.ep_val[i].proto, "udp") == 0)
dbp->addr.sin_addr.s_addr =
inetstr2int (serv->ep.ep_val[i].uaddr);
else
continue;
}
else
if (strcmp (serv->ep.ep_val[i].proto, "tcp") == 0)
dbp->addr.sin_addr.s_addr =
inetstr2int (serv->ep.ep_val[i].uaddr);
}
else
continue;
}
dbp->addr.sin_addr.s_addr =
inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
if (dbp->addr.sin_addr.s_addr == 0)
return NIS_FAIL;
@ -155,15 +140,15 @@ __bind_connect (dir_binding *dbp)
else
dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
&dbp->socket, 0, 0);
if (dbp->clnt == NULL)
return NIS_RPCERROR;
clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&TIMEOUT);
/* If the program exists, close the socket */
if (fcntl (dbp->socket, F_SETFD, 1) == -1)
perror (_("fcntl: F_SETFD"));
if (dbp->use_auth)
{
#if defined(HAVE_SECURE_RPC)
@ -171,7 +156,7 @@ __bind_connect (dir_binding *dbp)
{
char netname[MAXNETNAMELEN+1];
char *p;
p = stpcpy (netname, "unix.");
strncpy (p, serv->name,MAXNETNAMELEN-5);
netname[MAXNETNAMELEN] = '\0';
@ -187,7 +172,7 @@ __bind_connect (dir_binding *dbp)
dbp->clnt->cl_auth = authunix_create_default ();
dbp->use_auth = TRUE;
}
/* Get port for sanity checks later */
checklen = sizeof (struct sockaddr_in);
memset (&check, 0, checklen);
@ -207,11 +192,11 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
{
dir_binding *dbp;
u_int i;
dbp = calloc (1, sizeof (dir_binding));
if (dbp == NULL)
return NULL;
dbp->server_len = serv_len;
dbp->server_val = calloc (1, sizeof (nis_server) * serv_len);
if (dbp->server_val == NULL)
@ -219,17 +204,34 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
free (dbp);
return NULL;
}
if (flags & USE_DGRAM)
dbp->use_udp = TRUE;
else
dbp->use_udp = FALSE;
if (flags & NO_AUTHINFO)
dbp->use_auth = FALSE;
else
dbp->use_auth = TRUE;
if (flags & MASTER_ONLY)
dbp->master_only = TRUE;
else
dbp->master_only = FALSE;
dbp->trys = 1;
for (i = 0; i < serv_len; ++i)
{
if (serv_val[i].name != NULL)
dbp->server_val[i].name = strdup (serv_val[i].name);
dbp->server_val[i].ep.ep_len = serv_val[i].ep.ep_len;
if (dbp->server_val[i].ep.ep_len > 0)
{
unsigned long j;
dbp->server_val[i].ep.ep_val =
malloc (serv_val[i].ep.ep_len * sizeof (endpoint));
for (j = 0; j < dbp->server_val[i].ep.ep_len; ++j)
@ -267,24 +269,12 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
else
dbp->server_val[i].pkey.n_bytes = NULL;
}
dbp->server_used = __nis_ping (dbp->server_val, dbp->server_len);
if (flags & USE_DGRAM)
dbp->use_udp = TRUE;
else
dbp->use_udp = FALSE;
if (flags & NO_AUTHINFO)
dbp->use_auth = FALSE;
else
dbp->use_auth = TRUE;
if (flags & MASTER_ONLY)
dbp->master_only = TRUE;
else
dbp->master_only = FALSE;
dbp->trys = 1;
if (__nis_findfastest (dbp) < 1)
{
__bind_destroy (dbp);
return NULL;
}
return dbp;
}
@ -298,10 +288,11 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
nis_error retcode;
dir_binding *dbp;
if (flags & MASTER_ONLY)
if (flags & MASTER_ONLY)
server_len = 1;
dbp = __bind_create (server, server_len, flags);
if ((dbp = __bind_create (server, server_len, flags)) == NULL)
return NIS_UNAVAIL;
while (__bind_connect (dbp) != NIS_SUCCESS)
{
if (__bind_next (dbp) != NIS_SUCCESS)
@ -315,7 +306,7 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
{
again:
result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, TIMEOUT);
if (result != RPC_SUCCESS)
{
clnt_perror (dbp->clnt, "__do_niscall2: clnt_call");
@ -336,25 +327,56 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
case NIS_IBREMOVE:
case NIS_IBFIRST:
case NIS_IBNEXT:
if ((((nis_result *)xres)->status != NIS_SUCCESS) &&
(((nis_result *)xres)->status != NIS_S_SUCCESS))
if (__bind_next (dbp) == NIS_SUCCESS)
if ((((nis_result *)xres)->status == NIS_NOTFOUND) ||
(((nis_result *)xres)->status == NIS_NOSUCHNAME) ||
(((nis_result *)xres)->status == NIS_NOT_ME))
{
if (__bind_next (dbp) == NIS_SUCCESS)
while (__bind_connect (dbp) != NIS_SUCCESS)
{
if (__bind_next (dbp) != NIS_SUCCESS)
{
__bind_destroy (dbp);
return NIS_SUCCESS;
}
}
goto again;
}
case NIS_FINDDIRECTORY:
if (((fd_result *)xres)->status != NIS_SUCCESS)
if (__bind_next (dbp) == NIS_SUCCESS)
if ((((fd_result *)xres)->status == NIS_NOTFOUND) ||
(((fd_result *)xres)->status == NIS_NOSUCHNAME) ||
(((fd_result *)xres)->status == NIS_NOT_ME))
{
if (__bind_next (dbp) == NIS_SUCCESS)
while (__bind_connect (dbp) != NIS_SUCCESS)
{
if (__bind_next (dbp) != NIS_SUCCESS)
{
__bind_destroy (dbp);
return NIS_SUCCESS;
}
}
goto again;
break;
#if 0
case NIS_STATUS: /* nis_taglist */
case NIS_SERVSTATE:
}
break;
case NIS_DUMPLOG: /* log_result */
case NIS_DUMP:
if ((((log_result *)xres)->lr_status == NIS_NOTFOUND) ||
(((log_result *)xres)->lr_status == NIS_NOSUCHNAME) ||
(((log_result *)xres)->lr_status == NIS_NOT_ME))
{
if (__bind_next (dbp) == NIS_SUCCESS)
while (__bind_connect (dbp) != NIS_SUCCESS)
{
if (__bind_next (dbp) != NIS_SUCCESS)
{
__bind_destroy (dbp);
return NIS_SUCCESS;
}
}
goto again;
}
break;
case NIS_CHECKPOINT: /* cp_result */
break;
#endif
default:
break;
}
@ -363,12 +385,13 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
}
}
while ((flags & HARD_LOOKUP) && retcode == NIS_RPCERROR);
return retcode;
return retcode;
}
static directory_obj *
rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags,
nis_error *status)
{
fd_result *fd_res;
XDR xdrs;
@ -399,6 +422,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
switch (nis_dir_cmp (domain, dir->do_name))
{
case SAME_NAME:
*status = NIS_SUCCESS;
return dir;
case NOT_SEQUENTIAL:
/* NOT_SEQUENTIAL means, go one up and try it there ! */
@ -413,6 +437,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
domain ! (Now I understand why a root server must be a
replica of the parent domain) */
fd_res = __nis_finddirectory (dir, ndomain);
*status = fd_res->status;
if (fd_res->status != NIS_SUCCESS)
{
nis_free_directory (dir);
@ -431,7 +456,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
/* We have found a NIS+ server serving ndomain, now
let us search for "name" */
nis_free_directory (dir);
return rec_dirsearch (name, obj, flags);
return rec_dirsearch (name, obj, flags, status);
}
else
{
@ -447,7 +472,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
char leaf [strlen (name) + 3];
char ndomain [strlen (name) + 3];
char *cp;
do
{
if (strlen (domain) == 0)
@ -463,8 +488,9 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
cp = strchr (leaf, '\0');
*cp++ = '.';
strcpy (cp, domain);
fd_res = __nis_finddirectory (dir, leaf);
*status = fd_res->status;
if (fd_res->status != NIS_SUCCESS)
{
nis_free_directory (dir);
@ -483,15 +509,17 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
/* We have found a NIS+ server serving ndomain, now
let us search for "name" */
nis_free_directory (dir);
return rec_dirsearch (name, obj, flags);
return rec_dirsearch (name, obj, flags, status);
}
}
break;
case BAD_NAME:
nis_free_directory (dir);
*status = NIS_BADNAME;
return NULL;
}
nis_free_directory (dir);
*status = NIS_FAIL;
return NULL;
}
@ -509,19 +537,20 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
if ((flags & NO_CACHE) != NO_CACHE)
dir = __cache_search (name);
if (dir == NULL)
{
nis_error status;
dir = readColdStartFile ();
if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
return NIS_UNAVAIL;
dir = rec_dirsearch (name, dir, flags);
dir = rec_dirsearch (name, dir, flags, &status);
if (dir == NULL)
return NIS_NOTFOUND;
return status;
}
if (flags & MASTER_ONLY)
if (flags & MASTER_ONLY)
{
server = dir->do_servers.do_servers_val;
server_len = 1;
@ -531,11 +560,11 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
server = dir->do_servers.do_servers_val;
server_len = dir->do_servers.do_servers_len;
}
retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp,
flags);
nis_free_directory (dir);
return retcode;

251
nis/nis_findserv.c Normal file
View file

@ -0,0 +1,251 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <rpcsvc/nis.h>
#include "nis_intern.h"
/* Private data kept per client handle, from sunrpc/clnt_udp.c */
struct cu_data
{
int cu_sock;
bool_t cu_closeit;
struct sockaddr_in cu_raddr;
int cu_rlen;
struct timeval cu_wait;
struct timeval cu_total;
struct rpc_err cu_error;
XDR cu_outxdrs;
u_int cu_xdrpos;
u_int cu_sendsz;
char *cu_outbuf;
u_int cu_recvsz;
char cu_inbuf[1];
};
/* The following is the original routine from sunrpc/pm_getport.c.
The only change is the much shorter timeout. */
/*
* pmap_getport.c
* Client interface to pmap rpc service.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
/*
* Find the mapped port for program,version.
* Calls the pmap service remotely to do the lookup.
* Returns 0 if no map exists.
*/
static u_short
__pmap_getport (struct sockaddr_in *address, u_long program,
u_long version, u_int protocol)
{
const struct timeval timeout = {1, 0};
const struct timeval tottimeout = {1, 0};
u_short port = 0;
int socket = -1;
CLIENT *client;
struct pmap parms;
address->sin_port = htons (PMAPPORT);
client = clntudp_bufcreate (address, PMAPPROG, PMAPVERS, timeout, &socket,
RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client != (CLIENT *) NULL)
{
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = 0; /* not needed or used */
if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t) xdr_pmap,
(caddr_t) & parms, (xdrproc_t) xdr_u_short,
(caddr_t) & port, tottimeout) != RPC_SUCCESS)
{
rpc_createerr.cf_stat = RPC_PMAPFAILURE;
clnt_geterr (client, &rpc_createerr.cf_error);
}
else if (port == 0)
{
rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
}
CLNT_DESTROY (client);
}
/* (void)close(socket); CLNT_DESTROY already closed it */
address->sin_port = 0;
return port;
}
/* Transmit to NULLPROC, return immediately. */
static void *
nis_null_3_send (void *argp, CLIENT * clnt)
{
static char clnt_res;
struct timeval TIMEOUT = {0, 0};
memset ((char *) &clnt_res, 0, sizeof (clnt_res));
if (clnt_call (clnt, NULLPROC,
(xdrproc_t) xdr_void, (caddr_t) argp,
(xdrproc_t) xdr_void, (caddr_t) & clnt_res,
TIMEOUT) != RPC_SUCCESS)
return NULL;
return (void *) &clnt_res;
}
/* Receive request from NULLPROC asynchronously. */
static void *
nis_null_3_recv (void *argp, CLIENT * clnt)
{
static char clnt_res;
struct timeval TIMEOUT = {0, 0};
memset ((char *) &clnt_res, 0, sizeof (clnt_res));
if (clnt_call (clnt, NULLPROC,
(xdrproc_t) NULL, (caddr_t) argp,
(xdrproc_t) xdr_void, (caddr_t) & clnt_res,
TIMEOUT) != RPC_SUCCESS)
return NULL;
return (void *) &clnt_res;
}
/* This is now the public functions, which should find the fastest server */
struct findserv_req
{
struct sockaddr_in sin;
u_long xid;
u_int server_nr;
u_int server_ep;
};
long
__nis_findfastest (dir_binding * bind)
{
struct timeval TIMEOUT = {5, 0};
struct findserv_req **pings;
struct sockaddr_in sin;
int found = -1;
time_t xid_seed, xid_lookup;
int sock, dontblock = 1;
CLIENT *clnt;
void *foo = NULL;
u_long i, j, pings_count, pings_max;
struct cu_data *cu;
pings_max = bind->server_len * 2; /* Reserve a little bit more memory
for multihomed hosts */
pings_count = 0;
pings = malloc (sizeof (struct findserv_req *) * pings_max);
xid_seed = time (NULL) ^ getpid ();
memset (&sin, '\0', sizeof (sin));
sin.sin_family = AF_INET;
for (i = 0; i < bind->server_len; i++)
for (j = 0; j < bind->server_val[i].ep.ep_len; ++j)
if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0)
if (strcmp (bind->server_val[i].ep.ep_val[j].proto, "-") == 0)
{
sin.sin_addr.s_addr =
inetstr2int (bind->server_val[i].ep.ep_val[j].uaddr);
if (sin.sin_addr.s_addr == 0)
continue;
sin.sin_port = htons (__pmap_getport (&sin, NIS_PROG,
NIS_VERSION, IPPROTO_UDP));
if (sin.sin_port == 0)
continue;
if (pings_count >= pings_max)
{
pings_max += 10;
pings = realloc (pings, sizeof (struct findserv_req) *
pings_max);
}
pings[pings_count] = calloc (1, sizeof (struct findserv_req));
memcpy ((char *) &pings[pings_count]->sin, (char *) &sin,
sizeof (sin));
pings[pings_count]->xid = xid_seed;
pings[pings_count]->server_nr = i;
pings[pings_count]->server_ep = j;
++xid_seed;
++pings_count;
}
/* Make sure at least one server was assigned */
if (pings_count == 0)
{
free (pings);
return -1;
}
/* Create RPC handle */
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
clnt = clntudp_create (&sin, NIS_PROG, NIS_VERSION, TIMEOUT, &sock);
if (clnt == NULL)
{
close (sock);
for (i = 0; i < pings_count; ++i)
free (pings[i]);
free (pings);
return -1;
}
clnt->cl_auth = authunix_create_default ();
cu = (struct cu_data *) clnt->cl_private;
TIMEOUT.tv_sec = 0;
clnt_control (clnt, CLSET_TIMEOUT, (char *) &TIMEOUT);
ioctl (sock, FIONBIO, &dontblock);
/* Send to all servers the NULLPROC */
for (i = 0; i < pings_count; ++i)
{
/* clntudp_call() will increment, subtract one */
*((u_int32_t *) (cu->cu_outbuf)) = pings[i]->xid - 1;
bcopy ((char *) &pings[i]->sin, (char *) &cu->cu_raddr,
sizeof (struct sockaddr_in));
nis_null_3_send (foo, clnt);
}
/* Receive reply */
nis_null_3_recv (foo, clnt);
xid_lookup = *((u_int32_t *) (cu->cu_inbuf));
for (i = 0; i < pings_count; i++)
{
if (pings[i]->xid == xid_lookup)
{
bind->server_used = pings[i]->server_nr;
bind->current_ep = pings[i]->server_ep;
found = 1;
}
}
auth_destroy (clnt->cl_auth);
clnt_destroy (clnt);
close (sock);
for (i = 0; i < pings_count; ++i)
free (pings[i]);
free (pings);
return found;
}

View file

@ -24,12 +24,32 @@
__BEGIN_DECLS
struct dir_binding
{
CLIENT *clnt; /* RPC CLIENT handle */
nis_server *server_val; /* List of servers */
u_int server_len; /* # of servers */
u_int server_used; /* Which server we are bind in the moment ? */
u_int current_ep; /* Which endpoint of the server are in use? */
u_int trys; /* How many server have we tried ? */
bool_t master_only; /* Is only binded to the master */
bool_t use_auth; /* Do we use AUTH ? */
bool_t use_udp; /* Do we use UDP ? */
time_t create; /* Binding creation time */
struct sockaddr_in addr; /* Server's IP address */
int socket; /* Server's local socket */
unsigned short port; /* Local port */
};
typedef struct dir_binding dir_binding;
extern unsigned long inetstr2int __P ((const char *str));
extern long __nis_findfastest __P ((dir_binding *bind));
extern nis_error __do_niscall2 __P ((const nis_server *serv, u_int serv_len,
u_long prog, xdrproc_t xargs, caddr_t req,
xdrproc_t xres, caddr_t resp,
xdrproc_t xres, caddr_t resp,
u_long flags));
extern nis_error __do_niscall __P ((const_nis_name name, u_long prog,
xdrproc_t xargs, caddr_t req,
xdrproc_t xargs, caddr_t req,
xdrproc_t xres, caddr_t resp,
u_long flags));
#if defined (HAVE_SECURE_RPC)

View file

@ -96,6 +96,10 @@ nis_lookup (const_nis_name name, const u_long flags)
/* XXX Implement CALLBACK here ! */
++done;
break;
case NIS_UNAVAIL:
/* NIS+ is not installed, or all servers are down */
++done;
break;
default:
/* Try the next domainname if we don't follow a link */
if (count_links)

View file

@ -34,7 +34,7 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
if (dirobj == NULL)
{
res = nis_lookup (dirname, EXPAND_NAME + FOLLOW_LINKS);
res = nis_lookup (dirname, MASTER_ONLY);
if (res->status != NIS_SUCCESS && res->status != NIS_S_SUCCESS)
return;
obj = res->objects.objects_val;
@ -44,7 +44,11 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
/* Check if obj is really a diryectory object */
if (obj->zo_data.zo_type != DIRECTORY_OBJ)
abort ();
{
if (res != NULL)
nis_freeresult (res);
return;
}
if (dirname == NULL)
args.dir = obj->DI_data.do_name;

View file

@ -248,7 +248,11 @@ nis_list (const_nis_name name, u_long flags,
/* XXX Implement CALLBACK here ! */
++done;
break;
default:
case NIS_UNAVAIL:
/* NIS+ is not installed, or all servers are down */
++done;
break;
default:
/* Try the next domainname if we don't follow a link */
if (count_links)
{

View file

@ -24,6 +24,7 @@
fd_result *
__nis_finddirectory (directory_obj *dir, const_nis_name name)
{
nis_error status;
fd_args fd_args;
fd_result *fd_res;
@ -31,13 +32,14 @@ __nis_finddirectory (directory_obj *dir, const_nis_name name)
fd_args.requester = nis_local_host();
fd_res = calloc (1, sizeof (fd_result));
if (__do_niscall2 (dir->do_servers.do_servers_val,
dir->do_servers.do_servers_len, NIS_FINDDIRECTORY,
(xdrproc_t) xdr_fd_args,
(caddr_t) &fd_args, (xdrproc_t) xdr_fd_result,
(caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM) != NIS_SUCCESS)
fd_res->status = NIS_RPCERROR;
if ((status = __do_niscall2 (dir->do_servers.do_servers_val,
dir->do_servers.do_servers_len,
NIS_FINDDIRECTORY, (xdrproc_t) xdr_fd_args,
(caddr_t) &fd_args, (xdrproc_t) xdr_fd_result,
(caddr_t) fd_res,
NO_AUTHINFO|USE_DGRAM)) != NIS_SUCCESS)
fd_res->status = status;
return fd_res;
}

View file

@ -18,6 +18,7 @@
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <fcntl.h>
#include <nss.h>
#include <grp.h>
#include <ctype.h>
@ -132,6 +133,26 @@ internal_setgrent (ent_t *ent)
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl (fileno (ent->stream), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
fclose (ent->stream);
ent->stream = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
else
rewind (ent->stream);
@ -277,7 +298,7 @@ getgrent_next_nis (struct group *result, ent_t *ent, char *buffer,
if (!save_nis_first)
free (save_oldkey);
}
if (parse_res &&
in_blacklist (result->gr_name, strlen (result->gr_name), ent))
parse_res = 0; /* if result->gr_name in blacklist,search next entry */
@ -297,7 +318,7 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
{
nis_result *save_oldres;
bool_t save_nis_first;
if (ent->nis_first)
{
save_oldres = ent->result;
@ -324,7 +345,7 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
return niserr2nss (ent->result->status);
}
}
if ((parse_res = _nss_nisplus_parse_grent (ent->result, 0, result,
if ((parse_res = _nss_nisplus_parse_grent (ent->result, 0, result,
buffer, buflen)) == -1)
{
nis_freeresult (ent->result);
@ -370,7 +391,7 @@ getgrent_next_file_plusgroup (struct group *result, char *buffer,
nis_freeresult (res);
return status;
}
if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
buflen)) == -1)
{
__set_errno (ERANGE);

View file

@ -21,6 +21,7 @@
#include <pwd.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <netdb.h>
#include <string.h>
#include <bits/libc-lock.h>
@ -232,6 +233,26 @@ internal_setpwent (ent_t *ent)
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl (fileno (ent->stream), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
fclose (ent->stream);
ent->stream = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
else
rewind (ent->stream);
@ -274,7 +295,7 @@ internal_endpwent (ent_t *ent)
if (ent->netgroup)
__internal_endnetgrent (&ent->netgrdata);
ent->nis = ent->first = ent->netgroup = 0;
if (ent->oldkey != NULL)
@ -432,13 +453,13 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
give_pwd_free (&ent->pwd);
return NSS_STATUS_RETURN;
}
if (user == NULL || user[0] == '-')
continue;
if (domain != NULL && strcmp (ypdomain, domain) != 0)
continue;
p2len = pwd_need_buflen (&ent->pwd);
if (p2len > buflen)
{
@ -457,7 +478,7 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
nis_freeresult (nisres);
continue;
}
if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
buflen)) == -1)
{
nis_freeresult (nisres);
@ -551,7 +572,7 @@ getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
if (!saved_first)
nis_freeresult (saved_res);
}
if (parse_res &&
in_blacklist (result->pw_name, strlen (result->pw_name), ent))
parse_res = 0; /* if result->pw_name in blacklist,search next entry */
@ -592,7 +613,7 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
bool_t saved_first;
char *saved_oldkey;
int saved_oldlen;
if (ent->first)
{
if (yp_first (domain, "passwd.byname", &outkey, &outkeylen,
@ -602,7 +623,7 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
give_pwd_free (&ent->pwd);
return NSS_STATUS_UNAVAIL;
}
saved_first = TRUE;
saved_oldkey = ent->oldkey;
saved_oldlen = ent->oldkeylen;
@ -699,7 +720,7 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
nis_freeresult (res);
return status;
}
if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
buflen)) == -1)
{
nis_freeresult (res);
@ -713,10 +734,10 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
char *domain;
char *outval;
int outvallen;
if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
return NSS_STATUS_TRYAGAIN;
if (yp_match (domain, "passwd.byname", &result->pw_name[1],
strlen (result->pw_name) - 1, &outval, &outvallen)
!= YPERR_SUCCESS)

View file

@ -20,6 +20,7 @@
#include <nss.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <netdb.h>
#include <shadow.h>
#include <string.h>
@ -184,6 +185,26 @@ internal_setspent (ent_t *ent)
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl (fileno (ent->stream), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
fclose (ent->stream);
ent->stream = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
else
rewind (ent->stream);
@ -305,10 +326,10 @@ getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
give_spwd_free (&ent->pwd);
return NSS_STATUS_RETURN;
}
if (user == NULL || user[0] == '-')
continue;
if (domain != NULL && strcmp (ypdomain, domain) != 0)
continue;
@ -651,7 +672,7 @@ getspent_next_file_plususer (struct spwd *result, char *buffer,
nis_freeresult (res);
return status;
}
if ((parse_res = _nss_nisplus_parse_spent (res, result, buffer,
if ((parse_res = _nss_nisplus_parse_spent (res, result, buffer,
buflen)) == -1)
{
nis_freeresult (res);
@ -735,7 +756,7 @@ getspent_next_file (struct spwd *result, ent_t *ent,
__set_errno (ERANGE);
return NSS_STATUS_TRYAGAIN;
}
if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
/* This is a real entry. */
break;

View file

@ -130,12 +130,15 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
(caddr_t) &ypbr, TIMEOUT) != RPC_SUCCESS)
{
clnt_destroy (client);
close (clnt_sock);
if (is_new)
free (ysd);
return YPERR_YPBIND;
}
clnt_destroy (client);
close (clnt_sock);
if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
{
switch (ypbr.ypbind_resp_u.ypbind_error)
@ -174,7 +177,10 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
}
if (ysd->dom_client)
clnt_destroy (ysd->dom_client);
{
clnt_destroy (ysd->dom_client);
close (ysd->dom_socket);
}
ysd->dom_socket = RPC_ANYSOCK;
ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
TIMEOUT, &ysd->dom_socket);
@ -635,18 +641,16 @@ yp_all (const char *indomain, const char *inmap,
(caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
(caddr_t) &status, TIMEOUT);
clnt_destroy (clnt);
close (clnt_sock);
if (result != RPC_SUCCESS)
{
clnt_perror (ydb->dom_client, "yp_all: clnt_call");
clnt_destroy (clnt);
__yp_unbind (ydb);
result = YPERR_RPC;
}
else
{
clnt_destroy (clnt);
result = YPERR_SUCCESS;
}
result = YPERR_SUCCESS;
__libc_lock_unlock (ypbindlist_lock);

View file

@ -1,5 +1,5 @@
/* Common code for DB-based databases in nss_db module.
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 1997 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
@ -66,7 +66,27 @@ internal_setent (int stayopen)
db = __dbopen (DBFILE, O_RDONLY, 0, DB_BTREE, NULL);
if (db == NULL)
status = NSS_STATUS_UNAVAIL;
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl ((*db->fd) (db), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
(*db->close) (db);
db = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
/* Remember STAYOPEN flag. */

View file

@ -1,5 +1,5 @@
/* Mail alias file parser in nss_db module.
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -51,6 +51,26 @@ internal_setent (int stayopen)
if (db == NULL)
status = NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl ((*db->fd) (db), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
(*db->close) (db);
db = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
/* Remember STAYOPEN flag. */

View file

@ -53,6 +53,26 @@ _nss_db_setnetgrent (const char *group)
if (db == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl ((*db->fd) (db), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
(*db->close) (db);
db = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
if (status == NSS_STATUS_SUCCESS)

View file

@ -21,6 +21,7 @@
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <bits/libc-lock.h>
#include "nsswitch.h"
@ -72,6 +73,26 @@ internal_setent (int stayopen)
if (stream == NULL)
status = NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl (fileno (stream), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl (fileno (stream), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
fclose (stream);
stream = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
else
rewind (stream);

View file

@ -1,5 +1,5 @@
/* Mail alias file parser in nss_files module.
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -21,6 +21,7 @@
#include <aliases.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <bits/libc-lock.h>
#include <stdlib.h>
#include <stdio.h>
@ -49,6 +50,26 @@ internal_setent (void)
if (stream == NULL)
status = NSS_STATUS_UNAVAIL;
else
{
/* We have to make sure the file is `closed on exec'. */
int result, flags;
result = flags = fcntl (fileno (stream), F_GETFD, 0);
if (result >= 0)
{
flags |= FD_CLOEXEC;
result = fcntl (fileno (stream), F_SETFD, flags);
}
if (result < 0)
{
/* Something went wrong. Close the stream and return a
failure. */
fclose (stream);
stream = NULL;
status = NSS_STATUS_UNAVAIL;
}
}
}
else
rewind (stream);

View file

@ -50,12 +50,7 @@ LINE_PARSER
STRING_FIELD (addr, isspace, 1);
/* Parse address. */
if (inet_pton (AF_INET6, p, entdata->host_addr) > 0)
{
result->h_addrtype = AF_INET6;
result->h_length = IN6ADDRSZ;
}
else if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
{
if (_res.options & RES_USE_INET6)
{
@ -70,6 +65,11 @@ LINE_PARSER
result->h_length = INADDRSZ;
}
}
else if (inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
{
result->h_addrtype = AF_INET6;
result->h_length = IN6ADDRSZ;
}
else
/* Illegal address: ignore line. */
return 0;
@ -85,8 +85,12 @@ LINE_PARSER
#include "files-XXX.c"
DB_LOOKUP (hostbyname, ,,
LOOKUP_NAME (h_name, h_aliases),
const char *name)
{
if (result->h_addrtype != ((_res.options & RES_USE_INET6)
? AF_INET6 : AF_INET))
continue;
LOOKUP_NAME (h_name, h_aliases)
}, const char *name)
DB_LOOKUP (hostbyname2, ,,
{

View file

@ -68,6 +68,7 @@ typedef __key_t key_t;
#define __need_size_t
#include <stddef.h>
typedef size_t socklen_t;
#ifdef __USE_MISC
/* Old compatibility names for C types. */

View file

@ -118,24 +118,24 @@ extern char *strndup __P ((__const char *__string, size_t __n));
#if defined __USE_GNU && defined __GNUC__
/* Duplicate S, returning an identical alloca'd string. */
#define strdupa(s) \
# define strdupa(s) \
(__extension__ \
({ \
__const char *__old = (s); \
size_t __len = strlen (__old) + 1; \
char *__new = __builtin_alloca (__len); \
memcpy (__new, __old, __len); \
(char *) memcpy (__new, __old, __len); \
}))
/* Return an alloca'd copy of at most N bytes of string. */
#define strndupa(s, n) \
# define strndupa(s, n) \
(__extension__ \
({ \
__const char *__old = (s); \
size_t __len = strnlen (__old, (n)); \
char *__new = __builtin_alloca (__len + 1); \
__new[__len] = '\0'; \
memcpy (__new, __old, __len); \
(char *) memcpy (__new, __old, __len); \
}))
#endif
@ -182,14 +182,14 @@ extern size_t strlen __P ((__const char *__s));
If no '\0' terminator is found in that many characters, return MAXLEN. */
extern size_t strnlen __P ((__const char *__string, size_t __maxlen));
#ifdef __OPTIMIZE__
# ifdef __OPTIMIZE__
extern __inline size_t
strnlen (__const char *__string, size_t __maxlen)
{
__const char *__end = (__const char *) memchr (__string, '\0', __maxlen);
return __end ? __end - __string : __maxlen;
}
#endif
# endif
#endif
@ -207,6 +207,7 @@ extern char *strerror_r __P ((int __errnum, char *__buf, size_t __buflen));
extern void bcopy __P ((__const __ptr_t __src, __ptr_t __dest, size_t __n));
/* Set N bytes of S to 0. */
extern void __bzero __P ((__ptr_t __s, size_t __n));
extern void bzero __P ((__ptr_t __s, size_t __n));
/* Compare N bytes of S1 and S2 (same as memcmp). */

View file

@ -87,7 +87,7 @@ elf_machine_load_address (void)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf64_Addr plt;
extern void _dl_runtime_resolve (void);
@ -348,9 +348,9 @@ static inline void
elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc,
const Elf64_Sym *sym,
const struct r_found_version *version)
const struct r_found_version *version,
Elf64_Addr *const reloc_addr)
{
Elf64_Addr * const reloc_addr = (void *)(map->l_addr + reloc->r_offset);
unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
#ifndef RTLD_BOOTSTRAP

View file

@ -22,7 +22,7 @@
#undef ntohs
u_int16_t
__htons (x)
htons (x)
u_int16_t x;
{
#if BYTE_ORDER == BIG_ENDIAN

View file

@ -81,16 +81,20 @@ elf_machine_load_address (void)
destroys the passed register information. */
static ElfW(Addr) fixup (struct link_map *l, ElfW(Word) reloc_offset)
__attribute__ ((regparm (2), unused));
static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
ElfW(Addr) retaddr)
__attribute__ ((regparm (3), unused));
#endif
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int __attribute__ ((unused))
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word);
extern void _dl_runtime_profile (Elf32_Word);
if (l->l_info[DT_JMPREL] && lazy)
{
@ -100,9 +104,23 @@ elf_machine_runtime_setup (struct link_map *l, int lazy)
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
/* This function will get called to fix up the GOT entry indicated by
the offset on the stack, and then jump to the resolved address. */
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
/* The got[2] entry contains the address of a function which gets
called to get the address of a so far unresolved function and
jump to it. The profiling extension of the dynamic linker allows
to intercept the calls to collect information. In this case we
don't store the address in the GOT so that all future calls also
end in this function. */
if (profile)
{
got[2] = (Elf32_Addr) &_dl_runtime_profile;
/* Say that we really want profiling and the timers are started. */
_dl_profile_map = l;
}
else
/* This function will get called to fix up the GOT entry indicated by
the offset on the stack, and then jump to the resolved address. */
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
}
return lazy;
@ -126,12 +144,31 @@ _dl_runtime_resolve:
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_resolve, .-_dl_runtime_resolve
.globl _dl_runtime_profile
.type _dl_runtime_profile, @function
_dl_runtime_profile:
pushl %eax # Preserve registers otherwise clobbered.
pushl %ecx
pushl %edx
movl 20(%esp), %ecx # Load return address
movl 16(%esp), %edx # Copy args pushed by PLT in register. Note
movl 12(%esp), %eax # that `fixup' takes its parameters in regs.
call profile_fixup # Call resolver.
popl %edx # Get register content back.
popl %ecx
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_profile, .-_dl_runtime_profile
");
#else
# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
.globl _dl_runtime_resolve
.globl _dl_runtime_profile
.type _dl_runtime_resolve, @function
.type _dl_runtime_profile, @function
_dl_runtime_resolve:
_dl_runtime_profile:
pushl %eax # Preserve registers otherwise clobbered.
pushl %ecx
pushl %edx
@ -147,6 +184,7 @@ _dl_runtime_resolve:
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_resolve, .-_dl_runtime_resolve
.size _dl_runtime_profile, .-_dl_runtime_profile
");
#endif
/* The PLT uses Elf32_Rel relocs. */
@ -261,10 +299,9 @@ extern char **_dl_argv;
static inline void
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
const Elf32_Sym *sym, const struct r_found_version *version)
const Elf32_Sym *sym, const struct r_found_version *version,
Elf32_Addr *const reloc_addr)
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
{
#ifndef RTLD_BOOTSTRAP

View file

@ -1,7 +1,7 @@
/* Inline math functions for i387.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by John C. Bowman <bowman@ipp-garching.mpg.de>, 1995.
Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@ -28,45 +28,45 @@
These must not be inline functions since we have to be able to handle
all floating-point types. */
# define isgreater(x, y) \
({ int result; \
({ int __result; \
__asm__ ("fucompp; fnstsw; andb $0x45, %%ah; setz %%al;" \
"andl $0x01, %0" \
: "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
result; })
: "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
__result; })
# define isgreaterequal(x, y) \
({ int result; \
({ int __result; \
__asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al;" \
"andl $0x01, %0" \
: "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
result; })
: "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
__result; })
# define isless(x, y) \
({ int result; \
({ int __result; \
__asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x45, %%ah;" \
"setz %%al; andl $0x01, %0" \
: "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
result; })
: "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
__result; })
# define islessequal(x, y) \
({ int result; \
({ int __result; \
__asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x05, %%ah;" \
"setz %%al; andl $0x01, %0" \
: "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
result; })
: "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
__result; })
# define islessgreater(x, y) \
({ int result; \
({ int __result; \
__asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al;" \
"andl $0x01, %0" \
: "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
result; })
: "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
__result; })
# define isunordered(x, y) \
({ int result; \
({ int __result; \
__asm__ ("fucompp; fnstsw; sahf; setp %%al; andl $0x01, %0" \
: "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
result; })
: "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
__result; })
#endif
@ -88,425 +88,328 @@
# define __MATH_INLINE extern __inline
#endif
__MATH_INLINE double cos (double);
__MATH_INLINE double sin (double);
/* A macro to define float, double, and long double versions of various
math functions for the ix87 FPU. FUNC is the function name (which will
be suffixed with f and l for the float and long double version,
respectively). OP is the name of the FPU operation. */
#if defined __USE_MISC || defined __USE_ISOC9X
# define __inline_mathop(func, op) \
__inline_mathop_ (double, func, op) \
__inline_mathop_ (float, __CONCAT(func,f), op) \
__inline_mathop_ (long double, __CONCAT(func,l), op)
#else
# define __inline_mathop(func, op) \
__inline_mathop_ (double, func, op)
#endif
#define __inline_mathop_(float_type, func, op) \
__inline_mathop_decl_ (float_type, func, op, "0" (__x))
__MATH_INLINE double __expm1 (double __x);
__MATH_INLINE double
__expm1 (double __x)
{
register double __value, __exponent, __temp;
__asm __volatile__
("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t"
"fmul %%st(1) # x * log2(e)\n\t"
"fstl %%st(1)\n\t"
"frndint # int(x * log2(e))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(x * log2(e))\n\t"
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
"fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
: "=t" (__value), "=u" (__exponent) : "0" (__x));
__asm __volatile__
("fscale # 2^int(x * log2(e))\n\t"
: "=t" (__temp) : "0" (1.0), "u" (__exponent));
__temp -= 1.0;
#if defined __USE_MISC || defined __USE_ISOC9X
# define __inline_mathop_decl(func, op, params...) \
__inline_mathop_decl_ (double, func, op, params) \
__inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
__inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
#else
# define __inline_mathop_decl(func, op, params...) \
__inline_mathop_decl_ (double, func, op, params)
#endif
return __temp + __value;
}
#define __inline_mathop_decl_(float_type, func, op, params...) \
__MATHINLINE float_type func (float_type); \
__MATHINLINE float_type func (float_type __x) \
{ \
register float_type __result; \
__asm __volatile__ (op : "=t" (__results) : params); \
return __result; \
}
__MATH_INLINE double __sgn1 (double __x);
__MATH_INLINE double
__sgn1 (double __x)
{
return __x >= 0.0 ? 1.0 : -1.0;
}
__MATH_INLINE double sqrt (double __x);
__MATH_INLINE double
sqrt (double __x)
{
register double __value;
__asm __volatile__
("fsqrt"
: "=t" (__value) : "0" (__x));
#if defined __USE_MISC || defined __USE_ISOC9X
# define __inline_mathcode(func, arg, code) \
__inline_mathcode_ (double, func, arg, code) \
__inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
__inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
#else
# define __inline_mathcode(func, arg, code) \
__inline_mathcode_ (double, func, arg, code)
#endif
return __value;
}
#define __inline_mathcode_(float_type, func, arg, code) \
__MATH_INLINE float_type func (float_type); \
__MATH_INLINE float_type func (float_type arg) \
{ \
code; \
}
__MATH_INLINE double fabs (double __x);
__MATH_INLINE double
fabs (double __x)
{
register double __value;
__asm __volatile__
("fabs"
: "=t" (__value) : "0" (__x));
return __value;
}
#if defined __USE_MISC || defined __USE_ISOC9X
# define __inline_mathcode2(func, arg1, arg2, code) \
__inline_mathcode2_ (double, func, arg1, arg2, code) \
__inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
__inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
#else
# define __inline_mathcode2(func, arg1, arg2, code) \
__inline_mathcode2_ (double, func, arg1, arg2, code)
#endif
/* The argument range of this inline version is limited. */
__MATH_INLINE double sin (double __x);
__MATH_INLINE double
sin (double __x)
{
register double __value;
__asm __volatile__
("fsin"
: "=t" (__value) : "0" (__x));
#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
__MATH_INLINE float_type func (float_type, float_type); \
__MATH_INLINE float_type func (float_type arg1, float_type arg2) \
{ \
code; \
}
return __value;
}
/* The argument range of this inline version is limited. */
__MATH_INLINE double cos (double __x);
__MATH_INLINE double
cos (double __x)
{
register double __value;
__asm __volatile__
("fcos"
: "=t" (__value): "0" (__x));
/* Optimized inline implementation, sometimes woth reduced precision
and/or argument range. */
#define __expm1_code \
register long double __value; \
register long double __exponent; \
register long double __temp; \
__asm __volatile__ \
("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
"fmul %%st(1) # x * log2(e)\n\t" \
"fstl %%st(1)\n\t" \
"frndint # int(x * log2(e))\n\t" \
"fxch\n\t" \
"fsub %%st(1) # fract(x * log2(e))\n\t" \
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
"fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
: "=t" (__value), "=u" (__exponent) : "0" (__x)); \
__asm __volatile__ \
("fscale # 2^int(x * log2(e))\n\t" \
: "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
__temp -= 1.0; \
return __temp + __value
__inline_mathcode_ (long double, __expm1l, __x, __expm1_code)
return __value;
}
__MATH_INLINE double tan (double __x);
__MATH_INLINE double
tan (double __x)
{
register double __value;
register double __value2 __attribute__ ((unused));
__asm __volatile__
("fptan"
: "=t" (__value2), "=u" (__value) : "0" (__x));
#define __exp_code \
register long double __value; \
register long double __exponent; \
__asm __volatile__ \
("fldl2e # e^x = 2^(x * log2(e))\n\t" \
"fmul %%st(1) # x * log2(e)\n\t" \
"fstl %%st(1)\n\t" \
"frndint # int(x * log2(e))\n\t" \
"fxch\n\t" \
"fsub %%st(1) # fract(x * log2(e))\n\t" \
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
: "=t" (__value), "=u" (__exponent) : "0" (__x)); \
__value += 1.0; \
__asm __volatile__ \
("fscale" \
: "=t" (__value) : "0" (__value), "u" (__exponent)); \
return __value
__inline_mathcode (exp, __x, __exp_code)
__inline_mathcode_ (long double, __expl, __x, __exp_code)
return __value;
}
__MATH_INLINE double atan2 (double __y, double __x);
__MATH_INLINE double
atan2 (double __y, double __x)
{
register double __value;
__asm __volatile__
("fpatan\n\t"
"fldl %%st(0)"
: "=t" (__value) : "0" (__x), "u" (__y));
__inline_mathcode (tan, __x, \
register long double __value; \
register long double __value2 __attribute__ ((unused)); \
__asm __volatile__ \
("fptan" \
: "=t" (__value2), "=u" (__value) : "0" (__x)); \
return __value)
return __value;
}
__MATH_INLINE double asin (double __x);
__MATH_INLINE double
asin (double __x)
{
return atan2 (__x, sqrt (1.0 - __x * __x));
}
#define __atan2_code \
register long double __value; \
__asm __volatile__ \
("fpatan\n\t" \
: "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
return __value
__inline_mathcode2 (atan2, __y, __x, __atan2_code)
__inline_mathcode2_ (long double, __atan2l, __y, __x, __atan2_code)
__MATH_INLINE double acos (double __x);
__MATH_INLINE double
acos (double __x)
{
return atan2 (sqrt (1.0 - __x * __x), __x);
}
__MATH_INLINE double atan (double __x);
__MATH_INLINE double
atan (double __x)
{
register double __value;
__asm __volatile__
("fld1\n\t"
"fpatan"
: "=t" (__value) : "0" (__x));
__inline_mathcode2 (fmod, __x, __y, \
register long double __value; \
__asm __volatile__ \
("1: fprem\n\t" \
"fnstsw %%ax\n\t" \
"sahf\n\t" \
"jp 1b" \
: "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
return __value)
return __value;
}
__MATH_INLINE double exp (double __x);
__MATH_INLINE double
exp (double __x)
{
register double __value, __exponent;
__asm __volatile__
("fldl2e # e^x = 2^(x * log2(e))\n\t"
"fmul %%st(1) # x * log2(e)\n\t"
"fstl %%st(1)\n\t"
"frndint # int(x * log2(e))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(x * log2(e))\n\t"
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
: "=t" (__value), "=u" (__exponent) : "0" (__x));
__value += 1.0;
__asm __volatile__
("fscale"
: "=t" (__value) : "0" (__value), "u" (__exponent));
__inline_mathcode2 (pow, __x, __y, \
register long double __value; \
register long double __exponent; \
long int __p = (long int) __y; \
if (__x == 0.0 && __y > 0.0) \
return 0.0; \
if (__y == (double) __p) \
{ \
long double __r = 1.0; \
if (__p == 0) \
return 1.0; \
if (__p < 0) \
{ \
__p = -__p; \
__x = 1.0 / __x; \
} \
while (1) \
{ \
if (__p & 1) \
__r *= __x; \
__p >>= 1; \
if (__p == 0) \
return __r; \
__x *= __x; \
} \
/* NOTREACHED */ \
} \
__asm __volatile__ \
("fyl2x" : "=t" (__value) : "0" (__x), "u" (1.0) : "st1"); \
__asm __volatile__ \
("fmul %%st(1) # y * log2(x)\n\t" \
"fst %%st(1)\n\t" \
"frndint # int(y * log2(x))\n\t" \
"fxch\n\t" \
"fsub %%st(1) # fract(y * log2(x))\n\t" \
"f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" \
: "=t" (__value), "=u" (__exponent) : "0" (__y), "1" (__value)); \
__value += 1.0; \
__asm __volatile__ \
("fscale" \
: "=t" (__value) : "0" (__value), "u" (__exponent)); \
return __value)
return __value;
}
__MATH_INLINE double sinh (double __x);
__MATH_INLINE double
sinh (double __x)
{
register double __exm1 = __expm1 (fabs (__x));
__inline_mathop (sqrt, "fsqrt")
__inline_mathop_ (long double, __sqrtl, "fsqrt")
return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1 (__x);
}
__inline_mathop (fabs, "fabs")
__MATH_INLINE double cosh (double __x);
__MATH_INLINE double
cosh (double __x)
{
register double __ex = exp (__x);
/* The argument range of this inline version is reduced. */
__inline_mathop (sin, "fsin")
/* The argument range of this inline version is reduced. */
__inline_mathop (cos, "fcos")
return 0.5 * (__ex + 1.0 / __ex);
}
__inline_mathop (atan, "fld1; fpatan")
__inline_mathop (log, "fldln2; fxch; fyl2x")
__inline_mathop (log10, "fldlg2; fxch; fyl2x")
__MATH_INLINE double tanh (double __x);
__MATH_INLINE double
tanh (double __x)
{
register double __exm1 = __expm1 (-fabs (__x + __x));
__inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
__inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
return __exm1 / (__exm1 + 2.0) * __sgn1 (-__x);
}
__inline_mathcode (__sgn1, __x, return __x >= 0.0 ? 1.0 : -1.0)
__MATH_INLINE double log (double __x);
__MATH_INLINE double
log (double __x)
{
register double __value;
__asm __volatile__
("fldln2\n\t"
"fxch\n\t"
"fyl2x"
: "=t" (__value) : "0" (__x));
return __value;
}
/* The argument range of the inline version of sinhl is slightly reduced. */
__inline_mathcode (sinh, __x, \
register long double __exm1 = __expm1l (__builtin_fabsl (__x)); \
return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
__MATH_INLINE double log10 (double __x);
__MATH_INLINE double
log10 (double __x)
{
register double __value;
__asm __volatile__
("fldlg2\n\t"
"fxch\n\t"
"fyl2x"
: "=t" (__value) : "0" (__x));
__inline_mathcode (cosh, __x, \
register long double __ex = __expl (__x); \
return 0.5 * (__ex + 1.0 / __ex))
return __value;
}
__inline_mathcode (tanh, __x, \
register long double __exm1 = __expm1l (-__builtin_fabsl (__x + __x)); \
return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
__MATH_INLINE double __log2 (double __x);
__MATH_INLINE double
__log2 (double __x)
{
register double __value;
__asm __volatile__
("fyl2x"
: "=t" (__value) : "0" (__x), "u" (1.0));
return __value;
}
__inline_mathcode (floor, __x, \
register long double __value; \
__volatile unsigned short int __cw; \
__volatile unsigned short int __cwtmp; \
__asm __volatile ("fnstcw %0" : "=m" (__cw)); \
__cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
__asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
__asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
__asm __volatile ("fldcw %0" : : "m" (__cw)); \
return __value)
__MATH_INLINE double fmod (double __x, double __y);
__MATH_INLINE double
fmod (double __x, double __y)
{
register double __value;
__asm __volatile__
("1: fprem\n\t"
"fstsw %%ax\n\t"
"sahf\n\t"
"jp 1b"
: "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");
return __value;
}
__MATH_INLINE double ldexp (double __x, int __y);
__MATH_INLINE double
ldexp (double __x, int __y)
{
register double __value;
__asm __volatile__
("fscale"
: "=t" (__value) : "0" (__x), "u" ((double) __y));
return __value;
}
__MATH_INLINE double pow (double __x, double __y);
__MATH_INLINE double
pow (double __x, double __y)
{
register double __value, __exponent;
long __p = (long) __y;
if (__x == 0.0 && __y > 0.0)
return 0.0;
if (__y == (double) __p)
{
double __r = 1.0;
if (__p == 0)
return 1.0;
if (__p < 0)
{
__p = -__p;
__x = 1.0 / __x;
}
while (1)
{
if (__p & 1)
__r *= __x;
__p >>= 1;
if (__p == 0)
return __r;
__x *= __x;
}
/* NOTREACHED */
}
__asm __volatile__
("fmul %%st(1) # y * log2(x)\n\t"
"fstl %%st(1)\n\t"
"frndint # int(y * log2(x))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(y * log2(x))\n\t"
"f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
: "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y));
__value += 1.0;
__asm __volatile__
("fscale"
: "=t" (__value) : "0" (__value), "u" (__exponent));
return __value;
}
__MATH_INLINE double floor (double __x);
__MATH_INLINE double
floor (double __x)
{
register double __value;
__volatile unsigned short int __cw, __cwtmp;
__asm __volatile ("fnstcw %0" : "=m" (__cw));
__cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */
__asm __volatile ("fldcw %0" : : "m" (__cwtmp));
__asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
__asm __volatile ("fldcw %0" : : "m" (__cw));
return __value;
}
__MATH_INLINE double ceil (double __x);
__MATH_INLINE double
ceil (double __x)
{
register double __value;
__volatile unsigned short int __cw, __cwtmp;
__asm __volatile ("fnstcw %0" : "=m" (__cw));
__cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */
__asm __volatile ("fldcw %0" : : "m" (__cwtmp));
__asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
__asm __volatile ("fldcw %0" : : "m" (__cw));
return __value;
}
__inline_mathcode (ceil, __x, \
register long double __value; \
__volatile unsigned short int __cw; \
__volatile unsigned short int __cwtmp; \
__asm __volatile ("fnstcw %0" : "=m" (__cw)); \
__cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
__asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
__asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
__asm __volatile ("fldcw %0" : : "m" (__cw)); \
return __value)
/* Optimized versions for some non-standardized functions. */
#if defined __USE_ISOC9X || defined __USE_MISC
__MATH_INLINE double hypot (double __x, double __y);
__MATH_INLINE double
hypot (double __x, double __y)
{
return sqrt (__x * __x + __y * __y);
}
__inline_mathop_decl (log2, "fyl2x", "u" (1.0), "0" (__x) : "st(1)")
__inline_mathcode (expm1, __x, __expm1_code)
/* We cannot rely on M_SQRT being defined. So we do it for ourself
here. */
# define __M_SQRT2 _Mldbl(1.41421356237309504880) /* sqrt(2) */
__MATH_INLINE double log1p (double __x);
__MATH_INLINE double
log1p (double __x)
{
register double __value;
__inline_mathcode (log1p, __x, \
register long double __value; \
if (__builtin_fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
__value = logl (1.0 + __x); \
else \
__asm __volatile__ \
("fldln2\n\t" \
"fxch\n\t" \
"fyl2xp1" \
: "=t" (__value) : "0" (__x)); \
return __value)
if (fabs (__x) >= 1.0 - 0.5 * __M_SQRT2)
__value = log (1.0 + __x);
else
__asm __volatile__
("fldln2\n\t"
"fxch\n\t"
"fyl2xp1"
: "=t" (__value) : "0" (__x));
return __value;
}
/* The argument range of the inline version of asinhl is slightly reduced. */
__inline_mathcode (asinh, __x, \
register long double __y = __builtin_fabsl (__x); \
return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y) \
* __sgn1l (__x))
__MATH_INLINE double asinh (double __x);
__MATH_INLINE double
asinh (double __x)
{
register double __y = fabs (__x);
__inline_mathcode (acosh, __x, \
return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
return log1p ((__y * __y / (sqrt (__y * __y + 1.0) + 1.0) + __y)
* __sgn1 (__x));
}
__inline_mathcode (atanh, __x, \
register long double __y = __builtin_fabsl (__x); \
return (-0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * \
__sgn1l (__x)))
__MATH_INLINE double acosh (double __x);
__MATH_INLINE double
acosh (double __x)
{
return log (__x + sqrt (__x - 1.0) * sqrt (__x + 1.0));
}
__MATH_INLINE double atanh (double __x);
__MATH_INLINE double
atanh (double __x)
{
register double __y = fabs (__x);
/* The argument range of the inline version of hypotl is slightly reduced. */
__inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
return -0.5 * __log1p (-(__y + __y) / (1.0 + __y)) * __sgn1 (__x);
}
__inline_mathcode(logb, __x, \
register long double __value; \
register long double __junk; \
__asm __volatile__ \
("fxtract\n\t" \
: "=t" (__junk), "=u" (__value) : "0" (__x)); \
return __value)
__MATH_INLINE double logb (double __x);
__MATH_INLINE double
logb (double __x)
{
register double __value, __junk;
__asm __volatile__
("fxtract\n\t"
: "=t" (__junk), "=u" (__value) : "0" (__x));
return __value;
}
__inline_mathcode2 (ldexp, __x, __y, \
register long double __value; \
__asm __volatile__ \
("fscale" \
: "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
return __value)
#endif
#ifdef __USE_MISC
__MATH_INLINE double drem (double __x, double __y);
__MATH_INLINE double
drem (double __x, double __y)
{
register double __value;
__asm __volatile__
("1: fprem1\n\t"
"fstsw %%ax\n\t"
"sahf\n\t"
"jp 1b"
: "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");
__inline_mathcode2 (drem, __x, __y, \
register double __value; \
__asm __volatile__ \
("1: fprem1\n\t" \
"fstsw %%ax\n\t" \
"sahf\n\t" \
"jp 1b" \
: "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
return __value)
return __value;
}
/* This function is used in the `isfinite' macro. */
__MATH_INLINE int __finite (double __x);
@ -522,82 +425,89 @@ __finite (double __x)
return __result;
}
__MATH_INLINE double coshm1 (double __x);
__MATH_INLINE double
coshm1 (double __x)
{
register double __exm1 = __expm1 (fabs (__x));
/* Miscellaneous functions */
return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1;
}
__inline_mathcode (__sgn, __x, \
return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
__MATH_INLINE double acosh1p (double __x);
__MATH_INLINE double
acosh1p (double __x)
{
return __log1p (__x + sqrt (__x) * sqrt (__x + 2.0));
}
__inline_mathcode (__coshm1, __x, \
register long double __exm1 = __expm1l (__builtin_fabsl (__x)); \
return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
__MATH_INLINE void sincos (double __x, double *__sinx, double *__cosx);
__inline_mathcode (__acosh1p, __x, \
return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
__inline_mathcode (__pow2, __x, \
register long double __value; \
register long double __exponent; \
long int __p = (long int) __x; \
if (__x == (long double) __p) \
return ldexpl (1.0, __p); \
__asm __volatile__ \
("fldl %%st(0)\n\t" \
"frndint # int(x)\n\t" \
"fxch\n\t" \
"fsub %%st(1) # fract(x)\n\t" \
"f2xm1 # 2^(fract(x)) - 1\n\t" \
: "=t" (__value), "=u" (__exponent) : "0" (__x)); \
__value += 1.0; \
__asm __volatile__ \
("fscale" \
: "=t" (__value) : "0" (__value), "u" (__exponent)); \
return __value)
#define __sincos_code \
register long double __cosr; \
register long double __sinr; \
__asm __volatile__ \
("fsincos\n\t" \
"fnstsw %%ax\n\t" \
"testl $0x400, %%eax\n\t" \
"jz 1f\n\t" \
"fldpi\n\t" \
"fadd %%st(0)\n\t" \
"fxch %%st(1)\n\t" \
"2: fprem1\n\t" \
"fnstsw %%ax\n\t" \
"testl $0x400, %%eax\n\t" \
"jnz 2b\n\t" \
"fstp %%st(1)\n\t" \
"fsincos\n\t" \
"1:" \
: "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
*__sinx = __sinr; \
*__cosx = __cosr
__MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx);
__MATH_INLINE void
sincos (double __x, double *__sinx, double *__cosx)
__sincos (double __x, double *__sinx, double *__cosx)
{
register double __cosr, __sinr;
__asm __volatile__
("fsincos\n\t"
"fnstsw %%ax\n\t"
"testl $0x400, %%eax\n\t"
"jz 1f\n\t"
"fldpi\n\t"
"fadd %%st(0)\n\t"
"fxch %%st(1)\n\t"
"2: fprem1\n\t"
"fnstsw %%ax\n\t"
"testl $0x400, %%eax\n\t"
"jnz 2b\n\t"
"fstp %%st(1)\n\t"
"fsincos\n\t"
"1:"
: "=t" (__cosr), "=u" (__sinr) : "0" (__x));
*__sinx = __sinr;
*__cosx = __cosr;
__sincos_code;
}
__MATH_INLINE double sgn (double __x);
__MATH_INLINE double
sgn (double __x)
__MATH_INLINE void __sincosf (float __x, float *__sinx, float *__cosx);
__MATH_INLINE void
__sincosf (float __x, float *__sinx, float *__cosx)
{
return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0);
__sincos_code;
}
__MATH_INLINE double pow2 (double __x);
__MATH_INLINE double
pow2 (double __x)
__MATH_INLINE void __sincosl (long double __x, long double *__sinx,
long double *__cosx);
__MATH_INLINE void
__sincosl (long double __x, long double *__sinx, long double *__cosx)
{
register double __value, __exponent;
long __p = (long) __x;
if (__x == (double) __p)
return ldexp (1.0, __p);
__asm __volatile__
("fldl %%st(0)\n\t"
"frndint # int(x)\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(x)\n\t"
"f2xm1 # 2^(fract(x)) - 1\n\t"
: "=t" (__value), "=u" (__exponent) : "0" (__x));
__value += 1.0;
__asm __volatile__
("fscale"
: "=t" (__value) : "0" (__value), "u" (__exponent));
return __value;
__sincos_code;
}
#endif /* __USE_MISC */
/* Undefine some of the large macros which are not used anymore. */
#undef __expm1_code
#undef __exp_code
#undef __atan2_code
#undef __sincos_code
#endif /* __NO_MATH_INLINES */
#endif /* __GNUC__ */

View file

@ -0,0 +1,63 @@
/* Macros to swap the order of bytes in integer values. m68k version.
Copyright (C) 1997 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _BITS_BYTESWAP_H
#define _BITS_BYTESWAP_H 1
/* Swap bytes in 16 bit value. We don't provide an assembler version
because GCC is smart enough to generate optimal assembler output, and
this allows for better cse. */
#define __bswap_16(x) \
((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
/* Swap bytes in 32 bit value. */
#define __bswap_constant_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#if defined __GNUC__ && __GNUC__ >= 2
#define __bswap_32(x) \
__extension__ \
({ unsigned int __v; \
if (__builtin_constant_p (x)) \
__v = __bswap_constant_32 (x); \
else \
__asm__ __volatile__ ("ror%.w %#8, %0;" \
"swap %0;" \
"ror%.w %#8, %0" \
: "=d" (__v) \
: "0" (x)); \
__v; })
#else
#define __bswap_32(x) __bswap_constant_32 (x)
#endif
#if defined __GNUC__ && __GNUC__ >= 2
/* Swap bytes in 64 bit value. */
#define __bswap_64(x) \
__extension__ \
({ union { unsigned long long int __ll; \
unsigned long int __l[2]; } __v, __r; \
__v.__ll = (x); \
__r.__l[0] = __bswap_32 (__v.__l[1]); \
__r.__l[1] = __bswap_32 (__v.__l[0]); \
__r.__ll; })
#endif
#endif /* bits/byteswap.h */

View file

@ -76,7 +76,7 @@ elf_machine_load_address (void)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word);
@ -211,10 +211,9 @@ _dl_start_user:
static inline void
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version)
const Elf32_Sym *sym, const struct r_found_version *version,
Elf32_Addr *const reloc_addr)
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
if (ELF32_R_TYPE (reloc->r_info) == R_68K_RELATIVE)
*reloc_addr = map->l_addr + reloc->r_addend;
else

View file

@ -219,7 +219,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
ElfW(Addr) *got;
extern void _dl_runtime_resolve (ElfW(Word));
@ -533,9 +533,9 @@ _RTLD_EPILOGUE(ENTRY_POINT)\
static inline void
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version)
const ElfW(Sym) *sym, const struct r_found_version *version,
ElfW(Addr) *const reloc_addr)
{
ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
ElfW(Addr) loadbase;
ElfW(Addr) undo __attribute__ ((unused));

View file

@ -219,7 +219,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
ElfW(Addr) *got;
extern void _dl_runtime_resolve (ElfW(Word));
@ -529,9 +529,9 @@ _RTLD_EPILOGUE(ENTRY_POINT) \
static inline void
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version)
const ElfW(Sym) *sym, const struct r_found_version *version,
ElfW(Addr) *const reloc_addr)
{
ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
ElfW(Addr) loadbase;
ElfW(Addr) undo __attribute__ ((unused));

View file

@ -391,7 +391,7 @@ static ElfW(Addr) _dl_preferred_address = 1
ELF_MACHINE_RUNTIME_TRAMPOLINE, which resets the PLT entry to
be one of the above two types. These entries are set up here. */
static inline int
elf_machine_runtime_setup (struct link_map *map, int lazy)
elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
{
if (map->l_info[DT_JMPREL])
{
@ -510,10 +510,10 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
static inline void
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version)
const Elf32_Sym *sym, const struct r_found_version *version,
Elf32_addr *const reloc_addr)
{
const Elf32_Sym *const refsym = sym;
Elf32_Addr *const reloc_addr = (Elf32_Addr *)(map->l_addr + reloc->r_offset);
Elf32_Word loadbase, finaladdr;
const int rinfo = ELF32_R_TYPE (reloc->r_info);

View file

@ -224,7 +224,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *plt;
extern void _dl_runtime_resolve (Elf32_Word);

View file

@ -68,9 +68,9 @@ elf_machine_load_address (void)
static inline void
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version)
const Elf64_Sym *sym, const struct r_found_version *version,
Elf64_Addr *const reloc_addr)
{
Elf64_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
Elf64_Addr loadbase;
#ifndef RTLD_BOOTSTRAP
@ -200,7 +200,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf64_Rela *reloc)
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy)
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf64_Addr *got;
extern void _dl_runtime_resolve (Elf64_Word);

View file

@ -28,6 +28,7 @@
#define __need_NULL
#include <stddef.h>
#include <sys/types.h>
__BEGIN_DECLS
@ -130,25 +131,26 @@ struct msghdr
{
__ptr_t msg_name; /* Address to send to/receive from. */
int msg_namelen; /* Length of address data. */
/* XXX Should be type `size_t' according to POSIX.1g. */
/* XXX Should be type `socklen_t' according to POSIX.1g. */
struct iovec *msg_iov; /* Vector of data to send/receive into. */
size_t msg_iovlen; /* Number of elements in the vector. */
__ptr_t msg_control; /* Ancillary data (eg BSD filedesc passing). */
size_t msg_controllen; /* Ancillary data buffer length. */
socklen_t msg_controllen; /* Ancillary data buffer length. */
int msg_flags; /* Flags on received message. */
};
/* Structure used for storage of ancillary data object information. */
struct cmsghdr
{
size_t cmsg_len; /* Length of data in cmsg_data plus length
socklen_t cmsg_len; /* Length of data in cmsg_data plus length
of cmsghdr structure. */
int cmsg_level; /* Originating protocol. */
int cmsg_type; /* Protocol specific type. */
#if !defined __STRICT_ANSI__ && defined __GNUC__ && __GNUC__ >= 2
unsigned char __cmsg_data[0]; /* Ancillary data. */
/* XXX Perhaps this should be removed. */
#endif
};