mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 05:59:27 +08:00
Compare commits
206
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f70e81bca | ||
|
|
5c5ae36fd8 | ||
|
|
6172aaa35c | ||
|
|
8ab1a68d05 | ||
|
|
4d6acc61fa | ||
|
|
4d5da9a654 | ||
|
|
463e148b75 | ||
|
|
8d6468d0c8 | ||
|
|
6e86a7c21b | ||
|
|
a89d30d444 | ||
|
|
d8c7ef98c1 | ||
|
|
852fc4b91e | ||
|
|
6ba3531662 | ||
|
|
ba79d61b44 | ||
|
|
567c63af19 | ||
|
|
266180eb98 | ||
|
|
564210fe2f | ||
|
|
6d9756c910 | ||
|
|
9dd2fc5d87 | ||
|
|
780b91d932 | ||
|
|
dcfb26a705 | ||
|
|
5481bb895e | ||
|
|
e3ca0de5cb | ||
|
|
9646d93462 | ||
|
|
061c6526bf | ||
|
|
bf668fc8f0 | ||
|
|
6f3e22dc48 | ||
|
|
268eb64290 | ||
|
|
9f447fb32c | ||
|
|
bd5fa7727c | ||
|
|
500590c767 | ||
|
|
64a921419d | ||
|
|
1c2f546be8 | ||
|
|
1be6ec3033 | ||
|
|
c035afc960 | ||
|
|
4d02a5b18a | ||
|
|
e60062b769 | ||
|
|
3ed8c0596e | ||
|
|
02eec64431 | ||
|
|
e550852065 | ||
|
|
92f3773b4c | ||
|
|
8f30ca23f7 | ||
|
|
f127cd28b5 | ||
|
|
dfe1754a55 | ||
|
|
92702b9197 | ||
|
|
63b129ed59 | ||
|
|
c2bf8a5a23 | ||
|
|
b13aa0b866 | ||
|
|
df7c0d2312 | ||
|
|
aa592a63f9 | ||
|
|
198046e105 | ||
|
|
caa9e37aab | ||
|
|
1c384dcd5f | ||
|
|
58e071515a | ||
|
|
ee188d555b | ||
|
|
f68b86cc7b | ||
|
|
14d898aef6 | ||
|
|
a2b934be25 | ||
|
|
55f3aaff8c | ||
|
|
fa00327fbf | ||
|
|
bf18dbd7fa | ||
|
|
efec1d0c47 | ||
|
|
b25ae9c6a4 | ||
|
|
5f2eab4263 | ||
|
|
20328c3962 | ||
|
|
9f195df2d7 | ||
|
|
ec737e4210 | ||
|
|
b687dfbdca | ||
|
|
710f7bab59 | ||
|
|
6c03c2cf27 | ||
|
|
9004bc202e | ||
|
|
847242451c | ||
|
|
76060ec0b8 | ||
|
|
c3352e6233 | ||
|
|
8d6108c3db | ||
|
|
7f8b77039d | ||
|
|
d545ee47a2 | ||
|
|
77aae36646 | ||
|
|
d06b536dc1 | ||
|
|
0200214b28 | ||
|
|
215dbbb150 | ||
|
|
13a0be8823 | ||
|
|
2a4dcf76ca | ||
|
|
807912915b | ||
|
|
d36e769230 | ||
|
|
4e395306e8 | ||
|
|
5f160cde27 | ||
|
|
e463fcfba1 | ||
|
|
71a40c7471 | ||
|
|
59dd864187 | ||
|
|
27a110706b | ||
|
|
5790c439f9 | ||
|
|
41f27456ac | ||
|
|
613a76ff52 | ||
|
|
510ca033d6 | ||
|
|
fa0bc87c32 | ||
|
|
e685238c90 | ||
|
|
fe4d0ab794 | ||
|
|
d55dc14f28 | ||
|
|
12fb2990d4 | ||
|
|
a0777f5163 | ||
|
|
de3bf9b1a5 | ||
|
|
0efef8fcee | ||
|
|
0b0fc9d3a0 | ||
|
|
f202bbb213 | ||
|
|
395565f0c8 | ||
|
|
a8fd3594fb | ||
|
|
0405b04dde | ||
|
|
dc9972317e | ||
|
|
b8fe19fa80 | ||
|
|
1b82a4a8ca | ||
|
|
ee263689e0 | ||
|
|
20c811896c | ||
|
|
46d9215f3b | ||
|
|
0adc881c60 | ||
|
|
f8adc70c3f | ||
|
|
64166d9834 | ||
|
|
7cdef09812 | ||
|
|
c4cc693de7 | ||
|
|
8ab41b4bab | ||
|
|
1796d83f0f | ||
|
|
70c7151893 | ||
|
|
dfc34677ea | ||
|
|
7f0d69dbf4 | ||
|
|
01dbca86d1 | ||
|
|
a13dab1c0f | ||
|
|
a5b7bf0e62 | ||
|
|
95a108f0ba | ||
|
|
9fb16eeae8 | ||
|
|
45086082a0 | ||
|
|
d929664ab5 | ||
|
|
7da3079b42 | ||
|
|
0f90ef9650 | ||
|
|
aa1075ea2f | ||
|
|
d617ac4ee5 | ||
|
|
f8cac037ee | ||
|
|
7cfb2d8be3 | ||
|
|
9635799df3 | ||
|
|
6e85aaf798 | ||
|
|
4d4b48753c | ||
|
|
a7d25a1157 | ||
|
|
4392fd309a | ||
|
|
e91ce32f3c | ||
|
|
349e97bda6 | ||
|
|
7cf6f3e0e8 | ||
|
|
b5cc7a65af | ||
|
|
f55814ff6c | ||
|
|
c28fb3c893 | ||
|
|
05d4c98219 | ||
|
|
3e2632b62d | ||
|
|
8942a07afc | ||
|
|
5570726557 | ||
|
|
782e865067 | ||
|
|
03d0a7e2aa | ||
|
|
7c713e287e | ||
|
|
f0523145cc | ||
|
|
c17097f152 | ||
|
|
ce4d8b661a | ||
|
|
0e3426bbcf | ||
|
|
b928942eaa | ||
|
|
fc38dc5be9 | ||
|
|
ad41463d4e | ||
|
|
93a470c71a | ||
|
|
4ddc1f9dd6 | ||
|
|
28ca945828 | ||
|
|
cee8df033b | ||
|
|
3d46e1cd0a | ||
|
|
339841f985 | ||
|
|
db2286f6d9 | ||
|
|
8f0c527e13 | ||
|
|
7a12c6bba7 | ||
|
|
9e72046871 | ||
|
|
8962ae8d6b | ||
|
|
f5936b69da | ||
|
|
75cd5204dd | ||
|
|
5bd4495594 | ||
|
|
d3dc731b47 | ||
|
|
06f82985cb | ||
|
|
c508104668 | ||
|
|
392d7920cd | ||
|
|
7b3547eb0f | ||
|
|
b1794a285f | ||
|
|
b2c8be1fdf | ||
|
|
8555e89e37 | ||
|
|
072d114510 | ||
|
|
8ec2f30995 | ||
|
|
7f77e07b00 | ||
|
|
66aeca9cfb | ||
|
|
80bcb41041 | ||
|
|
e0637da1c7 | ||
|
|
9a8c0d4f41 | ||
|
|
b0d20a87b5 | ||
|
|
a641835acd | ||
|
|
f24f4dc82d | ||
|
|
147e600987 | ||
|
|
e2a501ab7c | ||
|
|
574ce5e4e4 | ||
|
|
b84095feb4 | ||
|
|
a1a5fa67c6 | ||
|
|
2e6878f7b1 | ||
|
|
3125073e10 | ||
|
|
d70576891e | ||
|
|
786db2208e | ||
|
|
aa0e1b599c | ||
|
|
2e516341fa | ||
|
|
299a95b9f0 |
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
Frequently Asked Question on GNU C Library
|
||||
|
||||
As every FAQ this one also tries to answer questions the user might have
|
||||
when using the pacakge. Please make sure you read this before sending
|
||||
questions or bug reports to the maintainers.
|
||||
|
||||
The GNU C Library is very complex. The building process exploits the
|
||||
features available in tools generally available. But many things can
|
||||
only be done using GNU tools. Also the code is sometimes hard to
|
||||
understand because it has to be portable but on the other hand must be
|
||||
fast. But you need not understand the details to use GNU C Library.
|
||||
This will only be necessary if you intend to contribute or change it.
|
||||
|
||||
If you have any questions you think should be answered in this document,
|
||||
please let me know.
|
||||
|
||||
--drepper@cygnus.com
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q1] ``What systems does the GNU C Library run on?''
|
||||
|
||||
[Q2] ``What compiler do I need to build GNU libc?''
|
||||
|
||||
[Q3] ``When starting make I get only error messages.
|
||||
What's wrong?''
|
||||
|
||||
[Q4] ``After I changed configure.in I get `Autoconf version X.Y.
|
||||
or higher is required for this script'. What can I do?''
|
||||
|
||||
[Q5] ``Do I need a special linker or archiver?''
|
||||
|
||||
[Q6] ``Do I need some more things to compile GNU C Library?''
|
||||
|
||||
[Q7] ``When I run `nm libc.so|grep " U "' on the produced library
|
||||
I still find unresolved symbols? Can this be ok?''
|
||||
|
||||
[Q8] ``I expect GNU libc to be 100% source code compatible with
|
||||
the old Linux based GNU libc. Why isn't it like this?''
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q1] ``What systems does the GNU C Library run on?''
|
||||
|
||||
[A1] {UD} This is difficult to answer. The file `README' lists the
|
||||
architectures GNU libc is known to run *at some time*. This does not
|
||||
mean that it still can be compiled and run on them in the moment.
|
||||
|
||||
The systems glibc is known to work on in the moment and most probably
|
||||
in the future are:
|
||||
|
||||
*-*-gnu GNU Hurd
|
||||
i[3456]86-*-linux Linux-2.0 on Intel
|
||||
|
||||
Other Linux platforms are also on the way to be supported but I need
|
||||
some success reports first.
|
||||
|
||||
If you have a system not listed above (or in the `README' file) and
|
||||
you are really interested in porting it, contact
|
||||
|
||||
<bug-glibc@prep.ai.mit.edu>
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q2] ``What compiler do I need to build GNU libc?''
|
||||
|
||||
[A2] {UD} It is (almost) impossible to compile GNU C Library using a
|
||||
different compiler than GNU CC. A lot of extensions of GNU CC are
|
||||
used to increase the portability and speed.
|
||||
|
||||
But this does not mean you have to use GNU CC for using the GNU C
|
||||
Library. In fact you should be able to use the native C compiler
|
||||
because the success only depends on the binutils: the linker and
|
||||
archiver.
|
||||
|
||||
The GNU CC is found like all other GNU packages on
|
||||
ftp://prep.ai.mit.edu/pub/gnu
|
||||
or better one of the many mirrors.
|
||||
|
||||
You always should try to use the latest official release. Older
|
||||
versions might not have all the features GNU libc could use.
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q3] ``When starting make I get only errors messages.
|
||||
What's wrong?''
|
||||
|
||||
[A3] {UD} You definitely need GNU make to translate GNU libc. No
|
||||
other make program has the needed functionality.
|
||||
|
||||
Versions before 3.74 have bugs which prevent correct execution so you
|
||||
should upgrade to the latest version before starting the compilation.
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q4] ``After I changed configure.in I get `Autoconf version X.Y.
|
||||
or higher is required for this script'. What can I do?''
|
||||
|
||||
[A4] {UD} You have to get the specified autoconf version (or a later)
|
||||
from your favourite mirror of prep.ai.mit.edu.
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q5] ``Do I need a special linker or archiver?''
|
||||
|
||||
[A5] {UD} If your native versions are not too buggy you can probably
|
||||
work with them. But GNU libc works best with GNU binutils.
|
||||
|
||||
On systems where the native linker does not support weak symbols you
|
||||
will not get a really ISO C compliant C library. Generally speaking
|
||||
you should use the GNU binutils if they provide at least the same
|
||||
functionality as your system's tools.
|
||||
|
||||
Always get the newest release of GNU binutils available.
|
||||
Older releases are known to have bugs that affect building the GNU C library.
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q6] ``Do I need some more things to compile GNU C Library?''
|
||||
|
||||
[A6] {UD} Yes, there are some more :-).
|
||||
|
||||
* lots of diskspace (for i386-linux this means, e.g., ~70MB).
|
||||
|
||||
You should avoid compiling on a NFS mounted device. This is very
|
||||
slow.
|
||||
|
||||
* plenty of time (approx 1h for i386-linux on i586@133 or 2.5h or
|
||||
i486@66).
|
||||
|
||||
If you are interested in some more measurements let me know.
|
||||
|
||||
* Some files depend on special tools. E.g., files ending in .gperf
|
||||
need a `gperf' program. The GNU version (part of libg++) is known
|
||||
to work while some vendor versions do not.
|
||||
|
||||
* When compiling for Linux:
|
||||
|
||||
+ the header files of the Linux kernel must be available in the
|
||||
search path of the CPP as <linux/*.h> and <asm/*.h>.
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q7] ``When I run `nm libc.so|grep " U "' on the produced library
|
||||
I still find unresolved symbols? Can this be ok?''
|
||||
|
||||
[A7] {UD} Yes, this is ok. There can be several kinds of unresolved
|
||||
symbols:
|
||||
|
||||
* magic symbols automatically generated by the linker. Names are
|
||||
often like __start_* and __stop_*
|
||||
|
||||
* symbols resolved by using libgcc.a
|
||||
(__udivdi3, __umoddi3, or similar)
|
||||
|
||||
* weak symbols, which need not be resolved at all
|
||||
(currently fabs among others; this gets resolved if the program
|
||||
is linked against libm, too.)
|
||||
|
||||
Generally, you should make sure you find a real program which produces
|
||||
errors while linking before deciding there is a problem.
|
||||
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
[Q8] ``I expect GNU libc to be 100% source code compatible with
|
||||
the old Linux based GNU libc. Why isn't it like this?''
|
||||
|
||||
[A8] {DMT} Not every extension in Linux libc's history was well
|
||||
thought-out. In fact it had a lot of problems with standards compliance
|
||||
and with cleanliness. With the introduction of a new version number these
|
||||
errors now can be corrected. Here is a list of the known source code
|
||||
incompatibilities:
|
||||
|
||||
* _GNU_SOURCE: glibc does not automatically define _GNU_SOURCE. Thus,
|
||||
if a program depends on GNU extensions or some other non-standard
|
||||
functionality, it is necessary to compile it with C compiler option
|
||||
-D_GNU_SOURCE, or better, to put `#define _GNU_SOURCE' at the beginning
|
||||
of your source files, before any C library header files are included.
|
||||
This difference normally manifests itself in the form of missing
|
||||
prototypes and/or data type definitions. Thus, if you get such errors,
|
||||
the first thing you should do is try defining _GNU_SOURCE and see if
|
||||
that makes the problem go away.
|
||||
|
||||
For more information consult the file `NOTES' part of the GNU C
|
||||
library sources.
|
||||
|
||||
* reboot(): GNU libc sanitizes the interface of reboot() to be more
|
||||
compatible with the interface used on other OSes. In particular,
|
||||
reboot() as implemented in glibc takes just one argument. This argument
|
||||
corresponds to the third argument of the Linux reboot system call.
|
||||
That is, a call of the form reboot(a, b, c) needs to be changed into
|
||||
reboot(c).
|
||||
|
||||
* errno: If a program uses variable "errno", then it _must_ include header
|
||||
file <errno.h>. The old libc often (erroneously) declared this variable
|
||||
implicitly as a side-effect of including other libc header files. glibc
|
||||
is careful to avoid such namespace pollution, which, in turn, means that
|
||||
you really need to include the header files that you depend on. This
|
||||
difference normally manifests itself in the form of the compiler
|
||||
complaining about the references of the undeclared symbol "errno".
|
||||
|
||||
* Linux-specific syscalls: All Linux system calls now have appropriate
|
||||
library wrappers and corresponding declarations in various header files.
|
||||
This is because the syscall() macro that was traditionally used to
|
||||
work around missing syscall wrappers are inherently non-portable and
|
||||
error-prone. The following tables lists all the new syscall stubs,
|
||||
the header-file declaring their interface and the system call name.
|
||||
|
||||
syscall name: wrapper name: declaring header file:
|
||||
------------- ------------- ----------------------
|
||||
bdflush bdflush <sys/kdaemon.h>
|
||||
create_module create_module <sys/module.h>
|
||||
delete_module delete_module <sys/module.h>
|
||||
get_kernel_syms get_kernel_syms <sys/module.h>
|
||||
init_module init_module <sys/module.h>
|
||||
syslog ksyslog_ctl <sys/klog.h>
|
||||
|
||||
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||
|
||||
|
||||
Answers were given by:
|
||||
{UD} Ulrich Drepper, <drepper@cygnus.com>
|
||||
{DMT} David Mosberger-Tang, <davidm@AZStarNet.com>
|
||||
|
||||
Amended by:
|
||||
{RM} Roland McGrath, <roland@gnu.ai.mit.edu>
|
||||
|
||||
Local Variables:
|
||||
mode:text
|
||||
End:
|
||||
@@ -31,12 +31,16 @@ foo:=$(shell echo 'foobar=$(filter %.c %.S %.s %.h,$(distribute))'>&2)
|
||||
|
||||
ifndef sysdep_dirs
|
||||
# Find all sysdep directories.
|
||||
export sysdep_dirs := $(shell find $(..)sysdeps -type d ! -name RCS -print)
|
||||
export sysdep_dirs := $(shell find $(..)sysdeps -type d \
|
||||
! -name CVS ! -name RCS -print)
|
||||
else
|
||||
# Defined by the parent.
|
||||
sysdep_dirs := $(addprefix $(..),$(sysdep_dirs))
|
||||
endif
|
||||
|
||||
# Make sure both stdio and libio get in, whichever is in use.
|
||||
subdirs += stdio libio
|
||||
|
||||
sysdep-Subdir-files := $(wildcard $(addsuffix /Subdirs,$(sysdep_dirs)))
|
||||
ifdef sysdep-Subdir-files
|
||||
subdirs := $(sort $(subdirs) \
|
||||
@@ -48,7 +52,7 @@ endif
|
||||
# where source files might be found.
|
||||
|
||||
ifdef subdir
|
||||
all-headers = $(headers)
|
||||
all-headers = $(filter-out $(sysdep_headers),$(headers))
|
||||
else
|
||||
+distinfo := $(shell MAKEFLAGS= MFLAGS= $(MAKE) -s no_deps=t \
|
||||
inhibit_interface_rules=t inhibit_mach_syscalls=t \
|
||||
@@ -62,19 +66,30 @@ all-headers := $(sort $(headers) $(wildcard $(all-headers)))
|
||||
endif
|
||||
foo:=$(shell echo 'IS THIS WORKING??? all-headers=$(all-headers)' >&2)
|
||||
|
||||
sources += $(addsuffix .c,$(elided-routines) \
|
||||
$(foreach l,$(extra-libs),$($l-routines)))
|
||||
|
||||
# Find all sysdep sources and headers.
|
||||
+maybe-sysdeps := $(sources) $(sources:.c=.s) $(sources:.c=.S) $(all-headers) \
|
||||
$(filter %.c %.S %.s %.h %.sub,$(distribute))
|
||||
foo:=$(shell echo '+maybe-sysdeps=$(+maybe-sysdeps)'>&2)
|
||||
# Find all the files that have a stub or generic version.
|
||||
try-sysdeps := $(foreach dir,$(..)sysdeps/stub $(..)sysdeps/generic,\
|
||||
try-sysdeps := $(foreach dir,$(..)sysdeps/stub $(..)sysdeps/generic \
|
||||
$(..)sysdeps/libm-ieee754,\
|
||||
$(addprefix $(dir)/,$(+maybe-sysdeps)))
|
||||
foo:=$(shell echo 'try-sysdeps=$(try-sysdeps)'>&2)
|
||||
+sysdeps := $(wildcard $(try-sysdeps))
|
||||
foo:=$(shell echo 'stub/generic +sysdeps=$(+sysdeps)'>&2)
|
||||
+sysdep-names := $(sort $(notdir $(+sysdeps)))
|
||||
+sysdep-names := $(sort $(patsubst $(..)sysdeps/generic/%,%,\
|
||||
$(patsubst $(..)sysdeps/stub/%,%,\
|
||||
$(patsubst $(..)sysdeps/libm-ieee754/%,%,\
|
||||
$(+sysdeps)))))
|
||||
foo:=$(shell echo '+sysdep-names=$(+sysdep-names)' >&2)
|
||||
|
||||
ifdef subdir-dirs
|
||||
vpath % $(subdir-dirs)
|
||||
endif
|
||||
|
||||
# Now find all the sysdep versions of those files.
|
||||
+sysdeps := $(wildcard $(foreach dir,$(sysdep_dirs) $(source_dirs),\
|
||||
$(addprefix $(dir)/, \
|
||||
@@ -105,11 +120,7 @@ foo:=$(shell echo '+tsrcs=$(+tsrcs)'>&2)
|
||||
foo:=$(shell echo foobie, dammit! >&2)
|
||||
|
||||
ifndef tardir
|
||||
rel+vers := $(shell sed -n -e 's/^.*RELEASE.*\"\([^"]*\)";$$/\1/p' \
|
||||
-e 's/^.*VERSION.*\"\([^"]*\)";$$/\1/p' \
|
||||
< $(..)version.h)
|
||||
release := $(word 1,$(rel+vers))
|
||||
version := $(word 2,$(rel+vers))
|
||||
-include $(common-objpfx)version.mk
|
||||
export tardir := glibc-$(version)
|
||||
endif
|
||||
|
||||
@@ -131,7 +142,6 @@ foo:=$(shell echo subdir foo >&2)
|
||||
$(wildcard $(addsuffix .input,$(tests)) \
|
||||
$(addsuffix .args,$(tests)))
|
||||
+tardeps := $(strip $(+tsrcs))
|
||||
+tsrcs := $(addprefix $(tardir)/$(subdir)/,$(+tardeps))
|
||||
|
||||
verbose = v
|
||||
|
||||
@@ -139,7 +149,8 @@ verbose = v
|
||||
dist: $(..)$(tardir) $(+tardeps)
|
||||
@cd ..; if test -f dist.tar; then c=u; else c=c; fi; \
|
||||
$(+cmdecho) "cd ..; tar $${c}h$(verbose)f dist.tar ..."; \
|
||||
tar $${c}h$(verbose)f dist.tar $(+tsrcs)
|
||||
tar $${c}h$(verbose)f dist.tar \
|
||||
$(addprefix $(tardir)/$(subdir)/,$(filter-out $<,$^))
|
||||
|
||||
else # Parent makefile.
|
||||
|
||||
@@ -157,7 +168,7 @@ foo:=$(shell echo '+sysdep-dist=$(+sysdep-dist)' >&2)
|
||||
|
||||
subdirs := $(filter-out crypt,$(subdirs))
|
||||
|
||||
+sysdep-tsrcs := $(wildcard $(foreach file,Makefile Implies \
|
||||
+sysdep-tsrcs := $(wildcard $(foreach file,Makefile Implies syscalls.list\
|
||||
configure configure.in,\
|
||||
$(addsuffix /$(file),$(sysdep_dirs)))) \
|
||||
$(+sysdep-dist)
|
||||
@@ -187,7 +198,8 @@ dist.tar: $(tardir) $(+tsrcs)
|
||||
tar chvf $@ $(addprefix $(tardir)/,$(filter-out $(tardir),$^))
|
||||
|
||||
$(tardir).tar: dist.tar subdir_dist
|
||||
tar xfv $< -C /tmp | doschk
|
||||
@echo Files listed here have names exceeding 14 chars.
|
||||
tar xfv $< -C /tmp | sed -n '/[^/]\{15,\}/p'
|
||||
tar covf $@ -C /tmp $(tardir)
|
||||
-rm -fr /tmp/$(tardir) &
|
||||
|
||||
@@ -210,7 +222,7 @@ README: README.template version.c
|
||||
sed -e 's/RELEASE/$(release)/' -e 's/VERSION/$(version)/' < $< > $@
|
||||
# Make it unwritable so I won't change it by mistake.
|
||||
chmod 444 $@
|
||||
test ! -d CVS || commit -m'Remade for $(release)-$(version)' $@
|
||||
test ! -d CVS || cvs commit -m'Remade for $(release)-$(version)' $@
|
||||
|
||||
|
||||
endif # Subdirectory vs. parent makefile
|
||||
|
||||
@@ -77,10 +77,12 @@ sources += $(filter %.c %.s %.S,$(all-dist))
|
||||
headers += $(filter %.h,$(all-dist))
|
||||
all-dist := $(filter-out %.h %.c %.s %.S,$(all-dist))
|
||||
|
||||
sources += $(foreach lib,$(extra-libs),$($(lib)-routines:=.c))
|
||||
|
||||
# All different versions of $(sources), preserving the configured sysdep
|
||||
# directory order.
|
||||
all-sources = $(wildcard $(sort $(sources) $(sources:.c=.S) \
|
||||
$(sources:.c=.s))) \
|
||||
all-sources = $(wildcard $(sort $(sources) $(sources:.c=.S) $(sources:.c=.s) \
|
||||
$(others:=.c) $(tests:=.c))) \
|
||||
$(foreach dir,$(all-dirs),\
|
||||
$(wildcard \
|
||||
$(addprefix $(dir)/,\
|
||||
@@ -143,7 +145,7 @@ else
|
||||
endif
|
||||
|
||||
$P/siglist.pot: $(common-objpfx)siglist.c; $(extract)
|
||||
$P/errlist.pot: $(..)sysdeps/mach/hurd/errlist.c; $(extract)
|
||||
$P/errlist.pot: $(..)sysdeps/gnu/errlist.c; $(extract)
|
||||
|
||||
# Extract all strings from these files; their strings are not marked.
|
||||
# Their surroundings are also not interesting.
|
||||
@@ -162,10 +164,15 @@ $P/subdirs.pot: $(subdirs:%=$P/%.pot)
|
||||
do sed "s%^#: %&$$d/%" $P/$$d.pot; done) > $@.new
|
||||
mv -f $@.new $@
|
||||
|
||||
# Get $(version) defined.
|
||||
include $(common-objpfx)version.mk
|
||||
|
||||
# Combine all the messages into the final sorted template translation file.
|
||||
$P/SYS_libc.pot: $(all-pot)
|
||||
@rm -f $@.new
|
||||
$(XGETTEXT) -d - -n -s --omit-header $^ > $@.new
|
||||
sed -e 's/VERSION/$(version)/' -e "s/DATE/`date +'%Y-%m-%d %k:%M'`/" \
|
||||
po/header.pot > $@.new
|
||||
$(XGETTEXT) -d - -n -s --omit-header $^ >> $@.new
|
||||
mv -f $@.new $@
|
||||
test ! -d CVS || cvs ci -m'Regenerated from source files' $@
|
||||
|
||||
|
||||
+39
-6
@@ -86,8 +86,17 @@ include $(common-objpfx)config.make
|
||||
$(common-objpfx)config.make: $(common-objpfx)config.status $(..)config.h.in
|
||||
cd $(<D); $(SHELL) $(<F)
|
||||
|
||||
# Find all the sysdeps configure fragments, to make sure we re-run
|
||||
# configure when any of them changes.
|
||||
sysdep-configures = \
|
||||
$(foreach dir,$(config-sysdirs),\
|
||||
$(patsubst %.in,%,\
|
||||
$(firstword $(wildcard \
|
||||
$(sysdep_dir)/$(dir)/configure \
|
||||
$(sysdep_dir)/$(dir)/configure.in))))
|
||||
|
||||
# Force the user to configure before making.
|
||||
$(common-objpfx)config.status: $(..)configure
|
||||
$(common-objpfx)config.status: $(..)configure $(sysdep-configures)
|
||||
@cd $(@D); if test -f $(@F); then exec $(SHELL) $(@F) --recheck; else \
|
||||
echo The GNU C library has not been configured. >&2; \
|
||||
echo Run \`configure\' to configure it before building. >&2; \
|
||||
@@ -213,6 +222,16 @@ ifndef localtime-file
|
||||
localtime-file = $(sysconfdir)/localtime
|
||||
endif
|
||||
|
||||
# What to use for leap second specifications in compiling the default
|
||||
# timezone files. Set this to `/dev/null' for no leap second handling as
|
||||
# 1003.1 requires, or to `leapseconds' for proper leap second handling.
|
||||
# Both zone flavors are always available as `posix/ZONE' and `right/ZONE'.
|
||||
# This variable determines the default: if it's `/dev/null',
|
||||
# ZONE==posix/ZONE; if it's `leapseconds', ZONE==right/ZONE.
|
||||
ifndef leapseconds
|
||||
leapseconds = /dev/null
|
||||
endif
|
||||
|
||||
# What timezone's DST rules should be used when a POSIX-style TZ
|
||||
# environment variable doesn't specify any rules. For 1003.1 compliance
|
||||
# this timezone must use rules that are as U.S. federal law defines DST.
|
||||
@@ -291,8 +310,13 @@ endif
|
||||
endif
|
||||
ifndef link-libc
|
||||
ifeq (yes,$(build-shared))
|
||||
link-libc = -Wl,-rpath-link=$(common-objdir) \
|
||||
$(common-objpfx)libc.so$(libc.so-version) $(gnulib)
|
||||
# We need the versioned name of libc.so in the deps of $(others) et al
|
||||
# so that the symlink to libc.so is created before anything tries to
|
||||
# run the linked programs.
|
||||
link-libc = -Wl,-rpath-link=$(rpath-link) \
|
||||
$(common-objpfx)libc.so$(libc.so-version) \
|
||||
$(elfobjdir)/$(rtld-installed-name) \
|
||||
$(common-objpfx)libc.a $(gnulib)
|
||||
# Choose the default search path for the dynamic linker based on
|
||||
# where we will install libraries.
|
||||
ifneq ($(libdir),$(slibdir))
|
||||
@@ -300,6 +324,8 @@ default-rpath = $(slibdir):$(libdir)
|
||||
else
|
||||
default-rpath = $(libdir)
|
||||
endif
|
||||
# This is how to find at build-time things that will be installed there.
|
||||
rpath-link = $(common-objdir):$(elfobjdir)
|
||||
else
|
||||
link-libc = $(common-objpfx)libc.a $(gnulib) $(common-objpfx)libc.a
|
||||
endif
|
||||
@@ -333,9 +359,9 @@ built-program-cmd = $(built-program-file)
|
||||
else
|
||||
comma = ,
|
||||
define built-program-cmd
|
||||
LD_LIBRARY_PATH=$(common-objdir)$(patsubst -Wl$(comma)-rpath-link=%,:%,\
|
||||
$(filter -Wl$(comma)-rpath-link=%,\
|
||||
$(sysdep-LDFLAGS))) \
|
||||
LD_LIBRARY_PATH=$(rpath-link)$(patsubst -Wl$(comma)-rpath-link=%,:%,\
|
||||
$(filter -Wl$(comma)-rpath-link=%,\
|
||||
$(sysdep-LDFLAGS))) \
|
||||
$(elf-objpfx)ld.so $(built-program-file)
|
||||
endef
|
||||
endif
|
||||
@@ -468,6 +494,13 @@ cross-compiling := yes
|
||||
else
|
||||
cross-compiling := no
|
||||
endif
|
||||
|
||||
# Figure out the version numbers from version.h.
|
||||
|
||||
$(common-objpfx)version.mk: $(..)version.h $(..)Makeconfig
|
||||
sed -n -e 's/^.*RELEASE.*"\([^"]*\)".*$$/release=\1/p' \
|
||||
-e 's/^.*VERSION.*"\([^"]*\)".*$$/version=\1/p' \
|
||||
< $< > $@-new
|
||||
mv -f $@-new $@
|
||||
|
||||
endif # Makeconfig not yet included
|
||||
|
||||
@@ -51,10 +51,10 @@ sysdep-subdirs := $(subst $(\n), ,$(sysdep-subdirs))
|
||||
endif
|
||||
|
||||
# These are the subdirectories containing the library source.
|
||||
subdirs = csu assert ctype db locale intl math setjmp signal stdlib \
|
||||
subdirs = csu assert ctype db locale intl catgets math setjmp signal stdlib \
|
||||
stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd\
|
||||
posix io termios resource misc socket sysvipc gmon gnulib \
|
||||
wctype $(wildcard crypt) manual $(sysdep-subdirs) elf
|
||||
posix io termios resource misc login socket sysvipc gmon gnulib \
|
||||
wctype $(wildcard crypt) manual $(sysdep-subdirs) elf po
|
||||
export subdirs := $(subdirs) # Benign, useless in GNU make before 3.63.
|
||||
|
||||
# The mach and hurd subdirectories have many generated header files which
|
||||
@@ -144,7 +144,9 @@ $(includedir)/stubs.h: subdir_install
|
||||
echo ' in the C library which is a stub, meaning it will fail';\
|
||||
echo ' every time called, usually setting errno to ENOSYS. */';\
|
||||
sort $(subdir-stubs)) > $(objpfx)stubs.h
|
||||
$(INSTALL_DATA) $(objpfx)stubs.h $@
|
||||
if test -r $@ && cmp -s $(objpfx)stubs.h $@; \
|
||||
then echo stubs.h unchanged ; \
|
||||
else $(INSTALL_DATA) $(objpfx)stubs.h $@; fi
|
||||
rm -f $(objpfx)stubs.h
|
||||
|
||||
# This makes the Info or DVI file of the documentation from the Texinfo source.
|
||||
@@ -220,14 +222,15 @@ parent_echo-distinfo:
|
||||
|
||||
# Make the distribution tarfile.
|
||||
|
||||
distribute := README INSTALL NOTES COPYING.LIB COPYING NEWS \
|
||||
ChangeLog ChangeLog.[0-9] \
|
||||
distribute := README INSTALL FAQ NOTES NEWS PROJECTS \
|
||||
COPYING.LIB COPYING ChangeLog ChangeLog.[0-9] \
|
||||
Makefile Makeconfig Makerules Rules Make-dist MakeTAGS \
|
||||
extra-lib.mk o-iterator.mk \
|
||||
ansidecl.h mkinstalldirs move-if-change install-sh \
|
||||
configure configure.in aclocal.m4 config.sub config.guess\
|
||||
config.make.in config-name.in Makefile.in \
|
||||
munch-tmpl.c munch.awk sysdep.h set-hooks.h libc-symbols.h
|
||||
config.h.in config.make.in config-name.in Makefile.in \
|
||||
munch-tmpl.c munch.awk \
|
||||
sysdep.h set-hooks.h libc-symbols.h version.h shlib-versions
|
||||
|
||||
distribute := $(strip $(distribute))
|
||||
generated := $(generated) stubs.h
|
||||
|
||||
@@ -36,8 +36,6 @@ ifneq "$(findstring env,$(origin sources))" ""
|
||||
sources :=
|
||||
endif
|
||||
|
||||
headers := $(headers) $(sysdep_headers)
|
||||
|
||||
oPATH := $(PATH)
|
||||
PATH := this definition should take precedence over $(oPATH)
|
||||
ifeq ($(PATH),$(oPATH))
|
||||
@@ -281,9 +279,11 @@ $(sed-remove-objpfx) > $(@:.d=.T)
|
||||
mv -f $(@:.d=.T) $@
|
||||
endef
|
||||
ifneq (,$(objpfx))
|
||||
sed-remove-objpfx = -e 's@ $(subst .,\., \
|
||||
$(subst @,\@,$(objpfx)))@ $$(objpfx)@g' \
|
||||
-e 's@^$(subst .,\.,$(subst @,\@,$(objpfx)))@$$(objpfx)@g'
|
||||
# Continuation lines here are dangerous because they introduce spaces!
|
||||
define sed-remove-objpfx
|
||||
-e 's@ $(subst .,\.,$(subst @,\@,$(objpfx)))@ $$(objpfx)@g' \
|
||||
-e 's@^$(subst .,\.,$(subst @,\@,$(objpfx)))@$$(objpfx)@g'
|
||||
endef
|
||||
endif
|
||||
|
||||
# Figure out the source filenames in this directory.
|
||||
@@ -293,6 +293,8 @@ override sources := $(addsuffix .c,$(filter-out $(elided-routines),\
|
||||
$(sysdep_routines)))
|
||||
sysdep_routines := $(sysdep_routines)
|
||||
|
||||
headers := $(headers) $(sysdep_headers)
|
||||
|
||||
# This is the list of all object files, gotten by
|
||||
# replacing every ".c" in `sources' with a ".o".
|
||||
override objects := $(addprefix $(objpfx),$(sources:.c=.o))
|
||||
@@ -302,7 +304,7 @@ override objects := $(addprefix $(objpfx),$(sources:.c=.o))
|
||||
# $(o-iterator-doit) to produce some desired rule using $o for the object
|
||||
# suffix, and setting $(object-suffixes-left) to $(object-suffixes); a copy
|
||||
# is produced for each object suffix in use.
|
||||
o-iterator = $(patsubst %,$(..)o-iterator.mk,$(object-suffixes))
|
||||
o-iterator = $(patsubst %,$(..)o-iterator.mk,$(object-suffixes-left))
|
||||
|
||||
# The makefile may define $(extra-libs) with `libfoo libbar'
|
||||
# to build libfoo.a et al from the modules listed in $(libfoo-routines).
|
||||
@@ -361,9 +363,15 @@ lib: lib-noranlib $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
|
||||
# Pattern rule for libraries: depend on the __.SYMDEF member updated by ranlib.
|
||||
lib%.a: lib%.a($(ar-symtab-name)) ;
|
||||
|
||||
# For object-suffix $o, the list of objects with that suffix.
|
||||
# Makefiles can define `elide-routines.so = foo' to leave foo.so out.
|
||||
o-objects = $(patsubst %.o,%$o,$(filter-out $(patsubst %,$(objpfx)%.o,\
|
||||
$(elide-routines$o)),\
|
||||
$(objects)))
|
||||
|
||||
libobjs: $(foreach o,$(object-suffixes),\
|
||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)(\
|
||||
$(notdir $(objects:.o=$o))))
|
||||
$(notdir $(o-objects))))
|
||||
lib-noranlib: libobjs
|
||||
others: $(addprefix $(objpfx),$(install-lib))
|
||||
|
||||
@@ -372,28 +380,33 @@ ifdef objects
|
||||
# Define a pattern rule that will match many targets libc.a(foo.%), for
|
||||
# each foo.o in $(objects) (% will just happen always to match `o'). This is
|
||||
# the only way to define a rule that updates many targets at once with one
|
||||
# sequence of commands. We in fact define the pattern rule to match
|
||||
# targets libc.a(foo.%), libc_pic.a(foo.%), etc, to avoid repeating the rule.
|
||||
# Each match will only ever be called upon to make member objects of
|
||||
# the appropriate type in each library (i.e. libc_pic.a(foo.so)).
|
||||
$(foreach l,$(libtypes),\
|
||||
$(common-objpfx)$(patsubst %,$l,c)($(notdir $(objects:.o=.%)))): \
|
||||
# sequence of commands.
|
||||
define o-iterator-doit
|
||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)(\
|
||||
$(addsuffix .%,$(filter-out $(elide-routines$o),$(notdir $(objects:.o=))))): \
|
||||
$(objpfx)stamp.%-$(subdir) ;
|
||||
endef
|
||||
object-suffixes-left := $(object-suffixes)
|
||||
include $(o-iterator)
|
||||
|
||||
# The pattern rule tells Make to remake $(objpfx)stamp.%-$(subdir) as
|
||||
# the way to update all the foo.% object files in $(objects).
|
||||
# Now we define a static pattern rule to update each
|
||||
# $(objpfx)stamp.SUFFIX-$(subdir) timestamp file;
|
||||
# these rules (one explicit rule is generated for each object suffix)
|
||||
# will update the parent archive with
|
||||
$(foreach o,$(object-suffixes),$(objpfx)stamp$o-$(subdir)): \
|
||||
$(objpfx)stamp%-$(subdir): $(objects:.o=%)
|
||||
$(patsubst %,cd %;,$(objdir)) \
|
||||
$(AR) cru$(verbose) ${O%-lib} \
|
||||
$(patsubst $(objpfx)%,%,$^)
|
||||
# `touch' won't let me touch a world-writable file I don't own. Sigh.
|
||||
rm -f $@
|
||||
touch $@
|
||||
# the way to update all the foo.% object files in $(objects). Now we
|
||||
# define explicit rules to update each $(objpfx)stamp.SUFFIX-$(subdir)
|
||||
# timestamp file; these rules (one explicit rule is generated for each
|
||||
# object suffix) will update the parent archive with ar. Use a static
|
||||
# pattern rule so $* is set to the object type during the commands.
|
||||
define o-iterator-doit
|
||||
$(objpfx)stamp$o-$(subdir): $(objpfx)stamp%-$(subdir): $(o-objects); $$(do-ar)
|
||||
endef
|
||||
object-suffixes-left := $(object-suffixes)
|
||||
include $(o-iterator)
|
||||
define do-ar
|
||||
$(patsubst %,cd %;,$(objdir)) \
|
||||
$(AR) cru$(verbose) ${O%-lib} \
|
||||
$(patsubst $(objpfx)%,%,$^)
|
||||
rm -f $@
|
||||
touch $@
|
||||
endef
|
||||
ifdef subdir
|
||||
O%-lib = $(filter ../,$(firstword $(objdir) ../))$(patsubst %,$(libtype$*),c)
|
||||
else
|
||||
@@ -407,17 +420,22 @@ endif
|
||||
define o-iterator-doit
|
||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)($(ar-symtab-name)): \
|
||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)(\
|
||||
$(patsubst $(objpfx)%.o,%$o,$(objects))) \
|
||||
$(filter subdir_lib,$(firstword $(subdir) subdir_lib)); \
|
||||
$(patsubst $(objpfx)%,%,$(o-objects))) $(subdirs-stamp-o); \
|
||||
$$(RANLIB) $$(common-objpfx)$$(patsubst %,$$(libtype$o),c)
|
||||
endef
|
||||
ifndef subdir
|
||||
subdirs-stamps := $(foreach d,$(subdirs),\
|
||||
$(firstword $(objdir) $(subdir))/stamp%-$d)
|
||||
subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps))
|
||||
$(subdirs-stamps): subdir_lib;
|
||||
endif
|
||||
object-suffixes-left = $(object-suffixes)
|
||||
include $(o-iterator)
|
||||
|
||||
|
||||
# This makes all the object files.
|
||||
.PHONY: objects objs
|
||||
objects objs: $(foreach o,$(object-suffixes),$(objects:.o=$o)) \
|
||||
objects objs: $(foreach o,$(object-suffixes),$(o-objects)) \
|
||||
$(addprefix $(objpfx),$(extra-objs))
|
||||
|
||||
# Canned sequence for building an extra library archive.
|
||||
@@ -428,6 +446,71 @@ $(AR) cru$(verbose) $(@:$(objpfx)%=%) \
|
||||
$(RANLIB) $@
|
||||
endef
|
||||
|
||||
# Shared library building.
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
|
||||
# Process the shlib-versions file, which tells us what shared library
|
||||
# version numbers to use when we install shared objects on this system.
|
||||
-include $(common-objpfx)soversions.mk
|
||||
$(common-objpfx)soversions.mk: $(..)shlib-versions $(..)Makerules \
|
||||
$(common-objpfx)config.make
|
||||
sed 's/#.*$$//' $< | while read conf versions; do \
|
||||
test -n "$$versions" || continue; \
|
||||
case '$(config-machine)-$(config-vendor)-$(config-os)' in $$conf)\
|
||||
for v in $$versions; do \
|
||||
lib="$${v%%=*}"; if eval "test -z \"\$$vers_lib$$lib\""; then \
|
||||
eval vers_lib$${lib}=yes; \
|
||||
echo $$lib.so-version=.$${v##$$lib=}; fi; \
|
||||
done ;; esac; done > $@T
|
||||
mv -f $@T $@
|
||||
|
||||
# Get $(version) defined with the release version number.
|
||||
-include $(common-objpfx)version.mk
|
||||
|
||||
|
||||
# Pattern rule to build a shared object from an archive of PIC objects.
|
||||
# This must come after the installation rules so Make doesn't try to
|
||||
# build shared libraries in place from the installed *_pic.a files.
|
||||
# $(LDLIBS-%.so) may contain -l switches to generate run-time dependencies
|
||||
# on other shared objects.
|
||||
lib%.so: lib%_pic.a; $(build-shlib)
|
||||
|
||||
ifeq ($(have-no-whole-archive),yes)
|
||||
no-whole-archive = -Wl,--no-whole-archive
|
||||
else
|
||||
no-whole-archive =
|
||||
endif
|
||||
|
||||
define build-shlib
|
||||
$(LINK.o) -shared -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS) \
|
||||
-Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \
|
||||
$(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \
|
||||
-Wl,-rpath-link=$(common-objdir) \
|
||||
-Wl,--whole-archive $^ $(no-whole-archive) \
|
||||
$(LDLIBS-$(@F:lib%.so=%).so)
|
||||
endef
|
||||
|
||||
# Don't try to use -lc when making libc.so itself.
|
||||
# Also omits crti.o and crtn.o, which we do not want
|
||||
# since we define our own `.init' section specially.
|
||||
LDFLAGS-c.so = -nostdlib -nostartfiles
|
||||
# Give libc.so an entry point and make it directly runnable itself.
|
||||
LDFLAGS-c.so += -e __libc_main
|
||||
# Use our own special initializer and finalizer files for libc.so.
|
||||
elfobjdir := $(firstword $(objdir) $(patsubst ../$(subdir),.,$(..)elf))
|
||||
$(common-objpfx)libc.so: $(elfobjdir)/soinit.so \
|
||||
$(common-objpfx)libc_pic.a \
|
||||
$(elfobjdir)/sofini.so $(elfobjdir)/ld.so
|
||||
$(build-shlib)
|
||||
|
||||
ifdef libc.so-version
|
||||
$(common-objpfx)libc.so$(libc.so-version): $(common-objpfx)libc.so
|
||||
rm -f $@
|
||||
ln -s $(<F) $@ || ln $< $@
|
||||
endif
|
||||
endif
|
||||
|
||||
# Installation.
|
||||
|
||||
# $(install-lib) are installed from the object directory into $(libdir);
|
||||
@@ -453,7 +536,7 @@ endef
|
||||
# Make the target directory if it doesn't exist, using the `mkinstalldirs'
|
||||
# script that does `mkdir -p' even if `mkdir' doesn't support that flag.
|
||||
define make-target-directory
|
||||
$(addprefix $(..)mkinstalldirs ,\
|
||||
$(addprefix $(..)./mkinstalldirs ,\
|
||||
$(filter-out $(wildcard $(@D:%/=%)),$(@D:%/=%)))
|
||||
endef
|
||||
|
||||
@@ -483,13 +566,84 @@ endef
|
||||
install-lib.so := $(filter %.so,$(install-lib:%_pic.a=%.so))
|
||||
install-lib := $(filter-out %.so %_pic.a,$(install-lib))
|
||||
ifeq (yes,$(build-shared))
|
||||
install-lib-nosubdir: $(foreach so,$(install-lib.so),\
|
||||
$(libdir)/$(patsubst $(libprefix)lib%,lib$(libprefix)%,\
|
||||
$(libprefix)$(so))$($(so)-version))
|
||||
|
||||
install-lib-nosubdir: $(install-lib.so:%=$(libdir)/%)
|
||||
|
||||
# Find which .so's have versions.
|
||||
versioned := $(strip $(foreach so,$(install-lib.so),\
|
||||
$(patsubst %,$(so),$($(so)-version))))
|
||||
|
||||
# Install all the unversioned shared libraries.
|
||||
$(addprefix $(libdir)/,$(filter-out $(versioned),$(install-lib.so))): \
|
||||
$(libdir)/%.so: $(objpfx)%.so; $(do-install-program)
|
||||
|
||||
make-link = cd $(@D); rm -f $(@F); $(LN_S) $(<F) $(@F)
|
||||
|
||||
ifdef libc.so-version
|
||||
# For a library specified to be version N, install three files:
|
||||
# libc.so -> libc.so.N (e.g. libc.so.6)
|
||||
# libc.so.6 -> libc-VERSION.so (e.g. libc-1.10.so)
|
||||
|
||||
$(slibdir)/libc.so$(libc.so-version): $(slibdir)/libc-$(version).so
|
||||
$(make-link)
|
||||
$(slibdir)/libc-$(version).so: $(common-objpfx)libc.so; $(do-install-program)
|
||||
install: $(slibdir)/libc.so$(libc.so-version)
|
||||
$(slibdir)/lib$(libprefix)c.so$(libc.so-version): $(common-objpfx)libc.so
|
||||
$(do-install-so)
|
||||
|
||||
ifndef subdir
|
||||
# What we install as libc.so for programs to link against is in fact an
|
||||
# archive. It contains the various $(static-only-routines) objects, and
|
||||
# the special object libc-syms.so that contains just the dynamic symbol
|
||||
# table of the shared libc object.
|
||||
install: $(libdir)/libc.so
|
||||
$(libdir)/libc.so: $(common-objpfx)libc.so$(libc.so-version) \
|
||||
$(elfobjdir)/$(rtld-installed-name) \
|
||||
$(common-objpfx)libc.a
|
||||
(echo '/* Use the shared library, but some functions are only in';\
|
||||
echo ' the static library, so try that secondarily.'; \
|
||||
echo ' The dynamic linker defines some functions used by $(<F),';\
|
||||
echo ' but ld uses definitions from libc.a before the examining';\
|
||||
echo ' dependencies of $(<F) to find $(rtld-installed-name). */';\
|
||||
echo 'GROUP ( $(^F) )') > $@.new
|
||||
mv -f $@.new $@
|
||||
|
||||
endif
|
||||
|
||||
else
|
||||
install: $(slibdir)/libc.so
|
||||
$(slibdir)/libc.so: $(common-objpfx)libc.so; $(do-install-program)
|
||||
endif
|
||||
|
||||
|
||||
ifneq (,$(versioned))
|
||||
# Produce three sets of rules as above for all the smaller versioned libraries.
|
||||
|
||||
define o-iterator-doit
|
||||
$(libdir)/$o: $(libdir)/$o$($o-version); $$(make-link)
|
||||
endef
|
||||
object-suffixes-left := $(versioned)
|
||||
include $(o-iterator)
|
||||
|
||||
# Make symlinks in the build directory, because the versioned names might
|
||||
# be referenced by a DT_NEEDED in another library.
|
||||
define o-iterator-doit
|
||||
$(objpfx)$o$($o-version): $(objpfx)$o; $$(make-link)
|
||||
endef
|
||||
object-suffixes-left := $(versioned)
|
||||
include $(o-iterator)
|
||||
|
||||
|
||||
define o-iterator-doit
|
||||
$(libdir)/$o$($o-version): $(libdir)/$(o:.so=)-$(version).so; $$(make-link)
|
||||
endef
|
||||
object-suffixes-left := $(versioned)
|
||||
include $(o-iterator)
|
||||
|
||||
define o-iterator-doit
|
||||
$(libdir)/$(o:.so=)-$(version).so: $(objpfx)$o; $$(do-install-program)
|
||||
endef
|
||||
object-suffixes-left := $(versioned)
|
||||
include $(o-iterator)
|
||||
endif
|
||||
|
||||
define do-install-so
|
||||
$(do-install-program)
|
||||
@@ -561,43 +715,6 @@ install-no-libc.a-nosubdir: install-headers-nosubdir install-data-nosubdir\
|
||||
install-others-nosubdir install-sbin-nosubdir
|
||||
install: install-no-libc.a-nosubdir
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
# Pattern rule to build a shared object from an archive of PIC objects.
|
||||
# This must come after the installation rules so Make doesn't try to
|
||||
# build shared libraries in place from the installed *_pic.a files.
|
||||
# $(LDLIBS-%.so) may contain -l switches to generate run-time dependencies
|
||||
# on other shared objects.
|
||||
lib%.so: lib%_pic.a; $(build-shlib)
|
||||
|
||||
define build-shlib
|
||||
$(LINK.o) -shared -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS) \
|
||||
-Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \
|
||||
$(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \
|
||||
-Wl,-rpath-link=$(common-objdir) \
|
||||
-Wl,--whole-archive $^ $(LDLIBS-$(@F:lib%.so=%).so)
|
||||
endef
|
||||
|
||||
# Don't try to use -lc when making libc.so itself.
|
||||
# Also omits crti.o and crtn.o, which we do not want
|
||||
# since we define our own `.init' section specially.
|
||||
LDFLAGS-c.so = -nostdlib -nostartfiles
|
||||
# Give libc.so an entry point and make it directly runnable itself.
|
||||
LDFLAGS-c.so += -e __libc_print_version
|
||||
# Use our own special initializer and finalizer files for libc.so.
|
||||
elfobjdir := $(firstword $(objdir) $(..)elf)
|
||||
$(common-objpfx)libc.so: $(elfobjdir)/soinit.so \
|
||||
$(common-objpfx)libc_pic.a \
|
||||
$(elfobjdir)/sofini.so
|
||||
$(build-shlib)
|
||||
|
||||
ifdef libc.so-version
|
||||
$(common-objpfx)libc.so$(libc.so-version): $(common-objpfx)libc.so
|
||||
rm -f $@
|
||||
ln -s $(<F) $@ || ln $< $@
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
# Command to compile $< in $(objdir) using the native libraries.
|
||||
define native-compile
|
||||
cwd=`pwd`; cd $(@D); $(BUILD_CC) $(BUILD_CFLAGS) \
|
||||
@@ -610,8 +727,12 @@ cd $(@D); $(BUILD_CC) $(BUILD_CFLAGS) $(<:$(common-objpfx)%=%) -o $(@F)
|
||||
endef
|
||||
|
||||
# We always want to use configuration definitions.
|
||||
ifdef objdir
|
||||
# This is always used in $(common-objdir), so we use no directory name.
|
||||
BUILD_CFLAGS = -include config.h
|
||||
else
|
||||
BUILD_CFLAGS = -include $(..)config.h
|
||||
endif
|
||||
|
||||
# Support the GNU standard name for this target.
|
||||
.PHONY: check
|
||||
@@ -647,7 +768,7 @@ common-mostlyclean:
|
||||
$(rmobjs)
|
||||
define rmobjs
|
||||
$(foreach o,$(object-suffixes),
|
||||
-rm -f $(addprefix $(objpfx),stamp$o-$(subdir)) $(objects:.o=$o))
|
||||
-rm -f $(addprefix $(objpfx),stamp$o-$(subdir)) $(o-objects))
|
||||
endef
|
||||
|
||||
# Also remove the dependencies and generated source files.
|
||||
@@ -664,12 +785,12 @@ stubs: $(common-objpfx)stub-$(subdir)
|
||||
s = $(sysdep_dir)/stub
|
||||
$(common-objpfx)stub-$(subdir): $(+depfiles)
|
||||
# Use /dev/null since `...` might expand to empty.
|
||||
s=`cd $s; /bin/pwd`; \
|
||||
$(patsubst %,cd %;,$(objdir)) \
|
||||
sed -n 's/^stub_warning *(\([^)]*\).*$$/#define __stub_\1/p' \
|
||||
`sed -n 's@^.*$s/\([a-z0-9_-]*\.c\).*$$@'"$$s"/'\1@p' \
|
||||
$(patsubst $(objpfx)%,%,$^) /dev/null` \
|
||||
/dev/null > $@T
|
||||
(s=`cd $s; /bin/pwd`; \
|
||||
$(patsubst %,cd %;,$(objdir)) \
|
||||
sed -n 's/^stub_warning *(\([^)]*\).*$$/#define __stub_\1/p' \
|
||||
`sed -n 's@^.*$s/\([a-z0-9_-]*\.c\).*$$@'"$$s"/'\1@p' \
|
||||
$(patsubst $(objpfx)%,%,$^) /dev/null` \
|
||||
/dev/null) > $@T
|
||||
mv -f $@T $@
|
||||
|
||||
# Make the distribution tar file.
|
||||
@@ -692,10 +813,12 @@ distinfo: Makefile $(..)Makerules
|
||||
|
||||
define distinfo-vars
|
||||
rm -f $@.new
|
||||
$(foreach var,subdir subdir-dirs sources elided-routines headers distribute \
|
||||
dont_distribute generated others tests,
|
||||
echo >> $@.new '$(var) := $($(var))')
|
||||
echo >> $@.new 'sources := $$(sources) $$(addsuffix .c,$$(elided-routines))'
|
||||
$(foreach var,subdir subdir-dirs sources elided-routines sysdep_routines \
|
||||
headers sysdep_headers distribute dont_distribute generated \
|
||||
others tests extra-libs $(extra-libs:%=%-routines) \
|
||||
$(addprefix install-,lib data bin sbin others),
|
||||
echo >> $@.new '$(subdir)-$(var) := $($(var))'
|
||||
echo >> $@.new '$(var) = $$($(subdir)-$(var))')
|
||||
endef
|
||||
|
||||
ifneq (,$(strip $(gpl2lgpl)))
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
Open jobs for finishing GNU libc:
|
||||
---------------------------------
|
||||
Status: May 1996
|
||||
|
||||
If you have time and talent to take over any of the jobs below please
|
||||
contact <bug-glibc@prep.ai.mit.edu>
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[ 1] Port to new platforms or test current version on formerly supported
|
||||
platforms.
|
||||
|
||||
|
||||
[ 2] Test compliance with standards. If you have access to recent
|
||||
standards (IEEE, ISO, ANSI, X/Open, ...) and/or test suites you
|
||||
could do some checks as the goal is to be compliant with all
|
||||
standards if they do not contradict each other.
|
||||
|
||||
|
||||
[ 3] Write translations for the GNU libc message for the so far
|
||||
unsupported languages. GNU libc is fully internationalized and
|
||||
users can immediately benefit from this.
|
||||
|
||||
Take a look at the matrix in
|
||||
ftp://prep.ai.mit.edu/pub/gnu/ABOUT-NLS
|
||||
for the current status (of course better use a mirror of prep).
|
||||
|
||||
|
||||
[ 4] Write wordexp() function; this is described in POSIX.2, The
|
||||
header <wordexp.h> already exists.
|
||||
|
||||
Implementation idea: use some functions from bash.
|
||||
|
||||
|
||||
[ 5] Write reentrent versions of crypt() et.al.
|
||||
|
||||
Implementation idea: Define in <crypt.h>
|
||||
|
||||
struct crypt_data
|
||||
{
|
||||
<... all the needed data ...>
|
||||
};
|
||||
|
||||
and define additional functions
|
||||
|
||||
char *crypt_r (__const char *__key, __const char *__salt,
|
||||
struct crypt_data *__data);
|
||||
|
||||
void setkey_r (__const char *__key, struct crypt_data *__data);
|
||||
|
||||
void encrypt_r (char *__block, int __edflag,
|
||||
struct crypt_data *__data);
|
||||
|
||||
If possible the non-reentrent functions should use the reentrent
|
||||
ones.
|
||||
|
||||
Because of the US export restrictions it might be a good idea if
|
||||
some non-american person does this job.
|
||||
|
||||
|
||||
[ 6] Write `long double' versions of the math functions. This should be
|
||||
done in collaboration with the NetBSD and FreeBSD people.
|
||||
|
||||
The libm is in fact fdlibm (not the same as in Linux libc).
|
||||
|
||||
|
||||
[ 7] If you enjoy assembler programming (as I do --drepper :-) you might
|
||||
be interested in writing optimized versions for some functions.
|
||||
Especially the string handling functions can be optimized a lot.
|
||||
|
||||
Take a look at
|
||||
|
||||
Faster String Functions
|
||||
Henry Spencer, University of Toronto
|
||||
Usenix Winter '92, pp. 419--428
|
||||
|
||||
or just ask. Currently mostly i?86 optimized versions exist.
|
||||
|
||||
|
||||
[ 8] Write nftw() function. Perhaps it might be good to reimplement the
|
||||
ftw() function as well to share most of the code.
|
||||
|
||||
|
||||
[ 9] Write AVL-tree based tsearch() et.al. functions. Currently only
|
||||
a very simple algorithm is used.
|
||||
|
||||
|
||||
[10] Extend regex and/or rx to work with wide characters.
|
||||
|
||||
|
||||
[11] Add mmap() support to malloc().
|
||||
Doug Lea's malloc implementation might give some ideas. Perhaps
|
||||
switching completly to his implementation is an option if it
|
||||
a) can work without mmap() support (not all system GNU libc
|
||||
is running on have mmap)
|
||||
b) is without mmap support at least as fast as the current
|
||||
implementation
|
||||
c) will be extended with the current hooks and additional functions
|
||||
+11
-10
@@ -6,16 +6,17 @@ As of this release, the GNU C library has been ported to the following
|
||||
configurations:
|
||||
|
||||
alpha-dec-osf1
|
||||
i386-bsd4.3
|
||||
i386-force_cpu386-none
|
||||
i386-gnu (for Hurd development only)
|
||||
i386-isc2.2
|
||||
i386-isc3
|
||||
i386-sco3.2
|
||||
i386-sco3.2v4
|
||||
i386-sequent-bsd
|
||||
i386-sysv
|
||||
i386-sysv4
|
||||
i[345]86-*-bsd4.3
|
||||
i[345]86-*-gnu
|
||||
i[345]86-*-isc2.2
|
||||
i[345]86-*-isc3
|
||||
i[345]86-*-linux
|
||||
i[345]86-*-sco3.2
|
||||
i[345]86-*-sco3.2v4
|
||||
i[345]86-*-sysv
|
||||
i[345]86-*-sysv4
|
||||
i[345]86-force_cpu386-none
|
||||
i[345]86-sequent-bsd
|
||||
i960-nindy960-none
|
||||
m68k-hp-bsd4.3
|
||||
m68k-mvme135-none
|
||||
|
||||
@@ -70,7 +70,11 @@ $(objpfx)dummy.o:
|
||||
@rm -f $(@:.o=.c)
|
||||
echo 'void __dummy__ () { }' > $(@:.o=.c)
|
||||
$(CC) -c $(@:.o=.c) -o $@
|
||||
generated := $(generated) dummy.o dummy.c
|
||||
$(objpfx)empty.o:
|
||||
@rm -f $(@:.o=.c)
|
||||
echo '' > $(@:.o=.c)
|
||||
$(CC) -c $(@:.o=.c) -o $@
|
||||
generated := $(generated) dummy.o dummy.c empty.c empty.o
|
||||
|
||||
# This makes all the auxilliary and test programs.
|
||||
|
||||
@@ -92,13 +96,13 @@ ifneq "$(strip $(tests))" ""
|
||||
# These are the implicit rules for making test outputs
|
||||
# from the test programs and whatever input files are present.
|
||||
$(objpfx)%.out: %.args $(objpfx)% %.input
|
||||
$(built-program-cmd) `cat $(word 1,$^)` < $(word 3,$^) > $@
|
||||
$($*-ENV) $(built-program-cmd) `cat $(word 1,$^)` < $(word 3,$^) > $@
|
||||
$(objpfx)%.out: %.args $(objpfx)%
|
||||
$(built-program-cmd) `cat $(word 1,$^)` > $@
|
||||
$($*-ENV) $(built-program-cmd) `cat $(word 1,$^)` > $@
|
||||
$(objpfx)%.out: %.input $(objpfx)%
|
||||
$(built-program-cmd) < $(word 1,$^) > $@
|
||||
$($*-ENV) $(built-program-cmd) < $(word 1,$^) > $@
|
||||
$(objpfx)%.out: /dev/null $(objpfx)% # Make it 2nd arg for canned sequence.
|
||||
$(built-program-cmd) > $@
|
||||
$($*-ENV) $(built-program-cmd) > $@
|
||||
endif # tests
|
||||
|
||||
.PHONY: distclean realclean subdir_distclean subdir_realclean \
|
||||
@@ -131,3 +135,16 @@ subdir_dist: dist
|
||||
# Convenient target to update all the generated source files.
|
||||
.PHONY: generated
|
||||
generated: $(addprefix $(objpfx),$(generated))
|
||||
|
||||
ifndef libc.so-version
|
||||
# Undefine this because it can't work when we libc.so is unversioned.
|
||||
static-only-routines =
|
||||
endif
|
||||
|
||||
ifdef static-only-routines
|
||||
# These routines are to be omitted from the shared library object,
|
||||
# so we replace the PIC objects for them with the empty object file.
|
||||
$(static-only-routines:%=$(objpfx)%.so): %.so: $(objpfx)empty.o
|
||||
rm -f $@
|
||||
ln $< $@
|
||||
endif
|
||||
|
||||
Vendored
+3
-2
@@ -3,7 +3,8 @@ dnl which appears in configure.in before the sysdep configure scripts are run.
|
||||
dnl Each sysdep configure.in does GLIBC_PROVIDES first, to avoid any
|
||||
dnl AC_REQUIREs or AC_BEFOREs duplicating their code.
|
||||
dnl
|
||||
define(AC_FD_MSG,4)dnl Autoconf lossage.
|
||||
define(AC_FD_MSG,6)dnl Autoconf lossage.
|
||||
define(AC_FD_CC,5)dnl Autoconf lossage.
|
||||
AC_DEFUN([GLIBC_PROVIDES], [dnl
|
||||
AC_PROVIDE([AC_PROG_INSTALL])dnl
|
||||
AC_PROVIDE([AC_PROG_RANLIB])dnl
|
||||
@@ -17,7 +18,7 @@ dnl
|
||||
AC_DEFUN(AC_CHECK_SYMBOL, [dnl
|
||||
AC_MSG_CHECKING(for $1)
|
||||
AC_CACHE_VAL(ac_cv_check_symbol_$1, [dnl
|
||||
AC_TRY_LINK(,
|
||||
AC_TRY_LINK(,
|
||||
changequote(,)dnl
|
||||
extern char *$1[]; puts(*$1);,
|
||||
changequote([,])dnl
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+2
-3
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 92, 94, 95, 96 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
|
||||
@@ -13,7 +13,7 @@ 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, 1992 Free Software Foundation, Inc., 675 Mass Ave,
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
@@ -95,4 +95,3 @@ __END_DECLS
|
||||
|
||||
|
||||
#endif /* NDEBUG. */
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Copyright (C) 1996 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.
|
||||
|
||||
#
|
||||
# Makefile for catgets.
|
||||
#
|
||||
subdir := catgets
|
||||
|
||||
headers = nl_types.h
|
||||
distribute = catgetsinfo.h config.h
|
||||
routines = catgets open_catalog
|
||||
others = gencat
|
||||
install-bin = gencat
|
||||
|
||||
gencat-modules = xmalloc
|
||||
|
||||
# To find xmalloc.c
|
||||
vpath %.c ../locale/programs
|
||||
|
||||
|
||||
include ../Rules
|
||||
|
||||
$(objpfx)gencat: $(gencat-modules:%=$(objpfx)%.o)
|
||||
|
||||
CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:"' \
|
||||
-DHAVE_CONFIG_H $(CPPFLAGS)
|
||||
@@ -0,0 +1,163 @@
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
|
||||
|
||||
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 <alloca.h>
|
||||
#include <nl_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "catgetsinfo.h"
|
||||
|
||||
|
||||
/* Open the catalog and return a descriptor for the catalog. */
|
||||
nl_catd
|
||||
catopen (const char *cat_name, int flag)
|
||||
{
|
||||
__nl_catd result;
|
||||
const char *env_var;
|
||||
|
||||
result = (__nl_catd) malloc (sizeof (__nl_catd));
|
||||
if (result == NULL)
|
||||
/* We cannot get enough memory. */
|
||||
return (nl_catd) -1;
|
||||
|
||||
result->status = closed;
|
||||
|
||||
result->cat_name = strdup (cat_name);
|
||||
if (result->cat_name == NULL)
|
||||
{
|
||||
free (result);
|
||||
return (nl_catd) -1;
|
||||
}
|
||||
|
||||
if (strchr (cat_name, '/') == NULL)
|
||||
{
|
||||
if (flag == NL_CAT_LOCALE)
|
||||
{
|
||||
env_var = getenv ("LC_ALL");
|
||||
if (env_var == NULL)
|
||||
{
|
||||
env_var = getenv ("LC_MESSAGES");
|
||||
if (env_var == NULL)
|
||||
{
|
||||
env_var = getenv ("LANG");
|
||||
if (env_var == NULL)
|
||||
env_var = "C";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
env_var = getenv ("LANG");
|
||||
if (env_var == NULL)
|
||||
env_var = "C";
|
||||
}
|
||||
|
||||
result->env_var = strdup (env_var);
|
||||
if (result->env_var == NULL)
|
||||
{
|
||||
free ((void *) result->cat_name);
|
||||
free ((void *) result);
|
||||
return (nl_catd) -1;
|
||||
}
|
||||
|
||||
if (getenv ("NLSPATH") != NULL)
|
||||
result->nlspath = strdup (getenv ("NLSPATH"));
|
||||
else
|
||||
result->nlspath = strdup (NLSPATH);
|
||||
|
||||
if (result->nlspath == NULL)
|
||||
{
|
||||
free ((void *) result->cat_name);
|
||||
free ((void *) result->env_var);
|
||||
free ((void *) result);
|
||||
return (nl_catd) -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result->env_var = NULL;
|
||||
result->nlspath = NULL;
|
||||
}
|
||||
|
||||
return (nl_catd) result;
|
||||
}
|
||||
|
||||
|
||||
/* Return message from message catalog. */
|
||||
char *
|
||||
catgets (nl_catd catalog_desc, int set, int message, const char *string)
|
||||
{
|
||||
__nl_catd catalog;
|
||||
size_t idx;
|
||||
size_t cnt;
|
||||
|
||||
/* Be generous if catalog which failed to be open is used. */
|
||||
if (catalog_desc == (nl_catd) -1 || ++set <= 0 || message < 0)
|
||||
return (char *) string;
|
||||
|
||||
catalog = (__nl_catd) catalog_desc;
|
||||
|
||||
if (catalog->status == closed)
|
||||
__open_catalog (catalog, 1);
|
||||
|
||||
if (catalog->status == nonexisting)
|
||||
return (char *) string;
|
||||
|
||||
idx = ((set * message) % catalog->plane_size) * 3;
|
||||
cnt = 0;
|
||||
do
|
||||
{
|
||||
if (catalog->name_ptr[idx + 0] == (u_int32_t) set
|
||||
&& catalog->name_ptr[idx + 1] == (u_int32_t) message)
|
||||
return (char *) &catalog->strings[catalog->name_ptr[idx + 2]];
|
||||
|
||||
idx += catalog->plane_size * 3;
|
||||
}
|
||||
while (++cnt < catalog->plane_depth);
|
||||
|
||||
return (char *) string;
|
||||
}
|
||||
|
||||
|
||||
/* Return resources used for loaded message catalog. */
|
||||
int
|
||||
catclose (nl_catd catalog_desc)
|
||||
{
|
||||
__nl_catd catalog;
|
||||
|
||||
catalog = (__nl_catd) catalog_desc;
|
||||
|
||||
if (catalog->status == mmaped)
|
||||
munmap ((void *) catalog->file_ptr, catalog->file_size);
|
||||
else if (catalog->status == malloced)
|
||||
free ((void *) catalog->file_ptr);
|
||||
else if (catalog->status != closed && catalog->status != nonexisting)
|
||||
return -1;
|
||||
|
||||
if (catalog->nlspath)
|
||||
free ((void *) catalog->nlspath);
|
||||
if (catalog->env_var)
|
||||
free ((void *) catalog->env_var);
|
||||
free ((void *) catalog);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
|
||||
|
||||
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 <sys/types.h>
|
||||
|
||||
|
||||
struct catalog_obj
|
||||
{
|
||||
u_int32_t magic;
|
||||
u_int32_t plane_size;
|
||||
u_int32_t plane_depth;
|
||||
/* This is in fact two arrays in one: always a pair of name and
|
||||
pointer into the data area. */
|
||||
u_int32_t name_ptr[0];
|
||||
};
|
||||
|
||||
|
||||
/* This structure will be filled after loading the catalog. */
|
||||
typedef struct catalog_info
|
||||
{
|
||||
enum { closed, nonexisting, mmaped, malloced } status;
|
||||
|
||||
const char *cat_name;
|
||||
const char *env_var;
|
||||
const char *nlspath;
|
||||
|
||||
size_t plane_size;
|
||||
size_t plane_depth;
|
||||
u_int32_t *name_ptr;
|
||||
const char *strings;
|
||||
|
||||
struct catalog_obj *file_ptr;
|
||||
size_t file_size;
|
||||
} *__nl_catd;
|
||||
|
||||
|
||||
|
||||
/* The magic number to signal we really have a catalog file. */
|
||||
#define CATGETS_MAGIC 0x960408de
|
||||
|
||||
|
||||
/* Prototypes for helper functions. */
|
||||
void __open_catalog (__nl_catd __catalog, int __with_path);
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef _CG_CONFIG_H
|
||||
#define _CG_CONFIG_H
|
||||
|
||||
/* Use the internal textdomain used for libc messages. */
|
||||
#define PACKAGE _libc_intl_domainname
|
||||
#ifndef VERSION
|
||||
/* Get libc version number. */
|
||||
#include "../version.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include_next <config.h>
|
||||
|
||||
#endif
|
||||
+1030
File diff suppressed because it is too large
Load Diff
@@ -16,38 +16,33 @@ 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 <sysdep.h>
|
||||
#define _ERRNO_H
|
||||
#include <errnos.h>
|
||||
#ifndef _NL_TYPES_H
|
||||
#define _NL_TYPES_H 1
|
||||
#include <features.h>
|
||||
|
||||
/* Linux has two versions of the select system call. The old one expected
|
||||
one argument which must be a pointer to a struct which contains the
|
||||
five values. The new version expects the five arguments be given in the
|
||||
registers. First try the new version, if it's not available fall back
|
||||
to the old version. */
|
||||
/* The default message set used by the gencat program. */
|
||||
#define NL_SETD 1
|
||||
|
||||
.text
|
||||
SYSCALL_ERROR_HANDLER
|
||||
ENTRY (__select)
|
||||
/* Value for FLAG parameter of `catgets' to say we want XPG4 compliance. */
|
||||
#define NL_CAT_LOCALE 1
|
||||
|
||||
#if 0 /* For now only use the old version. */
|
||||
DO_CALL (#SYS_ify (_newselect), 5)
|
||||
tst.l %d0
|
||||
jmi 1f
|
||||
rts
|
||||
/* Message catalog descriptor type. */
|
||||
typedef void *nl_catd;
|
||||
|
||||
1: move.l #-ENOSYS, %d1
|
||||
cmp.l %d1, %d0
|
||||
jne syscall_error /* Real error */
|
||||
|
||||
/* Try again using the old syscall interface. */
|
||||
#endif
|
||||
lea 4(%sp), %a0
|
||||
move.l %a0, %d1
|
||||
move.l #SYS_ify (select), %d0
|
||||
trap #0
|
||||
tst.l %d0
|
||||
jmi syscall_error
|
||||
ret
|
||||
__BEGIN_DECLS
|
||||
|
||||
weak_alias (__select, select)
|
||||
/* Open message catalog for later use, returning descriptor. */
|
||||
extern nl_catd catopen __P ((__const char *__cat_name, int __flag));
|
||||
|
||||
/* Return translation with NUMBER in SET of CATALOG; if not found
|
||||
return STRING. */
|
||||
extern char *catgets __P ((nl_catd __catalog, int __set, int __number,
|
||||
__const char *__string));
|
||||
|
||||
/* Close message CATALOG. */
|
||||
extern int catclose __P ((nl_catd __catalog));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* nl_types.h */
|
||||
@@ -0,0 +1,263 @@
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
|
||||
|
||||
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 <endian.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "catgetsinfo.h"
|
||||
|
||||
|
||||
#define SWAPU32(w) \
|
||||
(((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24))
|
||||
|
||||
|
||||
void
|
||||
__open_catalog (__nl_catd catalog, int with_path)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
int swapping;
|
||||
|
||||
if (strchr (catalog->cat_name, '/') != NULL || !with_path)
|
||||
fd = open (catalog->cat_name, O_RDONLY);
|
||||
else
|
||||
{
|
||||
const char *run_nlspath = catalog->nlspath;
|
||||
#define ENOUGH(n) \
|
||||
if (bufact + (n) >=bufmax) \
|
||||
{ \
|
||||
char *old_buf = buf; \
|
||||
bufmax += 256 + (n); \
|
||||
buf = (char *) alloca (bufmax); \
|
||||
memcpy (buf, old_buf, bufact); \
|
||||
}
|
||||
|
||||
/* The RUN_NLSPATH variable contains a colon separated list of
|
||||
descriptions where we expect to find catalogs. We have to
|
||||
recognize certain % substitutions and stop when we found the
|
||||
first existing file. */
|
||||
char *buf;
|
||||
size_t bufact;
|
||||
size_t bufmax;
|
||||
|
||||
buf = NULL;
|
||||
bufmax = 0;
|
||||
|
||||
fd = -1;
|
||||
while (*run_nlspath != '\0')
|
||||
{
|
||||
bufact = 0;
|
||||
while (*run_nlspath != ':' && *run_nlspath != '\0')
|
||||
if (*run_nlspath == '%')
|
||||
{
|
||||
const char *tmp;
|
||||
|
||||
++run_nlspath; /* We have seen the `%'. */
|
||||
switch (*run_nlspath++)
|
||||
{
|
||||
case 'N':
|
||||
/* Use the catalog name. */
|
||||
ENOUGH (strlen (catalog->cat_name));
|
||||
bufact = stpcpy (&buf[bufact], catalog->cat_name) - buf;
|
||||
break;
|
||||
case 'L':
|
||||
/* Use the current locale category value. */
|
||||
ENOUGH (strlen (catalog->env_var));
|
||||
bufact = stpcpy (&buf[bufact], catalog->env_var) - buf;
|
||||
break;
|
||||
case 'l':
|
||||
/* Use language element of locale category value. */
|
||||
tmp = catalog->env_var;
|
||||
do
|
||||
{
|
||||
ENOUGH (1);
|
||||
buf[bufact++] = *tmp++;
|
||||
}
|
||||
while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
|
||||
break;
|
||||
case 't':
|
||||
/* Use territory element of locale category value. */
|
||||
tmp = catalog->env_var;
|
||||
do
|
||||
++tmp;
|
||||
while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
|
||||
if (*tmp == '_')
|
||||
{
|
||||
++tmp;
|
||||
do
|
||||
{
|
||||
ENOUGH (1);
|
||||
buf[bufact++] = *tmp;
|
||||
}
|
||||
while (*tmp != '\0' && *tmp != '.');
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
/* Use code set element of locale category value. */
|
||||
tmp = catalog->env_var;
|
||||
do
|
||||
++tmp;
|
||||
while (*tmp != '\0' && *tmp != '.');
|
||||
if (*tmp == '.')
|
||||
{
|
||||
++tmp;
|
||||
do
|
||||
{
|
||||
ENOUGH (1);
|
||||
buf[bufact++] = *tmp;
|
||||
}
|
||||
while (*tmp != '\0');
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
ENOUGH (1);
|
||||
buf[bufact++] = '%';
|
||||
break;
|
||||
default:
|
||||
/* Unknown variable: ignore this path element. */
|
||||
bufact = 0;
|
||||
while (*run_nlspath != '\0' && *run_nlspath != ':')
|
||||
++run_nlspath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ENOUGH (1);
|
||||
buf[bufact++] = *run_nlspath++;
|
||||
}
|
||||
ENOUGH (1);
|
||||
buf[bufact] = '\0';
|
||||
|
||||
if (bufact != 0)
|
||||
{
|
||||
fd = open (buf, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
++run_nlspath;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd < 0 || fstat (fd, &st) < 0)
|
||||
{
|
||||
catalog->status = nonexisting;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef MAP_COPY
|
||||
/* Linux seems to lack read-only copy-on-write. */
|
||||
#define MAP_COPY MAP_PRIVATE
|
||||
#endif
|
||||
#ifndef MAP_FILE
|
||||
/* Some systems do not have this flag; it is superfluous. */
|
||||
#define MAP_FILE 0
|
||||
#endif
|
||||
#ifndef MAP_INHERIT
|
||||
/* Some systems might lack this; they lose. */
|
||||
#define MAP_INHERIT 0
|
||||
#endif
|
||||
catalog->file_size = st.st_size;
|
||||
catalog->file_ptr =
|
||||
(struct catalog_obj *) mmap (NULL, st.st_size, PROT_READ,
|
||||
MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0);
|
||||
if (catalog->file_ptr != (struct catalog_obj *) -1)
|
||||
/* Tell the world we managed to mmap the file. */
|
||||
catalog->status = mmaped;
|
||||
else
|
||||
{
|
||||
/* mmap failed perhaps because the system call is not
|
||||
implemented. Try to load the file. */
|
||||
size_t todo;
|
||||
catalog->file_ptr = malloc (st.st_size);
|
||||
if (catalog->file_ptr == NULL)
|
||||
{
|
||||
catalog->status = nonexisting;
|
||||
return;
|
||||
}
|
||||
todo = st.st_size;
|
||||
/* Save read, handle partial reads. */
|
||||
do
|
||||
{
|
||||
size_t now = read (fd, (((char *) &catalog->file_ptr)
|
||||
+ (st.st_size - todo)), todo);
|
||||
if (now == 0)
|
||||
{
|
||||
free ((void *) catalog->file_ptr);
|
||||
catalog->status = nonexisting;
|
||||
return;
|
||||
}
|
||||
todo -= now;
|
||||
}
|
||||
while (todo > 0);
|
||||
catalog->status = malloced;
|
||||
}
|
||||
|
||||
/* We don't need the file anymore. */
|
||||
close (fd);
|
||||
|
||||
/* Determine whether the file is a catalog file and if yes whether
|
||||
it is written using the correct byte order. Else we have to swap
|
||||
the values. */
|
||||
if (catalog->file_ptr->magic == CATGETS_MAGIC)
|
||||
swapping = 0;
|
||||
else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC))
|
||||
swapping = 1;
|
||||
else
|
||||
{
|
||||
/* Illegal file. Free he resources and mark catalog as not
|
||||
usable. */
|
||||
if (catalog->status == mmaped)
|
||||
munmap ((void *) catalog->file_ptr, catalog->file_size);
|
||||
else
|
||||
free (catalog->file_ptr);
|
||||
catalog->status = nonexisting;
|
||||
return;
|
||||
}
|
||||
|
||||
#define SWAP(x) (swapping ? SWAPU32 (x) : (x))
|
||||
|
||||
/* Get dimensions of the used hashing table. */
|
||||
catalog->plane_size = SWAP (catalog->file_ptr->plane_size);
|
||||
catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth);
|
||||
|
||||
/* The file contains two versions of the pointer tables. Pick the
|
||||
right one for the local byte order. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
catalog->name_ptr = &catalog->file_ptr->name_ptr[0];
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size
|
||||
* catalog->plane_depth
|
||||
* 3];
|
||||
#else
|
||||
# error Cannot handle __BYTE_ORDER byte order
|
||||
#endif
|
||||
|
||||
/* The rest of the file contains all the strings. They are
|
||||
addressed relative to the position of the first string. */
|
||||
catalog->strings =
|
||||
(const char *) &catalog->file_ptr->name_ptr[catalog->plane_size
|
||||
* catalog->plane_depth * 3 * 2];
|
||||
}
|
||||
Vendored
+42
-17
@@ -51,15 +51,13 @@ trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
|
||||
# Note: order is significant - the case branches are not exclusive.
|
||||
|
||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
alpha:OSF1:[VX]*:*)
|
||||
# After 1.2, OSF1 uses "V1.3" for uname -r.
|
||||
# After 4.x, OSF1 uses "X4.x" for uname -r.
|
||||
echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VX]//'`
|
||||
exit 0 ;;
|
||||
alpha:OSF1:*:*)
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
echo alpha-dec-osf${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
|
||||
exit 0 ;;
|
||||
21064:Windows_NT:50:3)
|
||||
echo alpha-dec-winnt3.5
|
||||
exit 0 ;;
|
||||
@@ -118,11 +116,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
VAX*:ULTRIX*:*:*)
|
||||
echo vax-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mips:*:4*:UMIPS)
|
||||
echo mips-mips-riscos4sysv
|
||||
exit 0 ;;
|
||||
mips:*:5*:RISCos)
|
||||
echo mips-mips-riscos${UNAME_RELEASE}
|
||||
mips:*:*:UMIPS | mips:*:*:RISCos)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
int main (argc, argv) int argc; char **argv; {
|
||||
#if defined (host_mips) && defined (MIPSEB)
|
||||
#if defined (SYSTYPE_SYSV)
|
||||
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#if defined (SYSTYPE_SVR4)
|
||||
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
|
||||
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
exit (-1);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy "${UNAME_RELEASE}" \
|
||||
&& rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo mips-mips-riscos{UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Night_Hawk:Power_UNIX:*:*)
|
||||
echo powerpc-harris-powerunix
|
||||
@@ -138,8 +152,8 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit 0 ;;
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88100 ] ; then
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
|
||||
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
|
||||
echo m88k-dg-dgux${UNAME_RELEASE}
|
||||
@@ -213,7 +227,7 @@ EOF
|
||||
echo romp-ibm-bsd4.4
|
||||
exit 0 ;;
|
||||
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
|
||||
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
|
||||
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
|
||||
exit 0 ;; # report: romp-ibm BSD 4.3
|
||||
*:BOSX:*:*)
|
||||
echo rs6000-bull-bosx
|
||||
@@ -330,6 +344,9 @@ EOF
|
||||
p*:CYGWIN*:*)
|
||||
echo powerpcle-unknown-cygwin32
|
||||
exit 0 ;;
|
||||
prep*:SunOS:5.*:*)
|
||||
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
*:GNU:*:*)
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
exit 0 ;;
|
||||
@@ -349,6 +366,8 @@ EOF
|
||||
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
|
||||
elif test "${UNAME_MACHINE}" = "alpha" ; then
|
||||
echo alpha-unknown-linux ; exit 0
|
||||
elif test "${UNAME_MACHINE}" = "sparc" ; then
|
||||
echo sparc-unknown-linux ; exit 0
|
||||
else
|
||||
# Either a pre-BFD a.out linker (linuxoldld) or one that does not give us
|
||||
# useful --help. Gcc wants to distinguish between linuxoldld and linuxaout.
|
||||
@@ -416,9 +435,15 @@ EOF
|
||||
exit 0 ;;
|
||||
M680[234]0:*:R3V[567]*:*)
|
||||
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
|
||||
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
|
||||
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
|
||||
UNAME_REL=4.3
|
||||
if test -f /etc/.relid; then
|
||||
UNAME_REL=4.3.`awk '{ print $3 }' /etc/.relid`
|
||||
fi
|
||||
uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& echo i486-ncr-sysv4.3 && exit 0 ;;
|
||||
&& echo i486-ncr-sysv$UNAME_REL && exit 0
|
||||
uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
&& echo i586-ncr-sysv$UNAME_REL && exit 0 ;;
|
||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||
uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& echo i486-ncr-sysv4 && exit 0 ;;
|
||||
|
||||
@@ -71,4 +71,8 @@
|
||||
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* The locale code needs these definitions. */
|
||||
|
||||
#define HAVE_REGEX 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,7 @@ exec_prefix = @exec_prefix@
|
||||
|
||||
# System configuration.
|
||||
config-machine = @host_cpu@
|
||||
base-machine = @base_machine@
|
||||
config-vendor = @host_vendor@
|
||||
config-os = @host_os@
|
||||
config-sysdirs = @sysnames@
|
||||
@@ -17,6 +18,8 @@ config-defines = @DEFS@
|
||||
elf = @elf@
|
||||
have-initfini = @libc_cv_have_initfini@
|
||||
|
||||
have-no-whole-archive = @libc_cv_ld_no_whole_archive@
|
||||
|
||||
# Configuration options.
|
||||
gnu-as = @gnu_as@
|
||||
gnu-ld = @gnu_ld@
|
||||
@@ -27,6 +30,7 @@ stdio = @stdio@
|
||||
|
||||
# Build tools.
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
AR = @AR@
|
||||
RANLIB = @RANLIB@
|
||||
AS = $(CC) -c
|
||||
@@ -35,5 +39,7 @@ AS = $(CC) -c
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
LN_S = @LN_S@
|
||||
MSGFMT = @MSGFMT@
|
||||
|
||||
# More variables may be inserted below by configure.
|
||||
|
||||
Vendored
+1
-1
@@ -662,7 +662,7 @@ case $os in
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -cygwin32* | -pe* | -psos* | -moss* )
|
||||
| -cygwin32* | -pe* | -psos* | -moss* | -proelf* )
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-sunos5*)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# From configure.in CVSid
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated automatically using autoconf version 2.9
|
||||
# Generated automatically using autoconf version 2.10
|
||||
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
|
||||
#
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
@@ -17,7 +17,7 @@ ac_help="$ac_help
|
||||
ac_help="$ac_help
|
||||
--with-gettext=DIR find GNU gettext source code in DIR (not needed)"
|
||||
ac_help="$ac_help
|
||||
--with-fp if using floating-point hardware"
|
||||
--with-fp if using floating-point hardware default=yes"
|
||||
ac_help="$ac_help
|
||||
--with-gnu-binutils if using GNU binutils (as and ld)"
|
||||
ac_help="$ac_help
|
||||
@@ -353,7 +353,7 @@ EOF
|
||||
verbose=yes ;;
|
||||
|
||||
-version | --version | --versio | --versi | --vers)
|
||||
echo "configure generated by autoconf version 2.9"
|
||||
echo "configure generated by autoconf version 2.10"
|
||||
exit 0 ;;
|
||||
|
||||
-with-* | --with-*)
|
||||
@@ -424,12 +424,12 @@ trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2
|
||||
# 2 errors and warnings
|
||||
# 3 some systems may open it to /dev/tty
|
||||
# 4 used on the Kubota Titan
|
||||
# 4 checking for... messages and results
|
||||
# 6 checking for... messages and results
|
||||
# 5 compiler messages saved in config.log
|
||||
if test "$silent" = yes; then
|
||||
exec 4>/dev/null
|
||||
exec 6>/dev/null
|
||||
else
|
||||
exec 4>&1
|
||||
exec 6>&1
|
||||
fi
|
||||
exec 5>./config.log
|
||||
|
||||
@@ -682,7 +682,7 @@ if $ac_config_sub sun4 >/dev/null 2>&1; then :
|
||||
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
|
||||
fi
|
||||
|
||||
echo $ac_n "checking host system type""... $ac_c" 1>&4
|
||||
echo $ac_n "checking host system type""... $ac_c" 1>&6
|
||||
|
||||
host_alias=$host
|
||||
case "$host_alias" in
|
||||
@@ -700,7 +700,7 @@ host=`$ac_config_sub $host_alias`
|
||||
host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
|
||||
host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
|
||||
host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
|
||||
echo "$ac_t""$host" 1>&4
|
||||
echo "$ac_t""$host" 1>&6
|
||||
|
||||
# We keep the original values in `$config_*' and never modify them, so we
|
||||
# can write them unchanged into config.make. Everything else uses
|
||||
@@ -716,43 +716,41 @@ esac
|
||||
case "$host_os" in
|
||||
gnu* | linux* | sysv4* | solaris2*)
|
||||
# These systems always use the ELF format.
|
||||
elf=yes ;;
|
||||
if test "$host_cpu" != alpha; then # Linux/Alpha is not fully ELF yet
|
||||
elf=yes
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Linux/Alpha does not use ELF yet.
|
||||
case "$host_cpu-$host_os" in
|
||||
alpha*-linux*)
|
||||
gnu_ld=no elf=no ;;
|
||||
esac
|
||||
|
||||
# Compute the list of sysdep directories for this configuration.
|
||||
sysdep_dir=$srcdir/sysdeps
|
||||
echo $ac_n "checking sysdep dirs""... $ac_c" 1>&4
|
||||
if eval "test \"`echo '$''{'libc_cv_sysdirs'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
else
|
||||
machine=$config_machine
|
||||
machine=$config_machine
|
||||
vendor=$config_vendor
|
||||
os=$config_os
|
||||
|
||||
# Expand the configuration machine name into a subdirectory by architecture
|
||||
# type and particular chip.
|
||||
case "$machine" in
|
||||
a29k | am29000) machine=a29k ;;
|
||||
alpha*) machine=alpha/$machine ;;
|
||||
hppa*) machine=hppa/$machine ;;
|
||||
i[345]86) machine=i386/$machine ;;
|
||||
m680?0) machine=m68k/$machine ;;
|
||||
m68k) machine=m68k/m68020 ;;
|
||||
m88???) machine=m88k/$machine ;;
|
||||
m88k) machine=m88k/m88100 ;;
|
||||
mips*) machine=mips/$machine ;;
|
||||
mips64*) machine=mips/mips64/$machine ;;
|
||||
sparc[6789]) machine=sparc/$machine ;;
|
||||
supersparc) machine=sparc/sparc8 ;;
|
||||
a29k | am29000) base_machine=a29k machine=a29k ;;
|
||||
alpha*) base_machine=alpha machine=alpha/$machine ;;
|
||||
hppa*) base_machine=hppa machine=hppa/$machine ;;
|
||||
i[345]86) base_machine=i386 machine=i386/$machine ;;
|
||||
m680?0) base_machine=m68k machine=m68k/$machine ;;
|
||||
m68k) base_machine=m68k machine=m68k/m68020 ;;
|
||||
m88???) base_machine=m88k machine=m88k/$machine ;;
|
||||
m88k) base_machine=m88k machine=m88k/m88100 ;;
|
||||
mips*) base_machine=mips machine=mips/$machine ;;
|
||||
mips64*) base_machine=mips64 machine=mips/mips64/$machine ;;
|
||||
sparc[6789]) base_machine=sparc machine=sparc/$machine ;;
|
||||
supersparc) base_machine=sparc machine=sparc/sparc8 ;;
|
||||
esac
|
||||
|
||||
# Make sco3.2v4 become sco3.2.4 and sunos4.1.1_U1 become sunos4.1.1.U1.
|
||||
|
||||
# Compute the list of sysdep directories for this configuration.
|
||||
sysdep_dir=$srcdir/sysdeps
|
||||
echo $ac_n "checking sysdep dirs""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_sysdirs'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
# Make sco3.2v4 become sco3.2.4 and sunos4.1.1_U1 become sunos4.1.1.U1.
|
||||
os="`echo $os | sed 's/\([0-9A-Z]\)[v_]\([0-9A-Z]\)/\1.\2/g'`"
|
||||
|
||||
case "$os" in
|
||||
@@ -915,7 +913,7 @@ done
|
||||
libc_cv_sysdirs="$sysnames"
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_sysdirs" 1>&4
|
||||
echo "$ac_t""$libc_cv_sysdirs" 1>&6
|
||||
sysnames="$libc_cv_sysdirs"
|
||||
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
@@ -928,10 +926,10 @@ echo "$ac_t""$libc_cv_sysdirs" 1>&4
|
||||
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
|
||||
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
|
||||
# ./install, which can be erroneously created by make from ./install.sh.
|
||||
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
|
||||
if test -z "$INSTALL"; then
|
||||
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
|
||||
for ac_dir in $PATH; do
|
||||
@@ -969,7 +967,7 @@ fi
|
||||
INSTALL="$ac_install_sh"
|
||||
fi
|
||||
fi
|
||||
echo "$ac_t""$INSTALL" 1>&4
|
||||
echo "$ac_t""$INSTALL" 1>&6
|
||||
|
||||
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
|
||||
# It thinks the first close brace ends the variable substitution.
|
||||
@@ -981,8 +979,61 @@ if test "$INSTALL" = "${srcdir}/install-sh"; then
|
||||
# The makefiles need to use a different form to find it in $srcdir.
|
||||
INSTALL='$(..)./install-sh'
|
||||
fi
|
||||
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
rm -f conftestdata
|
||||
if ln -s X conftestdata 2>/dev/null
|
||||
then
|
||||
rm -f conftestdata
|
||||
ac_cv_prog_LN_S="ln -s"
|
||||
else
|
||||
ac_cv_prog_LN_S=ln
|
||||
fi
|
||||
fi
|
||||
LN_S="$ac_cv_prog_LN_S"
|
||||
if test "$ac_cv_prog_LN_S" = "ln -s"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
echo $ac_n "checking build system type""... $ac_c" 1>&4
|
||||
for ac_prog in msgfmt gmsgfmt
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_MSGFMT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
if test -n "$MSGFMT"; then
|
||||
ac_cv_prog_MSGFMT="$MSGFMT" # Let the user override the test.
|
||||
else
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
|
||||
for ac_dir in $PATH; do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f $ac_dir/$ac_word; then
|
||||
ac_cv_prog_MSGFMT="$ac_prog"
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
fi
|
||||
fi
|
||||
MSGFMT="$ac_cv_prog_MSGFMT"
|
||||
if test -n "$MSGFMT"; then
|
||||
echo "$ac_t""$MSGFMT" 1>&6
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
test -n "$MSGFMT" && break
|
||||
done
|
||||
test -n "$MSGFMT" || MSGFMT=":"
|
||||
|
||||
|
||||
echo $ac_n "checking build system type""... $ac_c" 1>&6
|
||||
|
||||
build_alias=$build
|
||||
case "$build_alias" in
|
||||
@@ -997,7 +1048,7 @@ build=`$ac_config_sub $build_alias`
|
||||
build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
|
||||
build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
|
||||
build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
|
||||
echo "$ac_t""$build" 1>&4
|
||||
echo "$ac_t""$build" 1>&6
|
||||
|
||||
if test $host != $build; then
|
||||
ac_tool_prefix=${host_alias}-
|
||||
@@ -1007,9 +1058,9 @@ fi
|
||||
|
||||
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}gcc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
if test -n "$CC"; then
|
||||
ac_cv_prog_CC="$CC" # Let the user override the test.
|
||||
@@ -1028,18 +1079,74 @@ fi
|
||||
fi
|
||||
CC="$ac_cv_prog_CC"
|
||||
if test -n "$CC"; then
|
||||
echo "$ac_t""$CC" 1>&4
|
||||
echo "$ac_t""$CC" 1>&6
|
||||
else
|
||||
echo "$ac_t""no" 1>&4
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
|
||||
# On Suns, sometimes $CPP names a directory.
|
||||
if test -n "$CPP" && test -d "$CPP"; then
|
||||
CPP=
|
||||
fi
|
||||
if test -z "$CPP"; then
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
# This must be in double quotes, not single quotes, because CPP may get
|
||||
# substituted into the Makefile and "${CC-cc}" will confuse make.
|
||||
CPP="${CC-cc} -E"
|
||||
# On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
# not just through cpp.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1105 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
else
|
||||
echo "$ac_err" >&5
|
||||
rm -rf conftest*
|
||||
CPP="${CC-cc} -E -traditional-cpp"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1120 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1126: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
else
|
||||
echo "$ac_err" >&5
|
||||
rm -rf conftest*
|
||||
CPP=/lib/cpp
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
rm -f conftest*
|
||||
ac_cv_prog_CPP="$CPP"
|
||||
fi
|
||||
CPP="$ac_cv_prog_CPP"
|
||||
else
|
||||
ac_cv_prog_CPP="$CPP"
|
||||
fi
|
||||
echo "$ac_t""$CPP" 1>&6
|
||||
|
||||
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}ar; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
if test -n "$AR"; then
|
||||
ac_cv_prog_AR="$AR" # Let the user override the test.
|
||||
@@ -1058,18 +1165,18 @@ fi
|
||||
fi
|
||||
AR="$ac_cv_prog_AR"
|
||||
if test -n "$AR"; then
|
||||
echo "$ac_t""$AR" 1>&4
|
||||
echo "$ac_t""$AR" 1>&6
|
||||
else
|
||||
echo "$ac_t""no" 1>&4
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
if test -n "$RANLIB"; then
|
||||
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
|
||||
@@ -1087,9 +1194,9 @@ fi
|
||||
fi
|
||||
RANLIB="$ac_cv_prog_RANLIB"
|
||||
if test -n "$RANLIB"; then
|
||||
echo "$ac_t""$RANLIB" 1>&4
|
||||
echo "$ac_t""$RANLIB" 1>&6
|
||||
else
|
||||
echo "$ac_t""no" 1>&4
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
|
||||
@@ -1097,9 +1204,9 @@ if test -z "$ac_cv_prog_RANLIB"; then
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "ranlib", so it can be a program name with args.
|
||||
set dummy ranlib; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
if test -n "$RANLIB"; then
|
||||
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
|
||||
@@ -1118,9 +1225,9 @@ fi
|
||||
fi
|
||||
RANLIB="$ac_cv_prog_RANLIB"
|
||||
if test -n "$RANLIB"; then
|
||||
echo "$ac_t""$RANLIB" 1>&4
|
||||
echo "$ac_t""$RANLIB" 1>&6
|
||||
else
|
||||
echo "$ac_t""no" 1>&4
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
else
|
||||
@@ -1128,66 +1235,10 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&4
|
||||
# On Suns, sometimes $CPP names a directory.
|
||||
if test -n "$CPP" && test -d "$CPP"; then
|
||||
CPP=
|
||||
fi
|
||||
if test -z "$CPP"; then
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
else
|
||||
# This must be in double quotes, not single quotes, because CPP may get
|
||||
# substituted into the Makefile and "${CC-cc}" will confuse make.
|
||||
CPP="${CC-cc} -E"
|
||||
# On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
# not just through cpp.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1147 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1153: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
else
|
||||
echo "$ac_err" >&5
|
||||
rm -rf conftest*
|
||||
CPP="${CC-cc} -E -traditional-cpp"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1162 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1168: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
else
|
||||
echo "$ac_err" >&5
|
||||
rm -rf conftest*
|
||||
CPP=/lib/cpp
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
rm -f conftest*
|
||||
ac_cv_prog_CPP="$CPP"
|
||||
fi
|
||||
CPP="$ac_cv_prog_CPP"
|
||||
else
|
||||
ac_cv_prog_CPP="$CPP"
|
||||
fi
|
||||
echo "$ac_t""$CPP" 1>&4
|
||||
|
||||
|
||||
echo $ac_n "checking for signed size_t type""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for signed size_t type""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_signed_size_t'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
echo '#include <stddef.h>
|
||||
FOOBAR __SIZE_TYPE__ FOOBAR' > conftest.c
|
||||
@@ -1200,7 +1251,7 @@ fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_signed_size_t" 1>&4
|
||||
echo "$ac_t""$libc_cv_signed_size_t" 1>&6
|
||||
if test $libc_cv_signed_size_t = yes; then
|
||||
cat >> confdefs.h <<\EOF
|
||||
#undef __SIZE_TYPE__
|
||||
@@ -1208,12 +1259,12 @@ if test $libc_cv_signed_size_t = yes; then
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for libc-friendly stddef.h""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for libc-friendly stddef.h""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_friendly_stddef'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1217 "configure"
|
||||
#line 1268 "configure"
|
||||
#include "confdefs.h"
|
||||
#define __need_size_t
|
||||
#define __need_wchar_t
|
||||
@@ -1229,7 +1280,7 @@ size_t size; wchar_t wchar;
|
||||
if (&size == NULL || &wchar == NULL) abort ();
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1233: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:1284: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
libc_cv_friendly_stddef=yes
|
||||
else
|
||||
@@ -1240,15 +1291,15 @@ rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_friendly_stddef" 1>&4
|
||||
echo "$ac_t""$libc_cv_friendly_stddef" 1>&6
|
||||
if test $libc_cv_friendly_stddef = yes; then
|
||||
config_vars="$config_vars
|
||||
override stddef.h = # The installed <stddef.h> seems to be libc-friendly."
|
||||
fi
|
||||
|
||||
echo $ac_n "checking whether we need to use -P to assemble .S files""... $ac_c" 1>&4
|
||||
echo $ac_n "checking whether we need to use -P to assemble .S files""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_need_minus_P'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.S <<EOF
|
||||
#include "confdefs.h"
|
||||
@@ -1262,15 +1313,15 @@ fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_need_minus_P" 1>&4
|
||||
echo "$ac_t""$libc_cv_need_minus_P" 1>&6
|
||||
if test $libc_cv_need_minus_P = yes; then
|
||||
config_vars="$config_vars
|
||||
asm-CPPFLAGS = -P # The assembler can't grok cpp's # line directives."
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for assembler global-symbol directive""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for assembler global-symbol directive""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_asm_global_directive'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
libc_cv_asm_global_directive=UNKNOWN
|
||||
for ac_globl in .globl .global; do
|
||||
@@ -1287,7 +1338,7 @@ EOF
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_asm_global_directive" 1>&4
|
||||
echo "$ac_t""$libc_cv_asm_global_directive" 1>&6
|
||||
if test $libc_cv_asm_global_directive = UNKNOWN; then
|
||||
{ echo "configure: error: cannot determine asm global directive" 1>&2; exit 1; }
|
||||
else
|
||||
@@ -1297,9 +1348,9 @@ EOF
|
||||
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for .set assembler directive""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for .set assembler directive""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_asm_set_directive'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.s <<EOF
|
||||
.text
|
||||
@@ -1322,7 +1373,7 @@ fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_asm_set_directive" 1>&4
|
||||
echo "$ac_t""$libc_cv_asm_set_directive" 1>&6
|
||||
if test $libc_cv_asm_set_directive = yes; then
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define HAVE_ASM_SET_DIRECTIVE 1
|
||||
@@ -1331,21 +1382,22 @@ EOF
|
||||
fi
|
||||
|
||||
if test $elf != yes; then
|
||||
echo $ac_n "checking for .init and .fini sections""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for .init and .fini sections""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_have_initfini'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1340 "configure"
|
||||
#line 1391 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() { return 0; }
|
||||
int t() {
|
||||
asm (".section .init");
|
||||
asm (".section .fini");
|
||||
asm (".text");
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1349: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:1401: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
libc_cv_have_initfini=yes
|
||||
else
|
||||
@@ -1356,7 +1408,7 @@ rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_have_initfini" 1>&4
|
||||
echo "$ac_t""$libc_cv_have_initfini" 1>&6
|
||||
if test $libc_cv_have_initfini = yes; then
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define HAVE_INITFINI 1
|
||||
@@ -1368,12 +1420,12 @@ fi
|
||||
if test $elf = yes; then
|
||||
libc_cv_asm_underscores=no
|
||||
else
|
||||
echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_asm_underscores'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1377 "configure"
|
||||
#line 1429 "configure"
|
||||
#include "confdefs.h"
|
||||
asm ("_glibc_foobar:");
|
||||
int main() { return 0; }
|
||||
@@ -1381,7 +1433,7 @@ int t() {
|
||||
glibc_foobar ();
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
|
||||
if { (eval echo configure:1437: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
libc_cv_asm_underscores=yes
|
||||
else
|
||||
@@ -1392,7 +1444,7 @@ rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_asm_underscores" 1>&4
|
||||
echo "$ac_t""$libc_cv_asm_underscores" 1>&6
|
||||
fi
|
||||
if test $libc_cv_asm_underscores = no; then
|
||||
cat >> confdefs.h <<\EOF
|
||||
@@ -1406,9 +1458,9 @@ if test $elf = yes; then
|
||||
libc_cv_asm_weak_directive=yes
|
||||
libc_cv_asm_weakext_directive=no
|
||||
else
|
||||
echo $ac_n "checking for assembler .weak directive""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for assembler .weak directive""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_asm_weak_directive'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.s <<EOF
|
||||
.text
|
||||
@@ -1425,12 +1477,12 @@ EOF
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_asm_weak_directive" 1>&4
|
||||
echo "$ac_t""$libc_cv_asm_weak_directive" 1>&6
|
||||
|
||||
if test $libc_cv_asm_weak_directive = no; then
|
||||
echo $ac_n "checking for assembler .weakext directive""... $ac_c" 1>&4
|
||||
echo $ac_n "checking for assembler .weakext directive""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_asm_weakext_directive'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.s <<EOF
|
||||
.text
|
||||
@@ -1447,7 +1499,7 @@ EOF
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_asm_weakext_directive" 1>&4
|
||||
echo "$ac_t""$libc_cv_asm_weakext_directive" 1>&6
|
||||
|
||||
fi # no .weak
|
||||
fi # not ELF
|
||||
@@ -1464,6 +1516,24 @@ EOF
|
||||
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for ld --no-whole-archive""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_ld_no_whole_archive'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.c <<\EOF
|
||||
main () { exit (0); }
|
||||
EOF
|
||||
if ${CC-cc} $CFLAGS -Wl,--no-whole-archive \
|
||||
-o conftest conftest.c 2>/dev/null; then
|
||||
libc_cv_ld_no_whole_archive=yes
|
||||
else
|
||||
libc_cv_ld_no_whole_archive=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_ld_no_whole_archive" 1>&6
|
||||
|
||||
### End of automated tests.
|
||||
### Now run sysdeps configure fragments.
|
||||
|
||||
@@ -1476,7 +1546,7 @@ libc_link_sources=
|
||||
uname=
|
||||
for dir in $sysnames; do
|
||||
if test -r $sysdep_dir/$dir/configure; then
|
||||
echo "$ac_t""running configure fragment for $dir" 1>&4
|
||||
echo "$ac_t""running configure fragment for $dir" 1>&6
|
||||
. $sysdep_dir/$dir/configure
|
||||
fi
|
||||
|
||||
@@ -1501,9 +1571,9 @@ if test "$uname" = generic; then
|
||||
config_release=`echo $config_os | sed s/$uname_sysname//`
|
||||
fi
|
||||
|
||||
echo $ac_n "checking OS release for uname""... $ac_c" 1>&4
|
||||
echo $ac_n "checking OS release for uname""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_uname_release'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
kernel_release=`echo "$kernel_id" | sed 's/^[^0-9.]*\([0-9.]*\).*$/\1/'`
|
||||
if test x`echo "$config_release" | sed "s/^$kernel_release//"` \
|
||||
@@ -1519,12 +1589,12 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_uname_release" 1>&4
|
||||
echo "$ac_t""$libc_cv_uname_release" 1>&6
|
||||
uname_release="$libc_cv_uname_release"
|
||||
|
||||
echo $ac_n "checking OS version for uname""... $ac_c" 1>&4
|
||||
echo $ac_n "checking OS version for uname""... $ac_c" 1>&6
|
||||
if eval "test \"`echo '$''{'libc_cv_uname_version'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&4
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
kernel_version=`echo "$kernel_id" | sed 's/^[^#]*#\([0-9]*\).*$/\1/'`
|
||||
if test -n "$kernel_version"; then
|
||||
@@ -1534,7 +1604,7 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$ac_t""$libc_cv_uname_version" 1>&4
|
||||
echo "$ac_t""$libc_cv_uname_version" 1>&6
|
||||
uname_version="$libc_cv_uname_version"
|
||||
|
||||
config_uname=config-name.h:config-name.in
|
||||
@@ -1543,7 +1613,7 @@ else
|
||||
config_uname=
|
||||
fi
|
||||
|
||||
echo $ac_n "checking stdio selection""... $ac_c" 1>&4
|
||||
echo $ac_n "checking stdio selection""... $ac_c" 1>&6
|
||||
|
||||
case $stdio in
|
||||
libio) cat >> confdefs.h <<\EOF
|
||||
@@ -1552,7 +1622,7 @@ EOF
|
||||
;;
|
||||
default) stdio=stdio ;;
|
||||
esac
|
||||
echo "$ac_t""$stdio" 1>&4
|
||||
echo "$ac_t""$stdio" 1>&6
|
||||
|
||||
|
||||
if test $gnu_ld = yes; then
|
||||
@@ -1665,7 +1735,7 @@ do
|
||||
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
|
||||
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
|
||||
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
|
||||
echo "$CONFIG_STATUS generated by autoconf version 2.9"
|
||||
echo "$CONFIG_STATUS generated by autoconf version 2.10"
|
||||
exit 0 ;;
|
||||
-help | --help | --hel | --he | --h)
|
||||
echo "\$ac_cs_usage"; exit 0 ;;
|
||||
@@ -1711,19 +1781,23 @@ s%@host_alias@%$host_alias%g
|
||||
s%@host_cpu@%$host_cpu%g
|
||||
s%@host_vendor@%$host_vendor%g
|
||||
s%@host_os@%$host_os%g
|
||||
s%@base_machine@%$base_machine%g
|
||||
s%@sysnames@%$sysnames%g
|
||||
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
|
||||
s%@INSTALL_DATA@%$INSTALL_DATA%g
|
||||
s%@LN_S@%$LN_S%g
|
||||
s%@MSGFMT@%$MSGFMT%g
|
||||
s%@build@%$build%g
|
||||
s%@build_alias@%$build_alias%g
|
||||
s%@build_cpu@%$build_cpu%g
|
||||
s%@build_vendor@%$build_vendor%g
|
||||
s%@build_os@%$build_os%g
|
||||
s%@CC@%$CC%g
|
||||
s%@CPP@%$CPP%g
|
||||
s%@AR@%$AR%g
|
||||
s%@RANLIB@%$RANLIB%g
|
||||
s%@CPP@%$CPP%g
|
||||
s%@libc_cv_have_initfini@%$libc_cv_have_initfini%g
|
||||
s%@libc_cv_ld_no_whole_archive@%$libc_cv_ld_no_whole_archive%g
|
||||
s%@uname_sysname@%$uname_sysname%g
|
||||
s%@uname_release@%$uname_release%g
|
||||
s%@uname_version@%$uname_version%g
|
||||
@@ -1886,6 +1960,12 @@ cat >> $CONFIG_STATUS <<\EOF
|
||||
echo "$ac_file is unchanged"
|
||||
rm -f conftest.h
|
||||
else
|
||||
# Remove last slash and all that follows it. Not all systems have dirname.
|
||||
ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
|
||||
if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
|
||||
# The file is in a subdirectory.
|
||||
test ! -d "$ac_dir" && mkdir "$ac_dir"
|
||||
fi
|
||||
rm -f $ac_file
|
||||
mv conftest.h $ac_file
|
||||
fi
|
||||
|
||||
+43
-26
@@ -1,6 +1,6 @@
|
||||
Dnl Process this file with autoconf to produce a configure script.
|
||||
AC_REVISION([$CVSid$])
|
||||
AC_PREREQ(2.9)dnl dnl Minimum Autoconf version required.
|
||||
AC_PREREQ(2.10)dnl dnl Minimum Autoconf version required.
|
||||
AC_INIT(features.h)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
@@ -34,7 +34,7 @@ esac
|
||||
|
||||
dnl Arguments to specify presence of other packages/features.
|
||||
AC_ARG_WITH(fp, dnl
|
||||
--with-fp if using floating-point hardware,
|
||||
--with-fp if using floating-point hardware [default=yes],
|
||||
with_fp=$withval, with_fp=yes)
|
||||
AC_ARG_WITH(gnu-binutils, dnl
|
||||
--with-gnu-binutils if using GNU binutils (as and ld),
|
||||
@@ -86,18 +86,12 @@ esac
|
||||
case "$host_os" in
|
||||
gnu* | linux* | sysv4* | solaris2*)
|
||||
# These systems always use the ELF format.
|
||||
elf=yes ;;
|
||||
if test "$host_cpu" != alpha; then # Linux/Alpha is not fully ELF yet
|
||||
elf=yes
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Linux/Alpha does not use ELF yet.
|
||||
case "$host_cpu-$host_os" in
|
||||
alpha*-linux*)
|
||||
gnu_ld=no elf=no ;;
|
||||
esac
|
||||
|
||||
# Compute the list of sysdep directories for this configuration.
|
||||
sysdep_dir=$srcdir/sysdeps
|
||||
AC_CACHE_CHECK(sysdep dirs, libc_cv_sysdirs, [dnl
|
||||
machine=$config_machine
|
||||
vendor=$config_vendor
|
||||
os=$config_os
|
||||
@@ -107,20 +101,27 @@ changequote(,)dnl
|
||||
# Expand the configuration machine name into a subdirectory by architecture
|
||||
# type and particular chip.
|
||||
case "$machine" in
|
||||
a29k | am29000) machine=a29k ;;
|
||||
alpha*) machine=alpha/$machine ;;
|
||||
hppa*) machine=hppa/$machine ;;
|
||||
i[345]86) machine=i386/$machine ;;
|
||||
m680?0) machine=m68k/$machine ;;
|
||||
m68k) machine=m68k/m68020 ;;
|
||||
m88???) machine=m88k/$machine ;;
|
||||
m88k) machine=m88k/m88100 ;;
|
||||
mips*) machine=mips/$machine ;;
|
||||
mips64*) machine=mips/mips64/$machine ;;
|
||||
sparc[6789]) machine=sparc/$machine ;;
|
||||
supersparc) machine=sparc/sparc8 ;;
|
||||
a29k | am29000) base_machine=a29k machine=a29k ;;
|
||||
alpha*) base_machine=alpha machine=alpha/$machine ;;
|
||||
hppa*) base_machine=hppa machine=hppa/$machine ;;
|
||||
i[345]86) base_machine=i386 machine=i386/$machine ;;
|
||||
m680?0) base_machine=m68k machine=m68k/$machine ;;
|
||||
m68k) base_machine=m68k machine=m68k/m68020 ;;
|
||||
m88???) base_machine=m88k machine=m88k/$machine ;;
|
||||
m88k) base_machine=m88k machine=m88k/m88100 ;;
|
||||
mips*) base_machine=mips machine=mips/$machine ;;
|
||||
mips64*) base_machine=mips64 machine=mips/mips64/$machine ;;
|
||||
sparc[6789]) base_machine=sparc machine=sparc/$machine ;;
|
||||
supersparc) base_machine=sparc machine=sparc/sparc8 ;;
|
||||
esac
|
||||
changequote([,])dnl
|
||||
AC_SUBST(base_machine)
|
||||
|
||||
# Compute the list of sysdep directories for this configuration.
|
||||
sysdep_dir=$srcdir/sysdeps
|
||||
AC_CACHE_CHECK(sysdep dirs, libc_cv_sysdirs, [dnl
|
||||
dnl We need to use [ and ] for other purposes for a while now.
|
||||
changequote(,)dnl
|
||||
# Make sco3.2v4 become sco3.2.4 and sunos4.1.1_U1 become sunos4.1.1.U1.
|
||||
os="`echo $os | sed 's/\([0-9A-Z]\)[v_]\([0-9A-Z]\)/\1.\2/g'`"
|
||||
|
||||
@@ -293,11 +294,13 @@ if test "$INSTALL" = "${srcdir}/install-sh"; then
|
||||
# The makefiles need to use a different form to find it in $srcdir.
|
||||
INSTALL='$(..)./install-sh'
|
||||
fi
|
||||
AC_PROG_LN_S
|
||||
AC_CHECK_PROGS(MSGFMT, msgfmt gmsgfmt, :)
|
||||
|
||||
AC_CHECK_TOOL(CC, gcc)
|
||||
AC_PROG_CPP
|
||||
AC_CHECK_TOOL(AR, ar)
|
||||
AC_CHECK_TOOL(RANLIB, ranlib, :)
|
||||
AC_PROG_CPP
|
||||
|
||||
AC_CACHE_CHECK(for signed size_t type, libc_cv_signed_size_t, [dnl
|
||||
echo '#include <stddef.h>
|
||||
@@ -400,7 +403,8 @@ fi
|
||||
if test $elf != yes; then
|
||||
AC_CACHE_CHECK(for .init and .fini sections, libc_cv_have_initfini,
|
||||
[AC_TRY_COMPILE(, [asm (".section .init");
|
||||
asm (".section .fini");],
|
||||
asm (".section .fini");
|
||||
asm (".text");],
|
||||
libc_cv_have_initfini=yes,
|
||||
libc_cv_have_initfini=no)])
|
||||
AC_SUBST(libc_cv_have_initfini)dnl
|
||||
@@ -469,6 +473,19 @@ elif test $libc_cv_asm_weakext_directive = yes; then
|
||||
AC_DEFINE(HAVE_ASM_WEAKEXT_DIRECTIVE)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK(for ld --no-whole-archive, libc_cv_ld_no_whole_archive, [dnl
|
||||
cat > conftest.c <<\EOF
|
||||
main () { exit (0); }
|
||||
EOF
|
||||
if ${CC-cc} $CFLAGS -Wl,--no-whole-archive \
|
||||
-o conftest conftest.c 2>/dev/null; then
|
||||
libc_cv_ld_no_whole_archive=yes
|
||||
else
|
||||
libc_cv_ld_no_whole_archive=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
AC_SUBST(libc_cv_ld_no_whole_archive)dnl
|
||||
|
||||
### End of automated tests.
|
||||
### Now run sysdeps configure fragments.
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+2
-1
@@ -27,6 +27,7 @@
|
||||
|
||||
subdir := csu
|
||||
|
||||
routines = init-first
|
||||
csu-dummies = $(filter-out $(start-installed-name),crt1.o Mcrt1.o)
|
||||
extra-objs = start.o gmon-start.o \
|
||||
$(start-installed-name) g$(start-installed-name) \
|
||||
@@ -35,7 +36,7 @@ omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \
|
||||
$(csu-dummies))
|
||||
install-lib = $(start-installed-name) g$(start-installed-name) \
|
||||
$(csu-dummies)
|
||||
distribute = initfini.c
|
||||
distribute = initfini.c gmon-start.c start.c
|
||||
|
||||
all: # Make this the default target; it will be defined in Rules.
|
||||
|
||||
|
||||
+13
-1
@@ -1,5 +1,5 @@
|
||||
/* Special .init and .fini section support.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -98,6 +98,18 @@ _fini (void)
|
||||
Then fetch the .section directive just written and append that
|
||||
to crtn.s-new, followed by the function epilogue. */
|
||||
asm ("\nEOF.crti.fini\
|
||||
\n\
|
||||
cat > /dev/null <<\\EOF.fini.skip");
|
||||
|
||||
{
|
||||
/* Let GCC know that _fini is not a leaf function by having a dummy
|
||||
function call here. We arrange for this call to be omitted from
|
||||
either crt file. */
|
||||
extern void i_am_not_a_leaf (void);
|
||||
i_am_not_a_leaf ();
|
||||
}
|
||||
|
||||
asm ("\nEOF.fini.skip\
|
||||
\n\
|
||||
fgrep .fini crti.s-new >>crtn.s-new\n\
|
||||
cat >> crtn.s-new <<\\EOF.crtn.fini");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+8
-6
@@ -25,11 +25,13 @@ extern const char _nl_C_LC_CTYPE_class32[];
|
||||
extern const char _nl_C_LC_CTYPE_toupper[];
|
||||
extern const char _nl_C_LC_CTYPE_tolower[];
|
||||
extern const char _nl_C_LC_CTYPE_names[];
|
||||
extern const char _nl_C_LC_CTYPE_width[];
|
||||
|
||||
#define b(u,x,o) (((const u int *) _nl_C_LC_CTYPE_##x) + o);
|
||||
#define b(t,x,o) (((const t *) _nl_C_LC_CTYPE_##x) + o);
|
||||
|
||||
const unsigned short int *__ctype_b = b (unsigned short, class, 128);
|
||||
const unsigned int *__ctype32_b = b (unsigned, class32, 0);
|
||||
const int *__ctype_tolower = b (, tolower, 128);
|
||||
const int *__ctype_toupper = b (, toupper, 128);
|
||||
const unsigned int *__ctype_names = b (unsigned, names, 0);
|
||||
const unsigned short int *__ctype_b = b (unsigned short int, class, 128);
|
||||
const unsigned int *__ctype32_b = b (unsigned int, class32, 0);
|
||||
const int *__ctype_tolower = b (int, tolower, 128);
|
||||
const int *__ctype_toupper = b (int, toupper, 128);
|
||||
const unsigned int *__ctype_names = b (unsigned int, names, 0);
|
||||
const unsigned char *__ctype_width = b (unsigned char, width, 0);
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 92, 93, 95, 96 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
|
||||
@@ -13,7 +13,7 @@ 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, 1992 Free Software Foundation, Inc., 675 Mass Ave,
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94";
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ 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, 1992 Free Software Foundation, Inc., 675 Mass Ave,
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+51
-22
@@ -1,6 +1,6 @@
|
||||
# Makefile for elf subdirectory of GNU C Library.
|
||||
|
||||
# Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1995, 1996 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
|
||||
@@ -20,46 +20,66 @@
|
||||
|
||||
subdir := elf
|
||||
|
||||
headers := elf.h libelf.h link.h dlfcn.h
|
||||
routines := init-first
|
||||
headers = elf.h elfclass.h link.h dlfcn.h
|
||||
routines = $(dl-routines) dl-open dl-close dl-symbol dl-support
|
||||
|
||||
extra-libs = libelf libdl
|
||||
libelf-routines := elf_hash
|
||||
libdl-routines := dlopen dlclose dlsym dlerror
|
||||
libdl-inhibit-o = $(filter-out .so,$(object-suffixes)) # Build only shared.
|
||||
# The core dynamic linking functions are in libc for the static and
|
||||
# profiled libraries.
|
||||
dl-routines = $(addprefix dl-,load lookup object reloc deps \
|
||||
runtime error init fini debug)
|
||||
# But they are absent from the shared libc, because that code is in ld.so.
|
||||
elide-routines.so = $(dl-routines) dl-support
|
||||
|
||||
rtld-routines := rtld $(addprefix dl-,minimal load lookup object reloc \
|
||||
runtime sysdep error init fini)
|
||||
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h \
|
||||
# ld.so uses those routines, plus some special stuff for being the program
|
||||
# interpreter and operating independent of libc.
|
||||
rtld-routines := rtld $(dl-routines) dl-sysdep dl-minimal
|
||||
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
|
||||
soinit.c sofini.c ldd.sh.in linux-compat.c
|
||||
|
||||
extra-libs = libdl
|
||||
libdl-routines := dlopen dlclose dlsym dlerror dladdr
|
||||
|
||||
|
||||
all: # Make this the default target; it will be defined in Rules.
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
extra-objs = $(rtld-routines:=.so) soinit.so sofini.so
|
||||
generated = librtld.so
|
||||
generated = librtld.so dl-allobjs.so
|
||||
install-others = $(slibdir)/$(rtld-installed-name)
|
||||
install-bin = ldd
|
||||
|
||||
ifneq (,$(filter linux%,$(config-os)))
|
||||
ifneq (,$(filter linux% linux,$(config-os)))
|
||||
extra-objs += linux-compat.so
|
||||
install-others += $(slibdir)/ld-linux.so.1
|
||||
lib-noranlib: $(objpfx)ld-linux.so.1
|
||||
endif
|
||||
endif
|
||||
|
||||
include ../Rules
|
||||
|
||||
|
||||
ifeq (yes, $(build-shared))
|
||||
# Make sure these things are built in the `make lib' pass so they can be used
|
||||
# to run programs during the `make others' pass.
|
||||
lib-noranlib: $(objpfx)$(rtld-installed-name) \
|
||||
$(addprefix $(objpfx),$(extra-objs))
|
||||
endif
|
||||
|
||||
# Command to link into a larger single relocatable object.
|
||||
reloc-link = $(LINK.o) -nostdlib -nostartfiles -r -o $@
|
||||
|
||||
$(objpfx)dl-allobjs.so: $(rtld-routines:%=$(objpfx)%.so)
|
||||
$(reloc-link) $^
|
||||
|
||||
# Link together the dynamic linker into a single relocatable object.
|
||||
# We use this to produce both the ABI-compliant and Linux-compatible
|
||||
# dynamic linker shared objects below.
|
||||
$(objpfx)librtld.so: $(rtld-routines:%=$(objpfx)%.so) \
|
||||
$(objpfx)librtld.so: $(objpfx)dl-allobjs.so \
|
||||
$(patsubst %,$(common-objpfx)lib%_pic.a,\
|
||||
elf c $(LDLIBS-c.so:-l%=%))
|
||||
$(LINK.o) -nostdlib -nostartfiles -r -o $@ \
|
||||
'-Wl,-(' $^ -lgcc '-Wl,-)'
|
||||
c $(LDLIBS-c.so:-l%=%))
|
||||
$(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)'
|
||||
|
||||
$(objpfx)ld.so: $(objpfx)librtld.so
|
||||
$(rtld-link) -Wl,-soname=$(rtld-installed-name)
|
||||
@@ -71,21 +91,30 @@ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
|
||||
-Wl,-rpath=$(default-rpath) $^
|
||||
endef
|
||||
|
||||
# The dl code in the static libc needs a default library path.
|
||||
CFLAGS-dl-support.c = -D'DEFAULT_RPATH="$(default-rpath)"'
|
||||
|
||||
ifneq (ld.so, $(rtld-installed-name))
|
||||
# Make sure ld-gnu.so.1 exists in the build directory so we can link
|
||||
# against it.
|
||||
$(objpfx)$(rtld-installed-name): $(objpfx)ld.so
|
||||
rm -f $@
|
||||
ln $< $@
|
||||
endif
|
||||
|
||||
# The Linux-compatible dynamic linker shared object is just the same
|
||||
# with one object file of compatibility initialization code added.
|
||||
$(objpfx)ld-linux.so.1: $(objpfx)linux-compat.so
|
||||
|
||||
|
||||
# Specify the dependencies of libdl.so; its commands come from the generic
|
||||
# rule to build a shared library.
|
||||
$(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so
|
||||
$(patsubst %/,cd %;,$(objpfx)) \
|
||||
$(LINK.o) -shared -o $(@:$(objpfx)%=%) \
|
||||
$(LDFLAGS.so) $(LDFLAGS-dl.so) \
|
||||
-Wl,--whole-archive $(^:$(objpfx)%=%)
|
||||
|
||||
$(slibdir)/$(rtld-installed-name): $(objpfx)ld.so; $(do-install-program)
|
||||
$(slibdir)/ld-linux.so.1: $(objpfx)ld-linux.so.1; $(do-install-program)
|
||||
|
||||
$(objpfx)ldd: ldd.sh.in
|
||||
sed 's%@RTLD@%$(libdir)/$(rtld-installed-name)%g' < $< > $@.new
|
||||
$(objpfx)ldd: ldd.sh.in Makefile
|
||||
sed 's%@RTLD@%$(slibdir)/$(rtld-installed-name)%g' < $< > $@.new
|
||||
chmod 555 $@.new
|
||||
mv -f $@.new $@
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/* _dl_close -- Close a shared object opened by `_dl_open'.
|
||||
Copyright (C) 1996 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <link.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
#define LOSE(s) _dl_signal_error (0, map->l_name, s)
|
||||
|
||||
void
|
||||
_dl_close (struct link_map *map)
|
||||
{
|
||||
struct link_map **list;
|
||||
unsigned int i;
|
||||
|
||||
if (map->l_opencount == 0)
|
||||
LOSE ("shared object not open");
|
||||
|
||||
/* Decrement the reference count. */
|
||||
if (--map->l_opencount > 0 || map->l_type != lt_loaded)
|
||||
/* There are still references to this object. Do nothing more. */
|
||||
return;
|
||||
|
||||
/* Notify the debugger we are about to remove some loaded objects. */
|
||||
_r_debug.r_state = RT_DELETE;
|
||||
_dl_debug_state ();
|
||||
|
||||
list = map->l_searchlist;
|
||||
|
||||
/* The search list contains a counted reference to each object it
|
||||
points to, the 0th elt being MAP itself. Decrement the reference
|
||||
counts on all the objects MAP depends on. */
|
||||
for (i = 1; i < map->l_nsearchlist; ++i)
|
||||
--list[i]->l_opencount;
|
||||
|
||||
/* Clear the search list so it doesn't get freed while we are still
|
||||
using it. We have cached it in LIST and will free it when
|
||||
finished. */
|
||||
map->l_searchlist = NULL;
|
||||
|
||||
/* Check each element of the search list to see if all references to
|
||||
it are gone. */
|
||||
for (i = 0; i < map->l_nsearchlist; ++i)
|
||||
{
|
||||
struct link_map *map = list[i];
|
||||
if (map->l_opencount == 0 && map->l_type == lt_loaded)
|
||||
{
|
||||
/* That was the last reference, and this was a dlopen-loaded
|
||||
object. We can unmap it. */
|
||||
const ElfW(Phdr) *ph;
|
||||
|
||||
if (map->l_info[DT_FINI])
|
||||
/* Call its termination function. */
|
||||
(*(void (*) (void)) ((void *) map->l_addr +
|
||||
map->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||
|
||||
if (map->l_global)
|
||||
{
|
||||
/* This object is in the global scope list. Remove it. */
|
||||
struct link_map **tail = _dl_global_scope_end;
|
||||
do
|
||||
--tail;
|
||||
while (*tail != map);
|
||||
--_dl_global_scope_end;
|
||||
memcpy (tail, tail + 1, _dl_global_scope_end - tail);
|
||||
_dl_global_scope_end[0] = NULL;
|
||||
_dl_global_scope_end[1] = NULL;
|
||||
}
|
||||
|
||||
/* Unmap the segments. */
|
||||
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
||||
if (ph->p_type == PT_LOAD)
|
||||
{
|
||||
ElfW(Addr) mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||
ElfW(Addr) mapend = ((ph->p_vaddr + ph->p_memsz
|
||||
+ ph->p_align - 1)
|
||||
& ~(ph->p_align - 1));
|
||||
__munmap ((caddr_t) mapstart, mapend - mapstart);
|
||||
}
|
||||
|
||||
/* Finally, unlink the data structure and free it. */
|
||||
map->l_prev->l_next = map->l_next;
|
||||
if (map->l_next)
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
if (map->l_searchlist)
|
||||
free (map->l_searchlist);
|
||||
free (map);
|
||||
}
|
||||
}
|
||||
|
||||
free (list);
|
||||
|
||||
/* Notify the debugger those objects are finalized and gone. */
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state ();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Communicate dynamic linker state to the debugger at runtime.
|
||||
Copyright (C) 1996 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <link.h>
|
||||
|
||||
/* This structure communicates dl state to the debugger. The debugger
|
||||
normally finds it via the DT_DEBUG entry in the dynamic section, but in
|
||||
a statically-linked program there is no dynamic section for the debugger
|
||||
to examine and it looks for this particular symbol name. */
|
||||
struct r_debug _r_debug;
|
||||
|
||||
|
||||
/* Initialize _r_debug if it has not already been done. The argument is
|
||||
the run-time load address of the dynamic linker, to be put in
|
||||
_r_debug.r_ldbase. Returns the address of _r_debug. */
|
||||
|
||||
struct r_debug *
|
||||
_dl_debug_initialize (ElfW(Addr) ldbase)
|
||||
{
|
||||
if (_r_debug.r_brk == 0)
|
||||
{
|
||||
/* Tell the debugger where to find the map of loaded objects. */
|
||||
_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||
_r_debug.r_ldbase = _dl_rtld_map.l_addr; /* Record our load address. */
|
||||
_r_debug.r_map = _dl_loaded;
|
||||
_r_debug.r_brk = (ElfW(Addr)) &_dl_debug_state;
|
||||
}
|
||||
|
||||
return &_r_debug;
|
||||
}
|
||||
|
||||
|
||||
/* This function exists solely to have a breakpoint set on it by the
|
||||
debugger. The debugger is supposed to find this function's address by
|
||||
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
|
||||
for this particular symbol name in the PT_INTERP file. */
|
||||
void
|
||||
_dl_debug_state (void)
|
||||
{
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* Load the dependencies of a mapped object.
|
||||
Copyright (C) 1996 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <link.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
_dl_map_object_deps (struct link_map *map)
|
||||
{
|
||||
struct list
|
||||
{
|
||||
struct link_map *map;
|
||||
struct list *next;
|
||||
};
|
||||
struct list head, *tailp, *scanp;
|
||||
unsigned int nlist;
|
||||
|
||||
/* Start the search list with one element: MAP itself. */
|
||||
head.map = map;
|
||||
head.next = NULL;
|
||||
nlist = 1;
|
||||
|
||||
|
||||
/* Process each element of the search list, loading each of its immediate
|
||||
dependencies and appending them to the list as we step through it.
|
||||
This produces a flat, ordered list that represents a breadth-first
|
||||
search of the dependency tree. */
|
||||
for (scanp = tailp = &head; scanp; scanp = scanp->next)
|
||||
{
|
||||
struct link_map *l = scanp->map;
|
||||
|
||||
/* We use `l_reserved' as a mark bit to detect objects we have
|
||||
already put in the search list and avoid adding duplicate elements
|
||||
later in the list. */
|
||||
l->l_reserved = 1;
|
||||
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
const char *strtab
|
||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
const ElfW(Dyn) *d;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
/* Map in the needed object. */
|
||||
struct link_map *dep
|
||||
= _dl_map_object (l, strtab + d->d_un.d_val,
|
||||
l->l_type == lt_executable ? lt_library :
|
||||
l->l_type);
|
||||
|
||||
if (dep->l_reserved)
|
||||
/* This object is already in the search list we are
|
||||
building. Don't add a duplicate pointer. Release the
|
||||
reference just added by _dl_map_object. */
|
||||
--dep->l_opencount;
|
||||
else
|
||||
{
|
||||
/* Append DEP to the search list. */
|
||||
tailp->next = alloca (sizeof *tailp);
|
||||
tailp = tailp->next;
|
||||
tailp->map = dep;
|
||||
tailp->next = NULL;
|
||||
++nlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the search list we built in the object. It will be used for
|
||||
searches in the scope of this object. */
|
||||
map->l_searchlist = malloc (nlist * sizeof (struct link_map *));
|
||||
map->l_nsearchlist = nlist;
|
||||
|
||||
nlist = 0;
|
||||
for (scanp = &head; scanp; scanp = scanp->next)
|
||||
{
|
||||
map->l_searchlist[nlist++] = scanp->map;
|
||||
|
||||
/* Now clear all the mark bits we set in the objects on the search list
|
||||
to avoid duplicates, so the next call starts fresh. */
|
||||
scanp->map->l_reserved = 0;
|
||||
}
|
||||
}
|
||||
+41
-10
@@ -1,5 +1,5 @@
|
||||
/* Error handling for runtime dynamic linker.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -20,18 +20,47 @@ Cambridge, MA 02139, USA. */
|
||||
#include <stddef.h>
|
||||
#include <link.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
/* This structure communicates state between _dl_catch_error and
|
||||
_dl_signal_error. */
|
||||
struct catch
|
||||
{
|
||||
const char *errstring, *objname; /* Error detail filled in here. */
|
||||
jmp_buf env; /* longjmp here on error. */
|
||||
};
|
||||
|
||||
/* This points to such a structure during a call to _dl_catch_error.
|
||||
During implicit startup and run-time work for needed shared libraries,
|
||||
this is null. */
|
||||
static struct catch *catch;
|
||||
|
||||
static jmp_buf catch_env;
|
||||
static const char *signalled_errstring, *signalled_objname;
|
||||
|
||||
void
|
||||
_dl_signal_error (int errcode,
|
||||
const char *objname,
|
||||
const char *errstring)
|
||||
{
|
||||
signalled_errstring = errstring ?: "DYNAMIC LINKER BUG!!!";
|
||||
signalled_objname = objname;
|
||||
longjmp (catch_env, errcode ?: -1);
|
||||
if (! errstring)
|
||||
errstring = "DYNAMIC LINKER BUG!!!";
|
||||
|
||||
if (catch)
|
||||
{
|
||||
/* We are inside _dl_catch_error. Return to it. */
|
||||
catch->errstring = errstring;
|
||||
catch->objname = objname;
|
||||
longjmp (catch->env, errcode ?: -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Lossage while resolving the program's own symbols is always fatal. */
|
||||
extern char **_dl_argv; /* Set in rtld.c at startup. */
|
||||
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
|
||||
": error in loading shared libraries\n",
|
||||
objname ?: "", objname ? ": " : "",
|
||||
errstring, errcode ? ": " : "",
|
||||
errcode ? strerror (errcode) : "", "\n", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
@@ -40,18 +69,20 @@ _dl_catch_error (const char **errstring,
|
||||
void (*operate) (void))
|
||||
{
|
||||
int errcode;
|
||||
struct catch c = { errstring: NULL, objname: NULL };
|
||||
|
||||
signalled_errstring = signalled_objname = NULL;
|
||||
errcode = setjmp (catch_env);
|
||||
errcode = setjmp (c.env);
|
||||
if (errcode == 0)
|
||||
{
|
||||
catch = &c;
|
||||
(*operate) ();
|
||||
catch = NULL;
|
||||
*errstring = *objname = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We get here only if we longjmp'd out of OPERATE. */
|
||||
*errstring = signalled_errstring;
|
||||
*objname = signalled_objname;
|
||||
*errstring = c.errstring;
|
||||
*objname = c.objname;
|
||||
return errcode == -1 ? 0 : errcode;
|
||||
}
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/* Call the termination functions of loaded shared objects.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -26,5 +26,9 @@ _dl_fini (void)
|
||||
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (l->l_init_called && l->l_info[DT_FINI])
|
||||
(*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||
{
|
||||
(*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||
/* Make sure nothing happens if we are called twice. */
|
||||
l->l_init_called = 0;
|
||||
}
|
||||
}
|
||||
|
||||
+25
-40
@@ -1,5 +1,5 @@
|
||||
/* Return the next shared object initializer function not yet run.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -21,45 +21,35 @@ Cambridge, MA 02139, USA. */
|
||||
#include <link.h>
|
||||
|
||||
|
||||
Elf32_Addr
|
||||
_dl_init_next (void)
|
||||
{
|
||||
struct link_map *l;
|
||||
Elf32_Addr init;
|
||||
/* Run initializers for MAP and its dependencies, in inverse dependency
|
||||
order (that is, leaf nodes first). */
|
||||
|
||||
Elf32_Addr next_init (struct link_map *l)
|
||||
ElfW(Addr)
|
||||
_dl_init_next (struct link_map *map)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* The search list for symbol lookup is a flat list in top-down
|
||||
dependency order, so processing that list from back to front gets us
|
||||
breadth-first leaf-to-root order. */
|
||||
|
||||
i = map->l_nsearchlist;
|
||||
while (i-- > 0)
|
||||
{
|
||||
struct link_map *l = map->l_searchlist[i];
|
||||
|
||||
if (l->l_init_called)
|
||||
/* This object is all done. */
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
if (l->l_init_running)
|
||||
{
|
||||
/* This object's initializer was just running.
|
||||
Now mark it as having run, so this object
|
||||
will be skipped in the future. */
|
||||
l->l_init_called = 1;
|
||||
l->l_init_running = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
/* Find each dependency in order, and see if it
|
||||
needs to run an initializer. */
|
||||
const char *strtab
|
||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
const Elf32_Dyn *d;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
struct link_map *needed
|
||||
= _dl_map_object (l, strtab + d->d_un.d_val);
|
||||
Elf32_Addr init;
|
||||
--needed->l_opencount;
|
||||
init = next_init (needed); /* Recurse on this dependency. */
|
||||
if (init != 0)
|
||||
return init;
|
||||
}
|
||||
l->l_init_called = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l->l_info[DT_INIT] &&
|
||||
@@ -73,17 +63,12 @@ _dl_init_next (void)
|
||||
/* No initializer for this object.
|
||||
Mark it so we will skip it in the future. */
|
||||
l->l_init_called = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for the first initializer not yet called. */
|
||||
l = _dl_loaded;
|
||||
do
|
||||
{
|
||||
init = next_init (l);
|
||||
l = l->l_next;
|
||||
}
|
||||
while (init == 0 && l);
|
||||
|
||||
return init;
|
||||
/* Notify the debugger all new objects are now ready to go. */
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+347
-293
@@ -60,8 +60,312 @@ Cambridge, MA 02139, USA. */
|
||||
#define STRING(x) #x
|
||||
|
||||
int _dl_zerofd = -1;
|
||||
size_t _dl_pagesize;
|
||||
|
||||
|
||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||
opened on FD. */
|
||||
|
||||
struct link_map *
|
||||
_dl_map_object_from_fd (const char *name, int fd, char *realname,
|
||||
struct link_map *loader, int l_type)
|
||||
{
|
||||
struct link_map *l;
|
||||
void *file_mapping = NULL;
|
||||
size_t mapping_size = 0;
|
||||
|
||||
#define LOSE(s) lose (0, (s))
|
||||
void lose (int code, const char *msg)
|
||||
{
|
||||
(void) __close (fd);
|
||||
if (file_mapping)
|
||||
__munmap (file_mapping, mapping_size);
|
||||
if (l)
|
||||
{
|
||||
/* Remove the stillborn object from the list and free it. */
|
||||
if (l->l_prev)
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
free (l);
|
||||
}
|
||||
free (realname);
|
||||
_dl_signal_error (code, name, msg);
|
||||
}
|
||||
|
||||
inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len,
|
||||
int prot, int fixed, off_t offset)
|
||||
{
|
||||
caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot,
|
||||
fixed|MAP_COPY|MAP_FILE,
|
||||
fd, offset);
|
||||
if (mapat == (caddr_t) -1)
|
||||
lose (errno, "failed to map segment from shared object");
|
||||
return mapat;
|
||||
}
|
||||
|
||||
/* Make sure LOCATION is mapped in. */
|
||||
void *map (off_t location, size_t size)
|
||||
{
|
||||
if ((off_t) mapping_size <= location + (off_t) size)
|
||||
{
|
||||
void *result;
|
||||
if (file_mapping)
|
||||
__munmap (file_mapping, mapping_size);
|
||||
mapping_size = (location + size + 1 + _dl_pagesize - 1);
|
||||
mapping_size &= ~(_dl_pagesize - 1);
|
||||
result = __mmap (file_mapping, mapping_size, PROT_READ,
|
||||
MAP_COPY|MAP_FILE, fd, 0);
|
||||
if (result == (void *) -1)
|
||||
lose (errno, "cannot map file data");
|
||||
file_mapping = result;
|
||||
}
|
||||
return file_mapping + location;
|
||||
}
|
||||
|
||||
const ElfW(Ehdr) *header;
|
||||
const ElfW(Phdr) *phdr;
|
||||
const ElfW(Phdr) *ph;
|
||||
int type;
|
||||
|
||||
/* Look again to see if the real name matched another already loaded. */
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (! strcmp (realname, l->l_name))
|
||||
{
|
||||
/* The object is already loaded.
|
||||
Just bump its reference count and return it. */
|
||||
__close (fd);
|
||||
free (realname);
|
||||
++l->l_opencount;
|
||||
return l;
|
||||
}
|
||||
|
||||
if (_dl_pagesize == 0)
|
||||
_dl_pagesize = __getpagesize ();
|
||||
|
||||
/* Map in the first page to read the header. */
|
||||
header = map (0, sizeof *header);
|
||||
|
||||
/* Check the header for basic validity. */
|
||||
if (*(Elf32_Word *) &header->e_ident !=
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
((ELFMAG0 << (EI_MAG0 * 8)) |
|
||||
(ELFMAG1 << (EI_MAG1 * 8)) |
|
||||
(ELFMAG2 << (EI_MAG2 * 8)) |
|
||||
(ELFMAG3 << (EI_MAG3 * 8)))
|
||||
#else
|
||||
((ELFMAG0 << (EI_MAG3 * 8)) |
|
||||
(ELFMAG1 << (EI_MAG2 * 8)) |
|
||||
(ELFMAG2 << (EI_MAG1 * 8)) |
|
||||
(ELFMAG3 << (EI_MAG0 * 8)))
|
||||
#endif
|
||||
)
|
||||
LOSE ("invalid ELF header");
|
||||
#define ELF32_CLASS ELFCLASS32
|
||||
#define ELF64_CLASS ELFCLASS64
|
||||
if (header->e_ident[EI_CLASS] != ELFW(CLASS))
|
||||
LOSE ("ELF file class not " STRING(__ELF_WORDSIZE) "-bit");
|
||||
if (header->e_ident[EI_DATA] != byteorder)
|
||||
LOSE ("ELF file data encoding not " byteorder_name);
|
||||
if (header->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
LOSE ("ELF file version ident not " STRING(EV_CURRENT));
|
||||
if (header->e_version != EV_CURRENT)
|
||||
LOSE ("ELF file version not " STRING(EV_CURRENT));
|
||||
if (! elf_machine_matches_host (header->e_machine))
|
||||
LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
|
||||
if (header->e_phentsize != sizeof (ElfW(Phdr)))
|
||||
LOSE ("ELF file's phentsize not the expected size");
|
||||
|
||||
if (_dl_zerofd == -1)
|
||||
{
|
||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||
if (_dl_zerofd == -1)
|
||||
{
|
||||
__close (fd);
|
||||
_dl_signal_error (errno, NULL, "cannot open zero fill device");
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter the new object in the list of loaded objects. */
|
||||
l = _dl_new_object (realname, name, l_type);
|
||||
if (! l)
|
||||
lose (ENOMEM, "cannot create shared object descriptor");
|
||||
l->l_opencount = 1;
|
||||
l->l_loader = loader;
|
||||
|
||||
/* Extract the remaining details we need from the ELF header
|
||||
and then map in the program header table. */
|
||||
l->l_entry = header->e_entry;
|
||||
type = header->e_type;
|
||||
l->l_phnum = header->e_phnum;
|
||||
phdr = map (header->e_phoff, l->l_phnum * sizeof (ElfW(Phdr)));
|
||||
|
||||
{
|
||||
/* Scan the program header table, collecting its load commands. */
|
||||
struct loadcmd
|
||||
{
|
||||
ElfW(Addr) mapstart, mapend, dataend, allocend;
|
||||
off_t mapoff;
|
||||
int prot;
|
||||
} loadcmds[l->l_phnum], *c;
|
||||
size_t nloadcmds = 0;
|
||||
|
||||
l->l_ld = 0;
|
||||
l->l_phdr = 0;
|
||||
l->l_addr = 0;
|
||||
for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
/* These entries tell us where to find things once the file's
|
||||
segments are mapped in. We record the addresses it says
|
||||
verbatim, and later correct for the run-time load address. */
|
||||
case PT_DYNAMIC:
|
||||
l->l_ld = (void *) ph->p_vaddr;
|
||||
break;
|
||||
case PT_PHDR:
|
||||
l->l_phdr = (void *) ph->p_vaddr;
|
||||
break;
|
||||
|
||||
case PT_LOAD:
|
||||
/* A load command tells us to map in part of the file.
|
||||
We record the load commands and process them all later. */
|
||||
if (ph->p_align % _dl_pagesize != 0)
|
||||
LOSE ("ELF load command alignment not page-aligned");
|
||||
if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
|
||||
LOSE ("ELF load command address/offset not properly aligned");
|
||||
{
|
||||
struct loadcmd *c = &loadcmds[nloadcmds++];
|
||||
c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||
c->mapend = ((ph->p_vaddr + ph->p_filesz + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1));
|
||||
c->dataend = ph->p_vaddr + ph->p_filesz;
|
||||
c->allocend = ph->p_vaddr + ph->p_memsz;
|
||||
c->mapoff = ph->p_offset & ~(ph->p_align - 1);
|
||||
c->prot = 0;
|
||||
if (ph->p_flags & PF_R)
|
||||
c->prot |= PROT_READ;
|
||||
if (ph->p_flags & PF_W)
|
||||
c->prot |= PROT_WRITE;
|
||||
if (ph->p_flags & PF_X)
|
||||
c->prot |= PROT_EXEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are done reading the file's headers now. Unmap them. */
|
||||
__munmap (file_mapping, mapping_size);
|
||||
|
||||
/* Now process the load commands and map segments into memory. */
|
||||
c = loadcmds;
|
||||
|
||||
if (type == ET_DYN || type == ET_REL)
|
||||
{
|
||||
/* This is a position-independent shared object. We can let the
|
||||
kernel map it anywhere it likes, but we must have space for all
|
||||
the segments in their specified positions relative to the first.
|
||||
So we map the first segment without MAP_FIXED, but with its
|
||||
extent increased to cover all the segments. Then we remove
|
||||
access from excess portion, and there is known sufficient space
|
||||
there to remap from the later segments. */
|
||||
caddr_t mapat;
|
||||
mapat = map_segment (c->mapstart,
|
||||
loadcmds[nloadcmds - 1].allocend - c->mapstart,
|
||||
c->prot, 0, c->mapoff);
|
||||
l->l_addr = (ElfW(Addr)) mapat - c->mapstart;
|
||||
|
||||
/* Change protection on the excess portion to disallow all access;
|
||||
the portions we do not remap later will be inaccessible as if
|
||||
unallocated. Then jump into the normal segment-mapping loop to
|
||||
handle the portion of the segment past the end of the file
|
||||
mapping. */
|
||||
__mprotect (mapat + c->mapend,
|
||||
loadcmds[nloadcmds - 1].allocend - c->mapend,
|
||||
0);
|
||||
goto postmap;
|
||||
}
|
||||
|
||||
while (c < &loadcmds[nloadcmds])
|
||||
{
|
||||
if (c->mapend > c->mapstart)
|
||||
/* Map the segment contents from the file. */
|
||||
map_segment (l->l_addr + c->mapstart, c->mapend - c->mapstart,
|
||||
c->prot, MAP_FIXED, c->mapoff);
|
||||
|
||||
postmap:
|
||||
if (c->allocend > c->dataend)
|
||||
{
|
||||
/* Extra zero pages should appear at the end of this segment,
|
||||
after the data mapped from the file. */
|
||||
ElfW(Addr) zero, zeroend, zeropage;
|
||||
|
||||
zero = l->l_addr + c->dataend;
|
||||
zeroend = l->l_addr + c->allocend;
|
||||
zeropage = (zero + _dl_pagesize - 1) & ~(_dl_pagesize - 1);
|
||||
|
||||
if (zeroend < zeropage)
|
||||
/* All the extra data is in the last page of the segment.
|
||||
We can just zero it. */
|
||||
zeropage = zeroend;
|
||||
|
||||
if (zeropage > zero)
|
||||
{
|
||||
/* Zero the final part of the last page of the segment. */
|
||||
if ((c->prot & PROT_WRITE) == 0)
|
||||
{
|
||||
/* Dag nab it. */
|
||||
if (__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
|
||||
_dl_pagesize, c->prot|PROT_WRITE) < 0)
|
||||
lose (errno, "cannot change memory protections");
|
||||
}
|
||||
memset ((void *) zero, 0, zeropage - zero);
|
||||
if ((c->prot & PROT_WRITE) == 0)
|
||||
__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
|
||||
_dl_pagesize, c->prot);
|
||||
}
|
||||
|
||||
if (zeroend > zeropage)
|
||||
{
|
||||
/* Map the remaining zero pages in from the zero fill FD. */
|
||||
caddr_t mapat;
|
||||
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
|
||||
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
||||
_dl_zerofd, 0);
|
||||
if (mapat == (caddr_t) -1)
|
||||
lose (errno, "cannot map zero-fill pages");
|
||||
}
|
||||
}
|
||||
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are done mapping in the file. We no longer need the descriptor. */
|
||||
__close (fd);
|
||||
|
||||
if (l->l_type == lt_library && type == ET_EXEC)
|
||||
l->l_type = lt_executable;
|
||||
|
||||
if (l->l_ld == 0)
|
||||
{
|
||||
if (type == ET_DYN)
|
||||
LOSE ("object file has no dynamic section");
|
||||
}
|
||||
else
|
||||
(ElfW(Addr)) l->l_ld += l->l_addr;
|
||||
|
||||
if (l->l_phdr == 0)
|
||||
l->l_phdr = (void *) ((const ElfW(Ehdr) *) l->l_addr)->e_phoff;
|
||||
(ElfW(Addr)) l->l_phdr += l->l_addr;
|
||||
|
||||
l->l_entry += l->l_addr;
|
||||
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
if (l->l_info[DT_HASH])
|
||||
_dl_setup_hash (l);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Try to open NAME in one of the directories in DIRPATH.
|
||||
Return the fd, or -1. If successful, fill in *REALNAME
|
||||
with the malloc'd full directory name. */
|
||||
@@ -82,31 +386,48 @@ open_path (const char *name, size_t namelen,
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = alloca (strlen (dirpath) + 1 + namelen);
|
||||
buf = __alloca (strlen (dirpath) + 1 + namelen);
|
||||
do
|
||||
{
|
||||
size_t buflen;
|
||||
|
||||
dirpath = p;
|
||||
p = strpbrk (dirpath, ":;");
|
||||
if (p == NULL)
|
||||
p = strchr (dirpath, '\0');
|
||||
|
||||
if (p == dirpath)
|
||||
/* Two adjacent colons, or a colon at the beginning or the end of
|
||||
the path means to search the current directory. */
|
||||
(void) memcpy (buf, name, namelen);
|
||||
{
|
||||
/* Two adjacent colons, or a colon at the beginning or the end of
|
||||
the path means to search the current directory. */
|
||||
(void) memcpy (buf, name, namelen);
|
||||
buflen = namelen;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Construct the pathname to try. */
|
||||
(void) memcpy (buf, dirpath, p - dirpath);
|
||||
buf[p - dirpath] = '/';
|
||||
(void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
|
||||
buflen = p - dirpath + 1 + namelen;
|
||||
}
|
||||
|
||||
fd = open (buf, O_RDONLY);
|
||||
fd = __open (buf, O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
*realname = strdup (buf);
|
||||
return fd;
|
||||
*realname = malloc (buflen);
|
||||
if (*realname)
|
||||
{
|
||||
memcpy (*realname, buf, buflen);
|
||||
return fd;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No memory for the name, we certainly won't be able
|
||||
to load and link it. */
|
||||
__close (fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (errno != ENOENT && errno != EACCES)
|
||||
/* The file exists and is readable, but something went wrong. */
|
||||
@@ -117,11 +438,10 @@ open_path (const char *name, size_t namelen,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Map in the shared object file NAME. */
|
||||
|
||||
struct link_map *
|
||||
_dl_map_object (struct link_map *loader, const char *name)
|
||||
_dl_map_object (struct link_map *loader, const char *name, int type)
|
||||
{
|
||||
int fd;
|
||||
char *realname;
|
||||
@@ -149,10 +469,11 @@ _dl_map_object (struct link_map *loader, const char *name)
|
||||
}
|
||||
|
||||
fd = -1;
|
||||
if (loader && loader->l_info[DT_RPATH])
|
||||
trypath ((const char *) (loader->l_addr +
|
||||
loader->l_info[DT_STRTAB]->d_un.d_ptr +
|
||||
loader->l_info[DT_RPATH]->d_un.d_val));
|
||||
for (l = loader; l; l = l->l_loader)
|
||||
if (l && l->l_info[DT_RPATH])
|
||||
trypath ((const char *) (l->l_addr +
|
||||
l->l_info[DT_STRTAB]->d_un.d_ptr +
|
||||
l->l_info[DT_RPATH]->d_un.d_val));
|
||||
if (fd == -1 && ! _dl_secure)
|
||||
trypath (getenv ("LD_LIBRARY_PATH"));
|
||||
if (fd == -1)
|
||||
@@ -163,290 +484,23 @@ _dl_map_object (struct link_map *loader, const char *name)
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = open (name, O_RDONLY);
|
||||
fd = __open (name, O_RDONLY);
|
||||
if (fd != -1)
|
||||
realname = strdup (name);
|
||||
{
|
||||
size_t len = strlen (name) + 1;
|
||||
realname = malloc (len);
|
||||
if (realname)
|
||||
memcpy (realname, name, len);
|
||||
else
|
||||
{
|
||||
__close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == -1)
|
||||
_dl_signal_error (errno, name, "cannot open shared object file");
|
||||
|
||||
return _dl_map_object_from_fd (name, fd, realname);
|
||||
}
|
||||
|
||||
|
||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||
opened on FD. */
|
||||
|
||||
struct link_map *
|
||||
_dl_map_object_from_fd (const char *name, int fd, char *realname)
|
||||
{
|
||||
struct link_map *l = NULL;
|
||||
const size_t pagesize = getpagesize ();
|
||||
void *file_mapping = NULL;
|
||||
size_t mapping_size = 0;
|
||||
|
||||
#define LOSE(s) lose (0, (s))
|
||||
void lose (int code, const char *msg)
|
||||
{
|
||||
(void) close (fd);
|
||||
if (file_mapping)
|
||||
munmap (file_mapping, mapping_size);
|
||||
_dl_signal_error (code, l ? l->l_name : name, msg);
|
||||
}
|
||||
|
||||
inline caddr_t map_segment (Elf32_Addr mapstart, size_t len,
|
||||
int prot, int fixed, off_t offset)
|
||||
{
|
||||
caddr_t mapat = mmap ((caddr_t) mapstart, len, prot,
|
||||
fixed|MAP_COPY|MAP_FILE,
|
||||
fd, offset);
|
||||
if (mapat == (caddr_t) -1)
|
||||
lose (errno, "failed to map segment from shared object");
|
||||
return mapat;
|
||||
}
|
||||
|
||||
/* Make sure LOCATION is mapped in. */
|
||||
void *map (off_t location, size_t size)
|
||||
{
|
||||
if ((off_t) mapping_size <= location + (off_t) size)
|
||||
{
|
||||
void *result;
|
||||
if (file_mapping)
|
||||
munmap (file_mapping, mapping_size);
|
||||
mapping_size = (location + size + 1 + pagesize - 1);
|
||||
mapping_size &= ~(pagesize - 1);
|
||||
result = mmap (file_mapping, mapping_size, PROT_READ,
|
||||
MAP_COPY|MAP_FILE, fd, 0);
|
||||
if (result == (void *) -1)
|
||||
lose (errno, "cannot map file data");
|
||||
file_mapping = result;
|
||||
}
|
||||
return file_mapping + location;
|
||||
}
|
||||
|
||||
const Elf32_Ehdr *header;
|
||||
const Elf32_Phdr *phdr;
|
||||
const Elf32_Phdr *ph;
|
||||
int type;
|
||||
|
||||
/* Look again to see if the real name matched another already loaded. */
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (! strcmp (realname, l->l_name))
|
||||
{
|
||||
/* The object is already loaded.
|
||||
Just bump its reference count and return it. */
|
||||
close (fd);
|
||||
free (realname);
|
||||
++l->l_opencount;
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Map in the first page to read the header. */
|
||||
header = map (0, sizeof *header);
|
||||
|
||||
/* Check the header for basic validity. */
|
||||
if (*(Elf32_Word *) &header->e_ident !=
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
((ELFMAG0 << (EI_MAG0 * 8)) |
|
||||
(ELFMAG1 << (EI_MAG1 * 8)) |
|
||||
(ELFMAG2 << (EI_MAG2 * 8)) |
|
||||
(ELFMAG3 << (EI_MAG3 * 8)))
|
||||
#else
|
||||
((ELFMAG0 << (EI_MAG3 * 8)) |
|
||||
(ELFMAG1 << (EI_MAG2 * 8)) |
|
||||
(ELFMAG2 << (EI_MAG1 * 8)) |
|
||||
(ELFMAG3 << (EI_MAG0 * 8)))
|
||||
#endif
|
||||
)
|
||||
LOSE ("invalid ELF header");
|
||||
if (header->e_ident[EI_CLASS] != ELFCLASS32)
|
||||
LOSE ("ELF file class not 32-bit");
|
||||
if (header->e_ident[EI_DATA] != byteorder)
|
||||
LOSE ("ELF file data encoding not " byteorder_name);
|
||||
if (header->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
LOSE ("ELF file version ident not " STRING(EV_CURRENT));
|
||||
if (header->e_version != EV_CURRENT)
|
||||
LOSE ("ELF file version not " STRING(EV_CURRENT));
|
||||
if (! elf_machine_matches_host (header->e_machine))
|
||||
LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
|
||||
if (header->e_phentsize != sizeof (Elf32_Phdr))
|
||||
LOSE ("ELF file's phentsize not the expected size");
|
||||
|
||||
/* Enter the new object in the list of loaded objects. */
|
||||
l = _dl_new_object (realname, name, lt_loaded);
|
||||
l->l_opencount = 1;
|
||||
|
||||
if (_dl_zerofd == -1)
|
||||
{
|
||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||
if (_dl_zerofd == -1)
|
||||
_dl_signal_error (errno, NULL, "cannot open zero fill device");
|
||||
}
|
||||
|
||||
/* Extract the remaining details we need from the ELF header
|
||||
and then map in the program header table. */
|
||||
l->l_entry = header->e_entry;
|
||||
type = header->e_type;
|
||||
l->l_phnum = header->e_phnum;
|
||||
phdr = map (header->e_phoff, l->l_phnum * sizeof (Elf32_Phdr));
|
||||
|
||||
{
|
||||
/* Scan the program header table, collecting its load commands. */
|
||||
struct loadcmd
|
||||
{
|
||||
Elf32_Addr mapstart, mapend, dataend, allocend;
|
||||
off_t mapoff;
|
||||
int prot;
|
||||
} loadcmds[l->l_phnum], *c;
|
||||
size_t nloadcmds = 0;
|
||||
|
||||
l->l_ld = 0;
|
||||
l->l_phdr = 0;
|
||||
l->l_addr = 0;
|
||||
for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
/* These entries tell us where to find things once the file's
|
||||
segments are mapped in. We record the addresses it says
|
||||
verbatim, and later correct for the run-time load address. */
|
||||
case PT_DYNAMIC:
|
||||
l->l_ld = (void *) ph->p_vaddr;
|
||||
break;
|
||||
case PT_PHDR:
|
||||
l->l_phdr = (void *) ph->p_vaddr;
|
||||
break;
|
||||
|
||||
case PT_LOAD:
|
||||
/* A load command tells us to map in part of the file.
|
||||
We record the load commands and process them all later. */
|
||||
if (ph->p_align % pagesize != 0)
|
||||
LOSE ("ELF load command alignment not page-aligned");
|
||||
if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
|
||||
LOSE ("ELF load command address/offset not properly aligned");
|
||||
{
|
||||
struct loadcmd *c = &loadcmds[nloadcmds++];
|
||||
c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||
c->mapend = ((ph->p_vaddr + ph->p_filesz + pagesize - 1)
|
||||
& ~(pagesize - 1));
|
||||
c->dataend = ph->p_vaddr + ph->p_filesz;
|
||||
c->allocend = ph->p_vaddr + ph->p_memsz;
|
||||
c->mapoff = ph->p_offset & ~(ph->p_align - 1);
|
||||
c->prot = 0;
|
||||
if (ph->p_flags & PF_R)
|
||||
c->prot |= PROT_READ;
|
||||
if (ph->p_flags & PF_W)
|
||||
c->prot |= PROT_WRITE;
|
||||
if (ph->p_flags & PF_X)
|
||||
c->prot |= PROT_EXEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are done reading the file's headers now. Unmap them. */
|
||||
munmap (file_mapping, mapping_size);
|
||||
|
||||
/* Now process the load commands and map segments into memory. */
|
||||
c = loadcmds;
|
||||
|
||||
if (type == ET_DYN || type == ET_REL)
|
||||
{
|
||||
/* This is a position-independent shared object. We can let the
|
||||
kernel map it anywhere it likes, but we must have space for all
|
||||
the segments in their specified positions relative to the first.
|
||||
So we map the first segment without MAP_FIXED, but with its
|
||||
extent increased to cover all the segments. Then we remove
|
||||
access from excess portion, and there is known sufficient space
|
||||
there to remap from the later segments. */
|
||||
caddr_t mapat;
|
||||
mapat = map_segment (c->mapstart,
|
||||
loadcmds[nloadcmds - 1].allocend - c->mapstart,
|
||||
c->prot, 0, c->mapoff);
|
||||
l->l_addr = (Elf32_Addr) mapat - c->mapstart;
|
||||
|
||||
/* Change protection on the excess portion to disallow all access;
|
||||
the portions we do not remap later will be inaccessible as if
|
||||
unallocated. Then jump into the normal segment-mapping loop to
|
||||
handle the portion of the segment past the end of the file
|
||||
mapping. */
|
||||
mprotect (mapat + c->mapend,
|
||||
loadcmds[nloadcmds - 1].allocend - c->mapend,
|
||||
0);
|
||||
goto postmap;
|
||||
}
|
||||
|
||||
while (c < &loadcmds[nloadcmds])
|
||||
{
|
||||
if (c->mapend > c->mapstart)
|
||||
/* Map the segment contents from the file. */
|
||||
map_segment (l->l_addr + c->mapstart, c->mapend - c->mapstart,
|
||||
c->prot, MAP_FIXED, c->mapoff);
|
||||
|
||||
postmap:
|
||||
if (c->allocend > c->dataend)
|
||||
{
|
||||
/* Extra zero pages should appear at the end of this segment,
|
||||
after the data mapped from the file. */
|
||||
Elf32_Addr zero, zeroend, zeropage;
|
||||
|
||||
zero = l->l_addr + c->dataend;
|
||||
zeroend = l->l_addr + c->allocend;
|
||||
zeropage = (zero + pagesize - 1) & ~(pagesize - 1);
|
||||
|
||||
if (zeroend < zeropage)
|
||||
/* All the extra data is in the last page of the segment.
|
||||
We can just zero it. */
|
||||
zeropage = zeroend;
|
||||
|
||||
if (zeropage > zero)
|
||||
{
|
||||
/* Zero the final part of the last page of the segment. */
|
||||
if ((c->prot & PROT_WRITE) == 0)
|
||||
{
|
||||
/* Dag nab it. */
|
||||
if (mprotect ((caddr_t) (zero & ~(pagesize - 1)),
|
||||
pagesize, c->prot|PROT_WRITE) < 0)
|
||||
lose (errno, "cannot change memory protections");
|
||||
}
|
||||
memset ((void *) zero, 0, zeropage - zero);
|
||||
if ((c->prot & PROT_WRITE) == 0)
|
||||
mprotect ((caddr_t) (zero & ~(pagesize - 1)),
|
||||
pagesize, c->prot);
|
||||
}
|
||||
|
||||
if (zeroend > zeropage)
|
||||
{
|
||||
/* Map the remaining zero pages in from the zero fill FD. */
|
||||
caddr_t mapat;
|
||||
mapat = mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
|
||||
MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
||||
_dl_zerofd, 0);
|
||||
if (mapat == (caddr_t) -1)
|
||||
lose (errno, "cannot map zero-fill pages");
|
||||
}
|
||||
}
|
||||
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
l->l_type = type == ET_EXEC ? lt_executable : lt_library;
|
||||
|
||||
if (l->l_ld == 0)
|
||||
{
|
||||
if (type == ET_DYN)
|
||||
LOSE ("object file has no dynamic section");
|
||||
}
|
||||
else
|
||||
(Elf32_Addr) l->l_ld += l->l_addr;
|
||||
|
||||
if (l->l_phdr == 0)
|
||||
l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
|
||||
(Elf32_Addr) l->l_phdr += l->l_addr;
|
||||
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
if (l->l_info[DT_HASH])
|
||||
_dl_setup_hash (l);
|
||||
|
||||
return l;
|
||||
return _dl_map_object_from_fd (name, fd, realname, loader, type);
|
||||
}
|
||||
|
||||
+109
-77
@@ -1,5 +1,5 @@
|
||||
/* Look up a symbol in the loaded objects.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -18,94 +18,126 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <libelf.h>
|
||||
#include <link.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Search loaded objects' symbol tables for a definition of
|
||||
the symbol UNDEF_NAME. If NOSELF is nonzero, then *REF
|
||||
cannot satisfy the reference itself; some different binding
|
||||
must be found. */
|
||||
|
||||
Elf32_Addr
|
||||
_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
||||
struct link_map *symbol_scope,
|
||||
const char *reference_name,
|
||||
int noself)
|
||||
/* This is the hashing function specified by the ELF ABI. */
|
||||
static inline unsigned
|
||||
_dl_elf_hash (const char *name)
|
||||
{
|
||||
unsigned long int hash = elf_hash (undef_name);
|
||||
struct link_map *map;
|
||||
struct
|
||||
unsigned long int hash = 0;
|
||||
while (*name != '\0')
|
||||
{
|
||||
Elf32_Addr a;
|
||||
const Elf32_Sym *s;
|
||||
} weak_value = { 0, NULL };
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
for (map = symbol_scope; map; map = map->l_next)
|
||||
{
|
||||
const Elf32_Sym *symtab;
|
||||
const char *strtab;
|
||||
Elf32_Word symidx;
|
||||
|
||||
symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
|
||||
/* Search the appropriate hash bucket in this object's symbol table
|
||||
for a definition for the same symbol name. */
|
||||
for (symidx = map->l_buckets[hash % map->l_nbuckets];
|
||||
symidx != STN_UNDEF;
|
||||
symidx = map->l_chain[symidx])
|
||||
unsigned long int hi;
|
||||
hash = (hash << 4) + *name++;
|
||||
hi = hash & 0xf0000000;
|
||||
if (hi != 0)
|
||||
{
|
||||
const Elf32_Sym *sym = &symtab[symidx];
|
||||
|
||||
if (sym->st_value == 0 || /* No value. */
|
||||
sym->st_shndx == SHN_UNDEF || /* PLT entry. */
|
||||
(noself && sym == *ref)) /* The reference can't define it. */
|
||||
continue;
|
||||
|
||||
switch (ELF32_ST_TYPE (sym->st_info))
|
||||
{
|
||||
case STT_NOTYPE:
|
||||
case STT_FUNC:
|
||||
case STT_OBJECT:
|
||||
break;
|
||||
default:
|
||||
/* Not a code/data definition. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
|
||||
/* Not the symbol we are looking for. */
|
||||
continue;
|
||||
|
||||
switch (ELF32_ST_BIND (sym->st_info))
|
||||
{
|
||||
case STB_GLOBAL:
|
||||
/* Global definition. Just what we need. */
|
||||
*ref = sym;
|
||||
return map->l_addr;
|
||||
case STB_WEAK:
|
||||
/* Weak definition. Use this value if we don't find another. */
|
||||
if (! weak_value.s)
|
||||
{
|
||||
weak_value.s = sym;
|
||||
weak_value.a = map->l_addr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Local symbols are ignored. */
|
||||
break;
|
||||
}
|
||||
hash ^= hi >> 24;
|
||||
/* The ELF ABI says `hash &= ~hi', but this is equivalent
|
||||
in this case and on some machines one insn instead of two. */
|
||||
hash ^= hi;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (weak_value.s == NULL && ELF32_ST_BIND ((*ref)->st_info) != STB_WEAK)
|
||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||
UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero,
|
||||
then a PLT entry cannot satisfy the reference; some different binding
|
||||
must be found. */
|
||||
|
||||
ElfW(Addr)
|
||||
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||
struct link_map *symbol_scope[],
|
||||
const char *reference_name,
|
||||
ElfW(Addr) reloc_addr,
|
||||
int noplt)
|
||||
{
|
||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||
struct
|
||||
{
|
||||
ElfW(Addr) a;
|
||||
const ElfW(Sym) *s;
|
||||
} weak_value = { 0, NULL };
|
||||
size_t i;
|
||||
struct link_map **scope, *map;
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
for (scope = symbol_scope; *scope; ++scope)
|
||||
for (i = 0; i < (*scope)->l_nsearchlist; ++i)
|
||||
{
|
||||
const ElfW(Sym) *symtab;
|
||||
const char *strtab;
|
||||
ElfW(Symndx) symidx;
|
||||
|
||||
map = (*scope)->l_searchlist[i];
|
||||
|
||||
symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
|
||||
/* Search the appropriate hash bucket in this object's symbol table
|
||||
for a definition for the same symbol name. */
|
||||
for (symidx = map->l_buckets[hash % map->l_nbuckets];
|
||||
symidx != STN_UNDEF;
|
||||
symidx = map->l_chain[symidx])
|
||||
{
|
||||
const ElfW(Sym) *sym = &symtab[symidx];
|
||||
|
||||
if (sym->st_value == 0 || /* No value. */
|
||||
/* Cannot resolve to the location being filled in. */
|
||||
reloc_addr == map->l_addr + sym->st_value ||
|
||||
(noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */
|
||||
continue;
|
||||
|
||||
switch (ELFW(ST_TYPE) (sym->st_info))
|
||||
{
|
||||
case STT_NOTYPE:
|
||||
case STT_FUNC:
|
||||
case STT_OBJECT:
|
||||
break;
|
||||
default:
|
||||
/* Not a code/data definition. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
|
||||
/* Not the symbol we are looking for. */
|
||||
continue;
|
||||
|
||||
switch (ELFW(ST_BIND) (sym->st_info))
|
||||
{
|
||||
case STB_GLOBAL:
|
||||
/* Global definition. Just what we need. */
|
||||
*ref = sym;
|
||||
return map->l_addr;
|
||||
case STB_WEAK:
|
||||
/* Weak definition. Use this value if we don't find
|
||||
another. */
|
||||
if (! weak_value.s)
|
||||
{
|
||||
weak_value.s = sym;
|
||||
weak_value.a = map->l_addr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Local symbols are ignored. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (weak_value.s == NULL &&
|
||||
(*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK))
|
||||
{
|
||||
/* We could find no value for a strong reference. */
|
||||
const char msg[] = "undefined symbol: ";
|
||||
char buf[sizeof msg + strlen (undef_name)];
|
||||
memcpy (buf, msg, sizeof msg - 1);
|
||||
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
|
||||
memcpy (&buf[sizeof msg - 1], undef_name,
|
||||
sizeof buf - sizeof msg + 1);
|
||||
_dl_signal_error (0, reference_name, buf);
|
||||
}
|
||||
|
||||
@@ -119,8 +151,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
||||
void
|
||||
_dl_setup_hash (struct link_map *map)
|
||||
{
|
||||
Elf32_Word *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr;
|
||||
Elf32_Word nchain;
|
||||
ElfW(Symndx) *hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
|
||||
ElfW(Symndx) nchain;
|
||||
map->l_nbuckets = *hash++;
|
||||
nchain = *hash++;
|
||||
map->l_buckets = hash;
|
||||
|
||||
+18
-12
@@ -1,5 +1,5 @@
|
||||
/* Minimal replacements for basic facilities used in the dynamic linker.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -34,10 +34,9 @@ void *
|
||||
malloc (size_t n)
|
||||
{
|
||||
extern int _dl_zerofd;
|
||||
static size_t pagesize;
|
||||
|
||||
if (pagesize == 0)
|
||||
pagesize = __getpagesize ();
|
||||
if (_dl_pagesize == 0)
|
||||
_dl_pagesize = __getpagesize ();
|
||||
|
||||
if (_dl_zerofd == -1)
|
||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||
@@ -47,8 +46,8 @@ malloc (size_t n)
|
||||
/* Consume any unused space in the last page of our data segment. */
|
||||
extern int _end;
|
||||
alloc_ptr = &_end;
|
||||
alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + pagesize - 1)
|
||||
& ~(pagesize - 1));
|
||||
alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1));
|
||||
}
|
||||
|
||||
/* Make sure the allocation pointer is ideally aligned. */
|
||||
@@ -59,13 +58,13 @@ malloc (size_t n)
|
||||
{
|
||||
/* Insufficient space left; allocate another page. */
|
||||
caddr_t page;
|
||||
assert (n <= pagesize);
|
||||
page = mmap (0, pagesize, PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
||||
assert (n <= _dl_pagesize);
|
||||
page = __mmap (0, _dl_pagesize, PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
||||
assert (page != (caddr_t) -1);
|
||||
if (page != alloc_end)
|
||||
alloc_ptr = page;
|
||||
alloc_end = page + pagesize;
|
||||
alloc_end = page + _dl_pagesize;
|
||||
}
|
||||
|
||||
alloc_last_block = (void *) alloc_ptr;
|
||||
@@ -84,10 +83,17 @@ free (void *ptr)
|
||||
}
|
||||
weak_symbol (free)
|
||||
|
||||
/* This is never called. */
|
||||
/* This is only called with the most recent block returned by malloc. */
|
||||
void *
|
||||
realloc (void *ptr, size_t n)
|
||||
{ ptr += n; abort (); }
|
||||
{
|
||||
void *new;
|
||||
assert (ptr == alloc_last_block);
|
||||
alloc_ptr = alloc_last_block;
|
||||
new = malloc (n);
|
||||
assert (new == ptr);
|
||||
return new;
|
||||
}
|
||||
weak_symbol (realloc)
|
||||
|
||||
/* Avoid signal frobnication in setjmp/longjmp. Keeps things smaller. */
|
||||
|
||||
+4
-8
@@ -1,5 +1,5 @@
|
||||
/* Storage management for the chain of loaded shared objects.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -24,11 +24,8 @@ Cambridge, MA 02139, USA. */
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/* List of objects currently loaded. */
|
||||
struct link_map *_dl_loaded;
|
||||
|
||||
/* Tail of that list which were loaded at startup. */
|
||||
struct link_map *_dl_startup_loaded;
|
||||
/* List of objects currently loaded is [2] of this, aka _dl_loaded. */
|
||||
struct link_map *_dl_default_scope[5];
|
||||
|
||||
/* Allocate a `struct link_map' for a new object being loaded,
|
||||
and enter it into the _dl_loaded list. */
|
||||
@@ -38,8 +35,7 @@ _dl_new_object (char *realname, const char *libname, int type)
|
||||
{
|
||||
struct link_map *new = malloc (sizeof *new);
|
||||
if (! new)
|
||||
_dl_signal_error (ENOMEM, libname,
|
||||
"cannot allocate shared object descriptor");
|
||||
return NULL;
|
||||
|
||||
memset (new, 0, sizeof *new);
|
||||
new->l_name = realname;
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/* Load a shared object at runtime, relocate it, and run its initializer.
|
||||
Copyright (C) 1996 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <link.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
size_t _dl_global_scope_alloc;
|
||||
|
||||
struct link_map *
|
||||
_dl_open (struct link_map *parent, const char *file, int mode)
|
||||
{
|
||||
struct link_map *new, *l;
|
||||
ElfW(Addr) init;
|
||||
struct r_debug *r;
|
||||
|
||||
|
||||
/* Load the named object. */
|
||||
new = _dl_map_object (parent, file, lt_loaded);
|
||||
if (new->l_searchlist)
|
||||
/* It was already open. */
|
||||
return new;
|
||||
|
||||
/* Load that object's dependencies. */
|
||||
_dl_map_object_deps (new);
|
||||
|
||||
|
||||
/* Relocate the objects loaded. We do this in reverse order so that copy
|
||||
relocs of earlier objects overwrite the data written by later objects. */
|
||||
|
||||
l = new;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
while (1)
|
||||
{
|
||||
if (! l->l_relocated)
|
||||
{
|
||||
_dl_relocate_object (l, _dl_object_relocation_scope (l),
|
||||
(mode & RTLD_BINDING_MASK) == RTLD_LAZY);
|
||||
*_dl_global_scope_end = NULL;
|
||||
}
|
||||
|
||||
if (l == new)
|
||||
break;
|
||||
l = l->l_prev;
|
||||
}
|
||||
|
||||
new->l_global = (mode & RTLD_GLOBAL);
|
||||
if (new->l_global)
|
||||
{
|
||||
/* The symbols of the new object and its dependencies are to be
|
||||
introduced into the global scope that will be used to resolve
|
||||
references from other dynamically-loaded objects. */
|
||||
|
||||
if (_dl_global_scope_alloc == 0)
|
||||
{
|
||||
/* This is the first dynamic object given global scope. */
|
||||
_dl_global_scope_alloc = 8;
|
||||
_dl_global_scope = malloc (8 * sizeof (struct link_map *));
|
||||
if (! _dl_global_scope)
|
||||
{
|
||||
_dl_global_scope = _dl_default_scope;
|
||||
nomem:
|
||||
_dl_close (new);
|
||||
_dl_signal_error (ENOMEM, file, "cannot extend global scope");
|
||||
}
|
||||
_dl_global_scope[2] = _dl_default_scope[2];
|
||||
_dl_global_scope[3] = new;
|
||||
_dl_global_scope[4] = NULL;
|
||||
_dl_global_scope[5] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_dl_global_scope_alloc <
|
||||
_dl_global_scope_end - _dl_global_scope + 2)
|
||||
{
|
||||
/* Must extend the list. */
|
||||
struct link_map **new = realloc (_dl_global_scope,
|
||||
_dl_global_scope_alloc * 2);
|
||||
if (! new)
|
||||
goto nomem;
|
||||
_dl_global_scope_end = new + (_dl_global_scope_end -
|
||||
_dl_global_scope);
|
||||
_dl_global_scope = new;
|
||||
_dl_global_scope_alloc *= 2;
|
||||
}
|
||||
|
||||
/* Append the new object and re-terminate the list. */
|
||||
*_dl_global_scope_end++ = new;
|
||||
/* We keep the list double-terminated so the last element
|
||||
can be filled in for symbol lookups. */
|
||||
_dl_global_scope_end[0] = NULL;
|
||||
_dl_global_scope_end[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Notify the debugger we have added some objects. We need to call
|
||||
_dl_debug_initialize in a static program in case dynamic linking has
|
||||
not been used before. */
|
||||
r = _dl_debug_initialize (0);
|
||||
r->r_state = RT_ADD;
|
||||
_dl_debug_state ();
|
||||
|
||||
/* Run the initializer functions of new objects. */
|
||||
while (init = _dl_init_next (new))
|
||||
(*(void (*) (void)) init) ();
|
||||
|
||||
return new;
|
||||
}
|
||||
+21
-47
@@ -26,10 +26,8 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
|
||||
void
|
||||
_dl_relocate_object (struct link_map *l, int lazy)
|
||||
_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
|
||||
{
|
||||
const size_t pagesize = getpagesize ();
|
||||
|
||||
if (l->l_relocated)
|
||||
return;
|
||||
|
||||
@@ -37,89 +35,65 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
||||
{
|
||||
/* Bletch. We must make read-only segments writable
|
||||
long enough to relocate them. */
|
||||
const Elf32_Phdr *ph;
|
||||
const ElfW(Phdr) *ph;
|
||||
for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
|
||||
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
|
||||
{
|
||||
caddr_t mapstart = ((caddr_t) l->l_addr +
|
||||
(ph->p_vaddr & ~(pagesize - 1)));
|
||||
(ph->p_vaddr & ~(_dl_pagesize - 1)));
|
||||
caddr_t mapend = ((caddr_t) l->l_addr +
|
||||
((ph->p_vaddr + ph->p_memsz + pagesize - 1)
|
||||
& ~(pagesize - 1)));
|
||||
if (mprotect (mapstart, mapend - mapstart,
|
||||
PROT_READ|PROT_WRITE) < 0)
|
||||
((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1)));
|
||||
if (__mprotect (mapstart, mapend - mapstart,
|
||||
PROT_READ|PROT_WRITE) < 0)
|
||||
_dl_signal_error (errno, l->l_name,
|
||||
"cannot make segment writable for relocation");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct link_map *real_next, *scope;
|
||||
/* Do the actual relocation of the object's GOT and other data. */
|
||||
|
||||
const char *strtab
|
||||
const char *strtab /* String table object symbols. */
|
||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
|
||||
|
||||
Elf32_Addr resolve (const Elf32_Sym **ref, Elf32_Addr r_offset)
|
||||
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
||||
ElfW(Addr) reloc_addr, int noplt)
|
||||
{
|
||||
/* Look up the referenced symbol in the specified scope. */
|
||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
|
||||
l->l_name, (*ref)->st_value == r_offset);
|
||||
l->l_name, reloc_addr, noplt);
|
||||
}
|
||||
|
||||
real_next = l->l_next;
|
||||
if (l->l_info[DT_SYMBOLIC])
|
||||
{
|
||||
if (l->l_prev)
|
||||
l->l_prev->l_next = real_next;
|
||||
l->l_next = _dl_loaded;
|
||||
scope = l;
|
||||
}
|
||||
else
|
||||
scope = _dl_loaded;
|
||||
|
||||
if (l->l_type == lt_interpreter)
|
||||
/* We cannot be lazy when relocating the dynamic linker itself. It
|
||||
was previously relocated eagerly (allowing us to be running now),
|
||||
and needs always to be fully relocated so it can run without the
|
||||
aid of run-time fixups (because it's the one to do them), so we
|
||||
must always re-relocate its PLT eagerly. */
|
||||
lazy = 0;
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy, resolve);
|
||||
|
||||
/* Restore list frobnication done above for DT_SYMBOLIC. */
|
||||
l->l_next = real_next;
|
||||
if (l->l_prev)
|
||||
l->l_prev->l_next = l;
|
||||
}
|
||||
|
||||
/* Set up the PLT so its unrelocated entries will
|
||||
jump to _dl_runtime_resolve, which will relocate them. */
|
||||
/* Set up the PLT so its unrelocated entries will jump to
|
||||
_dl_runtime_resolve (dl-runtime.c), which will relocate them. */
|
||||
elf_machine_runtime_setup (l, lazy);
|
||||
|
||||
/* Mark the object so we know ths work has been done. */
|
||||
l->l_relocated = 1;
|
||||
|
||||
if (l->l_info[DT_TEXTREL])
|
||||
{
|
||||
/* Undo the protection change we made before relocating. */
|
||||
const Elf32_Phdr *ph;
|
||||
const ElfW(Phdr) *ph;
|
||||
for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
|
||||
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
|
||||
{
|
||||
caddr_t mapstart = ((caddr_t) l->l_addr +
|
||||
(ph->p_vaddr & ~(pagesize - 1)));
|
||||
(ph->p_vaddr & ~(_dl_pagesize - 1)));
|
||||
caddr_t mapend = ((caddr_t) l->l_addr +
|
||||
((ph->p_vaddr + ph->p_memsz + pagesize - 1)
|
||||
& ~(pagesize - 1)));
|
||||
((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1)));
|
||||
int prot = 0;
|
||||
if (ph->p_flags & PF_R)
|
||||
prot |= PROT_READ;
|
||||
if (ph->p_flags & PF_X)
|
||||
prot |= PROT_EXEC;
|
||||
if (mprotect (mapstart, mapend - mapstart, prot) < 0)
|
||||
if (__mprotect (mapstart, mapend - mapstart, prot) < 0)
|
||||
_dl_signal_error (errno, l->l_name,
|
||||
"can't restore segment prot after reloc");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+67
-33
@@ -20,13 +20,61 @@ Cambridge, MA 02139, USA. */
|
||||
#include <link.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
|
||||
/* The global scope we will use for symbol lookups.
|
||||
This will be modified by _dl_open if RTLD_GLOBAL is used. */
|
||||
struct link_map **_dl_global_scope = _dl_default_scope;
|
||||
struct link_map **_dl_global_scope_end = &_dl_default_scope[3];
|
||||
|
||||
|
||||
/* Hack _dl_global_scope[0] and [1] as necessary, and return a pointer into
|
||||
_dl_global_scope that should be passed to _dl_lookup_symbol for symbol
|
||||
references made in the object L's relocations. */
|
||||
inline struct link_map **
|
||||
_dl_object_relocation_scope (struct link_map *l)
|
||||
{
|
||||
if (l->l_info[DT_SYMBOLIC])
|
||||
{
|
||||
/* This object's global references are to be resolved first
|
||||
in the object itself, and only secondarily in more global
|
||||
scopes. */
|
||||
|
||||
if (! l->l_searchlist)
|
||||
/* We must construct the searchlist for this object. */
|
||||
_dl_map_object_deps (l);
|
||||
|
||||
/* The primary scope is this object itself and its
|
||||
dependencies. */
|
||||
_dl_global_scope[0] = l;
|
||||
|
||||
/* Secondary is the dependency tree that reached L; the object
|
||||
requested directly by the user is at the root of that tree. */
|
||||
while (l->l_loader)
|
||||
l = l->l_loader;
|
||||
_dl_global_scope[1] = l;
|
||||
|
||||
/* Finally, the global scope follows. */
|
||||
|
||||
return _dl_global_scope;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use first the global scope, and then the scope of the root of the
|
||||
dependency tree that first caused this object to be loaded. */
|
||||
while (l->l_loader)
|
||||
l = l->l_loader;
|
||||
*_dl_global_scope_end = l;
|
||||
return &_dl_global_scope[2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Figure out the right type, Rel or Rela. */
|
||||
#define elf_machine_rel 1
|
||||
#define elf_machine_rela 2
|
||||
#if elf_machine_relplt == elf_machine_rel
|
||||
#define PLTREL Elf32_Rel
|
||||
#define PLTREL ElfW(Rel)
|
||||
#elif elf_machine_relplt == elf_machine_rela
|
||||
#define PLTREL Elf32_Rela
|
||||
#define PLTREL ElfW(Rela)
|
||||
#else
|
||||
#error "dl-machine.h bug: elf_machine_relplt not rel or rela"
|
||||
#endif
|
||||
@@ -37,11 +85,11 @@ Cambridge, MA 02139, USA. */
|
||||
in the trampoline code will be a local PC-relative call. Tell the
|
||||
compiler not to worry that the function appears not to be called. */
|
||||
|
||||
static Elf32_Addr fixup (
|
||||
static ElfW(Addr) fixup (
|
||||
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||
#endif
|
||||
struct link_map *l, Elf32_Word reloc_offset)
|
||||
struct link_map *l, ElfW(Word) reloc_offset)
|
||||
__attribute__ ((unused));
|
||||
|
||||
/* This function is called through a special trampoline from the PLT the
|
||||
@@ -51,15 +99,15 @@ static Elf32_Addr fixup (
|
||||
to that address. Future calls will bounce directly from the PLT to the
|
||||
function. */
|
||||
|
||||
static Elf32_Addr
|
||||
static ElfW(Addr)
|
||||
fixup (
|
||||
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||
#endif
|
||||
struct link_map *l, Elf32_Word reloc_offset)
|
||||
struct link_map *l, ElfW(Word) reloc_offset)
|
||||
{
|
||||
const Elf32_Sym *const symtab
|
||||
= (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
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);
|
||||
|
||||
@@ -67,36 +115,22 @@ fixup (
|
||||
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
|
||||
reloc_offset);
|
||||
|
||||
const Elf32_Sym *definer;
|
||||
Elf32_Addr loadbase;
|
||||
struct link_map *scope, *real_next;
|
||||
/* Set up the scope to find symbols referenced by this object. */
|
||||
struct link_map **scope = _dl_object_relocation_scope (l);
|
||||
|
||||
/* Look up the symbol's run-time value. */
|
||||
|
||||
real_next = l->l_next;
|
||||
if (l->l_info[DT_SYMBOLIC])
|
||||
/* Perform the specified relocation. */
|
||||
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
||||
ElfW(Addr) reloc_addr, int noplt)
|
||||
{
|
||||
l->l_next = _dl_loaded;
|
||||
if (l->l_prev)
|
||||
l->l_prev->l_next = real_next;
|
||||
scope = l;
|
||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
|
||||
scope, l->l_name, reloc_addr, noplt);
|
||||
}
|
||||
else
|
||||
scope = _dl_loaded;
|
||||
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], resolve);
|
||||
|
||||
definer = &symtab[ELF32_R_SYM (reloc->r_info)];
|
||||
loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,
|
||||
scope, l->l_name, 0);
|
||||
*_dl_global_scope_end = NULL;
|
||||
|
||||
/* Restore list frobnication done above for DT_SYMBOLIC. */
|
||||
l->l_next = real_next;
|
||||
if (l->l_prev)
|
||||
l->l_prev->l_next = l;
|
||||
|
||||
/* Apply the relocation with that value. */
|
||||
elf_machine_relplt (l, reloc, loadbase, definer);
|
||||
|
||||
return *(Elf32_Addr *) (l->l_addr + reloc->r_offset);
|
||||
/* Return the address that was written by the relocation. */
|
||||
return *(ElfW(Addr) *) (l->l_addr + reloc->r_offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Support for dynamic linking code in static libc.
|
||||
Copyright (C) 1996 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* This file defines some things that for the dynamic linker are defined in
|
||||
rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */
|
||||
|
||||
int _dl_secure; /* Always honor LD_LIBRARY_PATH. */
|
||||
|
||||
extern char *__progname;
|
||||
char **_dl_argv = &__progname; /* This is checked for some error messages. */
|
||||
|
||||
/* This defines the default search path for libraries.
|
||||
For the dynamic linker it is set by -rpath when linking. */
|
||||
const char *_dl_rpath = DEFAULT_RPATH;
|
||||
|
||||
/* This is the only dl-sysdep.c function that is actually needed at run-time
|
||||
by _dl_map_object. */
|
||||
|
||||
int
|
||||
_dl_sysdep_open_zero_fill (void)
|
||||
{
|
||||
return __open ("/dev/zero", O_RDONLY);
|
||||
}
|
||||
|
||||
/* This should never be called. */
|
||||
void
|
||||
_dl_sysdep_fatal (void)
|
||||
{
|
||||
assert (! "_dl_sysdep_fatal called");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 1992, 1995 Free Software Foundation, Inc.
|
||||
/* Look up a symbol's run-time value in the scope of a loaded object.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -16,15 +17,17 @@ License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <ansidecl.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <link.h>
|
||||
|
||||
/* Return X with its signed changed to Y's. */
|
||||
double
|
||||
DEFUN(__copysign, (x, y), double x AND double y)
|
||||
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
||||
|
||||
ElfW(Addr)
|
||||
_dl_symbol_value (struct link_map *map, const char *name)
|
||||
{
|
||||
x = fabs (x);
|
||||
return y < 0 ? - x : x;
|
||||
ElfW(Addr) loadbase;
|
||||
const ElfW(Sym) *ref = NULL;
|
||||
struct link_map *scope[2] = { map, NULL };
|
||||
loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0);
|
||||
return loadbase + ref->st_value;
|
||||
}
|
||||
|
||||
weak_alias (__copysign, copysign)
|
||||
@@ -0,0 +1,86 @@
|
||||
/* dladdr -- Locate the shared object symbol nearest a given address.
|
||||
Copyright (C) 1996 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <link.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
int
|
||||
dladdr (void *address, Dl_info *info)
|
||||
{
|
||||
const ElfW(Addr) addr = (ElfW(Addr)) address;
|
||||
struct link_map *l, *match;
|
||||
const ElfW(Sym) *symtab, *matchsym;
|
||||
const char *strtab;
|
||||
|
||||
/* Find the highest-addressed object that ADDRESS is not below. */
|
||||
match = NULL;
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (addr >= l->l_addr && !match || match->l_addr < l->l_addr)
|
||||
match = l;
|
||||
|
||||
if (match)
|
||||
{
|
||||
/* We know ADDRESS lies within MATCH if in any shared object.
|
||||
Make sure it isn't past the end of MATCH's segments. */
|
||||
size_t n = match->l_phnum;
|
||||
do
|
||||
--n;
|
||||
while (match->l_phdr[n].p_type != PT_LOAD);
|
||||
if (addr >= (match->l_addr +
|
||||
match->l_phdr[n].p_vaddr + match->l_phdr[n].p_memsz))
|
||||
/* Off the end of the highest-addressed shared object. */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
/* Now we know what object the address lies in. */
|
||||
info->dli_fname = match->l_name;
|
||||
info->dli_fbase = (void *) match->l_addr;
|
||||
|
||||
symtab = ((void *) match->l_addr + match->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
strtab = ((void *) match->l_addr + match->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
|
||||
/* We assume that the string table follows the symbol table, because
|
||||
there is no way in ELF to know the size of the dynamic symbol table!! */
|
||||
for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab)
|
||||
if (addr >= match->l_addr + symtab->st_value && !matchsym ||
|
||||
matchsym->st_value < symtab->st_value &&
|
||||
ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL ||
|
||||
ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
|
||||
matchsym = symtab;
|
||||
|
||||
if (matchsym)
|
||||
{
|
||||
/* We found a symbol close by. Fill in its name and exact address. */
|
||||
info->dli_sname = strtab + matchsym->st_name;
|
||||
info->dli_saddr = (void *) (match->l_addr + matchsym->st_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No symbol matches. We return only the containing object. */
|
||||
info->dli_sname = NULL;
|
||||
info->dli_saddr = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
+2
-66
@@ -1,5 +1,5 @@
|
||||
/* dlclose -- Close a handle opened by `dlopen'.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -19,77 +19,13 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <link.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
#define LOSE(s) _dl_signal_error (0, map->l_name, s)
|
||||
|
||||
int
|
||||
dlclose (void *handle)
|
||||
{
|
||||
void doit (void)
|
||||
{
|
||||
struct link_map *map = handle;
|
||||
|
||||
if (map->l_opencount == 0)
|
||||
LOSE ("shared object not open");
|
||||
|
||||
/* Decrement the reference count. */
|
||||
--map->l_opencount;
|
||||
|
||||
if (map->l_opencount == 0 && map->l_type == lt_loaded)
|
||||
{
|
||||
/* That was the last reference, and this was a dlopen-loaded
|
||||
object. We can unmap it. */
|
||||
const Elf32_Phdr *ph;
|
||||
|
||||
if (map->l_info[DT_FINI])
|
||||
/* Call its termination function. */
|
||||
(*(void (*) (void)) ((void *) map->l_addr +
|
||||
map->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||
|
||||
if (map->l_info[DT_NEEDED])
|
||||
{
|
||||
/* Also close all the dependencies. */
|
||||
const char *strtab
|
||||
= (void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr;
|
||||
const Elf32_Dyn *d;
|
||||
for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
/* It must already be open, since this one needed it;
|
||||
so dlopen will just find us its `struct link_map'
|
||||
and bump its reference count. */
|
||||
struct link_map *o, *dep
|
||||
= dlopen (strtab + d->d_un.d_val, RTLD_LAZY);
|
||||
--dep->l_opencount; /* Lose the ref from that dlopen. */
|
||||
/* Now we have the handle; we can close it for real. */
|
||||
o = map;
|
||||
map = dep;
|
||||
doit ();
|
||||
map = o;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unmap the segments. */
|
||||
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
||||
if (ph->p_type == PT_LOAD)
|
||||
{
|
||||
Elf32_Addr mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||
Elf32_Addr mapend = ((ph->p_vaddr + ph->p_memsz
|
||||
+ ph->p_align - 1)
|
||||
& ~(ph->p_align - 1));
|
||||
munmap ((caddr_t) mapstart, mapend - mapstart);
|
||||
}
|
||||
|
||||
/* Finally, unlink the data structure and free it. */
|
||||
map->l_prev->l_next = map->l_next;
|
||||
if (map->l_next)
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
free (map);
|
||||
}
|
||||
_dl_close (handle);
|
||||
}
|
||||
|
||||
return _dlerror_run (doit) ? -1 : 0;
|
||||
|
||||
+21
-8
@@ -1,5 +1,5 @@
|
||||
/* dlfcn.h -- User functions for run-time dynamic loading.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -21,16 +21,19 @@ Cambridge, MA 02139, USA. */
|
||||
#define _DLFCN_H 1
|
||||
|
||||
|
||||
/* Type of the second argument to `dlopen'. */
|
||||
typedef enum
|
||||
{
|
||||
RTLD_LAZY = 1, /* Lazy function call binding. */
|
||||
RTLD_NOW = 2 /* Immediate function call binding. */
|
||||
} dl_open_mode;
|
||||
/* The MODE argument to `dlopen' contains one of the following: */
|
||||
#define RTLD_LAZY 0x001 /* Lazy function call binding. */
|
||||
#define RTLD_NOW 0x002 /* Immediate function call binding. */
|
||||
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
|
||||
|
||||
/* If the following bit is set in the MODE argument to `dlopen',
|
||||
the symbols of the loaded object and its dependencies are made
|
||||
visible as if the object were linked directly into the program. */
|
||||
#define RTLD_GLOBAL 0x100
|
||||
|
||||
/* Open the shared object FILE and map it in; return a handle that can be
|
||||
passed to `dlsym' to get symbol values from it. */
|
||||
extern void *dlopen (const char *__file, dl_open_mode);
|
||||
extern void *dlopen (const char *__file, int __mode);
|
||||
|
||||
/* Unmap and close a shared object opened by `dlopen'.
|
||||
The handle cannot be used again after calling `dlclose'. */
|
||||
@@ -45,5 +48,15 @@ extern void *dlsym (void *__handle, const char *__name);
|
||||
the error string so that a following call returns null. */
|
||||
extern char *dlerror (void);
|
||||
|
||||
/* Fill in *INFO with the following information about ADDRESS.
|
||||
Returns 0 iff no shared object's segments contain that address. */
|
||||
typedef struct
|
||||
{
|
||||
const char *dli_fname; /* File name of defining object. */
|
||||
void *dli_fbase; /* Load address of that object. */
|
||||
const char *dli_sname; /* Name of nearest symbol. */
|
||||
void *dli_saddr; /* Exact value of nearest symbol. */
|
||||
} Dl_info;
|
||||
extern int dladdr (void *__address, Dl_info *__info);
|
||||
|
||||
#endif /* dlfcn.h */
|
||||
|
||||
+4
-31
@@ -1,5 +1,5 @@
|
||||
/* dlopen -- Load a shared object at run time.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -22,40 +22,13 @@ Cambridge, MA 02139, USA. */
|
||||
#include <dlfcn.h>
|
||||
|
||||
void *
|
||||
dlopen (const char *file, dl_open_mode mode)
|
||||
dlopen (const char *file, int mode)
|
||||
{
|
||||
struct link_map *new, *l;
|
||||
struct link_map *new;
|
||||
|
||||
void doit (void)
|
||||
{
|
||||
Elf32_Addr init;
|
||||
|
||||
new = _dl_map_object (_dl_loaded, file);
|
||||
|
||||
/* Map in any dependencies. */
|
||||
for (l = new; l; l = l->l_next)
|
||||
if (! l->l_deps_loaded)
|
||||
{
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
const char *strtab
|
||||
= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
|
||||
const Elf32_Dyn *d;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
_dl_map_object (l, strtab + d->d_un.d_val);
|
||||
}
|
||||
l->l_deps_loaded = 1;
|
||||
}
|
||||
|
||||
/* Relocate the objects loaded. */
|
||||
for (l = new; l; l = l->l_next)
|
||||
if (! l->l_relocated)
|
||||
_dl_relocate_object (l, mode == RTLD_LAZY);
|
||||
|
||||
/* Run the initializer functions of new objects. */
|
||||
while (init = _dl_init_next ())
|
||||
(*(void (*) (void)) init) ();
|
||||
new = _dl_open (_dl_loaded, file ?: "", mode);
|
||||
}
|
||||
|
||||
return _dlerror_run (doit) ? NULL : new;
|
||||
|
||||
+6
-13
@@ -1,5 +1,5 @@
|
||||
/* dlsym -- Look up a symbol in a shared object loaded by `dlopen'.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -27,20 +27,13 @@ void *
|
||||
dlsym (void *handle, const char *name)
|
||||
{
|
||||
struct link_map *map = handle;
|
||||
struct link_map *real_next;
|
||||
Elf32_Addr loadbase;
|
||||
const Elf32_Sym *ref = NULL;
|
||||
int lose;
|
||||
ElfW(Addr) loadbase;
|
||||
const ElfW(Sym) *ref = NULL;
|
||||
void doit (void)
|
||||
{
|
||||
loadbase = _dl_lookup_symbol (name, &ref, map, map->l_name, 1);
|
||||
struct link_map *scope[2] = { map, NULL };
|
||||
loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0);
|
||||
}
|
||||
|
||||
/* Confine the symbol scope to just this map. */
|
||||
real_next = map->l_next;
|
||||
map->l_next = NULL;
|
||||
lose = _dlerror_run (doit);
|
||||
map->l_next = real_next;
|
||||
|
||||
return lose ? NULL : (void *) (loadbase + ref->st_value);
|
||||
return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
|
||||
}
|
||||
|
||||
+10
-30
@@ -22,7 +22,7 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifdef DO_RELA
|
||||
#define elf_dynamic_do_rel elf_dynamic_do_rela
|
||||
#define Elf32_Rel Elf32_Rela
|
||||
#define Rel Rela
|
||||
#define elf_machine_rel elf_machine_rela
|
||||
#endif
|
||||
|
||||
@@ -37,15 +37,15 @@ Cambridge, MA 02139, USA. */
|
||||
static inline void
|
||||
elf_dynamic_do_rel (struct link_map *map,
|
||||
int reltag, int sztag,
|
||||
Elf32_Addr (*resolve) (const Elf32_Sym **symbol,
|
||||
Elf32_Addr r_offset),
|
||||
ElfW(Addr) (*resolve) (const ElfW(Sym) **symbol,
|
||||
ElfW(Addr) reloc_addr, int noplt),
|
||||
int lazy)
|
||||
{
|
||||
const Elf32_Sym *const symtab
|
||||
= (const Elf32_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
const Elf32_Rel *r
|
||||
= (const Elf32_Rel *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr);
|
||||
const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r];
|
||||
const ElfW(Sym) *const symtab
|
||||
= (const ElfW(Sym) *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
const ElfW(Rel) *r
|
||||
= (const ElfW(Rel) *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr);
|
||||
const ElfW(Rel) *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r];
|
||||
|
||||
if (lazy)
|
||||
/* Doing lazy PLT relocations; they need very little info. */
|
||||
@@ -53,29 +53,9 @@ elf_dynamic_do_rel (struct link_map *map,
|
||||
elf_machine_lazy_rel (map, r);
|
||||
else
|
||||
for (; r < end; ++r)
|
||||
{
|
||||
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
|
||||
Elf32_Addr loadbase;
|
||||
|
||||
if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
|
||||
loadbase = 0; /* This value will not be consulted. */
|
||||
else if (ELF32_ST_BIND (definer->st_info) == STB_LOCAL)
|
||||
/* Local symbols always refer to the containing object. */
|
||||
loadbase = map->l_addr;
|
||||
else
|
||||
{
|
||||
if (resolve)
|
||||
loadbase = (*resolve) (&definer, r->r_offset);
|
||||
else
|
||||
{
|
||||
assert (definer->st_shndx != SHN_UNDEF);
|
||||
loadbase = map->l_addr;
|
||||
}
|
||||
}
|
||||
elf_machine_rel (map, r, loadbase, definer);
|
||||
}
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], resolve);
|
||||
}
|
||||
|
||||
#undef elf_dynamic_do_rel
|
||||
#undef Elf32_Rel
|
||||
#undef Rel
|
||||
#undef elf_machine_rel
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@ Cambridge, MA 02139, USA. */
|
||||
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
||||
|
||||
static inline void
|
||||
elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM + DT_PROCNUM])
|
||||
elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Dyn) *info[DT_NUM + DT_PROCNUM])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -48,9 +48,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM + DT_PROCNUM])
|
||||
}
|
||||
|
||||
if (info[DT_RELA])
|
||||
assert (info[DT_RELAENT]->d_un.d_val == sizeof (Elf32_Rela));
|
||||
assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
|
||||
if (info[DT_REL])
|
||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (Elf32_Rel));
|
||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
|
||||
if (info[DT_PLTREL])
|
||||
assert (info[DT_PLTREL]->d_un.d_val == DT_REL ||
|
||||
info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||
|
||||
@@ -23,16 +23,41 @@ Cambridge, MA 02139, USA. */
|
||||
#define _ELF_H 1
|
||||
|
||||
|
||||
/* Standard ELF types.
|
||||
/* Standard ELF types. Using __attribute__ mode ensures that GCC
|
||||
will choose the right number of bits for these types. */
|
||||
|
||||
Using __attribute__ mode ensures that gcc will choose the right for
|
||||
these types. */
|
||||
|
||||
typedef unsigned int Elf32_Addr __attribute__ ((mode (SI)));
|
||||
/* Type for a 16-bit quantity. */
|
||||
typedef unsigned int Elf32_Half __attribute__ ((mode (HI)));
|
||||
typedef unsigned int Elf32_Off __attribute__ ((mode (SI)));
|
||||
typedef int Elf32_Sword __attribute__ ((mode (SI)));
|
||||
typedef unsigned int Elf64_Half __attribute__ ((mode (HI)));
|
||||
|
||||
/* Types for signed and unsigned 32-bit quantities. */
|
||||
typedef unsigned int Elf32_Word __attribute__ ((mode (SI)));
|
||||
typedef int Elf32_Sword __attribute__ ((mode (SI)));
|
||||
typedef unsigned int Elf64_Word __attribute__ ((mode (SI)));
|
||||
typedef int Elf64_Sword __attribute__ ((mode (SI)));
|
||||
|
||||
/* Types for signed and unsigned 64-bit quantities. */
|
||||
typedef unsigned int Elf32_Xword __attribute__ ((mode (DI)));
|
||||
typedef int Elf32_Sxword __attribute__ ((mode (DI)));
|
||||
typedef unsigned int Elf64_Xword __attribute__ ((mode (DI)));
|
||||
typedef int Elf64_Sxword __attribute__ ((mode (DI)));
|
||||
|
||||
/* Type of addresses. */
|
||||
typedef unsigned int Elf32_Addr __attribute__ ((mode (SI)));
|
||||
typedef unsigned int Elf64_Addr __attribute__ ((mode (DI)));
|
||||
|
||||
/* Type of file offsets. */
|
||||
typedef unsigned int Elf32_Off __attribute__ ((mode (SI)));
|
||||
typedef unsigned int Elf64_Off __attribute__ ((mode (DI)));
|
||||
|
||||
/* Type for section indices, which are 16-bit quantities. */
|
||||
typedef unsigned int Elf32_Section __attribute__ ((mode (HI)));
|
||||
typedef unsigned int Elf64_Section __attribute__ ((mode (HI)));
|
||||
|
||||
/* Type of symbol indices. */
|
||||
typedef unsigned int Elf32_Symndx __attribute__ ((mode (SI)));
|
||||
typedef unsigned int Elf64_Symndx __attribute__ ((mode (DI)));
|
||||
|
||||
|
||||
/* The ELF file header. This appears at the start of every ELF file. */
|
||||
|
||||
@@ -56,6 +81,24 @@ typedef struct
|
||||
Elf32_Half e_shstrndx; /* Section header string table index */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
Elf64_Half e_type; /* Object file type */
|
||||
Elf64_Half e_machine; /* Architecture */
|
||||
Elf64_Word e_version; /* Object file version */
|
||||
Elf64_Addr e_entry; /* Entry point virtual address */
|
||||
Elf64_Off e_phoff; /* Program header table file offset */
|
||||
Elf64_Off e_shoff; /* Section header table file offset */
|
||||
Elf64_Word e_flags; /* Processor-specific flags */
|
||||
Elf64_Half e_ehsize; /* ELF header size in bytes */
|
||||
Elf64_Half e_phentsize; /* Program header table entry size */
|
||||
Elf64_Half e_phnum; /* Program header table entry count */
|
||||
Elf64_Half e_shentsize; /* Section header table entry size */
|
||||
Elf64_Half e_shnum; /* Section header table entry count */
|
||||
Elf64_Half e_shstrndx; /* Section header string table index */
|
||||
} Elf64_Ehdr;
|
||||
|
||||
/* Fields in the e_ident array. The EI_* macros are indices into the
|
||||
array. The macros under each EI_* macro are the values the byte
|
||||
may have. */
|
||||
@@ -119,11 +162,14 @@ typedef struct
|
||||
#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */
|
||||
|
||||
#define EM_PARISC 15 /* HPPA */
|
||||
#define EM_PPC 20 /* PowerPC */
|
||||
|
||||
/* If it is necessary to assign new unofficial EM_* values, please
|
||||
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
|
||||
chances of collision with official or non-GNU unofficial values. */
|
||||
|
||||
#define EM_ALPHA 0x9026
|
||||
|
||||
/* Legal values for e_version (version). */
|
||||
|
||||
#define EV_NONE 0 /* Invalid ELF version */
|
||||
@@ -145,6 +191,20 @@ typedef struct
|
||||
Elf32_Word sh_entsize; /* Entry size if section holds table */
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word sh_name; /* Section name (string tbl index) */
|
||||
Elf64_Word sh_type; /* Section type */
|
||||
Elf64_Xword sh_flags; /* Section flags */
|
||||
Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
||||
Elf64_Off sh_offset; /* Section file offset */
|
||||
Elf64_Xword sh_size; /* Section size in bytes */
|
||||
Elf64_Word sh_link; /* Link to another section */
|
||||
Elf64_Word sh_info; /* Additional section information */
|
||||
Elf64_Xword sh_addralign; /* Section alignment */
|
||||
Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
||||
} Elf64_Shdr;
|
||||
|
||||
/* Special section indices. */
|
||||
|
||||
#define SHN_UNDEF 0 /* Undefined section */
|
||||
@@ -191,9 +251,19 @@ typedef struct
|
||||
Elf32_Word st_size; /* Symbol size */
|
||||
unsigned char st_info; /* Symbol type and binding */
|
||||
unsigned char st_other; /* No defined meaning, 0 */
|
||||
Elf32_Half st_shndx; /* Section index */
|
||||
Elf32_Section st_shndx; /* Section index */
|
||||
} Elf32_Sym;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word st_name; /* Symbol name (string tbl index) */
|
||||
unsigned char st_info; /* Symbol type and binding */
|
||||
unsigned char st_other; /* No defined meaning, 0 */
|
||||
Elf64_Section st_shndx; /* Section index */
|
||||
Elf64_Addr st_value; /* Symbol value */
|
||||
Elf64_Xword st_size; /* Symbol size */
|
||||
} Elf64_Sym;
|
||||
|
||||
/* Special section index. */
|
||||
|
||||
#define SHN_UNDEF 0 /* No section, undefined symbol. */
|
||||
@@ -204,6 +274,11 @@ typedef struct
|
||||
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
||||
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
|
||||
#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
|
||||
#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
|
||||
#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
|
||||
|
||||
/* Legal values for ST_BIND subfield of st_info (symbol binding). */
|
||||
|
||||
#define STB_LOCAL 0 /* Local symbol */
|
||||
@@ -240,6 +315,17 @@ typedef struct
|
||||
Elf32_Word r_info; /* Relocation type and symbol index */
|
||||
} Elf32_Rel;
|
||||
|
||||
/* I have seen two different definitions of the Elf64_Rel and
|
||||
Elf64_Rela structures, so we'll leave them out until Novell (or
|
||||
whoever) gets their act together. */
|
||||
/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Addr r_offset; /* Address */
|
||||
Elf64_Xword r_info; /* Relocation type and symbol index */
|
||||
} Elf64_Rel;
|
||||
|
||||
/* Relocation table entry with addend (in section of type SHT_RELA). */
|
||||
|
||||
typedef struct
|
||||
@@ -249,15 +335,27 @@ typedef struct
|
||||
Elf32_Sword r_addend; /* Addend */
|
||||
} Elf32_Rela;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Addr r_offset; /* Address */
|
||||
Elf64_Xword r_info; /* Relocation type and symbol index */
|
||||
Elf64_Sxword r_addend; /* Addend */
|
||||
} Elf64_Rela;
|
||||
|
||||
/* How to extract and insert information held in the r_info field. */
|
||||
|
||||
#define ELF32_R_SYM(val) ((val) >> 8)
|
||||
#define ELF32_R_TYPE(val) ((val) & 0xff)
|
||||
#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
|
||||
|
||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
|
||||
#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type))
|
||||
|
||||
/* Program segment header. */
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Word p_type; /* Segment type */
|
||||
Elf32_Off p_offset; /* Segment file offset */
|
||||
Elf32_Addr p_vaddr; /* Segment virtual address */
|
||||
@@ -268,6 +366,18 @@ typedef struct {
|
||||
Elf32_Word p_align; /* Segment alignment */
|
||||
} Elf32_Phdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word p_type; /* Segment type */
|
||||
Elf64_Word p_flags; /* Segment flags */
|
||||
Elf64_Off p_offset; /* Segment file offset */
|
||||
Elf64_Addr p_vaddr; /* Segment virtual address */
|
||||
Elf64_Addr p_paddr; /* Segment physical address */
|
||||
Elf64_Xword p_filesz; /* Segment size in file */
|
||||
Elf64_Xword p_memsz; /* Segment size in memory */
|
||||
Elf64_Xword p_align; /* Segment alignment */
|
||||
} Elf64_Phdr;
|
||||
|
||||
/* Legal values for p_type (segment type). */
|
||||
|
||||
#define PT_NULL 0 /* Program header table entry unused */
|
||||
@@ -288,6 +398,17 @@ typedef struct {
|
||||
#define PF_R (1 << 2) /* Segment is readable */
|
||||
#define PF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||
|
||||
/* Legal values for note segment descriptor types for core files. */
|
||||
|
||||
#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
|
||||
#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
|
||||
#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
|
||||
|
||||
/* Legal values for the note segment descriptor types for object files. */
|
||||
|
||||
#define NT_VERSION 1 /* Contains a version string. */
|
||||
|
||||
|
||||
/* Dynamic section entry. */
|
||||
|
||||
typedef struct
|
||||
@@ -300,6 +421,16 @@ typedef struct
|
||||
} d_un;
|
||||
} Elf32_Dyn;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Sxword d_tag; /* Dynamic entry type */
|
||||
union
|
||||
{
|
||||
Elf64_Xword d_val; /* Integer value */
|
||||
Elf64_Addr d_ptr; /* Address value */
|
||||
} d_un;
|
||||
} Elf64_Dyn;
|
||||
|
||||
/* Legal values for d_tag (dynamic entry type). */
|
||||
|
||||
#define DT_NULL 0 /* Marks end of dynamic section */
|
||||
@@ -331,76 +462,6 @@ typedef struct
|
||||
#define DT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||
#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
|
||||
|
||||
/* Standard 64 bit ELF types. */
|
||||
|
||||
typedef unsigned int Elf64_Addr __attribute__ ((mode (DI)));
|
||||
typedef unsigned int Elf64_Half __attribute__ ((mode (HI)));
|
||||
typedef unsigned int Elf64_Off __attribute__ ((mode (DI)));
|
||||
typedef int Elf64_Sword __attribute__ ((mode (SI)));
|
||||
typedef int Elf64_Sxword __attribute__ ((mode (DI)));
|
||||
typedef unsigned int Elf64_Word __attribute__ ((mode (SI)));
|
||||
typedef unsigned int Elf64_Xword __attribute__ ((mode (DI)));
|
||||
typedef unsigned int Elf64_Byte __attribute__ ((mode (QI)));
|
||||
typedef unsigned int Elf64_Section __attribute__ ((mode (HI)));
|
||||
|
||||
/* 64 bit ELF file header. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
Elf64_Half e_type; /* Object file type */
|
||||
Elf64_Half e_machine; /* Architecture */
|
||||
Elf64_Word e_version; /* Object file version */
|
||||
Elf64_Addr e_entry; /* Entry point virtual address */
|
||||
Elf64_Off e_phoff; /* Program header table file offset */
|
||||
Elf64_Off e_shoff; /* Section header table file offset */
|
||||
Elf64_Word e_flags; /* Processor-specific flags */
|
||||
Elf64_Half e_ehsize; /* ELF header size in bytes */
|
||||
Elf64_Half e_phentsize; /* Program header table entry size */
|
||||
Elf64_Half e_phnum; /* Program header table entry count */
|
||||
Elf64_Half e_shentsize; /* Section header table entry size */
|
||||
Elf64_Half e_shnum; /* Section header table entry count */
|
||||
Elf64_Half e_shstrndx; /* Section header string table index */
|
||||
} Elf64_Ehdr;
|
||||
|
||||
/* 64 bit section header. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word sh_name; /* Section name (string tbl index) */
|
||||
Elf64_Word sh_type; /* Section type */
|
||||
Elf64_Xword sh_flags; /* Section flags */
|
||||
Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
||||
Elf64_Off sh_offset; /* Section file offset */
|
||||
Elf64_Xword sh_size; /* Section size in bytes */
|
||||
Elf64_Word sh_link; /* Link to another section */
|
||||
Elf64_Word sh_info; /* Additional section information */
|
||||
Elf64_Xword sh_addralign; /* Section alignment */
|
||||
Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
||||
} Elf64_Shdr;
|
||||
|
||||
/* 64 bit symbol table entry. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word st_name; /* Symbol name (string tbl index) */
|
||||
Elf64_Byte st_info; /* Symbol type and binding */
|
||||
Elf64_Byte st_other; /* No defined meaning, 0 */
|
||||
Elf64_Section st_shndx; /* Section index */
|
||||
Elf64_Addr st_value; /* Symbol value */
|
||||
Elf64_Xword st_size; /* Symbol size */
|
||||
} Elf64_Sym;
|
||||
|
||||
/* The 64 bit st_info field is the same as the 32 bit one. */
|
||||
|
||||
#define ELF64_ST_BIND(val) (((unsigned char) (val)) >> 4)
|
||||
#define ELF64_ST_TYPE(val) ((val) & 0xf)
|
||||
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
/* I have seen two different definitions of the Elf64_Rel and
|
||||
Elf64_Rela structures, so we'll leave them out until Novell (or
|
||||
whoever) gets their act together. */
|
||||
|
||||
/* Auxiliary vector. */
|
||||
|
||||
/* This vector is normally only used by the program interpreter. The
|
||||
@@ -421,6 +482,17 @@ typedef struct
|
||||
} a_un;
|
||||
} Elf32_auxv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long int a_type; /* Entry type */
|
||||
union
|
||||
{
|
||||
long int a_val; /* Integer value */
|
||||
void *a_ptr; /* Pointer value */
|
||||
void (*a_fcn) (void); /* Function pointer value */
|
||||
} a_un;
|
||||
} Elf64_auxv_t;
|
||||
|
||||
/* Legal values for a_type (entry type). */
|
||||
|
||||
#define AT_NULL 0 /* End of vector */
|
||||
@@ -521,9 +593,17 @@ typedef struct
|
||||
#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
|
||||
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
|
||||
|
||||
/* Legal values for MIPS architecture level. */
|
||||
|
||||
#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
|
||||
#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
|
||||
#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
|
||||
|
||||
/* Special section indices. */
|
||||
|
||||
#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
|
||||
#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
|
||||
#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
|
||||
#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
|
||||
#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
|
||||
|
||||
@@ -535,6 +615,9 @@ typedef struct
|
||||
#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
|
||||
#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information */
|
||||
#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
|
||||
#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
|
||||
#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
|
||||
#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
|
||||
|
||||
/* Legal values for sh_flags field of Elf32_Shdr. */
|
||||
|
||||
@@ -602,7 +685,8 @@ typedef struct
|
||||
#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
|
||||
#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
|
||||
#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
|
||||
#define DT_MIPS_NUM 0x15
|
||||
#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
|
||||
#define DT_MIPS_NUM 0x17
|
||||
|
||||
/* Legal values for DT_MIPS_FLAG Elf32_Dyn entry. */
|
||||
|
||||
@@ -632,4 +716,62 @@ typedef struct
|
||||
typedef Elf32_Addr Elf32_Conflict;
|
||||
|
||||
|
||||
/* HPPA specific definitions. */
|
||||
|
||||
/* Legal values for sh_type field of Elf32_Shdr. */
|
||||
|
||||
#define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */
|
||||
#define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */
|
||||
#define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */
|
||||
#define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */
|
||||
#define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */
|
||||
#define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */
|
||||
#define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */
|
||||
#define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */
|
||||
#define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */
|
||||
#define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */
|
||||
|
||||
/* Legal values for sh_flags field of Elf32_Shdr. */
|
||||
|
||||
#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
|
||||
|
||||
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
|
||||
|
||||
#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
|
||||
|
||||
|
||||
/* Alpha specific declarations. */
|
||||
|
||||
/* Alpha relocs. */
|
||||
|
||||
#define R_ALPHA_NONE 0 /* No reloc */
|
||||
#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
|
||||
#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
|
||||
#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
|
||||
#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
|
||||
#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
|
||||
#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
|
||||
#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
|
||||
#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
|
||||
#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
|
||||
#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
|
||||
#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
|
||||
#define R_ALPHA_OP_PUSH 12 /* OP stack push */
|
||||
#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
|
||||
#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
|
||||
#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
|
||||
#define R_ALPHA_GPVALUE 16
|
||||
#define R_ALPHA_GPRELHIGH 17
|
||||
#define R_ALPHA_GPRELLOW 18
|
||||
#define R_ALPHA_IMMED_GP_16 19
|
||||
#define R_ALPHA_IMMED_GP_HI32 20
|
||||
#define R_ALPHA_IMMED_SCN_HI32 21
|
||||
#define R_ALPHA_IMMED_BR_HI32 22
|
||||
#define R_ALPHA_IMMED_LO32 23
|
||||
#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
|
||||
#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
|
||||
#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
|
||||
#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
|
||||
|
||||
|
||||
#endif /* elf.h */
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* Define the global function for the inline `elf_hash' in libelf.h. */
|
||||
|
||||
#define _EXTERN_INLINE /* Define the function globally. */
|
||||
#include "libelf.h"
|
||||
-283
@@ -1,283 +0,0 @@
|
||||
/* Interface for manipulating ELF object files; functions found in -lelf.
|
||||
Copyright (C) 1995 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., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef _LIBELF_H
|
||||
#define _LIBELF_H 1
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <elf.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Commands to operate on an Elf descriptor.
|
||||
The meanings are slightly different for the different functions. */
|
||||
typedef enum
|
||||
{
|
||||
ELF_C_NULL = 0,
|
||||
ELF_C_READ, /* Read from the file. */
|
||||
ELF_C_WRITE, /* Write the file, ignoring old contents. */
|
||||
ELF_C_CLR, /* Clear specified flag bits. */
|
||||
ELF_C_SET, /* Set specified flag bits. */
|
||||
ELF_C_FDDONE, /* Close the fd; no further io will happen. */
|
||||
ELF_C_FDREAD, /* Read the whole file, then close it. */
|
||||
ELF_C_RDWR, /* Read from and modify the file. */
|
||||
ELF_C_NUM /* Number of valid command values. */
|
||||
} Elf_Cmd;
|
||||
|
||||
|
||||
/* Flag bits for `elf_flag*'. */
|
||||
#define ELF_F_DIRTY 0x1 /* Object is */
|
||||
#define ELF_F_LAYOUT 0x4
|
||||
|
||||
|
||||
/* File types. */
|
||||
typedef enum
|
||||
{
|
||||
ELF_K_NONE = 0,
|
||||
ELF_K_AR,
|
||||
ELF_K_COFF, /* The GNU -lelf does not support COFF. */
|
||||
ELF_K_ELF,
|
||||
ELF_K_NUM /* Number of valid file kinds. */
|
||||
} Elf_Kind;
|
||||
|
||||
|
||||
/* Translation types. */
|
||||
typedef enum
|
||||
{
|
||||
ELF_T_BYTE = 0,
|
||||
ELF_T_ADDR,
|
||||
ELF_T_DYN,
|
||||
ELF_T_EHDR,
|
||||
ELF_T_HALF,
|
||||
ELF_T_OFF,
|
||||
ELF_T_PHDR,
|
||||
ELF_T_RELA,
|
||||
ELF_T_REL,
|
||||
ELF_T_SHDR,
|
||||
ELF_T_SWORD,
|
||||
ELF_T_SYM,
|
||||
ELF_T_WORD,
|
||||
ELF_T_NUM
|
||||
} Elf_Type;
|
||||
|
||||
|
||||
/* These types are opaque to user code; only pointers to them are used. */
|
||||
typedef struct Elf Elf;
|
||||
typedef struct Elf_Scn Elf_Scn;
|
||||
|
||||
|
||||
/* Archive member header. */
|
||||
typedef struct
|
||||
{
|
||||
char *ar_name;
|
||||
time_t ar_date;
|
||||
uid_t ar_uid;
|
||||
gid_t ar_gid;
|
||||
mode_t ar_mode;
|
||||
off_t ar_size;
|
||||
char *ar_rawname;
|
||||
} Elf_Arhdr;
|
||||
|
||||
/* Archive symbol table. */
|
||||
typedef struct
|
||||
{
|
||||
char *as_name;
|
||||
size_t as_off;
|
||||
unsigned long int as_hash;
|
||||
} Elf_Arsym;
|
||||
|
||||
|
||||
/* Data descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
void *d_buf;
|
||||
Elf_Type d_type;
|
||||
size_t d_size;
|
||||
off_t d_off; /* Offset into section. */
|
||||
size_t d_align; /* Alignment in section. */
|
||||
unsigned int d_version; /* ELF version. */
|
||||
} Elf_Data;
|
||||
|
||||
|
||||
|
||||
/* Open an Elf descriptor on file descriptor FD.
|
||||
REF is the Elf descriptor for the containing archive (to open a member);
|
||||
or the descriptor previously returned for FD (to add a user reference);
|
||||
or NULL. */
|
||||
extern Elf *elf_begin __P ((int __fd, Elf_Cmd __cmd, Elf *__ref));
|
||||
|
||||
/* Finish using ELF (remove a user reference); if this is the last user
|
||||
reference, its data will be freed. */
|
||||
extern int elf_end __P ((Elf *__elf));
|
||||
|
||||
/* Control the library's access to the file descriptor for ELF.
|
||||
CMD is either ELF_C_FDDONE or ELF_C_FDREAD. */
|
||||
extern int elf_cntl __P ((Elf *__elf, Elf_Cmd __cmd));
|
||||
|
||||
|
||||
/* Return a string describing an ELF error number. */
|
||||
extern __const char *elf_errmsg __P ((int __errno));
|
||||
|
||||
/* Return the ELF error number for the last failed operation. */
|
||||
extern int elf_errno __P ((void));
|
||||
|
||||
/* Set the byte value used to fill sections for alignment. */
|
||||
extern void elf_fill __P ((int __fillchar));
|
||||
|
||||
/* The following functions `elf_flag*' all operate the same way:
|
||||
CMD is either ELF_C_SET or ELF_C_CLR; FLAGS are `ELF_F_*' above,
|
||||
which are set or cleared for the object the call relates to. */
|
||||
|
||||
/* Modify flags affecting the file as a whole (?). */
|
||||
extern unsigned int elf_flagelf __P ((Elf *__elf, Elf_Cmd __cmd,
|
||||
unsigned int __flags));
|
||||
/* Modify flags affecting DATA. */
|
||||
extern unsigned int elf_flagdata __P ((Elf_Data *__data, Elf_Cmd __cmd,
|
||||
unsigned int __flags));
|
||||
/* Modify flags affecting the ELF header. */
|
||||
extern unsigned int elf_flagehdr __P ((Elf *__elf, Elf_Cmd __cmd,
|
||||
unsigned int __flags));
|
||||
/* Modify flags affecting the ELF program header. */
|
||||
extern unsigned int elf_flagphdr __P ((Elf *__elf, Elf_Cmd __cmd,
|
||||
unsigned int __flags));
|
||||
/* Modify flags affecting the given section's data. */
|
||||
extern unsigned int elf_flagscn __P ((Elf_Scn *__scn, Elf_Cmd __cmd,
|
||||
unsigned int __flags));
|
||||
/* Modify flags affecting the given section's header. */
|
||||
extern unsigned int elf_flagshdr __P ((Elf_Scn *__scn, Elf_Cmd __cmd,
|
||||
unsigned int __flags));
|
||||
|
||||
|
||||
extern size_t elf32_fsize __P ((Elf_Type __type, size_t __count,
|
||||
unsigned int __ver));
|
||||
|
||||
/* Return the archive header for ELF, which must describe an archive. */
|
||||
extern Elf_Arhdr *elf_getarhdr __P ((Elf *__elf));
|
||||
|
||||
/* Return the archive symbol table for ELF, and store
|
||||
in *NELTSP the number of elements in the table. */
|
||||
extern Elf_Arsym *elf_getarsym __P ((Elf *__elf, size_t *__neltsp));
|
||||
|
||||
/* Return the file offset for the beginning of ELF.
|
||||
If ELF describes an archive member, this points to the member header. */
|
||||
extern off_t elf_getbase __P ((Elf *__elf));
|
||||
|
||||
/* Extract the data from a section. */
|
||||
extern Elf_Data *elf_getdata __P ((Elf_Scn *__scn, Elf_Data *__data));
|
||||
|
||||
/* Extract the ELF header from the file. */
|
||||
extern Elf32_Ehdr *elf32_getehdr __P ((Elf *__elf));
|
||||
|
||||
/* Extract the initial ELF identification bytes from the file.
|
||||
If PTR is nonnull, the number of identification bytes is stored there. */
|
||||
extern char *elf_getident __P((Elf *__elf, size_t *__ptr));
|
||||
|
||||
/* Extract the ELF program header from the file. */
|
||||
extern Elf32_Phdr *elf32_getphdr __P ((Elf *__elf));
|
||||
|
||||
/* Extract the indicated section from the file. */
|
||||
extern Elf_Scn *elf_getscn __P ((Elf *__elf, size_t __index));
|
||||
|
||||
/* Extract the section header from the section. */
|
||||
extern Elf32_Shdr *elf32_getshdr __P ((Elf_Scn *__scn));
|
||||
|
||||
/* Return the index of the section following SCN. */
|
||||
extern size_t elf_ndxscn __P ((Elf_Scn *__scn));
|
||||
|
||||
|
||||
/* Standard ELF symbol name hash function. */
|
||||
extern unsigned long int elf_hash __P ((__const char *__name));
|
||||
|
||||
#if defined (__OPTIMIZE__) || defined (_EXTERN_INLINE)
|
||||
#ifndef _EXTERN_INLINE
|
||||
#define _EXTERN_INLINE extern __inline
|
||||
#endif
|
||||
_EXTERN_INLINE unsigned long int
|
||||
elf_hash (__const char *__name)
|
||||
{
|
||||
/* This is the hashing function specified by the ELF ABI. */
|
||||
unsigned long int __hash = 0;
|
||||
while (*__name != '\0')
|
||||
{
|
||||
unsigned long int __hi;
|
||||
__hash = (__hash << 4) + *__name++;
|
||||
__hi = __hash & 0xf0000000;
|
||||
if (__hi != 0)
|
||||
{
|
||||
__hash ^= __hi >> 24;
|
||||
/* The ELF ABI says `hash &= ~hi', but this is equivalent
|
||||
in this case and on some machines one insn instead of two. */
|
||||
__hash ^= __hi;
|
||||
}
|
||||
}
|
||||
return __hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the kind of file ELF describes. */
|
||||
extern Elf_Kind elf_kind __P ((Elf *__elf));
|
||||
|
||||
extern Elf_Data *elf_newdata __P ((Elf_Scn *__scn));
|
||||
|
||||
/* Create the ELF header for ELF. */
|
||||
extern Elf32_Ehdr *elf32_newehdr __P ((Elf *__elf));
|
||||
|
||||
/* Create the program header for ELF, with COUNT segments. */
|
||||
extern Elf32_Phdr *elf32_newphdr __P ((Elf *__elf, size_t __count));
|
||||
|
||||
/* Create a new section in ELF. */
|
||||
extern Elf_Scn *elf_newscn __P ((Elf *__elf));
|
||||
|
||||
/* Return the section following SCN. */
|
||||
extern Elf_Scn *elf_nextscn __P ((Elf *__elf, Elf_Scn *__scn));
|
||||
|
||||
/* Set up ELF to read the next archive member. */
|
||||
extern Elf_Cmd elf_next __P ((Elf *__elf));
|
||||
|
||||
/* Set up ELF (which must describe an archive) to read the
|
||||
archive member that starts at file position OFFSET. */
|
||||
extern size_t elf_rand __P ((Elf *__elf, size_t __offset));
|
||||
|
||||
extern Elf_Data *elf_rawdata __P ((Elf_Scn *__scn, Elf_Data *__data));
|
||||
|
||||
/* Read the entire file into memory; store its size in *PTR. */
|
||||
extern char *elf_rawfile __P ((Elf *__elf, size_t *__ptr));
|
||||
|
||||
/* Return a pointer to the string at OFFSET bytes into the string table.
|
||||
SECTION is the index of the SHT_STRTAB section in ELF. */
|
||||
extern char *elf_strptr __P ((Elf *__elf, size_t __section, size_t __offset));
|
||||
|
||||
/* If CMD is ELF_C_NULL, update ELF's data structures based on any
|
||||
user modifications, and set the ELF_F_DIRTY flag if anything changed.
|
||||
If CMD is ELF_C_WRITE, do that and then write the changes to the file. */
|
||||
extern off_t elf_update __P ((Elf *__elf, Elf_Cmd __cmd));
|
||||
|
||||
/* Handle ELF version VER. Return the old version handled,
|
||||
or EV_NONE if VER is unrecognized. */
|
||||
extern unsigned int elf_version __P ((unsigned int __ver));
|
||||
|
||||
extern Elf_Data *elf32_xlatetof __P ((Elf_Data *__dst, const Elf_Data *__src,
|
||||
unsigned int __encode));
|
||||
extern Elf_Data *elf32_xlatetom __P ((Elf_Data *__dst, const Elf_Data *__src,
|
||||
unsigned int __encode));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _LIBELF_H */
|
||||
+113
-37
@@ -20,8 +20,18 @@ Cambridge, MA 02139, USA. */
|
||||
#ifndef _LINK_H
|
||||
#define _LINK_H 1
|
||||
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
/* We use this macro to refer to ELF types independent of the native wordsize.
|
||||
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
|
||||
#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
|
||||
#define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type)
|
||||
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
|
||||
#define _ElfW_1(e,w,t) e##w##t
|
||||
#include <elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
|
||||
|
||||
/* Rendezvous structure used by the run-time dynamic linker to communicate
|
||||
details of shared object loading to the debugger. If the executable's
|
||||
@@ -39,7 +49,7 @@ struct r_debug
|
||||
library or unmap it, and again when the mapping change is complete.
|
||||
The debugger can set a breakpoint at this address if it wants to
|
||||
notice shared object mapping changes. */
|
||||
Elf32_Addr r_brk;
|
||||
ElfW(Addr) r_brk;
|
||||
enum
|
||||
{
|
||||
/* This state value describes the mapping change taking place when
|
||||
@@ -49,9 +59,12 @@ struct r_debug
|
||||
RT_DELETE, /* Beginning to remove an object mapping. */
|
||||
} r_state;
|
||||
|
||||
Elf32_Addr r_ldbase; /* Base address the linker is loaded at. */
|
||||
ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */
|
||||
};
|
||||
|
||||
/* This is the instance of that structure used by the dynamic linker. */
|
||||
extern struct r_debug _r_debug;
|
||||
|
||||
/* This symbol refers to the "dynamic structure" in the `.dynamic' section
|
||||
of whatever module refers to `_DYNAMIC'. So, to find its own
|
||||
`struct r_debug', a program could do:
|
||||
@@ -59,7 +72,7 @@ struct r_debug
|
||||
if (dyn->d_tag == DT_DEBUG) r_debug = (struct r_debug) dyn->d_un.d_ptr;
|
||||
*/
|
||||
|
||||
extern Elf32_Dyn _DYNAMIC[];
|
||||
extern ElfW(Dyn) _DYNAMIC[];
|
||||
|
||||
|
||||
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
||||
@@ -73,9 +86,9 @@ struct link_map
|
||||
/* These first few members are part of the protocol with the debugger.
|
||||
This is the same format used in SVR4. */
|
||||
|
||||
Elf32_Addr l_addr; /* Base address shared object is loaded at. */
|
||||
ElfW(Addr) l_addr; /* Base address shared object is loaded at. */
|
||||
char *l_name; /* Absolute file name object was found in. */
|
||||
Elf32_Dyn *l_ld; /* Dynamic section of the shared object. */
|
||||
ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
|
||||
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
|
||||
|
||||
/* All following members are internal to the dynamic linker.
|
||||
@@ -85,27 +98,36 @@ struct link_map
|
||||
/* Indexed pointers to dynamic section.
|
||||
[0,DT_NUM) are indexed by the processor-independent tags.
|
||||
[DT_NUM,DT_NUM+DT_PROCNUM] are indexed by the tag minus DT_LOPROC. */
|
||||
Elf32_Dyn *l_info[DT_NUM + DT_PROCNUM];
|
||||
const Elf32_Phdr *l_phdr; /* Pointer to program header table in core. */
|
||||
Elf32_Word l_phnum; /* Number of program header entries. */
|
||||
Elf32_Addr l_entry; /* Entry point location. */
|
||||
ElfW(Dyn) *l_info[DT_NUM + DT_PROCNUM];
|
||||
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
|
||||
ElfW(Addr) l_entry; /* Entry point location. */
|
||||
ElfW(Half) l_phnum; /* Number of program header entries. */
|
||||
|
||||
/* Array of DT_NEEDED dependencies and their dependencies, in
|
||||
dependency order for symbol lookup. This is null before the
|
||||
dependencies have been loaded. */
|
||||
struct link_map **l_searchlist;
|
||||
unsigned int l_nsearchlist;
|
||||
|
||||
/* Dependent object that first caused this object to be loaded. */
|
||||
struct link_map *l_loader;
|
||||
|
||||
/* Symbol hash table. */
|
||||
Elf32_Word l_nbuckets;
|
||||
const Elf32_Word *l_buckets, *l_chain;
|
||||
ElfW(Symndx) l_nbuckets;
|
||||
const ElfW(Symndx) *l_buckets, *l_chain;
|
||||
|
||||
unsigned int l_opencount; /* Reference count for dlopen/dlclose. */
|
||||
enum /* Where this object came from. */
|
||||
{
|
||||
lt_executable, /* The main executable program. */
|
||||
lt_interpreter, /* The interpreter: the dynamic linker. */
|
||||
lt_library, /* Library needed by main executable. */
|
||||
lt_loaded, /* Extra run-time loaded shared object. */
|
||||
} l_type:2;
|
||||
unsigned int l_deps_loaded:1; /* Nonzero if DT_NEEDED items loaded. */
|
||||
unsigned int l_relocated:1; /* Nonzero if object's relocations done. */
|
||||
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
|
||||
unsigned int l_init_running:1; /* Nonzero while DT_INIT function runs. */
|
||||
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
|
||||
unsigned int l_reserved:2; /* Reserved for internal use. */
|
||||
};
|
||||
|
||||
/* Internal functions of the run-time dynamic linker.
|
||||
@@ -117,6 +139,9 @@ struct link_map
|
||||
user interface to run-time dynamic linking. */
|
||||
|
||||
|
||||
/* Cached value of `getpagesize ()'. */
|
||||
extern size_t _dl_pagesize;
|
||||
|
||||
/* File descriptor referring to the zero-fill device. */
|
||||
extern int _dl_zerofd;
|
||||
|
||||
@@ -169,37 +194,79 @@ extern int _dlerror_run (void (*operate) (void));
|
||||
LOADER's DT_RPATH is used in searching for NAME.
|
||||
If the object is already opened, returns its existing map. */
|
||||
extern struct link_map *_dl_map_object (struct link_map *loader,
|
||||
const char *name);
|
||||
const char *name, int type);
|
||||
|
||||
/* Similar, but file found at REALNAME and opened on FD.
|
||||
REALNAME must malloc'd storage and is used in internal data structures. */
|
||||
extern struct link_map *_dl_map_object_from_fd (const char *name,
|
||||
int fd, char *realname);
|
||||
/* Call _dl_map_object on the dependencies of MAP, and
|
||||
set up MAP->l_searchlist. */
|
||||
extern void _dl_map_object_deps (struct link_map *map);
|
||||
|
||||
/* Cache the locations of MAP's hash table. */
|
||||
extern void _dl_setup_hash (struct link_map *map);
|
||||
|
||||
|
||||
/* Open the shared object NAME, relocate it, and run its initializer if it
|
||||
hasn't already been run. LOADER's DT_RPATH is used in searching for
|
||||
NAME. MODE is as for `dlopen' (see <dlfcn.h>). If the object is
|
||||
already opened, returns its existing map. */
|
||||
extern struct link_map *_dl_open (struct link_map *loader,
|
||||
const char *name, int mode);
|
||||
|
||||
/* Close an object previously opened by _dl_open. */
|
||||
extern void _dl_close (struct link_map *map);
|
||||
|
||||
|
||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||
referred to by UNDEF. *SYM is the symbol table entry containing the
|
||||
reference; it is replaced with the defining symbol, and the base load
|
||||
address of the defining object is returned. SYMBOL_SCOPE is the head of
|
||||
the chain used for searching. REFERENCE_NAME should name the object
|
||||
containing the reference; it is used in error messages. If NOSELF is
|
||||
nonzero, them *SYM itself cannot define the value; another binding must
|
||||
be found. */
|
||||
extern Elf32_Addr _dl_lookup_symbol (const char *undef,
|
||||
const Elf32_Sym **sym,
|
||||
struct link_map *symbol_scope,
|
||||
address of the defining object is returned. SYMBOL_SCOPE is a
|
||||
null-terminated list of object scopes to search; each object's
|
||||
l_searchlist (i.e. the segment of the dependency tree starting at that
|
||||
object) is searched in turn. REFERENCE_NAME should name the object
|
||||
containing the reference; it is used in error messages. RELOC_ADDR is
|
||||
the address being fixed up and the chosen symbol cannot be one with this
|
||||
value. If NOPLT is nonzero, then the reference must not be resolved to
|
||||
a PLT entry. */
|
||||
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
||||
const ElfW(Sym) **sym,
|
||||
struct link_map *symbol_scope[],
|
||||
const char *reference_name,
|
||||
int noself);
|
||||
ElfW(Addr) reloc_addr,
|
||||
int noplt);
|
||||
|
||||
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
||||
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name);
|
||||
|
||||
|
||||
/* List of objects currently loaded. */
|
||||
extern struct link_map *_dl_loaded;
|
||||
/* Structure describing the dynamic linker itself. */
|
||||
extern struct link_map _dl_rtld_map;
|
||||
|
||||
/* The list of objects currently loaded is the third element of the
|
||||
`_dl_default_scope' array, and the fourth element is always null.
|
||||
This leaves two slots before it that are used when resolving
|
||||
DT_SYMBOLIC objects' references one after it for normal references
|
||||
(see below). */
|
||||
#define _dl_loaded (_dl_default_scope[2])
|
||||
extern struct link_map *_dl_default_scope[5];
|
||||
|
||||
/* Null-terminated list of objects in the dynamic `global scope'. The
|
||||
list starts at [2]; i.e. &_dl_global_scope[2] is the argument
|
||||
passed to _dl_lookup_symbol to search the global scope. To search
|
||||
a specific object and its dependencies in preference to the global
|
||||
scope, fill in the [1] slot and pass its address; for two specific
|
||||
object scopes, fill [0] and [1]. The list is double-terminated; to
|
||||
search the global scope and then a specific object and its
|
||||
dependencies, set *_dl_global_scope_end. This variable initially
|
||||
points to _dl_default_scope, and _dl_loaded is always kept in [2]
|
||||
of this list. A new list is malloc'd when new objects are loaded
|
||||
with RTLD_GLOBAL. */
|
||||
extern struct link_map **_dl_global_scope, **_dl_global_scope_end;
|
||||
extern size_t _dl_global_scope_alloc; /* Number of slots malloc'd. */
|
||||
|
||||
/* Hack _dl_global_scope[0] and [1] as necessary, and return a pointer into
|
||||
_dl_global_scope that should be passed to _dl_lookup_symbol for symbol
|
||||
references made in the object MAP's relocations. */
|
||||
extern struct link_map **_dl_object_relocation_scope (struct link_map *map);
|
||||
|
||||
/* Tail of that list which were loaded at startup. */
|
||||
extern struct link_map *_dl_startup_loaded;
|
||||
|
||||
/* Allocate a `struct link_map' for a new object being loaded,
|
||||
and enter it into the _dl_loaded list. */
|
||||
@@ -207,13 +274,17 @@ extern struct link_map *_dl_new_object (char *realname, const char *libname,
|
||||
int type);
|
||||
|
||||
/* Relocate the given object (if it hasn't already been).
|
||||
SCOPE is passed to _dl_lookup_symbol in symbol lookups.
|
||||
If LAZY is nonzero, don't relocate its PLT. */
|
||||
extern void _dl_relocate_object (struct link_map *map, int lazy);
|
||||
extern void _dl_relocate_object (struct link_map *map,
|
||||
struct link_map *scope[],
|
||||
int lazy);
|
||||
|
||||
/* Return the address of the next initializer function not yet run.
|
||||
When there are no more initializers to be run, this returns zero.
|
||||
The functions are returned in the order they should be called. */
|
||||
extern Elf32_Addr _dl_init_next (void);
|
||||
/* Return the address of the next initializer function for MAP or one of
|
||||
its dependencies that has not yet been run. When there are no more
|
||||
initializers to be run, this returns zero. The functions are returned
|
||||
in the order they should be called. */
|
||||
extern ElfW(Addr) _dl_init_next (struct link_map *map);
|
||||
|
||||
/* Call the finalizer functions of all shared objects whose
|
||||
initializer functions have completed. */
|
||||
@@ -223,7 +294,12 @@ extern void _dl_fini (void);
|
||||
any shared object mappings. The `r_state' member of `struct r_debug'
|
||||
says what change is taking place. This function's address is
|
||||
the value of the `r_brk' member. */
|
||||
extern void _dl_r_debug_state (void);
|
||||
extern void _dl_debug_state (void);
|
||||
|
||||
/* Initialize `struct r_debug' if it has not already been done. The
|
||||
argument is the run-time load address of the dynamic linker, to be put
|
||||
in the `r_ldbase' member. Returns the address of the structure. */
|
||||
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
|
||||
|
||||
|
||||
#endif /* link.h */
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/* Initializer for Linux-compatible dynamic linker `/lib/ld-linux.so.1'.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -32,9 +32,10 @@ Cambridge, MA 02139, USA. */
|
||||
void
|
||||
_init (void)
|
||||
{
|
||||
const Elf32_Sym *ref = NULL;
|
||||
Elf32_Addr loadbase = _dl_lookup_symbol ("atexit", &ref, _dl_loaded,
|
||||
const ElfW(Sym) *ref = NULL;
|
||||
struct link_map *scope[2] = { _dl_loaded, NULL };
|
||||
ElfW(Addr) loadbase = _dl_lookup_symbol ("atexit", &ref, scope,
|
||||
"<ld-linux.so.1 initialization>",
|
||||
1);
|
||||
0, 1);
|
||||
(*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini);
|
||||
}
|
||||
|
||||
+242
-286
@@ -35,10 +35,10 @@ RTLD_START
|
||||
After this, file access calls and getenv must work. This is responsible
|
||||
for setting _dl_secure if we need to be secure (e.g. setuid),
|
||||
and for setting _dl_argc and _dl_argv, and then calling _dl_main. */
|
||||
extern Elf32_Addr _dl_sysdep_start (void **start_argptr,
|
||||
void (*dl_main) (const Elf32_Phdr *phdr,
|
||||
Elf32_Word phent,
|
||||
Elf32_Addr *user_entry));
|
||||
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
||||
void (*dl_main) (const ElfW(Phdr) *phdr,
|
||||
ElfW(Half) phent,
|
||||
ElfW(Addr) *user_entry));
|
||||
extern void _dl_sysdep_start_cleanup (void);
|
||||
|
||||
int _dl_secure;
|
||||
@@ -46,15 +46,13 @@ int _dl_argc;
|
||||
char **_dl_argv;
|
||||
const char *_dl_rpath;
|
||||
|
||||
struct r_debug dl_r_debug;
|
||||
static void dl_main (const ElfW(Phdr) *phdr,
|
||||
ElfW(Half) phent,
|
||||
ElfW(Addr) *user_entry);
|
||||
|
||||
static void dl_main (const Elf32_Phdr *phdr,
|
||||
Elf32_Word phent,
|
||||
Elf32_Addr *user_entry);
|
||||
struct link_map _dl_rtld_map;
|
||||
|
||||
static struct link_map rtld_map;
|
||||
|
||||
Elf32_Addr
|
||||
ElfW(Addr)
|
||||
_dl_start (void *arg)
|
||||
{
|
||||
struct link_map bootstrap_map;
|
||||
@@ -75,13 +73,6 @@ _dl_start (void *arg)
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
|
||||
/* We must initialize `l_type' to make sure it is not `lt_interpreter'.
|
||||
That is the type to describe us, but not during bootstrapping--it
|
||||
indicates to elf_machine_rel{,a} that we were already relocated during
|
||||
bootstrapping, so it must anti-perform each bootstrapping relocation
|
||||
before applying the final relocation when ld.so is linked in as
|
||||
normal a shared library. */
|
||||
bootstrap_map.l_type = lt_library;
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, NULL);
|
||||
|
||||
|
||||
@@ -92,22 +83,23 @@ _dl_start (void *arg)
|
||||
|
||||
|
||||
/* Transfer data about ourselves to the permanent link_map structure. */
|
||||
rtld_map.l_addr = bootstrap_map.l_addr;
|
||||
rtld_map.l_ld = bootstrap_map.l_ld;
|
||||
memcpy (rtld_map.l_info, bootstrap_map.l_info, sizeof rtld_map.l_info);
|
||||
_dl_setup_hash (&rtld_map);
|
||||
_dl_rtld_map.l_addr = bootstrap_map.l_addr;
|
||||
_dl_rtld_map.l_ld = bootstrap_map.l_ld;
|
||||
memcpy (_dl_rtld_map.l_info, bootstrap_map.l_info,
|
||||
sizeof _dl_rtld_map.l_info);
|
||||
_dl_setup_hash (&_dl_rtld_map);
|
||||
|
||||
/* Cache the DT_RPATH stored in ld.so itself; this will be
|
||||
the default search path. */
|
||||
_dl_rpath = (void *) (rtld_map.l_addr +
|
||||
rtld_map.l_info[DT_STRTAB]->d_un.d_ptr +
|
||||
rtld_map.l_info[DT_RPATH]->d_un.d_val);
|
||||
_dl_rpath = (void *) (_dl_rtld_map.l_addr +
|
||||
_dl_rtld_map.l_info[DT_STRTAB]->d_un.d_ptr +
|
||||
_dl_rtld_map.l_info[DT_RPATH]->d_un.d_val);
|
||||
|
||||
/* Call the OS-dependent function to set up life so we can do things like
|
||||
file access. It will call `dl_main' (below) to do all the real work
|
||||
of the dynamic linker, and then unwind our frame and run the user
|
||||
entry point on the same stack we entered on. */
|
||||
return _dl_sysdep_start (&arg, &dl_main);
|
||||
return _dl_sysdep_start (arg, &dl_main);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,37 +111,35 @@ void _start (void);
|
||||
unsigned int _dl_skip_args; /* Nonzero if we were run directly. */
|
||||
|
||||
static void
|
||||
dl_main (const Elf32_Phdr *phdr,
|
||||
Elf32_Word phent,
|
||||
Elf32_Addr *user_entry)
|
||||
dl_main (const ElfW(Phdr) *phdr,
|
||||
ElfW(Half) phent,
|
||||
ElfW(Addr) *user_entry)
|
||||
{
|
||||
void doit (void)
|
||||
const ElfW(Phdr) *ph;
|
||||
struct link_map *l;
|
||||
const char *interpreter_name;
|
||||
int lazy;
|
||||
int list_only = 0;
|
||||
|
||||
if (*user_entry == (ElfW(Addr)) &_start)
|
||||
{
|
||||
const Elf32_Phdr *ph;
|
||||
struct link_map *l, *last, *before_rtld;
|
||||
const char *interpreter_name;
|
||||
int lazy;
|
||||
int list_only = 0;
|
||||
/* Ho ho. We are not the program interpreter! We are the program
|
||||
itself! This means someone ran ld.so as a command. Well, that
|
||||
might be convenient to do sometimes. We support it by
|
||||
interpreting the args like this:
|
||||
|
||||
if (*user_entry == (Elf32_Addr) &_start)
|
||||
{
|
||||
/* Ho ho. We are not the program interpreter! We are the program
|
||||
itself! This means someone ran ld.so as a command. Well, that
|
||||
might be convenient to do sometimes. We support it by
|
||||
interpreting the args like this:
|
||||
ld.so PROGRAM ARGS...
|
||||
|
||||
ld.so PROGRAM ARGS...
|
||||
|
||||
The first argument is the name of a file containing an ELF
|
||||
executable we will load and run with the following arguments.
|
||||
To simplify life here, PROGRAM is searched for using the
|
||||
normal rules for shared objects, rather than $PATH or anything
|
||||
like that. We just load it and use its entry point; we don't
|
||||
pay attention to its PT_INTERP command (we are the interpreter
|
||||
ourselves). This is an easy way to test a new ld.so before
|
||||
installing it. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
The first argument is the name of a file containing an ELF
|
||||
executable we will load and run with the following arguments.
|
||||
To simplify life here, PROGRAM is searched for using the
|
||||
normal rules for shared objects, rather than $PATH or anything
|
||||
like that. We just load it and use its entry point; we don't
|
||||
pay attention to its PT_INTERP command (we are the interpreter
|
||||
ourselves). This is an easy way to test a new ld.so before
|
||||
installing it. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
Usage: ld.so [--list] EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
||||
You have invoked `ld.so', the helper program for shared library executables.\n\
|
||||
This program usually lives in the file `/lib/ld.so', and special directives\n\
|
||||
@@ -162,251 +152,217 @@ that file itself, but always uses this helper program from the file you\n\
|
||||
specified, instead of the helper program file specified in the executable\n\
|
||||
file you run. This is mostly of use for maintainers to test new versions\n\
|
||||
of this helper program; chances are you did not intend to run this program.\n",
|
||||
NULL);
|
||||
NULL);
|
||||
|
||||
interpreter_name = _dl_argv[0];
|
||||
interpreter_name = _dl_argv[0];
|
||||
|
||||
if (! strcmp (_dl_argv[1], "--list"))
|
||||
{
|
||||
list_only = 1;
|
||||
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
}
|
||||
if (! strcmp (_dl_argv[1], "--list"))
|
||||
{
|
||||
list_only = 1;
|
||||
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
|
||||
l = _dl_map_object (NULL, _dl_argv[0]);
|
||||
phdr = l->l_phdr;
|
||||
phent = l->l_phnum;
|
||||
l->l_name = (char *) "";
|
||||
*user_entry = l->l_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a link_map for the executable itself.
|
||||
This will be what dlopen on "" returns. */
|
||||
l = _dl_new_object ((char *) "", "", lt_executable);
|
||||
l->l_phdr = phdr;
|
||||
l->l_phnum = phent;
|
||||
interpreter_name = 0;
|
||||
l->l_entry = *user_entry;
|
||||
}
|
||||
|
||||
if (l != _dl_loaded)
|
||||
{
|
||||
/* GDB assumes that the first element on the chain is the
|
||||
link_map for the executable itself, and always skips it.
|
||||
Make sure the first one is indeed that one. */
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
l->l_prev = NULL;
|
||||
l->l_next = _dl_loaded;
|
||||
_dl_loaded->l_prev = l;
|
||||
_dl_loaded = l;
|
||||
}
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
|
||||
/* Scan the program header table for the dynamic section. */
|
||||
for (ph = phdr; ph < &phdr[phent]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
case PT_DYNAMIC:
|
||||
/* This tells us where to find the dynamic section,
|
||||
which tells us everything we need to do. */
|
||||
l->l_ld = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
find the program interpreter, which is this program itself, the
|
||||
dynamic linker. We note what name finds us, so that a future
|
||||
dlopen call or DT_NEEDED entry, for something that wants to link
|
||||
against the dynamic linker as a shared library, will know that
|
||||
the shared object is already loaded. */
|
||||
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
}
|
||||
assert (interpreter_name); /* How else did we get here? */
|
||||
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
if (l->l_info[DT_HASH])
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
_dl_setup_hash (l);
|
||||
|
||||
if (l->l_info[DT_DEBUG])
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure, which we
|
||||
will set up later to communicate with the debugger. */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
|
||||
|
||||
/* Put the link_map for ourselves on the chain so it can be found by
|
||||
name. */
|
||||
rtld_map.l_name = (char *) rtld_map.l_libname = interpreter_name;
|
||||
rtld_map.l_type = lt_interpreter;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
l->l_next = &rtld_map;
|
||||
rtld_map.l_prev = l;
|
||||
|
||||
/* Now process all the DT_NEEDED entries and map in the objects.
|
||||
Each new link_map will go on the end of the chain, so we will
|
||||
come across it later in the loop to map in its dependencies. */
|
||||
before_rtld = NULL;
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
{
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
const char *strtab
|
||||
= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
|
||||
const Elf32_Dyn *d;
|
||||
last = l;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
struct link_map *new;
|
||||
new = _dl_map_object (l, strtab + d->d_un.d_val);
|
||||
if (!before_rtld && new == &rtld_map)
|
||||
before_rtld = last;
|
||||
last = new;
|
||||
}
|
||||
}
|
||||
l->l_deps_loaded = 1;
|
||||
}
|
||||
|
||||
/* If any DT_NEEDED entry referred to the interpreter object itself,
|
||||
reorder the list so it appears after its dependent. If not,
|
||||
remove it from the maps we will use for symbol resolution. */
|
||||
rtld_map.l_prev->l_next = rtld_map.l_next;
|
||||
if (rtld_map.l_next)
|
||||
rtld_map.l_next->l_prev = rtld_map.l_prev;
|
||||
if (before_rtld)
|
||||
{
|
||||
rtld_map.l_prev = before_rtld;
|
||||
rtld_map.l_next = before_rtld->l_next;
|
||||
before_rtld->l_next = &rtld_map;
|
||||
if (rtld_map.l_next)
|
||||
rtld_map.l_next->l_prev = &rtld_map;
|
||||
}
|
||||
|
||||
if (list_only)
|
||||
{
|
||||
/* We were run just to list the shared libraries. It is
|
||||
important that we do this before real relocation, because the
|
||||
functions we call below for output may no longer work properly
|
||||
after relocation. */
|
||||
|
||||
int i;
|
||||
|
||||
if (! _dl_loaded->l_info[DT_NEEDED])
|
||||
_dl_sysdep_message ("\t", "statically linked\n", NULL);
|
||||
else
|
||||
for (l = _dl_loaded->l_next; l; l = l->l_next)
|
||||
{
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (l->l_addr, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof l->l_addr * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message ("\t", l->l_libname, " => ", l->l_name,
|
||||
" (0x", bp, ")\n", NULL);
|
||||
}
|
||||
|
||||
for (i = 1; i < _dl_argc; ++i)
|
||||
{
|
||||
const Elf32_Sym *ref = NULL;
|
||||
Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||
_dl_loaded, "argument",
|
||||
1);
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (_dl_argv[i], " found at 0x", bp, NULL);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (loadbase, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
|
||||
}
|
||||
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||
|
||||
/* Now we have all the objects loaded. Relocate them all except for
|
||||
the dynamic linker itself. We do this in reverse order so that
|
||||
copy relocs of earlier objects overwrite the data written by later
|
||||
objects. We do not re-relocate the dynamic linker itself in this
|
||||
loop because that could result in the GOT entries for functions we
|
||||
call being changed, and that would break us. It is safe to
|
||||
relocate the dynamic linker out of order because it has no copy
|
||||
relocs (we know that because it is self-contained). */
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
do
|
||||
{
|
||||
if (l != &rtld_map)
|
||||
_dl_relocate_object (l, lazy);
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
|
||||
/* Do any necessary cleanups for the startup OS interface code.
|
||||
We do these now so that no calls are made after rtld re-relocation
|
||||
which might be resolved to different functions than we expect.
|
||||
We cannot do this before relocating the other objects because
|
||||
_dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */
|
||||
_dl_sysdep_start_cleanup ();
|
||||
|
||||
if (rtld_map.l_opencount > 0)
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||
_dl_relocate_object (&rtld_map, lazy);
|
||||
|
||||
/* Tell the debugger where to find the map of loaded objects. */
|
||||
dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||
dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address. */
|
||||
dl_r_debug.r_map = _dl_loaded;
|
||||
dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
|
||||
|
||||
if (rtld_map.l_info[DT_INIT])
|
||||
{
|
||||
/* Call the initializer for the compatibility version of the
|
||||
dynamic linker. There is no additional initialization
|
||||
required for the ABI-compliant dynamic linker. */
|
||||
|
||||
(*(void (*) (void)) (rtld_map.l_addr +
|
||||
rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
|
||||
|
||||
/* Clear the field so a future dlopen won't run it again. */
|
||||
rtld_map.l_info[DT_INIT] = NULL;
|
||||
}
|
||||
l = _dl_map_object (NULL, _dl_argv[0], lt_library);
|
||||
phdr = l->l_phdr;
|
||||
phent = l->l_phnum;
|
||||
l->l_name = (char *) "";
|
||||
*user_entry = l->l_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a link_map for the executable itself.
|
||||
This will be what dlopen on "" returns. */
|
||||
l = _dl_new_object ((char *) "", "", lt_library);
|
||||
l->l_phdr = phdr;
|
||||
l->l_phnum = phent;
|
||||
interpreter_name = 0;
|
||||
l->l_entry = *user_entry;
|
||||
}
|
||||
const char *errstring;
|
||||
const char *errobj;
|
||||
int err;
|
||||
|
||||
err = _dl_catch_error (&errstring, &errobj, &doit);
|
||||
if (errstring)
|
||||
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
|
||||
": error in loading shared libraries\n",
|
||||
errobj ?: "", errobj ? ": " : "",
|
||||
errstring, err ? ": " : "",
|
||||
err ? strerror (err) : "", "\n", NULL);
|
||||
if (l != _dl_loaded)
|
||||
{
|
||||
/* GDB assumes that the first element on the chain is the
|
||||
link_map for the executable itself, and always skips it.
|
||||
Make sure the first one is indeed that one. */
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
l->l_prev = NULL;
|
||||
l->l_next = _dl_loaded;
|
||||
_dl_loaded->l_prev = l;
|
||||
_dl_loaded = l;
|
||||
}
|
||||
|
||||
/* Scan the program header table for the dynamic section. */
|
||||
for (ph = phdr; ph < &phdr[phent]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
case PT_DYNAMIC:
|
||||
/* This tells us where to find the dynamic section,
|
||||
which tells us everything we need to do. */
|
||||
l->l_ld = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
find the program interpreter, which is this program itself, the
|
||||
dynamic linker. We note what name finds us, so that a future
|
||||
dlopen call or DT_NEEDED entry, for something that wants to link
|
||||
against the dynamic linker as a shared library, will know that
|
||||
the shared object is already loaded. */
|
||||
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
}
|
||||
assert (interpreter_name); /* How else did we get here? */
|
||||
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
if (l->l_info[DT_HASH])
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
_dl_setup_hash (l);
|
||||
|
||||
/* Put the link_map for ourselves on the chain so it can be found by
|
||||
name. */
|
||||
_dl_rtld_map.l_name = (char *) _dl_rtld_map.l_libname = interpreter_name;
|
||||
_dl_rtld_map.l_type = lt_library;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
l->l_next = &_dl_rtld_map;
|
||||
_dl_rtld_map.l_prev = l;
|
||||
|
||||
/* Load all the libraries specified by DT_NEEDED entries. */
|
||||
_dl_map_object_deps (l);
|
||||
|
||||
/* XXX if kept, move it so l_next list is in dep order because
|
||||
it will determine gdb's search order.
|
||||
Perhaps do this always, so later dlopen by name finds it?
|
||||
XXX But then gdb always considers it present. */
|
||||
if (_dl_rtld_map.l_opencount == 0)
|
||||
{
|
||||
/* No DT_NEEDED entry referred to the interpreter object itself,
|
||||
so remove it from the list of visible objects. */
|
||||
_dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;
|
||||
if (_dl_rtld_map.l_next)
|
||||
_dl_rtld_map.l_next->l_prev = _dl_rtld_map.l_prev;
|
||||
}
|
||||
|
||||
if (list_only)
|
||||
{
|
||||
/* We were run just to list the shared libraries. It is
|
||||
important that we do this before real relocation, because the
|
||||
functions we call below for output may no longer work properly
|
||||
after relocation. */
|
||||
|
||||
int i;
|
||||
|
||||
if (! _dl_loaded->l_info[DT_NEEDED])
|
||||
_dl_sysdep_message ("\t", "statically linked\n", NULL);
|
||||
else
|
||||
for (l = _dl_loaded->l_next; l; l = l->l_next)
|
||||
{
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (l->l_addr, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof l->l_addr * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message ("\t", l->l_libname, " => ", l->l_name,
|
||||
" (0x", bp, ")\n", NULL);
|
||||
}
|
||||
|
||||
for (i = 1; i < _dl_argc; ++i)
|
||||
{
|
||||
const ElfW(Sym) *ref = NULL;
|
||||
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||
&_dl_default_scope[2],
|
||||
"argument", 0, 0);
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (_dl_argv[i], " found at 0x", bp, NULL);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
bp = _itoa (loadbase, &buf[sizeof buf - 1], 16, 0);
|
||||
while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
|
||||
*--bp = '0';
|
||||
_dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
|
||||
}
|
||||
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||
|
||||
{
|
||||
/* Now we have all the objects loaded. Relocate them all except for
|
||||
the dynamic linker itself. We do this in reverse order so that copy
|
||||
relocs of earlier objects overwrite the data written by later
|
||||
objects. We do not re-relocate the dynamic linker itself in this
|
||||
loop because that could result in the GOT entries for functions we
|
||||
call being changed, and that would break us. It is safe to relocate
|
||||
the dynamic linker out of order because it has no copy relocs (we
|
||||
know that because it is self-contained). */
|
||||
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
do
|
||||
{
|
||||
if (l != &_dl_rtld_map)
|
||||
{
|
||||
_dl_relocate_object (l, _dl_object_relocation_scope (l), lazy);
|
||||
*_dl_global_scope_end = NULL;
|
||||
}
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
|
||||
/* Do any necessary cleanups for the startup OS interface code.
|
||||
We do these now so that no calls are made after rtld re-relocation
|
||||
which might be resolved to different functions than we expect.
|
||||
We cannot do this before relocating the other objects because
|
||||
_dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */
|
||||
_dl_sysdep_start_cleanup ();
|
||||
|
||||
if (_dl_rtld_map.l_opencount > 0)
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||
_dl_relocate_object (&_dl_rtld_map, &_dl_default_scope[2], 0);
|
||||
}
|
||||
|
||||
{
|
||||
/* Initialize _r_debug. */
|
||||
struct r_debug *r = _dl_debug_initialize (_dl_rtld_map.l_addr);
|
||||
|
||||
l = _dl_loaded;
|
||||
if (l->l_info[DT_DEBUG])
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
|
||||
|
||||
/* Notify the debugger that all objects are now mapped in. */
|
||||
r->r_state = RT_ADD;
|
||||
_dl_debug_state ();
|
||||
}
|
||||
|
||||
if (_dl_rtld_map.l_info[DT_INIT])
|
||||
{
|
||||
/* Call the initializer for the compatibility version of the
|
||||
dynamic linker. There is no additional initialization
|
||||
required for the ABI-compliant dynamic linker. */
|
||||
|
||||
(*(void (*) (void)) (_dl_rtld_map.l_addr +
|
||||
_dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
|
||||
|
||||
/* Clear the field so a future dlopen won't run it again. */
|
||||
_dl_rtld_map.l_info[DT_INIT] = NULL;
|
||||
}
|
||||
|
||||
/* Once we return, _dl_sysdep_start will invoke
|
||||
the DT_INIT functions and then *USER_ENTRY. */
|
||||
}
|
||||
|
||||
/* This function exists solely to have a breakpoint set on it by the
|
||||
debugger. */
|
||||
void
|
||||
_dl_r_debug_state (void)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ 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, 1992 Free Software Foundation, Inc., 675 Mass Ave,
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
@@ -37,6 +37,7 @@ __BEGIN_DECLS
|
||||
#undef __need_Emath
|
||||
|
||||
#ifdef _ERRNO_H
|
||||
|
||||
/* Declare the `errno' variable, unless it's defined as a macro by
|
||||
errnos.h. This is the case in GNU, where it is a per-thread variable.
|
||||
This redeclaration using the macro still works, but it will be a
|
||||
@@ -47,13 +48,22 @@ extern int errno;
|
||||
#endif
|
||||
|
||||
#ifdef __USE_GNU
|
||||
|
||||
/* The Hurd <errnos.h> defines `error_t' as an enumerated type
|
||||
so that printing `error_t' values in the debugger shows the names. */
|
||||
#ifndef __error_t_defined
|
||||
typedef int error_t;
|
||||
#define __error_t_defined 1
|
||||
#endif
|
||||
|
||||
/* The full and simple forms of the name with which the program was
|
||||
invoked. These variables are set up automatically at startup based on
|
||||
the value of ARGV[0] (this works only if you use GNU ld). */
|
||||
extern char *program_invocation_name, *program_invocation_short_name;
|
||||
#endif
|
||||
#endif /* Use GNU. */
|
||||
|
||||
#endif /* errno.h included */
|
||||
|
||||
__END_DECLS
|
||||
#endif
|
||||
|
||||
#endif /* errno.h */
|
||||
#endif /* errno.h */
|
||||
|
||||
+13
-4
@@ -10,6 +10,8 @@ extra-libs-left := $(filter-out $(lib),$(extra-libs-left))
|
||||
|
||||
object-suffixes-$(lib) := $(filter-out $($(lib)-inhibit-o),$(object-suffixes))
|
||||
|
||||
ifneq (,$(object-suffixes-$(lib)))
|
||||
|
||||
# Make sure these are simply-expanded variables before we append to them,
|
||||
# since we want the expressions we append to be expanded right now.
|
||||
install-lib := $(install-lib)
|
||||
@@ -17,13 +19,11 @@ extra-objs := $(extra-objs)
|
||||
|
||||
# Add each flavor of library to the lists of things to build and install.
|
||||
install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
|
||||
extra-objs += $(foreach o,$(object-suffixes-$(lib)),$($(lib)-routines:=$o))
|
||||
extra-objs += $(foreach o,$(object-suffixes-$(lib)),\
|
||||
$(patsubst %,%$o,$($(lib)-routines)))
|
||||
alltypes-$(lib) := $(foreach o,$(object-suffixes-$(lib)),\
|
||||
$(objpfx)$(patsubst %,$(libtype$o),\
|
||||
$(lib:lib%=%)))
|
||||
ifneq (,$(filter .so,$(object-suffixes-$(lib))))
|
||||
alltypes-$(lib) += $(objpfx)$(lib).so
|
||||
endif
|
||||
|
||||
ifeq (,$($(lib)-no-lib-dep))
|
||||
lib-noranlib: $(alltypes-$(lib))
|
||||
@@ -31,6 +31,13 @@ else
|
||||
others: $(alltypes-$(lib))
|
||||
endif
|
||||
|
||||
# The linked shared library is never a dependent of lib-noranlib,
|
||||
# because linking it will depend on libc.so already being built.
|
||||
ifneq (,$(filter .so,$(object-suffixes-$(lib))))
|
||||
others: $(objpfx)$(lib).so
|
||||
endif
|
||||
|
||||
|
||||
# Use o-iterator.mk to generate a rule for each flavor of library.
|
||||
define o-iterator-doit
|
||||
$(objpfx)$(patsubst %,$(libtype$o),$(lib:lib%=%)): \
|
||||
@@ -38,3 +45,5 @@ $(objpfx)$(patsubst %,$(libtype$o),$(lib:lib%=%)): \
|
||||
endef
|
||||
object-suffixes-left = $(object-suffixes-$(lib))
|
||||
include $(patsubst %,$(..)o-iterator.mk,$(object-suffixes-$(lib)))
|
||||
|
||||
endif
|
||||
|
||||
+21
-11
@@ -50,7 +50,6 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
The macro `__GNU_LIBRARY__' is defined by this file unconditionally.
|
||||
|
||||
All macros defined by this file are defined as 1.
|
||||
All macros listed above as possibly being defined by this file are
|
||||
explicitly undefined if they are not explicitly defined.
|
||||
Feature-test macros that are not defined by the user or compiler
|
||||
@@ -80,32 +79,43 @@ Cambridge, MA 02139, USA. */
|
||||
#define __FAVOR_BSD 1
|
||||
#endif
|
||||
|
||||
/* If _GNU_SOURCE was defined by the user, turn on all the other features. */
|
||||
#ifdef _GNU_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#undef _BSD_SOURCE
|
||||
#define _BSD_SOURCE 1
|
||||
#undef _SVID_SOURCE
|
||||
#define _SVID_SOURCE 1
|
||||
#endif
|
||||
|
||||
/* If nothing (other than _GNU_SOURCE) is defined,
|
||||
define _BSD_SOURCE and _SVID_SOURCE. */
|
||||
#if (!defined(__STRICT_ANSI__) && !defined(_POSIX_SOURCE) && \
|
||||
!defined(_POSIX_C_SOURCE) && !defined(_BSD_SOURCE) && \
|
||||
!defined(_SVID_SOURCE))
|
||||
#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE) && \
|
||||
!defined (_POSIX_C_SOURCE) && !defined (_BSD_SOURCE) && \
|
||||
!defined (_SVID_SOURCE))
|
||||
#define _BSD_SOURCE 1
|
||||
#define _SVID_SOURCE 1
|
||||
#endif
|
||||
|
||||
/* If none of the ANSI/POSIX macros are defined, use POSIX.1 and POSIX.2. */
|
||||
#if (!defined(__STRICT_ANSI__) && !defined(_POSIX_SOURCE) && \
|
||||
!defined(_POSIX_C_SOURCE))
|
||||
#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE) && \
|
||||
!defined (_POSIX_C_SOURCE))
|
||||
#define _POSIX_SOURCE 1
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_SOURCE) || _POSIX_C_SOURCE >= 1
|
||||
#if defined (_POSIX_SOURCE) || _POSIX_C_SOURCE >= 1
|
||||
#define __USE_POSIX 1
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 2
|
||||
#if defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 2
|
||||
#define __USE_POSIX2 1
|
||||
#endif
|
||||
|
||||
#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE)
|
||||
#if defined (_BSD_SOURCE) || defined (_SVID_SOURCE)
|
||||
#define __USE_MISC 1
|
||||
#endif
|
||||
|
||||
@@ -133,10 +143,10 @@ Cambridge, MA 02139, USA. */
|
||||
the shared C library corresponding to this set of header files. */
|
||||
|
||||
#undef __GNU_LIBRARY__
|
||||
#define __GNU_LIBRARY__ 5
|
||||
#define __GNU_LIBRARY__ 6
|
||||
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__ < 2
|
||||
#if !defined (__GNUC__) || __GNUC__ < 2
|
||||
/* In GCC version 2, (__extension__ EXPR) will not complain
|
||||
about GCC extensions used in EXPR under -ansi or -pedantic. */
|
||||
#define __extension__
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
subdir := gmon
|
||||
|
||||
headers := sys/gmon.h sys/gmon_out.h
|
||||
distribute := machine-gmon.h
|
||||
distribute := machine-gmon.h profil-counter.h
|
||||
routines := gmon mcount profil bb_init_func bb_exit_func
|
||||
|
||||
include ../Rules
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include <signal/gnu/signal.h>
|
||||
@@ -1 +0,0 @@
|
||||
#include <time/gnu/time.h>
|
||||
@@ -1 +0,0 @@
|
||||
#include <posix/gnu/wait.h>
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 1992, 1995, 1996 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
|
||||
@@ -13,7 +13,7 @@ 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, 1992 Free Software Foundation, Inc., 675 Mass Ave,
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
|
||||
*.gz *.Z *.tar *.tgz
|
||||
=*
|
||||
TODO COPYING* AUTHORS copyr-* copying.*
|
||||
|
||||
+8
-34
@@ -25,11 +25,9 @@ include ../Makeconfig
|
||||
|
||||
|
||||
headers = hurd.h $(interface-headers) \
|
||||
$(addprefix hurd/,fd.h id.h port.h signal.h sigpreempt.h \
|
||||
$(addprefix hurd/,fd.h id.h port.h signal.h sigpreempt.h ioctl.h\
|
||||
userlink.h resource.h threadvar.h lookup.h)
|
||||
|
||||
distribute := hurdstartup.h hurdfault.h intr-rpc.defs STATUS
|
||||
|
||||
# The RPC interfaces go in a separate library.
|
||||
interface-library := libhurduser
|
||||
user-interfaces := $(addprefix hurd/,\
|
||||
@@ -38,10 +36,11 @@ user-interfaces := $(addprefix hurd/,\
|
||||
msg msg_reply msg_request \
|
||||
exec exec_startup crash interrupt \
|
||||
fs fsys io term tioctl socket ifsock)
|
||||
server-interfaces := hurd/msg
|
||||
server-interfaces := hurd/msg faultexc
|
||||
|
||||
routines = hurdstartup hurdinit \
|
||||
hurdid hurdlookup hurdpid hurdrlimit hurdprio hurdexec \
|
||||
path-lookup \
|
||||
setauth \
|
||||
pid2task task2pid \
|
||||
getuids setuids getumask fchroot \
|
||||
@@ -52,39 +51,18 @@ routines = hurdstartup hurdinit \
|
||||
vpprintf \
|
||||
ports-get ports-set hurdports hurdmsg \
|
||||
$(sig) $(dtable) hurdinline port-cleanup report-wait
|
||||
sig = hurdsig hurdfault faultexc siginfo hurd-raise preempt-sig \
|
||||
sig = hurdsig hurdfault siginfo hurd-raise preempt-sig \
|
||||
trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind \
|
||||
thread-self thread-cancel intr-msg catch-signal
|
||||
dtable = dtable port2fd new-fd alloc-fd intern-fd \
|
||||
getdport openport \
|
||||
fd-close fd-read fd-write hurdioctl ctty-input ctty-output
|
||||
distribute = hurdstartup.h hurdfault.h faultexc.defs intr-rpc.defs intr-rpc.h
|
||||
|
||||
# XXX this is a temporary hack; see hurdmalloc.h
|
||||
routines += hurdmalloc
|
||||
distribute += hurdmalloc.h
|
||||
|
||||
# Get the proper definition of `hurd-srcdir'.
|
||||
include ../sysdeps/mach/hurd/Makefile
|
||||
|
||||
# Use and install the Hurd header files directly out of the Hurd source.
|
||||
|
||||
# Find the MiG defs files in the Hurd source.
|
||||
vpath %.defs $(hurd-srcdir)
|
||||
|
||||
# Install all .h and .defs files we find in the Hurd's hurd/ directory.
|
||||
hurd-headers := $(patsubst $(hurd-srcdir)/%,%,\
|
||||
$(wildcard $(addprefix $(hurd-srcdir)/hurd/,\
|
||||
*.defs *.h)))
|
||||
|
||||
|
||||
# Don't distribute the Hurd headers; they are in the Hurd distribution.
|
||||
dont_distribute = $(hurd-headers)
|
||||
|
||||
# DO NOT try to remake these in any way!!!
|
||||
$(addprefix $(hurd-srcdir)/,$(hurd-headers)) : ;
|
||||
install-others += $(addprefix $(includedir)/,$(hurd-headers))
|
||||
$(includedir)/hurd/%: $(hurd-srcdir)/hurd/%; $(do-install)
|
||||
|
||||
include ../mach/Machrules
|
||||
include ../Rules
|
||||
|
||||
@@ -93,13 +71,9 @@ include ../Rules
|
||||
# _hurd_intr_rpc_mach_msg.
|
||||
user-MIGFLAGS += -imacros intr-rpc.defs
|
||||
|
||||
$(objpfx)fault%.c $(objpfx)fault%.h: $(mach-srcdir)/mach/%.defs
|
||||
$(MIG) $(MIGFLAGS) -prefix _hurdsig_fault_ \
|
||||
-server $(@:.h=.c) -sheader $(@:.c=.h) \
|
||||
-user /dev/null -header /dev/null \
|
||||
$<
|
||||
generated += faultexc.c faultexc.h
|
||||
# The special exc server for sigthread faults uses a special prefix.
|
||||
MIGFLAGS-faultexc = -prefix _hurdsig_fault_
|
||||
|
||||
# We need this static dependency to get faultexc.h generated the first time.
|
||||
$(objpfx)hurdfault.o $(objpfx)hurdfault.d: \
|
||||
$(objpfx)faultexc.h $(objpfx)faultexc.c
|
||||
$(objpfx)faultexc_server.h $(objpfx)faultexc_server.c
|
||||
|
||||
+10
-7
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994, 1995, 1996 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
|
||||
@@ -29,18 +29,21 @@ _S_catch_exception_raise (mach_port_t port,
|
||||
int code,
|
||||
int subcode)
|
||||
{
|
||||
int signo, error;
|
||||
long int sigcode;
|
||||
struct hurd_sigstate *ss;
|
||||
int signo;
|
||||
struct hurd_signal_detail d;
|
||||
|
||||
if (task != __mach_task_self ())
|
||||
/* The sender wasn't the kernel. */
|
||||
return EPERM;
|
||||
|
||||
d.exc = exception;
|
||||
d.exc_code = code;
|
||||
d.exc_subcode = subcode;
|
||||
|
||||
/* Call the machine-dependent function to translate the Mach exception
|
||||
codes into a signal number and subcode. */
|
||||
_hurd_exception2signal (exception, code, subcode,
|
||||
&signo, &sigcode, &error);
|
||||
_hurd_exception2signal (&d, &signo);
|
||||
|
||||
/* Find the sigstate structure for the faulting thread. */
|
||||
__mutex_lock (&_hurd_siglock);
|
||||
@@ -64,13 +67,13 @@ _S_catch_exception_raise (mach_port_t port,
|
||||
no code should do anything that can fault while holding the
|
||||
sigstate lock. */
|
||||
|
||||
ss->critical_section = 0;
|
||||
__spin_unlock (&ss->critical_section_lock);
|
||||
ss->context = NULL;
|
||||
__spin_unlock (&ss->lock);
|
||||
}
|
||||
|
||||
/* Post the signal. */
|
||||
_hurd_internal_post_signal (ss, signo, sigcode, error,
|
||||
_hurd_internal_post_signal (ss, signo, &d,
|
||||
MACH_PORT_NULL, MACH_MSG_TYPE_PORT_SEND,
|
||||
0);
|
||||
|
||||
|
||||
+4
-6
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 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
|
||||
@@ -173,7 +173,7 @@ static void
|
||||
ctty_new_pgrp (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
HURD_CRITICAL_BEGIN;
|
||||
__mutex_lock (&_hurd_dtable_lock);
|
||||
|
||||
@@ -226,7 +226,7 @@ reauth_dtable (void)
|
||||
{
|
||||
struct hurd_fd *const d = _hurd_dtable[i];
|
||||
mach_port_t new, newctty, ref;
|
||||
|
||||
|
||||
if (d == NULL)
|
||||
/* Nothing to do for an unused descriptor cell. */
|
||||
continue;
|
||||
@@ -235,14 +235,13 @@ reauth_dtable (void)
|
||||
|
||||
/* Take the descriptor cell's lock. */
|
||||
__spin_lock (&d->port.lock);
|
||||
|
||||
|
||||
/* Reauthenticate the descriptor's port. */
|
||||
if (d->port.port != MACH_PORT_NULL &&
|
||||
! __io_reauthenticate (d->port.port,
|
||||
ref, MACH_MSG_TYPE_MAKE_SEND) &&
|
||||
! __USEPORT (AUTH, __auth_user_authenticate
|
||||
(port,
|
||||
d->port.port,
|
||||
ref, MACH_MSG_TYPE_MAKE_SEND,
|
||||
&new)))
|
||||
{
|
||||
@@ -254,7 +253,6 @@ reauth_dtable (void)
|
||||
ref, MACH_MSG_TYPE_MAKE_SEND) &&
|
||||
! __USEPORT (AUTH, __auth_user_authenticate
|
||||
(port,
|
||||
d->ctty.port,
|
||||
ref, MACH_MSG_TYPE_MAKE_SEND,
|
||||
&newctty)))
|
||||
_hurd_port_set (&d->ctty, newctty);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/* This file is processed by mig with -prefix _hurdsig_fault_
|
||||
to create the special exception server used for signal thread
|
||||
fault recovery. */
|
||||
|
||||
#include <mach/exc.defs>
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994, 1995, 1996 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
|
||||
@@ -27,7 +27,7 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
void
|
||||
_hurd_raise_signal (struct hurd_sigstate *ss,
|
||||
int signo, long int sigcode, int sigerror)
|
||||
int signo, const struct hurd_signal_detail *detail)
|
||||
{
|
||||
if (ss == NULL)
|
||||
{
|
||||
@@ -37,12 +37,11 @@ _hurd_raise_signal (struct hurd_sigstate *ss,
|
||||
|
||||
/* Mark SIGNO as pending to be delivered. */
|
||||
__sigaddset (&ss->pending, signo);
|
||||
ss->pending_data[signo].code = sigcode;
|
||||
ss->pending_data[signo].error = sigerror;
|
||||
ss->pending_data[signo] = *detail;
|
||||
|
||||
__spin_unlock (&ss->lock);
|
||||
|
||||
/* Send a message to the signal thread so it
|
||||
will wake up and check for pending signals. */
|
||||
__msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
|
||||
__msg_sig_post (_hurd_msgport, signo, detail->code, __mach_task_self ());
|
||||
}
|
||||
|
||||
+16
@@ -76,6 +76,7 @@ extern int _hurd_exec_flags; /* Flags word passed in exec_startup. */
|
||||
extern struct hurd_port *_hurd_ports;
|
||||
extern unsigned int _hurd_nports;
|
||||
extern volatile mode_t _hurd_umask;
|
||||
extern sigset_t _hurdsig_traced;
|
||||
|
||||
/* Shorthand macro for internal library code referencing _hurd_ports (see
|
||||
<hurd/port.h>). */
|
||||
@@ -183,6 +184,21 @@ extern file_t file_name_lookup_under (file_t startdir, const char *file,
|
||||
int flags, mode_t mode);
|
||||
|
||||
|
||||
/* Lookup FILE_NAME and return the node opened with FLAGS & MODE
|
||||
(see hurd_file_name_lookup for details), but a simple file name (without
|
||||
any directory prefixes) will be consecutively prefixed with the pathnames
|
||||
in the `:' separated list PATH until one succeeds in a successful lookup.
|
||||
If none succeed, then the first error that wasn't ENOENT is returned, or
|
||||
ENOENT if no other errors were returned. If PREFIXED_NAME is non-NULL,
|
||||
then if the result is looked up directly, *PREFIXED_NAME is set to NULL, and
|
||||
if it is looked up using a prefix from PATH, *PREFIXED_NAME is set to
|
||||
malloc'd storage containing the prefixed name. */
|
||||
extern file_t file_name_path_lookup (const char *file_name, const char *path,
|
||||
int flags, mode_t mode,
|
||||
char **prefixed_name);
|
||||
|
||||
|
||||
|
||||
/* Open a file descriptor on a port. FLAGS are as for `open'; flags
|
||||
affected by io_set_openmodes are not changed by this. If successful,
|
||||
this consumes a user reference for PORT (which will be deallocated on
|
||||
|
||||
+7
-3
@@ -1,5 +1,5 @@
|
||||
/* File descriptors.
|
||||
Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1995, 1996 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
|
||||
@@ -153,14 +153,18 @@ _hurd_fd_error_signal (error_t err)
|
||||
|
||||
/* Handle an error from an RPC on a file descriptor's port. You should
|
||||
always use this function to handle errors from RPCs made on file
|
||||
descriptor ports. Some errors are translated into signals. */
|
||||
descriptor ports. Some errors are translated into signals. */
|
||||
|
||||
_EXTERN_INLINE error_t
|
||||
_hurd_fd_error (int fd, error_t err)
|
||||
{
|
||||
int signo = _hurd_fd_error_signal (err);
|
||||
if (signo)
|
||||
_hurd_raise_signal (NULL, signo, fd, err);
|
||||
{
|
||||
const struct hurd_signal_detail detail
|
||||
= { code: fd, error: err, exc: 0 };
|
||||
_hurd_raise_signal (NULL, signo, &detail);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
+30
-1
@@ -1,5 +1,5 @@
|
||||
/* Declarations of file name translation functions for the GNU Hurd.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 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
|
||||
@@ -98,4 +98,33 @@ error_t hurd_file_name_lookup_retry (error_t (*use_init_port)
|
||||
file_t *result);
|
||||
|
||||
|
||||
/* If FILE_NAME contains a '/', or PATH is NULL, call FUN with FILE_NAME, and
|
||||
return the result (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to
|
||||
NULL). Otherwise, call FUN repeatedly with FILE_NAME prefixed with each
|
||||
successive `:' separated element of PATH, returning whenever FUN returns
|
||||
0 (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to the resulting
|
||||
prefixed path). If FUN never returns 0, return the first non-ENOENT
|
||||
return value, or ENOENT if there is none. */
|
||||
error_t file_name_path_scan (const char *file_name, const char *path,
|
||||
error_t (*fun)(const char *name),
|
||||
char **prefixed_name);
|
||||
|
||||
/* Lookup FILE_NAME and return the node opened with FLAGS & MODE in result
|
||||
(see hurd_file_name_lookup for details), but a simple filename (without
|
||||
any directory prefixes) will be consectutively prefixed with the pathnames
|
||||
in the `:' separated list PATH until one succeeds in a successful lookup.
|
||||
If none succeed, then the first error that wasn't ENOENT is returned, or
|
||||
ENOENT if no other errors were returned. If PREFIXED_NAME is non-NULL,
|
||||
then if RESULT is looked up directly, *PREFIXED_NAME is set to NULL, and
|
||||
if it is looked up using a prefix from PATH, *PREFIXED_NAME is set to
|
||||
malloced storage containing the prefixed name. */
|
||||
error_t hurd_file_name_path_lookup (error_t (*use_init_port)
|
||||
(int which,
|
||||
error_t (*operate) (mach_port_t)),
|
||||
file_t (*get_dtable_port) (int fd),
|
||||
const char *file_name, const char *path,
|
||||
int flags, mode_t mode,
|
||||
file_t *result, char **prefixed_name);
|
||||
|
||||
|
||||
#endif /* hurd/lookup.h */
|
||||
|
||||
+53
-39
@@ -43,13 +43,25 @@ Cambridge, MA 02139, USA. */
|
||||
struct hurd_signal_preempter; /* <hurd/sigpreempt.h> */
|
||||
|
||||
|
||||
/* Full details of a signal. */
|
||||
struct hurd_signal_detail
|
||||
{
|
||||
/* Codes from origination Mach exception_raise message. */
|
||||
integer_t exc, exc_code, exc_subcode;
|
||||
/* Sigcode as passed or computed from exception codes. */
|
||||
integer_t code;
|
||||
/* Error code as passed or extracted from exception codes. */
|
||||
error_t error;
|
||||
};
|
||||
|
||||
|
||||
/* Per-thread signal state. */
|
||||
|
||||
struct hurd_sigstate
|
||||
{
|
||||
spin_lock_t lock; /* Locks most of the rest of the structure. */
|
||||
spin_lock_t critical_section_lock; /* Held if in critical section. */
|
||||
|
||||
int critical_section; /* Nonzero if in critical section. */
|
||||
spin_lock_t lock; /* Locks most of the rest of the structure. */
|
||||
|
||||
thread_t thread;
|
||||
struct hurd_sigstate *next; /* Linked-list of thread sigstates. */
|
||||
@@ -65,13 +77,8 @@ struct hurd_sigstate
|
||||
stack frame, and each next element in an outermore frame. */
|
||||
struct hurd_signal_preempter *preempters;
|
||||
|
||||
struct
|
||||
{
|
||||
/* For each signal that may be pending, the
|
||||
sigcode and error code to deliver it with. */
|
||||
long int code;
|
||||
error_t error;
|
||||
} pending_data[NSIG];
|
||||
/* For each signal that may be pending, the details to deliver it with. */
|
||||
struct hurd_signal_detail pending_data[NSIG];
|
||||
|
||||
/* If `suspended' is set when this thread gets a signal,
|
||||
the signal thread sends an empty message to it. */
|
||||
@@ -159,27 +166,22 @@ _hurd_critical_section_lock (void)
|
||||
(void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
|
||||
struct hurd_sigstate *ss = *location;
|
||||
if (ss == NULL)
|
||||
/* The thread variable is unset; this must be the first time we've
|
||||
asked for it. In this case, the critical section flag cannot
|
||||
possible already be set. Look up our sigstate structure the slow
|
||||
way; this locks the sigstate lock. */
|
||||
ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
|
||||
else
|
||||
__spin_lock (&ss->lock);
|
||||
|
||||
if (ss->critical_section)
|
||||
{
|
||||
/* We are already in a critical section, so do nothing. */
|
||||
/* The thread variable is unset; this must be the first time we've
|
||||
asked for it. In this case, the critical section flag cannot
|
||||
possible already be set. Look up our sigstate structure the slow
|
||||
way; this locks the sigstate lock. */
|
||||
ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
|
||||
__spin_unlock (&ss->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the critical section flag so no signal handler will run. */
|
||||
ss->critical_section = 1;
|
||||
__spin_unlock (&ss->lock);
|
||||
if (! __spin_try_lock (&ss->critical_section_lock))
|
||||
/* We are already in a critical section, so do nothing. */
|
||||
return NULL;
|
||||
|
||||
/* Return our sigstate pointer; this will be passed to
|
||||
_hurd_critical_section_unlock to clear the critical section flag. */
|
||||
/* With the critical section lock held no signal handler will run.
|
||||
Return our sigstate pointer; this will be passed to
|
||||
_hurd_critical_section_unlock to unlock it. */
|
||||
return ss;
|
||||
}
|
||||
|
||||
@@ -191,19 +193,18 @@ _hurd_critical_section_unlock (void *our_lock)
|
||||
return;
|
||||
else
|
||||
{
|
||||
/* It was us who acquired the critical section lock. Clear the
|
||||
critical section flag. */
|
||||
/* It was us who acquired the critical section lock. Unlock it. */
|
||||
struct hurd_sigstate *ss = our_lock;
|
||||
sigset_t pending;
|
||||
__spin_lock (&ss->lock);
|
||||
ss->critical_section = 0;
|
||||
__spin_unlock (&ss->critical_section_lock);
|
||||
pending = ss->pending & ~ss->blocked;
|
||||
__spin_unlock (&ss->lock);
|
||||
if (pending)
|
||||
/* There are unblocked signals pending, which weren't
|
||||
delivered because we were in the critical section.
|
||||
Tell the signal thread to deliver them now. */
|
||||
__msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
|
||||
__msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,27 +224,28 @@ extern void _hurdsig_init (void);
|
||||
|
||||
extern void _hurdsig_fault_init (void);
|
||||
|
||||
/* Raise a signal as described by SIGNO, SIGCODE and SIGERROR, on the
|
||||
thread whose sigstate SS points to. If SS is a null pointer, this
|
||||
instead affects the calling thread. */
|
||||
/* Raise a signal as described by SIGNO an DETAIL, on the thread whose
|
||||
sigstate SS points to. If SS is a null pointer, this instead affects
|
||||
the calling thread. */
|
||||
|
||||
extern void _hurd_raise_signal (struct hurd_sigstate *ss,
|
||||
int signo, long int sigcode, int sigerror);
|
||||
extern void _hurd_raise_signal (struct hurd_sigstate *ss, int signo,
|
||||
const struct hurd_signal_detail *detail);
|
||||
|
||||
/* Translate a Mach exception into a signal (machine-dependent). */
|
||||
|
||||
extern void _hurd_exception2signal (int exception, int code, int subcode,
|
||||
int *signo, long int *sigcode, int *error);
|
||||
extern void _hurd_exception2signal (struct hurd_signal_detail *detail,
|
||||
int *signo);
|
||||
|
||||
|
||||
/* Make the thread described by SS take the signal described by SIGNO and
|
||||
SIGCODE. If the process is traced, this will in fact stop with a SIGNO
|
||||
DETAIL. If the process is traced, this will in fact stop with a SIGNO
|
||||
as the stop signal unless UNTRACED is nonzero. When the signal can be
|
||||
considered delivered, sends a sig_post reply message on REPLY_PORT
|
||||
indicating success. SS is not locked. */
|
||||
|
||||
extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
int signo, long int sigcode, int error,
|
||||
int signo,
|
||||
struct hurd_signal_detail *detail,
|
||||
mach_port_t reply_port,
|
||||
mach_msg_type_name_t reply_port_type,
|
||||
int untraced);
|
||||
@@ -258,7 +260,7 @@ extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
struct machine_thread_all_state;
|
||||
extern struct sigcontext *
|
||||
_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
||||
int signo, long int sigcode,
|
||||
int signo, struct hurd_signal_detail *detail,
|
||||
int rpc_wait, struct machine_thread_all_state *state);
|
||||
|
||||
/* Function run by the signal thread to receive from the signal port. */
|
||||
@@ -279,6 +281,18 @@ extern void _hurd_longjmp_thread_state (void *state, jmp_buf env, int value);
|
||||
|
||||
extern void _hurd_siginfo_handler (int);
|
||||
|
||||
/* Replacement for mach_msg used in RPCs to provide Hurd interruption
|
||||
semantics. Args are all the same as for mach_msg. intr-rpc.h arranges
|
||||
for this version to be used automatically by the RPC stubs the library
|
||||
builds in place of the normal mach_msg. */
|
||||
error_t _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
|
||||
mach_msg_option_t option,
|
||||
mach_msg_size_t send_size,
|
||||
mach_msg_size_t rcv_size,
|
||||
mach_port_t rcv_name,
|
||||
mach_msg_timeout_t timeout,
|
||||
mach_port_t notify);
|
||||
|
||||
|
||||
/* Milliseconds to wait for an interruptible RPC to return after
|
||||
`interrupt_operation'. */
|
||||
|
||||
@@ -23,6 +23,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <errno.h>
|
||||
#include <signal.h> /* For sigset_t, sighandler_t, SIG_ERR. */
|
||||
struct hurd_sigstate; /* <hurd/signal.h> */
|
||||
struct hurd_signal_detail; /* <hurd/signal.h> */
|
||||
|
||||
struct hurd_signal_preempter
|
||||
{
|
||||
@@ -39,7 +40,7 @@ struct hurd_signal_preempter
|
||||
is processed as if the return value were its handler setting. */
|
||||
sighandler_t (*preempter) (struct hurd_signal_preempter *preempter,
|
||||
struct hurd_sigstate *ss,
|
||||
int *signo, long int *sigcode, int *sigerror);
|
||||
int *signo, struct hurd_signal_detail *detail);
|
||||
/* If PREEMPTER is null, act as if it returned HANDLER. */
|
||||
sighandler_t handler;
|
||||
|
||||
|
||||
+24
-46
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 92, 93, 94, 95, 96 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
|
||||
@@ -25,6 +25,8 @@ Cambridge, MA 02139, USA. */
|
||||
#include <hurd.h>
|
||||
#include <hurd/fd.h>
|
||||
#include <hurd/signal.h>
|
||||
#include <assert.h>
|
||||
#include <argz.h>
|
||||
|
||||
/* Overlay TASK, executing FILE with arguments ARGV and environment ENVP.
|
||||
If TASK == mach_task_self (), some ports are dealloc'd by the exec server.
|
||||
@@ -34,7 +36,7 @@ _hurd_exec (task_t task, file_t file,
|
||||
char *const argv[], char *const envp[])
|
||||
{
|
||||
error_t err;
|
||||
char *args, *env, *ap;
|
||||
char *args, *env;
|
||||
size_t argslen, envlen;
|
||||
int ints[INIT_INT_MAX];
|
||||
mach_port_t ports[_hurd_nports];
|
||||
@@ -43,40 +45,14 @@ _hurd_exec (task_t task, file_t file,
|
||||
unsigned int dtablesize, i;
|
||||
struct hurd_port **dtable_cells;
|
||||
struct hurd_userlink *ulink_dtable;
|
||||
char *const *p;
|
||||
struct hurd_sigstate *ss;
|
||||
mach_port_t *please_dealloc, *pdp;
|
||||
|
||||
|
||||
/* Pack the arguments into an array with nulls separating the elements. */
|
||||
argslen = 0;
|
||||
if (argv != NULL)
|
||||
{
|
||||
p = argv;
|
||||
while (*p != NULL)
|
||||
argslen += strlen (*p++) + 1;
|
||||
args = __alloca (argslen);
|
||||
ap = args;
|
||||
for (p = argv; *p != NULL; ++p)
|
||||
ap = __memccpy (ap, *p, '\0', ULONG_MAX);
|
||||
}
|
||||
else
|
||||
args = NULL;
|
||||
|
||||
/* Pack the environment into an array with nulls separating elements. */
|
||||
envlen = 0;
|
||||
if (envp != NULL)
|
||||
{
|
||||
p = envp;
|
||||
while (*p != NULL)
|
||||
envlen += strlen (*p++) + 1;
|
||||
env = __alloca (envlen);
|
||||
ap = env;
|
||||
for (p = envp; *p != NULL; ++p)
|
||||
ap = __memccpy (ap, *p, '\0', ULONG_MAX);
|
||||
}
|
||||
else
|
||||
env = NULL;
|
||||
/* XXX needs to be hurdmalloc XXX */
|
||||
if (err = __argz_create (argv, &args, &argslen))
|
||||
return err;
|
||||
if (err = __argz_create (envp, &env, &envlen))
|
||||
goto outargs;
|
||||
|
||||
/* Load up the ports to give to the new program. */
|
||||
for (i = 0; i < _hurd_nports; ++i)
|
||||
@@ -88,7 +64,7 @@ _hurd_exec (task_t task, file_t file,
|
||||
{
|
||||
while (--i > 0)
|
||||
_hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
|
||||
return err;
|
||||
goto outenv;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -109,11 +85,19 @@ _hurd_exec (task_t task, file_t file,
|
||||
/* We will set these all below. */
|
||||
break;
|
||||
|
||||
case INIT_TRACEMASK:
|
||||
ints[i] = _hurdsig_traced;
|
||||
break;
|
||||
|
||||
default:
|
||||
ints[i] = 0;
|
||||
}
|
||||
|
||||
ss = _hurd_self_sigstate ();
|
||||
|
||||
assert (! __spin_lock_locked (&ss->critical_section_lock));
|
||||
__spin_lock (&ss->critical_section_lock);
|
||||
|
||||
__spin_lock (&ss->lock);
|
||||
ints[INIT_SIGMASK] = ss->blocked;
|
||||
ints[INIT_SIGPENDING] = ss->pending;
|
||||
@@ -130,7 +114,6 @@ _hurd_exec (task_t task, file_t file,
|
||||
critical section flag avoids anything we call trying to acquire the
|
||||
sigstate lock. */
|
||||
|
||||
ss->critical_section = 1;
|
||||
__spin_unlock (&ss->lock);
|
||||
|
||||
/* Pack up the descriptor table to give the new program. */
|
||||
@@ -217,8 +200,7 @@ _hurd_exec (task_t task, file_t file,
|
||||
*pdp++ = dtable[i];
|
||||
}
|
||||
|
||||
err = __file_exec (file, task,
|
||||
_hurd_exec_flags & EXEC_INHERITED,
|
||||
err = __file_exec (file, task, 0,
|
||||
args, argslen, env, envlen,
|
||||
dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
|
||||
ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
|
||||
@@ -244,15 +226,11 @@ _hurd_exec (task_t task, file_t file,
|
||||
__mutex_unlock (&_hurd_dtable_lock);
|
||||
|
||||
/* Safe to let signals happen now. */
|
||||
{
|
||||
sigset_t pending;
|
||||
__spin_lock (&ss->lock);
|
||||
ss->critical_section = 0;
|
||||
pending = ss->pending & ~ss->blocked;
|
||||
__spin_unlock (&ss->lock);
|
||||
if (pending)
|
||||
__msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
|
||||
}
|
||||
_hurd_critical_section_unlock (ss);
|
||||
|
||||
outargs:
|
||||
free (args);
|
||||
outenv:
|
||||
free (env);
|
||||
return err;
|
||||
}
|
||||
|
||||
+8
-6
@@ -25,7 +25,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include "thread_state.h"
|
||||
#include "faultexc.h" /* mig-generated header for our exc server. */
|
||||
#include "faultexc_server.h" /* mig-generated header for our exc server. */
|
||||
#include <assert.h>
|
||||
|
||||
jmp_buf _hurdsig_fault_env;
|
||||
@@ -42,19 +42,21 @@ _hurdsig_fault_catch_exception_raise (mach_port_t port,
|
||||
int subcode)
|
||||
{
|
||||
int signo;
|
||||
long int sigcode;
|
||||
int sigerror;
|
||||
struct hurd_signal_detail d;
|
||||
|
||||
if (port != forward_sigexc ||
|
||||
thread != _hurd_msgport_thread || task != __mach_task_self ())
|
||||
return EPERM; /* Strange bogosity. */
|
||||
|
||||
d.exc = exception;
|
||||
d.exc_code = code;
|
||||
d.exc_subcode = subcode;
|
||||
|
||||
/* Call the machine-dependent function to translate the Mach exception
|
||||
codes into a signal number and subcode. */
|
||||
_hurd_exception2signal (exception, code, subcode,
|
||||
&signo, &sigcode, &sigerror);
|
||||
_hurd_exception2signal (&d, &signo);
|
||||
|
||||
return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preempter, signo, sigcode)
|
||||
return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preempter, signo, d.code)
|
||||
? 0 : EGREGIOUS;
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -30,6 +30,7 @@ int _hurd_exec_flags;
|
||||
struct hurd_port *_hurd_ports;
|
||||
unsigned int _hurd_nports;
|
||||
mode_t _hurd_umask;
|
||||
sigset_t _hurdsig_traced;
|
||||
|
||||
error_t
|
||||
_hurd_ports_use (int which, error_t (*operate) (mach_port_t))
|
||||
@@ -69,15 +70,18 @@ _hurd_init (int flags, char **argv,
|
||||
__task_set_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
|
||||
portarray[INIT_PORT_BOOTSTRAP]);
|
||||
|
||||
/* Tell the proc server we exist, if it does. */
|
||||
if (portarray[INIT_PORT_PROC] != MACH_PORT_NULL)
|
||||
_hurd_proc_init (argv);
|
||||
|
||||
if (intarraysize > INIT_UMASK)
|
||||
_hurd_umask = intarray[INIT_UMASK] & 0777;
|
||||
else
|
||||
_hurd_umask = CMASK;
|
||||
|
||||
if (intarraysize > INIT_TRACEMASK)
|
||||
_hurdsig_traced = intarray[INIT_TRACEMASK];
|
||||
|
||||
/* Tell the proc server we exist, if it does. */
|
||||
if (portarray[INIT_PORT_PROC] != MACH_PORT_NULL)
|
||||
_hurd_proc_init (argv);
|
||||
|
||||
/* All done with init ints and ports. */
|
||||
__vm_deallocate (__mach_task_self (),
|
||||
(vm_address_t) intarray,
|
||||
@@ -147,11 +151,11 @@ _hurd_proc_init (char **argv)
|
||||
here, like _hurd_pid, are already initialized. */
|
||||
RUN_HOOK (_hurd_proc_subinit, ());
|
||||
|
||||
if (_hurd_exec_flags & EXEC_TRACED)
|
||||
if (_hurdsig_traced)
|
||||
/* This process is "traced", meaning it should stop on signals or exec.
|
||||
We are all set up now to handle signals. Stop ourselves, to inform
|
||||
our parent (presumably a debugger) that the exec has completed. */
|
||||
__msg_sig_post (_hurd_msgport, SIGTRAP, __mach_task_self ());
|
||||
__msg_sig_post (_hurd_msgport, SIGTRAP, 0, __mach_task_self ());
|
||||
}
|
||||
|
||||
/* Called when we get a message telling us to change our proc server port. */
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ _hurd_sig_post (pid_t pid, int sig, mach_port_t arg_refport)
|
||||
(refport = arg_refport, 0), 0,
|
||||
/* If no message port we cannot send signals. */
|
||||
msgport == MACH_PORT_NULL ? EPERM :
|
||||
__msg_sig_post (msgport, sig, refport));
|
||||
__msg_sig_post (msgport, sig, 0, refport));
|
||||
if (! err)
|
||||
delivered = 1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
|
||||
mach_port_t ref = __mach_reply_port ();
|
||||
error_t reauth (auth_t auth)
|
||||
{
|
||||
return __auth_user_authenticate (auth, unauth, ref,
|
||||
return __auth_user_authenticate (auth, ref,
|
||||
MACH_MSG_TYPE_MAKE_SEND,
|
||||
result);
|
||||
}
|
||||
|
||||
+123
-42
@@ -37,24 +37,39 @@
|
||||
/*
|
||||
* HISTORY
|
||||
* $Log$
|
||||
* Revision 1.10 1995/02/13 22:04:34 roland
|
||||
* (malloc_init): Add self reference to avoid not only the `defined but not
|
||||
* used' warning, but also to avoid GCC optimizing out the entire function
|
||||
* (!).
|
||||
* Revision 1.11 1996/06/06 15:13:47 miles
|
||||
* Changes to bring in line with the hurd libthreads/malloc.c:
|
||||
* (more_memory): Use assert_perror instead of MACH_CALL.
|
||||
* "cthread_internals.h": Include removed.
|
||||
* (realloc): Use LOG2_MIN_SIZE.
|
||||
* (LOG2_MIN_SIZE): New macro.
|
||||
* (realloc): Don't bother allocating a new block if the
|
||||
* new size request fits in the old one and doesn't waste any space.
|
||||
* Only free the old block if we successfully got a new one.
|
||||
* [MCHECK] (struct header): New type.
|
||||
* (union header): Only define if !MCHECK.
|
||||
* (HEADER_SIZE, HEADER_NEXT, HEADER_FREE, HEADER_CHECK): New macros.
|
||||
* [MCHECK] (MIN_SIZE): Add correct definition for this case.
|
||||
* (more_memory, malloc, free, realloc): Use above macros, and add appropiate
|
||||
* checks & frobs in MCHECK case.
|
||||
*
|
||||
* Revision 1.9 1995/02/13 16:36:08 roland
|
||||
* Include string.h; #define bcopy using memcpy.
|
||||
* Revision 1.6 1996/03/07 21:13:08 miles
|
||||
* (realloc):
|
||||
* Use LOG2_MIN_SIZE.
|
||||
* Don't bother allocating a new block if the new size request fits in the old
|
||||
* one and doesn't waste any space.
|
||||
* Only free the old block if we successfully got a new one.
|
||||
* (LOG2_MIN_SIZE): New macro.
|
||||
*
|
||||
* Revision 1.8 1995/02/03 01:54:21 roland
|
||||
* Remove bogus bcopy decl.
|
||||
* Revision 1.5 1996/03/06 23:51:04 miles
|
||||
* [MCHECK] (struct header): New type.
|
||||
* (union header): Only define if !MCHECK.
|
||||
* (HEADER_SIZE, HEADER_NEXT, HEADER_FREE, HEADER_CHECK): New macros.
|
||||
* [MCHECK] (MIN_SIZE): Add correct definition for this case.
|
||||
* (more_memory, malloc, free, realloc):
|
||||
* Use above macros, and add appropiate checks & frobs in MCHECK case.
|
||||
*
|
||||
* Revision 1.7 1995/01/26 04:22:02 roland
|
||||
* Don't include gnu-stabs.h.
|
||||
*
|
||||
* Revision 1.6 1994/12/07 19:41:26 roland
|
||||
* (vm_allocate, vm_page_size): #define these to __ names at top.
|
||||
*
|
||||
* Revision 1.5 1994/06/04 01:48:44 roland
|
||||
* Revision 1.4 1994/05/05 11:21:42 roland
|
||||
* entered into RCS
|
||||
*
|
||||
* Revision 2.7 91/05/14 17:57:34 mrt
|
||||
@@ -99,9 +114,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <cthreads.h>
|
||||
#include "cthread_internals.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include <cthreads.h>
|
||||
|
||||
#define MCHECK
|
||||
|
||||
/*
|
||||
* Structure of memory block header.
|
||||
@@ -109,12 +126,41 @@
|
||||
* When allocated, fl points to free list.
|
||||
* Size of header is 4 bytes, so minimum usable block size is 8 bytes.
|
||||
*/
|
||||
|
||||
#define CHECK_BUSY 0x8a3c743e
|
||||
#define CHECK_FREE 0x66688b92
|
||||
|
||||
#ifdef MCHECK
|
||||
|
||||
typedef struct header {
|
||||
long check;
|
||||
union {
|
||||
struct header *next;
|
||||
struct free_list *fl;
|
||||
} u;
|
||||
} *header_t;
|
||||
|
||||
#define HEADER_SIZE sizeof (struct header)
|
||||
#define HEADER_NEXT(h) ((h)->u.next)
|
||||
#define HEADER_FREE(h) ((h)->u.fl)
|
||||
#define HEADER_CHECK(h) ((h)->check)
|
||||
#define MIN_SIZE 16
|
||||
#define LOG2_MIN_SIZE 4
|
||||
|
||||
#else /* ! MCHECK */
|
||||
|
||||
typedef union header {
|
||||
union header *next;
|
||||
struct free_list *fl;
|
||||
} *header_t;
|
||||
|
||||
#define HEADER_SIZE sizeof (union header)
|
||||
#define HEADER_NEXT(h) ((h)->next)
|
||||
#define HEADER_FREE(h) ((h)->fl)
|
||||
#define MIN_SIZE 8 /* minimum block size */
|
||||
#define LOG2_MIN_SIZE 3
|
||||
|
||||
#endif /* MCHECK */
|
||||
|
||||
typedef struct free_list {
|
||||
spin_lock_t lock; /* spin lock for mutual exclusion */
|
||||
@@ -125,10 +171,10 @@ typedef struct free_list {
|
||||
} *free_list_t;
|
||||
|
||||
/*
|
||||
* Free list with index i contains blocks of size 2^(i+3) including header.
|
||||
* Smallest block size is 8, with 4 bytes available to user.
|
||||
* Size argument to malloc is a signed integer for sanity checking,
|
||||
* so largest block size is 2^31.
|
||||
* Free list with index i contains blocks of size 2 ^ (i + LOG2_MIN_SIZE)
|
||||
* including header. Smallest block size is MIN_SIZE, with MIN_SIZE -
|
||||
* HEADER_SIZE bytes available to user. Size argument to malloc is a signed
|
||||
* integer for sanity checking, so largest block size is 2^31.
|
||||
*/
|
||||
#define NBUCKETS 29
|
||||
|
||||
@@ -173,18 +219,23 @@ more_memory(size, fl)
|
||||
if (size <= vm_page_size) {
|
||||
amount = vm_page_size;
|
||||
n = vm_page_size / size;
|
||||
/*
|
||||
* We lose vm_page_size - n*size bytes here. */
|
||||
/* We lose vm_page_size - n*size bytes here. */
|
||||
} else {
|
||||
amount = size;
|
||||
n = 1;
|
||||
}
|
||||
MACH_CALL(vm_allocate(mach_task_self(), &where, (vm_size_t) amount, TRUE), r);
|
||||
|
||||
r = vm_allocate(mach_task_self(), &where, (vm_size_t) amount, TRUE);
|
||||
assert_perror (r);
|
||||
|
||||
h = (header_t) where;
|
||||
do {
|
||||
h->next = fl->head;
|
||||
fl->head = h;
|
||||
h = (header_t) ((char *) h + size);
|
||||
HEADER_NEXT (h) = fl->head;
|
||||
#ifdef MCHECK
|
||||
HEADER_CHECK (h) = CHECK_FREE;
|
||||
#endif
|
||||
fl->head = h;
|
||||
h = (header_t) ((char *) h + size);
|
||||
} while (--n != 0);
|
||||
}
|
||||
|
||||
@@ -199,7 +250,7 @@ malloc(size)
|
||||
|
||||
if ((int) size < 0) /* sanity check */
|
||||
return 0;
|
||||
size += sizeof(union header);
|
||||
size += HEADER_SIZE;
|
||||
/*
|
||||
* Find smallest power-of-two block size
|
||||
* big enough to hold requested size plus header.
|
||||
@@ -232,7 +283,13 @@ malloc(size)
|
||||
/*
|
||||
* Pop block from free list.
|
||||
*/
|
||||
fl->head = h->next;
|
||||
fl->head = HEADER_NEXT (h);
|
||||
|
||||
#ifdef MCHECK
|
||||
assert (HEADER_CHECK (h) == CHECK_FREE);
|
||||
HEADER_CHECK (h) = CHECK_BUSY;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
fl->in_use += 1;
|
||||
#endif DEBUG
|
||||
@@ -242,11 +299,11 @@ malloc(size)
|
||||
* so we can figure out where it goes
|
||||
* at free() time.
|
||||
*/
|
||||
h->fl = fl;
|
||||
HEADER_FREE (h) = fl;
|
||||
/*
|
||||
* Return pointer past the block header.
|
||||
*/
|
||||
return ((char *) h) + sizeof(union header);
|
||||
return ((char *) h) + HEADER_SIZE;
|
||||
}
|
||||
|
||||
/* Declaration changed to standard one for GNU. */
|
||||
@@ -263,8 +320,13 @@ free(base)
|
||||
/*
|
||||
* Find free list for block.
|
||||
*/
|
||||
h = (header_t) (base - sizeof(union header));
|
||||
fl = h->fl;
|
||||
h = (header_t) (base - HEADER_SIZE);
|
||||
|
||||
#ifdef MCHECK
|
||||
assert (HEADER_CHECK (h) == CHECK_BUSY);
|
||||
#endif
|
||||
|
||||
fl = HEADER_FREE (h);
|
||||
i = fl - malloc_free_list;
|
||||
/*
|
||||
* Sanity checks.
|
||||
@@ -281,7 +343,10 @@ free(base)
|
||||
* Push block on free list.
|
||||
*/
|
||||
spin_lock(&fl->lock);
|
||||
h->next = fl->head;
|
||||
HEADER_NEXT (h) = fl->head;
|
||||
#ifdef MCHECK
|
||||
HEADER_CHECK (h) = CHECK_FREE;
|
||||
#endif
|
||||
fl->head = h;
|
||||
#ifdef DEBUG
|
||||
fl->in_use -= 1;
|
||||
@@ -308,8 +373,11 @@ realloc(old_base, new_size)
|
||||
/*
|
||||
* Find size of old block.
|
||||
*/
|
||||
h = (header_t) (old_base - sizeof(union header));
|
||||
fl = h->fl;
|
||||
h = (header_t) (old_base - HEADER_SIZE);
|
||||
#ifdef MCHECK
|
||||
assert (HEADER_CHECK (h) == CHECK_BUSY);
|
||||
#endif
|
||||
fl = HEADER_FREE (h);
|
||||
i = fl - malloc_free_list;
|
||||
/*
|
||||
* Sanity checks.
|
||||
@@ -323,16 +391,29 @@ realloc(old_base, new_size)
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Free list with index i contains blocks of size 2^(i+3) including header.
|
||||
* Free list with index i contains blocks of size
|
||||
* 2 ^ (i + * LOG2_MIN_SIZE) including header.
|
||||
*/
|
||||
old_size = (1 << (i+3)) - sizeof(union header);
|
||||
old_size = (1 << (i + LOG2_MIN_SIZE)) - HEADER_SIZE;
|
||||
|
||||
if (new_size <= old_size
|
||||
&& new_size > (((old_size + HEADER_SIZE) >> 1) - HEADER_SIZE))
|
||||
/* The new size still fits in the same block, and wouldn't fit in
|
||||
the next smaller block! */
|
||||
return old_base;
|
||||
|
||||
/*
|
||||
* Allocate new block, copy old bytes, and free old block.
|
||||
*/
|
||||
new_base = malloc(new_size);
|
||||
if (new_base != 0)
|
||||
bcopy(old_base, new_base, (int) (old_size < new_size ? old_size : new_size));
|
||||
free(old_base);
|
||||
if (new_base)
|
||||
bcopy(old_base, new_base,
|
||||
(int) (old_size < new_size ? old_size : new_size));
|
||||
|
||||
if (new_base || new_size == 0)
|
||||
/* Free OLD_BASE, but only if the malloc didn't fail. */
|
||||
free (old_base);
|
||||
|
||||
return new_base;
|
||||
}
|
||||
|
||||
@@ -354,7 +435,7 @@ print_malloc_free_list()
|
||||
spin_lock(&fl->lock);
|
||||
if (fl->in_use != 0 || fl->head != 0) {
|
||||
total_used += fl->in_use * size;
|
||||
for (n = 0, h = fl->head; h != 0; h = h->next, n += 1)
|
||||
for (n = 0, h = fl->head; h != 0; h = HEADER_NEXT (h), n += 1)
|
||||
;
|
||||
total_free += n * size;
|
||||
fprintf(stderr, "%10d %10d %10d %10d\n",
|
||||
|
||||
+8
-49
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992, 1994, 1995, 1996 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
|
||||
@@ -22,6 +22,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <argz.h>
|
||||
|
||||
|
||||
#define AUTHCHECK \
|
||||
@@ -238,6 +239,10 @@ set_int (int which, int value)
|
||||
}
|
||||
__spin_unlock (&ss->lock);
|
||||
return 0;
|
||||
|
||||
case INIT_TRACEMASK:
|
||||
_hurdsig_traced = value;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return EINVAL;
|
||||
@@ -377,57 +382,15 @@ _S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
|
||||
|
||||
AUTHCHECK;
|
||||
|
||||
envc = _hurd_split_args (data, datalen, NULL);
|
||||
envc = __argz_count (data, datalen);
|
||||
envp = malloc ((envc + 1) * sizeof (char *));
|
||||
if (envp == NULL)
|
||||
return errno;
|
||||
_hurd_split_args (data, datalen, envp);
|
||||
__argz_extract (data, datalen, envp);
|
||||
__environ = envp; /* XXX cooperate with loadenv et al */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get and frob the exec flags. */
|
||||
|
||||
kern_return_t
|
||||
_S_msg_get_exec_flags (mach_port_t process, mach_port_t auth,
|
||||
int *flags)
|
||||
{
|
||||
AUTHCHECK;
|
||||
|
||||
*flags = _hurd_exec_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
_S_msg_set_all_exec_flags (mach_port_t process, mach_port_t auth,
|
||||
int flags)
|
||||
{
|
||||
AUTHCHECK;
|
||||
|
||||
_hurd_exec_flags = flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
_S_msg_set_some_exec_flags (mach_port_t process, mach_port_t auth,
|
||||
int flags)
|
||||
{
|
||||
AUTHCHECK;
|
||||
|
||||
_hurd_exec_flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
_S_msg_clear_some_exec_flags (mach_port_t process, mach_port_t auth,
|
||||
int flags)
|
||||
{
|
||||
AUTHCHECK;
|
||||
|
||||
_hurd_exec_flags &= ~flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* XXX */
|
||||
|
||||
@@ -445,7 +408,3 @@ _S_msg_set_dtable (mach_port_t process,
|
||||
portarray_t dtable,
|
||||
mach_msg_type_number_t dtableCnt)
|
||||
{ return EOPNOTSUPP; }
|
||||
|
||||
kern_return_t
|
||||
_S_msg_startup_dosync (mach_port_t process)
|
||||
{ return EOPNOTSUPP; }
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/* Support code for dealing with priorities in the Hurd.
|
||||
Copyright (C) 1994, 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994, 1995, 1996 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
|
||||
@@ -62,7 +62,7 @@ _hurd_priority_which_map (enum __priority_which which, int who,
|
||||
char *tw = 0;
|
||||
size_t twsz = 0;
|
||||
if (err = __USEPORT (PROC, __proc_getprocinfo (port, pids[i],
|
||||
pi_flags,
|
||||
&pi_flags,
|
||||
&pi, &pisize,
|
||||
&tw, &twsz)))
|
||||
continue;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user