2003-05-28 Jeff Johnston <jjohnstn@redhat.com>

Tom Fitzsimmons  <fitzsim@redhat.com>

	* configure.in: Add iconvdata support for x86 linux.
	* configure: Regenerated.
	* libc/sys/linux/Makefile.am: Add EL/IX level 3 network, dynamic
	library, iconv, and linuxthreads support.
	* libc/sys/linux/configure.in: Ditto.
	* libc/sys/linux/Makefile.in: Regenerated.
	* libc/sys/linux/configure: Ditto.
	* iconvdata/EUC-JP.irreversible: New file.
	* iconvdata/Makefile.am: Ditto.
	* iconvdata/Makefile.in: Ditto.
	* iconvdata/SJIS.irreversible: Ditto.
	* iconvdata/aclocal.m4: Ditto.
	* iconvdata/configure: Ditto.
	* iconvdata/configure.in: Ditto.
	* iconvdata/dummy.c: Ditto.
	* iconvdata/euc-jp.c: Ditto.
	* iconvdata/gconv-modules: Ditto.
	* iconvdata/jis0201.c: Ditto.
	* iconvdata/jis0201.h: Ditto.
	* iconvdata/jis0208.c: Ditto.
	* iconvdata/jis0208.h: Ditto.
	* iconvdata/jis0212.c: Ditto.
	* iconvdata/jis0212.h: Ditto.
	* iconvdata/sjis.c: Ditto.
	* libc/include/errno.h: Protect definition of error_t.
	* libc/sys/linux/gethostid.c: New file.
	* libc/sys/linux/sethostid.c: Ditto.
	* libc/sys/linux/dl/Makefile.am: Ditto.
	* libc/sys/linux/dl/Makefile.in: Ditto.
	* libc/sys/linux/dl/abi-tag.h: Ditto.
	* libc/sys/linux/dl/atomicity.h: Ditto.
	* libc/sys/linux/dl/dl-addr.c: Ditto.
	* libc/sys/linux/dl/dl-cache.c: Ditto.
	* libc/sys/linux/dl/dl-cache.h: Ditto.
	* libc/sys/linux/dl/dl-close.c: Ditto.
	* libc/sys/linux/dl/dl-debug.c: Ditto.
	* libc/sys/linux/dl/dl-deps.c: Ditto.
	* libc/sys/linux/dl/dl-dst.h: Ditto.
	* libc/sys/linux/dl/dl-error.c: Ditto.
	* libc/sys/linux/dl/dl-fini.c: Ditto.
	* libc/sys/linux/dl/dl-init.c: Ditto.
	* libc/sys/linux/dl/dl-iteratephdr.c: Ditto.
	* libc/sys/linux/dl/dl-libc.c: Ditto.
	* libc/sys/linux/dl/dl-librecon.h: Ditto.
	* libc/sys/linux/dl/dl-load.c: Ditto.
	* libc/sys/linux/dl/dl-lookup.c: Ditto.
	* libc/sys/linux/dl/dl-lookupcfg.h: Ditto.
	* libc/sys/linux/dl/dl-minimal.c: Ditto.
	* libc/sys/linux/dl/dl-misc.c: Ditto.
	* libc/sys/linux/dl/dl-object.c: Ditto.
	* libc/sys/linux/dl/dl-open.c: Ditto.
	* libc/sys/linux/dl/dl-osinfo.h: Ditto.
	* libc/sys/linux/dl/dl-profile.c: Ditto.
	* libc/sys/linux/dl/dl-profstub.c: Ditto.
	* libc/sys/linux/dl/dl-reloc.c: Ditto.
	* libc/sys/linux/dl/dl-runtime.c: Ditto.
	* libc/sys/linux/dl/dl-support.c: Ditto.
	* libc/sys/linux/dl/dl-sym.c: Ditto.
	* libc/sys/linux/dl/dl-version.c: Ditto.
	* libc/sys/linux/dl/dlfcn.h: Ditto.
	* libc/sys/linux/dl/do-lookup.h: Ditto.
	* libc/sys/linux/dl/do-rel.h: Ditto.
	* libc/sys/linux/dl/dynamic-link.h: Ditto.
	* libc/sys/linux/dl/kernel-features.h: Ditto.
	* libc/sys/linux/dl/ldsodefs.h: Ditto.
	* libc/sys/linux/dl/libintl.h: Ditto.
	* libc/sys/linux/dl/trusted-dirs.h: Ditto.
	* libc/sys/linux/dl/unsecvars.h: Ditto.
	* libc/sys/linux/iconv/Makefile.am: Ditto.
	* libc/sys/linux/iconv/Makefile.in: Ditto.
	* libc/sys/linux/iconv/categories.def: Ditto.
	* libc/sys/linux/iconv/dummy-repertoire.c: Ditto.
	* libc/sys/linux/iconv/gconv.c: Ditto.
	* libc/sys/linux/iconv/gconv_builtin.c: Ditto.
	* libc/sys/linux/iconv/gconv_builtin.h: Ditto.
	* libc/sys/linux/iconv/gconv_cache.c: Ditto.
	* libc/sys/linux/iconv/gconv_charset.h: Ditto.
	* libc/sys/linux/iconv/gconv_close.c: Ditto.
	* libc/sys/linux/iconv/gconv_conf.c: Ditto.
	* libc/sys/linux/iconv/gconv_db.c: Ditto.
	* libc/sys/linux/iconv/gconv_dl.c: Ditto.
	* libc/sys/linux/iconv/gconv_int.h: Ditto.
	* libc/sys/linux/iconv/gconv_open.c: Ditto.
	* libc/sys/linux/iconv/gconv_simple.c: Ditto.
	* libc/sys/linux/iconv/gconv_trans.c: Ditto.
	* libc/sys/linux/iconv/hash-string.h: Ditto.
	* libc/sys/linux/iconv/iconv.c: Ditto.
	* libc/sys/linux/iconv/iconv.h: Ditto.
	* libc/sys/linux/iconv/iconv_charmap.c: Ditto.
	* libc/sys/linux/iconv/iconv_close.c: Ditto.
	* libc/sys/linux/iconv/iconv_open.c: Ditto.
	* libc/sys/linux/iconv/iconvconfig.c: Ditto.
	* libc/sys/linux/iconv/iconvconfig.h: Ditto.
	* libc/sys/linux/iconv/loadinfo.h: Ditto.
	* libc/sys/linux/iconv/localeinfo.h: Ditto.
	* libc/sys/linux/iconv/loop.c: Ditto.
	* libc/sys/linux/iconv/skeleton.c: Ditto.
	* libc/sys/linux/iconv/strtab.c: Ditto.
	* libc/sys/linux/include/dl-hash.h: Ditto.
	* libc/sys/linux/include/dlfcn.h: Ditto.
	* libc/sys/linux/include/fnmatch.h: Ditto.
	* libc/sys/linux/include/gconv.h: Ditto.
	* libc/sys/linux/include/glob.h: Ditto.
	* libc/sys/linux/include/hesiod.h: Ditto.
	* libc/sys/linux/include/ifaddrs.h: Ditto.
	* libc/sys/linux/include/libc_private.h: Ditto.
	* libc/sys/linux/include/link.h: Ditto.
	* libc/sys/linux/include/namespace.h: Ditto.
	* libc/sys/linux/include/netconfig.h: Ditto.
	* libc/sys/linux/include/netdb.h: Ditto.
	* libc/sys/linux/include/nsswitch.h: Ditto.
	* libc/sys/linux/include/regex.h: Ditto.
	* libc/sys/linux/include/resolv.h: Ditto.
	* libc/sys/linux/include/rune.h: Ditto.
	* libc/sys/linux/include/runetype.h: Ditto.
	* libc/sys/linux/include/semaphore.h: Ditto.
	* libc/sys/linux/include/setlocale.h: Ditto.
	* libc/sys/linux/include/un-namespace.h: Ditto.
	* libc/sys/linux/include/wordexp.h: Ditto.
	* libc/sys/linux/include/arpa/ftp.h: Ditto.
	* libc/sys/linux/include/arpa/inet.h: Ditto.
	* libc/sys/linux/include/arpa/nameser.h: Ditto.
	* libc/sys/linux/include/arpa/nameser_compat.h: Ditto.
	* libc/sys/linux/include/arpa/telnet.h: Ditto.
	* libc/sys/linux/include/arpa/tftp.h: Ditto.
	* libc/sys/linux/include/net/bpf.h: Ditto.
	* libc/sys/linux/include/net/bpf_compat.h: Ditto.
	* libc/sys/linux/include/net/bpfdesc.h: Ditto.
	* libc/sys/linux/include/net/bridge.h: Ditto.
	* libc/sys/linux/include/net/ethernet.h: Ditto.
	* libc/sys/linux/include/net/fddi.h: Ditto.
	* libc/sys/linux/include/net/if.h: Ditto.
	* libc/sys/linux/include/net/if_arc.h: Ditto.
	* libc/sys/linux/include/net/if_arp.h: Ditto.
	* libc/sys/linux/include/net/if_atm.h: Ditto.
	* libc/sys/linux/include/net/if_dl.h: Ditto.
	* libc/sys/linux/include/net/if_gif.h: Ditto.
	* libc/sys/linux/include/net/if_ieee80211.h: Ditto.
	* libc/sys/linux/include/net/if_llc.h: Ditto.
	* libc/sys/linux/include/net/if_media.h: Ditto.
	* libc/sys/linux/include/net/if_mib.h: Ditto.
	* libc/sys/linux/include/net/if_ppp.h: Ditto.
	* libc/sys/linux/include/net/if_pppvar.h: Ditto.
	* libc/sys/linux/include/net/if_slvar.h: Ditto.
	* libc/sys/linux/include/net/if_sppp.h: Ditto.
	* libc/sys/linux/include/net/if_stf.h: Ditto.
	* libc/sys/linux/include/net/if_tap.h: Ditto.
	* libc/sys/linux/include/net/if_tapvar.h: Ditto.
	* libc/sys/linux/include/net/if_tun.h: Ditto.
	* libc/sys/linux/include/net/if_tunvar.h: Ditto.
	* libc/sys/linux/include/net/if_types.h: Ditto.
	* libc/sys/linux/include/net/if_var.h: Ditto.
	* libc/sys/linux/include/net/if_vlan_var.h: Ditto.
	* libc/sys/linux/include/net/intrq.h: Ditto.
	* libc/sys/linux/include/net/iso88025.h: Ditto.
	* libc/sys/linux/include/net/net_osdep.h: Ditto.
	* libc/sys/linux/include/net/netisr.h: Ditto.
	* libc/sys/linux/include/net/pfil.h: Ditto.
	* libc/sys/linux/include/net/pfkeyv2.h: Ditto.
	* libc/sys/linux/include/net/ppp_comp.h: Ditto.
	* libc/sys/linux/include/net/ppp_defs.h: Ditto.
	* libc/sys/linux/include/net/radix.h: Ditto.
	* libc/sys/linux/include/net/raw_cb.h: Ditto.
	* libc/sys/linux/include/net/route.h: Ditto.
	* libc/sys/linux/include/net/slcompress.h: Ditto.
	* libc/sys/linux/include/net/slip.h: Ditto.
	* libc/sys/linux/include/net/zlib.h: Ditto.
	* libc/sys/linux/include/netinet/icmp6.h: Ditto.
	* libc/sys/linux/include/netinet/icmp_var.h: Ditto.
	* libc/sys/linux/include/netinet/if_atm.h: Ditto.
	* libc/sys/linux/include/netinet/if_ether.h: Ditto.
	* libc/sys/linux/include/netinet/igmp.h: Ditto.
	* libc/sys/linux/include/netinet/igmp_var.h: Ditto.
	* libc/sys/linux/include/netinet/in.h: Ditto.
	* libc/sys/linux/include/netinet/in_gif.h: Ditto.
	* libc/sys/linux/include/netinet/in_pcb.h: Ditto.
	* libc/sys/linux/include/netinet/in_systm.h: Ditto.
	* libc/sys/linux/include/netinet/in_var.h: Ditto.
	* libc/sys/linux/include/netinet/ip.h: Ditto.
	* libc/sys/linux/include/netinet/ip6.h: Ditto.
	* libc/sys/linux/include/netinet/ip_dummynet.h: Ditto.
	* libc/sys/linux/include/netinet/ip_ecn.h: Ditto.
	* libc/sys/linux/include/netinet/ip_encap.h: Ditto.
	* libc/sys/linux/include/netinet/ip_flow.h: Ditto.
	* libc/sys/linux/include/netinet/ip_fw.h: Ditto.
	* libc/sys/linux/include/netinet/ip_icmp.h: Ditto.
	* libc/sys/linux/include/netinet/ip_mroute.h: Ditto.
	* libc/sys/linux/include/netinet/ip_var.h: Ditto.
	* libc/sys/linux/include/netinet/ipprotosw.h: Ditto.
	* libc/sys/linux/include/netinet/tcp.h: Ditto.
	* libc/sys/linux/include/netinet/tcp_debug.h: Ditto.
	* libc/sys/linux/include/netinet/tcp_fsm.h: Ditto.
	* libc/sys/linux/include/netinet/tcp_seq.h: Ditto.
	* libc/sys/linux/include/netinet/tcp_timer.h: Ditto.
	* libc/sys/linux/include/netinet/tcp_var.h: Ditto.
	* libc/sys/linux/include/netinet/tcpip.h: Ditto.
	* libc/sys/linux/include/netinet/udp.h: Ditto.
	* libc/sys/linux/include/netinet/udp_var.h: Ditto.
	* libc/sys/linux/include/netinet6/ah.h: Ditto.
	* libc/sys/linux/include/netinet6/ah6.h: Ditto.
	* libc/sys/linux/include/netinet6/esp.h: Ditto.
	* libc/sys/linux/include/netinet6/esp6.h: Ditto.
	* libc/sys/linux/include/netinet6/esp_rijndael.h: Ditto.
	* libc/sys/linux/include/netinet6/icmp6.h: Ditto.
	* libc/sys/linux/include/netinet6/in6.h: Ditto.
	* libc/sys/linux/include/netinet6/in6_gif.h: Ditto.
	* libc/sys/linux/include/netinet6/in6_ifattach.h: Ditto.
	* libc/sys/linux/include/netinet6/in6_pcb.h: Ditto.
	* libc/sys/linux/include/netinet6/in6_prefix.h: Ditto.
	* libc/sys/linux/include/netinet6/in6_var.h: Ditto.
	* libc/sys/linux/include/netinet6/ip6.h: Ditto.
	* libc/sys/linux/include/netinet6/ip6_ecn.h: Ditto.
	* libc/sys/linux/include/netinet6/ip6_fw.h: Ditto.
	* libc/sys/linux/include/netinet6/ip6_mroute.h: Ditto.
	* libc/sys/linux/include/netinet6/ip6_var.h: Ditto.
	* libc/sys/linux/include/netinet6/ip6protosw.h: Ditto.
	* libc/sys/linux/include/netinet6/ipcomp.h: Ditto.
	* libc/sys/linux/include/netinet6/ipcomp6.h: Ditto.
	* libc/sys/linux/include/netinet6/ipsec.h: Ditto.
	* libc/sys/linux/include/netinet6/ipsec6.h: Ditto.
	* libc/sys/linux/include/netinet6/mld6_var.h: Ditto.
	* libc/sys/linux/include/netinet6/nd6.h: Ditto.
	* libc/sys/linux/include/netinet6/pim6.h: Ditto.
	* libc/sys/linux/include/netinet6/pim6_var.h: Ditto.
	* libc/sys/linux/include/netinet6/raw_ip6.h: Ditto.
	* libc/sys/linux/include/netinet6/scope6_var.h: Ditto.
	* libc/sys/linux/include/netinet6/tcp6_var.h: Ditto.
	* libc/sys/linux/include/netinet6/udp6_var.h: Ditto.
	* libc/sys/linux/include/netns/idp.h: Ditto.
	* libc/sys/linux/include/netns/idp_var.h: Ditto.
	* libc/sys/linux/include/netns/ns.h: Ditto.
	* libc/sys/linux/include/netns/ns_error.h: Ditto.
	* libc/sys/linux/include/netns/ns_if.h: Ditto.
	* libc/sys/linux/include/netns/ns_pcb.h: Ditto.
	* libc/sys/linux/include/netns/sp.h: Ditto.
	* libc/sys/linux/include/netns/spidp.h: Ditto.
	* libc/sys/linux/include/netns/spp_debug.h: Ditto.
	* libc/sys/linux/include/netns/spp_timer.h: Ditto.
	* libc/sys/linux/include/netns/spp_var.h: Ditto.
	* libc/sys/linux/include/rpc/Makefile: Ditto.
	* libc/sys/linux/include/rpc/auth.h: Ditto.
	* libc/sys/linux/include/rpc/auth_des.h: Ditto.
	* libc/sys/linux/include/rpc/auth_kerb.h: Ditto.
	* libc/sys/linux/include/rpc/auth_unix.h: Ditto.
	* libc/sys/linux/include/rpc/clnt.h: Ditto.
	* libc/sys/linux/include/rpc/clnt_soc.h: Ditto.
	* libc/sys/linux/include/rpc/clnt_stat.h: Ditto.
	* libc/sys/linux/include/rpc/des.h: Ditto.
	* libc/sys/linux/include/rpc/des_crypt.h: Ditto.
	* libc/sys/linux/include/rpc/nettype.h: Ditto.
	* libc/sys/linux/include/rpc/pmap_clnt.h: Ditto.
	* libc/sys/linux/include/rpc/pmap_prot.h: Ditto.
	* libc/sys/linux/include/rpc/pmap_rmt.h: Ditto.
	* libc/sys/linux/include/rpc/raw.h: Ditto.
	* libc/sys/linux/include/rpc/rpc.h: Ditto.
	* libc/sys/linux/include/rpc/rpc_com.h: Ditto.
	* libc/sys/linux/include/rpc/rpc_msg.h: Ditto.
	* libc/sys/linux/include/rpc/rpcb_clnt.h: Ditto.
	* libc/sys/linux/include/rpc/rpcb_prot.h: Ditto.
	* libc/sys/linux/include/rpc/rpcb_prot.x: Ditto.
	* libc/sys/linux/include/rpc/rpcent.h: Ditto.
	* libc/sys/linux/include/rpc/svc.h: Ditto.
	* libc/sys/linux/include/rpc/svc_auth.h: Ditto.
	* libc/sys/linux/include/rpc/svc_dg.h: Ditto.
	* libc/sys/linux/include/rpc/svc_soc.h: Ditto.
	* libc/sys/linux/include/rpc/types.h: Ditto.
	* libc/sys/linux/include/rpc/xdr.h: Ditto.
	* libc/sys/linux/intl/Makefile.am: Ditto.
	* libc/sys/linux/intl/Makefile.in: Ditto.
	* libc/sys/linux/intl/bindtextdom.c: Ditto.
	* libc/sys/linux/intl/catgets.c: Ditto.
	* libc/sys/linux/intl/catgetsinfo.h: Ditto.
	* libc/sys/linux/intl/config.h: Ditto.
	* libc/sys/linux/intl/dcgettext.c: Ditto.
	* libc/sys/linux/intl/dcigettext.c: Ditto.
	* libc/sys/linux/intl/dcngettext.c: Ditto.
	* libc/sys/linux/intl/dgettext.c: Ditto.
	* libc/sys/linux/intl/dngettext.c: Ditto.
	* libc/sys/linux/intl/explodename.c: Ditto.
	* libc/sys/linux/intl/finddomain.c: Ditto.
	* libc/sys/linux/intl/gettext.c: Ditto.
	* libc/sys/linux/intl/gettext.h: Ditto.
	* libc/sys/linux/intl/gettextP.h: Ditto.
	* libc/sys/linux/intl/hash-string.h: Ditto.
	* libc/sys/linux/intl/l10nflist.c: Ditto.
	* libc/sys/linux/intl/loadinfo.h: Ditto.
	* libc/sys/linux/intl/loadmsgcat.c: Ditto.
	* libc/sys/linux/intl/locale.alias: Ditto.
	* libc/sys/linux/intl/localealias.c: Ditto.
	* libc/sys/linux/intl/ngettext.c: Ditto.
	* libc/sys/linux/intl/open_catalog.c: Ditto.
	* libc/sys/linux/intl/plural.c: Ditto.
	* libc/sys/linux/intl/plural.y: Ditto.
	* libc/sys/linux/intl/stpcpy.c: Ditto.
	* libc/sys/linux/intl/textdomain.c: Ditto.
	* libc/sys/linux/linuxthreads/LICENSE: Ditto.
	* libc/sys/linux/linuxthreads/Makefile.am: Ditto.
	* libc/sys/linux/linuxthreads/Makefile.in: Ditto.
	* libc/sys/linux/linuxthreads/aclocal.m4: Ditto.
	* libc/sys/linux/linuxthreads/attr.c: Ditto.
	* libc/sys/linux/linuxthreads/barrier.c: Ditto.
	* libc/sys/linux/linuxthreads/bp-sym.h: Ditto.
	* libc/sys/linux/linuxthreads/cancel.c: Ditto.
	* libc/sys/linux/linuxthreads/condvar.c: Ditto.
	* libc/sys/linux/linuxthreads/config.h: Ditto.
	* libc/sys/linux/linuxthreads/configure: Ditto.
	* libc/sys/linux/linuxthreads/configure.in: Ditto.
	* libc/sys/linux/linuxthreads/defs.awk: Ditto.
	* libc/sys/linux/linuxthreads/ecmutex.c: Ditto.
	* libc/sys/linux/linuxthreads/events.c: Ditto.
	* libc/sys/linux/linuxthreads/getcpuclockid.c: Ditto.
	* libc/sys/linux/linuxthreads/getreent.c: Ditto.
	* libc/sys/linux/linuxthreads/internals.h: Ditto.
	* libc/sys/linux/linuxthreads/join.c: Ditto.
	* libc/sys/linux/linuxthreads/joinrace.c: Ditto.
	* libc/sys/linux/linuxthreads/kernel-features.h: Ditto.
	* libc/sys/linux/linuxthreads/libc-internal.h: Ditto.
	* libc/sys/linux/linuxthreads/libc-symbols.h: Ditto.
	* libc/sys/linux/linuxthreads/linuxthreads.texi: Ditto.
	* libc/sys/linux/linuxthreads/lockfile.c: Ditto.
	* libc/sys/linux/linuxthreads/manager.c: Ditto.
	* libc/sys/linux/linuxthreads/mq_notify.c: Ditto.
	* libc/sys/linux/linuxthreads/mutex.c: Ditto.
	* libc/sys/linux/linuxthreads/no-tsd.c: Ditto.
	* libc/sys/linux/linuxthreads/oldsemaphore.c: Ditto.
	* libc/sys/linux/linuxthreads/posix-timer.h: Ditto.
	* libc/sys/linux/linuxthreads/prio.c: Ditto.
	* libc/sys/linux/linuxthreads/proc_service.h: Ditto.
	* libc/sys/linux/linuxthreads/pt-machine.c: Ditto.
	* libc/sys/linux/linuxthreads/ptclock_gettime.c: Ditto.
	* libc/sys/linux/linuxthreads/ptclock_settime.c: Ditto.
	* libc/sys/linux/linuxthreads/ptfork.c: Ditto.
	* libc/sys/linux/linuxthreads/pthread.c: Ditto.
	* libc/sys/linux/linuxthreads/ptlongjmp.c: Ditto.
	* libc/sys/linux/linuxthreads/queue.h: Ditto.
	* libc/sys/linux/linuxthreads/reent.c: Ditto.
	* libc/sys/linux/linuxthreads/reqsyscalls.c: Ditto.
	* libc/sys/linux/linuxthreads/restart.h: Ditto.
	* libc/sys/linux/linuxthreads/rwlock.c: Ditto.
	* libc/sys/linux/linuxthreads/semaphore.c: Ditto.
	* libc/sys/linux/linuxthreads/semaphore.h: Ditto.
	* libc/sys/linux/linuxthreads/shlib-compat.h: Ditto.
	* libc/sys/linux/linuxthreads/signals.c: Ditto.
	* libc/sys/linux/linuxthreads/specific.c: Ditto.
	* libc/sys/linux/linuxthreads/spinlock.c: Ditto.
	* libc/sys/linux/linuxthreads/spinlock.h: Ditto.
	* libc/sys/linux/linuxthreads/sysctl.c: Ditto.
	* libc/sys/linux/linuxthreads/td_init.c: Ditto.
	* libc/sys/linux/linuxthreads/td_log.c: Ditto.
	* libc/sys/linux/linuxthreads/td_symbol_list.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_clear_event.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_delete.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_enable_stats.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_event_addr.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_event_getmsg.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_get_nthreads.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_get_ph.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_get_stats.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_map_id2thr.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_map_lwp2thr.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_new.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_reset_stats.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_set_event.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_setconcurrency.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_thr_iter.c: Ditto.
	* libc/sys/linux/linuxthreads/td_ta_tsd_iter.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_clear_event.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_dbresume.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_dbsuspend.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_event_enable.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_event_getmsg.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_get_info.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_getfpregs.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_getgregs.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_getxregs.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_getxregsize.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_set_event.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_setfpregs.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_setgregs.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_setprio.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_setsigpending.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_setxregs.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_sigsetmask.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_tsd.c: Ditto.
	* libc/sys/linux/linuxthreads/td_thr_validate.c: Ditto.
	* libc/sys/linux/linuxthreads/testrtsig.h: Ditto.
	* libc/sys/linux/linuxthreads/thread_db.h: Ditto.
	* libc/sys/linux/linuxthreads/thread_dbP.h: Ditto.
	* libc/sys/linux/linuxthreads/timer_create.c: Ditto.
	* libc/sys/linux/linuxthreads/timer_delete.c: Ditto.
	* libc/sys/linux/linuxthreads/timer_getoverr.c: Ditto.
	* libc/sys/linux/linuxthreads/timer_gettime.c: Ditto.
	* libc/sys/linux/linuxthreads/timer_routines.c: Ditto.
	* libc/sys/linux/linuxthreads/timer_settime.c: Ditto.
	* libc/sys/linux/linuxthreads/tst-cancel.c: Ditto.
	* libc/sys/linux/linuxthreads/tst-context.c: Ditto.
	* libc/sys/linux/linuxthreads/tststack.c: Ditto.
	* libc/sys/linux/linuxthreads/unload.c: Ditto.
	* libc/sys/linux/linuxthreads/weaks.c: Ditto.
	* libc/sys/linux/linuxthreads/wrapsyscall.c: Ditto.
	* libc/sys/linux/linuxthreads/bits/initspin.h: Ditto.
	* libc/sys/linux/linuxthreads/bits/libc-lock.h: Ditto.
	* libc/sys/linux/linuxthreads/bits/libc-tsd.h: Ditto.
	* libc/sys/linux/linuxthreads/bits/local_lim.h: Ditto.
	* libc/sys/linux/linuxthreads/bits/posix_opt.h: Ditto.
	* libc/sys/linux/linuxthreads/bits/pthreadtypes.h: Ditto.
	* libc/sys/linux/linuxthreads/bits/sigthread.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/Makefile.am: Ditto.
	* libc/sys/linux/linuxthreads/machine/Makefile.in: Ditto.
	* libc/sys/linux/linuxthreads/machine/aclocal.m4: Ditto.
	* libc/sys/linux/linuxthreads/machine/configure: Ditto.
	* libc/sys/linux/linuxthreads/machine/configure.in: Ditto.
	* libc/sys/linux/linuxthreads/machine/generic/generic-sysd: Ditto.ep.h
	* libc/sys/linux/linuxthreads/machine/i386/Makefile.am: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/Makefile.in: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/aclocal.m4: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/bp-asm.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/clone.S: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/configure: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/configure.in: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.S: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/pspinlock.c: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/pt-machine.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/sigcontextinfo.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/stackinfo.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/sysdep.S: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/sysdep.h: Ditto.
	* libc/sys/linux/linuxthreads/machine/i386/useldt.h: Ditto.
	* libc/sys/linux/machine/i386/dl-machine.h: Ditto.
	* libc/sys/linux/net/Makefile.am: Ditto.
	* libc/sys/linux/net/Makefile.in: Ditto.
	* libc/sys/linux/net/addr2ascii.3: Ditto.
	* libc/sys/linux/net/addr2ascii.c: Ditto.
	* libc/sys/linux/net/ascii2addr.c: Ditto.
	* libc/sys/linux/net/base64.c: Ditto.
	* libc/sys/linux/net/bindresvport.c: Ditto.
	* libc/sys/linux/net/byteorder.3: Ditto.
	* libc/sys/linux/net/ether_addr.c: Ditto.
	* libc/sys/linux/net/ethers.3: Ditto.
	* libc/sys/linux/net/getaddrinfo.3: Ditto.
	* libc/sys/linux/net/getaddrinfo.c: Ditto.
	* libc/sys/linux/net/gethostbydns.c: Ditto.
	* libc/sys/linux/net/gethostbyht.c: Ditto.
	* libc/sys/linux/net/gethostbyname.3: Ditto.
	* libc/sys/linux/net/gethostbynis.c: Ditto.
	* libc/sys/linux/net/gethostnamadr.c: Ditto.
	* libc/sys/linux/net/getifaddrs.3: Ditto.
	* libc/sys/linux/net/getifaddrs.c: Ditto.
	* libc/sys/linux/net/getipnodebyname.3: Ditto.
	* libc/sys/linux/net/getnameinfo.3: Ditto.
	* libc/sys/linux/net/getnameinfo.c: Ditto.
	* libc/sys/linux/net/getnetbydns.c: Ditto.
	* libc/sys/linux/net/getnetbyht.c: Ditto.
	* libc/sys/linux/net/getnetbynis.c: Ditto.
	* libc/sys/linux/net/getnetent.3: Ditto.
	* libc/sys/linux/net/getnetnamadr.c: Ditto.
	* libc/sys/linux/net/getproto.c: Ditto.
	* libc/sys/linux/net/getprotoent.3: Ditto.
	* libc/sys/linux/net/getprotoent.c: Ditto.
	* libc/sys/linux/net/getprotoname.c: Ditto.
	* libc/sys/linux/net/getservbyname.c: Ditto.
	* libc/sys/linux/net/getservbyport.c: Ditto.
	* libc/sys/linux/net/getservent.3: Ditto.
	* libc/sys/linux/net/getservent.c: Ditto.
	* libc/sys/linux/net/herror.c: Ditto.
	* libc/sys/linux/net/hesiod.3: Ditto.
	* libc/sys/linux/net/hesiod.c: Ditto.
	* libc/sys/linux/net/if_indextoname.3: Ditto.
	* libc/sys/linux/net/ifname.c: Ditto.
	* libc/sys/linux/net/inet.3: Ditto.
	* libc/sys/linux/net/inet6_option_s: Ditto.pace.3
	* libc/sys/linux/net/inet6_rthdr_space.3: Ditto.
	* libc/sys/linux/net/inet_addr.c: Ditto.
	* libc/sys/linux/net/inet_lnaof.c: Ditto.
	* libc/sys/linux/net/inet_makeaddr.c: Ditto.
	* libc/sys/linux/net/inet_net.3: Ditto.
	* libc/sys/linux/net/inet_net_ntop.c: Ditto.
	* libc/sys/linux/net/inet_net_pton.c: Ditto.
	* libc/sys/linux/net/inet_neta.c: Ditto.
	* libc/sys/linux/net/inet_netof.c: Ditto.
	* libc/sys/linux/net/inet_network.c: Ditto.
	* libc/sys/linux/net/inet_ntoa.c: Ditto.
	* libc/sys/linux/net/inet_ntop.c: Ditto.
	* libc/sys/linux/net/inet_pton.c: Ditto.
	* libc/sys/linux/net/innetgr-stub.c: Ditto.
	* libc/sys/linux/net/ip6opt.c: Ditto.
	* libc/sys/linux/net/iso_addr.3: Ditto.
	* libc/sys/linux/net/iso_addr.c: Ditto.
	* libc/sys/linux/net/issetugid-stub.c: Ditto.
	* libc/sys/linux/net/linkaddr.3: Ditto.
	* libc/sys/linux/net/linkaddr.c: Ditto.
	* libc/sys/linux/net/map_v4v6.c: Ditto.
	* libc/sys/linux/net/name6.c: Ditto.
	* libc/sys/linux/net/namespace.h: Ditto.
	* libc/sys/linux/net/ns.3: Ditto.
	* libc/sys/linux/net/ns_addr.c: Ditto.
	* libc/sys/linux/net/ns_name.c: Ditto.
	* libc/sys/linux/net/ns_netint.c: Ditto.
	* libc/sys/linux/net/ns_ntoa.c: Ditto.
	* libc/sys/linux/net/ns_parse.c: Ditto.
	* libc/sys/linux/net/ns_print.c: Ditto.
	* libc/sys/linux/net/ns_ttl.c: Ditto.
	* libc/sys/linux/net/nsap_addr.c: Ditto.
	* libc/sys/linux/net/nsdispatch.3: Ditto.
	* libc/sys/linux/net/nsdispatch.c: Ditto.
	* libc/sys/linux/net/nslexer.c: Ditto.
	* libc/sys/linux/net/nslexer.l: Ditto.
	* libc/sys/linux/net/nsparser.c: Ditto.
	* libc/sys/linux/net/nsparser.h: Ditto.
	* libc/sys/linux/net/nsparser.y: Ditto.
	* libc/sys/linux/net/rcmd.3: Ditto.
	* libc/sys/linux/net/rcmd.c: Ditto.
	* libc/sys/linux/net/rcmdsh.3: Ditto.
	* libc/sys/linux/net/rcmdsh.c: Ditto.
	* libc/sys/linux/net/recv.c: Ditto.
	* libc/sys/linux/net/res_comp.c: Ditto.
	* libc/sys/linux/net/res_config.h: Ditto.
	* libc/sys/linux/net/res_data.c: Ditto.
	* libc/sys/linux/net/res_debug.c: Ditto.
	* libc/sys/linux/net/res_init.c: Ditto.
	* libc/sys/linux/net/res_mkquery.c: Ditto.
	* libc/sys/linux/net/res_mkupdate.c: Ditto.
	* libc/sys/linux/net/res_query.c: Ditto.
	* libc/sys/linux/net/res_send.c: Ditto.
	* libc/sys/linux/net/res_update.c: Ditto.
	* libc/sys/linux/net/resolver.3: Ditto.
	* libc/sys/linux/net/rthdr.c: Ditto.
	* libc/sys/linux/net/send.c: Ditto.
	* libc/sys/linux/net/un-namespace.h: Ditto.
	* libc/sys/linux/net/vars.c: Ditto.
	* libc/sys/linux/stdlib/COPYRIGHT: Ditto.
	* libc/sys/linux/stdlib/Makefile.am: Ditto.
	* libc/sys/linux/stdlib/Makefile.in: Ditto.
	* libc/sys/linux/stdlib/cclass.h: Ditto.
	* libc/sys/linux/stdlib/cname.h: Ditto.
	* libc/sys/linux/stdlib/collate.c: Ditto.
	* libc/sys/linux/stdlib/collate.h: Ditto.
	* libc/sys/linux/stdlib/collcmp.c: Ditto.
	* libc/sys/linux/stdlib/engine.c: Ditto.
	* libc/sys/linux/stdlib/fnmatch.3: Ditto.
	* libc/sys/linux/stdlib/fnmatch.c: Ditto.
	* libc/sys/linux/stdlib/glob.3: Ditto.
	* libc/sys/linux/stdlib/glob.c: Ditto.
	* libc/sys/linux/stdlib/reallocf.c: Ditto.
	* libc/sys/linux/stdlib/regcomp.c: Ditto.
	* libc/sys/linux/stdlib/regerror.c: Ditto.
	* libc/sys/linux/stdlib/regex.3: Ditto.
	* libc/sys/linux/stdlib/regex2.h: Ditto.
	* libc/sys/linux/stdlib/regexec.c: Ditto.
	* libc/sys/linux/stdlib/regfree.c: Ditto.
	* libc/sys/linux/stdlib/utils.h: Ditto.
	* libc/sys/linux/stdlib/wordexp.c: Ditto.
	* libc/sys/linux/stdlib/wordfree.c: Ditto.
	* libc/sys/linux/sys/dlfcn.h: Ditto.
	* libc/sys/linux/sys/elfclass.h: Ditto.
	* libc/sys/linux/sys/event.h: Ditto.
	* libc/sys/linux/sys/ioccom.h: Ditto.
	* libc/sys/linux/sys/libc-tsd.h: Ditto.
	* libc/sys/linux/sys/link.h: Ditto.
	* libc/sys/linux/sys/lock.h: Ditto.
	* libc/sys/linux/sys/param.h: Ditto.
	* libc/sys/linux/sys/socket.h: Ditto.
	* libc/sys/linux/sys/sockio.h: Ditto.
This commit is contained in:
Jeff Johnston 2003-05-28 22:04:40 +00:00
parent 4218d88897
commit b359e82cea
564 changed files with 147374 additions and 3 deletions

View File

@ -1,3 +1,571 @@
2003-05-28 Jeff Johnston <jjohnstn@redhat.com>
Tom Fitzsimmons <fitzsim@redhat.com>
* configure.in: Add iconvdata support for x86 linux.
* configure: Regenerated.
* libc/sys/linux/Makefile.am: Add EL/IX level 3 network, dynamic
library, iconv, and linuxthreads support.
* libc/sys/linux/configure.in: Ditto.
* libc/sys/linux/Makefile.in: Regenerated.
* libc/sys/linux/configure: Ditto.
* iconvdata/EUC-JP.irreversible: New file.
* iconvdata/Makefile.am: Ditto.
* iconvdata/Makefile.in: Ditto.
* iconvdata/SJIS.irreversible: Ditto.
* iconvdata/aclocal.m4: Ditto.
* iconvdata/configure: Ditto.
* iconvdata/configure.in: Ditto.
* iconvdata/dummy.c: Ditto.
* iconvdata/euc-jp.c: Ditto.
* iconvdata/gconv-modules: Ditto.
* iconvdata/jis0201.c: Ditto.
* iconvdata/jis0201.h: Ditto.
* iconvdata/jis0208.c: Ditto.
* iconvdata/jis0208.h: Ditto.
* iconvdata/jis0212.c: Ditto.
* iconvdata/jis0212.h: Ditto.
* iconvdata/sjis.c: Ditto.
* libc/include/errno.h: Protect definition of error_t.
* libc/sys/linux/gethostid.c: New file.
* libc/sys/linux/sethostid.c: Ditto.
* libc/sys/linux/dl/Makefile.am: Ditto.
* libc/sys/linux/dl/Makefile.in: Ditto.
* libc/sys/linux/dl/abi-tag.h: Ditto.
* libc/sys/linux/dl/atomicity.h: Ditto.
* libc/sys/linux/dl/dl-addr.c: Ditto.
* libc/sys/linux/dl/dl-cache.c: Ditto.
* libc/sys/linux/dl/dl-cache.h: Ditto.
* libc/sys/linux/dl/dl-close.c: Ditto.
* libc/sys/linux/dl/dl-debug.c: Ditto.
* libc/sys/linux/dl/dl-deps.c: Ditto.
* libc/sys/linux/dl/dl-dst.h: Ditto.
* libc/sys/linux/dl/dl-error.c: Ditto.
* libc/sys/linux/dl/dl-fini.c: Ditto.
* libc/sys/linux/dl/dl-init.c: Ditto.
* libc/sys/linux/dl/dl-iteratephdr.c: Ditto.
* libc/sys/linux/dl/dl-libc.c: Ditto.
* libc/sys/linux/dl/dl-librecon.h: Ditto.
* libc/sys/linux/dl/dl-load.c: Ditto.
* libc/sys/linux/dl/dl-lookup.c: Ditto.
* libc/sys/linux/dl/dl-lookupcfg.h: Ditto.
* libc/sys/linux/dl/dl-minimal.c: Ditto.
* libc/sys/linux/dl/dl-misc.c: Ditto.
* libc/sys/linux/dl/dl-object.c: Ditto.
* libc/sys/linux/dl/dl-open.c: Ditto.
* libc/sys/linux/dl/dl-osinfo.h: Ditto.
* libc/sys/linux/dl/dl-profile.c: Ditto.
* libc/sys/linux/dl/dl-profstub.c: Ditto.
* libc/sys/linux/dl/dl-reloc.c: Ditto.
* libc/sys/linux/dl/dl-runtime.c: Ditto.
* libc/sys/linux/dl/dl-support.c: Ditto.
* libc/sys/linux/dl/dl-sym.c: Ditto.
* libc/sys/linux/dl/dl-version.c: Ditto.
* libc/sys/linux/dl/dlfcn.h: Ditto.
* libc/sys/linux/dl/do-lookup.h: Ditto.
* libc/sys/linux/dl/do-rel.h: Ditto.
* libc/sys/linux/dl/dynamic-link.h: Ditto.
* libc/sys/linux/dl/kernel-features.h: Ditto.
* libc/sys/linux/dl/ldsodefs.h: Ditto.
* libc/sys/linux/dl/libintl.h: Ditto.
* libc/sys/linux/dl/trusted-dirs.h: Ditto.
* libc/sys/linux/dl/unsecvars.h: Ditto.
* libc/sys/linux/iconv/Makefile.am: Ditto.
* libc/sys/linux/iconv/Makefile.in: Ditto.
* libc/sys/linux/iconv/categories.def: Ditto.
* libc/sys/linux/iconv/dummy-repertoire.c: Ditto.
* libc/sys/linux/iconv/gconv.c: Ditto.
* libc/sys/linux/iconv/gconv_builtin.c: Ditto.
* libc/sys/linux/iconv/gconv_builtin.h: Ditto.
* libc/sys/linux/iconv/gconv_cache.c: Ditto.
* libc/sys/linux/iconv/gconv_charset.h: Ditto.
* libc/sys/linux/iconv/gconv_close.c: Ditto.
* libc/sys/linux/iconv/gconv_conf.c: Ditto.
* libc/sys/linux/iconv/gconv_db.c: Ditto.
* libc/sys/linux/iconv/gconv_dl.c: Ditto.
* libc/sys/linux/iconv/gconv_int.h: Ditto.
* libc/sys/linux/iconv/gconv_open.c: Ditto.
* libc/sys/linux/iconv/gconv_simple.c: Ditto.
* libc/sys/linux/iconv/gconv_trans.c: Ditto.
* libc/sys/linux/iconv/hash-string.h: Ditto.
* libc/sys/linux/iconv/iconv.c: Ditto.
* libc/sys/linux/iconv/iconv.h: Ditto.
* libc/sys/linux/iconv/iconv_charmap.c: Ditto.
* libc/sys/linux/iconv/iconv_close.c: Ditto.
* libc/sys/linux/iconv/iconv_open.c: Ditto.
* libc/sys/linux/iconv/iconvconfig.c: Ditto.
* libc/sys/linux/iconv/iconvconfig.h: Ditto.
* libc/sys/linux/iconv/loadinfo.h: Ditto.
* libc/sys/linux/iconv/localeinfo.h: Ditto.
* libc/sys/linux/iconv/loop.c: Ditto.
* libc/sys/linux/iconv/skeleton.c: Ditto.
* libc/sys/linux/iconv/strtab.c: Ditto.
* libc/sys/linux/include/dl-hash.h: Ditto.
* libc/sys/linux/include/dlfcn.h: Ditto.
* libc/sys/linux/include/fnmatch.h: Ditto.
* libc/sys/linux/include/gconv.h: Ditto.
* libc/sys/linux/include/glob.h: Ditto.
* libc/sys/linux/include/hesiod.h: Ditto.
* libc/sys/linux/include/ifaddrs.h: Ditto.
* libc/sys/linux/include/libc_private.h: Ditto.
* libc/sys/linux/include/link.h: Ditto.
* libc/sys/linux/include/namespace.h: Ditto.
* libc/sys/linux/include/netconfig.h: Ditto.
* libc/sys/linux/include/netdb.h: Ditto.
* libc/sys/linux/include/nsswitch.h: Ditto.
* libc/sys/linux/include/regex.h: Ditto.
* libc/sys/linux/include/resolv.h: Ditto.
* libc/sys/linux/include/rune.h: Ditto.
* libc/sys/linux/include/runetype.h: Ditto.
* libc/sys/linux/include/semaphore.h: Ditto.
* libc/sys/linux/include/setlocale.h: Ditto.
* libc/sys/linux/include/un-namespace.h: Ditto.
* libc/sys/linux/include/wordexp.h: Ditto.
* libc/sys/linux/include/arpa/ftp.h: Ditto.
* libc/sys/linux/include/arpa/inet.h: Ditto.
* libc/sys/linux/include/arpa/nameser.h: Ditto.
* libc/sys/linux/include/arpa/nameser_compat.h: Ditto.
* libc/sys/linux/include/arpa/telnet.h: Ditto.
* libc/sys/linux/include/arpa/tftp.h: Ditto.
* libc/sys/linux/include/net/bpf.h: Ditto.
* libc/sys/linux/include/net/bpf_compat.h: Ditto.
* libc/sys/linux/include/net/bpfdesc.h: Ditto.
* libc/sys/linux/include/net/bridge.h: Ditto.
* libc/sys/linux/include/net/ethernet.h: Ditto.
* libc/sys/linux/include/net/fddi.h: Ditto.
* libc/sys/linux/include/net/if.h: Ditto.
* libc/sys/linux/include/net/if_arc.h: Ditto.
* libc/sys/linux/include/net/if_arp.h: Ditto.
* libc/sys/linux/include/net/if_atm.h: Ditto.
* libc/sys/linux/include/net/if_dl.h: Ditto.
* libc/sys/linux/include/net/if_gif.h: Ditto.
* libc/sys/linux/include/net/if_ieee80211.h: Ditto.
* libc/sys/linux/include/net/if_llc.h: Ditto.
* libc/sys/linux/include/net/if_media.h: Ditto.
* libc/sys/linux/include/net/if_mib.h: Ditto.
* libc/sys/linux/include/net/if_ppp.h: Ditto.
* libc/sys/linux/include/net/if_pppvar.h: Ditto.
* libc/sys/linux/include/net/if_slvar.h: Ditto.
* libc/sys/linux/include/net/if_sppp.h: Ditto.
* libc/sys/linux/include/net/if_stf.h: Ditto.
* libc/sys/linux/include/net/if_tap.h: Ditto.
* libc/sys/linux/include/net/if_tapvar.h: Ditto.
* libc/sys/linux/include/net/if_tun.h: Ditto.
* libc/sys/linux/include/net/if_tunvar.h: Ditto.
* libc/sys/linux/include/net/if_types.h: Ditto.
* libc/sys/linux/include/net/if_var.h: Ditto.
* libc/sys/linux/include/net/if_vlan_var.h: Ditto.
* libc/sys/linux/include/net/intrq.h: Ditto.
* libc/sys/linux/include/net/iso88025.h: Ditto.
* libc/sys/linux/include/net/net_osdep.h: Ditto.
* libc/sys/linux/include/net/netisr.h: Ditto.
* libc/sys/linux/include/net/pfil.h: Ditto.
* libc/sys/linux/include/net/pfkeyv2.h: Ditto.
* libc/sys/linux/include/net/ppp_comp.h: Ditto.
* libc/sys/linux/include/net/ppp_defs.h: Ditto.
* libc/sys/linux/include/net/radix.h: Ditto.
* libc/sys/linux/include/net/raw_cb.h: Ditto.
* libc/sys/linux/include/net/route.h: Ditto.
* libc/sys/linux/include/net/slcompress.h: Ditto.
* libc/sys/linux/include/net/slip.h: Ditto.
* libc/sys/linux/include/net/zlib.h: Ditto.
* libc/sys/linux/include/netinet/icmp6.h: Ditto.
* libc/sys/linux/include/netinet/icmp_var.h: Ditto.
* libc/sys/linux/include/netinet/if_atm.h: Ditto.
* libc/sys/linux/include/netinet/if_ether.h: Ditto.
* libc/sys/linux/include/netinet/igmp.h: Ditto.
* libc/sys/linux/include/netinet/igmp_var.h: Ditto.
* libc/sys/linux/include/netinet/in.h: Ditto.
* libc/sys/linux/include/netinet/in_gif.h: Ditto.
* libc/sys/linux/include/netinet/in_pcb.h: Ditto.
* libc/sys/linux/include/netinet/in_systm.h: Ditto.
* libc/sys/linux/include/netinet/in_var.h: Ditto.
* libc/sys/linux/include/netinet/ip.h: Ditto.
* libc/sys/linux/include/netinet/ip6.h: Ditto.
* libc/sys/linux/include/netinet/ip_dummynet.h: Ditto.
* libc/sys/linux/include/netinet/ip_ecn.h: Ditto.
* libc/sys/linux/include/netinet/ip_encap.h: Ditto.
* libc/sys/linux/include/netinet/ip_flow.h: Ditto.
* libc/sys/linux/include/netinet/ip_fw.h: Ditto.
* libc/sys/linux/include/netinet/ip_icmp.h: Ditto.
* libc/sys/linux/include/netinet/ip_mroute.h: Ditto.
* libc/sys/linux/include/netinet/ip_var.h: Ditto.
* libc/sys/linux/include/netinet/ipprotosw.h: Ditto.
* libc/sys/linux/include/netinet/tcp.h: Ditto.
* libc/sys/linux/include/netinet/tcp_debug.h: Ditto.
* libc/sys/linux/include/netinet/tcp_fsm.h: Ditto.
* libc/sys/linux/include/netinet/tcp_seq.h: Ditto.
* libc/sys/linux/include/netinet/tcp_timer.h: Ditto.
* libc/sys/linux/include/netinet/tcp_var.h: Ditto.
* libc/sys/linux/include/netinet/tcpip.h: Ditto.
* libc/sys/linux/include/netinet/udp.h: Ditto.
* libc/sys/linux/include/netinet/udp_var.h: Ditto.
* libc/sys/linux/include/netinet6/ah.h: Ditto.
* libc/sys/linux/include/netinet6/ah6.h: Ditto.
* libc/sys/linux/include/netinet6/esp.h: Ditto.
* libc/sys/linux/include/netinet6/esp6.h: Ditto.
* libc/sys/linux/include/netinet6/esp_rijndael.h: Ditto.
* libc/sys/linux/include/netinet6/icmp6.h: Ditto.
* libc/sys/linux/include/netinet6/in6.h: Ditto.
* libc/sys/linux/include/netinet6/in6_gif.h: Ditto.
* libc/sys/linux/include/netinet6/in6_ifattach.h: Ditto.
* libc/sys/linux/include/netinet6/in6_pcb.h: Ditto.
* libc/sys/linux/include/netinet6/in6_prefix.h: Ditto.
* libc/sys/linux/include/netinet6/in6_var.h: Ditto.
* libc/sys/linux/include/netinet6/ip6.h: Ditto.
* libc/sys/linux/include/netinet6/ip6_ecn.h: Ditto.
* libc/sys/linux/include/netinet6/ip6_fw.h: Ditto.
* libc/sys/linux/include/netinet6/ip6_mroute.h: Ditto.
* libc/sys/linux/include/netinet6/ip6_var.h: Ditto.
* libc/sys/linux/include/netinet6/ip6protosw.h: Ditto.
* libc/sys/linux/include/netinet6/ipcomp.h: Ditto.
* libc/sys/linux/include/netinet6/ipcomp6.h: Ditto.
* libc/sys/linux/include/netinet6/ipsec.h: Ditto.
* libc/sys/linux/include/netinet6/ipsec6.h: Ditto.
* libc/sys/linux/include/netinet6/mld6_var.h: Ditto.
* libc/sys/linux/include/netinet6/nd6.h: Ditto.
* libc/sys/linux/include/netinet6/pim6.h: Ditto.
* libc/sys/linux/include/netinet6/pim6_var.h: Ditto.
* libc/sys/linux/include/netinet6/raw_ip6.h: Ditto.
* libc/sys/linux/include/netinet6/scope6_var.h: Ditto.
* libc/sys/linux/include/netinet6/tcp6_var.h: Ditto.
* libc/sys/linux/include/netinet6/udp6_var.h: Ditto.
* libc/sys/linux/include/netns/idp.h: Ditto.
* libc/sys/linux/include/netns/idp_var.h: Ditto.
* libc/sys/linux/include/netns/ns.h: Ditto.
* libc/sys/linux/include/netns/ns_error.h: Ditto.
* libc/sys/linux/include/netns/ns_if.h: Ditto.
* libc/sys/linux/include/netns/ns_pcb.h: Ditto.
* libc/sys/linux/include/netns/sp.h: Ditto.
* libc/sys/linux/include/netns/spidp.h: Ditto.
* libc/sys/linux/include/netns/spp_debug.h: Ditto.
* libc/sys/linux/include/netns/spp_timer.h: Ditto.
* libc/sys/linux/include/netns/spp_var.h: Ditto.
* libc/sys/linux/include/rpc/Makefile: Ditto.
* libc/sys/linux/include/rpc/auth.h: Ditto.
* libc/sys/linux/include/rpc/auth_des.h: Ditto.
* libc/sys/linux/include/rpc/auth_kerb.h: Ditto.
* libc/sys/linux/include/rpc/auth_unix.h: Ditto.
* libc/sys/linux/include/rpc/clnt.h: Ditto.
* libc/sys/linux/include/rpc/clnt_soc.h: Ditto.
* libc/sys/linux/include/rpc/clnt_stat.h: Ditto.
* libc/sys/linux/include/rpc/des.h: Ditto.
* libc/sys/linux/include/rpc/des_crypt.h: Ditto.
* libc/sys/linux/include/rpc/nettype.h: Ditto.
* libc/sys/linux/include/rpc/pmap_clnt.h: Ditto.
* libc/sys/linux/include/rpc/pmap_prot.h: Ditto.
* libc/sys/linux/include/rpc/pmap_rmt.h: Ditto.
* libc/sys/linux/include/rpc/raw.h: Ditto.
* libc/sys/linux/include/rpc/rpc.h: Ditto.
* libc/sys/linux/include/rpc/rpc_com.h: Ditto.
* libc/sys/linux/include/rpc/rpc_msg.h: Ditto.
* libc/sys/linux/include/rpc/rpcb_clnt.h: Ditto.
* libc/sys/linux/include/rpc/rpcb_prot.h: Ditto.
* libc/sys/linux/include/rpc/rpcb_prot.x: Ditto.
* libc/sys/linux/include/rpc/rpcent.h: Ditto.
* libc/sys/linux/include/rpc/svc.h: Ditto.
* libc/sys/linux/include/rpc/svc_auth.h: Ditto.
* libc/sys/linux/include/rpc/svc_dg.h: Ditto.
* libc/sys/linux/include/rpc/svc_soc.h: Ditto.
* libc/sys/linux/include/rpc/types.h: Ditto.
* libc/sys/linux/include/rpc/xdr.h: Ditto.
* libc/sys/linux/intl/Makefile.am: Ditto.
* libc/sys/linux/intl/Makefile.in: Ditto.
* libc/sys/linux/intl/bindtextdom.c: Ditto.
* libc/sys/linux/intl/catgets.c: Ditto.
* libc/sys/linux/intl/catgetsinfo.h: Ditto.
* libc/sys/linux/intl/config.h: Ditto.
* libc/sys/linux/intl/dcgettext.c: Ditto.
* libc/sys/linux/intl/dcigettext.c: Ditto.
* libc/sys/linux/intl/dcngettext.c: Ditto.
* libc/sys/linux/intl/dgettext.c: Ditto.
* libc/sys/linux/intl/dngettext.c: Ditto.
* libc/sys/linux/intl/explodename.c: Ditto.
* libc/sys/linux/intl/finddomain.c: Ditto.
* libc/sys/linux/intl/gettext.c: Ditto.
* libc/sys/linux/intl/gettext.h: Ditto.
* libc/sys/linux/intl/gettextP.h: Ditto.
* libc/sys/linux/intl/hash-string.h: Ditto.
* libc/sys/linux/intl/l10nflist.c: Ditto.
* libc/sys/linux/intl/loadinfo.h: Ditto.
* libc/sys/linux/intl/loadmsgcat.c: Ditto.
* libc/sys/linux/intl/locale.alias: Ditto.
* libc/sys/linux/intl/localealias.c: Ditto.
* libc/sys/linux/intl/ngettext.c: Ditto.
* libc/sys/linux/intl/open_catalog.c: Ditto.
* libc/sys/linux/intl/plural.c: Ditto.
* libc/sys/linux/intl/plural.y: Ditto.
* libc/sys/linux/intl/stpcpy.c: Ditto.
* libc/sys/linux/intl/textdomain.c: Ditto.
* libc/sys/linux/linuxthreads/LICENSE: Ditto.
* libc/sys/linux/linuxthreads/Makefile.am: Ditto.
* libc/sys/linux/linuxthreads/Makefile.in: Ditto.
* libc/sys/linux/linuxthreads/aclocal.m4: Ditto.
* libc/sys/linux/linuxthreads/attr.c: Ditto.
* libc/sys/linux/linuxthreads/barrier.c: Ditto.
* libc/sys/linux/linuxthreads/bp-sym.h: Ditto.
* libc/sys/linux/linuxthreads/cancel.c: Ditto.
* libc/sys/linux/linuxthreads/condvar.c: Ditto.
* libc/sys/linux/linuxthreads/config.h: Ditto.
* libc/sys/linux/linuxthreads/configure: Ditto.
* libc/sys/linux/linuxthreads/configure.in: Ditto.
* libc/sys/linux/linuxthreads/defs.awk: Ditto.
* libc/sys/linux/linuxthreads/ecmutex.c: Ditto.
* libc/sys/linux/linuxthreads/events.c: Ditto.
* libc/sys/linux/linuxthreads/getcpuclockid.c: Ditto.
* libc/sys/linux/linuxthreads/getreent.c: Ditto.
* libc/sys/linux/linuxthreads/internals.h: Ditto.
* libc/sys/linux/linuxthreads/join.c: Ditto.
* libc/sys/linux/linuxthreads/joinrace.c: Ditto.
* libc/sys/linux/linuxthreads/kernel-features.h: Ditto.
* libc/sys/linux/linuxthreads/libc-internal.h: Ditto.
* libc/sys/linux/linuxthreads/libc-symbols.h: Ditto.
* libc/sys/linux/linuxthreads/linuxthreads.texi: Ditto.
* libc/sys/linux/linuxthreads/lockfile.c: Ditto.
* libc/sys/linux/linuxthreads/manager.c: Ditto.
* libc/sys/linux/linuxthreads/mq_notify.c: Ditto.
* libc/sys/linux/linuxthreads/mutex.c: Ditto.
* libc/sys/linux/linuxthreads/no-tsd.c: Ditto.
* libc/sys/linux/linuxthreads/oldsemaphore.c: Ditto.
* libc/sys/linux/linuxthreads/posix-timer.h: Ditto.
* libc/sys/linux/linuxthreads/prio.c: Ditto.
* libc/sys/linux/linuxthreads/proc_service.h: Ditto.
* libc/sys/linux/linuxthreads/pt-machine.c: Ditto.
* libc/sys/linux/linuxthreads/ptclock_gettime.c: Ditto.
* libc/sys/linux/linuxthreads/ptclock_settime.c: Ditto.
* libc/sys/linux/linuxthreads/ptfork.c: Ditto.
* libc/sys/linux/linuxthreads/pthread.c: Ditto.
* libc/sys/linux/linuxthreads/ptlongjmp.c: Ditto.
* libc/sys/linux/linuxthreads/queue.h: Ditto.
* libc/sys/linux/linuxthreads/reent.c: Ditto.
* libc/sys/linux/linuxthreads/reqsyscalls.c: Ditto.
* libc/sys/linux/linuxthreads/restart.h: Ditto.
* libc/sys/linux/linuxthreads/rwlock.c: Ditto.
* libc/sys/linux/linuxthreads/semaphore.c: Ditto.
* libc/sys/linux/linuxthreads/semaphore.h: Ditto.
* libc/sys/linux/linuxthreads/shlib-compat.h: Ditto.
* libc/sys/linux/linuxthreads/signals.c: Ditto.
* libc/sys/linux/linuxthreads/specific.c: Ditto.
* libc/sys/linux/linuxthreads/spinlock.c: Ditto.
* libc/sys/linux/linuxthreads/spinlock.h: Ditto.
* libc/sys/linux/linuxthreads/sysctl.c: Ditto.
* libc/sys/linux/linuxthreads/td_init.c: Ditto.
* libc/sys/linux/linuxthreads/td_log.c: Ditto.
* libc/sys/linux/linuxthreads/td_symbol_list.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_clear_event.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_delete.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_enable_stats.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_event_addr.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_event_getmsg.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_get_nthreads.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_get_ph.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_get_stats.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_map_id2thr.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_map_lwp2thr.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_new.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_reset_stats.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_set_event.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_setconcurrency.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_thr_iter.c: Ditto.
* libc/sys/linux/linuxthreads/td_ta_tsd_iter.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_clear_event.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_dbresume.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_dbsuspend.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_event_enable.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_event_getmsg.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_get_info.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_getfpregs.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_getgregs.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_getxregs.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_getxregsize.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_set_event.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_setfpregs.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_setgregs.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_setprio.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_setsigpending.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_setxregs.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_sigsetmask.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_tsd.c: Ditto.
* libc/sys/linux/linuxthreads/td_thr_validate.c: Ditto.
* libc/sys/linux/linuxthreads/testrtsig.h: Ditto.
* libc/sys/linux/linuxthreads/thread_db.h: Ditto.
* libc/sys/linux/linuxthreads/thread_dbP.h: Ditto.
* libc/sys/linux/linuxthreads/timer_create.c: Ditto.
* libc/sys/linux/linuxthreads/timer_delete.c: Ditto.
* libc/sys/linux/linuxthreads/timer_getoverr.c: Ditto.
* libc/sys/linux/linuxthreads/timer_gettime.c: Ditto.
* libc/sys/linux/linuxthreads/timer_routines.c: Ditto.
* libc/sys/linux/linuxthreads/timer_settime.c: Ditto.
* libc/sys/linux/linuxthreads/tst-cancel.c: Ditto.
* libc/sys/linux/linuxthreads/tst-context.c: Ditto.
* libc/sys/linux/linuxthreads/tststack.c: Ditto.
* libc/sys/linux/linuxthreads/unload.c: Ditto.
* libc/sys/linux/linuxthreads/weaks.c: Ditto.
* libc/sys/linux/linuxthreads/wrapsyscall.c: Ditto.
* libc/sys/linux/linuxthreads/bits/initspin.h: Ditto.
* libc/sys/linux/linuxthreads/bits/libc-lock.h: Ditto.
* libc/sys/linux/linuxthreads/bits/libc-tsd.h: Ditto.
* libc/sys/linux/linuxthreads/bits/local_lim.h: Ditto.
* libc/sys/linux/linuxthreads/bits/posix_opt.h: Ditto.
* libc/sys/linux/linuxthreads/bits/pthreadtypes.h: Ditto.
* libc/sys/linux/linuxthreads/bits/sigthread.h: Ditto.
* libc/sys/linux/linuxthreads/machine/Makefile.am: Ditto.
* libc/sys/linux/linuxthreads/machine/Makefile.in: Ditto.
* libc/sys/linux/linuxthreads/machine/aclocal.m4: Ditto.
* libc/sys/linux/linuxthreads/machine/configure: Ditto.
* libc/sys/linux/linuxthreads/machine/configure.in: Ditto.
* libc/sys/linux/linuxthreads/machine/generic/generic-sysd: Ditto.ep.h
* libc/sys/linux/linuxthreads/machine/i386/Makefile.am: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/Makefile.in: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/aclocal.m4: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/bp-asm.h: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/clone.S: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/configure: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/configure.in: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.S: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.h: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/pspinlock.c: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/pt-machine.h: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/sigcontextinfo.h: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/stackinfo.h: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/sysdep.S: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/sysdep.h: Ditto.
* libc/sys/linux/linuxthreads/machine/i386/useldt.h: Ditto.
* libc/sys/linux/machine/i386/dl-machine.h: Ditto.
* libc/sys/linux/net/Makefile.am: Ditto.
* libc/sys/linux/net/Makefile.in: Ditto.
* libc/sys/linux/net/addr2ascii.3: Ditto.
* libc/sys/linux/net/addr2ascii.c: Ditto.
* libc/sys/linux/net/ascii2addr.c: Ditto.
* libc/sys/linux/net/base64.c: Ditto.
* libc/sys/linux/net/bindresvport.c: Ditto.
* libc/sys/linux/net/byteorder.3: Ditto.
* libc/sys/linux/net/ether_addr.c: Ditto.
* libc/sys/linux/net/ethers.3: Ditto.
* libc/sys/linux/net/getaddrinfo.3: Ditto.
* libc/sys/linux/net/getaddrinfo.c: Ditto.
* libc/sys/linux/net/gethostbydns.c: Ditto.
* libc/sys/linux/net/gethostbyht.c: Ditto.
* libc/sys/linux/net/gethostbyname.3: Ditto.
* libc/sys/linux/net/gethostbynis.c: Ditto.
* libc/sys/linux/net/gethostnamadr.c: Ditto.
* libc/sys/linux/net/getifaddrs.3: Ditto.
* libc/sys/linux/net/getifaddrs.c: Ditto.
* libc/sys/linux/net/getipnodebyname.3: Ditto.
* libc/sys/linux/net/getnameinfo.3: Ditto.
* libc/sys/linux/net/getnameinfo.c: Ditto.
* libc/sys/linux/net/getnetbydns.c: Ditto.
* libc/sys/linux/net/getnetbyht.c: Ditto.
* libc/sys/linux/net/getnetbynis.c: Ditto.
* libc/sys/linux/net/getnetent.3: Ditto.
* libc/sys/linux/net/getnetnamadr.c: Ditto.
* libc/sys/linux/net/getproto.c: Ditto.
* libc/sys/linux/net/getprotoent.3: Ditto.
* libc/sys/linux/net/getprotoent.c: Ditto.
* libc/sys/linux/net/getprotoname.c: Ditto.
* libc/sys/linux/net/getservbyname.c: Ditto.
* libc/sys/linux/net/getservbyport.c: Ditto.
* libc/sys/linux/net/getservent.3: Ditto.
* libc/sys/linux/net/getservent.c: Ditto.
* libc/sys/linux/net/herror.c: Ditto.
* libc/sys/linux/net/hesiod.3: Ditto.
* libc/sys/linux/net/hesiod.c: Ditto.
* libc/sys/linux/net/if_indextoname.3: Ditto.
* libc/sys/linux/net/ifname.c: Ditto.
* libc/sys/linux/net/inet.3: Ditto.
* libc/sys/linux/net/inet6_option_s: Ditto.pace.3
* libc/sys/linux/net/inet6_rthdr_space.3: Ditto.
* libc/sys/linux/net/inet_addr.c: Ditto.
* libc/sys/linux/net/inet_lnaof.c: Ditto.
* libc/sys/linux/net/inet_makeaddr.c: Ditto.
* libc/sys/linux/net/inet_net.3: Ditto.
* libc/sys/linux/net/inet_net_ntop.c: Ditto.
* libc/sys/linux/net/inet_net_pton.c: Ditto.
* libc/sys/linux/net/inet_neta.c: Ditto.
* libc/sys/linux/net/inet_netof.c: Ditto.
* libc/sys/linux/net/inet_network.c: Ditto.
* libc/sys/linux/net/inet_ntoa.c: Ditto.
* libc/sys/linux/net/inet_ntop.c: Ditto.
* libc/sys/linux/net/inet_pton.c: Ditto.
* libc/sys/linux/net/innetgr-stub.c: Ditto.
* libc/sys/linux/net/ip6opt.c: Ditto.
* libc/sys/linux/net/iso_addr.3: Ditto.
* libc/sys/linux/net/iso_addr.c: Ditto.
* libc/sys/linux/net/issetugid-stub.c: Ditto.
* libc/sys/linux/net/linkaddr.3: Ditto.
* libc/sys/linux/net/linkaddr.c: Ditto.
* libc/sys/linux/net/map_v4v6.c: Ditto.
* libc/sys/linux/net/name6.c: Ditto.
* libc/sys/linux/net/namespace.h: Ditto.
* libc/sys/linux/net/ns.3: Ditto.
* libc/sys/linux/net/ns_addr.c: Ditto.
* libc/sys/linux/net/ns_name.c: Ditto.
* libc/sys/linux/net/ns_netint.c: Ditto.
* libc/sys/linux/net/ns_ntoa.c: Ditto.
* libc/sys/linux/net/ns_parse.c: Ditto.
* libc/sys/linux/net/ns_print.c: Ditto.
* libc/sys/linux/net/ns_ttl.c: Ditto.
* libc/sys/linux/net/nsap_addr.c: Ditto.
* libc/sys/linux/net/nsdispatch.3: Ditto.
* libc/sys/linux/net/nsdispatch.c: Ditto.
* libc/sys/linux/net/nslexer.c: Ditto.
* libc/sys/linux/net/nslexer.l: Ditto.
* libc/sys/linux/net/nsparser.c: Ditto.
* libc/sys/linux/net/nsparser.h: Ditto.
* libc/sys/linux/net/nsparser.y: Ditto.
* libc/sys/linux/net/rcmd.3: Ditto.
* libc/sys/linux/net/rcmd.c: Ditto.
* libc/sys/linux/net/rcmdsh.3: Ditto.
* libc/sys/linux/net/rcmdsh.c: Ditto.
* libc/sys/linux/net/recv.c: Ditto.
* libc/sys/linux/net/res_comp.c: Ditto.
* libc/sys/linux/net/res_config.h: Ditto.
* libc/sys/linux/net/res_data.c: Ditto.
* libc/sys/linux/net/res_debug.c: Ditto.
* libc/sys/linux/net/res_init.c: Ditto.
* libc/sys/linux/net/res_mkquery.c: Ditto.
* libc/sys/linux/net/res_mkupdate.c: Ditto.
* libc/sys/linux/net/res_query.c: Ditto.
* libc/sys/linux/net/res_send.c: Ditto.
* libc/sys/linux/net/res_update.c: Ditto.
* libc/sys/linux/net/resolver.3: Ditto.
* libc/sys/linux/net/rthdr.c: Ditto.
* libc/sys/linux/net/send.c: Ditto.
* libc/sys/linux/net/un-namespace.h: Ditto.
* libc/sys/linux/net/vars.c: Ditto.
* libc/sys/linux/stdlib/COPYRIGHT: Ditto.
* libc/sys/linux/stdlib/Makefile.am: Ditto.
* libc/sys/linux/stdlib/Makefile.in: Ditto.
* libc/sys/linux/stdlib/cclass.h: Ditto.
* libc/sys/linux/stdlib/cname.h: Ditto.
* libc/sys/linux/stdlib/collate.c: Ditto.
* libc/sys/linux/stdlib/collate.h: Ditto.
* libc/sys/linux/stdlib/collcmp.c: Ditto.
* libc/sys/linux/stdlib/engine.c: Ditto.
* libc/sys/linux/stdlib/fnmatch.3: Ditto.
* libc/sys/linux/stdlib/fnmatch.c: Ditto.
* libc/sys/linux/stdlib/glob.3: Ditto.
* libc/sys/linux/stdlib/glob.c: Ditto.
* libc/sys/linux/stdlib/reallocf.c: Ditto.
* libc/sys/linux/stdlib/regcomp.c: Ditto.
* libc/sys/linux/stdlib/regerror.c: Ditto.
* libc/sys/linux/stdlib/regex.3: Ditto.
* libc/sys/linux/stdlib/regex2.h: Ditto.
* libc/sys/linux/stdlib/regexec.c: Ditto.
* libc/sys/linux/stdlib/regfree.c: Ditto.
* libc/sys/linux/stdlib/utils.h: Ditto.
* libc/sys/linux/stdlib/wordexp.c: Ditto.
* libc/sys/linux/stdlib/wordfree.c: Ditto.
* libc/sys/linux/sys/dlfcn.h: Ditto.
* libc/sys/linux/sys/elfclass.h: Ditto.
* libc/sys/linux/sys/event.h: Ditto.
* libc/sys/linux/sys/ioccom.h: Ditto.
* libc/sys/linux/sys/libc-tsd.h: Ditto.
* libc/sys/linux/sys/link.h: Ditto.
* libc/sys/linux/sys/lock.h: Ditto.
* libc/sys/linux/sys/param.h: Ditto.
* libc/sys/linux/sys/socket.h: Ditto.
* libc/sys/linux/sys/sockio.h: Ditto.
2003-05-28 Dhananjay Deshpande <dhananjayd@kpitcummins.com>
* newlib/libc/machine/h8300/memcpy.S: Use .h8300hn and .h8300sn for

6
newlib/configure vendored
View File

@ -3090,6 +3090,12 @@ else
fi
EXTRA_DIRS=
case $host in
i345686-pc-linux-*)
configdirs="${configdirs} iconvdata"
EXTRA_DIRS=iconvdata
;;
esac
# These get added in the top-level configure.in, except in the case where

View File

@ -51,6 +51,12 @@ fi
AM_CONDITIONAL(HAVE_DOC, test x$have_doc = xyes)
EXTRA_DIRS=
case $host in
i[3456]86-pc-linux-*)
configdirs="${configdirs} iconvdata"
EXTRA_DIRS=iconvdata
;;
esac
AC_SUBST(EXTRA_DIRS)
# These get added in the top-level configure.in, except in the case where

View File

@ -0,0 +1,2 @@
0x5C 0x00A5
0x7E 0x203E

View File

@ -0,0 +1,25 @@
## Process this file with automake to generate Makefile.in
AUTOMAKE_OPTIONS = cygnus
INCLUDES = -I$(srcdir) -I$(srcdir)/../libc/sys/linux $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
if ELIX_LEVEL_1
LIB_OBJS =
else
LIB_OBJS = euc-jp.$(oext) jis0201.$(oext) jis0208.$(oext) jis0212.$(oext)
endif
AM_CFLAGS = -DNDEBUG
all: Makefile
pkglib_LTLIBRARIES = EUC-JP.la
EUC_JP_la_SOURCES = dummy.c
EUC_JP_la_LIBADD = $(LIB_OBJS)
EUC_JP_la_DEPENDENCIES = $(LIB_OBJS)
EUC_JP_la_LDFLAGS = -module -no-undefined -Xcompiler -Wl,-rpath-link=.. -Xcompiler -nostdlib -L.. -lc
install-data-local: install-pkglibLTLIBRARIES $(srcdir)/gconv-modules
$(INSTALL_DATA) $(srcdir)/gconv-modules $(DESTDIR)$(pkglibdir)/gconv-modules

View File

@ -0,0 +1,389 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_alias = @build_alias@
build_triplet = @build@
host_alias = @host_alias@
host_triplet = @host@
target_alias = @target_alias@
target_triplet = @target@
AR = @AR@
AS = @AS@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
LDFLAGS = @LDFLAGS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
VERSION = @VERSION@
aext = @aext@
libm_machine_dir = @libm_machine_dir@
machine_dir = @machine_dir@
newlib_basedir = @newlib_basedir@
oext = @oext@
sys_dir = @sys_dir@
AUTOMAKE_OPTIONS = cygnus
INCLUDES = -I$(srcdir) -I$(srcdir)/../libc/sys/linux $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
@ELIX_LEVEL_1_TRUE@LIB_OBJS =
@ELIX_LEVEL_1_FALSE@LIB_OBJS = @ELIX_LEVEL_1_FALSE@euc-jp.$(oext) jis0201.$(oext) jis0208.$(oext) jis0212.$(oext)
AM_CFLAGS = -DNDEBUG
pkglib_LTLIBRARIES = EUC-JP.la
EUC_JP_la_SOURCES = dummy.c
EUC_JP_la_LIBADD = $(LIB_OBJS)
EUC_JP_la_DEPENDENCIES = $(LIB_OBJS)
EUC_JP_la_LDFLAGS = -module -no-undefined -Xcompiler -Wl,-rpath-link=.. -Xcompiler -nostdlib -L.. -lc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(pkglib_LTLIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
EUC_JP_la_OBJECTS = dummy.lo
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in aclocal.m4 configure configure.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
SOURCES = $(EUC_JP_la_SOURCES)
OBJECTS = $(EUC_JP_la_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .lo .o .obj .s
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
mostlyclean-pkglibLTLIBRARIES:
clean-pkglibLTLIBRARIES:
-test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
distclean-pkglibLTLIBRARIES:
maintainer-clean-pkglibLTLIBRARIES:
install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
@list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(pkglibdir)/$$p; \
else :; fi; \
done
uninstall-pkglibLTLIBRARIES:
@$(NORMAL_UNINSTALL)
list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(pkglibdir)/$$p; \
done
.c.o:
$(COMPILE) -c $<
# FIXME: We should only use cygpath when building on Windows,
# and only if it is available.
.c.obj:
$(COMPILE) -c `cygpath -w $<`
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
-rm -f *.$(OBJEXT)
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
.c.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
maintainer-clean-libtool:
EUC-JP.la: $(EUC_JP_la_OBJECTS) $(EUC_JP_la_DEPENDENCIES)
$(LINK) -rpath $(pkglibdir) $(EUC_JP_la_LDFLAGS) $(EUC_JP_la_OBJECTS) $(EUC_JP_la_LIBADD) $(LIBS)
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am:
check: check-am
installcheck-am:
installcheck: installcheck-am
install-info-am:
install-info: install-info-am
install-exec-am: install-pkglibLTLIBRARIES
install-exec: install-exec-am
install-data-am: install-data-local
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-pkglibLTLIBRARIES
uninstall: uninstall-am
all-am: Makefile $(LTLIBRARIES)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-pkglibLTLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-tags \
mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-pkglibLTLIBRARIES clean-compile clean-libtool \
clean-tags clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-pkglibLTLIBRARIES distclean-compile \
distclean-libtool distclean-tags distclean-generic \
clean-am
-rm -f libtool
distclean: distclean-am
-rm -f config.status
maintainer-clean-am: maintainer-clean-pkglibLTLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
-rm -f config.status
.PHONY: mostlyclean-pkglibLTLIBRARIES distclean-pkglibLTLIBRARIES \
clean-pkglibLTLIBRARIES maintainer-clean-pkglibLTLIBRARIES \
uninstall-pkglibLTLIBRARIES install-pkglibLTLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-info-am \
install-info install-exec-am install-exec install-data-local \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
all: Makefile
install-data-local: install-pkglibLTLIBRARIES $(srcdir)/gconv-modules
$(INSTALL_DATA) $(srcdir)/gconv-modules $(DESTDIR)$(pkglibdir)/gconv-modules
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,5 @@
0x5C 0x005C
0x7E 0x007E
0x8191 0xFFE0
0x8192 0xFFE1
0x81CA 0xFFE2

1181
newlib/iconvdata/aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

3291
newlib/iconvdata/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
dnl This is the newlib/iconvdata configure.in file.
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.5)
AC_INIT(jis0201.c)
dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake.
AC_CONFIG_AUX_DIR(../..)
NEWLIB_CONFIGURE(..)
dnl We have to enable libtool after NEWLIB_CONFIGURE because if we try and
dnl add it into NEWLIB_CONFIGURE, executable tests are made before the first
dnl line of the macro which fail because appropriate LDFLAGS are not set.
if test "${use_libtool}" = "yes"; then
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
fi
AC_OUTPUT(Makefile)

1
newlib/iconvdata/dummy.c Normal file
View File

@ -0,0 +1 @@
/* empty file to force proper Makefile creation */

246
newlib/iconvdata/euc-jp.c Normal file
View File

@ -0,0 +1,246 @@
/* Mapping tables for EUC-JP handling.
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <dlfcn.h>
#include <stdint.h>
#include <gconv.h>
#include <jis0201.h>
#include <jis0208.h>
#include <jis0212.h>
/* Definitions used in the body of the `gconv' function. */
#define CHARSET_NAME "EUC-JP//"
#define FROM_LOOP from_euc_jp
#define TO_LOOP to_euc_jp
#define DEFINE_INIT 1
#define DEFINE_FINI 1
#define MIN_NEEDED_FROM 1
#define MAX_NEEDED_FROM 3
#define MIN_NEEDED_TO 4
/* First define the conversion function from EUC-JP to UCS4. */
#define MIN_NEEDED_INPUT MIN_NEEDED_FROM
#define MAX_NEEDED_INPUT MAX_NEEDED_FROM
#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO
#define LOOPFCT FROM_LOOP
#define BODY \
{ \
uint32_t ch = *inptr; \
\
if (ch < 0x8e || (ch >= 0x90 && ch <= 0x9f)) \
++inptr; \
else if (ch == 0xff) \
{ \
/* This is illegal. */ \
if (! ignore_errors_p ()) \
{ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
\
++inptr; \
++*irreversible; \
continue; \
} \
else \
{ \
/* Two or more byte character. First test whether the next \
character is also available. */ \
int ch2; \
\
if (__builtin_expect (inptr + 1 >= inend, 0)) \
{ \
/* The second character is not available. Store the \
intermediate result. */ \
result = __GCONV_INCOMPLETE_INPUT; \
break; \
} \
\
ch2 = inptr[1]; \
\
/* All second bytes of a multibyte character must be >= 0xa1. */ \
if (__builtin_expect (ch2 < 0xa1, 0)) \
{ \
/* This is an illegal character. */ \
if (! ignore_errors_p ()) \
{ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
\
++inptr; \
++*irreversible; \
continue; \
} \
\
if (ch == 0x8e) \
{ \
/* This is code set 2: half-width katakana. */ \
ch = jisx0201_to_ucs4 (ch2); \
if (__builtin_expect (ch, 0) == __UNKNOWN_10646_CHAR) \
{ \
/* Illegal character. */ \
if (! ignore_errors_p ()) \
{ \
/* This is an illegal character. */ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
} \
\
inptr += 2; \
} \
else \
{ \
const unsigned char *endp; \
\
if (ch == 0x8f) \
{ \
/* This is code set 3: JIS X 0212-1990. */ \
endp = inptr + 1; \
\
ch = jisx0212_to_ucs4 (&endp, inend - endp, 0x80); \
} \
else \
{ \
/* This is code set 1: JIS X 0208. */ \
endp = inptr; \
\
ch = jisx0208_to_ucs4 (&endp, inend - inptr, 0x80); \
} \
\
if (__builtin_expect (ch, 1) == 0) \
{ \
/* Not enough input available. */ \
result = __GCONV_INCOMPLETE_INPUT; \
break; \
} \
if (__builtin_expect (ch, 0) == __UNKNOWN_10646_CHAR) \
{ \
/* Illegal character. */ \
if (! ignore_errors_p ()) \
{ \
/* This is an illegal character. */ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
\
inptr += 2; \
++*irreversible; \
continue; \
} \
inptr = endp; \
} \
} \
\
put32 (outptr, ch); \
outptr += 4; \
}
#define LOOP_NEED_FLAGS
#include <iconv/loop.c>
/* Next, define the other direction. */
#define MIN_NEEDED_INPUT MIN_NEEDED_TO
#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM
#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM
#define LOOPFCT TO_LOOP
#define BODY \
{ \
uint32_t ch = get32 (inptr); \
\
if (ch < 0x8e || (ch >= 0x90 && ch <= 0x9f)) \
/* It's plain ASCII or C1. */ \
*outptr++ = ch; \
else if (ch == 0xa5) \
/* YEN sign => backslash */ \
*outptr++ = 0x5c; \
else if (ch == 0x203e) \
/* overscore => asciitilde */ \
*outptr++ = 0x7e; \
else \
{ \
/* Try the JIS character sets. */ \
size_t found; \
\
/* See whether we have room for at least two characters. */ \
if (__builtin_expect (outptr + 1 >= outend, 0)) \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
\
found = ucs4_to_jisx0201 (ch, outptr + 1); \
if (found != __UNKNOWN_10646_CHAR) \
{ \
/* Yes, it's a JIS 0201 character. Store the shift byte. */ \
*outptr = 0x8e; \
outptr += 2; \
} \
else \
{ \
/* No JIS 0201 character. */ \
found = ucs4_to_jisx0208 (ch, outptr, 2); \
/* Please note that we always have enough room for the output. */ \
if (found != __UNKNOWN_10646_CHAR) \
{ \
/* It's a JIS 0208 character, adjust it for EUC-JP. */ \
*outptr++ += 0x80; \
*outptr++ += 0x80; \
} \
else \
{ \
/* No JIS 0208 character. */ \
found = ucs4_to_jisx0212 (ch, outptr + 1, \
outend - outptr - 1); \
\
if (__builtin_expect (found, 1) == 0) \
{ \
/* We ran out of space. */ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
else if (__builtin_expect (found, 0) != __UNKNOWN_10646_CHAR) \
{ \
/* It's a JIS 0212 character, adjust it for EUC-JP. */ \
*outptr++ = 0x8f; \
*outptr++ += 0x80; \
*outptr++ += 0x80; \
} \
else \
{ \
UNICODE_TAG_HANDLER (ch, 4); \
\
/* Illegal character. */ \
STANDARD_ERR_HANDLER (4); \
} \
} \
} \
} \
\
inptr += 4; \
}
#define LOOP_NEED_FLAGS
#include <iconv/loop.c>
/* Now define the toplevel functions. */
#include <iconv/skeleton.c>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
/* Mapping tables for JIS0201 handling.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stdint.h>
const uint32_t __jisx0201_to_ucs4[256] =
{
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x00a5, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x203e, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67,
0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77,
0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f,
0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87,
0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f,
0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97,
0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};

View File

@ -0,0 +1,60 @@
/* Access functions for JISX0201 conversion.
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _JIS0201_H
#define _JIS0201_H 1
/* Conversion table. */
extern const uint32_t __jisx0201_to_ucs4[];
static inline uint32_t
jisx0201_to_ucs4 (char ch)
{
uint32_t val = __jisx0201_to_ucs4[(unsigned char) ch];
if (val == 0 && ch != '\0')
val = __UNKNOWN_10646_CHAR;
return val;
}
static inline size_t
ucs4_to_jisx0201 (uint32_t wch, char *s)
{
char ch;
if (wch == 0xa5)
ch = '\x5c';
else if (wch == 0x203e)
ch = '\x7e';
else if (wch < 0x7e && wch != 0x5c)
ch = wch;
else if (wch >= 0xff61 && wch <= 0xff9f)
ch = wch - 0xfec0;
else
return __UNKNOWN_10646_CHAR;
s[0] = ch;
return 1;
}
#endif /* jis0201.h */

5012
newlib/iconvdata/jis0208.c Normal file

File diff suppressed because it is too large Load Diff

108
newlib/iconvdata/jis0208.h Normal file
View File

@ -0,0 +1,108 @@
/* Access functions for JISX0208 conversion.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _JIS0208_H
#define _JIS0208_H 1
#include <gconv.h>
#include <stdint.h>
/* Conversion table. */
extern const uint16_t __jis0208_to_ucs[];
extern const char __jisx0208_from_ucs4_lat1[256][2];
extern const char __jisx0208_from_ucs4_greek[0xc1][2];
extern const struct jisx0208_ucs_idx __jisx0208_from_ucs_idx[];
extern const char __jisx0208_from_ucs_tab[][2];
/* Struct for table with indeces in UCS mapping table. */
struct jisx0208_ucs_idx
{
uint16_t start;
uint16_t end;
uint16_t idx;
};
static inline uint32_t
jisx0208_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
{
unsigned char ch = *(*s);
unsigned char ch2;
int idx;
if (ch < offset || (ch - offset) <= 0x20)
return __UNKNOWN_10646_CHAR;
if (avail < 2)
return 0;
ch2 = (*s)[1];
if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
return __UNKNOWN_10646_CHAR;
idx = (ch - 0x21 - offset) * 94 + (ch2 - 0x21 - offset);
if (idx >= 0x1e80)
return __UNKNOWN_10646_CHAR;
(*s) += 2;
return __jis0208_to_ucs[idx] ?: ((*s) -= 2, __UNKNOWN_10646_CHAR);
}
static inline size_t
ucs4_to_jisx0208 (uint32_t wch, char *s, size_t avail)
{
unsigned int ch = (unsigned int) wch;
const char *cp;
if (avail < 2)
return 0;
if (ch < 0x100)
cp = __jisx0208_from_ucs4_lat1[ch];
else if (ch >= 0x391 && ch <= 0x451)
cp = __jisx0208_from_ucs4_greek[ch - 0x391];
else
{
const struct jisx0208_ucs_idx *rp = __jisx0208_from_ucs_idx;
if (ch >= 0xffff)
return __UNKNOWN_10646_CHAR;
while (ch > rp->end)
++rp;
if (ch >= rp->start)
cp = __jisx0208_from_ucs_tab[rp->idx + ch - rp->start];
else
return __UNKNOWN_10646_CHAR;
}
if (cp[0] == '\0')
return __UNKNOWN_10646_CHAR;
s[0] = cp[0];
s[1] = cp[1];
return 2;
}
#endif /* jis0208.h */

3940
newlib/iconvdata/jis0212.c Normal file

File diff suppressed because it is too large Load Diff

110
newlib/iconvdata/jis0212.h Normal file
View File

@ -0,0 +1,110 @@
/* Access functions for JISX0212 conversion.
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _JIS0212_H
#define _JIS0212_H 1
#include <gconv.h>
#include <stdint.h>
/* Struct for table with indeces in mapping table. */
struct jisx0212_idx
{
uint16_t start;
uint16_t end;
uint16_t idx;
};
/* Conversion table. */
extern const struct jisx0212_idx __jisx0212_to_ucs_idx[];
extern const uint16_t __jisx0212_to_ucs[];
extern const struct jisx0212_idx __jisx0212_from_ucs_idx[];
extern const char __jisx0212_from_ucs[][2];
static inline uint32_t
jisx0212_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
{
const struct jisx0212_idx *rp = __jisx0212_to_ucs_idx;
unsigned char ch = *(*s);
unsigned char ch2;
uint32_t wch = 0;
int idx;
if (ch < offset || (ch - offset) < 0x22 || (ch - offset) > 0x6d)
return __UNKNOWN_10646_CHAR;
if (avail < 2)
return 0;
ch2 = (*s)[1];
if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
return __UNKNOWN_10646_CHAR;
idx = (ch - offset - 0x21) * 94 + (ch2 - offset - 0x21);
while (idx > rp->end)
++rp;
if (idx >= rp->start)
wch = __jisx0212_to_ucs[rp->idx + idx - rp->start];
if (wch != L'\0')
(*s) += 2;
else
wch = __UNKNOWN_10646_CHAR;
return wch;
}
static inline size_t
ucs4_to_jisx0212 (uint32_t wch, char *s, size_t avail)
{
const struct jisx0212_idx *rp = __jisx0212_from_ucs_idx;
unsigned int ch = (unsigned int) wch;
const char *cp;
if (ch >= 0xffff)
return __UNKNOWN_10646_CHAR;
while (ch > rp->end)
++rp;
if (ch >= rp->start)
cp = __jisx0212_from_ucs[rp->idx + ch - rp->start];
else
return __UNKNOWN_10646_CHAR;
if (cp[0] == '\0')
return __UNKNOWN_10646_CHAR;
s[0] = cp[0];
if (cp[1] != '\0')
{
if (avail < 2)
return 0;
s[1] = cp[1];
}
return 2;
}
#endif /* jis0212.h */

4512
newlib/iconvdata/sjis.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
#ifndef __ERRNO_H__
#define __ERRNO_H__
#ifndef __error_t_defined
typedef int error_t;
#define __error_t_defined 1
#endif
#include <sys/errno.h>

View File

@ -169,6 +169,8 @@ liblinux_la_LDFLAGS = -Xcompiler -nostdlib
ADD_OBJS = \
malloc.$(oext) \
gethostid.$(oext) \
sethostid.$(oext) \
$(LINUX_MACH_LIB)
if USE_LIBTOOL

View File

@ -257,6 +257,8 @@ liblinux_la_LDFLAGS = -Xcompiler -nostdlib
ADD_OBJS = \
malloc.$(oext) \
gethostid.$(oext) \
sethostid.$(oext) \
$(LINUX_MACH_LIB)

View File

@ -3043,6 +3043,17 @@ fi
EXTRA_SUBDIRS=
EXTRA_SUBLIBS=
if test "${newlib_multithread}" = "yes"; then
EXTRA_CONFIG_DIRS=linuxthreads
fi
if test "x${newlib_elix_level}" = "x1"; then
EXTRA_SUBDIRS=linuxthreads net
else
EXTRA_SUBDIRS="linuxthreads net intl stdlib iconv dl"
EXTRA_SUBLIBS="net/libnet.la intl/libintl.la stdlib/libstdlib.la iconv/libiconv.la dl/libdl.la"
fi
subdirs="machine $EXTRA_CONFIG_DIRS"
@ -3161,7 +3172,7 @@ done
ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL"
trap 'rm -fr `echo "Makefile cmath/Makefile argp/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
trap 'rm -fr `echo "Makefile intl/Makefile net/Makefile stdlib/Makefile iconv/Makefile dl/Makefile cmath/Makefile argp/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
@ -3300,7 +3311,7 @@ EOF
cat >> $CONFIG_STATUS <<EOF
CONFIG_FILES=\${CONFIG_FILES-"Makefile cmath/Makefile argp/Makefile"}
CONFIG_FILES=\${CONFIG_FILES-"Makefile intl/Makefile net/Makefile stdlib/Makefile iconv/Makefile dl/Makefile cmath/Makefile argp/Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then

View File

@ -31,9 +31,20 @@ AC_SUBST(LINUX_MACH_LIB)
EXTRA_SUBDIRS=
EXTRA_SUBLIBS=
if test "${newlib_multithread}" = "yes"; then
EXTRA_CONFIG_DIRS=linuxthreads
fi
if test "x${newlib_elix_level}" = "x1"; then
EXTRA_SUBDIRS=linuxthreads net
else
EXTRA_SUBDIRS="linuxthreads net intl stdlib iconv dl"
EXTRA_SUBLIBS="net/libnet.la intl/libintl.la stdlib/libstdlib.la iconv/libiconv.la dl/libdl.la"
fi
AC_SUBST(EXTRA_SUBDIRS)
AC_SUBST(EXTRA_SUBLIBS)
AC_CONFIG_SUBDIRS(machine $EXTRA_CONFIG_DIRS)
AC_OUTPUT(Makefile cmath/Makefile argp/Makefile)
AC_OUTPUT(Makefile intl/Makefile net/Makefile stdlib/Makefile iconv/Makefile dl/Makefile cmath/Makefile argp/Makefile)

View File

@ -0,0 +1,25 @@
## Process this file with automake to generate Makefile.in
AUTOMAKE_OPTIONS = cygnus
INCLUDES = -DSHARED -D_GNU_SOURCE $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -I$(srcdir)/..
LIB_SOURCES = \
dl-addr.c dl-deps.c dl-init.c dl-load.c dl-misc.c dl-profile.c dl-runtime.c dl-version.c \
dl-close.c dl-error.c dl-iteratephdr.c dl-lookup.c dl-object.c dl-profstub.c dl-support.c \
dl-debug.c dl-fini.c dl-libc.c dl-open.c dl-reloc.c dl-sym.c dl-cache.c
AM_CFLAGS = -D_GNU_SOURCE -D__strerror_r=strerror_r
libdl_la_LDFLAGS = -Xcompiler -nostdlib
if USE_LIBTOOL
noinst_LTLIBRARIES = libdl.la
libdl_la_SOURCES = $(LIB_SOURCES)
noinst_DATA = objectlist.awk.in
else
noinst_LIBRARIES = lib.a
lib_a_SOURCES = $(LIB_SOURCES)
noinst_DATA =
endif # USE_LIBTOOL
include $(srcdir)/../../../../Makefile.shared

View File

@ -0,0 +1,379 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_alias = @build_alias@
build_triplet = @build@
host_alias = @host_alias@
host_triplet = @host@
target_alias = @target_alias@
target_triplet = @target@
AR = @AR@
AS = @AS@
AWK = @AWK@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
LDFLAGS = @LDFLAGS@
LIBTOOL = @LIBTOOL@
LINUX_MACH_LIB = @LINUX_MACH_LIB@
LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
VERSION = @VERSION@
aext = @aext@
libm_machine_dir = @libm_machine_dir@
machine_dir = @machine_dir@
newlib_basedir = @newlib_basedir@
oext = @oext@
sys_dir = @sys_dir@
AUTOMAKE_OPTIONS = cygnus
INCLUDES = -DSHARED -D_GNU_SOURCE $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -I$(srcdir)/..
LIB_SOURCES = \
dl-addr.c dl-deps.c dl-init.c dl-load.c dl-misc.c dl-profile.c dl-runtime.c dl-version.c \
dl-close.c dl-error.c dl-iteratephdr.c dl-lookup.c dl-object.c dl-profstub.c dl-support.c \
dl-debug.c dl-fini.c dl-libc.c dl-open.c dl-reloc.c dl-sym.c dl-cache.c
AM_CFLAGS = -D_GNU_SOURCE -D__strerror_r=strerror_r
libdl_la_LDFLAGS = -Xcompiler -nostdlib
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = @USE_LIBTOOL_TRUE@libdl.la
@USE_LIBTOOL_TRUE@libdl_la_SOURCES = @USE_LIBTOOL_TRUE@$(LIB_SOURCES)
@USE_LIBTOOL_TRUE@noinst_DATA = @USE_LIBTOOL_TRUE@objectlist.awk.in
@USE_LIBTOOL_FALSE@noinst_DATA =
@USE_LIBTOOL_FALSE@noinst_LIBRARIES = @USE_LIBTOOL_FALSE@lib.a
@USE_LIBTOOL_FALSE@lib_a_SOURCES = @USE_LIBTOOL_FALSE@$(LIB_SOURCES)
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
lib_a_LIBADD =
@USE_LIBTOOL_FALSE@lib_a_OBJECTS = dl-addr.$(OBJEXT) dl-deps.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-init.$(OBJEXT) dl-load.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-misc.$(OBJEXT) dl-profile.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-runtime.$(OBJEXT) dl-version.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-close.$(OBJEXT) dl-error.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-iteratephdr.$(OBJEXT) dl-lookup.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-object.$(OBJEXT) dl-profstub.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-support.$(OBJEXT) dl-debug.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-fini.$(OBJEXT) dl-libc.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-open.$(OBJEXT) dl-reloc.$(OBJEXT) \
@USE_LIBTOOL_FALSE@dl-sym.$(OBJEXT) dl-cache.$(OBJEXT)
LTLIBRARIES = $(noinst_LTLIBRARIES)
libdl_la_LIBADD =
@USE_LIBTOOL_TRUE@libdl_la_OBJECTS = dl-addr.lo dl-deps.lo dl-init.lo \
@USE_LIBTOOL_TRUE@dl-load.lo dl-misc.lo dl-profile.lo dl-runtime.lo \
@USE_LIBTOOL_TRUE@dl-version.lo dl-close.lo dl-error.lo \
@USE_LIBTOOL_TRUE@dl-iteratephdr.lo dl-lookup.lo dl-object.lo \
@USE_LIBTOOL_TRUE@dl-profstub.lo dl-support.lo dl-debug.lo dl-fini.lo \
@USE_LIBTOOL_TRUE@dl-libc.lo dl-open.lo dl-reloc.lo dl-sym.lo \
@USE_LIBTOOL_TRUE@dl-cache.lo
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DATA = $(noinst_DATA)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
SOURCES = $(lib_a_SOURCES) $(libdl_la_SOURCES)
OBJECTS = $(lib_a_OBJECTS) $(libdl_la_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .lo .o .obj .s
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(srcdir)/../../../../Makefile.shared
cd $(top_srcdir) && $(AUTOMAKE) --cygnus dl/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.c.o:
$(COMPILE) -c $<
# FIXME: We should only use cygpath when building on Windows,
# and only if it is available.
.c.obj:
$(COMPILE) -c `cygpath -w $<`
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
-rm -f *.$(OBJEXT)
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
.c.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
maintainer-clean-libtool:
lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES)
-rm -f lib.a
$(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD)
$(RANLIB) lib.a
mostlyclean-noinstLTLIBRARIES:
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
distclean-noinstLTLIBRARIES:
maintainer-clean-noinstLTLIBRARIES:
libdl.la: $(libdl_la_OBJECTS) $(libdl_la_DEPENDENCIES)
$(LINK) $(libdl_la_LDFLAGS) $(libdl_la_OBJECTS) $(libdl_la_LIBADD) $(LIBS)
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = dl
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am:
check: check-am
installcheck-am:
installcheck: installcheck-am
install-info-am:
install-info: install-info-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(DATA)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-noinstLTLIBRARIES \
mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \
clean-noinstLTLIBRARIES clean-tags clean-generic \
mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-libtool distclean-noinstLTLIBRARIES \
distclean-tags distclean-generic clean-am
-rm -f libtool
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-noinstLTLIBRARIES \
maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool mostlyclean-noinstLTLIBRARIES \
distclean-noinstLTLIBRARIES clean-noinstLTLIBRARIES \
maintainer-clean-noinstLTLIBRARIES tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
check-am installcheck-am installcheck install-info-am install-info \
install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
objectlist.awk.in: $(noinst_LTLIBRARIES)
-rm -f objectlist.awk.in
for i in `ls *.lo` ; \
do \
echo $$i `pwd`/$$i >> objectlist.awk.in ; \
done
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,4 @@
#define __ABI_TAG_OS 0
#ifndef __ABI_TAG_VERSION
# define __ABI_TAG_VERSION 2,0,0
#endif

View File

@ -0,0 +1,56 @@
/* Low-level functions for atomic operations. ix86 version, x >= 4.
Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _ATOMICITY_H
#define _ATOMICITY_H 1
static inline uint32_t
__attribute__ ((unused))
exchange_and_add (volatile uint32_t *mem, uint32_t val)
{
register uint32_t result;
__asm__ __volatile__ ("lock; xaddl %0,%1"
: "=r" (result), "=m" (*mem) : "0" (val), "1" (*mem));
return result;
}
static inline void
__attribute__ ((unused))
atomic_add (volatile uint32_t *mem, int val)
{
__asm__ __volatile__ ("lock; addl %1,%0"
: "=m" (*mem) : "ir" (val), "0" (*mem));
}
static inline char
__attribute__ ((unused))
compare_and_swap (volatile long int *p, long int oldval, long int newval)
{
char ret;
long int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (newval), "1" (*p), "a" (oldval));
return ret;
}
#endif /* atomicity.h */

View File

@ -0,0 +1,101 @@
/* Locate the shared object symbol nearest a given address.
Copyright (C) 1996-2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <dlfcn.h>
#include <stddef.h>
#include <ldsodefs.h>
int
internal_function
_dl_addr (const void *address, Dl_info *info)
{
const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address);
struct link_map *l, *match;
const ElfW(Sym) *symtab, *matchsym;
const char *strtab;
ElfW(Word) strtabsize;
/* 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_map_start && addr < l->l_map_end)
{
/* We know ADDRESS lies within L if in any shared object.
Make sure it isn't past the end of L's segments. */
size_t n = l->l_phnum;
if (n > 0)
{
do
--n;
while (l->l_phdr[n].p_type != PT_LOAD);
if (addr >= (l->l_addr +
l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz))
/* Off the end of the highest-addressed shared object. */
continue;
}
match = l;
break;
}
if (match == NULL)
return 0;
/* Now we know what object the address lies in. */
info->dli_fname = match->l_name;
info->dli_fbase = (void *) match->l_addr;
/* If this is the main program the information is incomplete. */
if (__builtin_expect (info->dli_fbase == NULL, 0))
{
info->dli_fname = _dl_argv[0];
info->dli_fbase = (void *) match->l_map_start;
}
symtab = (const void *) D_PTR (match, l_info[DT_SYMTAB]);
strtab = (const void *) D_PTR (match, l_info[DT_STRTAB]);
strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
/* 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
&& ((symtab->st_size == 0 && addr == match->l_addr + symtab->st_value)
|| addr < match->l_addr + symtab->st_value + symtab->st_size)
&& symtab->st_name < strtabsize
&& (matchsym == NULL || 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;
}

View File

@ -0,0 +1,271 @@
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sys/mman.h>
#include <dl-cache.h>
#include <machine/dl-procinfo.h>
#include <machine/weakalias.h>
extern const char *_dl_platform;
#ifndef _DL_PLATFORMS_COUNT
# define _DL_PLATFORMS_COUNT 0
#endif
/* This is the starting address and the size of the mmap()ed file. */
static struct cache_file *cache;
static struct cache_file_new *cache_new;
static size_t cachesize;
/* 1 if cache_data + PTR points into the cache. */
#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
/* This is the cache ID we expect. Normally it is 3 for glibc linked
binaries. */
int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID;
#define SEARCH_CACHE(cache) \
/* We use binary search since the table is sorted in the cache file. \
The first matching entry in the table is returned. \
It is important to use the same algorithm as used while generating \
the cache file. */ \
do \
{ \
left = 0; \
right = cache->nlibs - 1; \
\
while (left <= right) \
{ \
__typeof__ (cache->libs[0].key) key; \
\
middle = (left + right) / 2; \
\
key = cache->libs[middle].key; \
\
/* Make sure string table indices are not bogus before using \
them. */ \
if (! _dl_cache_verify_ptr (key)) \
{ \
cmpres = 1; \
break; \
} \
\
/* Actually compare the entry with the key. */ \
cmpres = _dl_cache_libcmp (name, cache_data + key); \
if (__builtin_expect (cmpres == 0, 0)) \
{ \
/* Found it. LEFT now marks the last entry for which we \
know the name is correct. */ \
left = middle; \
\
/* There might be entries with this name before the one we \
found. So we have to find the beginning. */ \
while (middle > 0) \
{ \
__typeof__ (cache->libs[0].key) key; \
\
key = cache->libs[middle - 1].key; \
/* Make sure string table indices are not bogus before \
using them. */ \
if (! _dl_cache_verify_ptr (key) \
/* Actually compare the entry. */ \
|| _dl_cache_libcmp (name, cache_data + key) != 0) \
break; \
--middle; \
} \
\
do \
{ \
int flags; \
__typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \
\
/* Only perform the name test if necessary. */ \
if (middle > left \
/* We haven't seen this string so far. Test whether the \
index is ok and whether the name matches. Otherwise \
we are done. */ \
&& (! _dl_cache_verify_ptr (lib->key) \
|| (_dl_cache_libcmp (name, cache_data + lib->key) \
!= 0))) \
break; \
\
flags = lib->flags; \
if (_dl_cache_check_flags (flags) \
&& _dl_cache_verify_ptr (lib->value)) \
{ \
if (best == NULL || flags == _dl_correct_cache_id) \
{ \
HWCAP_CHECK; \
best = cache_data + lib->value; \
\
if (flags == _dl_correct_cache_id) \
/* We've found an exact match for the shared \
object and no general `ELF' release. Stop \
searching. */ \
break; \
} \
} \
} \
while (++middle <= right); \
break; \
} \
\
if (cmpres < 0) \
left = middle + 1; \
else \
right = middle - 1; \
} \
} \
while (0)
/* Look up NAME in ld.so.cache and return the file name stored there,
or null if none is found. */
const char *
internal_function
_dl_load_cache_lookup (const char *name)
{
int left, right, middle;
int cmpres;
const char *cache_data;
uint32_t cache_data_size;
const char *best;
if (cache == NULL)
{
/* Read the contents of the file. */
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
PROT_READ);
/* We can handle three different cache file formats here:
- the old libc5/glibc2.0/2.1 format
- the old format with the new format in it
- only the new format
The following checks if the cache contains any of these formats. */
if (file != MAP_FAILED && cachesize > sizeof *cache
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
{
size_t offset;
/* Looks ok. */
cache = file;
/* Check for new version. */
offset = ALIGN_CACHE (sizeof (struct cache_file)
+ cache->nlibs * sizeof (struct file_entry));
cache_new = (struct cache_file_new *) ((void *) cache + offset);
if (cachesize < (offset + sizeof (struct cache_file_new))
|| memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
cache_new = (void *) -1;
}
else if (file != MAP_FAILED && cachesize > sizeof *cache_new
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
{
cache_new = file;
cache = file;
}
else
{
if (file != MAP_FAILED)
munmap (file, cachesize);
cache = (void *) -1;
}
assert (cache != NULL);
}
if (cache == (void *) -1)
/* Previously looked for the cache file and didn't find it. */
return NULL;
best = NULL;
if (cache_new != (void *) -1)
{
/* This file ends in static libraries where we don't have a hwcap. */
unsigned long int *hwcap;
uint64_t platform;
weak_extern (_dl_hwcap);
/* This is where the strings start. */
cache_data = (const char *) cache_new;
/* Now we can compute how large the string table is. */
cache_data_size = (const char *) cache + cachesize - cache_data;
hwcap = &_dl_hwcap;
platform = _dl_string_platform (_dl_platform);
if (platform != -1)
platform = 1ULL << platform;
/* Only accept hwcap if it's for the right platform. */
#define HWCAP_CHECK \
if (_dl_osversion && cache_new->libs[middle].osversion > _dl_osversion) \
continue; \
if (_DL_PLATFORMS_COUNT && platform != -1 \
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \
continue; \
if (hwcap \
&& ((lib->hwcap & *hwcap & ~_DL_HWCAP_PLATFORM) > *hwcap)) \
continue
SEARCH_CACHE (cache_new);
}
else
{
/* This is where the strings start. */
cache_data = (const char *) &cache->libs[cache->nlibs];
/* Now we can compute how large the string table is. */
cache_data_size = (const char *) cache + cachesize - cache_data;
#undef HWCAP_CHECK
#define HWCAP_CHECK do {} while (0)
SEARCH_CACHE (cache);
}
/* Print our result if wanted. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0) && best != NULL)
_dl_debug_printf (" trying file=%s\n", best);
return best;
}
#ifndef MAP_COPY
/* If the system does not support MAP_COPY we cannot leave the file open
all the time since this would create problems when the file is replaced.
Therefore we provide this function to close the file and open it again
once needed. */
void
_dl_unload_cache (void)
{
if (cache != NULL && cache != (struct cache_file *) -1)
{
munmap (cache, cachesize);
cache = NULL;
}
}
#endif

View File

@ -0,0 +1,140 @@
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stdint.h>
#ifndef _DL_CACHE_DEFAULT_ID
# define _DL_CACHE_DEFAULT_ID 3
#endif
#ifndef _dl_cache_check_flags
# define _dl_cache_check_flags(flags) \
((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
#endif
#ifndef SYSCONFDIR
# define SYSCONFDIR "/etc"
#endif
#ifndef LD_SO_CACHE
# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
#endif
#define CACHEMAGIC "ld.so-1.7.0"
/* libc5 and glibc 2.0/2.1 use the same format. For glibc 2.2 another
format has been added in a compatible way:
The beginning of the string table is used for the new table:
old_magic
nlibs
libs[0]
...
libs[nlibs-1]
pad, new magic needs to be aligned
- this is string[0] for the old format
new magic - this is string[0] for the new format
newnlibs
...
newlibs[0]
...
newlibs[newnlibs-1]
string 1
string 2
...
*/
struct file_entry
{
int flags; /* This is 1 for an ELF library. */
unsigned int key, value; /* String table indices. */
};
struct cache_file
{
char magic[sizeof CACHEMAGIC - 1];
unsigned int nlibs;
struct file_entry libs[0];
};
#define CACHEMAGIC_NEW "glibc-ld.so.cache"
#define CACHE_VERSION "1.1"
#define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
struct file_entry_new
{
int32_t flags; /* This is 1 for an ELF library. */
uint32_t key, value; /* String table indices. */
uint32_t osversion; /* Required OS version. */
uint64_t hwcap; /* Hwcap entry. */
};
struct cache_file_new
{
char magic[sizeof CACHEMAGIC_NEW - 1];
char version[sizeof CACHE_VERSION - 1];
uint32_t nlibs; /* Number of entries. */
uint32_t len_strings; /* Size of string table. */
uint32_t unused[5]; /* Leave space for future extensions
and align to 8 byte boundary. */
struct file_entry_new libs[0]; /* Entries describing libraries. */
/* After this the string table of size len_strings is found. */
};
/* Used to align cache_file_new. */
#define ALIGN_CACHE(addr) \
(((addr) + __alignof__ (struct cache_file_new) -1) \
& (~(__alignof__ (struct cache_file_new) - 1)))
static int
_dl_cache_libcmp (const char *p1, const char *p2)
{
while (*p1 != '\0')
{
if (*p1 >= '0' && *p1 <= '9')
{
if (*p2 >= '0' && *p2 <= '9')
{
/* Must compare this numerically. */
int val1;
int val2;
val1 = *p1++ - '0';
val2 = *p2++ - '0';
while (*p1 >= '0' && *p1 <= '9')
val1 = val1 * 10 + *p1++ - '0';
while (*p2 >= '0' && *p2 <= '9')
val2 = val2 * 10 + *p2++ - '0';
if (val1 != val2)
return val1 - val2;
}
else
return 1;
}
else if (*p2 >= '0' && *p2 <= '9')
return -1;
else if (*p1 != *p2)
return *p1 - *p2;
else
{
++p1;
++p2;
}
}
return *p1 - *p2;
}

View File

@ -0,0 +1,334 @@
/* Close a shared object opened by `_dl_open'.
Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <dlfcn.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <bits/libc-lock.h>
#include <ldsodefs.h>
#include <sys/types.h>
#include <sys/mman.h>
/* Type of the constructor functions. */
typedef void (*fini_t) (void);
void
internal_function
_dl_close (void *_map)
{
struct reldep_list
{
struct link_map **rellist;
unsigned int nrellist;
struct reldep_list *next;
} *reldeps = NULL;
struct link_map **list;
struct link_map *map = _map;
unsigned int i;
unsigned int *new_opencount;
/* First see whether we can remove the object at all. */
if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
&& map->l_init_called)
/* Nope. Do nothing. */
return;
if (__builtin_expect (map->l_opencount, 1) == 0)
_dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
/* Acquire the lock. */
#ifdef HAVE_DD_LOCK
__lock_acquire(_dl_load_lock);
#endif
/* Decrement the reference count. */
if (map->l_opencount > 1 || map->l_type != lt_loaded)
{
/* There are still references to this object. Do nothing more. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
_dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
map->l_name, map->l_opencount);
/* One decrement the object itself, not the dependencies. */
--map->l_opencount;
#ifdef HAVE_DD_LOCK
__lock_release(_dl_load_lock);
#endif
return;
}
list = map->l_initfini;
/* Compute the new l_opencount values. */
i = map->l_searchlist.r_nlist;
if (__builtin_expect (i == 0, 0))
/* This can happen if we handle relocation dependencies for an
object which wasn't loaded directly. */
for (i = 1; list[i] != NULL; ++i)
;
new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));
for (i = 0; list[i] != NULL; ++i)
{
list[i]->l_idx = i;
new_opencount[i] = list[i]->l_opencount;
}
--new_opencount[0];
for (i = 1; list[i] != NULL; ++i)
if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
/* Decrement counter. */
&& --new_opencount[i] == 0
/* Test whether this object was also loaded directly. */
&& list[i]->l_searchlist.r_list != NULL)
{
/* In this case we have the decrement all the dependencies of
this object. They are all in MAP's dependency list. */
unsigned int j;
struct link_map **dep_list = list[i]->l_searchlist.r_list;
for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j)
if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
|| ! dep_list[j]->l_init_called)
{
assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
--new_opencount[dep_list[j]->l_idx];
}
}
assert (new_opencount[0] == 0);
/* Call all termination functions at once. */
for (i = 0; list[i] != NULL; ++i)
{
struct link_map *imap = list[i];
if (new_opencount[i] == 0 && imap->l_type == lt_loaded
&& (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
&& (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called)
/* Skip any half-cooked objects that were never initialized. */
&& imap->l_init_called)
{
/* When debugging print a message first. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
_dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name);
/* Call its termination function. */
if (imap->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (imap->l_addr
+ imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
unsigned int cnt;
for (cnt = 0; cnt < sz; ++cnt)
((fini_t) (imap->l_addr + array[cnt])) ();
}
/* Next try the old-style destructor. */
if (imap->l_info[DT_FINI] != NULL)
(*(void (*) (void)) DL_DT_FINI_ADDRESS
(imap, (void *) imap->l_addr
+ imap->l_info[DT_FINI]->d_un.d_ptr)) ();
}
else if (new_opencount[i] != 0 && imap->l_type == lt_loaded)
{
/* The object is still used. But the object we are unloading
right now is responsible for loading it and therefore we
have the search list of the current object in its scope.
Remove it. */
struct r_scope_elem **runp = imap->l_scope;
while (*runp != NULL)
if (*runp == &map->l_searchlist)
{
/* Copy all later elements. */
while ((runp[0] = runp[1]) != NULL)
++runp;
break;
}
else
++runp;
}
/* Store the new l_opencount value. */
imap->l_opencount = new_opencount[i];
/* Just a sanity check. */
assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
}
/* Notify the debugger we are about to remove some loaded objects. */
_r_debug.r_state = RT_DELETE;
_dl_debug_state ();
/* Check each element of the search list to see if all references to
it are gone. */
for (i = 0; list[i] != NULL; ++i)
{
struct link_map *imap = list[i];
if (imap->l_opencount == 0 && imap->l_type == lt_loaded)
{
struct libname_list *lnp;
/* That was the last reference, and this was a dlopen-loaded
object. We can unmap it. */
if (__builtin_expect (imap->l_global, 0))
{
/* This object is in the global scope list. Remove it. */
unsigned int cnt = _dl_main_searchlist->r_nlist;
do
--cnt;
while (_dl_main_searchlist->r_list[cnt] != imap);
/* The object was already correctly registered. */
while (++cnt < _dl_main_searchlist->r_nlist)
_dl_main_searchlist->r_list[cnt - 1]
= _dl_main_searchlist->r_list[cnt];
--_dl_main_searchlist->r_nlist;
}
/* We can unmap all the maps at once. We determined the
start address and length when we loaded the object and
the `munmap' call does the rest. */
DL_UNMAP (imap);
/* Finally, unlink the data structure and free it. */
#ifdef SHARED
/* We will unlink the first object only if this is a statically
linked program. */
assert (imap->l_prev != NULL);
imap->l_prev->l_next = imap->l_next;
#else
if (imap->l_prev != NULL)
imap->l_prev->l_next = imap->l_next;
else
_dl_loaded = imap->l_next;
#endif
--_dl_nloaded;
if (imap->l_next)
imap->l_next->l_prev = imap->l_prev;
if (imap->l_versions != NULL)
free (imap->l_versions);
if (imap->l_origin != NULL && imap->l_origin != (char *) -1)
free ((char *) imap->l_origin);
/* If the object has relocation dependencies save this
information for latter. */
if (__builtin_expect (imap->l_reldeps != NULL, 0))
{
struct reldep_list *newrel;
newrel = (struct reldep_list *) alloca (sizeof (*reldeps));
newrel->rellist = imap->l_reldeps;
newrel->nrellist = imap->l_reldepsact;
newrel->next = reldeps;
reldeps = newrel;
}
/* This name always is allocated. */
free (imap->l_name);
/* Remove the list with all the names of the shared object. */
lnp = imap->l_libname;
do
{
struct libname_list *this = lnp;
lnp = lnp->next;
if (!this->dont_free)
free (this);
}
while (lnp != NULL);
/* Remove the searchlists. */
if (imap != map)
free (imap->l_initfini);
/* Remove the scope array if we allocated it. */
if (imap->l_scope != imap->l_scope_mem)
free (imap->l_scope);
if (imap->l_phdr_allocated)
free ((void *) imap->l_phdr);
if (imap->l_rpath_dirs.dirs != (void *) -1)
free (imap->l_rpath_dirs.dirs);
if (imap->l_runpath_dirs.dirs != (void *) -1)
free (imap->l_runpath_dirs.dirs);
free (imap);
}
}
/* Notify the debugger those objects are finalized and gone. */
_r_debug.r_state = RT_CONSISTENT;
_dl_debug_state ();
/* Now we can perhaps also remove the modules for which we had
dependencies because of symbol lookup. */
while (__builtin_expect (reldeps != NULL, 0))
{
while (reldeps->nrellist-- > 0)
_dl_close (reldeps->rellist[reldeps->nrellist]);
free (reldeps->rellist);
reldeps = reldeps->next;
}
free (list);
/* Release the lock. */
#ifdef HAVE_DD_LOCK
__lock_release(_dl_load_lock);
#endif
}
static void
free_mem (void)
{
if (__builtin_expect (_dl_global_scope_alloc, 0) != 0
&& _dl_main_searchlist->r_nlist == _dl_initial_searchlist.r_nlist)
{
/* All object dynamically loaded by the program are unloaded. Free
the memory allocated for the global scope variable. */
struct link_map **old = _dl_main_searchlist->r_list;
/* Put the old map in. */
_dl_main_searchlist->r_list = _dl_initial_searchlist.r_list;
/* Signal that the original map is used. */
_dl_global_scope_alloc = 0;
/* Now free the old map. */
free (old);
}
}
text_set_element (__libc_subfreeres, free_mem);

View File

@ -0,0 +1,57 @@
/* Communicate dynamic linker state to the debugger at runtime.
Copyright (C) 1996, 1998, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <ldsodefs.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 *
internal_function
_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 = ldbase;
_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)
{
}

View File

@ -0,0 +1,561 @@
/* Load the dependencies of a mapped object.
Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <ldsodefs.h>
#include <dl-dst.h>
/* Whether an shared object references one or more auxiliary objects
is signaled by the AUXTAG entry in l_info. */
#define AUXTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ DT_EXTRATAGIDX (DT_AUXILIARY))
/* Whether an shared object references one or more auxiliary objects
is signaled by the AUXTAG entry in l_info. */
#define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ DT_EXTRATAGIDX (DT_FILTER))
/* This is zero at program start to signal that the global scope map is
allocated by rtld. Later it keeps the size of the map. It might be
reset if in _dl_close if the last global object is removed. */
size_t _dl_global_scope_alloc;
extern size_t _dl_platformlen;
/* When loading auxiliary objects we must ignore errors. It's ok if
an object is missing. */
struct openaux_args
{
/* The arguments to openaux. */
struct link_map *map;
int trace_mode;
const char *strtab;
const char *name;
/* The return value of openaux. */
struct link_map *aux;
};
static void
openaux (void *a)
{
struct openaux_args *args = (struct openaux_args *) a;
args->aux = _dl_map_object (args->map, args->name, 0,
(args->map->l_type == lt_executable
? lt_library : args->map->l_type),
args->trace_mode, 0);
}
/* We use a very special kind of list to track the path
through the list of loaded shared objects. We have to
produce a flat list with unique members of all involved objects.
*/
struct list
{
int done; /* Nonzero if this map was processed. */
struct link_map *map; /* The data. */
struct list *next; /* Elements for normal list. */
};
/* Macro to expand DST. It is an macro since we use `alloca'. */
#define expand_dst(l, str, fatal) \
({ \
const char *__str = (str); \
const char *__result = __str; \
size_t __cnt = DL_DST_COUNT(__str, 0); \
\
if (__cnt != 0) \
{ \
char *__newp; \
\
__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str), \
__cnt)); \
\
__result = DL_DST_SUBSTITUTE (l, __str, __newp, 0); \
\
if (*__result == '\0') \
{ \
/* The replacement for the DST is not known. We can't \
processed. */ \
if (fatal) \
_dl_signal_error (0, __str, NULL, N_("\
empty dynamics string token substitution")); \
else \
{ \
/* This is for DT_AUXILIARY. */ \
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0)) \
_dl_debug_printf ("cannot load auxiliary `%s' because of" \
"empty dynamic string token " \
"substitution\n", __str); \
continue; \
} \
} \
} \
\
__result; })
void
internal_function
_dl_map_object_deps (struct link_map *map,
struct link_map **preloads, unsigned int npreloads,
int trace_mode)
{
struct list known[1 + npreloads + 1];
struct list *runp, *tail;
unsigned int nlist, i;
/* Object name. */
const char *name;
int errno_saved;
int errno_reason;
const char *errstring;
const char *objname;
auto inline void preload (struct link_map *map);
inline void preload (struct link_map *map)
{
known[nlist].done = 0;
known[nlist].map = map;
known[nlist].next = &known[nlist + 1];
++nlist;
/* 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. */
map->l_reserved = 1;
}
/* No loaded object so far. */
nlist = 0;
/* First load MAP itself. */
preload (map);
/* Add the preloaded items after MAP but before any of its dependencies. */
for (i = 0; i < npreloads; ++i)
preload (preloads[i]);
/* Terminate the lists. */
known[nlist - 1].next = NULL;
/* Pointer to last unique object. */
tail = &known[nlist - 1];
/* Process each element of the search list, loading each of its
auxiliary objects and immediate dependencies. Auxiliary objects
will be added in the list before the object itself and
dependencies will be appended to the list as we step through it.
This produces a flat, ordered list that represents a
breadth-first search of the dependency tree.
The whole process is complicated by the fact that we better
should use alloca for the temporary list elements. But using
alloca means we cannot use recursive function calls. */
errno_saved = errno;
errno_reason = 0;
errstring = NULL;
errno = 0;
name = NULL;
for (runp = known; runp; )
{
struct link_map *l = runp->map;
struct link_map **needed = NULL;
unsigned int nneeded = 0;
/* Unless otherwise stated, this object is handled. */
runp->done = 1;
/* Allocate a temporary record to contain the references to the
dependencies of this object. */
if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
&& l != map && l->l_ldnum > 0)
needed = (struct link_map **) alloca (l->l_ldnum
* sizeof (struct link_map *));
if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
{
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
struct openaux_args args;
struct list *orig;
const ElfW(Dyn) *d;
args.strtab = strtab;
args.map = l;
args.trace_mode = trace_mode;
orig = runp;
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
{
/* Map in the needed object. */
struct link_map *dep;
int err;
/* Recognize DSTs. */
name = expand_dst (l, strtab + d->d_un.d_val, 0);
/* Store the tag in the argument structure. */
args.name = name;
err = _dl_catch_error (&objname, &errstring, openaux, &args);
if (__builtin_expect (errstring != NULL, 0))
{
if (err)
errno_reason = err;
else
errno_reason = -1;
goto out;
}
else
dep = args.aux;
if (! dep->l_reserved)
{
/* Allocate new entry. */
struct list *newp;
newp = alloca (sizeof (struct list));
/* Append DEP to the list. */
newp->map = dep;
newp->done = 0;
newp->next = NULL;
tail->next = newp;
tail = newp;
++nlist;
/* Set the mark bit that says it's already in the list. */
dep->l_reserved = 1;
}
/* Remember this dependency. */
if (needed != NULL)
needed[nneeded++] = dep;
}
else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER)
{
struct list *newp;
/* Recognize DSTs. */
name = expand_dst (l, strtab + d->d_un.d_val,
d->d_tag == DT_AUXILIARY);
/* Store the tag in the argument structure. */
args.name = name;
if (d->d_tag == DT_AUXILIARY)
{
int err;
/* Say that we are about to load an auxiliary library. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
_dl_debug_printf ("load auxiliary object=%s"
" requested by file=%s\n", name,
l->l_name[0]
? l->l_name : _dl_argv[0]);
/* We must be prepared that the addressed shared
object is not available. */
err = _dl_catch_error (&objname, &errstring, openaux,
&args);
if (__builtin_expect (errstring != NULL, 0))
{
/* We are not interested in the error message. */
assert (errstring != NULL);
if (errstring != _dl_out_of_memory)
free ((char *) errstring);
/* Simply ignore this error and continue the work. */
continue;
}
}
else
{
int err;
/* Say that we are about to load an auxiliary library. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
_dl_debug_printf ("load filtered object=%s"
" requested by file=%s\n", name,
l->l_name[0]
? l->l_name : _dl_argv[0]);
/* For filter objects the dependency must be available. */
err = _dl_catch_error (&objname, &errstring, openaux,
&args);
if (__builtin_expect (errstring != NULL, 0))
{
if (err)
errno_reason = err;
else
errno_reason = -1;
goto out;
}
}
/* The auxiliary object is actually available.
Incorporate the map in all the lists. */
/* Allocate new entry. This always has to be done. */
newp = alloca (sizeof (struct list));
/* We want to insert the new map before the current one,
but we have no back links. So we copy the contents of
the current entry over. Note that ORIG and NEWP now
have switched their meanings. */
memcpy (newp, orig, sizeof (*newp));
/* Initialize new entry. */
orig->done = 0;
orig->map = args.aux;
/* Remember this dependency. */
if (needed != NULL)
needed[nneeded++] = args.aux;
/* We must handle two situations here: the map is new,
so we must add it in all three lists. If the map
is already known, we have two further possibilities:
- if the object is before the current map in the
search list, we do nothing. It is already found
early
- if the object is after the current one, we must
move it just before the current map to make sure
the symbols are found early enough
*/
if (args.aux->l_reserved)
{
/* The object is already somewhere in the list.
Locate it first. */
struct list *late;
/* This object is already in the search list we
are building. Don't add a duplicate pointer.
Just added by _dl_map_object. */
for (late = newp; late->next != NULL; late = late->next)
if (late->next->map == args.aux)
break;
if (late->next != NULL)
{
/* The object is somewhere behind the current
position in the search path. We have to
move it to this earlier position. */
orig->next = newp;
/* Now remove the later entry from the list
and adjust the tail pointer. */
if (tail == late->next)
tail = late;
late->next = late->next->next;
/* We must move the object earlier in the chain. */
if (args.aux->l_prev != NULL)
args.aux->l_prev->l_next = args.aux->l_next;
if (args.aux->l_next != NULL)
args.aux->l_next->l_prev = args.aux->l_prev;
args.aux->l_prev = newp->map->l_prev;
newp->map->l_prev = args.aux;
if (args.aux->l_prev != NULL)
args.aux->l_prev->l_next = args.aux;
args.aux->l_next = newp->map;
}
else
{
/* The object must be somewhere earlier in the
list. Undo to the current list element what
we did above. */
memcpy (orig, newp, sizeof (*newp));
continue;
}
}
else
{
/* This is easy. We just add the symbol right here. */
orig->next = newp;
++nlist;
/* Set the mark bit that says it's already in the list. */
args.aux->l_reserved = 1;
/* The only problem is that in the double linked
list of all objects we don't have this new
object at the correct place. Correct this here. */
if (args.aux->l_prev)
args.aux->l_prev->l_next = args.aux->l_next;
if (args.aux->l_next)
args.aux->l_next->l_prev = args.aux->l_prev;
args.aux->l_prev = newp->map->l_prev;
newp->map->l_prev = args.aux;
if (args.aux->l_prev != NULL)
args.aux->l_prev->l_next = args.aux;
args.aux->l_next = newp->map;
}
/* Move the tail pointer if necessary. */
if (orig == tail)
tail = newp;
/* Move on the insert point. */
orig = newp;
}
}
/* Terminate the list of dependencies and store the array address. */
if (needed != NULL)
{
needed[nneeded++] = NULL;
l->l_initfini = (struct link_map **)
malloc ((nneeded + 1) * sizeof needed[0]);
if (l->l_initfini == NULL)
_dl_signal_error (ENOMEM, map->l_name, NULL,
N_("cannot allocate dependency list"));
l->l_initfini[0] = l;
memcpy (&l->l_initfini[1], needed, nneeded * sizeof needed[0]);
}
/* If we have no auxiliary objects just go on to the next map. */
if (runp->done)
do
runp = runp->next;
while (runp != NULL && runp->done);
}
out:
if (errno == 0 && errno_saved != 0)
__set_errno (errno_saved);
if (map->l_initfini != NULL && map->l_type == lt_loaded)
{
/* This object was previously loaded as a dependency and we have
a separate l_initfini list. We don't need it anymore. */
assert (map->l_searchlist.r_list == NULL);
free (map->l_initfini);
}
/* Store the search list we built in the object. It will be used for
searches in the scope of this object. */
map->l_initfini =
(struct link_map **) malloc ((2 * nlist + 1)
* sizeof (struct link_map *));
if (map->l_initfini == NULL)
_dl_signal_error (ENOMEM, map->l_name, NULL,
N_("cannot allocate symbol search list"));
map->l_searchlist.r_list = &map->l_initfini[nlist + 1];
map->l_searchlist.r_nlist = nlist;
for (nlist = 0, runp = known; runp; runp = runp->next)
{
if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
/* This can happen when we trace the loading. */
--map->l_searchlist.r_nlist;
else
map->l_searchlist.r_list[nlist++] = runp->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. */
runp->map->l_reserved = 0;
}
/* Maybe we can remove some relocation dependencies now. */
assert (map->l_searchlist.r_list[0] == map);
for (i = 0; i < map->l_reldepsact; ++i)
{
unsigned int j;
for (j = 1; j < nlist; ++j)
if (map->l_searchlist.r_list[j] == map->l_reldeps[i])
{
/* A direct or transitive dependency is also on the list
of relocation dependencies. Remove the latter. */
--map->l_reldeps[i]->l_opencount;
for (j = i + 1; j < map->l_reldepsact; ++j)
map->l_reldeps[j - 1] = map->l_reldeps[j];
--map->l_reldepsact;
/* Account for the '++i' performed by the 'for'. */
--i;
break;
}
}
/* Now determine the order in which the initialization has to happen. */
memcpy (map->l_initfini, map->l_searchlist.r_list,
nlist * sizeof (struct link_map *));
/* We can skip looking for the binary itself which is at the front
of the search list. Look through the list backward so that circular
dependencies are not changing the order. */
for (i = 1; i < nlist; ++i)
{
struct link_map *l = map->l_searchlist.r_list[i];
unsigned int j;
unsigned int k;
/* Find the place in the initfini list where the map is currently
located. */
for (j = 1; map->l_initfini[j] != l; ++j)
;
/* Find all object for which the current one is a dependency and
move the found object (if necessary) in front. */
for (k = j + 1; k < nlist; ++k)
{
struct link_map **runp;
runp = map->l_initfini[k]->l_initfini;
if (runp != NULL)
{
while (*runp != NULL)
if (__builtin_expect (*runp++ == l, 0))
{
struct link_map *here = map->l_initfini[k];
/* Move it now. */
memmove (&map->l_initfini[j] + 1,
&map->l_initfini[j],
(k - j) * sizeof (struct link_map *));
map->l_initfini[j] = here;
break;
}
}
}
}
/* Terminate the list of dependencies. */
map->l_initfini[nlist] = NULL;
if (errno_reason)
_dl_signal_error (errno_reason == -1 ? 0 : errno_reason,
objname, NULL, errstring);
}

View File

@ -0,0 +1,45 @@
/* Handling of dynamic sring tokens.
Copyright (C) 1999, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Determine the number of DST elements in the name. Only if IS_PATH is
nonzero paths are recognized (i.e., multiple, ':' separated filenames). */
#define DL_DST_COUNT(name, is_path) \
({ \
size_t __cnt = 0; \
const char *__sf = strchr (name, '$'); \
\
if (__builtin_expect (__sf != NULL, 0)) \
__cnt = _dl_dst_count (__sf, is_path); \
\
__cnt; })
/* Prototype for used function. */
extern size_t _dl_dst_count (const char *name, int is_path);
/* Guess from the number of DSTs the length of the result string. */
#define DL_DST_REQUIRED(l, name, len, cnt) 1024
/* Perform the DST substitution. */
#define DL_DST_SUBSTITUTE(l, name, res, is_path) \
_dl_dst_substitute (l, name, res, is_path)
/* Prototype for used function. */
extern char *_dl_dst_substitute (struct link_map *l, const char *name,
char *result, int is_path);

View File

@ -0,0 +1,189 @@
/* Error handling for runtime dynamic linker.
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <libintl.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sys/libc-tsd.h>
/* This structure communicates state between _dl_catch_error and
_dl_signal_error. */
struct catch
{
const char *objname; /* Object/File name. */
const char *errstring; /* Error detail filled in here. */
jmp_buf env; /* longjmp here on error. */
};
/* Multiple threads at once can use the `_dl_catch_error' function. The
calls can come from `_dl_map_object_deps', `_dlerror_run', or from
any of the libc functionality which loads dynamic objects (NSS, iconv).
Therefore we have to be prepared to save the state in thread-local
memory. */
__libc_tsd_define (static, DL_ERROR)
#define tsd_getspecific() __libc_tsd_get (DL_ERROR)
#define tsd_setspecific(data) __libc_tsd_set (DL_ERROR, (data))
/* This message we return as a last resort. We define the string in a
variable since we have to avoid freeing it and so have to enable
a pointer comparison. See below and in dlfcn/dlerror.c. */
const char _dl_out_of_memory[] = "out of memory";
/* This points to a function which is called when an continuable error is
received. Unlike the handling of `catch' this function may return.
The arguments will be the `errstring' and `objname'.
Since this functionality is not used in normal programs (only in ld.so)
we do not care about multi-threaded programs here. We keep this as a
global variable. */
static receiver_fct receiver;
void
internal_function
_dl_signal_error (int errcode, const char *objname, const char *occation,
const char *errstring)
{
struct catch *lcatch;
if (! errstring)
errstring = N_("DYNAMIC LINKER BUG!!!");
lcatch = tsd_getspecific ();
if (objname == NULL)
objname = "";
if (lcatch != NULL)
{
/* We are inside _dl_catch_error. Return to it. We have to
duplicate the error string since it might be allocated on the
stack. The object name is always a string constant. */
size_t len_objname = strlen (objname) + 1;
size_t len_errstring = strlen (errstring) + 1;
lcatch->errstring = (char *) malloc (len_objname + len_errstring);
if (lcatch->errstring != NULL)
{
char *tmp;
/* Make a copy of the object file name and the error string. */
tmp = memcpy ((char *) lcatch->errstring,
errstring, len_errstring);
tmp += len_errstring;
lcatch->objname = memcpy (tmp,
objname, len_objname);
}
else
{
/* This is better than nothing. */
lcatch->objname = "";
lcatch->errstring = _dl_out_of_memory;
}
longjmp (lcatch->env, errcode ?: -1);
}
else
{
/* Lossage while resolving the program's own symbols is always fatal. */
char buffer[1024];
_dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
_dl_argv[0] ?: "<program name unknown>",
occation ?: N_("error while loading shared libraries"),
objname, *objname ? ": " : "",
errstring, errcode ? ": " : "",
(errcode
? __strerror_r (errcode, buffer, sizeof buffer)
: ""));
}
}
void
internal_function
_dl_signal_cerror (int errcode, const char *objname, const char *occation,
const char *errstring)
{
if (receiver)
{
/* We are inside _dl_receive_error. Call the user supplied
handler and resume the work. The receiver will still be
installed. */
(*receiver) (errcode, objname, errstring);
}
else
_dl_signal_error (errcode, objname, occation, errstring);
}
int
internal_function
_dl_catch_error (const char **objname, const char **errstring,
void (*operate) (void *), void *args)
{
int errcode;
struct catch *volatile old;
struct catch c;
/* We need not handle `receiver' since setting a `catch' is handled
before it. */
/* Some systems (e.g., SPARC) handle constructors to local variables
inefficient. So we initialize `c' by hand. */
c.errstring = NULL;
old = tsd_getspecific ();
errcode = setjmp (c.env);
if (__builtin_expect (errcode, 0) == 0)
{
tsd_setspecific (&c);
(*operate) (args);
tsd_setspecific (old);
*objname = NULL;
*errstring = NULL;
return 0;
}
/* We get here only if we longjmp'd out of OPERATE. */
tsd_setspecific (old);
*objname = c.objname;
*errstring = c.errstring;
return errcode == -1 ? 0 : errcode;
}
void
internal_function
_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
{
struct catch *old_catch;
receiver_fct old_receiver;
old_catch = tsd_getspecific ();
old_receiver = receiver;
/* Set the new values. */
tsd_setspecific (NULL);
receiver = fct;
(*operate) (args);
tsd_setspecific (old_catch);
receiver = old_receiver;
}

View File

@ -0,0 +1,172 @@
/* Call the termination functions of loaded shared objects.
Copyright (C) 1995,96,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <alloca.h>
#include <assert.h>
#include <string.h>
#include <ldsodefs.h>
/* Type of the constructor functions. */
typedef void (*fini_t) (void);
void
internal_function
_dl_fini (void)
{
/* Lots of fun ahead. We have to call the destructors for all still
loaded objects. The problem is that the ELF specification now
demands that dependencies between the modules are taken into account.
I.e., the destructor for a module is called before the ones for any
of its dependencies.
To make things more complicated, we cannot simply use the reverse
order of the constructors. Since the user might have loaded objects
using `dlopen' there are possibly several other modules with its
dependencies to be taken into account. Therefore we have to start
determining the order of the modules once again from the beginning. */
unsigned int i;
struct link_map *l;
struct link_map **maps;
/* XXX Could it be (in static binaries) that there is no object loaded? */
assert (_dl_nloaded > 0);
/* Now we can allocate an array to hold all the pointers and copy
the pointers in. */
maps = (struct link_map **) alloca (_dl_nloaded
* sizeof (struct link_map *));
for (l = _dl_loaded, i = 0; l != NULL; l = l->l_next)
{
assert (i < _dl_nloaded);
maps[i++] = l;
/* Bump l_opencount of all objects so that they are not dlclose()ed
from underneath us. */
++l->l_opencount;
}
assert (i == _dl_nloaded);
/* Now we have to do the sorting. */
for (l = _dl_loaded->l_next; l != NULL; l = l->l_next)
{
unsigned int j;
unsigned int k;
/* Find the place in the `maps' array. */
for (j = 1; maps[j] != l; ++j)
;
/* Find all object for which the current one is a dependency and
move the found object (if necessary) in front. */
for (k = j + 1; k < _dl_nloaded; ++k)
{
struct link_map **runp;
runp = maps[k]->l_initfini;
if (runp != NULL)
{
while (*runp != NULL)
if (*runp == l)
{
struct link_map *here = maps[k];
/* Move it now. */
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
maps[j++] = here;
break;
}
else
++runp;
}
if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
{
unsigned int m = maps[k]->l_reldepsact;
struct link_map **relmaps = maps[k]->l_reldeps;
while (m-- > 0)
{
if (relmaps[m] == l)
{
struct link_map *here = maps[k];
/* Move it now. */
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
maps[j] = here;
break;
}
}
}
}
}
/* `maps' now contains the objects in the right order. Now call the
destructors. We have to process this array from the front. */
for (i = 0; i < _dl_nloaded; ++i)
{
l = maps[i];
if (l->l_init_called)
{
/* Make sure nothing happens if we are called twice. */
l->l_init_called = 0;
/* Don't call the destructors for objects we are not supposed to. */
if (l->l_name[0] == '\0' && l->l_type == lt_executable)
continue;
/* Is there a destructor function? */
if (l->l_info[DT_FINI_ARRAY] == NULL && l->l_info[DT_FINI] == NULL)
continue;
/* When debugging print a message first. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
_dl_debug_printf ("\ncalling fini: %s\n\n",
l->l_name[0] ? l->l_name : _dl_argv[0]);
/* First see whether an array is given. */
if (l->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (l->l_addr
+ l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int sz = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
unsigned int cnt;
for (cnt = 0; cnt < sz; ++cnt)
((fini_t) (l->l_addr + array[cnt])) ();
}
/* Next try the old-style destructor. */
if (l->l_info[DT_FINI] != NULL)
((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
}
}
}

View File

@ -0,0 +1,149 @@
/* Return the next shared object initializer function not yet run.
Copyright (C) 1995,1996,1998,1999,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stddef.h>
#include <ldsodefs.h>
/* Type of the initializer. */
typedef void (*init_t) (int, char **, char **);
/* Flag, nonzero during startup phase. */
extern int _dl_starting_up;
/* The object to be initialized first. */
extern struct link_map *_dl_initfirst;
static void
call_init (struct link_map *l, int argc, char **argv, char **env)
{
if (l->l_init_called)
/* This object is all done. */
return;
/* Avoid handling this constructor again in case we have a circular
dependency. */
l->l_init_called = 1;
/* Check for object which constructors we do not run here. */
if (__builtin_expect (l->l_name[0], 'a') == '\0'
&& l->l_type == lt_executable)
return;
/* Are there any constructors? */
if (l->l_info[DT_INIT] == NULL
&& __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1))
return;
/* Print a debug message if wanted. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
_dl_debug_printf ("\ncalling init: %s\n\n",
l->l_name[0] ? l->l_name : _dl_argv[0]);
/* Now run the local constructors. There are two forms of them:
- the one named by DT_INIT
- the others in the DT_INIT_ARRAY.
*/
if (l->l_info[DT_INIT] != NULL)
{
init_t init = (init_t) DL_DT_INIT_ADDRESS
(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr);
/* Call the function. */
init (argc, argv, env);
}
/* Next see whether there is an array with initialization functions. */
if (l->l_info[DT_INIT_ARRAY] != NULL)
{
unsigned int j;
unsigned int jm;
ElfW(Addr) *addrs;
jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
addrs = (ElfW(Addr) *) (l->l_info[DT_INIT_ARRAY]->d_un.d_ptr
+ l->l_addr);
for (j = 0; j < jm; ++j)
((init_t) addrs[j]) (argc, argv, env);
}
}
void
internal_function
_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
{
ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
struct r_debug *r;
unsigned int i;
if (__builtin_expect (_dl_initfirst != NULL, 0))
{
call_init (_dl_initfirst, argc, argv, env);
_dl_initfirst = NULL;
}
/* Don't do anything if there is no preinit array. */
if (__builtin_expect (preinit_array != NULL, 0)
&& (i = preinit_array->d_un.d_val / sizeof (ElfW(Addr))) > 0)
{
ElfW(Addr) *addrs;
unsigned int cnt;
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
_dl_debug_printf ("\ncalling preinit: %s\n\n",
main_map->l_name[0]
? main_map->l_name : _dl_argv[0]);
addrs = (ElfW(Addr) *) (main_map->l_info[DT_PREINIT_ARRAY]->d_un.d_ptr
+ main_map->l_addr);
for (cnt = 0; cnt < i; ++cnt)
((init_t) addrs[cnt]) (argc, argv, env);
}
/* 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 ();
/* Stupid users forced the ELF specification to be changed. It now
says that the dynamic loader is responsible for determining the
order in which the constructors have to run. The constructors
for all dependencies of an object must run before the constructor
for the object itself. Circular dependencies are left unspecified.
This is highly questionable since it puts the burden on the dynamic
loader which has to find the dependencies at runtime instead of
letting the user do it right. Stupidity rules! */
i = main_map->l_searchlist.r_nlist;
while (i-- > 0)
call_init (main_map->l_initfini[i], argc, argv, env);
/* Notify the debugger all new objects are now ready to go. */
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
/* Finished starting up. */
_dl_starting_up = 0;
}

View File

@ -0,0 +1,65 @@
/* Get loaded objects program headers.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <ldsodefs.h>
#include <stddef.h>
#include <bits/libc-lock.h>
int
__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
size_t size, void *data), void *data)
{
struct link_map *l;
struct dl_phdr_info info;
int ret = 0;
/* Make sure we are alone. */
#ifdef HAVE_DD_LOCK
__lock_acquire(_dl_load_lock);
#endif
for (l = _dl_loaded; l != NULL; l = l->l_next)
{
/* Skip the dynamic linker. */
if (l->l_phdr == NULL)
continue;
info.dlpi_addr = l->l_addr;
info.dlpi_name = l->l_name;
info.dlpi_phdr = l->l_phdr;
info.dlpi_phnum = l->l_phnum;
ret = callback (&info, sizeof (struct dl_phdr_info), data);
if (ret)
break;
}
/* Release the lock. */
#ifdef HAVE_DD_LOCK
__lock_release(_dl_load_lock);
#endif
return ret;
}
#ifdef SHARED
weak_alias (__dl_iterate_phdr, dl_iterate_phdr);
#endif

View File

@ -0,0 +1,156 @@
/* Handle loading and unloading shared objects for internal libc purposes.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <dlfcn.h>
#include <stdlib.h>
#include <ldsodefs.h>
/* The purpose of this file is to provide wrappers around the dynamic
linker error mechanism (similar to dlopen() et al in libdl) which
are usable from within libc. Generally we want to throw away the
string that dlerror() would return and just pass back a null pointer
for errors. This also lets the rest of libc not know about the error
handling mechanism.
Much of this code came from gconv_dl.c with slight modifications. */
static int
internal_function
dlerror_run (void (*operate) (void *), void *args)
{
const char *objname;
const char *last_errstring = NULL;
int result;
(void) _dl_catch_error (&objname, &last_errstring, operate, args);
result = last_errstring != NULL;
if (result && last_errstring != _dl_out_of_memory)
free ((char *) last_errstring);
return result;
}
/* These functions are called by dlerror_run... */
struct do_dlopen_args
{
/* Argument to do_dlopen. */
const char *name;
/* Return from do_dlopen. */
struct link_map *map;
};
struct do_dlsym_args
{
/* Arguments to do_dlsym. */
struct link_map *map;
const char *name;
/* Return values of do_dlsym. */
lookup_t loadbase;
const ElfW(Sym) *ref;
};
static void
do_dlopen (void *ptr)
{
struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
/* Open and relocate the shared object. */
args->map = _dl_open (args->name, RTLD_LAZY, NULL);
}
static void
do_dlsym (void *ptr)
{
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
args->ref = NULL;
args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
args->map->l_local_scope, 0, 1);
}
static void
do_dlclose (void *ptr)
{
_dl_close ((struct link_map *) ptr);
}
/* ... and these functions call dlerror_run. */
void *
__libc_dlopen (const char *__name)
{
struct do_dlopen_args args;
args.name = __name;
return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
}
void *
__libc_dlsym (void *__map, const char *__name)
{
struct do_dlsym_args args;
args.map = __map;
args.name = __name;
return (dlerror_run (do_dlsym, &args) ? NULL
: (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
}
int
__libc_dlclose (void *__map)
{
return dlerror_run (do_dlclose, __map);
}
static void
free_mem (void)
{
struct link_map *l;
struct r_search_path_elem *d;
/* Remove all search directories. */
d = _dl_all_dirs;
while (d != _dl_init_all_dirs)
{
struct r_search_path_elem *old = d;
d = d->next;
free (old);
}
/* Remove all additional names added to the objects. */
for (l = _dl_loaded; l != NULL; l = l->l_next)
{
struct libname_list *lnp = l->l_libname->next;
l->l_libname->next = NULL;
while (lnp != NULL)
{
struct libname_list *old = lnp;
lnp = lnp->next;
if (! old->dont_free)
free (old);
}
}
}
text_set_element (__libc_subfreeres, free_mem);

View File

@ -0,0 +1,87 @@
/* Optional code to distinguish library flavours.
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _DL_LIBRECON_H
#define _DL_LIBRECON_H 1
#define DISTINGUISH_LIB_VERSIONS \
do \
{ \
/* We have to find out whether the binary is linked against \
libc 5 or glibc. We do this by looking at all the DT_NEEDED \
entries. If one is libc.so.5 this is a libc 5 linked binary. */ \
if (_dl_loaded->l_info[DT_NEEDED]) \
{ \
/* We have dependencies. */ \
const ElfW(Dyn) *d; \
const char *strtab; \
\
strtab = (const char *) D_PTR (_dl_loaded, l_info[DT_STRTAB]); \
\
for (d = _dl_loaded->l_ld; d->d_tag != DT_NULL; ++d) \
if (d->d_tag == DT_NEEDED \
&& strcmp (strtab + d->d_un.d_val, "libc.so.5") == 0) \
break; \
\
/* We print a `5' or `6' depending on the outcome. */ \
_dl_printf (d->d_tag != DT_NULL ? "5\n" : "6\n"); \
} \
} \
while (0)
/* Recognizing extra environment variables. */
#define EXTRA_LD_ENVVARS \
case 13: \
if (memcmp (envline, "ASSUME_KERNEL", 13) == 0) \
{ \
unsigned long int i, j, osversion = 0; \
char *p = &envline[14], *q; \
\
for (i = 0; i < 3; i++, p = q + 1) \
{ \
j = __strtoul_internal (p, &q, 0, 0); \
if (j >= 255 || p == q || (i < 2 && *q && *q != '.')) \
{ \
osversion = 0; \
break; \
} \
osversion |= j << (16 - 8 * i); \
if (!*q) \
break; \
} \
if (osversion) \
_dl_osversion = osversion; \
break; \
} \
\
case 15: \
if (memcmp (envline, "LIBRARY_VERSION", 15) == 0) \
{ \
_dl_correct_cache_id = envline[16] == '5' ? 2 : 3; \
break; \
}
/* Extra unsecure variables. The names are all stuffed in a single
string which means they have to be terminated with a '\0' explicitly. */
#define EXTRA_UNSECURE_ENVVARS \
"LD_AOUT_LIBRARY_PATH\0" \
"LD_AOUT_PRELOAD\0"
#endif /* dl-librecon.h */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,654 @@
/* Look up a symbol in the loaded objects.
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <alloca.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ldsodefs.h>
#include "dl-hash.h"
#include <machine/dl-machine.h>
#include <bits/libc-lock.h>
#include <assert.h>
#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
/* We need this string more than once. */
static const char undefined_msg[] = "undefined symbol: ";
struct sym_val
{
const ElfW(Sym) *s;
struct link_map *m;
};
#define make_string(string, rest...) \
({ \
const char *all[] = { string, ## rest }; \
size_t len, cnt; \
char *result, *cp; \
\
len = 1; \
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
len += strlen (all[cnt]); \
\
cp = result = alloca (len); \
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
{ \
cp = strcpy (cp, all[cnt]); \
cp += strlen(all[cnt]); \
} \
\
result; \
})
/* Statistics function. */
unsigned long int _dl_num_relocations;
/* We have two different situations when looking up a simple: with or
without versioning. gcc is not able to optimize a single function
definition serving for both purposes so we define two functions. */
#define VERSIONED 0
#include "do-lookup.h"
#define VERSIONED 1
#include "do-lookup.h"
/* Add extra dependency on MAP to UNDEF_MAP. */
static int
internal_function
add_dependency (struct link_map *undef_map, struct link_map *map)
{
struct link_map **list;
struct link_map *runp;
unsigned int act;
unsigned int i;
int result = 0;
/* Avoid self-references. */
if (undef_map == map)
return 0;
/* Make sure nobody can unload the object while we are at it. */
#ifdef HAVE_DD_LOCK
__lock_acquire(_dl_load_lock);
#endif
/* Determine whether UNDEF_MAP already has a reference to MAP. First
look in the normal dependencies. */
if (undef_map->l_searchlist.r_list != NULL)
{
list = undef_map->l_initfini;
for (i = 0; list[i] != NULL; ++i)
if (list[i] == map)
goto out;
}
/* No normal dependency. See whether we already had to add it
to the special list of dynamic dependencies. */
list = undef_map->l_reldeps;
act = undef_map->l_reldepsact;
for (i = 0; i < act; ++i)
if (list[i] == map)
goto out;
/* The object is not yet in the dependency list. Before we add
it make sure just one more time the object we are about to
reference is still available. There is a brief period in
which the object could have been removed since we found the
definition. */
runp = _dl_loaded;
while (runp != NULL && runp != map)
runp = runp->l_next;
if (runp != NULL)
{
/* The object is still available. Add the reference now. */
if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
{
/* Allocate more memory for the dependency list. Since this
can never happen during the startup phase we can use
`realloc'. */
void *newp;
undef_map->l_reldepsmax += 5;
newp = realloc (undef_map->l_reldeps,
undef_map->l_reldepsmax
* sizeof (struct link_map *));
if (__builtin_expect (newp != NULL, 1))
undef_map->l_reldeps = (struct link_map **) newp;
else
/* Correct the addition. */
undef_map->l_reldepsmax -= 5;
}
/* If we didn't manage to allocate memory for the list this is
no fatal mistake. We simply increment the use counter of the
referenced object and don't record the dependencies. This
means this increment can never be reverted and the object
will never be unloaded. This is semantically the correct
behaviour. */
if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
if (map->l_searchlist.r_list != NULL)
/* And increment the counter in the referenced object. */
++map->l_opencount;
else
/* We have to bump the counts for all dependencies since so far
this object was only a normal or transitive dependency.
Now it might be closed with _dl_close() directly. */
for (list = map->l_initfini; *list != NULL; ++list)
++(*list)->l_opencount;
/* Display information if we are debugging. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
_dl_debug_printf ("\
\nfile=%s; needed by %s (relocation dependency)\n\n",
map->l_name[0] ? map->l_name : _dl_argv[0],
undef_map->l_name[0]
? undef_map->l_name : _dl_argv[0]);
}
else
/* Whoa, that was bad luck. We have to search again. */
result = -1;
out:
/* Release the lock. */
#ifdef HAVE_DD_LOCK
__lock_release(_dl_load_lock);
#endif
return result;
}
static int
internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i,
struct link_map *skip, int type_class);
static int
internal_function
_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i,
const struct r_found_version *const version,
struct link_map *skip, int type_class);
/* Search loaded objects' symbol tables for a definition of the symbol
UNDEF_NAME. */
lookup_t
internal_function
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
int type_class, int explicit)
{
unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
int protected;
++_dl_num_relocations;
/* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope)
if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
type_class))
{
/* We have to check whether this would bind UNDEF_MAP to an object
in the global scope which was dynamically loaded. In this case
we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& ! explicit
/* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference
was just removed. Try finding another definition. */
return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
type_class, 0);
break;
}
if (__builtin_expect (current_value.s == NULL, 0))
{
const char *reference_name = undef_map ? undef_map->l_name : NULL;
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
/* We could find no value for a strong reference. */
/* XXX We cannot translate the messages. */
_dl_signal_cerror (0, (reference_name && reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
N_("relocation error"),
make_string (undefined_msg, undef_name));
*ref = NULL;
return 0;
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
{
const char *reference_name = undef_map ? undef_map->l_name : NULL;
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
(reference_name && reference_name[0]
? reference_name : (_dl_argv[0] ?: "<main program>")),
current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
protected ? "protected" : "normal", undef_name);
}
if (__builtin_expect (protected == 0, 1))
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
else
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol */
struct sym_val protected_value = { NULL, NULL };
for (scope = symbol_scope; *scope; ++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
0, NULL, ELF_RTYPE_CLASS_PLT))
break;
if (protected_value.s == NULL || protected_value.m == undef_map)
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
return LOOKUP_VALUE (undef_map);
}
}
/* This function is nearly the same as `_dl_lookup_symbol' but it
skips in the first list all objects until SKIP_MAP is found. I.e.,
it only considers objects which were loaded after the described
object. If there are more search lists the object described by
SKIP_MAP is only skipped. */
lookup_t
internal_function
_dl_lookup_symbol_skip (const char *undef_name,
struct link_map *undef_map, const ElfW(Sym) **ref,
struct r_scope_elem *symbol_scope[],
struct link_map *skip_map)
{
const char *reference_name = undef_map ? undef_map->l_name : NULL;
const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
size_t i;
int protected;
++_dl_num_relocations;
/* Search the relevant loaded objects for a definition. */
scope = symbol_scope;
for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
assert (i < (*scope)->r_nlist);
if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
skip_map, 0))
while (*++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
skip_map, 0))
break;
if (__builtin_expect (current_value.s == NULL, 0))
{
*ref = NULL;
return 0;
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
(reference_name && reference_name[0]
? reference_name : (_dl_argv[0] ?: "<main program>")),
current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
protected ? "protected" : "normal", undef_name);
if (__builtin_expect (protected == 0, 1))
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
else
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol. */
struct sym_val protected_value = { NULL, NULL };
if (i >= (*scope)->r_nlist
|| !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
i, skip_map, ELF_RTYPE_CLASS_PLT))
while (*++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
0, skip_map, ELF_RTYPE_CLASS_PLT))
break;
if (protected_value.s == NULL || protected_value.m == undef_map)
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
return LOOKUP_VALUE (undef_map);
}
}
/* This function works like _dl_lookup_symbol but it takes an
additional arguement with the version number of the requested
symbol.
XXX We'll see whether we need this separate function. */
lookup_t
internal_function
_dl_lookup_versioned_symbol (const char *undef_name,
struct link_map *undef_map, const ElfW(Sym) **ref,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
int type_class, int explicit)
{
unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
int protected;
++_dl_num_relocations;
/* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope)
{
int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
*scope, 0, version, NULL, type_class);
if (res > 0)
{
/* We have to check whether this would bind UNDEF_MAP to an object
in the global scope which was dynamically loaded. In this case
we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& ! explicit
/* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference
was just removed. Try finding another definition. */
return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
symbol_scope, version,
type_class, 0);
break;
}
if (__builtin_expect (res, 0) < 0)
{
/* Oh, oh. The file named in the relocation entry does not
contain the needed symbol. */
const char *reference_name = undef_map ? undef_map->l_name : NULL;
/* XXX We cannot translate the message. */
_dl_signal_cerror (0, (reference_name && reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
N_("relocation error"),
make_string ("symbol ", undef_name, ", version ",
version->name,
" not defined in file ",
version->filename,
" with link time reference",
res == -2
? " (no version symbols)" : ""));
*ref = NULL;
return 0;
}
}
if (__builtin_expect (current_value.s == NULL, 0))
{
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
{
/* We could find no value for a strong reference. */
const char *reference_name = undef_map ? undef_map->l_name : NULL;
/* XXX We cannot translate the message. */
_dl_signal_cerror (0, (reference_name && reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")), NULL,
make_string (undefined_msg, undef_name,
", version ",
version->name ?: NULL));
}
*ref = NULL;
return 0;
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
{
const char *reference_name = undef_map ? undef_map->l_name : NULL;
_dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
(reference_name && reference_name[0]
? reference_name : (_dl_argv[0] ?: "<main program>")),
current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
protected ? "protected" : "normal",
undef_name, version->name);
}
if (__builtin_expect (protected == 0, 1))
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
else
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol */
struct sym_val protected_value = { NULL, NULL };
for (scope = symbol_scope; *scope; ++scope)
if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
*scope, 0, version, NULL,
ELF_RTYPE_CLASS_PLT))
break;
if (protected_value.s == NULL || protected_value.m == undef_map)
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
return LOOKUP_VALUE (undef_map);
}
}
/* Similar to _dl_lookup_symbol_skip but takes an additional argument
with the version we are looking for. */
lookup_t
internal_function
_dl_lookup_versioned_symbol_skip (const char *undef_name,
struct link_map *undef_map,
const ElfW(Sym) **ref,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
struct link_map *skip_map)
{
const char *reference_name = undef_map ? undef_map->l_name : NULL;
const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
size_t i;
int protected;
++_dl_num_relocations;
/* Search the relevant loaded objects for a definition. */
scope = symbol_scope;
for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
assert (i < (*scope)->r_nlist);
if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
*scope, i, version, skip_map, 0))
while (*++scope)
if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
*scope, 0, version, skip_map, 0))
break;
if (__builtin_expect (current_value.s == NULL, 0))
{
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
{
/* We could find no value for a strong reference. */
const size_t len = strlen (undef_name);
char buf[sizeof undefined_msg + len];
char *tmp;
tmp = memcpy (buf, undefined_msg, sizeof undefined_msg - 1);
tmp += (sizeof undefined_msg - 1);
memcpy (tmp, undef_name, len + 1);
/* XXX We cannot translate the messages. */
_dl_signal_cerror (0, (reference_name && reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
NULL, buf);
}
*ref = NULL;
return 0;
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
_dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
(reference_name && reference_name[0]
? reference_name : (_dl_argv[0] ?: "<main program>")),
current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
protected ? "protected" : "normal",
undef_name, version->name);
if (__builtin_expect (protected == 0, 1))
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
else
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol */
struct sym_val protected_value = { NULL, NULL };
if (i >= (*scope)->r_nlist
|| !_dl_do_lookup_versioned (undef_name, hash, *ref,
&protected_value, *scope, i, version,
skip_map, ELF_RTYPE_CLASS_PLT))
while (*++scope)
if (_dl_do_lookup_versioned (undef_name, hash, *ref,
&protected_value, *scope, 0, version,
skip_map, ELF_RTYPE_CLASS_PLT))
break;
if (protected_value.s == NULL || protected_value.m == undef_map)
{
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
return LOOKUP_VALUE (undef_map);
}
}
/* Cache the location of MAP's hash table. */
void
internal_function
_dl_setup_hash (struct link_map *map)
{
Elf_Symndx *hash;
Elf_Symndx nchain;
if (!map->l_info[DT_HASH])
return;
hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
map->l_nbuckets = *hash++;
nchain = *hash++;
map->l_buckets = hash;
hash += map->l_nbuckets;
map->l_chain = hash;
}
/* These are here so that we only inline do_lookup{,_versioned} in the common
case, not everywhere. */
static int
internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i,
struct link_map *skip, int type_class)
{
return do_lookup (undef_name, hash, ref, result, scope, i, skip,
type_class);
}
static int
internal_function
_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i,
const struct r_found_version *const version,
struct link_map *skip, int type_class)
{
return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
version, skip, type_class);
}

View File

@ -0,0 +1,22 @@
/* Configuration of lookup functions.
Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Some platforms need more information from the symbol lookup function
than just the address. But this is not generally the case. */
#undef DL_LOOKUP_RETURNS_MAP

View File

@ -0,0 +1,250 @@
/* Minimal replacements for basic facilities used in the dynamic linker.
Copyright (C) 1995,96,97,98,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <ldsodefs.h>
#include <machine/weakalias.h>
#include <assert.h>
/* Minimal `malloc' allocator for use while loading shared libraries.
No block is ever freed. */
static void *alloc_ptr, *alloc_end, *alloc_last_block;
/* Declarations of global functions. */
extern void weak_function free (void *ptr);
extern void * weak_function realloc (void *ptr, size_t n);
extern unsigned long int weak_function __strtoul_internal
(const char *nptr, char **endptr, int base, int group);
extern unsigned long int weak_function strtoul (const char *nptr,
char **endptr, int base);
void * weak_function
malloc (size_t n)
{
#ifdef MAP_ANON
#define _dl_zerofd (-1)
#else
extern int _dl_zerofd;
if (_dl_zerofd == -1)
_dl_zerofd = _dl_sysdep_open_zero_fill ();
#define MAP_ANON 0
#endif
if (alloc_end == 0)
{
/* 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) + _dl_pagesize - 1)
& ~(_dl_pagesize - 1));
}
/* Make sure the allocation pointer is ideally aligned. */
alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + sizeof (double) - 1)
& ~(sizeof (double) - 1));
if (alloc_ptr + n >= alloc_end)
{
/* Insufficient space left; allocate another page. */
caddr_t page;
size_t nup = (n + _dl_pagesize - 1) & ~(_dl_pagesize - 1);
page = __mmap (0, nup, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
assert (page != MAP_FAILED);
if (page != alloc_end)
alloc_ptr = page;
alloc_end = page + nup;
}
alloc_last_block = (void *) alloc_ptr;
alloc_ptr += n;
return alloc_last_block;
}
/* We use this function occasionally since the real implementation may
be optimized when it can assume the memory it returns already is
set to NUL. */
void * weak_function
calloc (size_t nmemb, size_t size)
{
size_t total = nmemb * size;
void *result = malloc (total);
return memset (result, '\0', total);
}
/* This will rarely be called. */
void weak_function
free (void *ptr)
{
/* We can free only the last block allocated. */
if (ptr == alloc_last_block)
alloc_ptr = alloc_last_block;
}
/* This is only called with the most recent block returned by malloc. */
void * weak_function
realloc (void *ptr, size_t n)
{
void *new;
if (ptr == NULL)
return malloc (n);
assert (ptr == alloc_last_block);
alloc_ptr = alloc_last_block;
new = malloc (n);
assert (new == ptr);
return new;
}
/* Define our own version of the internal function used by strerror. We
only provide the messages for some common errors. This avoids pulling
in the whole error list. */
char * weak_function
__strerror_r (int errnum, char *buf, size_t buflen)
{
char *msg;
switch (errnum)
{
case ENOMEM:
msg = (char *) "Cannot allocate memory";
break;
case EINVAL:
msg = (char *) "Invalid argument";
break;
case ENOENT:
msg = (char *) "No such file or directory";
break;
case EPERM:
msg = (char *) "Operation not permitted";
break;
case EIO:
msg = (char *) "Input/output error";
break;
case EACCES:
msg = (char *) "Permission denied";
break;
default:
/* No need to check buffer size, all calls in the dynamic linker
provide enough space. */
msg = (char *) "Error";
break;
}
return msg;
}
#ifndef NDEBUG
/* Define (weakly) our own assert failure function which doesn't use stdio.
If we are linked into the user program (-ldl), the normal __assert_fail
defn can override this one. */
void weak_function
__assert_fail (const char *assertion,
const char *file, unsigned int line, const char *function)
{
_dl_fatal_printf ("\
Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n",
file, line, function ?: "", function ? ": " : "",
assertion);
}
void weak_function
__assert_perror_fail (int errnum,
const char *file, unsigned int line,
const char *function)
{
char errbuf[64];
_dl_fatal_printf ("\
Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s\n",
file, line, function ?: "", function ? ": " : "",
__strerror_r (errnum, errbuf, sizeof (errbuf)));
}
#endif
unsigned long int weak_function
__strtoul_internal (const char *nptr, char **endptr, int base, int group)
{
unsigned long int result = 0;
long int sign = 1;
while (*nptr == ' ' || *nptr == '\t')
++nptr;
if (*nptr == '-')
{
sign = -1;
++nptr;
}
else if (*nptr == '+')
++nptr;
if (*nptr < '0' || *nptr > '9')
{
if (endptr != NULL)
*endptr = (char *) nptr;
return 0UL;
}
assert (base == 0);
base = 10;
if (*nptr == '0')
{
if (nptr[1] == 'x' || nptr[1] == 'X')
{
base = 16;
nptr += 2;
}
else
base = 8;
}
while (*nptr >= '0' && *nptr <= '9')
{
unsigned long int digval = *nptr - '0';
if (result > LONG_MAX / 10
|| (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
{
errno = ERANGE;
if (endptr != NULL)
*endptr = (char *) nptr;
return ULONG_MAX;
}
result *= base;
result += digval;
++nptr;
}
if (endptr != NULL)
*endptr = (char *) nptr;
return result * sign;
}

View File

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

View File

@ -0,0 +1,163 @@
/* Storage management for the chain of loaded shared objects.
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <assert.h>
/* Allocate a `struct link_map' for a new object being loaded,
and enter it into the _dl_loaded list. */
struct link_map *
internal_function
_dl_new_object (char *realname, const char *libname, int type,
struct link_map *loader)
{
struct link_map *l;
int idx;
size_t libname_len = strlen (libname) + 1;
struct link_map *new;
struct libname_list *newname;
new = (struct link_map *) calloc (sizeof (*new) + sizeof (*newname)
+ libname_len, 1);
if (new == NULL)
return NULL;
new->l_libname = newname = (struct libname_list *) (new + 1);
newname->name = (char *) memcpy (newname + 1, libname, libname_len);
/* newname->next = NULL; We use calloc therefore not necessary. */
newname->dont_free = 1;
new->l_name = realname;
new->l_type = type;
new->l_loader = loader;
/* new->l_global = 0; We use calloc therefore not necessary. */
/* Use the 'l_scope_mem' array by default for the the 'l_scope'
information. If we need more entries we will allocate a large
array dynamically. */
new->l_scope = new->l_scope_mem;
new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
/* Counter for the scopes we have to handle. */
idx = 0;
if (_dl_loaded != NULL)
{
l = _dl_loaded;
while (l->l_next != NULL)
l = l->l_next;
new->l_prev = l;
/* new->l_next = NULL; Would be necessary but we use calloc. */
l->l_next = new;
/* Add the global scope. */
new->l_scope[idx++] = &_dl_loaded->l_searchlist;
}
else
_dl_loaded = new;
++_dl_nloaded;
/* If we have no loader the new object acts as it. */
if (loader == NULL)
loader = new;
else
/* Determine the local scope. */
while (loader->l_loader != NULL)
loader = loader->l_loader;
/* Insert the scope if it isn't the global scope we already added. */
if (idx == 0 || &loader->l_searchlist != new->l_scope[0])
new->l_scope[idx] = &loader->l_searchlist;
new->l_local_scope[0] = &new->l_searchlist;
/* Don't try to find the origin for the main map which has the name "". */
if (realname[0] != '\0')
{
size_t realname_len = strlen (realname) + 1;
char *origin;
char *cp;
if (realname[0] == '/')
{
/* It is an absolute path. Use it. But we have to make a
copy since we strip out the trailing slash. */
cp = origin = (char *) malloc (realname_len);
if (origin == NULL)
{
origin = (char *) -1;
goto out;
}
}
else
{
size_t len = realname_len;
char *result = NULL;
/* Get the current directory name. */
origin = NULL;
do
{
len += 128;
origin = (char *) realloc (origin, len);
}
while (origin != NULL
&& (result = getcwd (origin, len - realname_len)) == NULL
&& errno == ERANGE);
if (result == NULL)
{
/* We were not able to determine the current directory.
Note that free(origin) is OK if origin == NULL. */
free (origin);
origin = (char *) -1;
goto out;
}
/* Find the end of the path and see whether we have to add
a slash. */
cp = memchr (origin, '\0', strlen(origin));
if (cp[-1] != '/')
*cp++ = '/';
}
/* Add the real file name. */
memcpy (cp, realname, realname_len);
/* Now remove the filename and the slash. Leave the slash if it
the name is something like "/foo". */
cp = strrchr (origin, '/');
if (cp == origin)
origin[1] = '\0';
else
*cp = '\0';
out:
new->l_origin = origin;
}
return new;
}

View File

@ -0,0 +1,487 @@
/* Load a shared object at runtime, relocate it, and run its initializer.
Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
#include <sys/param.h>
#include <ldsodefs.h>
#include <bp-sym.h>
#include <dl-dst.h>
#include <machine/weakalias.h>
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
ElfW(Addr) *user_entry));
weak_extern (BP_SYM (_dl_sysdep_start))
/* This function is used to unload the cache file if necessary. */
extern void _dl_unload_cache (void);
int __libc_argc = 0;
char **__libc_argv = NULL;
extern char **environ;
extern int _dl_lazy; /* Do we do lazy relocations? */
/* Undefine the following for debugging. */
/* #define SCOPE_DEBUG 1 */
#ifdef SCOPE_DEBUG
static void show_scope (struct link_map *new);
#endif
extern size_t _dl_platformlen;
/* We must be carefull not to leave us in an inconsistent state. Thus we
catch any error and re-raise it after cleaning up. */
struct dl_open_args
{
const char *file;
int mode;
const void *caller;
struct link_map *map;
};
static int
add_to_global (struct link_map *new)
{
struct link_map **new_global;
unsigned int to_add = 0;
unsigned int cnt;
/* Count the objects we have to put in the global scope. */
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
if (new->l_searchlist.r_list[cnt]->l_global == 0)
++to_add;
/* The symbols of the new objects and its dependencies are to be
introduced into the global scope that will be used to resolve
references from other dynamically-loaded objects.
The global scope is the searchlist in the main link map. We
extend this list if necessary. There is one problem though:
since this structure was allocated very early (before the libc
is loaded) the memory it uses is allocated by the malloc()-stub
in the ld.so. When we come here these functions are not used
anymore. Instead the malloc() implementation of the libc is
used. But this means the block from the main map cannot be used
in an realloc() call. Therefore we allocate a completely new
array the first time we have to add something to the locale scope. */
if (_dl_global_scope_alloc == 0)
{
/* This is the first dynamic object given global scope. */
_dl_global_scope_alloc = _dl_main_searchlist->r_nlist + to_add + 8;
new_global = (struct link_map **)
malloc (_dl_global_scope_alloc * sizeof (struct link_map *));
if (new_global == NULL)
{
_dl_global_scope_alloc = 0;
nomem:
_dl_signal_error (ENOMEM, new->l_libname->name, NULL,
N_("cannot extend global scope"));
return 1;
}
/* Copy over the old entries. */
memcpy (new_global, _dl_main_searchlist->r_list,
(_dl_main_searchlist->r_nlist * sizeof (struct link_map *)));
_dl_main_searchlist->r_list = new_global;
}
else if (_dl_main_searchlist->r_nlist + to_add > _dl_global_scope_alloc)
{
/* We have to extend the existing array of link maps in the
main map. */
new_global = (struct link_map **)
realloc (_dl_main_searchlist->r_list,
((_dl_global_scope_alloc + to_add + 8)
* sizeof (struct link_map *)));
if (new_global == NULL)
goto nomem;
_dl_global_scope_alloc += to_add + 8;
_dl_main_searchlist->r_list = new_global;
}
/* Now add the new entries. */
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
{
struct link_map *map = new->l_searchlist.r_list[cnt];
if (map->l_global == 0)
{
map->l_global = 1;
_dl_main_searchlist->r_list[_dl_main_searchlist->r_nlist] = map;
++_dl_main_searchlist->r_nlist;
}
}
return 0;
}
static void
dl_open_worker (void *a)
{
struct dl_open_args *args = a;
const char *file = args->file;
int mode = args->mode;
struct link_map *new, *l;
const char *dst;
int lazy;
unsigned int i;
/* Maybe we have to expand a DST. */
dst = strchr (file, '$');
if (dst != NULL)
{
const void *caller = args->caller;
size_t len = strlen (file);
size_t required;
struct link_map *call_map;
char *new_file;
/* We have to find out from which object the caller is calling. */
call_map = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (caller >= (const void *) l->l_map_start
&& caller < (const void *) l->l_map_end)
{
/* There must be exactly one DSO for the range of the virtual
memory. Otherwise something is really broken. */
call_map = l;
break;
}
if (call_map == NULL)
/* In this case we assume this is the main application. */
call_map = _dl_loaded;
/* Determine how much space we need. We have to allocate the
memory locally. */
required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));
/* Get space for the new file name. */
new_file = (char *) alloca (required + 1);
/* Generate the new file name. */
DL_DST_SUBSTITUTE (call_map, file, new_file, 0);
/* If the substitution failed don't try to load. */
if (*new_file == '\0')
_dl_signal_error (0, "dlopen", NULL,
N_("empty dynamic string token substitution"));
/* Now we have a new file name. */
file = new_file;
}
/* Load the named object. */
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0,
mode);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
if (new == NULL)
{
assert (mode & RTLD_NOLOAD);
return;
}
/* It was already open. */
if (new->l_searchlist.r_list != NULL)
{
/* Let the user know about the opencount. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
_dl_debug_printf ("opening file=%s; opencount == %u\n\n",
new->l_name, new->l_opencount);
/* If the user requested the object to be in the global namespace
but it is not so far, add it now. */
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
(void) add_to_global (new);
/* Increment just the reference counter of the object. */
++new->l_opencount;
return;
}
/* Load that object's dependencies. */
_dl_map_object_deps (new, NULL, 0, 0);
/* So far, so good. Now check the versions. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
if (new->l_searchlist.r_list[i]->l_versions == NULL)
(void) _dl_check_map_versions (new->l_searchlist.r_list[i], 0, 0);
#ifdef SCOPE_DEBUG
show_scope (new);
#endif
/* Only do lazy relocation if `LD_BIND_NOW' is not set. */
lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && _dl_lazy;
/* 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)
{
#if 0
#ifdef SHARED
if (_dl_profile != NULL)
{
/* If this here is the shared object which we want to profile
make sure the profile is started. We can find out whether
this is necessary or not by observing the `_dl_profile_map'
variable. If was NULL but is not NULL afterwars we must
start the profiling. */
struct link_map *old_profile_map = _dl_profile_map;
_dl_relocate_object (l, l->l_scope, 1, 1);
if (old_profile_map == NULL && _dl_profile_map != NULL)
/* We must prepare the profiling. */
_dl_start_profile (_dl_profile_map, _dl_profile_output);
}
else
#endif
#endif
_dl_relocate_object (l, l->l_scope, lazy, 0);
}
if (l == new)
break;
l = l->l_prev;
}
/* Increment the open count for all dependencies. If the file is
not loaded as a dependency here add the search list of the newly
loaded object to the scope. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
if (++new->l_searchlist.r_list[i]->l_opencount > 1
&& new->l_searchlist.r_list[i]->l_type == lt_loaded)
{
struct link_map *imap = new->l_searchlist.r_list[i];
struct r_scope_elem **runp = imap->l_scope;
size_t cnt = 0;
while (*runp != NULL)
{
/* This can happen if imap was just loaded, but during
relocation had l_opencount bumped because of relocation
dependency. Avoid duplicates in l_scope. */
if (__builtin_expect (*runp == &new->l_searchlist, 0))
break;
++cnt;
++runp;
}
if (*runp != NULL)
/* Avoid duplicates. */
continue;
if (__builtin_expect (cnt + 1 >= imap->l_scope_max, 0))
{
/* The 'r_scope' array is too small. Allocate a new one
dynamically. */
struct r_scope_elem **newp;
size_t new_size = imap->l_scope_max * 2;
if (imap->l_scope == imap->l_scope_mem)
{
newp = (struct r_scope_elem **)
malloc (new_size * sizeof (struct r_scope_elem *));
if (newp == NULL)
_dl_signal_error (ENOMEM, "dlopen", NULL,
N_("cannot create scope list"));
imap->l_scope = memcpy (newp, imap->l_scope,
cnt * sizeof (imap->l_scope[0]));
}
else
{
newp = (struct r_scope_elem **)
realloc (imap->l_scope,
new_size * sizeof (struct r_scope_elem *));
if (newp == NULL)
_dl_signal_error (ENOMEM, "dlopen", NULL,
N_("cannot create scope list"));
imap->l_scope = newp;
}
imap->l_scope_max = new_size;
}
imap->l_scope[cnt++] = &new->l_searchlist;
imap->l_scope[cnt] = NULL;
}
/* Run the initializer functions of new objects. */
_dl_init (new, __libc_argc, __libc_argv, environ);
/* Now we can make the new map available in the global scope. */
if (mode & RTLD_GLOBAL)
/* Move the object in the global namespace. */
if (add_to_global (new) != 0)
/* It failed. */
return;
/* Mark the object as not deletable if the RTLD_NODELETE flags was
passed. */
if (__builtin_expect (mode & RTLD_NODELETE, 0))
new->l_flags_1 |= DF_1_NODELETE;
/* Let the user know about the opencount. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
_dl_debug_printf ("opening file=%s; opencount == %u\n\n",
new->l_name, new->l_opencount);
}
void *
internal_function
_dl_open (const char *file, int mode, const void *caller)
{
struct dl_open_args args;
const char *objname;
const char *errstring;
int errcode;
if ((mode & RTLD_BINDING_MASK) == 0)
/* One of the flags must be set. */
_dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
/* Make sure we are alone. */
#ifdef HAVE_DD_LOCK
__lock_acquire_recursive(_dl_load_lock);
#endif
args.file = file;
args.mode = mode;
args.caller = caller;
args.map = NULL;
errcode = _dl_catch_error (&objname, &errstring, dl_open_worker, &args);
#ifndef MAP_COPY
/* We must munmap() the cache file. */
_dl_unload_cache ();
#endif
/* Release the lock. */
#ifdef HAVE_DD_LOCK
__lock_release_recursive(_dl_load_lock);
#endif
if (errstring)
{
/* Some error occurred during loading. */
char *local_errstring;
size_t len_errstring;
/* Remove the object from memory. It may be in an inconsistent
state if relocation failed, for example. */
if (args.map)
{
unsigned int i;
/* Increment open counters for all objects since this has
not happened yet. */
for (i = 0; i < args.map->l_searchlist.r_nlist; ++i)
++args.map->l_searchlist.r_list[i]->l_opencount;
_dl_close (args.map);
}
/* Make a local copy of the error string so that we can release the
memory allocated for it. */
len_errstring = strlen (errstring) + 1;
if (objname == errstring + len_errstring)
{
size_t total_len = len_errstring + strlen (objname) + 1;
local_errstring = alloca (total_len);
memcpy (local_errstring, errstring, total_len);
objname = local_errstring + len_errstring;
}
else
{
local_errstring = alloca (len_errstring);
memcpy (local_errstring, errstring, len_errstring);
}
if (errstring != _dl_out_of_memory)
free ((char *) errstring);
/* Reraise the error. */
_dl_signal_error (errcode, objname, NULL, local_errstring);
}
#ifndef SHARED
DL_STATIC_INIT (args.map);
#endif
return args.map;
}
#ifdef SCOPE_DEBUG
#include <unistd.h>
static void
show_scope (struct link_map *new)
{
int scope_cnt;
for (scope_cnt = 0; new->l_scope[scope_cnt] != NULL; ++scope_cnt)
{
char numbuf[2];
unsigned int cnt;
numbuf[0] = '0' + scope_cnt;
numbuf[1] = '\0';
_dl_printf ("scope %s:", numbuf);
for (cnt = 0; cnt < new->l_scope[scope_cnt]->r_nlist; ++cnt)
if (*new->l_scope[scope_cnt]->r_list[cnt]->l_name)
_dl_printf (" %s", new->l_scope[scope_cnt]->r_list[cnt]->l_name);
else
_dl_printf (" <main>");
_dl_printf ("\n");
}
}
#endif

View File

@ -0,0 +1,108 @@
/* Operating system specific code for generic dynamic loader functions.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <string.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include "kernel-features.h"
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifdef SHARED
/* This is the function used in the dynamic linker to print the fatal error
message. */
static inline void
__attribute__ ((__noreturn__))
dl_fatal (const char *str)
{
_dl_dprintf (2, str);
_exit (1);
}
#endif
#define DL_SYSDEP_OSCHECK(FATAL) \
do { \
/* Test whether the kernel is new enough. This test is only \
performed if the library is not compiled to run on all \
kernels. */ \
if (__LINUX_KERNEL_VERSION > 0) \
{ \
char bufmem[64]; \
char *buf = bufmem; \
unsigned int version; \
int parts; \
char *cp; \
struct utsname uts; \
\
/* Try the uname syscall */ \
if (__uname (&uts)) \
{ \
/* This was not successful. Now try reading the /proc \
filesystem. */ \
ssize_t reslen; \
int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY); \
if (fd == -1 \
|| (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0) \
/* This also didn't work. We give up since we cannot \
make sure the library can actually work. */ \
FATAL ("FATAL: cannot determine library version\n"); \
__close (fd); \
buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0'; \
} \
else \
buf = uts.release; \
\
/* Now convert it into a number. The string consists of at most \
three parts. */ \
version = 0; \
parts = 0; \
cp = buf; \
while ((*cp >= '0') && (*cp <= '9')) \
{ \
unsigned int here = *cp++ - '0'; \
\
while ((*cp >= '0') && (*cp <= '9')) \
{ \
here *= 10; \
here += *cp++ - '0'; \
} \
\
++parts; \
version <<= 8; \
version |= here; \
\
if (*cp++ != '.') \
/* Another part following? */ \
break; \
} \
\
if (parts < 3) \
version <<= 8 * (3 - parts); \
\
/* Now we can test with the required version. */ \
if (version < __LINUX_KERNEL_VERSION) \
/* Not sufficent. */ \
FATAL ("FATAL: kernel too old\n"); \
\
_dl_osversion = version; \
} \
} while (0)

View File

@ -0,0 +1,539 @@
/* Profiling of shared libraries.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
Based on the BSD mcount implementation.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sys/gmon.h>
#include <sys/gmon_out.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <atomicity.h>
#include <config.h>
/* The LD_PROFILE feature has to be implemented different to the
normal profiling using the gmon/ functions. The problem is that an
arbitrary amount of processes simulataneously can be run using
profiling and all write the results in the same file. To provide
this mechanism one could implement a complicated mechanism to merge
the content of two profiling runs or one could extend the file
format to allow more than one data set. For the second solution we
would have the problem that the file can grow in size beyond any
limit and both solutions have the problem that the concurrency of
writing the results is a big problem.
Another much simpler method is to use mmap to map the same file in
all using programs and modify the data in the mmap'ed area and so
also automatically on the disk. Using the MAP_SHARED option of
mmap(2) this can be done without big problems in more than one
file.
This approach is very different from the normal profiling. We have
to use the profiling data in exactly the way they are expected to
be written to disk. But the normal format used by gprof is not usable
to do this. It is optimized for size. It writes the tags as single
bytes but this means that the following 32/64 bit values are
unaligned.
Therefore we use a new format. This will look like this
0 1 2 3 <- byte is 32 bit word
0000 g m o n
0004 *version* <- GMON_SHOBJ_VERSION
0008 00 00 00 00
000c 00 00 00 00
0010 00 00 00 00
0014 *tag* <- GMON_TAG_TIME_HIST
0018 ?? ?? ?? ??
?? ?? ?? ?? <- 32/64 bit LowPC
0018+A ?? ?? ?? ??
?? ?? ?? ?? <- 32/64 bit HighPC
0018+2*A *histsize*
001c+2*A *profrate*
0020+2*A s e c o
0024+2*A n d s \0
0028+2*A \0 \0 \0 \0
002c+2*A \0 \0 \0
002f+2*A s
0030+2*A ?? ?? ?? ?? <- Count data
... ...
0030+2*A+K ?? ?? ?? ??
0030+2*A+K *tag* <- GMON_TAG_CG_ARC
0034+2*A+K *lastused*
0038+2*A+K ?? ?? ?? ??
?? ?? ?? ?? <- FromPC#1
0038+3*A+K ?? ?? ?? ??
?? ?? ?? ?? <- ToPC#1
0038+4*A+K ?? ?? ?? ?? <- Count#1
... ... ...
0038+(2*(CN-1)+2)*A+(CN-1)*4+K ?? ?? ?? ??
?? ?? ?? ?? <- FromPC#CGN
0038+(2*(CN-1)+3)*A+(CN-1)*4+K ?? ?? ?? ??
?? ?? ?? ?? <- ToPC#CGN
0038+(2*CN+2)*A+(CN-1)*4+K ?? ?? ?? ?? <- Count#CGN
We put (for now?) no basic block information in the file since this would
introduce rase conditions among all the processes who want to write them.
`K' is the number of count entries which is computed as
textsize / HISTFRACTION
`CG' in the above table is the number of call graph arcs. Normally,
the table is sparse and the profiling code writes out only the those
entries which are really used in the program run. But since we must
not extend this table (the profiling file) we'll keep them all here.
So CN can be executed in advance as
MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS
Now the remaining question is: how to build the data structures we can
work with from this data. We need the from set and must associate the
froms with all the associated tos. We will do this by constructing this
data structures at the program start. To do this we'll simply visit all
entries in the call graph table and add it to the appropriate list. */
extern int __profile_frequency (void);
/* We define a special type to address the elements of the arc table.
This is basically the `gmon_cg_arc_record' format but it includes
the room for the tag and it uses real types. */
struct here_cg_arc_record
{
uintptr_t from_pc;
uintptr_t self_pc;
uint32_t count;
} __attribute__ ((packed));
static struct here_cg_arc_record *data;
/* Nonzero if profiling is under way. */
static int running;
/* This is the number of entry which have been incorporated in the toset. */
static uint32_t narcs;
/* This is a pointer to the object representing the number of entries
currently in the mmaped file. At no point of time this has to be the
same as NARCS. If it is equal all entries from the file are in our
lists. */
static volatile uint32_t *narcsp;
static volatile uint16_t *kcount;
static size_t kcountsize;
struct here_fromstruct
{
struct here_cg_arc_record volatile *here;
uint16_t link;
};
static volatile uint16_t *tos;
static struct here_fromstruct *froms;
static uint32_t fromlimit;
static volatile uint32_t fromidx;
static uintptr_t lowpc;
static size_t textsize;
static unsigned int hashfraction;
static unsigned int log_hashfraction;
/* Set up profiling data to profile object desribed by MAP. The output
file is found (or created) in OUTPUT_DIR. */
void
internal_function
_dl_start_profile (struct link_map *map, const char *output_dir)
{
char *filename;
int fd;
struct stat64 st;
const ElfW(Phdr) *ph;
ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
ElfW(Addr) mapend = 0;
struct gmon_hdr gmon_hdr;
struct gmon_hist_hdr hist_hdr;
char *hist, *cp, *tmp;
size_t idx;
size_t tossize;
size_t fromssize;
uintptr_t highpc;
struct gmon_hdr *addr = NULL;
off_t expected_size;
/* See profil(2) where this is described. */
int s_scale;
#define SCALE_1_TO_1 0x10000L
/* Compute the size of the sections which contain program code. */
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
{
ElfW(Addr) start = (ph->p_vaddr & ~(_dl_pagesize - 1));
ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
& ~(_dl_pagesize - 1));
if (start < mapstart)
mapstart = start;
if (end > mapend)
mapend = end;
}
/* Now we can compute the size of the profiling data. This is done
with the same formulars as in `monstartup' (see gmon.c). */
running = 0;
lowpc = ROUNDDOWN (mapstart + map->l_addr,
HISTFRACTION * sizeof (HISTCOUNTER));
highpc = ROUNDUP (mapend + map->l_addr,
HISTFRACTION * sizeof (HISTCOUNTER));
textsize = highpc - lowpc;
kcountsize = textsize / HISTFRACTION;
hashfraction = HASHFRACTION;
if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
/* If HASHFRACTION is a power of two, mcount can use shifting
instead of integer division. Precompute shift amount. */
log_hashfraction = ffs (hashfraction * sizeof (*froms)) - 1;
else
log_hashfraction = -1;
tossize = textsize / HASHFRACTION;
fromlimit = textsize * ARCDENSITY / 100;
if (fromlimit < MINARCS)
fromlimit = MINARCS;
if (fromlimit > MAXARCS)
fromlimit = MAXARCS;
fromssize = fromlimit * sizeof (struct here_fromstruct);
expected_size = (sizeof (struct gmon_hdr)
+ 4 + sizeof (struct gmon_hist_hdr) + kcountsize
+ 4 + 4 + fromssize * sizeof (struct here_cg_arc_record));
/* Create the gmon_hdr we expect or write. */
memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
*(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION;
/* Create the hist_hdr we expect or write. */
*(char **) hist_hdr.low_pc = (char *) mapstart;
*(char **) hist_hdr.high_pc = (char *) mapend;
*(int32_t *) hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER);
*(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
hist_hdr.dimen_abbrev = 's';
/* First determine the output name. We write in the directory
OUTPUT_DIR and the name is composed from the shared objects
soname (or the file name) and the ending ".profile". */
filename = (char *) alloca (strlen (output_dir) + 1 + strlen (_dl_profile)
+ sizeof ".profile");
cp = strcpy (filename, output_dir);
cp += strlen (output_dir);
*cp++ = '/';
tmp = strcpy (cp, _dl_profile);
tmp += strlen (_dl_profile);
strcpy (tmp, ".profile");
#ifdef O_NOFOLLOW
# define EXTRA_FLAGS | O_NOFOLLOW
#else
# define EXTRA_FLAGS
#endif
fd = __open (filename, O_RDWR | O_CREAT EXTRA_FLAGS);
if (fd == -1)
{
/* We cannot write the profiling data so don't do anything. */
char buf[400];
_dl_error_printf ("%s: cannot open file: %s\n", filename,
__strerror_r (errno, buf, sizeof buf));
return;
}
if (fstat64 (fd, &st) < 0 || !S_ISREG (st.st_mode))
{
/* Not stat'able or not a regular file => don't use it. */
char buf[400];
int errnum = errno;
__close (fd);
_dl_error_printf ("%s: cannot stat file: %s\n", filename,
__strerror_r (errnum, buf, sizeof buf));
return;
}
/* Test the size. If it does not match what we expect from the size
values in the map MAP we don't use it and warn the user. */
if (st.st_size == 0)
{
/* We have to create the file. */
char buf[_dl_pagesize];
memset (buf, '\0', _dl_pagesize);
if (__lseek (fd, expected_size & ~(_dl_pagesize - 1), SEEK_SET) == -1)
{
char buf[400];
int errnum;
cannot_create:
errnum = errno;
__close (fd);
_dl_error_printf ("%s: cannot create file: %s\n", filename,
__strerror_r (errnum, buf, sizeof buf));
return;
}
if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
& (_dl_pagesize - 1))))
< 0)
goto cannot_create;
}
else if (st.st_size != expected_size)
{
__close (fd);
wrong_format:
if (addr != NULL)
__munmap ((void *) addr, expected_size);
_dl_error_printf ("%s: file is no correct profile data file for `%s'\n",
filename, _dl_profile);
return;
}
addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FILE, fd, 0);
if (addr == (struct gmon_hdr *) MAP_FAILED)
{
char buf[400];
int errnum = errno;
__close (fd);
_dl_error_printf ("%s: cannot map file: %s\n", filename,
__strerror_r (errnum, buf, sizeof buf));
return;
}
/* We don't need the file desriptor anymore. */
__close (fd);
/* Pointer to data after the header. */
hist = (char *) (addr + 1);
kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t)
+ sizeof (struct gmon_hist_hdr));
/* Compute pointer to array of the arc information. */
narcsp = (uint32_t *) ((char *) kcount + kcountsize + sizeof (uint32_t));
data = (struct here_cg_arc_record *) ((char *) narcsp + sizeof (uint32_t));
if (st.st_size == 0)
{
/* Create the signature. */
memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));
*(uint32_t *) hist = GMON_TAG_TIME_HIST;
memcpy (hist + sizeof (uint32_t), &hist_hdr,
sizeof (struct gmon_hist_hdr));
narcsp[-1] = GMON_TAG_CG_ARC;
}
else
{
/* Test the signature in the file. */
if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
|| *(uint32_t *) hist != GMON_TAG_TIME_HIST
|| memcmp (hist + sizeof (uint32_t), &hist_hdr,
sizeof (struct gmon_hist_hdr)) != 0
|| narcsp[-1] != GMON_TAG_CG_ARC)
goto wrong_format;
}
/* Allocate memory for the froms data and the pointer to the tos records. */
tos = (uint16_t *) calloc (tossize + fromssize, 1);
if (tos == NULL)
{
__munmap ((void *) addr, expected_size);
_dl_fatal_printf ("Out of memory while initializing profiler\n");
/* NOTREACHED */
}
froms = (struct here_fromstruct *) ((char *) tos + tossize);
fromidx = 0;
/* Now we have to process all the arc count entries. BTW: it is
not critical whether the *NARCSP value changes meanwhile. Before
we enter a new entry in to toset we will check that everything is
available in TOS. This happens in _dl_mcount.
Loading the entries in reverse order should help to get the most
frequently used entries at the front of the list. */
for (idx = narcs = MIN (*narcsp, fromlimit); idx > 0; )
{
size_t to_index;
size_t newfromidx;
--idx;
to_index = (data[idx].self_pc / (hashfraction * sizeof (*tos)));
newfromidx = fromidx++;
froms[newfromidx].here = &data[idx];
froms[newfromidx].link = tos[to_index];
tos[to_index] = newfromidx;
}
/* Setup counting data. */
if (kcountsize < highpc - lowpc)
{
#if 0
s_scale = ((double) kcountsize / (highpc - lowpc)) * SCALE_1_TO_1;
#else
size_t range = highpc - lowpc;
size_t quot = range / kcountsize;
if (quot >= SCALE_1_TO_1)
s_scale = 1;
else if (quot >= SCALE_1_TO_1 / 256)
s_scale = SCALE_1_TO_1 / quot;
else if (range > ULONG_MAX / 256)
s_scale = (SCALE_1_TO_1 * 256) / (range / (kcountsize / 256));
else
s_scale = (SCALE_1_TO_1 * 256) / ((range * 256) / kcountsize);
#endif
}
else
s_scale = SCALE_1_TO_1;
/* Start the profiler. */
profil ((void *) kcount, kcountsize, lowpc, s_scale);
/* Turn on profiling. */
running = 1;
}
void
_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
{
volatile uint16_t *topcindex;
size_t i, fromindex;
struct here_fromstruct *fromp;
if (! running)
return;
/* Compute relative addresses. The shared object can be loaded at
any address. The value of frompc could be anything. We cannot
restrict it in any way, just set to a fixed value (0) in case it
is outside the allowed range. These calls show up as calls from
<external> in the gprof output. */
frompc -= lowpc;
if (frompc >= textsize)
frompc = 0;
selfpc -= lowpc;
if (selfpc >= textsize)
goto done;
/* Getting here we now have to find out whether the location was
already used. If yes we are lucky and only have to increment a
counter (this also has to be atomic). If the entry is new things
are getting complicated... */
/* Avoid integer divide if possible. */
if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
i = selfpc >> log_hashfraction;
else
i = selfpc / (hashfraction * sizeof (*tos));
topcindex = &tos[i];
fromindex = *topcindex;
if (fromindex == 0)
goto check_new_or_add;
fromp = &froms[fromindex];
/* We have to look through the chain of arcs whether there is already
an entry for our arc. */
while (fromp->here->from_pc != frompc)
{
if (fromp->link != 0)
do
fromp = &froms[fromp->link];
while (fromp->link != 0 && fromp->here->from_pc != frompc);
if (fromp->here->from_pc != frompc)
{
topcindex = &fromp->link;
check_new_or_add:
/* Our entry is not among the entries we read so far from the
data file. Now see whether we have to update the list. */
while (narcs != *narcsp && narcs < fromlimit)
{
size_t to_index;
size_t newfromidx;
to_index = (data[narcs].self_pc
/ (hashfraction * sizeof (*tos)));
newfromidx = exchange_and_add (&fromidx, 1) + 1;
froms[newfromidx].here = &data[narcs];
froms[newfromidx].link = tos[to_index];
tos[to_index] = newfromidx;
atomic_add (&narcs, 1);
}
/* If we still have no entry stop searching and insert. */
if (*topcindex == 0)
{
uint32_t newarc = exchange_and_add (narcsp, 1);
/* In rare cases it could happen that all entries in FROMS are
occupied. So we cannot count this anymore. */
if (newarc >= fromlimit)
goto done;
*topcindex = exchange_and_add (&fromidx, 1) + 1;
fromp = &froms[*topcindex];
fromp->here = &data[newarc];
data[newarc].from_pc = frompc;
data[newarc].self_pc = selfpc;
data[newarc].count = 0;
fromp->link = 0;
atomic_add (&narcs, 1);
break;
}
fromp = &froms[*topcindex];
}
else
/* Found in. */
break;
}
/* Increment the counter. */
atomic_add (&fromp->here->count, 1);
done:
;
}

View File

@ -0,0 +1,43 @@
/* Helper definitions for profiling of shared libraries.
Copyright (C) 1998, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <dlfcn.h>
#include <elf.h>
#include <ldsodefs.h>
#include <libc-symbols.h>
/* This is the map for the shared object we profile. It is defined here
only because we test for this value being NULL or not. */
extern struct link_map *_dl_profile_map;
void
_dl_mcount_wrapper (void *selfpc)
{
_dl_mcount ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc);
}
void
_dl_mcount_wrapper_check (void *selfpc)
{
if (_dl_profile_map != NULL)
_dl_mcount ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc);
}

View File

@ -0,0 +1,213 @@
/* Relocate a shared object and resolve its references to other loaded objects.
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <libintl.h>
#include <stdlib.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/types.h>
#include "dynamic-link.h"
/* Statistics function. */
unsigned long int _dl_num_cache_relocations;
void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int lazy, int consider_profiling)
{
struct textrels
{
caddr_t start;
size_t len;
int prot;
struct textrels *next;
} *textrels = NULL;
/* Initialize it to make the compiler happy. */
const char *errstring = NULL;
if (l->l_relocated)
return;
/* If DT_BIND_NOW is set relocate all references in this object. We
do not do this if we are profiling, of course. */
if (!consider_profiling
&& __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
lazy = 0;
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_RELOC, 0))
_dl_printf ("\nrelocation processing: %s%s\n",
l->l_name[0] ? l->l_name : _dl_argv[0], lazy ? " (lazy)" : "");
/* DT_TEXTREL is now in level 2 and might phase out at some time.
But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
testing easier and therefore it will be available at all time. */
if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
{
/* Bletch. We must make read-only segments writable
long enough to relocate them. */
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)
{
struct textrels *newp;
newp = (struct textrels *) alloca (sizeof (*newp));
newp->len = (((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
& ~(_dl_pagesize - 1))
- (ph->p_vaddr & ~(_dl_pagesize - 1)));
newp->start = ((ph->p_vaddr & ~(_dl_pagesize - 1))
+ (caddr_t) l->l_addr);
if (mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
{
errstring = N_("cannot make segment writable for relocation");
call_error:
_dl_signal_error (errno, l->l_name, NULL, errstring);
}
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
newp->prot = (PF_TO_PROT
>> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
#else
newp->prot = 0;
if (ph->p_flags & PF_R)
newp->prot |= PROT_READ;
if (ph->p_flags & PF_W)
newp->prot |= PROT_WRITE;
if (ph->p_flags & PF_X)
newp->prot |= PROT_EXEC;
#endif
newp->next = textrels;
textrels = newp;
}
}
{
/* Do the actual relocation of the object's GOT and other data. */
/* String table object symbols. */
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
#define RESOLVE_MAP(ref, version, r_type) \
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
&& elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
? (++_dl_num_cache_relocations, \
(*ref) = l->l_lookup_cache.ret, \
l->l_lookup_cache.value) \
: ({ lookup_t _lr; \
int _tc = elf_machine_type_class (r_type); \
l->l_lookup_cache.type_class = _tc; \
l->l_lookup_cache.sym = (*ref); \
_lr = ((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
l, (ref), scope, \
(version), _tc, 0) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
scope, _tc, 0)); \
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l)
#define RESOLVE(ref, version, r_type) \
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
&& elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
? (++_dl_num_cache_relocations, \
(*ref) = l->l_lookup_cache.ret, \
l->l_lookup_cache.value) \
: ({ lookup_t _lr; \
int _tc = elf_machine_type_class (r_type); \
l->l_lookup_cache.type_class = _tc; \
l->l_lookup_cache.sym = (*ref); \
_lr = ((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
l, (ref), scope, \
(version), _tc, 0) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
scope, _tc, 0)); \
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l->l_addr)
#include "dynamic-link.h"
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
if (__builtin_expect (consider_profiling, 0))
{
/* Allocate the array which will contain the already found
relocations. If the shared object lacks a PLT (for example
if it only contains lead function) the l_info[DT_PLTRELSZ]
will be NULL. */
if (l->l_info[DT_PLTRELSZ] == NULL)
{
errstring = N_("%s: profiler found no PLTREL in object %s\n");
fatal:
_dl_fatal_printf (errstring,
_dl_argv[0] ?: "<program name unknown>",
l->l_name);
}
l->l_reloc_result =
(ElfW(Addr) *) calloc (sizeof (ElfW(Addr)),
l->l_info[DT_PLTRELSZ]->d_un.d_val);
if (l->l_reloc_result == NULL)
{
errstring = N_("\
%s: profiler out of memory shadowing PLTREL of %s\n");
goto fatal;
}
}
}
/* Mark the object so we know this work has been done. */
l->l_relocated = 1;
/* Undo the segment protection changes. */
while (__builtin_expect (textrels != NULL, 0))
{
if (mprotect (textrels->start, textrels->len, textrels->prot) < 0)
{
errstring = N_("cannot restore segment prot after reloc");
goto call_error;
}
textrels = textrels->next;
}
}
void
internal_function
_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
{
/* XXX We cannot translate these messages. */
static const char msg[2][32] = { "unexpected reloc type",
"unexpected PLT reloc type" };
char msgbuf[sizeof (msg[0])];
strcpy (msgbuf, msg[plt]);
_dl_signal_error (0, map->l_name, NULL, msgbuf);
}

View File

@ -0,0 +1,231 @@
/* On-demand PLT fixup for shared objects.
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <alloca.h>
#include <stdlib.h>
#include <unistd.h>
#include <ldsodefs.h>
#include "dynamic-link.h"
#define __attribute_used__
#if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
# define PLTREL ElfW(Rela)
#else
# define PLTREL ElfW(Rel)
#endif
#ifndef VERSYMIDX
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
#endif
/* This function is called through a special trampoline from the PLT the
first time each PLT entry is called. We must perform the relocation
specified in the PLT of the given shared object, and return the resolved
function address to the trampoline, which will restart the original call
to that address. Future calls will bounce directly from the PLT to the
function. */
#ifndef ELF_MACHINE_NO_PLT
static ElfW(Addr) __attribute_used__
fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
# endif
/* GKM FIXME: Fix trampoline to pass bounds so we can do
without the `__unbounded' qualifier. */
struct link_map *__unbounded l, ElfW(Word) reloc_offset)
{
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
const PLTREL *const reloc
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
lookup_t result;
ElfW(Addr) value;
/* The use of `alloca' here looks ridiculous but it helps. The goal is
to prevent the function from being inlined and thus optimized out.
There is no official way to do this so we use this trick. gcc never
inlines functions which use `alloca'. */
alloca (sizeof (int));
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
/* Look up the target symbol. If the normal lookup rules are not
used don't look in the global scope. */
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
default:
{
const ElfW(Half) *vernum =
(const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
const struct r_found_version *version = &l->l_versions[ndx];
if (version->hash != 0)
{
result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
l, &sym, l->l_scope,
version,
ELF_RTYPE_CLASS_PLT, 0);
break;
}
}
case 0:
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
}
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
value = l->l_addr + sym->st_value;
#ifdef DL_LOOKUP_RETURNS_MAP
result = l;
#endif
}
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);
/* Finally, fix up the plt itself. */
if (__builtin_expect (_dl_bind_not, 0))
return value;
return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
}
#endif
#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
static ElfW(Addr) __attribute_used__
profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
#endif
struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
ElfW(Addr) *resultp;
lookup_t result;
ElfW(Addr) value;
/* The use of `alloca' here looks ridiculous but it helps. The goal is
to prevent the function from being inlined, and thus optimized out.
There is no official way to do this so we use this trick. gcc never
inlines functions which use `alloca'. */
alloca (sizeof (int));
/* This is the address in the array where we store the result of previous
relocations. */
resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
value = *resultp;
if (value == 0)
{
/* This is the first time we have to relocate this object. */
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
const PLTREL *const reloc
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
/* Look up the target symbol. If the symbol is marked STV_PROTECTED
don't look in the global scope. */
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
default:
{
const ElfW(Half) *vernum =
(const void *) D_PTR (l,l_info[VERSYMIDX (DT_VERSYM)]);
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
const struct r_found_version *version = &l->l_versions[ndx];
if (version->hash != 0)
{
result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
l, &sym, l->l_scope,
version,
ELF_RTYPE_CLASS_PLT,
0);
break;
}
}
case 0:
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
}
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
value = l->l_addr + sym->st_value;
#ifdef DL_LOOKUP_RETURNS_MAP
result = l;
#endif
}
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);
/* Store the result for later runs. */
if (__builtin_expect (! _dl_bind_not, 1))
*resultp = value;
}
(*mcount_fct) (retaddr, value);
return value;
}
#endif /* PROF && ELF_MACHINE_NO_PLT */
/* This macro is defined in dl-machine.h to define the entry point called
by the PLT. The `fixup' function above does the real work, but a little
more twiddling is needed to get the stack right and jump to the address
finally resolved. */
ELF_MACHINE_RUNTIME_TRAMPOLINE

View File

@ -0,0 +1,184 @@
/* Support for dynamic linking code in static libc.
Copyright (C) 1996, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* 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. */
#include <errno.h>
#include <libintl.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <pthread.h>
#include <ldsodefs.h>
#include <machine/dl-machine.h>
#include <dl-librecon.h>
#include <unsecvars.h>
#include <machine/hp-timing.h>
char *__progname = "newlib";
char **_dl_argv = &__progname; /* This is checked for some error messages. */
/* Name of the architecture. */
const char *_dl_platform;
size_t _dl_platformlen;
int _dl_debug_mask;
int _dl_lazy;
/* XXX I know about at least one case where we depend on the old weak
behavior (it has to do with librt). Until we get DSO groups implemented
we have to make this the default. Bummer. --drepper */
#if 0
int _dl_dynamic_weak;
#else
int _dl_dynamic_weak = 1;
#endif
/* If nonzero print warnings about problematic situations. */
int _dl_verbose;
/* Structure to store information about search paths. */
struct r_search_path *_dl_search_paths;
/* We never do profiling. */
const char *_dl_profile;
/* Names of shared object for which the RUNPATHs and RPATHs should be
ignored. */
const char *_dl_inhibit_rpath;
/* The map for the object we will profile. */
struct link_map *_dl_profile_map;
/* This is the address of the last stack address ever used. */
void *__libc_stack_end;
/* Path where the binary is found. */
const char *_dl_origin_path;
/* Nonzero if runtime lookup should not update the .got/.plt. */
int _dl_bind_not;
/* Initially empty list of loaded objects. */
struct link_map *_dl_loaded;
/* Number of object in the _dl_loaded list. */
unsigned int _dl_nloaded;
/* Fake scope. In dynamically linked binaries this is the scope of the
main application but here we don't have something like this. So
create a fake scope containing nothing. */
struct r_scope_elem _dl_initial_searchlist;
/* Variable which can be used in lookup to process the global scope. */
struct r_scope_elem *_dl_global_scope[2] = { &_dl_initial_searchlist, NULL };
/* This is a global pointer to this structure which is public. It is
used by dlopen/dlclose to add and remove objects from what is regarded
to be the global scope. */
struct r_scope_elem *_dl_main_searchlist = &_dl_initial_searchlist;
/* Nonzero during startup. */
int _dl_starting_up = 1;
/* We expect less than a second for relocation. */
#ifdef HP_SMALL_TIMING_AVAIL
# undef HP_TIMING_AVAIL
# define HP_TIMING_AVAIL HP_SMALL_TIMING_AVAIL
#endif
/* Initial value of the CPU clock. */
#ifndef HP_TIMING_NONAVAIL
hp_timing_t _dl_cpuclock_offset;
#endif
/* During the program run we must not modify the global data of
loaded shared object simultanously in two threads. Therefore we
protect `_dl_open' and `_dl_close' in dl-close.c.
This must be a recursive lock since the initializer function of
the loaded object might as well require a call to this function.
At this time it is not anymore a problem to modify the tables. */
__LOCK_RECURSIVE_INIT (, _dl_load_lock)
#ifdef HAVE_AUX_VECTOR
extern int _dl_clktck;
void
internal_function
_dl_aux_init (ElfW(auxv_t) *av)
{
for (; av->a_type != AT_NULL; ++av)
switch (av->a_type)
{
case AT_PAGESZ:
_dl_pagesize = av->a_un.a_val;
break;
case AT_CLKTCK:
_dl_clktck = av->a_un.a_val;
break;
}
}
#endif
void non_dynamic_init (void) __attribute__ ((unused));
void
non_dynamic_init (void)
{
if (HP_TIMING_AVAIL)
HP_TIMING_NOW (_dl_cpuclock_offset);
if (!_dl_pagesize)
_dl_pagesize = __getpagesize ();
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
/* Initialize the data structures for the search paths for shared
objects. */
_dl_init_paths (getenv ("LD_LIBRARY_PATH"));
_dl_lazy = *(getenv ("LD_BIND_NOW") ?: "") == '\0';
_dl_bind_not = *(getenv ("LD_BIND_NOT") ?: "") != '\0';
_dl_dynamic_weak = *(getenv ("LD_DYNAMIC_WEAK") ?: "") == '\0';
#ifdef DL_PLATFORM_INIT
DL_PLATFORM_INIT;
#endif
/* Now determine the length of the platform string. */
if (_dl_platform != NULL)
_dl_platformlen = strlen (_dl_platform);
}
text_set_element (__libc_subinit, non_dynamic_init);
const struct r_strlenpair *
internal_function
_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
size_t *max_capstrlen)
{
static struct r_strlenpair result;
static char buf[1];
result.str = buf; /* Does not really matter. */
result.len = 0;
*sz = 1;
return &result;
}

View File

@ -0,0 +1,158 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stddef.h>
#include <setjmp.h>
#include <libintl.h>
#include <dlfcn.h>
#include <ldsodefs.h>
#include <dl-hash.h>
void *
internal_function
_dl_sym (void *handle, const char *name, void *who)
{
const ElfW(Sym) *ref = NULL;
lookup_t result;
ElfW(Addr) caller = (ElfW(Addr)) who;
struct link_map *match;
struct link_map *l;
/* If the address is not recognized the call comes from the main
program (we hope). */
match = _dl_loaded;
/* Find the highest-addressed object that CALLER is not below. */
for (l = _dl_loaded; l != NULL; l = l->l_next)
if (caller >= l->l_map_start && caller < l->l_map_end)
{
/* There must be exactly one DSO for the range of the virtual
memory. Otherwise something is really broken. */
match = l;
break;
}
if (handle == RTLD_DEFAULT)
/* Search the global scope as seen in the caller object. */
result = _dl_lookup_symbol (name, match, &ref, match->l_scope, 0, 0);
else
{
if (handle != RTLD_NEXT)
{
/* Search the scope of the given object. */
struct link_map *map = handle;
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
0, 1);
}
else
{
if (__builtin_expect (match == _dl_loaded, 0))
{
if (! _dl_loaded
|| caller < _dl_loaded->l_map_start
|| caller >= _dl_loaded->l_map_end)
_dl_signal_error (0, NULL, NULL, N_("\
RTLD_NEXT used in code not dynamically loaded"));
}
l = match;
while (l->l_loader != NULL)
l = l->l_loader;
result = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
match);
}
}
if (ref != NULL)
return DL_SYMBOL_ADDRESS (result, ref);
return NULL;
}
void *
internal_function
_dl_vsym (void *handle, const char *name, const char *version, void *who)
{
const ElfW(Sym) *ref = NULL;
struct r_found_version vers;
lookup_t result;
ElfW(Addr) caller = (ElfW(Addr)) who;
struct link_map *match;
struct link_map *l;
/* Compute hash value to the version string. */
vers.name = version;
vers.hidden = 1;
vers.hash = _dl_elf_hash (version);
/* We don't have a specific file where the symbol can be found. */
vers.filename = NULL;
/* If the address is not recognized the call comes from the main
program (we hope). */
match = _dl_loaded;
/* Find the highest-addressed object that CALLER is not below. */
for (l = _dl_loaded; l != NULL; l = l->l_next)
if (caller >= l->l_map_start && caller < l->l_map_end)
{
/* There must be exactly one DSO for the range of the virtual
memory. Otherwise something is really broken. */
match = l;
break;
}
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
result = _dl_lookup_versioned_symbol (name, match, &ref, match->l_scope,
&vers, 0, 0);
else if (handle == RTLD_NEXT)
{
if (__builtin_expect (match == _dl_loaded, 0))
{
if (! _dl_loaded
|| caller < _dl_loaded->l_map_start
|| caller >= _dl_loaded->l_map_end)
_dl_signal_error (0, NULL, NULL, N_("\
RTLD_NEXT used in code not dynamically loaded"));
}
l = match;
while (l->l_loader != NULL)
l = l->l_loader;
result = _dl_lookup_versioned_symbol_skip (name, l, &ref,
l->l_local_scope,
&vers, match);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
result = _dl_lookup_versioned_symbol (name, map, &ref,
map->l_local_scope, &vers, 0, 1);
}
if (ref != NULL)
return DL_SYMBOL_ADDRESS (result, ref);
return NULL;
}

View File

@ -0,0 +1,385 @@
/* Handle symbol and library versioning.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <elf.h>
#include <errno.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <ldsodefs.h>
#include <assert.h>
#ifndef VERSYMIDX
# define VERSYMIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
#endif
#define make_string(string, rest...) \
({ \
const char *all[] = { string, ## rest }; \
size_t len, cnt; \
char *result, *cp; \
\
len = 1; \
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
len += strlen (all[cnt]); \
\
cp = result = alloca (len); \
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
{ \
cp = strcpy (cp, all[cnt]); \
cp += strlen (all[cnt]); \
} \
\
result; \
})
static inline struct link_map *
find_needed (const char *name, struct link_map *map)
{
struct link_map *tmap;
unsigned int n;
for (tmap = _dl_loaded; tmap != NULL; tmap = tmap->l_next)
if (_dl_name_match_p (name, tmap))
return tmap;
/* The required object is not in the global scope, look to see if it is
a dependency of the current object. */
for (n = 0; n < map->l_searchlist.r_nlist; n++)
if (_dl_name_match_p (name, map->l_searchlist.r_list[n]))
return map->l_searchlist.r_list[n];
/* Should never happen. */
return NULL;
}
static int
internal_function
match_symbol (const char *name, ElfW(Word) hash, const char *string,
struct link_map *map, int verbose, int weak)
{
const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
ElfW(Addr) def_offset;
ElfW(Verdef) *def;
/* Initialize to make the compiler happy. */
const char *errstring = NULL;
int result = 0;
/* Display information about what we are doing while debugging. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_VERSIONS, 0))
_dl_debug_printf ("\
checking for version `%s' in file %s required by file %s\n",
string, map->l_name[0] ? map->l_name : _dl_argv[0],
name);
if (__builtin_expect (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL, 0))
{
/* The file has no symbol versioning. I.e., the dependent
object was linked against another version of this file. We
only print a message if verbose output is requested. */
if (verbose)
{
/* XXX We cannot translate the messages. */
errstring = make_string ("\
no version information available (required by ", name, ")");
goto call_cerror;
}
return 0;
}
def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr;
assert (def_offset != 0);
def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset);
while (1)
{
/* Currently the version number of the definition entry is 1.
Make sure all we see is this version. */
if (__builtin_expect (def->vd_version, 1) != 1)
{
char buf[20];
buf[sizeof (buf) - 1] = '\0';
/* XXX We cannot translate the message. */
errstring = make_string ("unsupported version of Verdef record");
result = 1;
goto call_cerror;
}
/* Compare the hash values. */
if (hash == def->vd_hash)
{
ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux);
/* To be safe, compare the string as well. */
if (__builtin_expect (strcmp (string, strtab + aux->vda_name), 0)
== 0)
/* Bingo! */
return 0;
}
/* If no more definitions we failed to find what we want. */
if (def->vd_next == 0)
break;
/* Next definition. */
def = (ElfW(Verdef) *) ((char *) def + def->vd_next);
}
/* Symbol not found. If it was a weak reference it is not fatal. */
if (__builtin_expect (weak, 1))
{
if (verbose)
{
/* XXX We cannot translate the message. */
errstring = make_string ("weak version `", string,
"' not found (required by ", name, ")");
goto call_cerror;
}
return 0;
}
/* XXX We cannot translate the message. */
errstring = make_string ("version `", string, "' not found (required by ",
name, ")");
result = 1;
call_cerror:
_dl_signal_cerror (0, map->l_name[0] ? map->l_name : _dl_argv[0], NULL,
errstring);
return result;
}
int
internal_function
_dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
{
int result = 0;
const char *strtab;
/* Pointer to section with needed versions. */
ElfW(Dyn) *dyn;
/* Pointer to dynamic section with definitions. */
ElfW(Dyn) *def;
/* We need to find out which is the highest version index used
in a dependecy. */
unsigned int ndx_high = 0;
/* Initialize to make the compiler happy. */
const char *errstring = NULL;
int errval = 0;
/* If we don't have a string table, we must be ok. */
if (map->l_info[DT_STRTAB] == NULL)
return 0;
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
dyn = map->l_info[VERSYMIDX (DT_VERNEED)];
def = map->l_info[VERSYMIDX (DT_VERDEF)];
if (dyn != NULL)
{
/* This file requires special versions from its dependencies. */
ElfW(Verneed) *ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
/* Currently the version number of the needed entry is 1.
Make sure all we see is this version. */
if (__builtin_expect (ent->vn_version, 1) != 1)
{
char buf[20];
buf[sizeof (buf) - 1] = '\0';
/* XXX We cannot translate the message. */
errstring = make_string ("unsupported version of Verneed record\n");
call_error:
_dl_signal_error (errval, (*map->l_name ? map->l_name : _dl_argv[0]),
NULL, errstring);
}
while (1)
{
ElfW(Vernaux) *aux;
struct link_map *needed = find_needed (strtab + ent->vn_file, map);
/* If NEEDED is NULL this means a dependency was not found
and no stub entry was created. This should never happen. */
assert (needed != NULL);
/* Make sure this is no stub we created because of a missing
dependency. */
if (__builtin_expect (! trace_mode, 1)
|| ! __builtin_expect (needed->l_faked, 0))
{
/* NEEDED is the map for the file we need. Now look for the
dependency symbols. */
aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
while (1)
{
/* Match the symbol. */
result |= match_symbol ((*map->l_name
? map->l_name : _dl_argv[0]),
aux->vna_hash,
strtab + aux->vna_name,
needed, verbose,
aux->vna_flags & VER_FLG_WEAK);
/* Compare the version index. */
if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
ndx_high = aux->vna_other & 0x7fff;
if (aux->vna_next == 0)
/* No more symbols. */
break;
/* Next symbol. */
aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
}
}
if (ent->vn_next == 0)
/* No more dependencies. */
break;
/* Next dependency. */
ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
}
}
/* We also must store the names of the defined versions. Determine
the maximum index here as well.
XXX We could avoid the loop by just taking the number of definitions
as an upper bound of new indeces. */
if (def != NULL)
{
ElfW(Verdef) *ent;
ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
while (1)
{
if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high)
ndx_high = ent->vd_ndx & 0x7fff;
if (ent->vd_next == 0)
/* No more definitions. */
break;
ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
}
}
if (ndx_high > 0)
{
/* Now we are ready to build the array with the version names
which can be indexed by the version index in the VERSYM
section. */
map->l_versions = (struct r_found_version *)
calloc (ndx_high + 1, sizeof (*map->l_versions));
if (__builtin_expect (map->l_versions == NULL, 0))
{
errstring = N_("cannot allocate version reference table");
errval = ENOMEM;
goto call_error;
}
/* Store the number of available symbols. */
map->l_nversions = ndx_high + 1;
/* Compute the pointer to the version symbols. */
map->l_versyms = (void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
if (dyn != NULL)
{
ElfW(Verneed) *ent;
ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
while (1)
{
ElfW(Vernaux) *aux;
aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
while (1)
{
ElfW(Half) ndx = aux->vna_other & 0x7fff;
map->l_versions[ndx].hash = aux->vna_hash;
map->l_versions[ndx].hidden = aux->vna_other & 0x8000;
map->l_versions[ndx].name = &strtab[aux->vna_name];
map->l_versions[ndx].filename = &strtab[ent->vn_file];
if (aux->vna_next == 0)
/* No more symbols. */
break;
/* Advance to next symbol. */
aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
}
if (ent->vn_next == 0)
/* No more dependencies. */
break;
/* Advance to next dependency. */
ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
}
}
/* And insert the defined versions. */
if (def != NULL)
{
ElfW(Verdef) *ent;
ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
while (1)
{
ElfW(Verdaux) *aux;
aux = (ElfW(Verdaux) *) ((char *) ent + ent->vd_aux);
if ((ent->vd_flags & VER_FLG_BASE) == 0)
{
/* The name of the base version should not be
available for matching a versioned symbol. */
ElfW(Half) ndx = ent->vd_ndx & 0x7fff;
map->l_versions[ndx].hash = ent->vd_hash;
map->l_versions[ndx].name = &strtab[aux->vda_name];
map->l_versions[ndx].filename = NULL;
}
if (ent->vd_next == 0)
/* No more definitions. */
break;
ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
}
}
}
return result;
}
int
internal_function
_dl_check_all_versions (struct link_map *map, int verbose, int trace_mode)
{
struct link_map *l;
int result = 0;
for (l = map; l != NULL; l = l->l_next)
result |= ! l->l_faked && _dl_check_map_versions (l, verbose, trace_mode);
return result;
}

View File

@ -0,0 +1,84 @@
/* User functions for run-time dynamic loading.
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _DLFCN_H
#define _DLFCN_H 1
#include <features.h>
/* Collect various system dependent definitions and declarations. */
#include <sys/dlfcn.h>
/* If the first argument of `dlsym' or `dlvsym' is set to RTLD_NEXT
the run-time address of the symbol called NAME in the next shared
object is returned. The "next" relation is defined by the order
the shared objects were loaded. */
# define RTLD_NEXT ((void *) -1l)
/* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT
the run-time address of the symbol called NAME in the global scope
is returned. */
# define RTLD_DEFAULT ((void *) 0)
__BEGIN_DECLS
/* 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, int __mode) __THROW;
/* Unmap and close a shared object opened by `dlopen'.
The handle cannot be used again after calling `dlclose'. */
extern int dlclose (void *__handle) __THROW;
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME. */
extern void *dlsym (void *__restrict __handle,
__const char *__restrict __name) __THROW;
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME with VERSION. */
extern void *dlvsym (void *__restrict __handle,
__const char *__restrict __name,
__const char *__restrict __version) __THROW;
/* When any of the above functions fails, call this function
to return a string describing the error. Each call resets
the error string so that a following call returns null. */
extern char *dlerror (void) __THROW;
/* Structure containing information about object searched using
`dladdr'. */
typedef struct
{
__const char *dli_fname; /* File name of defining object. */
void *dli_fbase; /* Load address of that object. */
__const char *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Exact value of nearest symbol. */
} Dl_info;
/* Fill in *INFO with the following information about ADDRESS.
Returns 0 iff no shared object's segments contain that address. */
extern int dladdr (__const void *__address, Dl_info *__info) __THROW;
__END_DECLS
#endif /* dlfcn.h */

View File

@ -0,0 +1,200 @@
/* Look up a symbol in the loaded objects.
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#if VERSIONED
# define FCT do_lookup_versioned
# define ARG const struct r_found_version *const version,
#else
# define FCT do_lookup
# define ARG
#endif
/* Inner part of the lookup functions. We return a value > 0 if we
found the symbol, the value 0 if nothing is found and < 0 if
something bad happened. */
static inline int
FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG
struct link_map *skip, int type_class)
{
struct link_map **list = scope->r_list;
size_t n = scope->r_nlist;
struct link_map *map;
do
{
const ElfW(Sym) *symtab;
const char *strtab;
const ElfW(Half) *verstab;
Elf_Symndx symidx;
const ElfW(Sym) *sym;
#if ! VERSIONED
int num_versions = 0;
const ElfW(Sym) *versioned_sym = NULL;
#endif
map = list[i];
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if (skip != NULL && map == skip)
continue;
/* Don't search the executable when resolving a copy reloc. */
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
continue;
/* Print some debugging info if wanted. */
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_SYMBOLS, 0))
_dl_debug_printf ("symbol=%s; lookup in file=%s\n", undef_name,
map->l_name[0] ? map->l_name : _dl_argv[0]);
symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
verstab = map->l_versyms;
/* 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])
{
sym = &symtab[symidx];
assert (ELF_RTYPE_CLASS_PLT == 1);
if (sym->st_value == 0 || /* No value. */
/* ((type_class & ELF_RTYPE_CLASS_PLT)
&& (sym->st_shndx == SHN_UNDEF)) */
(type_class & (sym->st_shndx == SHN_UNDEF)))
continue;
if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC)
/* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC entries
since these are no code/data definitions. */
continue;
if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
/* Not the symbol we are looking for. */
continue;
#if VERSIONED
if (__builtin_expect (verstab == NULL, 0))
{
/* We need a versioned symbol but haven't found any. If
this is the object which is referenced in the verneed
entry it is a bug in the library since a symbol must
not simply disappear.
It would also be a bug in the object since it means that
the list of required versions is incomplete and so the
tests in dl-version.c haven't found a problem.*/
assert (version->filename == NULL
|| ! _dl_name_match_p (version->filename, map));
/* Otherwise we accept the symbol. */
}
else
{
/* We can match the version information or use the
default one if it is not hidden. */
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if ((map->l_versions[ndx].hash != version->hash
|| strcmp (map->l_versions[ndx].name, version->name))
&& (version->hidden || map->l_versions[ndx].hash
|| (verstab[symidx] & 0x8000)))
/* It's not the version we want. */
continue;
}
#else
/* No specific version is selected. When the object file
also does not define a version we have a match.
Otherwise we accept the default version, or in case there
is only one version defined, this one version. */
if (verstab != NULL)
{
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if (ndx > 2) /* map->l_versions[ndx].hash != 0) */
{
/* Don't accept hidden symbols. */
if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0)
/* No version so far. */
versioned_sym = sym;
continue;
}
}
#endif
/* There cannot be another entry for this symbol so stop here. */
goto found_it;
}
/* If we have seen exactly one versioned symbol while we are
looking for an unversioned symbol and the version is not the
default version we still accept this symbol since there are
no possible ambiguities. */
#if VERSIONED
sym = NULL;
#else
sym = num_versions == 1 ? versioned_sym : NULL;
#endif
if (sym != NULL)
{
found_it:
switch (ELFW(ST_BIND) (sym->st_info))
{
case STB_WEAK:
/* Weak definition. Use this value if we don't find another. */
if (__builtin_expect (_dl_dynamic_weak, 0))
{
if (! result->s)
{
result->s = sym;
result->m = map;
}
break;
}
/* FALLTHROUGH */
case STB_GLOBAL:
/* Global definition. Just what we need. */
result->s = sym;
result->m = map;
return 1;
default:
/* Local symbols are ignored. */
break;
}
}
#if VERSIONED
/* If this current map is the one mentioned in the verneed entry
and we have not found a weak entry, it is a bug. */
if (symidx == STN_UNDEF && version->filename != NULL
&& __builtin_expect (_dl_name_match_p (version->filename, map), 0))
return -1;
#endif
}
while (++i < n);
/* We have not found anything until now. */
return 0;
}
#undef FCT
#undef ARG
#undef VERSIONED

View File

@ -0,0 +1,118 @@
/* Do relocations for ELF dynamic linking.
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* This file may be included twice, to define both
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
#include <machine/weakalias.h>
#ifdef DO_RELA
# define elf_dynamic_do_rel elf_dynamic_do_rela
# define RELCOUNT_IDX VERSYMIDX (DT_RELACOUNT)
# define Rel Rela
# define elf_machine_rel elf_machine_rela
# define elf_machine_rel_relative elf_machine_rela_relative
#else
# define RELCOUNT_IDX VERSYMIDX (DT_RELCOUNT)
#endif
#ifndef VERSYMIDX
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
#endif
/* Perform the relocations in MAP on the running program image as specified
by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
relocations; they should be set up to call _dl_runtime_resolve, rather
than fully resolved now. */
static inline void
elf_dynamic_do_rel (struct link_map *map,
ElfW(Addr) reladdr, ElfW(Addr) relsize,
int lazy)
{
const ElfW(Rel) *r = (const void *) reladdr;
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
ElfW(Addr) l_addr = map->l_addr;
#ifndef RTLD_BOOTSTRAP
/* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
not clever enough to see through all the function calls to realize
that. */
if (lazy)
{
/* Doing lazy PLT relocations; they need very little info. */
for (; r < end; ++r)
elf_machine_lazy_rel (map, l_addr, r);
}
else
#endif
{
const ElfW(Sym) *const symtab =
(const void *) D_PTR (map, l_info[DT_SYMTAB]);
ElfW(Word) nrelative = (map->l_info[RELCOUNT_IDX] == NULL
? 0 : map->l_info[RELCOUNT_IDX]->d_un.d_val);
const ElfW(Rel) *relative = r;
r = MIN (r + nrelative, end);
#ifndef RTLD_BOOTSTRAP
/* This is defined in rtld.c, but nowhere in the static libc.a; make
the reference weak so static programs can still link. This
declaration cannot be done when compiling rtld.c (i.e. #ifdef
RTLD_BOOTSTRAP) because rtld.c contains the common defn for
_dl_rtld_map, which is incompatible with a weak decl in the same
file. */
weak_extern (_dl_rtld_map);
if (map != &_dl_rtld_map) /* Already done in rtld itself. */
# ifndef DO_RELA
/* Rela platforms get the offset from r_addend and this must
be copied in the relocation address. Therefore we can skip
the relative relocations only if this is for rel
relocations. */
if (l_addr != 0)
# endif
#endif
for (; relative < r; ++relative)
elf_machine_rel_relative (l_addr, relative,
(void *) (l_addr + relative->r_offset));
if (map->l_info[VERSYMIDX (DT_VERSYM)])
{
const ElfW(Half) *const version =
(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
for (; r < end; ++r)
{
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx],
(void *) (l_addr + r->r_offset));
}
}
else
for (; r < end; ++r)
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
(void *) (l_addr + r->r_offset));
}
}
#undef elf_dynamic_do_rel
#undef Rel
#undef elf_machine_rel
#undef elf_machine_rel_relative
#undef RELCOUNT_IDX

View File

@ -0,0 +1,244 @@
/* Inline functions for dynamic linking.
Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <elf.h>
#include <machine/dl-machine.h>
#include <assert.h>
#ifndef VERSYMIDX
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
#endif
/* Global read-only variable defined in rtld.c which is nonzero if we
shall give more warning messages. */
extern int _dl_verbose __attribute__ ((unused));
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
static inline void __attribute__ ((unused))
elf_get_dynamic_info (struct link_map *l)
{
ElfW(Dyn) *dyn = l->l_ld;
ElfW(Addr) l_addr;
ElfW(Dyn) **info;
if (! dyn)
return;
l_addr = l->l_addr;
info = l->l_info;
while (dyn->d_tag != DT_NULL)
{
if (dyn->d_tag < DT_NUM)
info[dyn->d_tag] = dyn;
else if (dyn->d_tag >= DT_LOPROC &&
dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
else if ((Elf32_Word) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
info[VERSYMIDX (dyn->d_tag)] = dyn;
else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+ DT_VERSIONTAGNUM] = dyn;
else
assert (! "bad dynamic tag");
++dyn;
}
#ifndef DL_RO_DYN_SECTION
if (info[DT_PLTGOT] != NULL)
info[DT_PLTGOT]->d_un.d_ptr += l_addr;
if (info[DT_STRTAB] != NULL)
info[DT_STRTAB]->d_un.d_ptr += l_addr;
if (info[DT_SYMTAB] != NULL)
info[DT_SYMTAB]->d_un.d_ptr += l_addr;
# if ! ELF_MACHINE_NO_RELA
if (info[DT_RELA] != NULL)
{
assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
info[DT_RELA]->d_un.d_ptr += l_addr;
}
# endif
# if ! ELF_MACHINE_NO_REL
if (info[DT_REL] != NULL)
{
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
info[DT_REL]->d_un.d_ptr += l_addr;
}
# endif
#endif
if (info[DT_PLTREL] != NULL)
{
# if ELF_MACHINE_NO_RELA
assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
# elif ELF_MACHINE_NO_REL
assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
# else
assert (info[DT_PLTREL]->d_un.d_val == DT_REL
|| info[DT_PLTREL]->d_un.d_val == DT_RELA);
# endif
}
#ifndef DL_RO_DYN_SECTION
if (info[DT_JMPREL] != NULL)
info[DT_JMPREL]->d_un.d_ptr += l_addr;
if (info[VERSYMIDX (DT_VERSYM)] != NULL)
info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
#endif
if (info[DT_FLAGS] != NULL)
{
/* Flags are used. Translate to the old form where available.
Since these l_info entries are only tested for NULL pointers it
is ok if they point to the DT_FLAGS entry. */
ElfW(Word) flags = info[DT_FLAGS]->d_un.d_val;
if (flags & DF_SYMBOLIC)
info[DT_SYMBOLIC] = info[DT_FLAGS];
if (flags & DF_TEXTREL)
info[DT_TEXTREL] = info[DT_FLAGS];
if (flags & DF_BIND_NOW)
info[DT_BIND_NOW] = info[DT_FLAGS];
}
if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
if (info[DT_RUNPATH] != NULL)
/* If both RUNPATH and RPATH are given, the latter is ignored. */
info[DT_RPATH] = NULL;
}
#ifdef RESOLVE
/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
These functions are almost identical, so we use cpp magic to avoid
duplicating their code. It cannot be done in a more general function
because we must be able to completely inline. */
/* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
range. Note that according to the ELF spec, this is completely legal!
But conditionally define things so that on machines we know this will
not happen we do something more optimal. */
# ifdef ELF_MACHINE_PLTREL_OVERLAP
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
do { \
struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \
int ranges_index; \
\
ranges[0].lazy = ranges[2].lazy = 0; \
ranges[1].lazy = 1; \
ranges[0].size = ranges[1].size = ranges[2].size = 0; \
\
if ((map)->l_info[DT_##RELOC]) \
{ \
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
} \
\
if ((do_lazy) \
&& (map)->l_info[DT_PLTREL] \
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
{ \
ranges[1].start = D_PTR ((map), l_info[DT_JMPREL]); \
ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
ranges[2].start = ranges[1].start + ranges[1].size; \
ranges[2].size = ranges[0].start + ranges[0].size - ranges[2].start; \
ranges[0].size = ranges[1].start - ranges[0].start; \
} \
\
for (ranges_index = 0; ranges_index < 3; ++ranges_index) \
elf_dynamic_do_##reloc ((map), \
ranges[ranges_index].start, \
ranges[ranges_index].size, \
ranges[ranges_index].lazy); \
} while (0)
# else
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
do { \
struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \
int ranges_index; \
ranges[0].lazy = 0; \
ranges[0].size = ranges[1].size = 0; \
ranges[0].start = 0; \
\
if ((map)->l_info[DT_##RELOC]) \
{ \
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
} \
if ((map)->l_info[DT_PLTREL] \
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
{ \
ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
\
if ((do_lazy) \
/* This test does not only detect whether the relocation \
sections are in the right order, it also checks whether \
there is a DT_REL/DT_RELA section. */ \
|| ranges[0].start + ranges[0].size != start) \
{ \
ranges[1].start = start; \
ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
ranges[1].lazy = (do_lazy); \
} \
else \
/* Combine processing the sections. */ \
ranges[0].size += (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
} \
\
for (ranges_index = 0; ranges_index < 2; ++ranges_index) \
elf_dynamic_do_##reloc ((map), \
ranges[ranges_index].start, \
ranges[ranges_index].size, \
ranges[ranges_index].lazy); \
} while (0)
# endif
# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
# define _ELF_CHECK_REL 0
# else
# define _ELF_CHECK_REL 1
# endif
# if ! ELF_MACHINE_NO_REL
# include "do-rel.h"
# define ELF_DYNAMIC_DO_REL(map, lazy) \
_ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL)
# else
# define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do. */
# endif
# if ! ELF_MACHINE_NO_RELA
# define DO_RELA
# include "do-rel.h"
# define ELF_DYNAMIC_DO_RELA(map, lazy) \
_ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL)
# else
# define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do. */
# endif
/* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */
# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
do { \
int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
(consider_profile)); \
ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
} while (0)
#endif

View File

@ -0,0 +1,193 @@
/* Set flags signalling availability of kernel features based on given
kernel version number.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* This file must not contain any C code. At least it must be protected
to allow using the file also in assembler files. */
#ifndef __LINUX_KERNEL_VERSION
/* We assume the worst; all kernels should be supported. */
# define __LINUX_KERNEL_VERSION 0
#endif
/* We assume for __LINUX_KERNEL_VERSION the same encoding used in
linux/version.h. I.e., the major, minor, and subminor all get a
byte with the major number being in the highest byte. This means
we can do numeric comparisons.
In the following we will define certain symbols depending on
whether the describes kernel feature is available in the kernel
version given by __LINUX_KERNEL_VERSION. We are not always exactly
recording the correct versions in which the features were
introduced. If somebody cares these values can afterwards be
corrected. Most of the numbers here are set corresponding to
2.2.0. */
/* `getcwd' system call. */
#if __LINUX_KERNEL_VERSION >= 131584
# define __ASSUME_GETCWD_SYSCALL 1
#endif
/* Real-time signal became usable in 2.1.70. */
#if __LINUX_KERNEL_VERSION >= 131398
# define __ASSUME_REALTIME_SIGNALS 1
#endif
/* When were the `pread'/`pwrite' syscalls introduced? */
#if __LINUX_KERNEL_VERSION >= 131584
# define __ASSUME_PREAD_SYSCALL 1
# define __ASSUME_PWRITE_SYSCALL 1
#endif
/* When was `poll' introduced? */
#if __LINUX_KERNEL_VERSION >= 131584
# define __ASSUME_POLL_SYSCALL 1
#endif
/* The `lchown' syscall was introduced in 2.1.80. */
#if __LINUX_KERNEL_VERSION >= 131408
# define __ASSUME_LCHOWN_SYSCALL 1
#endif
/* When did the `setresuid' sysall became available? */
#if __LINUX_KERNEL_VERSION >= 131584 && !defined __sparc__
# define __ASSUME_SETRESUID_SYSCALL 1
#endif
/* The SIOCGIFNAME ioctl is available starting with 2.1.50. */
#if __LINUX_KERNEL_VERSION >= 131408
# define __ASSUME_SIOCGIFNAME 1
#endif
/* On x86 another `getrlimit' syscall was added in 2.3.25. */
#if __LINUX_KERNEL_VERSION >= 131865 && defined __i386__
# define __ASSUME_NEW_GETRLIMIT_SYSCALL 1
#endif
/* On x86 the truncate64/ftruncate64 syscalls were introduced in 2.3.31. */
#if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__
# define __ASSUME_TRUNCATE64_SYSCALL 1
#endif
/* On x86 the mmap2 syscall was introduced in 2.3.31. */
#if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__
# define __ASSUME_MMAP2_SYSCALL 1
#endif
/* On x86 the stat64/lstat64/fstat64 syscalls were introduced in 2.3.34. */
#if __LINUX_KERNEL_VERSION >= 131874 && defined __i386__
# define __ASSUME_STAT64_SYSCALL 1
#endif
/* On sparc and ARM the truncate64/ftruncate64/mmap2/stat64/lstat64/fstat64
syscalls were introduced in 2.3.35. */
#if __LINUX_KERNEL_VERSION >= 131875 && (defined __sparc__ || defined __arm__)
# define __ASSUME_TRUNCATE64_SYSCALL 1
# define __ASSUME_MMAP2_SYSCALL 1
# define __ASSUME_STAT64_SYSCALL 1
#endif
/* I know for sure that these are in 2.3.35 on powerpc. */
#if __LINUX_KERNEL_VERSION >= 131875 && defined __powerpc__
# define __ASSUME_TRUNCATE64_SYSCALL 1
# define __ASSUME_STAT64_SYSCALL 1
# define __ASSUME_NEW_GETRLIMIT_SYSCALL 1
#endif
/* Linux 2.3.39 introduced 32bit UID/GIDs and IPC64. Some platforms had 32
bit type all along. */
#if __LINUX_KERNEL_VERSION >= 131879 || defined __powerpc__ || defined __mips__
# define __ASSUME_32BITUIDS 1
# ifndef __powerpc__
# define __ASSUME_IPC64 1
# endif
# ifdef __sparc__
# define __ASSUME_SETRESUID_SYSCALL 1
# endif
#endif
/* Linux 2.4.0 on PPC introduced a correct IPC64. */
#if __LINUX_KERNEL_VERSION >= 132096 && defined __powerpc__
# define __ASSUME_IPC64 1
#endif
/* We can use the LDTs for threading with Linux 2.3.99 and newer. */
#if __LINUX_KERNEL_VERSION >= 131939
# define __ASSUME_LDT_WORKS 1
#endif
/* The changed st_ino field appeared in 2.4.0-test6. But we cannot
distinguish this version from other 2.4.0 releases. Therefore play
save and assume it available is for 2.4.1 and up. */
#if __LINUX_KERNEL_VERSION >= 132097
# define __ASSUME_ST_INO_64_BIT 1
#endif
/* To support locking of large files a new fcntl() syscall was introduced
in 2.4.0-test7. We test for 2.4.1 for the earliest version we know
the syscall is available. */
#if __LINUX_KERNEL_VERSION >= 132097 && (defined __i386__ || defined __sparc__)
# define __ASSUME_FCNTL64 1
#endif
/* Arm got fcntl64 in 2.4.4, PowerPC and SH have it also in 2.4.4 (I
don't know when it got introduced). */
#if __LINUX_KERNEL_VERSION >= 132100 \
&& (defined __arm__ || defined __powerpc__ || defined __sh__)
# define __ASSUME_FCNTL64 1
#endif
/* The getdents64 syscall was introduced in 2.4.0-test7. We test for
2.4.1 for the earliest version we know the syscall is available. */
#if __LINUX_KERNEL_VERSION >= 132097
# define __ASSUME_GETDENTS64_SYSCALL 1
#endif
/* When did O_DIRECTORY became available? Early in 2.3 but when?
Be safe, use 2.3.99. */
#if __LINUX_KERNEL_VERSION >= 131939
# define __ASSUME_O_DIRECTORY 1
#endif
/* Starting with one of the 2.4.0 pre-releases the Linux kernel passes
up the page size information. */
#if __LINUX_KERNEL_VERSION >= 132097
# define __ASSUME_AT_PAGESIZE 1
#endif
/* Starting with 2.4.5 kernels PPC passes the AUXV in the standard way
and the mmap2 syscall made it into the official kernel. */
#if __LINUX_KERNEL_VERSION >= (132096+5) && defined __powerpc__
# define __ASSUME_STD_AUXV 1
# define __ASSUME_MMAP2_SYSCALL 1
#endif
/* There are an infinite number of PA-RISC kernel versions numbered
2.4.0. But they've not really been released as such. We require
and expect the final version here. */
#ifdef __hppa__
# define __ASSUME_32BITUIDS 1
# define __ASSUME_TRUNCATE64_SYSCALL 1
# define __ASSUME_MMAP2_SYSCALL 1
# define __ASSUME_STAT64_SYSCALL 1
# define __ASSUME_IPC64 1
# define __ASSUME_ST_INO_64_BIT 1
# define __ASSUME_FCNTL64 1
# define __ASSUME_GETDENTS64_SYSCALL 1
#endif

View File

@ -0,0 +1,535 @@
/* Run-time dynamic linker data structures for loaded ELF shared objects.
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _LDSODEFS_H
#define _LDSODEFS_H 1
#include <features.h>
#define __need_size_t
#define __need_NULL
#include <stddef.h>
#include <string.h>
#include <elf.h>
#include <dlfcn.h>
#include <link.h>
#include <dl-lookupcfg.h>
#include <bits/libc-lock.h>
__BEGIN_DECLS
/* 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 internal_function
/* All references to the value of l_info[DT_PLTGOT],
l_info[DT_STRTAB], l_info[DT_SYMTAB], l_info[DT_RELA],
l_info[DT_REL], l_info[DT_JMPREL], and l_info[VERSYMIDX (DT_VERSYM)]
have to be accessed via the D_PTR macro. The macro is needed since for
most architectures the entry is already relocated - but for some not
and we need to relocate at access time. */
#ifdef DL_RO_DYN_SECTION
# define D_PTR(map,i) (map->i->d_un.d_ptr + map->l_addr)
#else
# define D_PTR(map,i) map->i->d_un.d_ptr
#endif
/* On some platforms more information than just the address of the symbol
is needed from the lookup functions. In this case we return the whole
link map. */
#ifdef DL_LOOKUP_RETURNS_MAP
typedef struct link_map *lookup_t;
# define LOOKUP_VALUE(map) map
# define LOOKUP_VALUE_ADDRESS(map) (map ? map->l_addr : 0)
#else
typedef ElfW(Addr) lookup_t;
# define LOOKUP_VALUE(map) map->l_addr
# define LOOKUP_VALUE_ADDRESS(address) address
#endif
/* on some architectures a pointer to a function is not just a pointer
to the actual code of the function but rather an architecture
specific descriptor. */
#ifndef ELF_FUNCTION_PTR_IS_SPECIAL
# define DL_SYMBOL_ADDRESS(map, ref) \
(void *) (LOOKUP_VALUE_ADDRESS (map) + ref->st_value)
# define DL_LOOKUP_ADDRESS(addr) ((ElfW(Addr)) (addr))
# define DL_DT_INIT_ADDRESS(map, start) (start)
# define DL_DT_FINI_ADDRESS(map, start) (start)
#endif
/* Unmap a loaded object, called by _dl_close (). */
#ifndef DL_UNMAP_IS_SPECIAL
# define DL_UNMAP(map) \
__munmap ((void *) (map)->l_map_start, \
(map)->l_map_end - (map)->l_map_start)
#endif
/* By default we do not need special support to initialize DSOs loaded
by statically linked binaries. */
#ifndef DL_STATIC_INIT
# define DL_STATIC_INIT(map)
#endif
/* Reloc type classes as returned by elf_machine_type_class().
ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
satisfied by any symbol in the executable. */
#define ELF_RTYPE_CLASS_PLT 1
#define ELF_RTYPE_CLASS_COPY 2
/* ELF uses the PF_x macros to specify the segment permissions, mmap
uses PROT_xxx. In most cases the three macros have the values 1, 2,
and 3 but not in a matching order. The following macros allows
converting from the PF_x values to PROT_xxx values. */
#define PF_TO_PROT \
((PROT_READ << (PF_R * 4)) \
| (PROT_WRITE << (PF_W * 4)) \
| (PROT_EXEC << (PF_X * 4)) \
| ((PROT_READ | PROT_WRITE) << ((PF_R | PF_W) * 4)) \
| ((PROT_READ | PROT_EXEC) << ((PF_R | PF_X) * 4)) \
| ((PROT_WRITE | PROT_EXEC) << (PF_W | PF_X) * 4) \
| ((PROT_READ | PROT_WRITE | PROT_EXEC) << ((PF_R | PF_W | PF_X) * 4)))
/* For the version handling we need an array with only names and their
hash values. */
struct r_found_version
{
const char *name;
ElfW(Word) hash;
int hidden;
const char *filename;
};
/* We want to cache information about the searches for shared objects. */
enum r_dir_status { unknown, nonexisting, existing };
struct r_search_path_elem
{
/* This link is only used in the `all_dirs' member of `r_search_path'. */
struct r_search_path_elem *next;
/* Strings saying where the definition came from. */
const char *what;
const char *where;
/* Basename for this search path element. The string must end with
a slash character. */
const char *dirname;
size_t dirnamelen;
enum r_dir_status status[0];
};
struct r_strlenpair
{
const char *str;
size_t len;
};
/* A data structure for a simple single linked list of strings. */
struct libname_list
{
const char *name; /* Name requested (before search). */
struct libname_list *next; /* Link to next name for this object. */
int dont_free; /* Flag whether this element should be freed
if the object is not entirely unloaded. */
};
/* Test whether given NAME matches any of the names of the given object. */
static __inline int
__attribute__ ((unused))
_dl_name_match_p (const char *__name, struct link_map *__map)
{
int __found = strcmp (__name, __map->l_name) == 0;
struct libname_list *__runp = __map->l_libname;
while (! __found && __runp != NULL)
if (strcmp (__name, __runp->name) == 0)
__found = 1;
else
__runp = __runp->next;
return __found;
}
/* Function used as argument for `_dl_receive_error' function. The
arguments are the error code, error string, and the objname the
error occurred in. */
typedef void (*receiver_fct) (int, const char *, const char *);
/* Internal functions of the run-time dynamic linker.
These can be accessed if you link again the dynamic linker
as a shared library, as in `-lld' or `/lib/ld.so' explicitly;
but are not normally of interest to user programs.
The `-ldl' library functions in <dlfcn.h> provide a simple
user interface to run-time dynamic linking. */
/* Parameters passed to the dynamic linker. */
extern char **_dl_argv;
/* Cached value of `getpagesize ()'. */
extern size_t _dl_pagesize;
/* OS version. */
extern unsigned int _dl_osversion;
/* File descriptor referring to the zero-fill device. */
extern int _dl_zerofd;
/* Name of the shared object to be profiled (if any). */
extern const char *_dl_profile;
/* Map of shared object to be profiled. */
extern struct link_map *_dl_profile_map;
/* Filename of the output file. */
extern const char *_dl_profile_output;
/* If nonzero the appropriate debug information is printed. */
extern int _dl_debug_mask;
#define DL_DEBUG_LIBS (1 << 0)
#define DL_DEBUG_IMPCALLS (1 << 1)
#define DL_DEBUG_BINDINGS (1 << 2)
#define DL_DEBUG_SYMBOLS (1 << 3)
#define DL_DEBUG_VERSIONS (1 << 4)
#define DL_DEBUG_RELOC (1 << 5)
#define DL_DEBUG_FILES (1 << 6)
#define DL_DEBUG_STATISTICS (1 << 7)
/* This one is used only internally. */
#define DL_DEBUG_HELP (1 << 8)
/* Expect cache ID. */
extern int _dl_correct_cache_id;
/* Mask for hardware capabilities that are available. */
extern unsigned long int _dl_hwcap;
/* Mask for important hardware capabilities we honour. */
extern unsigned long int _dl_hwcap_mask;
/* File descriptor to write debug messages to. */
extern int _dl_debug_fd;
/* Names of shared object for which the RPATH should be ignored. */
extern const char *_dl_inhibit_rpath;
/* Nonzero if references should be treated as weak during runtime linking. */
extern int _dl_dynamic_weak;
/* The array with message we print as a last resort. */
extern const char _dl_out_of_memory[];
/* Nonzero if runtime lookups should not update the .got/.plt. */
extern int _dl_bind_not;
/* List of search directories. */
extern struct r_search_path_elem *_dl_all_dirs;
extern struct r_search_path_elem *_dl_init_all_dirs;
/* OS-dependent function to open the zero-fill device. */
extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
/* During the program run we must not modify the global data of
loaded shared object simultanously in two threads. Therefore we
protect `_dl_open' and `_dl_close' in dl-close.c.
This must be a recursive lock since the initializer function of
the loaded object might as well require a call to this function.
At this time it is not anymore a problem to modify the tables. */
__libc_lock_define_recursive (extern, _dl_load_lock)
/* Write message on the debug file descriptor. The parameters are
interpreted as for a `printf' call. All the lines start with a
tag showing the PID. */
extern void _dl_debug_printf (const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
/* Write message on the debug file descriptor. The parameters are
interpreted as for a `printf' call. All the lines buf the first
start with a tag showing the PID. */
extern void _dl_debug_printf_c (const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
/* Write a message on the specified descriptor FD. The parameters are
interpreted as for a `printf' call. */
extern void _dl_dprintf (int fd, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
/* Write a message on the specified descriptor standard output. The
parameters are interpreted as for a `printf' call. */
#define _dl_printf(fmt, args...) \
_dl_dprintf (STDOUT_FILENO, fmt, ##args)
/* Write a message on the specified descriptor standard error. The
parameters are interpreted as for a `printf' call. */
#define _dl_error_printf(fmt, args...) \
_dl_dprintf (STDERR_FILENO, fmt, ##args)
/* Write a message on the specified descriptor standard error and exit
the program. The parameters are interpreted as for a `printf' call. */
#define _dl_fatal_printf(fmt, args...) \
do \
{ \
_dl_dprintf (STDERR_FILENO, fmt, ##args); \
_exit (127); \
} \
while (1)
/* This function is called by all the internal dynamic linker functions
when they encounter an error. ERRCODE is either an `errno' code or
zero; OBJECT is the name of the problematical shared object, or null if
it is a general problem; ERRSTRING is a string describing the specific
problem. */
extern void _dl_signal_error (int errcode, const char *object,
const char *occurred, const char *errstring)
internal_function
__attribute__ ((__noreturn__));
/* Like _dl_signal_error, but may return when called in the context of
_dl_receive_error. */
extern void _dl_signal_cerror (int errcode, const char *object,
const char *occation, const char *errstring)
internal_function;
/* Call OPERATE, receiving errors from `dl_signal_cerror'. Unlike
`_dl_catch_error' the operation is resumed after the OPERATE
function returns.
ARGS is passed as argument to OPERATE. */
extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
void *args)
internal_function;
/* Open the shared object NAME and map in its segments.
LOADER's DT_RPATH is used in searching for NAME.
If the object is already opened, returns its existing map.
For preloaded shared objects PRELOADED is set to a non-zero
value to allow additional security checks. */
extern struct link_map *_dl_map_object (struct link_map *loader,
const char *name, int preloaded,
int type, int trace_mode, int mode)
internal_function;
/* Call _dl_map_object on the dependencies of MAP, and set up
MAP->l_searchlist. PRELOADS points to a vector of NPRELOADS previously
loaded objects that will be inserted into MAP->l_searchlist after MAP
but before its dependencies. */
extern void _dl_map_object_deps (struct link_map *map,
struct link_map **preloads,
unsigned int npreloads, int trace_mode)
internal_function;
/* Cache the locations of MAP's hash table. */
extern void _dl_setup_hash (struct link_map *map) internal_function;
/* 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 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.
TYPE_CLASS describes the type of symbol we are looking for. */
extern lookup_t _dl_lookup_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
int type_class, int explicit)
internal_function;
/* Lookup versioned symbol. */
extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
int type_class, int explicit)
internal_function;
/* For handling RTLD_NEXT we must be able to skip shared objects. */
extern lookup_t _dl_lookup_symbol_skip (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
struct link_map *skip_this)
internal_function;
/* For handling RTLD_NEXT with versioned symbols we must be able to
skip shared objects. */
extern lookup_t _dl_lookup_versioned_symbol_skip (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
struct link_map *skip_this)
internal_function;
/* 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)
internal_function;
/* Structure describing the dynamic linker itself. */
extern struct link_map _dl_rtld_map;
/* And a pointer to the map for the main map. */
extern struct link_map *_dl_loaded;
/* Number of object in the _dl_loaded list. */
extern unsigned int _dl_nloaded;
/* Array representing global scope. */
extern struct r_scope_elem *_dl_global_scope[2];
/* Direct pointer to the searchlist of the main object. */
extern struct r_scope_elem *_dl_main_searchlist;
/* Copy of the content of `_dl_main_searchlist'. */
extern struct r_scope_elem _dl_initial_searchlist;
/* This is zero at program start to signal that the global scope map is
allocated by rtld. Later it keeps the size of the map. It might be
reset if in _dl_close if the last global object is removed. */
extern size_t _dl_global_scope_alloc;
/* Allocate a `struct link_map' for a new object being loaded,
and enter it into the _dl_main_map list. */
extern struct link_map *_dl_new_object (char *realname, const char *libname,
int type, struct link_map *loader)
internal_function;
/* 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,
struct r_scope_elem *scope[],
int lazy, int consider_profiling);
/* Call _dl_signal_error with a message about an unhandled reloc type.
TYPE is the result of ELFW(R_TYPE) (r_info), i.e. an R_<CPU>_* value.
PLT is nonzero if this was a PLT reloc; it just affects the message. */
extern void _dl_reloc_bad_type (struct link_map *map,
unsigned int type, int plt)
internal_function __attribute__ ((__noreturn__));
/* Check the version dependencies of all objects available through
MAP. If VERBOSE print some more diagnostics. */
extern int _dl_check_all_versions (struct link_map *map, int verbose,
int trace_mode)
internal_function;
/* Check the version dependencies for MAP. If VERBOSE print some more
diagnostics. */
extern int _dl_check_map_versions (struct link_map *map, int verbose,
int trace_mode)
internal_function;
/* Initialize the object in SCOPE by calling the constructors with
ARGC, ARGV, and ENV as the parameters. */
extern void _dl_init (struct link_map *main_map, int argc, char **argv,
char **env) internal_function;
/* Call the finalizer functions of all shared objects whose
initializer functions have completed. */
extern void _dl_fini (void) internal_function;
/* The dynamic linker calls this function before and having changing
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_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)
internal_function;
/* Initialize the basic data structure for the search paths. */
extern void _dl_init_paths (const char *library_path) internal_function;
/* Gather the information needed to install the profiling tables and start
the timers. */
extern void _dl_start_profile (struct link_map *map, const char *output_dir)
internal_function;
/* The actual functions used to keep book on the calls. */
extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
/* This function is simply a wrapper around the _dl_mcount function
which does not require a FROMPC parameter since this is the
calling function. */
extern void _dl_mcount_wrapper (void *selfpc);
/* Show the members of the auxiliary array passed up from the kernel. */
extern void _dl_show_auxv (void) internal_function;
/* Return all environment variables starting with `LD_', one after the
other. */
extern char *_dl_next_ld_env_entry (char ***position) internal_function;
/* Return an array with the names of the important hardware capabilities. */
extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
size_t paltform_len,
size_t *sz,
size_t *max_capstrlen)
internal_function;
/* Look up NAME in ld.so.cache and return the file name stored there,
or null if none is found. */
extern const char *_dl_load_cache_lookup (const char *name)
internal_function;
/* If the system does not support MAP_COPY we cannot leave the file open
all the time since this would create problems when the file is replaced.
Therefore we provide this function to close the file and open it again
once needed. */
extern void _dl_unload_cache (void);
/* System-dependent function to read a file's whole contents in the
most convenient manner available. *SIZEP gets the size of the
file. On error MAP_FAILED is returned. */
extern void *_dl_sysdep_read_whole_file (const char *file, size_t *sizep,
int prot)
internal_function;
/* System-specific function to do initial startup for the dynamic linker.
After this, file access calls and getenv must work. This is responsible
for setting __libc_enable_secure if we need to be secure (e.g. setuid),
and for setting _dl_argc and _dl_argv, and then calling _dl_main. */
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
ElfW(Addr) *user_entry));
extern void _dl_sysdep_start_cleanup (void)
internal_function;
__END_DECLS
#endif /* ldsodefs.h */

View File

@ -0,0 +1,2 @@
#define N_(x) x

View File

@ -0,0 +1,7 @@
#define SYSTEM_DIRS \
"/usr/local/lib/"
#define SYSTEM_DIRS_LEN \
15
#define SYSTEM_DIRS_MAX_LEN 15

View File

@ -0,0 +1,19 @@
/* Environment variable to be removed for SUID programs. The names are
all stuffed in a single string which means they have to be terminated
with a '\0' explicitly. */
#define UNSECURE_ENVVARS \
"LD_PRELOAD\0" \
"LD_LIBRARY_PATH\0" \
"LD_ORIGIN_PATH\0" \
"LD_DEBUG_OUTPUT\0" \
"LD_PROFILE\0" \
"GCONV_PATH\0" \
"HOSTALIASES\0" \
"LOCALDOMAIN\0" \
"LOCPATH\0" \
"MALLOC_TRACE\0" \
"NLSPATH\0" \
"RESOLV_HOST_CONF\0" \
"RES_OPTIONS\0" \
"TMPDIR\0" \
"TZDIR\0"

View File

@ -0,0 +1,114 @@
/* Copyright (C) 1995,1996,1998,1999,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#define HOSTIDFILE "/etc/hostid"
#define OLD_HOSTIDFILE "/etc/hostid"
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
# define OPEN __open64
#else
# define OPEN __open
#endif
#ifdef SET_PROCEDURE
int
sethostid (id)
long int id;
{
int fd;
ssize_t written;
/* Open file for writing. Everybody is allowed to read this file. */
fd = OPEN (HOSTIDFILE, O_CREAT|O_WRONLY|O_TRUNC, 0644);
if (fd < 0)
return -1;
written = __write (fd, &id, sizeof (id));
__close (fd);
return written != sizeof (id) ? -1 : 0;
}
#else
# include <string.h>
# include <sys/param.h>
# include <netdb.h>
# include <netinet/in.h>
long int
gethostid ()
{
char hostname[MAXHOSTNAMELEN + 1];
size_t buflen;
char *buffer;
struct hostent hostbuf, *hp;
unsigned long int id;
struct in_addr in;
int herr;
int fd;
/* First try to get the ID from a former invocation of sethostid. */
fd = OPEN (HOSTIDFILE, O_RDONLY);
if (fd >= 0)
{
ssize_t n = __read (fd, &id, sizeof (id));
__close (fd);
if (n == sizeof (id))
return id;
}
/* Getting from the file was not successful. An intelligent guess for
a unique number of a host is its IP address. Return this. */
if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0')
/* This also fails. Return and arbitrary value. */
return 0;
buflen = 1024;
buffer = alloca (buflen);
/* To get the IP address we need to know the host name. */
while (__gethostbyname_r (hostname, &hostbuf, buffer, buflen, &hp, &herr)
!= 0
|| hp == NULL)
if (herr != NETDB_INTERNAL || errno != ERANGE)
return 0;
else
{
/* Enlarge buffer. */
buflen *= 2;
buffer = alloca (buflen);
}
in.s_addr = 0;
memcpy (&in, hp->h_addr,
(int) sizeof (in) < hp->h_length ? sizeof (in) : hp->h_length);
/* For the return value to be not exactly the IP address we do some
bit fiddling. */
return in.s_addr << 16 | in.s_addr >> 16;
}
#endif

View File

@ -0,0 +1,27 @@
## Process this file with automake to generate Makefile.in
AUTOMAKE_OPTIONS = cygnus
INCLUDES = -DGCONV_DIR='"$(pkglibdir)"' -DGCONV_PATH='"$(pkglibdir)"' -I$(srcdir) -I$(srcdir)/.. $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
LIB_SOURCES = \
iconv.h gconv.h \
iconv_open.c iconv.c iconv_close.c \
gconv_open.c gconv.c gconv_close.c \
gconv_db.c gconv_dl.c gconv_conf.c gconv_builtin.c \
gconv_simple.c gconv_trans.c gconv_cache.c
libiconv_la_CFLAGS =
libiconv_la_LDFLAGS = -Xcompiler -nostdlib
if USE_LIBTOOL
noinst_LTLIBRARIES = libiconv.la
libiconv_la_SOURCES = $(LIB_SOURCES)
noinst_DATA = objectlist.awk.in
else
noinst_LIBRARIES = lib.a
lib_a_SOURCES = $(LIB_SOURCES)
noinst_DATA =
endif # USE_LIBTOOL
include $(srcdir)/../../../../Makefile.shared

View File

@ -0,0 +1,375 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_alias = @build_alias@
build_triplet = @build@
host_alias = @host_alias@
host_triplet = @host@
target_alias = @target_alias@
target_triplet = @target@
AR = @AR@
AS = @AS@
AWK = @AWK@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
LDFLAGS = @LDFLAGS@
LIBTOOL = @LIBTOOL@
LINUX_MACH_LIB = @LINUX_MACH_LIB@
LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
VERSION = @VERSION@
aext = @aext@
libm_machine_dir = @libm_machine_dir@
machine_dir = @machine_dir@
newlib_basedir = @newlib_basedir@
oext = @oext@
sys_dir = @sys_dir@
AUTOMAKE_OPTIONS = cygnus
INCLUDES = -DGCONV_DIR='"$(pkglibdir)"' -DGCONV_PATH='"$(pkglibdir)"' -I$(srcdir) -I$(srcdir)/.. $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
LIB_SOURCES = \
iconv.h gconv.h \
iconv_open.c iconv.c iconv_close.c \
gconv_open.c gconv.c gconv_close.c \
gconv_db.c gconv_dl.c gconv_conf.c gconv_builtin.c \
gconv_simple.c gconv_trans.c gconv_cache.c
libiconv_la_CFLAGS =
libiconv_la_LDFLAGS = -Xcompiler -nostdlib
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = @USE_LIBTOOL_TRUE@libiconv.la
@USE_LIBTOOL_TRUE@libiconv_la_SOURCES = @USE_LIBTOOL_TRUE@$(LIB_SOURCES)
@USE_LIBTOOL_TRUE@noinst_DATA = @USE_LIBTOOL_TRUE@objectlist.awk.in
@USE_LIBTOOL_FALSE@noinst_DATA =
@USE_LIBTOOL_FALSE@noinst_LIBRARIES = @USE_LIBTOOL_FALSE@lib.a
@USE_LIBTOOL_FALSE@lib_a_SOURCES = @USE_LIBTOOL_FALSE@$(LIB_SOURCES)
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
lib_a_LIBADD =
@USE_LIBTOOL_FALSE@lib_a_OBJECTS = iconv_open.$(OBJEXT) iconv.$(OBJEXT) \
@USE_LIBTOOL_FALSE@iconv_close.$(OBJEXT) gconv_open.$(OBJEXT) \
@USE_LIBTOOL_FALSE@gconv.$(OBJEXT) gconv_close.$(OBJEXT) \
@USE_LIBTOOL_FALSE@gconv_db.$(OBJEXT) gconv_dl.$(OBJEXT) \
@USE_LIBTOOL_FALSE@gconv_conf.$(OBJEXT) gconv_builtin.$(OBJEXT) \
@USE_LIBTOOL_FALSE@gconv_simple.$(OBJEXT) gconv_trans.$(OBJEXT) \
@USE_LIBTOOL_FALSE@gconv_cache.$(OBJEXT)
LTLIBRARIES = $(noinst_LTLIBRARIES)
libiconv_la_LIBADD =
@USE_LIBTOOL_TRUE@libiconv_la_OBJECTS = iconv_open.lo iconv.lo \
@USE_LIBTOOL_TRUE@iconv_close.lo gconv_open.lo gconv.lo gconv_close.lo \
@USE_LIBTOOL_TRUE@gconv_db.lo gconv_dl.lo gconv_conf.lo \
@USE_LIBTOOL_TRUE@gconv_builtin.lo gconv_simple.lo gconv_trans.lo \
@USE_LIBTOOL_TRUE@gconv_cache.lo
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DATA = $(noinst_DATA)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
SOURCES = $(lib_a_SOURCES) $(libiconv_la_SOURCES)
OBJECTS = $(lib_a_OBJECTS) $(libiconv_la_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .lo .o .obj .s
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(srcdir)/../../../../Makefile.shared
cd $(top_srcdir) && $(AUTOMAKE) --cygnus iconv/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.c.o:
$(COMPILE) -c $<
# FIXME: We should only use cygpath when building on Windows,
# and only if it is available.
.c.obj:
$(COMPILE) -c `cygpath -w $<`
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
-rm -f *.$(OBJEXT)
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
.c.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
maintainer-clean-libtool:
lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES)
-rm -f lib.a
$(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD)
$(RANLIB) lib.a
mostlyclean-noinstLTLIBRARIES:
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
distclean-noinstLTLIBRARIES:
maintainer-clean-noinstLTLIBRARIES:
libiconv.la: $(libiconv_la_OBJECTS) $(libiconv_la_DEPENDENCIES)
$(LINK) $(libiconv_la_LDFLAGS) $(libiconv_la_OBJECTS) $(libiconv_la_LIBADD) $(LIBS)
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = iconv
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am:
check: check-am
installcheck-am:
installcheck: installcheck-am
install-info-am:
install-info: install-info-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(DATA)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-noinstLTLIBRARIES \
mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \
clean-noinstLTLIBRARIES clean-tags clean-generic \
mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-libtool distclean-noinstLTLIBRARIES \
distclean-tags distclean-generic clean-am
-rm -f libtool
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-noinstLTLIBRARIES \
maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool mostlyclean-noinstLTLIBRARIES \
distclean-noinstLTLIBRARIES clean-noinstLTLIBRARIES \
maintainer-clean-noinstLTLIBRARIES tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
check-am installcheck-am installcheck install-info-am install-info \
install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
objectlist.awk.in: $(noinst_LTLIBRARIES)
-rm -f objectlist.awk.in
for i in `ls *.lo` ; \
do \
echo $$i `pwd`/$$i >> objectlist.awk.in ; \
done
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,344 @@
/* Definition of all available locale categories and their items. -*- C -*-
Copyright (C) 1995-2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* These definitions are used by the locale-related files in the C library
and the programs `localedef' and `locale'.
The general format of the descriptions is like this:
DEFINE_CATEGORY (ID, name, ( items ), setlocale-postload)
where items itself is an array of entries in the form
{ ID, name, standard, value-type, min, max }
The usage of the load, check, output functions depends on the individual
program code which loads this file.
The various value types for the items are `string', `stringarray', `byte'
`bytearray', and `word'. These cover all possible values in the current
locale definitions. `min' and `max' can be individually used again. */
#ifndef NO_POSTLOAD
#define NO_POSTLOAD NULL
#endif
DEFINE_CATEGORY
(
LC_COLLATE, "LC_COLLATE",
(
DEFINE_ELEMENT (_NL_COLLATE_NRULES, "collate-nrules", std, word)
DEFINE_ELEMENT (_NL_COLLATE_RULESETS, "collate-rulesets", std, string)
DEFINE_ELEMENT (_NL_COLLATE_TABLEMB, "collate-tablemb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_WEIGHTMB, "collate-weightmb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_EXTRAMB, "collate-extramb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_INDIRECTMB, "collate-indirectmb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_TABLEWC, "collate-tablewc", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_WEIGHTWC, "collate-weightwc", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_EXTRAWC, "collate-extrawc", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_INDIRECTWC, "collate-indirectwc", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_HASH_SIZEMB, "collate-symb-hash-sizemb", std, word)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_TABLEMB, "collate-symb-tablemb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_EXTRAMB, "collate-symb-extramb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string)
), NO_POSTLOAD)
/* The actual definition of ctype is meaningless here. It is hard coded in
the code because it has to be handled very specially. Only the names of
the functions and the value types are important. */
DEFINE_CATEGORY
(
LC_CTYPE, "LC_CTYPE",
(
DEFINE_ELEMENT (_NL_CTYPE_CLASS, "ctype-class", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TOUPPER, "ctype-toupper", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TOLOWER, "ctype-tolower", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_CLASS32, "ctype-class32", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, stringlist, 10, 32)
DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES, "ctype-map-names", std, stringlist, 2, 32)
DEFINE_ELEMENT (_NL_CTYPE_WIDTH, "ctype-width", std, bytearray)
DEFINE_ELEMENT (_NL_CTYPE_MB_CUR_MAX, "ctype-mb-cur-max", std, word)
DEFINE_ELEMENT (_NL_CTYPE_CODESET_NAME, "charmap", std, string)
DEFINE_ELEMENT (_NL_CTYPE_TOUPPER32, "ctype-toupper32", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TOLOWER32, "ctype-tolower32", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_CLASS_OFFSET, "ctype-class-offset", std, word)
DEFINE_ELEMENT (_NL_CTYPE_MAP_OFFSET, "ctype-map-offset", std, word)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS_MB_LEN, "ctype-indigits_mb-len", std, word)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS0_MB, "ctype-indigits0_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS1_MB, "ctype-indigits1_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS2_MB, "ctype-indigits2_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS3_MB, "ctype-indigits3_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS4_MB, "ctype-indigits4_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS5_MB, "ctype-indigits5_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS6_MB, "ctype-indigits6_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS7_MB, "ctype-indigits7_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS8_MB, "ctype-indigits8_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS9_MB, "ctype-indigits9_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS_WC_LEN, "ctype-indigits_wc-len", std, word)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS0_WC, "ctype-indigits0_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS1_WC, "ctype-indigits1_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS2_WC, "ctype-indigits2_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS3_WC, "ctype-indigits3_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS4_WC, "ctype-indigits4_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS5_WC, "ctype-indigits5_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS6_WC, "ctype-indigits6_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS7_WC, "ctype-indigits7_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS8_WC, "ctype-indigits8_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_INDIGITS9_WC, "ctype-indigits9_wc", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT0_MB, "ctype-outdigit0_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT1_MB, "ctype-outdigit1_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT2_MB, "ctype-outdigit2_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT3_MB, "ctype-outdigit3_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT4_MB, "ctype-outdigit4_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT5_MB, "ctype-outdigit5_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT6_MB, "ctype-outdigit6_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT7_MB, "ctype-outdigit7_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT8_MB, "ctype-outdigit8_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT9_MB, "ctype-outdigit9_mb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT0_WC, "ctype-outdigit0_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT1_WC, "ctype-outdigit1_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT2_WC, "ctype-outdigit2_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT3_WC, "ctype-outdigit3_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT4_WC, "ctype-outdigit4_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT5_WC, "ctype-outdigit5_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT6_WC, "ctype-outdigit6_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT7_WC, "ctype-outdigit7_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT8_WC, "ctype-outdigit8_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT9_WC, "ctype-outdigit9_wc", std, word)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TAB_SIZE, "ctype-translit-tab-size", std, word)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_FROM_IDX, "ctype-translit-from-idx", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_FROM_TBL, "ctype-translit-from-tbl", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TO_IDX, "ctype-translit-to-idx", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TO_TBL, "ctype-translit-to-tbl", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN, "ctype-translit-default-missing-len", std, word)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_DEFAULT_MISSING, "ctype-translit-default-missing", std, wstring)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_IGNORE_LEN, "ctype-translit-ignore-len", std, word)
DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_IGNORE, "ctype-translit-ignore", std, string)
), _nl_postload_ctype)
DEFINE_CATEGORY
(
LC_MONETARY, "LC_MONETARY",
(
DEFINE_ELEMENT (INT_CURR_SYMBOL, "int_curr_symbol", std, string)
DEFINE_ELEMENT (CURRENCY_SYMBOL, "currency_symbol", std, string)
DEFINE_ELEMENT (MON_DECIMAL_POINT, "mon_decimal_point", std, string)
DEFINE_ELEMENT (MON_THOUSANDS_SEP, "mon_thousands_sep", std, string)
DEFINE_ELEMENT (MON_GROUPING, "mon_grouping", std, bytearray)
DEFINE_ELEMENT (POSITIVE_SIGN, "positive_sign", std, string)
DEFINE_ELEMENT (NEGATIVE_SIGN, "negative_sign", std, string)
DEFINE_ELEMENT (INT_FRAC_DIGITS, "int_frac_digits", std, byte)
DEFINE_ELEMENT (FRAC_DIGITS, "frac_digits", std, byte)
DEFINE_ELEMENT (P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (__INT_P_CS_PRECEDES, "int_p_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (__INT_P_SEP_BY_SPACE, "int_p_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (__INT_N_CS_PRECEDES, "int_n_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (__INT_N_SEP_BY_SPACE, "int_n_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (__INT_P_SIGN_POSN, "int_p_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (__INT_N_SIGN_POSN, "int_n_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_CURR_SYMBOL, "duo_int_curr_symbol", std, string)
DEFINE_ELEMENT (_NL_MONETARY_DUO_CURRENCY_SYMBOL, "duo_currency_symbol", std, string)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_FRAC_DIGITS, "duo_int_frac_digits", std, byte)
DEFINE_ELEMENT (_NL_MONETARY_DUO_FRAC_DIGITS, "duo_frac_digits", std, byte)
DEFINE_ELEMENT (_NL_MONETARY_DUO_P_CS_PRECEDES, "duo_p_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SEP_BY_SPACE, "duo_p_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (_NL_MONETARY_DUO_N_CS_PRECEDES, "duo_n_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SEP_BY_SPACE, "duo_n_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_CS_PRECEDES, "duo_int_p_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE, "duo_int_p_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_CS_PRECEDES, "duo_int_n_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE, "duo_int_n_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SIGN_POSN, "duo_p_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SIGN_POSN, "duo_n_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SIGN_POSN, "duo_int_p_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SIGN_POSN, "duo_int_n_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_FROM, "uno_valid_from", std, word)
DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_TO, "uno_valid_to", std, word)
DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_FROM, "duo_valid_from", std, word)
DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_TO, "duo_valid_to", std, word)
DEFINE_ELEMENT (_NL_MONETARY_CONVERSION_RATE, "conversion_rate", std, wordarray, 2, 2)
DEFINE_ELEMENT (_NL_MONETARY_DECIMAL_POINT_WC, "monetary-decimal-point-wc", std, word)
DEFINE_ELEMENT (_NL_MONETARY_THOUSANDS_SEP_WC, "monetary-thousands-sep-wc", std, word)
DEFINE_ELEMENT (_NL_MONETARY_CODESET, "monetary-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_NUMERIC, "LC_NUMERIC",
(
DEFINE_ELEMENT (DECIMAL_POINT, "decimal_point", std, string)
DEFINE_ELEMENT (THOUSANDS_SEP, "thousands_sep", std, string)
DEFINE_ELEMENT (GROUPING, "grouping", std, bytearray)
DEFINE_ELEMENT (_NL_NUMERIC_DECIMAL_POINT_WC, "numeric-decimal-point-wc", std, word)
DEFINE_ELEMENT (_NL_NUMERIC_THOUSANDS_SEP_WC, "numeric-thousands-sep-wc", std, word)
DEFINE_ELEMENT (_NL_NUMERIC_CODESET, "numeric-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_TIME, "LC_TIME",
(
DEFINE_ELEMENT (ABDAY_1, "abday", std, stringarray, 7, 7)
DEFINE_ELEMENT (DAY_1, "day", std, stringarray, 7, 7)
DEFINE_ELEMENT (ABMON_1, "abmon", std, stringarray, 12, 12)
DEFINE_ELEMENT (MON_1, "mon", std, stringarray, 12, 12)
DEFINE_ELEMENT (AM_STR, "am_pm", std, stringarray, 2, 2)
DEFINE_ELEMENT (D_T_FMT, "d_t_fmt", std, string)
DEFINE_ELEMENT (D_FMT, "d_fmt", std, string)
DEFINE_ELEMENT (T_FMT, "t_fmt", std, string)
DEFINE_ELEMENT (T_FMT_AMPM, "t_fmt_ampm", std, string)
DEFINE_ELEMENT (ERA, "era", opt, stringlist, 0, 100)
DEFINE_ELEMENT (ERA_YEAR, "era_year", opt, string)
DEFINE_ELEMENT (ERA_D_FMT, "era_d_fmt", opt, string)
DEFINE_ELEMENT (ALT_DIGITS, "alt_digits", opt, stringlist, 100, 100)
DEFINE_ELEMENT (ERA_D_T_FMT, "era_d_t_fmt", opt, string)
DEFINE_ELEMENT (ERA_T_FMT, "era_t_fmt", opt, string)
DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES, "time-era-num-entries", opt, word)
DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES, "time-era-entries", opt, string)
DEFINE_ELEMENT (_NL_WABDAY_1, "wide-abday", std, wstringarray, 7, 7)
DEFINE_ELEMENT (_NL_WDAY_1, "wide-day", std, wstringarray, 7, 7)
DEFINE_ELEMENT (_NL_WABMON_1, "wide-abmon", std, wstringarray, 12, 12)
DEFINE_ELEMENT (_NL_WMON_1, "wide-mon", std, wstringarray, 12, 12)
DEFINE_ELEMENT (_NL_WAM_STR, "wide-am_pm", std, wstringarray, 2, 2)
DEFINE_ELEMENT (_NL_WD_T_FMT, "wide-d_t_fmt", std, wstring)
DEFINE_ELEMENT (_NL_WD_FMT, "wide-d_fmt", std, wstring)
DEFINE_ELEMENT (_NL_WT_FMT, "wide-t_fmt", std, wstring)
DEFINE_ELEMENT (_NL_WT_FMT_AMPM, "wide-t_fmt_ampm", std, wstring)
DEFINE_ELEMENT (_NL_WERA_YEAR, "wide-era_year", opt, wstring)
DEFINE_ELEMENT (_NL_WERA_D_FMT, "wide-era_d_fmt", opt, wstring)
DEFINE_ELEMENT (_NL_WALT_DIGITS, "wide-alt_digits", opt, wstringlist, 1000, 100)
DEFINE_ELEMENT (_NL_WERA_D_T_FMT, "wide-era_d_t_fmt", opt, wstring)
DEFINE_ELEMENT (_NL_WERA_T_FMT, "wide-era_t_fmt", opt, wstring)
DEFINE_ELEMENT (_NL_TIME_WEEK_NDAYS, "week-ndays", std, byte)
DEFINE_ELEMENT (_NL_TIME_WEEK_1STDAY, "week-1stday", std, word)
DEFINE_ELEMENT (_NL_TIME_WEEK_1STWEEK, "week-1stweek", std, byte)
DEFINE_ELEMENT (_NL_TIME_FIRST_WEEKDAY, "first_weekday", std, byte)
DEFINE_ELEMENT (_NL_TIME_FIRST_WORKDAY, "first_workday", std, byte)
DEFINE_ELEMENT (_NL_TIME_CAL_DIRECTION, "cal_direction", std, byte)
DEFINE_ELEMENT (_NL_TIME_TIMEZONE, "timezone", std, string)
DEFINE_ELEMENT (_DATE_FMT, "date_fmt", opt, string)
DEFINE_ELEMENT (_NL_W_DATE_FMT, "wide-date_fmt", opt, wstring)
DEFINE_ELEMENT (_NL_TIME_CODESET, "time-codeset", std, string)
), _nl_postload_time)
DEFINE_CATEGORY
(
LC_MESSAGES, "LC_MESSAGES",
(
DEFINE_ELEMENT (YESEXPR, "yesexpr", std, string)
DEFINE_ELEMENT (NOEXPR, "noexpr", std, string)
DEFINE_ELEMENT (YESSTR, "yesstr", opt, string)
DEFINE_ELEMENT (NOSTR, "nostr", opt, string)
DEFINE_ELEMENT (_NL_MESSAGES_CODESET, "messages-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_PAPER, "LC_PAPER",
(
DEFINE_ELEMENT (_NL_PAPER_HEIGHT, "height", std, word)
DEFINE_ELEMENT (_NL_PAPER_WIDTH, "width", std, word)
DEFINE_ELEMENT (_NL_PAPER_CODESET, "paper-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_NAME, "LC_NAME",
(
DEFINE_ELEMENT (_NL_NAME_NAME_FMT, "name_fmt", std, string)
DEFINE_ELEMENT (_NL_NAME_NAME_GEN, "name_gen", std, string)
DEFINE_ELEMENT (_NL_NAME_NAME_MR, "name_mr", std, string)
DEFINE_ELEMENT (_NL_NAME_NAME_MRS, "name_mrs", std, string)
DEFINE_ELEMENT (_NL_NAME_NAME_MISS, "name_miss", std, string)
DEFINE_ELEMENT (_NL_NAME_NAME_MS, "name_ms", std, string)
DEFINE_ELEMENT (_NL_NAME_CODESET, "name-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_ADDRESS, "LC_ADDRESS",
(
DEFINE_ELEMENT (_NL_ADDRESS_POSTAL_FMT, "postal_fmt", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NAME, "country_name", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_POST, "country_post", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB2, "country_ab2", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB3, "country_ab3", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_CAR, "country_car", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NUM, "country_num", std, word)
DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_ISBN, "country_isbn", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_LANG_NAME, "lang_name", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_LANG_AB, "lang_ab", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_LANG_TERM, "lang_term", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_LANG_LIB, "lang_lib", std, string)
DEFINE_ELEMENT (_NL_ADDRESS_CODESET, "address-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_TELEPHONE, "LC_TELEPHONE",
(
DEFINE_ELEMENT (_NL_TELEPHONE_TEL_INT_FMT, "tel_int_fmt", std, string)
DEFINE_ELEMENT (_NL_TELEPHONE_TEL_DOM_FMT, "tel_dom_fmt", std, string)
DEFINE_ELEMENT (_NL_TELEPHONE_INT_SELECT, "int_select", std, string)
DEFINE_ELEMENT (_NL_TELEPHONE_INT_PREFIX, "int_prefix", std, string)
DEFINE_ELEMENT (_NL_TELEPHONE_CODESET, "telephone-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_MEASUREMENT, "LC_MEASUREMENT",
(
DEFINE_ELEMENT (_NL_MEASUREMENT_MEASUREMENT, "measurement", std, byte)
DEFINE_ELEMENT (_NL_MEASUREMENT_CODESET, "measurement-codeset", std, string)
), NO_POSTLOAD)
DEFINE_CATEGORY
(
LC_IDENTIFICATION, "LC_IDENTIFICATION",
(
DEFINE_ELEMENT (_NL_IDENTIFICATION_TITLE, "title", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_SOURCE, "source", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_ADDRESS, "address", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_CONTACT, "contact", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_EMAIL, "email", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_TEL, "tel", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_FAX, "fax", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_LANGUAGE, "language", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_TERRITORY, "territory", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_AUDIENCE, "audience", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_APPLICATION, "applcation", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_ABBREVIATION, "abbreviation", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_REVISION, "revision", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_DATE, "date", std, string)
DEFINE_ELEMENT (_NL_IDENTIFICATION_CATEGORY, "category", std, stringarray, 13, 13)
DEFINE_ELEMENT (_NL_IDENTIFICATION_CODESET, "identification-codeset", std, string)
), NO_POSTLOAD)

View File

@ -0,0 +1,37 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* For iconv we don't have to handle repertoire maps. Provide dummy
definitions to allow the use of linereader.c unchanged. */
#include <repertoire.h>
uint32_t
repertoire_find_value (const struct repertoire_t *repertoire, const char *name,
size_t len)
{
return ILLEGAL_CHAR_VALUE;
}
const char *
repertoire_find_symbol (const struct repertoire_t *repertoire, uint32_t ucs)
{
return NULL;
}

View File

@ -0,0 +1,73 @@
/* Convert characters in input buffer using conversion descriptor to
output buffer.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <gconv_int.h>
#include <sys/param.h>
#include <dlfcn.h>
#include <stddef.h>
int
internal_function
__gconv (__gconv_t cd, const unsigned char **inbuf,
const unsigned char *inbufend, unsigned char **outbuf,
unsigned char *outbufend, size_t *irreversible)
{
size_t last_step;
int result;
if (cd == (__gconv_t) -1L)
return __GCONV_ILLEGAL_DESCRIPTOR;
last_step = cd->__nsteps - 1;
assert (irreversible != NULL);
*irreversible = 0;
cd->__data[last_step].__outbuf = outbuf != NULL ? *outbuf : NULL;
cd->__data[last_step].__outbufend = outbufend;
if (inbuf == NULL || *inbuf == NULL)
/* We just flush. */
result = cd->__steps->__fct (cd->__steps, cd->__data, NULL, NULL, NULL,
irreversible,
cd->__data[last_step].__outbuf == NULL ? 2 : 1, 0);
else
{
const unsigned char *last_start;
assert (outbuf != NULL && *outbuf != NULL);
do
{
last_start = *inbuf;
result = cd->__steps->__fct (cd->__steps, cd->__data, inbuf, inbufend,
NULL, irreversible, 0, 0);
}
while (result == __GCONV_EMPTY_INPUT && last_start != *inbuf
&& *inbuf + cd->__steps->__min_needed_from <= inbufend);
}
if (outbuf != NULL && *outbuf != NULL)
*outbuf = cd->__data[last_step].__outbuf;
return result;
}

View File

@ -0,0 +1,84 @@
/* Table for builtin transformation mapping.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <endian.h>
#include <limits.h>
#include <string.h>
#include <gconv_int.h>
#include <assert.h>
static struct builtin_map
{
const char *name;
__gconv_fct fct;
int min_needed_from;
int max_needed_from;
int min_needed_to;
int max_needed_to;
} map[] =
{
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
MinT, MaxT) \
{ \
.name = Name, \
.fct = Fct, \
\
.min_needed_from = MinF, \
.max_needed_from = MaxF, \
.min_needed_to = MinT, \
.max_needed_to = MaxT \
},
#define BUILTIN_ALIAS(From, To)
#include <gconv_builtin.h>
};
void
internal_function
__gconv_get_builtin_trans (const char *name, struct __gconv_step *step)
{
size_t cnt;
for (cnt = 0; cnt < sizeof (map) / sizeof (map[0]); ++cnt)
if (strcmp (name, map[cnt].name) == 0)
break;
assert (cnt < sizeof (map) / sizeof (map[0]));
step->__fct = map[cnt].fct;
step->__init_fct = NULL;
step->__end_fct = NULL;
step->__shlib_handle = NULL;
step->__modname = NULL;
step->__min_needed_from = map[cnt].min_needed_from;
step->__max_needed_from = map[cnt].max_needed_from;
step->__min_needed_to = map[cnt].min_needed_to;
step->__max_needed_to = map[cnt].max_needed_to;
/* None of the builtin converters handles stateful encoding. */
step->__stateful = 0;
}

View File

@ -0,0 +1,115 @@
/* Builtin transformations.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
BUILTIN_ALIAS ("UCS4//", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("UCS-4//", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("UCS-4BE//", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("CSUCS4//", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("ISO-10646//", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("10646-1:1993//", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("10646-1:1993/UCS4/", "ISO-10646/UCS4/")
BUILTIN_ALIAS ("OSF00010104//", "ISO-10646/UCS4/") /* level 1 */
BUILTIN_ALIAS ("OSF00010105//", "ISO-10646/UCS4/") /* level 2 */
BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
__gconv_transform_internal_ucs4, 4, 4, 4, 4)
BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
__gconv_transform_ucs4_internal, 4, 4, 4, 4)
BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
__gconv_transform_internal_ucs4le, 4, 4, 4, 4)
BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
__gconv_transform_ucs4le_internal, 4, 4, 4, 4)
BUILTIN_ALIAS ("WCHAR_T//", "INTERNAL")
BUILTIN_ALIAS ("UTF8//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("ISO-IR-193//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("ISO-10646/UTF-8/", "ISO-10646/UTF8/")
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
__gconv_transform_internal_utf8, 4, 4, 1, 6)
BUILTIN_TRANSFORMATION ("ISO-10646/UTF8/", "INTERNAL", 1, "=utf8->INTERNAL",
__gconv_transform_utf8_internal, 1, 6, 4, 4)
BUILTIN_ALIAS ("UCS2//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("OSF00010100//", "ISO-10646/UCS2/") /* level 1 */
BUILTIN_ALIAS ("OSF00010101//", "ISO-10646/UCS2/") /* level 2 */
BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
__gconv_transform_ucs2_internal, 2, 2, 4, 4)
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
__gconv_transform_internal_ucs2, 4, 4, 2, 2)
BUILTIN_ALIAS ("ANSI_X3.4//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("ISO-IR-6//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("ANSI_X3.4-1986//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("ISO_646.IRV:1991//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("ASCII//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("ISO646-US//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("US-ASCII//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("US//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("IBM367//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("CP367//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("CSASCII//", "ANSI_X3.4-1968//")
BUILTIN_ALIAS ("OSF00010020//", "ANSI_X3.4-1968//")
BUILTIN_TRANSFORMATION ("ANSI_X3.4-1968//", "INTERNAL", 1, "=ascii->INTERNAL",
__gconv_transform_ascii_internal, 4, 4, 1, 1)
BUILTIN_TRANSFORMATION ("INTERNAL", "ANSI_X3.4-1968//", 1, "=INTERNAL->ascii",
__gconv_transform_internal_ascii, 4, 4, 1, 1)
#if BYTE_ORDER == BIG_ENDIAN
BUILTIN_ALIAS ("UNICODEBIG//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2BE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//")
BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
"=ucs2reverse->INTERNAL",
__gconv_transform_ucs2reverse_internal, 2, 2, 4, 4)
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
"=INTERNAL->ucs2reverse",
__gconv_transform_internal_ucs2reverse, 4, 4, 2, 2)
#else
BUILTIN_ALIAS ("UNICODELITTLE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//")
BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
"=ucs2reverse->INTERNAL",
__gconv_transform_ucs2reverse_internal, 2, 2, 4, 4)
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
"=INTERNAL->ucs2reverse",
__gconv_transform_internal_ucs2reverse, 4, 4, 2, 2)
#endif

View File

@ -0,0 +1,459 @@
/* Cache handling for iconv modules.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <dlfcn.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <gconv_int.h>
#include <iconvconfig.h>
#include "hash-string.h"
void *__gconv_cache;
static size_t cache_size;
static int cache_malloced;
int
internal_function
__gconv_load_cache (void)
{
int fd;
struct stat64 st;
struct gconvcache_header *header;
/* We cannot use the cache if the GCONV_PATH environment variable is
set. */
__gconv_path_envvar = getenv ("GCONV_PATH");
if (__gconv_path_envvar != NULL)
return -1;
/* See whether the cache file exists. */
fd = open (GCONV_MODULES_CACHE, O_RDONLY);
if (__builtin_expect (fd, 0) == -1)
/* Not available. */
return -1;
#ifdef _POSIX_ASYNC_IO
/* Get information about the file. */
if (__builtin_expect (fstat64 (fd, &st), 0) < 0
/* We do not have to start looking at the file if it cannot contain
at least the cache header. */
|| st.st_size < sizeof (struct gconvcache_header))
{
#endif
close_and_exit:
close (fd);
return -1;
#ifdef _POSIX_ASYNC_IO
}
#endif
/* Make the file content available. */
cache_size = st.st_size;
#ifdef _POSIX_MAPPED_FILES
__gconv_cache = mmap (NULL, cache_size, PROT_READ, MAP_SHARED, fd, 0);
if (__builtin_expect (__gconv_cache == MAP_FAILED, 0))
#endif
{
size_t already_read;
__gconv_cache = malloc (cache_size);
if (__gconv_cache == NULL)
goto close_and_exit;
already_read = 0;
do
{
ssize_t n = read (fd, (char *) __gconv_cache + already_read,
cache_size - already_read);
if (__builtin_expect (n, 0) == -1)
{
free (__gconv_cache);
__gconv_cache = NULL;
goto close_and_exit;
}
already_read += n;
}
while (already_read < cache_size);
cache_malloced = 1;
}
/* We don't need the file descriptor anymore. */
close (fd);
/* Check the consistency. */
header = (struct gconvcache_header *) __gconv_cache;
if (__builtin_expect (header->magic, GCONVCACHE_MAGIC) != GCONVCACHE_MAGIC
|| __builtin_expect (header->string_offset >= cache_size, 0)
|| __builtin_expect (header->hash_offset >= cache_size, 0)
|| __builtin_expect (header->hash_size == 0, 0)
|| __builtin_expect ((header->hash_offset
+ header->hash_size * sizeof (struct hash_entry))
> cache_size, 0)
|| __builtin_expect (header->module_offset >= cache_size, 0)
|| __builtin_expect (header->otherconv_offset > cache_size, 0))
{
if (cache_malloced)
{
free (__gconv_cache);
cache_malloced = 0;
}
#ifdef _POSIX_MAPPED_FILES
else
__munmap (__gconv_cache, cache_size);
#endif
__gconv_cache = NULL;
return -1;
}
/* That worked. */
return 0;
}
static int
internal_function
find_module_idx (const char *str, size_t *idxp)
{
unsigned int idx;
unsigned int hval;
unsigned int hval2;
const struct gconvcache_header *header;
const char *strtab;
const struct hash_entry *hashtab;
unsigned int limit;
header = (const struct gconvcache_header *) __gconv_cache;
strtab = (char *) __gconv_cache + header->string_offset;
hashtab = (struct hash_entry *) ((char *) __gconv_cache
+ header->hash_offset);
hval = hash_string (str);
idx = hval % header->hash_size;
hval2 = 1 + hval % (header->hash_size - 2);
limit = cache_size - header->string_offset;
while (hashtab[idx].string_offset != 0)
if (hashtab[idx].string_offset < limit
&& strcmp (str, strtab + hashtab[idx].string_offset) == 0)
{
*idxp = hashtab[idx].module_idx;
return 0;
}
else
if ((idx += hval2) >= header->hash_size)
idx -= header->hash_size;
/* Nothing found. */
return -1;
}
#ifndef STATIC_GCONV
static int
internal_function
find_module (const char *directory, const char *filename,
struct __gconv_step *result)
{
size_t dirlen = strlen (directory);
size_t fnamelen = strlen (filename) + 1;
char fullname[dirlen + fnamelen];
int status = __GCONV_NOCONV;
char *tmp;
tmp = mempcpy (fullname, directory, dirlen);
tmp += dirlen;
memcpy (tmp, filename, fnamelen);
result->__shlib_handle = __gconv_find_shlib (fullname);
if (result->__shlib_handle != NULL)
{
status = __GCONV_OK;
result->__modname = NULL;
result->__fct = result->__shlib_handle->fct;
result->__init_fct = result->__shlib_handle->init_fct;
result->__end_fct = result->__shlib_handle->end_fct;
result->__data = NULL;
if (result->__init_fct != NULL)
status = result->__init_fct (result);
}
return status;
}
#endif
int
internal_function
__gconv_compare_alias_cache (const char *name1, const char *name2, int *result)
{
size_t name1_idx;
size_t name2_idx;
if (__gconv_cache == NULL)
return -1;
if (find_module_idx (name1, &name1_idx) != 0
|| find_module_idx (name2, &name2_idx) != 0)
*result = strcmp (name1, name2);
else
*result = (int) (name1_idx - name2_idx);
return 0;
}
int
internal_function
__gconv_lookup_cache (const char *toset, const char *fromset,
struct __gconv_step **handle, size_t *nsteps, int flags)
{
const struct gconvcache_header *header;
const char *strtab;
size_t fromidx;
size_t toidx;
const struct module_entry *modtab;
const struct module_entry *from_module;
const struct module_entry *to_module;
struct __gconv_step *result;
if (__gconv_cache == NULL)
/* We have no cache available. */
return __GCONV_NODB;
header = (const struct gconvcache_header *) __gconv_cache;
strtab = (char *) __gconv_cache + header->string_offset;
modtab = (const struct module_entry *) ((char *) __gconv_cache
+ header->module_offset);
if (find_module_idx (fromset, &fromidx) != 0
|| (header->module_offset + (fromidx + 1) * sizeof (struct module_entry)
> cache_size))
return __GCONV_NOCONV;
from_module = &modtab[fromidx];
if (find_module_idx (toset, &toidx) != 0
|| (header->module_offset + (toidx + 1) * sizeof (struct module_entry)
> cache_size))
return __GCONV_NOCONV;
to_module = &modtab[toidx];
/* Avoid copy-only transformations if the user requests. */
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0) && fromidx == toidx)
return __GCONV_NOCONV;
/* If there are special conversions available examine them first. */
if (fromidx != 0 && toidx != 0
&& __builtin_expect (from_module->extra_offset, 0) != 0)
{
/* Search through the list to see whether there is a module
matching the destination character set. */
const struct extra_entry *extra;
/* Note the -1. This is due to the offset added in iconvconfig.
See there for more explanations. */
extra = (const struct extra_entry *) ((char *) __gconv_cache
+ header->otherconv_offset
+ from_module->extra_offset - 1);
while (extra->module_cnt != 0
&& extra->module[extra->module_cnt - 1].outname_offset != toidx)
extra = (const struct extra_entry *) ((char *) extra
+ sizeof (struct extra_entry)
+ (extra->module_cnt
* sizeof (struct extra_entry_module)));
if (extra->module_cnt != 0)
{
/* Use the extra module. First determine how many steps. */
char *fromname;
int idx;
*nsteps = extra->module_cnt;
*handle = result =
(struct __gconv_step *) malloc (extra->module_cnt
* sizeof (struct __gconv_step));
if (result == NULL)
return __GCONV_NOMEM;
fromname = (char *) strtab + from_module->canonname_offset;
idx = 0;
do
{
result[idx].__from_name = fromname;
fromname = result[idx].__to_name =
(char *) strtab + modtab[extra->module[idx].outname_offset].canonname_offset;
result[idx].__counter = 1;
result[idx].__data = NULL;
#ifndef STATIC_GCONV
if (strtab[extra->module[idx].dir_offset] != '\0')
{
/* Load the module, return handle for it. */
int res;
res = find_module (strtab + extra->module[idx].dir_offset,
strtab + extra->module[idx].name_offset,
&result[idx]);
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
{
/* Something went wrong. */
free (result);
goto try_internal;
}
}
else
#endif
/* It's a builtin transformation. */
__gconv_get_builtin_trans (strtab
+ extra->module[idx].name_offset,
&result[idx]);
}
while (++idx < extra->module_cnt);
return __GCONV_OK;
}
}
try_internal:
/* See whether we can convert via the INTERNAL charset. */
if ((fromidx != 0 && __builtin_expect (from_module->fromname_offset, 1) == 0)
|| (toidx != 0 && __builtin_expect (to_module->toname_offset, 1) == 0)
|| (fromidx == 0 && toidx == 0))
/* Not possible. Nothing we can do. */
return __GCONV_NOCONV;
/* We will use up to two modules. Always allocate room for two. */
result = (struct __gconv_step *) malloc (2 * sizeof (struct __gconv_step));
if (result == NULL)
return __GCONV_NOMEM;
*handle = result;
*nsteps = 0;
/* Generate data structure for conversion to INTERNAL. */
if (fromidx != 0)
{
result[0].__from_name = (char *) strtab + from_module->canonname_offset;
result[0].__to_name = (char *) "INTERNAL";
result[0].__counter = 1;
result[0].__data = NULL;
#ifndef STATIC_GCONV
if (strtab[from_module->todir_offset] != '\0')
{
/* Load the module, return handle for it. */
int res = find_module (strtab + from_module->todir_offset,
strtab + from_module->toname_offset,
&result[0]);
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
{
/* Something went wrong. */
free (result);
return res;
}
}
else
#endif
/* It's a builtin transformation. */
__gconv_get_builtin_trans (strtab + from_module->toname_offset,
&result[0]);
++*nsteps;
}
/* Generate data structure for conversion from INTERNAL. */
if (toidx != 0)
{
int idx = *nsteps;
result[idx].__from_name = (char *) "INTERNAL";
result[idx].__to_name = (char *) strtab + to_module->canonname_offset;
result[idx].__counter = 1;
result[idx].__data = NULL;
#ifndef STATIC_GCONV
if (strtab[to_module->fromdir_offset] != '\0')
{
/* Load the module, return handle for it. */
int res = find_module (strtab + to_module->fromdir_offset,
strtab + to_module->fromname_offset,
&result[idx]);
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
{
/* Something went wrong. */
if (idx != 0)
__gconv_release_step (&result[0]);
free (result);
return res;
}
}
else
#endif
/* It's a builtin transformation. */
__gconv_get_builtin_trans (strtab + to_module->fromname_offset,
&result[idx]);
++*nsteps;
}
return __GCONV_OK;
}
/* Free memory allocated for the transformation record. */
void
internal_function
__gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
{
if (__gconv_cache != NULL)
/* The only thing we have to deallocate is the record with the
steps. */
free (steps);
}
/* Free all resources if necessary. */
static void __attribute__ ((unused))
free_mem (void)
{
if (cache_malloced)
free (__gconv_cache);
#ifdef _POSIX_MAPPED_FILES
else
__munmap (__gconv_cache, cache_size);
#endif
}
text_set_element (__libc_subfreeres, free_mem);

View File

@ -0,0 +1,73 @@
/* Charset name normalization.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <ctype.h>
#include <locale.h>
static inline void
strip (char *wp, const char *s)
{
int slash_count = 0;
char old_locale[20], *old_locale_p;
/* Set locale to default C locale. */
old_locale_p = setlocale(LC_ALL, "C");
strncpy(old_locale, old_locale_p, 20);
while (*s != '\0')
{
if (isalnum (*s)
|| *s == '_' || *s == '-' || *s == '.')
*wp++ = toupper (*s);
else if (*s == '/')
{
if (++slash_count == 3)
break;
*wp++ = '/';
}
++s;
}
while (slash_count++ < 2)
*wp++ = '/';
*wp = '\0';
setlocale(LC_ALL, old_locale);
}
static char * __attribute__ ((unused))
upstr (char *dst, const char *str)
{
char *cp = dst;
char old_locale[20], *old_locale_p;
/* Set locale to default C locale. */
old_locale_p = setlocale(LC_ALL, "C");
strncpy(old_locale, old_locale_p, 20);
while ((*cp++ = toupper (*str++)) != '\0')
/* nothing */;
setlocale(LC_ALL, old_locale);
return dst;
}
/* If NAME is an codeset alias expand it. */
extern int __gconv_compare_alias (const char *name1, const char *name2)
internal_function;

View File

@ -0,0 +1,65 @@
/* Release any resource associated with given conversion descriptor.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stdlib.h>
#include <gconv_int.h>
int
internal_function
__gconv_close (__gconv_t cd)
{
struct __gconv_step *srunp;
struct __gconv_step_data *drunp;
size_t nsteps;
/* Free all resources by calling destructor functions and release
the implementations. */
srunp = cd->__steps;
nsteps = cd->__nsteps;
drunp = cd->__data;
do
{
struct __gconv_trans_data *transp;
transp = drunp->__trans;
while (transp != NULL)
{
struct __gconv_trans_data *curp = transp;
transp = transp->__next;
if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
curp->__trans_end_fct (curp->__data);
free (curp);
}
if (!(drunp->__flags & __GCONV_IS_LAST) && drunp->__outbuf != NULL)
free (drunp->__outbuf);
}
while (!((drunp++)->__flags & __GCONV_IS_LAST));
/* Free the data allocated for the descriptor. */
free (cd);
/* Close the participating modules. */
return __gconv_close_transform (srunp, nsteps);
}

View File

@ -0,0 +1,680 @@
/* Handle configuration data.
Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <search.h>
#include <stddef.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <dirent.h>
#include <gconv_int.h>
/* This is the default path where we look for module lists. */
static const char default_gconv_path[] = GCONV_PATH;
/* The path elements, as determined by the __gconv_get_path function.
All path elements end in a slash. */
struct path_elem *__gconv_path_elem;
/* Maximum length of a single path element in __gconv_path_elem. */
size_t __gconv_max_path_elem_len;
/* We use the following struct if we couldn't allocate memory. */
static const struct path_elem empty_path_elem;
/* Name of the file containing the module information in the directories
along the path. */
static const char gconv_conf_filename[] = "gconv-modules";
/* Filename extension for the modules. */
#ifndef MODULE_EXT
# define MODULE_EXT ".so"
#endif
static const char gconv_module_ext[] = MODULE_EXT;
/* We have a few builtin transformations. */
static struct gconv_module builtin_modules[] =
{
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
MinT, MaxT) \
{ \
from_string: From, \
to_string: To, \
cost_hi: Cost, \
cost_lo: INT_MAX, \
module_name: Name \
},
#define BUILTIN_ALIAS(From, To)
#include "gconv_builtin.h"
};
#undef BUILTIN_TRANSFORMATION
#undef BUILTIN_ALIAS
static const char *builtin_aliases[] =
{
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
MinT, MaxT)
#define BUILTIN_ALIAS(From, To) From " " To,
#include "gconv_builtin.h"
};
#ifdef USE_IN_LIBIO
# include <libio/libioP.h>
# define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp)
#endif
/* Value of the GCONV_PATH environment variable. */
const char *__gconv_path_envvar;
/* Test whether there is already a matching module known. */
static int
internal_function
detect_conflict (const char *alias)
{
struct gconv_module *node = __gconv_modules_db;
while (node != NULL)
{
int cmpres = strcmp (alias, node->from_string);
if (cmpres == 0)
/* We have a conflict. */
return 1;
else if (cmpres < 0)
node = node->left;
else
node = node->right;
}
return node != NULL;
}
/* Add new alias. */
static inline void
add_alias (char *rp, void *modules)
{
/* We now expect two more string. The strings are normalized
(converted to UPPER case) and strored in the alias database. */
struct gconv_alias *new_alias;
char *from, *to, *wp;
char old_locale[20], *old_locale_p;
/* Set locale to default C locale. */
old_locale_p = setlocale(LC_ALL, "C");
strncpy(old_locale, old_locale_p, 20);
while (isspace (*rp))
++rp;
from = wp = rp;
while (*rp != '\0' && !isspace (*rp))
*wp++ = toupper (*rp++);
if (*rp == '\0')
{
setlocale(LC_ALL, old_locale);
/* There is no `to' string on the line. Ignore it. */
return;
}
*wp++ = '\0';
to = ++rp;
while (isspace (*rp))
++rp;
while (*rp != '\0' && !isspace (*rp))
*wp++ = toupper (*rp++);
if (to == wp)
{
setlocale(LC_ALL, old_locale);
/* No `to' string, ignore the line. */
return;
}
*wp++ = '\0';
/* Test whether this alias conflicts with any available module. */
if (detect_conflict (from))
{
setlocale(LC_ALL, old_locale);
/* It does conflict, don't add the alias. */
return;
}
new_alias = (struct gconv_alias *) malloc (sizeof (struct gconv_alias) + (wp - from));
if (new_alias != NULL)
{
void **inserted;
new_alias->fromname = memcpy ((char *) new_alias
+ sizeof (struct gconv_alias),
from, wp - from);
new_alias->toname = new_alias->fromname + (to - from);
inserted = (void **) tsearch (new_alias, &__gconv_alias_db,
__gconv_alias_compare);
if (inserted == NULL || *inserted != new_alias)
/* Something went wrong, free this entry. */
free (new_alias);
}
setlocale(LC_ALL, old_locale);
}
/* Insert a data structure for a new module in the search tree. */
static inline void
internal_function
insert_module (struct gconv_module *newp, int tobefreed)
{
struct gconv_module **rootp = &__gconv_modules_db;
while (*rootp != NULL)
{
struct gconv_module *root = *rootp;
int cmpres;
cmpres = strcmp (newp->from_string, root->from_string);
if (cmpres == 0)
{
/* Both strings are identical. Insert the string at the
end of the `same' list if it is not already there. */
while (strcmp (newp->from_string, root->from_string) != 0
|| strcmp (newp->to_string, root->to_string) != 0)
{
rootp = &root->same;
root = *rootp;
if (root == NULL)
break;
}
if (root != NULL)
{
/* This is a no new conversion. But maybe the cost is
better. */
if (newp->cost_hi < root->cost_hi
|| (newp->cost_hi == root->cost_hi
&& newp->cost_lo < root->cost_lo))
{
newp->left = root->left;
newp->right = root->right;
newp->same = root->same;
*rootp = newp;
free (root);
}
else if (tobefreed)
free (newp);
return;
}
break;
}
else if (cmpres < 0)
rootp = &root->left;
else
rootp = &root->right;
}
/* Plug in the new node here. */
*rootp = newp;
}
/* Add new module. */
static void
internal_function
add_module (char *rp, const char *directory, size_t dir_len, void **modules,
size_t *nmodules, int modcounter)
{
/* We expect now
1. `from' name
2. `to' name
3. filename of the module
4. an optional cost value
*/
struct gconv_alias fake_alias;
struct gconv_module *new_module;
char *from, *to, *module, *wp;
int need_ext;
int cost_hi;
char old_locale[20], *old_locale_p;
char *old;
size_t len;
char *new;
/* Set locale to default C locale. */
old_locale_p = setlocale(LC_ALL, "C");
strncpy(old_locale, old_locale_p, 20);
while (isspace (*rp))
++rp;
from = rp;
while (*rp != '\0' && !isspace (*rp))
{
*rp = toupper (*rp);
++rp;
}
if (*rp == '\0')
{
setlocale(LC_ALL, old_locale);
return;
}
*rp++ = '\0';
to = wp = rp;
while (isspace (*rp))
{
setlocale(LC_ALL, old_locale);
++rp;
}
while (*rp != '\0' && !isspace (*rp))
*wp++ = toupper (*rp++);
if (*rp == '\0')
{
setlocale(LC_ALL, old_locale);
return;
}
*wp++ = '\0';
do
++rp;
while (isspace (*rp));
module = wp;
while (*rp != '\0' && !isspace (*rp))
*wp++ = *rp++;
if (*rp == '\0')
{
/* There is no cost, use one by default. */
*wp++ = '\0';
cost_hi = 1;
}
else
{
/* There might be a cost value. */
char *endp;
*wp++ = '\0';
cost_hi = strtol (rp, &endp, 10);
if (rp == endp || cost_hi < 1)
/* No useful information. */
cost_hi = 1;
}
if (module[0] == '\0')
{
setlocale(LC_ALL, old_locale);
/* No module name given. */
return;
}
if (module[0] == '/')
dir_len = 0;
/* See whether we must add the ending. */
need_ext = 0;
if (wp - module < (ptrdiff_t) sizeof (gconv_module_ext)
|| memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,
sizeof (gconv_module_ext)) != 0)
/* We must add the module extension. */
need_ext = sizeof (gconv_module_ext) - 1;
/* See whether we have already an alias with this name defined. */
old = from;
len = strnlen (old, to - from);
new = (char *) alloca (len + 1);
new[len] = '\0';
fake_alias.fromname = (char *) memcpy (new, old, len);
if (tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL)
{
setlocale(LC_ALL, old_locale);
/* This module duplicates an alias. */
return;
}
new_module = (struct gconv_module *) calloc (1,
sizeof (struct gconv_module)
+ (wp - from)
+ dir_len + need_ext);
if (new_module != NULL)
{
char *tmp;
new_module->from_string = tmp = (char *) (new_module + 1);
tmp = memcpy (tmp, from, to - from);
tmp += (to - from);
new_module->to_string = tmp;
tmp = memcpy (tmp, to, module - to);
tmp += (module - to);
new_module->cost_hi = cost_hi;
new_module->cost_lo = modcounter;
new_module->module_name = tmp;
if (dir_len != 0)
{
tmp = memcpy (tmp, directory, dir_len);
tmp += dir_len;
}
tmp = memcpy (tmp, module, wp - module);
tmp += (wp - module);
if (need_ext)
memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
/* Now insert the new module data structure in our search tree. */
insert_module (new_module, 1);
}
setlocale(LC_ALL, old_locale);
}
/* Read the next configuration file. */
static void
internal_function
read_conf_file (const char *filename, const char *directory, size_t dir_len,
void **modules, size_t *nmodules)
{
FILE *fp = fopen (filename, "r");
char *line = NULL;
size_t line_len = 0;
static int modcounter;
char old_locale[20], *old_locale_p;
/* Don't complain if a file is not present or readable, simply silently
ignore it. */
if (fp == NULL)
return;
/* Set locale to default C locale. */
old_locale_p = setlocale(LC_ALL, "C");
strncpy(old_locale, old_locale_p, 20);
/* Process the known entries of the file. Comments start with `#' and
end with the end of the line. Empty lines are ignored. */
while (!feof (fp))
{
char *rp, *endp, *word;
ssize_t n = __getdelim (&line, &line_len, '\n', fp);
if (n < 0)
/* An error occurred. */
break;
rp = line;
/* Terminate the line (excluding comments or newline) by an NUL byte
to simplify the following code. */
endp = strchr (rp, '#');
if (endp != NULL)
*endp = '\0';
else
if (rp[n - 1] == '\n')
rp[n - 1] = '\0';
while (isspace (*rp))
++rp;
/* If this is an empty line go on with the next one. */
if (rp == endp)
continue;
word = rp;
while (*rp != '\0' && !isspace (*rp))
++rp;
if (rp - word == sizeof ("alias") - 1
&& memcmp (word, "alias", sizeof ("alias") - 1) == 0)
add_alias (rp, *modules);
else if (rp - word == sizeof ("module") - 1
&& memcmp (word, "module", sizeof ("module") - 1) == 0)
add_module (rp, directory, dir_len, modules, nmodules, modcounter++);
/* else */
/* Otherwise ignore the line. */
}
free (line);
fclose (fp);
setlocale(LC_ALL, old_locale);
}
/* Determine the directories we are looking for data in. */
void
__gconv_get_path (void)
{
struct path_elem *result;
__LOCK_INIT(static, path_lock);
#ifdef HAVE_DD_LOCK
__lock_acquire(path_lock);
#endif
/* Make sure there wasn't a second thread doing it already. */
result = (struct path_elem *) __gconv_path_elem;
if (result == NULL)
{
/* Determine the complete path first. */
char *gconv_path;
size_t gconv_path_len;
char *elem;
char *oldp;
char *cp;
int nelems;
char *cwd;
size_t cwdlen;
if (__gconv_path_envvar == NULL)
{
char * old = default_gconv_path;
size_t len = strlen (old) + 1;
char *new = (char *) alloca (len);
/* No user-defined path. Make a modifiable copy of the
default path. */
gconv_path = (char *) memcpy (new, old, len);
gconv_path_len = sizeof (default_gconv_path);
cwd = NULL;
cwdlen = 0;
}
else
{
/* Append the default path to the user-defined path. */
size_t user_len = strlen (__gconv_path_envvar);
char *tmp;
gconv_path_len = user_len + 1 + sizeof (default_gconv_path);
gconv_path = alloca (gconv_path_len);
tmp = memcpy (gconv_path, __gconv_path_envvar,
user_len);
tmp += user_len;
memcpy (tmp, ":", 1);
tmp += 1;
memcpy (tmp,
default_gconv_path, sizeof (default_gconv_path));
cwd = getcwd (NULL, 0);
cwdlen = strlen (cwd);
}
assert (default_gconv_path[0] == '/');
/* In a first pass we calculate the number of elements. */
oldp = NULL;
cp = strchr (gconv_path, ':');
nelems = 1;
while (cp != NULL)
{
if (cp != oldp + 1)
++nelems;
oldp = cp;
cp = strchr (cp + 1, ':');
}
/* Allocate the memory for the result. */
result = (struct path_elem *) malloc ((nelems + 1)
* sizeof (struct path_elem)
+ gconv_path_len + nelems
+ (nelems - 1) * (cwdlen + 1));
if (result != NULL)
{
char *strspace = (char *) &result[nelems + 1];
int n = 0;
/* Separate the individual parts. */
__gconv_max_path_elem_len = 0;
elem = strtok_r (gconv_path, ":", &gconv_path);
assert (elem != NULL);
do
{
result[n].name = strspace;
if (elem[0] != '/')
{
assert (cwd != NULL);
strspace = memcpy (strspace, cwd, cwdlen);
strspace += cwdlen;
*strspace++ = '/';
}
strspace = strcpy (strspace, elem);
while(*strspace != '\0') strspace++;
if (strspace[-1] != '/')
*strspace++ = '/';
result[n].len = strspace - result[n].name;
if (result[n].len > __gconv_max_path_elem_len)
__gconv_max_path_elem_len = result[n].len;
*strspace++ = '\0';
++n;
}
while ((elem = strtok_r (NULL, ":", &gconv_path)) != NULL);
result[n].name = NULL;
result[n].len = 0;
}
__gconv_path_elem = result ?: (struct path_elem *) &empty_path_elem;
if (cwd != NULL)
free (cwd);
}
#ifdef HAVE_DD_LOCK
__lock_release(path_lock);
#endif
}
/* Read all configuration files found in the user-specified and the default
path. */
void
__gconv_read_conf (void)
{
void *modules = NULL;
size_t nmodules = 0;
int save_errno = errno;
size_t cnt;
char *filename;
char *tmp;
const char *elem;
size_t elem_len;
/* First see whether we should use the cache. */
if (__gconv_load_cache () == 0)
{
/* Yes, we are done. */
__set_errno (save_errno);
return;
}
#ifndef STATIC_GCONV
/* Find out where we have to look. */
if (__gconv_path_elem == NULL)
__gconv_get_path ();
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
{
elem = __gconv_path_elem[cnt].name;
elem_len = __gconv_path_elem[cnt].len;
/* No slash needs to be inserted between elem and gconv_conf_filename;
elem already ends in a slash. */
filename = alloca (elem_len + sizeof (gconv_conf_filename));
tmp = memcpy (filename, elem, elem_len);
tmp += elem_len;
memcpy (tmp, gconv_conf_filename, sizeof (gconv_conf_filename));
/* Read the next configuration file. */
read_conf_file (filename, elem, elem_len, &modules, &nmodules);
}
#endif
/* Add the internal modules. */
for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
++cnt)
{
struct gconv_alias fake_alias;
fake_alias.fromname = (char *) builtin_modules[cnt].from_string;
if (tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
!= NULL)
/* It'll conflict so don't add it. */
continue;
insert_module (&builtin_modules[cnt], 0);
}
/* Add aliases for builtin conversions. */
cnt = sizeof (builtin_aliases) / sizeof (builtin_aliases[0]);
while (cnt > 0)
{
char * old = builtin_aliases[--cnt];
size_t len = strlen (old) + 1;
char *new = (char *) alloca (len);
char *copy = (char *) memcpy (new, old, len);
add_alias (copy, modules);
}
/* Restore the error number. */
__set_errno (save_errno);
}
/* Free all resources if necessary. */
static void __attribute__ ((unused))
free_mem (void)
{
if (__gconv_path_elem != NULL && __gconv_path_elem != &empty_path_elem)
free ((void *) __gconv_path_elem);
}
text_set_element (__libc_subfreeres, free_mem);

View File

@ -0,0 +1,803 @@
/* Provide access to the collection of available transformation modules.
Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <limits.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <dirent.h>
#include <dlfcn.h>
#include <gconv_int.h>
#include <gconv_charset.h>
/* Simple data structure for alias mapping. We have two names, `from'
and `to'. */
void *__gconv_alias_db;
/* Array with available modules. */
struct gconv_module *__gconv_modules_db;
/* We modify global data. */
__LOCK_INIT(static, lock);
/* Function for searching alias. */
int
__gconv_alias_compare (const void *p1, const void *p2)
{
const struct gconv_alias *s1 = (const struct gconv_alias *) p1;
const struct gconv_alias *s2 = (const struct gconv_alias *) p2;
return strcmp (s1->fromname, s2->fromname);
}
/* To search for a derivation we create a list of intermediate steps.
Each element contains a pointer to the element which precedes it
in the derivation order. */
struct derivation_step
{
const char *result_set;
size_t result_set_len;
int cost_lo;
int cost_hi;
struct gconv_module *code;
struct derivation_step *last;
struct derivation_step *next;
};
#define NEW_STEP(result, hi, lo, module, last_mod) \
({ struct derivation_step *newp = alloca (sizeof (struct derivation_step)); \
newp->result_set = result; \
newp->result_set_len = strlen (result); \
newp->cost_hi = hi; \
newp->cost_lo = lo; \
newp->code = module; \
newp->last = last_mod; \
newp->next = NULL; \
newp; })
/* If a specific transformation is used more than once we should not need
to start looking for it again. Instead cache each successful result. */
struct known_derivation
{
const char *from;
const char *to;
struct __gconv_step *steps;
size_t nsteps;
};
/* Compare function for database of found derivations. */
static int
derivation_compare (const void *p1, const void *p2)
{
const struct known_derivation *s1 = (const struct known_derivation *) p1;
const struct known_derivation *s2 = (const struct known_derivation *) p2;
int result;
result = strcmp (s1->from, s2->from);
if (result == 0)
result = strcmp (s1->to, s2->to);
return result;
}
/* The search tree for known derivations. */
static void *known_derivations;
/* Look up whether given transformation was already requested before. */
static int
internal_function
derivation_lookup (const char *fromset, const char *toset,
struct __gconv_step **handle, size_t *nsteps)
{
struct known_derivation key = { fromset, toset, NULL, 0 };
struct known_derivation **result;
result = tfind (&key, &known_derivations, derivation_compare);
if (result == NULL)
return __GCONV_NOCONV;
*handle = (*result)->steps;
*nsteps = (*result)->nsteps;
/* Please note that we return GCONV_OK even if the last search for
this transformation was unsuccessful. */
return __GCONV_OK;
}
/* Add new derivation to list of known ones. */
static void
internal_function
add_derivation (const char *fromset, const char *toset,
struct __gconv_step *handle, size_t nsteps)
{
struct known_derivation *new_deriv;
size_t fromset_len = strlen (fromset) + 1;
size_t toset_len = strlen (toset) + 1;
new_deriv = (struct known_derivation *)
malloc (sizeof (struct known_derivation) + fromset_len + toset_len);
if (new_deriv != NULL)
{
char *tmp;
new_deriv->from = (char *) (new_deriv + 1);
tmp = memcpy (new_deriv + 1, fromset, fromset_len);
tmp += fromset_len;
new_deriv->to = memcpy (tmp,
toset, toset_len);
new_deriv->steps = handle;
new_deriv->nsteps = nsteps;
if (tsearch (new_deriv, &known_derivations, derivation_compare)
== NULL)
/* There is some kind of memory allocation problem. */
free (new_deriv);
}
/* Please note that we don't complain if the allocation failed. This
is not tragically but in case we use the memory debugging facilities
not all memory will be freed. */
}
static void
free_derivation (void *p)
{
struct known_derivation *deriv = (struct known_derivation *) p;
size_t cnt;
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
if (deriv->steps[cnt].__counter > 0
&& deriv->steps[cnt].__end_fct != NULL)
deriv->steps[cnt].__end_fct (&deriv->steps[cnt]);
/* Free the name strings. */
free ((char *) deriv->steps[0].__from_name);
free ((char *) deriv->steps[deriv->nsteps - 1].__to_name);
free ((struct __gconv_step *) deriv->steps);
free (deriv);
}
/* Decrement the reference count for a single step in a steps array. */
void
internal_function
__gconv_release_step (struct __gconv_step *step)
{
if (--step->__counter == 0)
{
/* Call the destructor. */
if (step->__end_fct != NULL)
step->__end_fct (step);
#ifndef STATIC_GCONV
/* Skip builtin modules; they are not reference counted. */
if (step->__shlib_handle != NULL)
{
/* Release the loaded module. */
__gconv_release_shlib (step->__shlib_handle);
step->__shlib_handle = NULL;
}
#endif
}
}
static int
internal_function
gen_steps (struct derivation_step *best, const char *toset,
const char *fromset, struct __gconv_step **handle, size_t *nsteps)
{
size_t step_cnt = 0;
struct __gconv_step *result;
struct derivation_step *current;
int status = __GCONV_NOMEM;
/* First determine number of steps. */
for (current = best; current->last != NULL; current = current->last)
++step_cnt;
result = (struct __gconv_step *) malloc (sizeof (struct __gconv_step)
* step_cnt);
if (result != NULL)
{
int failed = 0;
status = __GCONV_OK;
*nsteps = step_cnt;
current = best;
while (step_cnt-- > 0)
{
result[step_cnt].__from_name = (step_cnt == 0
? strdup (fromset)
: (char *)current->last->result_set);
result[step_cnt].__to_name = (step_cnt + 1 == *nsteps
? strdup (current->result_set)
: result[step_cnt + 1].__from_name);
result[step_cnt].__counter = 1;
result[step_cnt].__data = NULL;
#ifndef STATIC_GCONV
if (current->code->module_name[0] == '/')
{
/* Load the module, return handle for it. */
struct __gconv_loaded_object *shlib_handle =
__gconv_find_shlib (current->code->module_name);
if (shlib_handle == NULL)
{
failed = 1;
break;
}
result[step_cnt].__shlib_handle = shlib_handle;
result[step_cnt].__modname = shlib_handle->name;
result[step_cnt].__fct = shlib_handle->fct;
result[step_cnt].__init_fct = shlib_handle->init_fct;
result[step_cnt].__end_fct = shlib_handle->end_fct;
/* Call the init function. */
if (result[step_cnt].__init_fct != NULL)
{
status = result[step_cnt].__init_fct (&result[step_cnt]);
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
{
failed = 1;
/* Make sure we unload this modules. */
--step_cnt;
result[step_cnt].__end_fct = NULL;
break;
}
}
}
else
#endif
/* It's a builtin transformation. */
__gconv_get_builtin_trans (current->code->module_name,
&result[step_cnt]);
current = current->last;
}
if (__builtin_expect (failed, 0) != 0)
{
/* Something went wrong while initializing the modules. */
while (++step_cnt < *nsteps)
__gconv_release_step (&result[step_cnt]);
free (result);
*nsteps = 0;
*handle = NULL;
if (status == __GCONV_OK)
status = __GCONV_NOCONV;
}
else
*handle = result;
}
else
{
*nsteps = 0;
*handle = NULL;
}
return status;
}
#ifndef STATIC_GCONV
static int
internal_function
increment_counter (struct __gconv_step *steps, size_t nsteps)
{
/* Increment the user counter. */
size_t cnt = nsteps;
int result = __GCONV_OK;
while (cnt-- > 0)
{
struct __gconv_step *step = &steps[cnt];
if (step->__counter++ == 0)
{
/* Skip builtin modules. */
if (step->__modname != NULL)
{
/* Reopen a previously used module. */
step->__shlib_handle = __gconv_find_shlib (step->__modname);
if (step->__shlib_handle == NULL)
{
/* Oops, this is the second time we use this module
(after unloading) and this time loading failed!? */
--step->__counter;
while (++cnt < nsteps)
__gconv_release_step (&steps[cnt]);
result = __GCONV_NOCONV;
break;
}
/* The function addresses defined by the module may
have changed. */
step->__fct = step->__shlib_handle->fct;
step->__init_fct = step->__shlib_handle->init_fct;
step->__end_fct = step->__shlib_handle->end_fct;
}
if (step->__init_fct != NULL)
step->__init_fct (step);
}
}
return result;
}
#endif
/* The main function: find a possible derivation from the `fromset' (either
the given name or the alias) to the `toset' (again with alias). */
static int
internal_function
find_derivation (const char *toset, const char *toset_expand,
const char *fromset, const char *fromset_expand,
struct __gconv_step **handle, size_t *nsteps)
{
struct derivation_step *first, *current, **lastp, *solution = NULL;
int best_cost_hi = INT_MAX;
int best_cost_lo = INT_MAX;
int result;
/* Look whether an earlier call to `find_derivation' has already
computed a possible derivation. If so, return it immediately. */
result = derivation_lookup (fromset_expand ?: fromset, toset_expand ?: toset,
handle, nsteps);
if (result == __GCONV_OK)
{
#ifndef STATIC_GCONV
result = increment_counter (*handle, *nsteps);
#endif
return result;
}
/* The task is to find a sequence of transformations, backed by the
existing modules - whether builtin or dynamically loadable -,
starting at `fromset' (or `fromset_expand') and ending at `toset'
(or `toset_expand'), and with minimal cost.
For computer scientists, this is a shortest path search in the
graph where the nodes are all possible charsets and the edges are
the transformations listed in __gconv_modules_db.
For now we use a simple algorithm with quadratic runtime behaviour.
A breadth-first search, starting at `fromset' and `fromset_expand'.
The list starting at `first' contains all nodes that have been
visited up to now, in the order in which they have been visited --
excluding the goal nodes `toset' and `toset_expand' which get
managed in the list starting at `solution'.
`current' walks through the list starting at `first' and looks
which nodes are reachable from the current node, adding them to
the end of the list [`first' or `solution' respectively] (if
they are visited the first time) or updating them in place (if
they have have already been visited).
In each node of either list, cost_lo and cost_hi contain the
minimum cost over any paths found up to now, starting at `fromset'
or `fromset_expand', ending at that node. best_cost_lo and
best_cost_hi represent the minimum over the elements of the
`solution' list. */
if (fromset_expand != NULL)
{
first = NEW_STEP (fromset_expand, 0, 0, NULL, NULL);
first->next = NEW_STEP (fromset, 0, 0, NULL, NULL);
lastp = &first->next->next;
}
else
{
first = NEW_STEP (fromset, 0, 0, NULL, NULL);
lastp = &first->next;
}
for (current = first; current != NULL; current = current->next)
{
/* Now match all the available module specifications against the
current charset name. If any of them matches check whether
we already have a derivation for this charset. If yes, use the
one with the lower costs. Otherwise add the new charset at the
end.
The module database is organized in a tree form which allows
searching for prefixes. So we search for the first entry with a
matching prefix and any other matching entry can be found from
this place. */
struct gconv_module *node;
/* Maybe it is not necessary anymore to look for a solution for
this entry since the cost is already as high (or higher) as
the cost for the best solution so far. */
if (current->cost_hi > best_cost_hi
|| (current->cost_hi == best_cost_hi
&& current->cost_lo >= best_cost_lo))
continue;
node = __gconv_modules_db;
while (node != NULL)
{
int cmpres = strcmp (current->result_set, node->from_string);
if (cmpres == 0)
{
/* Walk through the list of modules with this prefix and
try to match the name. */
struct gconv_module *runp;
/* Check all the modules with this prefix. */
runp = node;
do
{
const char *result_set = (strcmp (runp->to_string, "-") == 0
? (toset_expand ?: toset)
: runp->to_string);
int cost_hi = runp->cost_hi + current->cost_hi;
int cost_lo = runp->cost_lo + current->cost_lo;
struct derivation_step *step;
/* We managed to find a derivation. First see whether
we have reached one of the goal nodes. */
if (strcmp (result_set, toset) == 0
|| (toset_expand != NULL
&& strcmp (result_set, toset_expand) == 0))
{
/* Append to the `solution' list if there
is no entry with this name. */
for (step = solution; step != NULL; step = step->next)
if (strcmp (result_set, step->result_set) == 0)
break;
if (step == NULL)
{
step = NEW_STEP (result_set,
cost_hi, cost_lo,
runp, current);
step->next = solution;
solution = step;
}
else if (step->cost_hi > cost_hi
|| (step->cost_hi == cost_hi
&& step->cost_lo > cost_lo))
{
/* A better path was found for the node,
on the `solution' list. */
step->code = runp;
step->last = current;
step->cost_hi = cost_hi;
step->cost_lo = cost_lo;
}
/* Update best_cost accordingly. */
if (cost_hi < best_cost_hi
|| (cost_hi == best_cost_hi
&& cost_lo < best_cost_lo))
{
best_cost_hi = cost_hi;
best_cost_lo = cost_lo;
}
}
else if (cost_hi < best_cost_hi
|| (cost_hi == best_cost_hi
&& cost_lo < best_cost_lo))
{
/* Append at the end of the `first' list if there
is no entry with this name. */
for (step = first; step != NULL; step = step->next)
if (strcmp (result_set, step->result_set) == 0)
break;
if (step == NULL)
{
*lastp = NEW_STEP (result_set,
cost_hi, cost_lo,
runp, current);
lastp = &(*lastp)->next;
}
else if (step->cost_hi > cost_hi
|| (step->cost_hi == cost_hi
&& step->cost_lo > cost_lo))
{
/* A better path was found for the node,
on the `first' list. */
step->code = runp;
step->last = current;
/* Update the cost for all steps. */
for (step = first; step != NULL;
step = step->next)
/* But don't update the start nodes. */
if (step->code != NULL)
{
struct derivation_step *back;
int hi, lo;
hi = step->code->cost_hi;
lo = step->code->cost_lo;
for (back = step->last; back->code != NULL;
back = back->last)
{
hi += back->code->cost_hi;
lo += back->code->cost_lo;
}
step->cost_hi = hi;
step->cost_lo = lo;
}
/* Likewise for the nodes on the solution list.
Also update best_cost accordingly. */
for (step = solution; step != NULL;
step = step->next)
{
step->cost_hi = (step->code->cost_hi
+ step->last->cost_hi);
step->cost_lo = (step->code->cost_lo
+ step->last->cost_lo);
if (step->cost_hi < best_cost_hi
|| (step->cost_hi == best_cost_hi
&& step->cost_lo < best_cost_lo))
{
best_cost_hi = step->cost_hi;
best_cost_lo = step->cost_lo;
}
}
}
}
runp = runp->same;
}
while (runp != NULL);
break;
}
else if (cmpres < 0)
node = node->left;
else
node = node->right;
}
}
if (solution != NULL)
{
/* We really found a way to do the transformation. */
/* Choose the best solution. This is easy because we know that
the solution list has at most length 2 (one for every possible
goal node). */
if (solution->next != NULL)
{
struct derivation_step *solution2 = solution->next;
if (solution2->cost_hi < solution->cost_hi
|| (solution2->cost_hi == solution->cost_hi
&& solution2->cost_lo < solution->cost_lo))
solution = solution2;
}
/* Now build a data structure describing the transformation steps. */
result = gen_steps (solution, toset_expand ?: toset,
fromset_expand ?: fromset, handle, nsteps);
}
else
{
/* We haven't found a transformation. Clear the result values. */
*handle = NULL;
*nsteps = 0;
}
/* Add result in any case to list of known derivations. */
add_derivation (fromset_expand ?: fromset, toset_expand ?: toset,
*handle, *nsteps);
return result;
}
/* Control of initialization. */
__libc_once_define (static, once);
static const char *
do_lookup_alias (const char *name)
{
struct gconv_alias key;
struct gconv_alias **found;
key.fromname = (char *) name;
found = tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
return found != NULL ? (*found)->toname : NULL;
}
int
internal_function
__gconv_compare_alias (const char *name1, const char *name2)
{
int result;
/* Ensure that the configuration data is read. */
__libc_once (once, __gconv_read_conf);
if (__gconv_compare_alias_cache (name1, name2, &result) != 0)
result = strcmp (do_lookup_alias (name1) ?: name1,
do_lookup_alias (name2) ?: name2);
return result;
}
int
internal_function
__gconv_find_transform (const char *toset, const char *fromset,
struct __gconv_step **handle, size_t *nsteps,
int flags)
{
const char *fromset_expand;
const char *toset_expand;
int result;
/* Ensure that the configuration data is read. */
__libc_once (once, __gconv_read_conf);
/* Acquire the lock. */
#ifdef HAVE_DD_LOCK
__lock_acquire(lock);
#endif
result = __gconv_lookup_cache (toset, fromset, handle, nsteps, flags);
if (result != __GCONV_NODB)
{
/* We have a cache and could resolve the request, successful or not. */
#ifdef HAVE_DD_LOCK
__lock_release(lock);
#endif
return result;
}
/* If we don't have a module database return with an error. */
if (__gconv_modules_db == NULL)
{
#ifdef HAVE_DD_LOCK
__lock_release(lock);
#endif
return __GCONV_NOCONV;
}
/* See whether the names are aliases. */
fromset_expand = do_lookup_alias (fromset);
toset_expand = do_lookup_alias (toset);
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0)
/* We are not supposed to create a pseudo transformation (means
copying) when the input and output character set are the same. */
&& (strcmp (toset, fromset) == 0
|| (toset_expand != NULL && strcmp (toset_expand, fromset) == 0)
|| (fromset_expand != NULL
&& (strcmp (toset, fromset_expand) == 0
|| (toset_expand != NULL
&& strcmp (toset_expand, fromset_expand) == 0)))))
{
/* Both character sets are the same. */
#ifdef HAVE_DD_LOCK
__lock_release(lock);
#endif
return __GCONV_NOCONV;
}
result = find_derivation (toset, toset_expand, fromset, fromset_expand,
handle, nsteps);
/* Release the lock. */
#ifdef HAVE_DD_LOCK
__lock_release(lock);
#endif
/* The following code is necessary since `find_derivation' will return
GCONV_OK even when no derivation was found but the same request
was processed before. I.e., negative results will also be cached. */
return (result == __GCONV_OK
? (*handle == NULL ? __GCONV_NOCONV : __GCONV_OK)
: result);
}
/* Release the entries of the modules list. */
int
internal_function
__gconv_close_transform (struct __gconv_step *steps, size_t nsteps)
{
int result = __GCONV_OK;
size_t cnt;
/* Acquire the lock. */
#ifdef HAVE_DD_LOCK
__lock_acquire(lock);
#endif
#ifndef STATIC_GCONV
cnt = nsteps;
while (cnt-- > 0)
__gconv_release_step (&steps[cnt]);
#endif
/* If we use the cache we free a bit more since we don't keep any
transformation records around, they are cheap enough to
recreate. */
__gconv_release_cache (steps, nsteps);
/* Release the lock. */
#ifdef HAVE_DD_LOCK
__lock_release(lock);
#endif
return result;
}
/* Free the modules mentioned. */
static void
internal_function
free_modules_db (struct gconv_module *node)
{
if (node->left != NULL)
free_modules_db (node->left);
if (node->right != NULL)
free_modules_db (node->right);
do
{
struct gconv_module *act = node;
node = node->same;
if (act->module_name[0] == '/')
free (act);
}
while (node != NULL);
}
/* Free all resources if necessary. */
static void __attribute__ ((unused))
free_mem (void)
{
if (__gconv_alias_db != NULL)
tdestroy (__gconv_alias_db, free);
if (__gconv_modules_db != NULL)
free_modules_db (__gconv_modules_db);
if (known_derivations != NULL)
tdestroy (known_derivations, free_derivation);
}
text_set_element (__libc_subfreeres, free_mem);

View File

@ -0,0 +1,237 @@
/* Handle loading/unloading of shared object for transformation.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <dlfcn.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <bits/libc-lock.h>
#include <sys/param.h>
#include <ltdl.h>
#include <gconv_int.h>
#ifdef DEBUG
/* For debugging purposes. */
static void print_all (void);
#endif
/* This is a tuning parameter. If a transformation module is not used
anymore it gets not immediately unloaded. Instead we wait a certain
number of load attempts for further modules. If none of the
subsequent load attempts name the same object it finally gets unloaded.
Otherwise it is still available which hopefully is the frequent case.
The following number is the number of unloading attempts we wait
before unloading. */
#define TRIES_BEFORE_UNLOAD 2
/* Array of loaded objects. This is shared by all threads so we have
to use semaphores to access it. */
static void *loaded;
/* Comparison function for searching `loaded_object' tree. */
static int
known_compare (const void *p1, const void *p2)
{
const struct __gconv_loaded_object *s1 =
(const struct __gconv_loaded_object *) p1;
const struct __gconv_loaded_object *s2 =
(const struct __gconv_loaded_object *) p2;
return strcmp (s1->name, s2->name);
}
/* Open the gconv database if necessary. A non-negative return value
means success. */
struct __gconv_loaded_object *
internal_function
__gconv_find_shlib (const char *name)
{
struct __gconv_loaded_object *found;
void *keyp;
/* Search the tree of shared objects previously requested. Data in
the tree are `loaded_object' structures, whose first member is a
`const char *', the lookup key. The search returns a pointer to
the tree node structure; the first member of the is a pointer to
our structure (i.e. what will be a `loaded_object'); since the
first member of that is the lookup key string, &FCT_NAME is close
enough to a pointer to our structure to use as a lookup key that
will be passed to `known_compare' (above). */
keyp = tfind (&name, &loaded, known_compare);
if (keyp == NULL)
{
/* This name was not known before. */
size_t namelen = strlen (name) + 1;
found = malloc (sizeof (struct __gconv_loaded_object) + namelen);
if (found != NULL)
{
/* Point the tree node at this new structure. */
found->name = (char *) memcpy (found + 1, name, namelen);
found->counter = -TRIES_BEFORE_UNLOAD - 1;
found->handle = NULL;
if (__builtin_expect (tsearch (found, &loaded, known_compare)
== NULL, 0))
{
/* Something went wrong while inserting the entry. */
free (found);
found = NULL;
}
}
}
else
found = *(struct __gconv_loaded_object **) keyp;
/* Try to load the shared object if the usage count is 0. This
implies that if the shared object is not loadable, the handle is
NULL and the usage count > 0. */
if (found != NULL)
{
if (found->counter < -TRIES_BEFORE_UNLOAD)
{
assert (found->handle == NULL);
found->handle = __libc_dlopen (found->name);
if (found->handle != NULL)
{
found->fct = __libc_dlsym (found->handle, "gconv");
if (found->fct == NULL)
{
/* Argh, no conversion function. There is something
wrong here. */
__gconv_release_shlib (found);
found = NULL;
}
else
{
found->init_fct = __libc_dlsym (found->handle, "gconv_init");
found->end_fct = __libc_dlsym (found->handle, "gconv_end");
/* We have succeeded in loading the shared object. */
found->counter = 1;
}
}
else
/* Error while loading the shared object. */
found = NULL;
}
else if (found->handle != NULL)
found->counter = MAX (found->counter + 1, 1);
}
return found;
}
/* This is very ugly but the tsearch functions provide no way to pass
information to the walker function. So we use a global variable.
It is MT safe since we use a lock. */
static struct __gconv_loaded_object *release_handle;
static void
do_release_shlib (void *nodep, VISIT value, int level)
{
struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
if (value != preorder && value != leaf)
return;
if (obj == release_handle)
{
/* This is the object we want to unload. Now decrement the
reference counter. */
assert (obj->counter > 0);
--obj->counter;
}
else if (obj->counter <= 0 && obj->counter >= -TRIES_BEFORE_UNLOAD
&& --obj->counter < -TRIES_BEFORE_UNLOAD && obj->handle != NULL)
{
/* Unload the shared object. */
__libc_dlclose (obj->handle);
obj->handle = NULL;
}
}
/* Notify system that a shared object is not longer needed. */
void
internal_function
__gconv_release_shlib (struct __gconv_loaded_object *handle)
{
/* Urgh, this is ugly but we have no other possibility. */
release_handle = handle;
/* Process all entries. Please note that we also visit entries
with release counts <= 0. This way we can finally unload them
if necessary. */
twalk (loaded, (void *) do_release_shlib);
}
/* We run this if we debug the memory allocation. */
static void
do_release_all (void *nodep)
{
struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;
/* Unload the shared object. */
if (obj->handle != NULL)
__libc_dlclose (obj->handle);
free (obj);
}
static void __attribute__ ((unused))
free_mem (void)
{
tdestroy (loaded, do_release_all);
}
text_set_element (__libc_subfreeres, free_mem);
#ifdef DEBUG
static void
do_print (const void *nodep, VISIT value, int level)
{
struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
printf ("%10s: \"%s\", %d\n",
value == leaf ? "leaf" :
value == preorder ? "preorder" :
value == postorder ? "postorder" : "endorder",
obj->name, obj->counter);
}
static void
print_all (void)
{
__twalk (loaded, do_print);
}
#endif

View File

@ -0,0 +1,288 @@
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GCONV_INT_H
#define _GCONV_INT_H 1
#include "gconv.h"
#include <libc-symbols.h>
__BEGIN_DECLS
/* Type to represent search path. */
struct path_elem
{
const char *name;
size_t len;
};
/* Variable with search path for `gconv' implementation. */
extern struct path_elem *__gconv_path_elem;
/* Maximum length of a single path element. */
extern size_t __gconv_max_path_elem_len;
/* Structure for alias definition. Simply two strings. */
struct gconv_alias
{
char *fromname;
char *toname;
};
/* How many character should be conveted in one call? */
#define GCONV_NCHAR_GOAL 8160
/* Structure describing one loaded shared object. This normally are
objects to perform conversation but as a special case the db shared
object is also handled. */
struct __gconv_loaded_object
{
/* Name of the object. It must be the first structure element. */
const char *name;
/* Reference counter for the db functionality. If no conversion is
needed we unload the db library. */
int counter;
/* The handle for the shared object. */
void *handle;
/* Pointer to the functions the module defines. */
__gconv_fct fct;
__gconv_init_fct init_fct;
__gconv_end_fct end_fct;
};
/* Description for an available conversion module. */
struct gconv_module
{
const char *from_string;
const char *to_string;
int cost_hi;
int cost_lo;
const char *module_name;
struct gconv_module *left; /* Prefix smaller. */
struct gconv_module *same; /* List of entries with identical prefix. */
struct gconv_module *right; /* Prefix larger. */
};
/* Internal data structure to represent transliteration module. */
struct trans_struct
{
const char *name;
struct trans_struct *next;
const char **csnames;
size_t ncsnames;
__gconv_trans_fct trans_fct;
__gconv_trans_context_fct trans_context_fct;
__gconv_trans_init_fct trans_init_fct;
__gconv_trans_end_fct trans_end_fct;
};
/* Flags for `gconv_open'. */
enum
{
GCONV_AVOID_NOCONV = 1 << 0
};
/* Global variables. */
/* Database of alias names. */
extern void *__gconv_alias_db;
/* Array with available modules. */
extern size_t __gconv_nmodules;
extern struct gconv_module *__gconv_modules_db;
/* Value of the GCONV_PATH environment variable. */
extern const char *__gconv_path_envvar;
/* The gconv functions expects the name to be in upper case and complete,
including the trailing slashes if necessary. */
#define norm_add_slashes(str,suffix) \
({ \
const char *cp = (str); \
char *result; \
char *tmp; \
size_t cnt = 0; \
size_t suffix_len = (suffix) == NULL ? 0 : strlen (suffix); \
\
while (*cp != '\0') \
if (*cp++ == '/') \
++cnt; \
\
tmp = result = alloca (cp - (str) + 3 + suffix_len); \
cp = (str); \
while (*cp != '\0') \
*tmp++ = __toupper_l (*cp++, &_nl_C_locobj); \
if (cnt < 2) \
{ \
*tmp++ = '/'; \
if (cnt < 1) \
{ \
*tmp++ = '/'; \
if (suffix != NULL) \
{ \
tmp = memcpy (tmp, suffix, suffix_len); \
tmp += suffix_len; \
} \
} \
} \
*tmp = '\0'; \
result; \
})
/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */
extern int __gconv_open (const char *toset, const char *fromset,
__gconv_t *handle, int flags)
internal_function;
/* Free resources associated with transformation descriptor CD. */
extern int __gconv_close (__gconv_t cd)
internal_function;
/* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF
according to rules described by CD and place up to *OUTBYTESLEFT
bytes in buffer starting at *OUTBUF. Return number of non-identical
conversions in *IRREVERSIBLE if this pointer is not null. */
extern int __gconv (__gconv_t cd, const unsigned char **inbuf,
const unsigned char *inbufend, unsigned char **outbuf,
unsigned char *outbufend, size_t *irreversible)
internal_function;
/* Return in *HANDLE a pointer to an array with *NSTEPS elements describing
the single steps necessary for transformation from FROMSET to TOSET. */
extern int __gconv_find_transform (const char *toset, const char *fromset,
struct __gconv_step **handle,
size_t *nsteps, int flags)
internal_function;
/* Search for transformation in cache data. */
extern int __gconv_lookup_cache (const char *toset, const char *fromset,
struct __gconv_step **handle, size_t *nsteps,
int flags)
internal_function;
/* Compare the two name for whether they are after alias expansion the
same. This function uses the cache and fails if none is
loaded. */
extern int __gconv_compare_alias_cache (const char *name1, const char *name2,
int *result) internal_function;
/* Free data associated with a step's structure. */
extern void __gconv_release_step (struct __gconv_step *step)
internal_function;
/* Read all the configuration data and cache it. */
extern void __gconv_read_conf (void);
/* Try to read module cache file. */
extern int __gconv_load_cache (void) internal_function;
/* Determine the directories we are looking in. */
extern void __gconv_get_path (void);
/* Comparison function to search alias. */
extern int __gconv_alias_compare (const void *p1, const void *p2);
/* Clear reference to transformation step implementations which might
cause the code to be unloaded. */
extern int __gconv_close_transform (struct __gconv_step *steps,
size_t nsteps)
internal_function;
/* Free all resources allocated for the transformation record when
using the cache. */
extern void __gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
internal_function;
/* Load shared object named by NAME. If already loaded increment reference
count. */
extern struct __gconv_loaded_object *__gconv_find_shlib (const char *name)
internal_function;
/* Release shared object. If no further reference is available unload
the object. */
extern void __gconv_release_shlib (struct __gconv_loaded_object *handle)
internal_function;
/* Fill STEP with information about builtin module with NAME. */
extern void __gconv_get_builtin_trans (const char *name,
struct __gconv_step *step)
internal_function;
/* Try to load transliteration step module. */
extern int __gconv_translit_find (struct trans_struct *trans)
internal_function;
/* Transliteration using the locale's data. */
extern int __gconv_transliterate (struct __gconv_step *step,
struct __gconv_step_data *step_data,
void *trans_data,
__const unsigned char *inbufstart,
__const unsigned char **inbufp,
__const unsigned char *inbufend,
unsigned char **outbufstart,
size_t *irreversible);
/* Builtin transformations. */
#ifdef _LIBC
# define __BUILTIN_TRANS(Name) \
extern int Name (struct __gconv_step *step, \
struct __gconv_step_data *data, \
const unsigned char **inbuf, \
const unsigned char *inbufend, \
unsigned char **outbufstart, size_t *irreversible, \
int do_flush, int consume_incomplete)
__BUILTIN_TRANS (__gconv_transform_ascii_internal);
__BUILTIN_TRANS (__gconv_transform_internal_ascii);
__BUILTIN_TRANS (__gconv_transform_utf8_internal);
__BUILTIN_TRANS (__gconv_transform_internal_utf8);
__BUILTIN_TRANS (__gconv_transform_ucs2_internal);
__BUILTIN_TRANS (__gconv_transform_internal_ucs2);
__BUILTIN_TRANS (__gconv_transform_ucs2reverse_internal);
__BUILTIN_TRANS (__gconv_transform_internal_ucs2reverse);
__BUILTIN_TRANS (__gconv_transform_internal_ucs4);
__BUILTIN_TRANS (__gconv_transform_ucs4_internal);
__BUILTIN_TRANS (__gconv_transform_internal_ucs4le);
__BUILTIN_TRANS (__gconv_transform_ucs4le_internal);
__BUILTIN_TRANS (__gconv_transform_internal_utf16);
__BUILTIN_TRANS (__gconv_transform_utf16_internal);
# undef __BUITLIN_TRANS
#endif
__END_DECLS
#endif /* gconv_int.h */

View File

@ -0,0 +1,326 @@
/* Find matching transformation algorithms and initialize steps.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <gconv_int.h>
int
internal_function
__gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
int flags)
{
struct __gconv_step *steps;
size_t nsteps;
__gconv_t result = NULL;
size_t cnt = 0;
int res;
int conv_flags = 0;
const char *errhand;
const char *ignore;
struct trans_struct *trans = NULL;
char old_locale[20], *old_locale_p;
char *old, *new;
size_t len;
/* Find out whether any error handling method is specified. */
errhand = strchr (toset, '/');
if (errhand != NULL)
errhand = strchr (errhand + 1, '/');
if (__builtin_expect (errhand != NULL, 1))
{
if (*++errhand == '\0')
errhand = NULL;
else
{
/* Make copy without the error handling description. */
char *newtoset = (char *) alloca (errhand - toset + 1);
char *tok;
char *ptr;
newtoset[errhand - toset] = '\0';
toset = memcpy (newtoset, toset, errhand - toset);
/* Find the appropriate transliteration handlers. */
old = (char *)(errhand);
len = strlen (old) + 1;
new = (char *) alloca (len);
tok = (char *) memcpy (new, old, len);
tok = strtok_r (tok, ",", &ptr);
/* Set locale to default C locale. */
old_locale_p = setlocale(LC_ALL, "C");
strncpy(old_locale, old_locale_p, 20);
while (tok != NULL)
{
if (strcasecmp (tok, "TRANSLIT") == 0)
{
/* It's the builtin transliteration handling. We only
support it for working on the internal encoding. */
static const char *internal_trans_names[1] = { "INTERNAL" };
struct trans_struct *lastp = NULL;
struct trans_struct *runp;
for (runp = trans; runp != NULL; runp = runp->next)
if (runp->trans_fct == __gconv_transliterate)
break;
else
lastp = runp;
if (runp == NULL)
{
struct trans_struct *newp;
newp = (struct trans_struct *) alloca (sizeof (*newp));
memset (newp, '\0', sizeof (*newp));
/* We leave the `name' field zero to signal that
this is an internal transliteration step. */
newp->csnames = internal_trans_names;
newp->ncsnames = 1;
newp->trans_fct = __gconv_transliterate;
if (lastp == NULL)
trans = newp;
else
lastp->next = newp;
}
}
else if (strcasecmp (tok, "IGNORE") == 0)
/* Set the flag to ignore all errors. */
conv_flags |= __GCONV_IGNORE_ERRORS;
else
{
/* `tok' is possibly a module name. We'll see later
whether we can find it. But first see that we do
not already a module of this name. */
struct trans_struct *lastp = NULL;
struct trans_struct *runp;
for (runp = trans; runp != NULL; runp = runp->next)
if (runp->name != NULL
&& strcasecmp (tok, runp->name) == 0)
break;
else
lastp = runp;
if (runp == NULL)
{
struct trans_struct *newp;
newp = (struct trans_struct *) alloca (sizeof (*newp));
memset (newp, '\0', sizeof (*newp));
newp->name = tok;
if (lastp == NULL)
trans = newp;
else
lastp->next = newp;
}
}
tok = strtok_r (NULL, ",", &ptr);
}
}
}
/* For the source character set we ignore the error handler specification.
XXX Is this really always the best? */
ignore = strchr (fromset, '/');
if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
&& *++ignore != '\0')
{
char *newfromset = (char *) alloca (ignore - fromset + 1);
newfromset[ignore - fromset] = '\0';
fromset = memcpy (newfromset, fromset, ignore - fromset);
}
res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
if (res == __GCONV_OK)
{
/* Find the modules. */
struct trans_struct *lastp = NULL;
struct trans_struct *runp;
for (runp = trans; runp != NULL; runp = runp->next)
{
if (runp->name == NULL
|| __builtin_expect (__gconv_translit_find (runp), 0) == 0)
lastp = runp;
else
/* This means we haven't found the module. Remove it. */
(lastp == NULL ? trans : lastp->next) = runp->next;
}
/* Allocate room for handle. */
result = (__gconv_t) malloc (sizeof (struct __gconv_info)
+ (nsteps
* sizeof (struct __gconv_step_data)));
if (result == NULL)
res = __GCONV_NOMEM;
else
{
size_t n;
/* Remember the list of steps. */
result->__steps = steps;
result->__nsteps = nsteps;
/* Clear the array for the step data. */
memset (result->__data, '\0',
nsteps * sizeof (struct __gconv_step_data));
/* Call all initialization functions for the transformation
step implementations. */
for (cnt = 0; cnt < nsteps; ++cnt)
{
size_t size;
/* Would have to be done if we would not clear the whole
array above. */
#if 0
/* Reset the counter. */
result->__data[cnt].__invocation_counter = 0;
/* It's a regular use. */
result->__data[cnt].__internal_use = 0;
#endif
/* We use the `mbstate_t' member in DATA. */
result->__data[cnt].__statep = &result->__data[cnt].__state;
/* Now see whether we can use any of the transliteration
modules for this step. */
for (runp = trans; runp != NULL; runp = runp->next)
for (n = 0; n < runp->ncsnames; ++n)
if (strcasecmp (steps[cnt].__from_name, runp->csnames[n]) == 0)
{
void *data = NULL;
/* Match! Now try the initializer. */
if (runp->trans_init_fct == NULL
|| (runp->trans_init_fct (&data,
steps[cnt].__to_name)
== __GCONV_OK))
{
/* Append at the end of the list. */
struct __gconv_trans_data *newp;
struct __gconv_trans_data **lastp;
newp = (struct __gconv_trans_data *)
malloc (sizeof (struct __gconv_trans_data));
if (newp == NULL)
{
res = __GCONV_NOMEM;
goto bail;
}
newp->__trans_fct = runp->trans_fct;
newp->__trans_context_fct = runp->trans_context_fct;
newp->__trans_end_fct = runp->trans_end_fct;
newp->__data = data;
newp->__next = NULL;
lastp = &result->__data[cnt].__trans;
while (*lastp != NULL)
lastp = &(*lastp)->__next;
*lastp = newp;
}
break;
}
/* If this is the last step we must not allocate an
output buffer. */
if (cnt < nsteps - 1)
{
result->__data[cnt].__flags = conv_flags;
/* Allocate the buffer. */
size = (GCONV_NCHAR_GOAL * steps[cnt].__max_needed_to);
result->__data[cnt].__outbuf = (char *) malloc (size);
if (result->__data[cnt].__outbuf == NULL)
{
res = __GCONV_NOMEM;
goto bail;
}
result->__data[cnt].__outbufend =
result->__data[cnt].__outbuf + size;
}
else
{
/* Handle the last entry. */
result->__data[cnt].__flags = conv_flags | __GCONV_IS_LAST;
break;
}
}
}
if (res != __GCONV_OK)
{
/* Something went wrong. Free all the resources. */
int serrno;
bail:
serrno = errno;
if (result != NULL)
{
while (cnt-- > 0)
{
struct __gconv_trans_data *transp;
transp = result->__data[cnt].__trans;
while (transp != NULL)
{
struct __gconv_trans_data *curp = transp;
transp = transp->__next;
if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
curp->__trans_end_fct (curp->__data);
free (curp);
}
free (result->__data[cnt].__outbuf);
}
free (result);
result = NULL;
}
__gconv_close_transform (steps, nsteps);
__set_errno (serrno);
}
}
*handle = result;
setlocale(LC_ALL, old_locale);
return res;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
/* Transliteration using the locale's data.
Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <dlfcn.h>
#include <search.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <ltdl.h>
#include "gconv_int.h"
#include "localeinfo.h"
int
__gconv_transliterate (struct __gconv_step *step,
struct __gconv_step_data *step_data,
void *trans_data __attribute__ ((unused)),
const unsigned char *inbufstart,
const unsigned char **inbufp,
const unsigned char *inbufend,
unsigned char **outbufstart, size_t *irreversible)
{
return 0;
}
/* Structure to represent results of found (or not) transliteration
modules. */
struct known_trans
{
/* This structure must remain the first member. */
struct trans_struct info;
char *fname;
void *handle;
int open_count;
};
/* Tree with results of previous calls to __gconv_translit_find. */
static void *search_tree;
/* We modify global data. */
__LOCK_INIT(static, lock);
/* Compare two transliteration entries. */
static int
trans_compare (const void *p1, const void *p2)
{
const struct known_trans *s1 = (const struct known_trans *) p1;
const struct known_trans *s2 = (const struct known_trans *) p2;
return strcmp (s1->info.name, s2->info.name);
}
/* Open (maybe reopen) the module named in the struct. Get the function
and data structure pointers we need. */
static int
open_translit (struct known_trans *trans)
{
__gconv_trans_query_fct queryfct;
trans->handle = __libc_dlopen (trans->fname);
if (trans->handle == NULL)
/* Not available. */
return 1;
/* Find the required symbol. */
queryfct = __libc_dlsym (trans->handle, "gconv_trans_context");
if (queryfct == NULL)
{
/* We cannot live with that. */
close_and_out:
__libc_dlclose (trans->handle);
trans->handle = NULL;
return 1;
}
/* Get the context. */
if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames)
!= 0)
goto close_and_out;
/* Of course we also have to have the actual function. */
trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans");
if (trans->info.trans_fct == NULL)
goto close_and_out;
/* Now the optional functions. */
trans->info.trans_init_fct =
__libc_dlsym (trans->handle, "gconv_trans_init");
trans->info.trans_context_fct =
__libc_dlsym (trans->handle, "gconv_trans_context");
trans->info.trans_end_fct =
__libc_dlsym (trans->handle, "gconv_trans_end");
trans->open_count = 1;
return 0;
}
int
internal_function
__gconv_translit_find (struct trans_struct *trans)
{
struct known_trans **found;
const struct path_elem *runp;
int res = 1;
/* We have to have a name. */
assert (trans->name != NULL);
/* Acquire the lock. */
#ifdef HAVE_DD_LOCK
__lock_acquire(lock);
#endif
/* See whether we know this module already. */
found = tfind (trans, &search_tree, trans_compare);
if (found != NULL)
{
/* Is this module available? */
if ((*found)->handle != NULL)
{
/* Maybe we have to reopen the file. */
if ((*found)->handle != (void *) -1)
/* The object is not unloaded. */
res = 0;
else if (open_translit (*found) == 0)
{
/* Copy the data. */
*trans = (*found)->info;
(*found)->open_count++;
res = 0;
}
}
}
else
{
size_t name_len = strlen (trans->name) + 1;
int need_so = 0;
struct known_trans *newp;
/* We have to continue looking for the module. */
if (__gconv_path_elem == NULL)
__gconv_get_path ();
/* See whether we have to append .so. */
if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0)
need_so = 1;
/* Create a new entry. */
newp = (struct known_trans *) malloc (sizeof (struct known_trans)
+ (__gconv_max_path_elem_len
+ name_len + 3)
+ name_len);
if (newp != NULL)
{
char *cp;
/* Clear the struct. */
memset (newp, '\0', sizeof (struct known_trans));
/* Store a copy of the module name. */
newp->info.name = cp = (char *) (newp + 1);
cp = memcpy (cp, trans->name, name_len);
cp += name_len;
newp->fname = cp;
/* Search in all the directories. */
for (runp = __gconv_path_elem; runp->name != NULL; ++runp)
{
strcpy ((char *) newp->fname, runp->name);
while(newp->fname != '\0') newp->fname++;
cp = memcpy (newp->fname,
trans->name, name_len);
cp += name_len;
if (need_so)
memcpy (cp, ".so", sizeof (".so"));
if (open_translit (newp) == 0)
{
/* We found a module. */
res = 0;
break;
}
}
if (res)
newp->fname = NULL;
/* In any case we'll add the entry to our search tree. */
if (tsearch (newp, &search_tree, trans_compare) == NULL)
{
/* Yickes, this should not happen. Unload the object. */
res = 1;
/* XXX unload here. */
}
}
}
#ifdef HAVE_DD_LOCK
__lock_release(lock);
#endif
return res;
}

View File

@ -0,0 +1,60 @@
/* Implements a string hashing function.
Copyright (C) 1995, 1997, 1998, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* @@ end of prolog @@ */
#ifndef PARAMS
# if __STDC__
# define PARAMS(Args) Args
# else
# define PARAMS(Args) ()
# endif
#endif
/* We assume to have `unsigned long int' value with at least 32 bits. */
#define HASHWORDBITS 32
/* Defines the so called `hashpjw' function by P.J. Weinberger
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1986, 1987 Bell Telephone Laboratories, Inc.] */
static unsigned long int hash_string PARAMS ((const char *__str_param));
static inline unsigned long int
hash_string (str_param)
const char *str_param;
{
unsigned long int hval, g;
const char *str = str_param;
/* Compute the hash value for the given string. */
hval = 0;
while (*str != '\0')
{
hval <<= 4;
hval += (unsigned long int) *str++;
g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
if (g != 0)
{
hval ^= g >> (HASHWORDBITS - 8);
hval ^= g;
}
}
return hval;
}

View File

@ -0,0 +1,96 @@
/* Convert characters in input buffer using conversion descriptor to
output buffer.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stddef.h> /* for NULL */
#include <errno.h>
#include <iconv.h>
#include <gconv_int.h>
#include <assert.h>
size_t
iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
size_t *outbytesleft)
{
__gconv_t gcd = (__gconv_t) cd;
char *outstart = outbuf ? *outbuf : NULL;
size_t irreversible;
int result;
if (__builtin_expect (inbuf == NULL || *inbuf == NULL, 0))
{
if (outbuf == NULL || *outbuf == NULL)
result = __gconv (gcd, NULL, NULL, NULL, NULL, &irreversible);
else
result = __gconv (gcd, NULL, NULL, (unsigned char **) outbuf,
(unsigned char *) (outstart + *outbytesleft),
&irreversible);
}
else
{
const char *instart = *inbuf;
result = __gconv (gcd, (const unsigned char **) inbuf,
(const unsigned char *) (*inbuf + *inbytesleft),
(unsigned char **) outbuf,
(unsigned char *) (*outbuf + *outbytesleft),
&irreversible);
*inbytesleft -= *inbuf - instart;
}
if (outstart != NULL)
*outbytesleft -= *outbuf - outstart;
switch (__builtin_expect (result, __GCONV_OK))
{
case __GCONV_ILLEGAL_DESCRIPTOR:
__set_errno (EBADF);
irreversible = (size_t) -1L;
break;
case __GCONV_ILLEGAL_INPUT:
__set_errno (EILSEQ);
irreversible = (size_t) -1L;
break;
case __GCONV_FULL_OUTPUT:
__set_errno (E2BIG);
irreversible = (size_t) -1L;
break;
case __GCONV_INCOMPLETE_INPUT:
__set_errno (EINVAL);
irreversible = (size_t) -1L;
break;
case __GCONV_EMPTY_INPUT:
case __GCONV_OK:
/* Nothing. */
break;
default:
assert (!"Nothing like this should happen");
}
return irreversible;
}

View File

@ -0,0 +1,51 @@
/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _ICONV_H
#define _ICONV_H 1
#include <features.h>
#define __need_size_t
#include <stddef.h>
__BEGIN_DECLS
/* Identifier for conversion method from one codeset to another. */
typedef void *iconv_t;
/* Allocate descriptor for code conversion from codeset FROMCODE to
codeset TOCODE. */
extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode)
__THROW;
/* Convert at most *INBYTESLEFT bytes from *INBUF according to the
code conversion algorithm specified by CD and place up to
*OUTBYTESLEFT bytes in buffer at *OUTBUF. */
extern size_t iconv (iconv_t __cd, char **__restrict __inbuf,
size_t *__restrict __inbytesleft,
char **__restrict __outbuf,
size_t *__restrict __outbytesleft);
/* Free resources allocated for descriptor CD for code conversion. */
extern int iconv_close (iconv_t __cd) __THROW;
__END_DECLS
#endif /* iconv.h */

View File

@ -0,0 +1,563 @@
/* Convert using charmaps and possibly iconv().
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <iconv.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "iconv_prog.h"
/* Prototypes for a few program-wide used functions. */
extern void *xmalloc (size_t __n);
extern void *xcalloc (size_t __n, size_t __s);
struct convtable
{
int term[256 / 8];
union
{
struct convtable *sub;
struct charseq *out;
} val[256];
};
static inline struct convtable *
allocate_table (void)
{
return (struct convtable *) xcalloc (1, sizeof (struct convtable));
}
static inline int
is_term (struct convtable *tbl, unsigned int idx)
{
return tbl->term[idx / 8] & (1 << (idx % 8));
}
static inline void
clear_term (struct convtable *tbl, unsigned int idx)
{
tbl->term[idx / 8] &= ~(1 << (idx % 8));
}
static inline void
set_term (struct convtable *tbl, unsigned int idx)
{
tbl->term[idx / 8] |= 1 << (idx % 8);
}
/* Generate the conversion table. */
static struct convtable *use_from_charmap (struct charmap_t *from_charmap,
const char *to_code);
static struct convtable *use_to_charmap (const char *from_code,
struct charmap_t *to_charmap);
static struct convtable *use_both_charmaps (struct charmap_t *from_charmap,
struct charmap_t *to_charmap);
/* Prototypes for the functions doing the actual work. */
static int process_block (struct convtable *tbl, char *addr, size_t len,
FILE *output);
static int process_fd (struct convtable *tbl, int fd, FILE *output);
static int process_file (struct convtable *tbl, FILE *input, FILE *output);
int
charmap_conversion (const char *from_code, struct charmap_t *from_charmap,
const char *to_code, struct charmap_t *to_charmap,
int argc, int remaining, char *argv[], FILE *output)
{
struct convtable *cvtbl;
int status = EXIT_SUCCESS;
/* We have three different cases to handle:
- both, from_charmap and to_charmap, are available. This means we
can assume that the symbolic names match and use them to create
the mapping.
- only from_charmap is available. In this case we can only hope that
the symbolic names used are of the <Uxxxx> form in which case we
can use a UCS4->"to_code" iconv() conversion for the second step.
- only to_charmap is available. This is similar, only that we would
use iconv() for the "to_code"->UCS4 conversion.
We first create a table which maps input bytes into output bytes.
Once this is done we can handle all three of the cases above
equally. */
if (from_charmap != NULL)
{
if (to_charmap == NULL)
cvtbl = use_from_charmap (from_charmap, to_code);
else
cvtbl = use_both_charmaps (from_charmap, to_charmap);
}
else
{
assert (to_charmap != NULL);
cvtbl = use_to_charmap (from_code, to_charmap);
}
/* If we couldn't generate a table stop now. */
if (cvtbl == NULL)
return EXIT_FAILURE;
/* We can now start the conversion. */
if (remaining == argc)
{
if (process_file (cvtbl, stdin, output) != 0)
status = EXIT_FAILURE;
}
else
do
{
struct stat st;
char *addr;
int fd;
if (verbose)
printf ("%s:\n", argv[remaining]);
if (strcmp (argv[remaining], "-") == 0)
fd = 0;
else
{
fd = open (argv[remaining], O_RDONLY);
if (fd == -1)
{
error (0, errno, _("cannot open input file `%s'"),
argv[remaining]);
status = EXIT_FAILURE;
continue;
}
}
#ifdef _POSIX_MAPPED_FILES
/* We have possibilities for reading the input file. First try
to mmap() it since this will provide the fastest solution. */
if (fstat (fd, &st) == 0
&& ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE,
fd, 0)) != MAP_FAILED))
{
/* Yes, we can use mmap(). The descriptor is not needed
anymore. */
if (close (fd) != 0)
error (EXIT_FAILURE, errno,
_("error while closing input `%s'"), argv[remaining]);
if (process_block (cvtbl, addr, st.st_size, output) < 0)
{
/* Something went wrong. */
status = EXIT_FAILURE;
/* We don't need the input data anymore. */
munmap ((void *) addr, st.st_size);
/* We cannot go on with producing output since it might
lead to problem because the last output might leave
the output stream in an undefined state. */
break;
}
/* We don't need the input data anymore. */
munmap ((void *) addr, st.st_size);
}
else
#endif /* _POSIX_MAPPED_FILES */
{
/* Read the file in pieces. */
if (process_fd (cvtbl, fd, output) != 0)
{
/* Something went wrong. */
status = EXIT_FAILURE;
/* We don't need the input file anymore. */
close (fd);
/* We cannot go on with producing output since it might
lead to problem because the last output might leave
the output stream in an undefined state. */
break;
}
/* Now close the file. */
close (fd);
}
}
while (++remaining < argc);
/* All done. */
return status;
}
static void
add_bytes (struct convtable *tbl, struct charseq *in, struct charseq *out)
{
int n = 0;
unsigned int byte;
assert (in->nbytes > 0);
byte = ((unsigned char *) in->bytes)[n];
while (n + 1 < in->nbytes)
{
if (is_term (tbl, byte) || tbl->val[byte].sub == NULL)
{
/* Note that we simply ignore a definition for a byte sequence
which is also the prefix for a longer one. */
clear_term (tbl, byte);
tbl->val[byte].sub =
(struct convtable *) xcalloc (1, sizeof (struct convtable));
}
tbl = tbl->val[byte].sub;
byte = ((unsigned char *) in->bytes)[++n];
}
/* Only add the new sequence if there is none yet and the byte sequence
is not part of an even longer one. */
if (! is_term (tbl, byte) && tbl->val[byte].sub == NULL)
{
set_term (tbl, byte);
tbl->val[byte].out = out;
}
}
static struct convtable *
use_from_charmap (struct charmap_t *from_charmap, const char *to_code)
{
/* We iterate over all entries in the from_charmap and for those which
have a known UCS4 representation we use an iconv() call to determine
the mapping to the to_code charset. */
struct convtable *rettbl;
iconv_t cd;
void *ptr = NULL;
const void *key;
size_t keylen;
void *data;
cd = iconv_open (to_code, "WCHAR_T");
if (cd == (iconv_t) -1)
/* We cannot do anything. */
return NULL;
rettbl = allocate_table ();
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *in = (struct charseq *) data;
if (in->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { in->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
struct charseq *newp;
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
+ outlen);
newp->name = in->name;
newp->ucs4 = in->ucs4;
newp->nbytes = outlen;
memcpy (newp->bytes, outbuf, outlen);
add_bytes (rettbl, in, newp);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
}
iconv_close (cd);
return rettbl;
}
static struct convtable *
use_to_charmap (const char *from_code, struct charmap_t *to_charmap)
{
/* We iterate over all entries in the to_charmap and for those which
have a known UCS4 representation we use an iconv() call to determine
the mapping to the from_code charset. */
struct convtable *rettbl;
iconv_t cd;
void *ptr = NULL;
const void *key;
size_t keylen;
void *data;
/* Note that the conversion we use here is the reverse direction. Without
exhaustive search we cannot figure out which input yields the UCS4
character we are looking for. Therefore we determine it the other
way round. */
cd = iconv_open (from_code, "WCHAR_T");
if (cd == (iconv_t) -1)
/* We cannot do anything. */
return NULL;
rettbl = allocate_table ();
while (iterate_table (&to_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *out = (struct charseq *) data;
if (out->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { out->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
struct charseq *newp;
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
+ outlen);
newp->name = out->name;
newp->ucs4 = out->ucs4;
newp->nbytes = outlen;
memcpy (newp->bytes, outbuf, outlen);
add_bytes (rettbl, newp, out);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
}
iconv_close (cd);
return rettbl;
}
static struct convtable *
use_both_charmaps (struct charmap_t *from_charmap,
struct charmap_t *to_charmap)
{
/* In this case we iterate over all the entries in the from_charmap,
determine the internal name, and find an appropriate entry in the
to_charmap (if it exists). */
struct convtable *rettbl = allocate_table ();
void *ptr = NULL;
const void *key;
size_t keylen;
void *data;
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *in = (struct charseq *) data;
struct charseq *out = charmap_find_value (to_charmap, key, keylen);
if (out != NULL)
add_bytes (rettbl, in, out);
}
return rettbl;
}
static int
process_block (struct convtable *tbl, char *addr, size_t len, FILE *output)
{
size_t n = 0;
while (n < len)
{
struct convtable *cur = tbl;
unsigned char *curp = (unsigned char *) addr;
unsigned int byte = *curp;
int cnt;
struct charseq *out;
while (! is_term (cur, byte))
if (cur->val[byte].sub == NULL)
{
/* This is a invalid sequence. Skip the first byte if we are
ignoring errors. Otherwise punt. */
if (! omit_invalid)
{
error (0, 0, _("illegal input sequence at position %Zd"), n);
return -1;
}
n -= curp - (unsigned char *) addr;
byte = *(curp = (unsigned char *) ++addr);
if (++n >= len)
/* All converted. */
return 0;
cur = tbl;
}
else
{
cur = cur->val[byte].sub;
if (++n >= len)
{
error (0, 0, _("\
incomplete character or shift sequence at end of buffer"));
return -1;
}
byte = *++curp;
}
/* We found a final byte. Write the output bytes. */
out = cur->val[byte].out;
for (cnt = 0; cnt < out->nbytes; ++cnt)
fputc_unlocked (out->bytes[cnt], output);
addr = (char *) curp + 1;
++n;
}
return 0;
}
static int
process_fd (struct convtable *tbl, int fd, FILE *output)
{
/* we have a problem with reading from a desriptor since we must not
provide the iconv() function an incomplete character or shift
sequence at the end of the buffer. Since we have to deal with
arbitrary encodings we must read the whole text in a buffer and
process it in one step. */
static char *inbuf = NULL;
static size_t maxlen = 0;
char *inptr = NULL;
size_t actlen = 0;
while (actlen < maxlen)
{
ssize_t n = read (fd, inptr, maxlen - actlen);
if (n == 0)
/* No more text to read. */
break;
if (n == -1)
{
/* Error while reading. */
error (0, errno, _("error while reading the input"));
return -1;
}
inptr += n;
actlen += n;
}
if (actlen == maxlen)
while (1)
{
ssize_t n;
/* Increase the buffer. */
maxlen += 32768;
inbuf = realloc (inbuf, maxlen);
if (inbuf == NULL)
error (0, errno, _("unable to allocate buffer for input"));
inptr = inbuf + actlen;
do
{
n = read (fd, inptr, maxlen - actlen);
if (n == 0)
/* No more text to read. */
break;
if (n == -1)
{
/* Error while reading. */
error (0, errno, _("error while reading the input"));
return -1;
}
inptr += n;
actlen += n;
}
while (actlen < maxlen);
if (n == 0)
/* Break again so we leave both loops. */
break;
}
/* Now we have all the input in the buffer. Process it in one run. */
return process_block (tbl, inbuf, actlen, output);
}
static int
process_file (struct convtable *tbl, FILE *input, FILE *output)
{
/* This should be safe since we use this function only for `stdin' and
we haven't read anything so far. */
return process_fd (tbl, fileno (input), output);
}

View File

@ -0,0 +1,37 @@
/* Release any resource associated with given conversion descriptor.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <iconv.h>
#include <gconv_int.h>
int
iconv_close (iconv_t cd)
{
if (__builtin_expect (cd == (iconv_t *) -1L, 0))
{
__set_errno (EBADF);
return -1;
}
return __gconv_close ((__gconv_t) cd) ? -1 : 0;
}

View File

@ -0,0 +1,65 @@
/* Get descriptor for character set conversion.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
#include <gconv_int.h>
#include "gconv_charset.h"
iconv_t
iconv_open (const char *tocode, const char *fromcode)
{
char *tocode_conv;
char *fromcode_conv;
size_t tocode_len;
size_t fromcode_len;
__gconv_t cd;
int res;
/* Normalize the name. We remove all characters beside alpha-numeric,
'_', '-', '/', and '.'. */
tocode_len = strlen (tocode);
tocode_conv = alloca (tocode_len + 3);
strip (tocode_conv, tocode);
tocode = tocode_conv[2] == '\0' ? upstr (tocode_conv, tocode) : tocode_conv;
fromcode_len = strlen (fromcode);
fromcode_conv = alloca (fromcode_len + 3);
strip (fromcode_conv, fromcode);
fromcode = (fromcode_conv[2] == '\0'
? upstr (fromcode_conv, fromcode) : fromcode_conv);
res = __gconv_open (tocode, fromcode, &cd, 0);
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
{
/* We must set the error number according to the specs. */
if (res == __GCONV_NOCONV || res == __GCONV_NODB)
__set_errno (EINVAL);
return (iconv_t) -1;
}
return (iconv_t) cd;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
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 <stdint.h>
typedef uint16_t gidx_t;
struct gconvcache_header
{
uint32_t magic;
gidx_t string_offset;
gidx_t hash_offset;
gidx_t hash_size;
gidx_t module_offset;
gidx_t otherconv_offset;
};
struct hash_entry
{
gidx_t string_offset;
gidx_t module_idx;
};
struct module_entry
{
gidx_t canonname_offset;
gidx_t fromdir_offset;
gidx_t fromname_offset;
gidx_t todir_offset;
gidx_t toname_offset;
gidx_t extra_offset;
};
struct extra_entry
{
gidx_t module_cnt;
struct extra_entry_module
{
gidx_t outname_offset;
gidx_t dir_offset;
gidx_t name_offset;
} module[0];
};
#define GCONVCACHE_MAGIC 0x20010324
#define GCONV_MODULES_CACHE GCONV_DIR "/gconv-modules.cache"

View File

@ -0,0 +1,100 @@
/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _LOADINFO_H
#define _LOADINFO_H 1
#ifndef PARAMS
# if __STDC__
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
#ifndef internal_function
# define internal_function
#endif
/* Tell the compiler when a conditional or integer expression is
almost always true or almost always false. */
#ifndef HAVE_BUILTIN_EXPECT
# define __builtin_expect(expr, val) (expr)
#endif
/* Encoding of locale name parts. */
#define CEN_REVISION 1
#define CEN_SPONSOR 2
#define CEN_SPECIAL 4
#define XPG_NORM_CODESET 8
#define XPG_CODESET 16
#define TERRITORY 32
#define CEN_AUDIENCE 64
#define XPG_MODIFIER 128
#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE)
#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER)
struct loaded_l10nfile
{
const char *filename;
int decided;
const void *data;
struct loaded_l10nfile *next;
struct loaded_l10nfile *successor[1];
};
/* Normalize codeset name. There is no standard for the codeset
names. Normalization allows the user to use any of the common
names. The return value is dynamically allocated and has to be
freed by the caller. */
extern const char *_nl_normalize_codeset PARAMS ((const char *codeset,
size_t name_len));
extern struct loaded_l10nfile *
_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
const char *dirlist, size_t dirlist_len, int mask,
const char *language, const char *territory,
const char *codeset,
const char *normalized_codeset,
const char *modifier, const char *special,
const char *sponsor, const char *revision,
const char *filename, int do_allocate));
extern const char *_nl_expand_alias PARAMS ((const char *name));
/* normalized_codeset is dynamically allocated and has to be freed by
the caller. */
extern int _nl_explode_name PARAMS ((char *name, const char **language,
const char **modifier,
const char **territory,
const char **codeset,
const char **normalized_codeset,
const char **special,
const char **sponsor,
const char **revision));
extern char *_nl_find_language PARAMS ((const char *name));
#endif /* loadinfo.h */

View File

@ -0,0 +1,209 @@
/* Declarations for internal libc locale interfaces
Copyright (C) 1995, 96, 97, 98, 99,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _LOCALEINFO_H
#define _LOCALEINFO_H 1
#include <stddef.h>
#include <langinfo.h>
#include <limits.h>
#include <time.h>
#include <stdint.h>
#include <sys/types.h>
/* This has to be changed whenever a new locale is defined. */
#define __LC_LAST 13
#include "loadinfo.h" /* For loaded_l10nfile definition. */
/* Magic number at the beginning of a locale data file for CATEGORY. */
#define LIMAGIC(category) ((unsigned int) (0x20000828 ^ (category)))
/* Two special weight constants for the collation data. */
#define IGNORE_CHAR 2
/* We use a special value for the usage counter in `locale_data' to
signal that this data must never be removed anymore. */
#define MAX_USAGE_COUNT (UINT_MAX - 1)
#define UNDELETABLE UINT_MAX
/* Structure describing locale data in core for a category. */
struct locale_data
{
const char *name;
const char *filedata; /* Region mapping the file data. */
off_t filesize; /* Size of the file (and the region). */
int mmaped; /* If nonzero the data is mmaped. */
unsigned int usage_count; /* Counter for users. */
int use_translit; /* Nonzero if the mb*towv*() and wc*tomb()
functions should use transliteration. */
const char *options; /* Extra options from the locale name,
not used in the path to the locale data. */
unsigned int nstrings; /* Number of strings below. */
union locale_data_value
{
const uint32_t *wstr;
const char *string;
unsigned int word;
}
values __flexarr; /* Items, usually pointers into `filedata'. */
};
/* We know three kinds of collation sorting rules. */
enum coll_sort_rule
{
illegal_0__,
sort_forward,
sort_backward,
illegal_3__,
sort_position,
sort_forward_position,
sort_backward_position,
sort_mask
};
/* We can map the types of the entries into a few categories. */
enum value_type
{
none,
string,
stringarray,
byte,
bytearray,
word,
stringlist,
wordarray,
wstring,
wstringarray,
wstringlist
};
/* Definitions for `era' information from LC_TIME. */
#define ERA_NAME_FORMAT_MEMBERS 4
#define ERA_M_NAME 0
#define ERA_M_FORMAT 1
#define ERA_W_NAME 2
#define ERA_W_FORMAT 3
/* Structure to access `era' information from LC_TIME. */
struct era_entry
{
uint32_t direction; /* Contains '+' or '-'. */
int32_t offset;
int32_t start_date[3];
int32_t stop_date[3];
const char *era_name;
const char *era_format;
const wchar_t *era_wname;
const wchar_t *era_wformat;
int absolute_direction;
/* absolute direction:
+1 indicates that year number is higher in the future. (like A.D.)
-1 indicates that year number is higher in the past. (like B.C.) */
};
/* LC_CTYPE specific:
Hardwired indices for standard wide character translation mappings. */
enum
{
__TOW_toupper = 0,
__TOW_tolower = 1
};
/* LC_CTYPE specific:
Access a wide character class with a single character index.
_ISCTYPE (c, desc) = iswctype (btowc (c), desc).
c must be an `unsigned char'. desc must be a nonzero wctype_t. */
#define _ISCTYPE(c, desc) \
(((((const uint32_t *) (desc)) - 8)[(c) >> 5] >> ((c) & 0x1f)) & 1)
/* For each category declare the variable for the current locale data. */
#define DEFINE_CATEGORY(category, category_name, items, a) \
extern struct locale_data *_nl_current_##category;
#include "categories.def"
#undef DEFINE_CATEGORY
extern const char *const _nl_category_names[__LC_LAST];
extern const size_t _nl_category_name_sizes[__LC_LAST];
extern struct locale_data * *const _nl_current[__LC_LAST];
/* Extract the current CATEGORY locale's string for ITEM. */
#define _NL_CURRENT(category, item) \
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
/* Extract the current CATEGORY locale's string for ITEM. */
#define _NL_CURRENT_WSTR(category, item) \
((wchar_t *) (_nl_current_##category->values[_NL_ITEM_INDEX (item)].wstr))
/* Extract the current CATEGORY locale's word for ITEM. */
#define _NL_CURRENT_WORD(category, item) \
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].word)
/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */
#define _NL_CURRENT_DEFINE(category) \
extern struct locale_data _nl_C_##category; \
struct locale_data *_nl_current_##category = &_nl_C_##category
/* Load the locale data for CATEGORY from the file specified by *NAME.
If *NAME is "", use environment variables as specified by POSIX,
and fill in *NAME with the actual name used. The directories
listed in LOCALE_PATH are searched for the locale files. */
extern struct locale_data *_nl_find_locale (const char *locale_path,
size_t locale_path_len,
int category, const char **name);
/* Try to load the file described by FILE. */
extern void _nl_load_locale (struct loaded_l10nfile *file, int category);
/* Free all resource. */
extern void _nl_unload_locale (struct locale_data *locale);
/* Free the locale and give back all memory if the usage count is one. */
extern void _nl_remove_locale (int locale, struct locale_data *data);
/* Return `era' entry which corresponds to TP. Used in strftime. */
extern struct era_entry *_nl_get_era_entry (const struct tm *tp);
/* Return `era' cnt'th entry . Used in strptime. */
extern struct era_entry *_nl_select_era_entry (int cnt);
/* Return `alt_digit' which corresponds to NUMBER. Used in strftime. */
extern const char *_nl_get_alt_digit (unsigned int number);
/* Similar, but now for wide characters. */
extern const wchar_t *_nl_get_walt_digit (unsigned int number);
/* Parse string as alternative digit and return numeric value. */
extern int _nl_parse_alt_digit (const char **strp);
/* Postload processing. */
extern void _nl_postload_ctype (void);
extern void _nl_postload_time (void);
#endif /* localeinfo.h */

View File

@ -0,0 +1,450 @@
/* Conversion loop frame work.
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* This file provides a frame for the reader loop in all conversion modules.
The actual code must (of course) be provided in the actual module source
code but certain actions can be written down generically, with some
customization options which are these:
MIN_NEEDED_INPUT minimal number of input bytes needed for the next
conversion.
MIN_NEEDED_OUTPUT minimal number of bytes produced by the next round
of conversion.
MAX_NEEDED_INPUT you guess it, this is the maximal number of input
bytes needed. It defaults to MIN_NEEDED_INPUT
MAX_NEEDED_OUTPUT likewise for output bytes.
LOOPFCT name of the function created. If not specified
the name is `loop' but this prevents the use
of multiple functions in the same file.
BODY this is supposed to expand to the body of the loop.
The user must provide this.
EXTRA_LOOP_DECLS extra arguments passed from converion loop call.
INIT_PARAMS code to define and initialize variables from params.
UPDATE_PARAMS code to store result in params.
*/
#include <assert.h>
#include <machine/endian.h>
#include <gconv.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <sys/param.h> /* For MIN. */
#define __need_size_t
#include <stddef.h>
/* We have to provide support for machines which are not able to handled
unaligned memory accesses. Some of the character encodings have
representations with a fixed width of 2 or 4 bytes. But if we cannot
access unaligned memory we still have to read byte-wise. */
#undef FCTNAME2
#if defined _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
/* We can handle unaligned memory access. */
# define get16(addr) *((__const uint16_t *) (addr))
# define get32(addr) *((__const uint32_t *) (addr))
/* We need no special support for writing values either. */
# define put16(addr, val) *((uint16_t *) (addr)) = (val)
# define put32(addr, val) *((uint32_t *) (addr)) = (val)
# define FCTNAME2(name) name
#else
/* Distinguish between big endian and little endian. */
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define get16(addr) \
(((__const unsigned char *) (addr))[1] << 8 \
| ((__const unsigned char *) (addr))[0])
# define get32(addr) \
(((((__const unsigned char *) (addr))[3] << 8 \
| ((__const unsigned char *) (addr))[2]) << 8 \
| ((__const unsigned char *) (addr))[1]) << 8 \
| ((__const unsigned char *) (addr))[0])
# define put16(addr, val) \
({ uint16_t __val = (val); \
((unsigned char *) (addr))[0] = __val; \
((unsigned char *) (addr))[1] = __val >> 8; \
(void) 0; })
# define put32(addr, val) \
({ uint32_t __val = (val); \
((unsigned char *) (addr))[0] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[1] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[2] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[3] = __val; \
(void) 0; })
# else
# define get16(addr) \
(((__const unsigned char *) (addr))[0] << 8 \
| ((__const unsigned char *) (addr))[1])
# define get32(addr) \
(((((__const unsigned char *) (addr))[0] << 8 \
| ((__const unsigned char *) (addr))[1]) << 8 \
| ((__const unsigned char *) (addr))[2]) << 8 \
| ((__const unsigned char *) (addr))[3])
# define put16(addr, val) \
({ uint16_t __val = (val); \
((unsigned char *) (addr))[1] = __val; \
((unsigned char *) (addr))[0] = __val >> 8; \
(void) 0; })
# define put32(addr, val) \
({ uint32_t __val = (val); \
((unsigned char *) (addr))[3] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[2] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[1] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[0] = __val; \
(void) 0; })
# endif
# define FCTNAME2(name) name##_unaligned
#endif
#define FCTNAME(name) FCTNAME2(name)
/* We need at least one byte for the next round. */
#ifndef MIN_NEEDED_INPUT
# error "MIN_NEEDED_INPUT definition missing"
#endif
/* Let's see how many bytes we produce. */
#ifndef MAX_NEEDED_INPUT
# define MAX_NEEDED_INPUT MIN_NEEDED_INPUT
#endif
/* We produce at least one byte in the next round. */
#ifndef MIN_NEEDED_OUTPUT
# error "MIN_NEEDED_OUTPUT definition missing"
#endif
/* Let's see how many bytes we produce. */
#ifndef MAX_NEEDED_OUTPUT
# define MAX_NEEDED_OUTPUT MIN_NEEDED_OUTPUT
#endif
/* Default name for the function. */
#ifndef LOOPFCT
# define LOOPFCT loop
#endif
/* Make sure we have a loop body. */
#ifndef BODY
# error "Definition of BODY missing for function" LOOPFCT
#endif
/* If no arguments have to passed to the loop function define the macro
as empty. */
#ifndef EXTRA_LOOP_DECLS
# define EXTRA_LOOP_DECLS
#endif
/* To make it easier for the writers of the modules, we define a macro
to test whether we have to ignore errors. */
#define ignore_errors_p() \
(irreversible != NULL && (flags & __GCONV_IGNORE_ERRORS))
/* Error handling with transliteration/transcription function use and
ignoring of errors. Note that we cannot use the do while (0) trick
since `break' and `continue' must reach certain points. */
#define STANDARD_ERR_HANDLER(Incr) \
{ \
struct __gconv_trans_data *trans; \
\
result = __GCONV_ILLEGAL_INPUT; \
\
if (irreversible == NULL) \
/* This means we are in call from __gconv_transliterate. In this \
case we are not doing any error recovery outself. */ \
break; \
\
/* First try the transliteration methods. */ \
for (trans = step_data->__trans; trans != NULL; trans = trans->__next) \
{ \
result = trans->__trans_fct (step, step_data, trans->__data, *inptrp, \
&inptr, inend, &outptr, irreversible); \
if (result != __GCONV_ILLEGAL_INPUT) \
break; \
} \
/* If any of them recognized the input continue with the loop. */ \
if (result != __GCONV_ILLEGAL_INPUT) \
continue; \
\
/* Next see whether we have to ignore the error. If not, stop. */ \
if (! ignore_errors_p ()) \
break; \
\
/* When we come here it means we ignore the character. */ \
++*irreversible; \
inptr += Incr; \
continue; \
}
/* Handling of Unicode 3.1 TAG characters. Unicode recommends
"If language codes are not relevant to the particular processing
operation, then they should be ignored."
This macro is usually called right before STANDARD_ERR_HANDLER (Incr). */
#define UNICODE_TAG_HANDLER(Character, Incr) \
{ \
/* TAG characters are those in the range U+E0000..U+E007F. */ \
if (((Character) >> 7) == (0xe0000 >> 7)) \
{ \
inptr += Incr; \
continue; \
} \
}
/* The function returns the status, as defined in gconv.h. */
static inline int
FCTNAME (LOOPFCT) (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outptrp, const unsigned char *outend,
size_t *irreversible EXTRA_LOOP_DECLS)
{
#ifdef LOOP_NEED_STATE
mbstate_t *state = step_data->__statep;
#endif
#ifdef LOOP_NEED_FLAGS
int flags = step_data->__flags;
#endif
#ifdef LOOP_NEED_DATA
void *data = step->__data;
#endif
int result = __GCONV_EMPTY_INPUT;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
#ifdef INIT_PARAMS
INIT_PARAMS;
#endif
while (inptr != inend)
{
/* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the
compiler generating better code. They will be optimized away
since MIN_NEEDED_OUTPUT is always a constant. */
if ((MIN_NEEDED_OUTPUT != 1
&& __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
|| (MIN_NEEDED_OUTPUT == 1
&& __builtin_expect (outptr >= outend, 0)))
{
/* Overflow in the output buffer. */
result = __GCONV_FULL_OUTPUT;
break;
}
if (MIN_NEEDED_INPUT > 1
&& __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
{
/* We don't have enough input for another complete input
character. */
result = __GCONV_INCOMPLETE_INPUT;
break;
}
/* Here comes the body the user provides. It can stop with
RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the
input characters vary in size), GCONV_ILLEGAL_INPUT, or
GCONV_FULL_OUTPUT (if the output characters vary in size). */
BODY
}
/* Update the pointers pointed to by the parameters. */
*inptrp = inptr;
*outptrp = outptr;
#ifdef UPDATE_PARAMS
UPDATE_PARAMS;
#endif
return result;
}
/* Include the file a second time to define the function to handle
unaligned access. */
#if !defined DEFINE_UNALIGNED && !defined _STRING_ARCH_unaligned \
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
# undef get16
# undef get32
# undef put16
# undef put32
# undef unaligned
# define DEFINE_UNALIGNED
# include "loop.c"
# undef DEFINE_UNALIGNED
#endif
#if MAX_NEEDED_INPUT > 1
# define SINGLE(fct) SINGLE2 (fct)
# define SINGLE2(fct) fct##_single
static inline int
SINGLE(LOOPFCT) (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
size_t *irreversible EXTRA_LOOP_DECLS)
{
mbstate_t *state = step_data->__statep;
#ifdef LOOP_NEED_FLAGS
int flags = step_data->__flags;
#endif
#ifdef LOOP_NEED_DATA
void *data = step->__data;
#endif
int result = __GCONV_OK;
unsigned char bytebuf[MAX_NEEDED_INPUT];
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t inlen;
#ifdef INIT_PARAMS
INIT_PARAMS;
#endif
#ifdef UNPACK_BYTES
UNPACK_BYTES
#else
/* Add the bytes from the state to the input buffer. */
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
bytebuf[inlen] = state->__value.__wchb[inlen];
#endif
/* Are there enough bytes in the input buffer? */
if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
{
*inptrp = inend;
#ifdef STORE_REST
inptr = bytebuf;
inptrp = &inptr;
inend = &bytebuf[inlen];
STORE_REST
#else
/* We don't have enough input for another complete input
character. */
while (inptr < inend)
state->__value.__wchb[inlen++] = *inptr++;
#endif
return __GCONV_INCOMPLETE_INPUT;
}
/* Enough space in output buffer. */
if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
|| (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
/* Overflow in the output buffer. */
return __GCONV_FULL_OUTPUT;
/* Now add characters from the normal input buffer. */
do
bytebuf[inlen++] = *inptr++;
while (inlen < MAX_NEEDED_INPUT && inptr < inend);
inptr = bytebuf;
inend = &bytebuf[inlen];
do
{
BODY
}
while (0);
/* Now we either have produced an output character and consumed all the
bytes from the state and at least one more, or the character is still
incomplete, or we have some other error (like illegal input character,
no space in output buffer). */
if (__builtin_expect (inptr != bytebuf, 1))
{
/* We found a new character. */
assert (inptr - bytebuf > (state->__count & 7));
*inptrp += inptr - bytebuf - (state->__count & 7);
*outptrp = outptr;
result = __GCONV_OK;
/* Clear the state buffer. */
state->__count &= ~7;
}
else if (result == __GCONV_INCOMPLETE_INPUT)
{
/* This can only happen if we have less than MAX_NEEDED_INPUT bytes
available. */
assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
*inptrp += inend - bytebuf - (state->__count & 7);
#ifdef STORE_REST
inptrp = &inptr;
STORE_REST
#else
/* We don't have enough input for another complete input
character. */
while (inptr < inend)
state->__value.__wchb[inlen++] = *inptr++;
#endif
}
return result;
}
# undef SINGLE
# undef SINGLE2
#endif
/* We remove the macro definitions so that we can include this file again
for the definition of another function. */
#undef MIN_NEEDED_INPUT
#undef MAX_NEEDED_INPUT
#undef MIN_NEEDED_OUTPUT
#undef MAX_NEEDED_OUTPUT
#undef LOOPFCT
#undef BODY
#undef LOOPFCT
#undef EXTRA_LOOP_DECLS
#undef INIT_PARAMS
#undef UPDATE_PARAMS
#undef UNPACK_BYTES
#undef LOOP_NEED_STATE
#undef LOOP_NEED_FLAGS
#undef LOOP_NEED_DATA
#undef get16
#undef get32
#undef put16
#undef put32
#undef unaligned

View File

@ -0,0 +1,696 @@
/* Skeleton for a conversion module.
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* This file can be included to provide definitions of several things
many modules have in common. It can be customized using the following
macros:
DEFINE_INIT define the default initializer. This requires the
following symbol to be defined.
CHARSET_NAME string with official name of the coded character
set (in all-caps)
DEFINE_FINI define the default destructor function.
MIN_NEEDED_FROM minimal number of bytes needed for the from-charset.
MIN_NEEDED_TO likewise for the to-charset.
MAX_NEEDED_FROM maximal number of bytes needed for the from-charset.
This macro is optional, it defaults to MIN_NEEDED_FROM.
MAX_NEEDED_TO likewise for the to-charset.
DEFINE_DIRECTION_OBJECTS
two objects will be defined to be used when the
`gconv' function must only distinguish two
directions. This is implied by DEFINE_INIT.
If this macro is not defined the following
macro must be available.
FROM_DIRECTION this macro is supposed to return a value != 0
if we convert from the current character set,
otherwise it return 0.
EMIT_SHIFT_TO_INIT this symbol is optional. If it is defined it
defines some code which writes out a sequence
of characters which bring the current state into
the initial state.
FROM_LOOP name of the function implementing the conversion
from the current characters.
TO_LOOP likewise for the other direction
ONE_DIRECTION optional. If defined to 1, only one conversion
direction is defined instead of two. In this
case, FROM_DIRECTION should be defined to 1, and
FROM_LOOP and TO_LOOP should have the same value.
SAVE_RESET_STATE in case of an error we must reset the state for
the rerun so this macro must be defined for
stateful encodings. It takes an argument which
is nonzero when saving.
RESET_INPUT_BUFFER If the input character sets allow this the macro
can be defined to reset the input buffer pointers
to cover only those characters up to the error.
FUNCTION_NAME if not set the conversion function is named `gconv'.
PREPARE_LOOP optional code preparing the conversion loop. Can
contain variable definitions.
END_LOOP also optional, may be used to store information
EXTRA_LOOP_ARGS optional macro specifying extra arguments passed
to loop function.
*/
#include <assert.h>
#include <gconv.h>
#include <string.h>
#define __need_size_t
#define __need_NULL
#include <stddef.h>
#include <wchar.h>
#ifndef STATIC_GCONV
# include <dlfcn.h>
#endif
# define DL_CALL_FCT(fct, args) fct args
/* The direction objects. */
#if DEFINE_DIRECTION_OBJECTS || DEFINE_INIT
static int from_object;
static int to_object;
# ifndef FROM_DIRECTION
# define FROM_DIRECTION (step->__data == &from_object)
# endif
#else
# ifndef FROM_DIRECTION
# error "FROM_DIRECTION must be provided if direction objects are not used"
# endif
#endif
/* How many bytes are needed at most for the from-charset. */
#ifndef MAX_NEEDED_FROM
# define MAX_NEEDED_FROM MIN_NEEDED_FROM
#endif
/* Same for the to-charset. */
#ifndef MAX_NEEDED_TO
# define MAX_NEEDED_TO MIN_NEEDED_TO
#endif
/* Define macros which can access unaligned buffers. These macros are
supposed to be used only in code outside the inner loops. For the inner
loops we have other definitions which allow optimized access. */
#ifdef _STRING_ARCH_unaligned
/* We can handle unaligned memory access. */
# define get16u(addr) *((__const uint16_t *) (addr))
# define get32u(addr) *((__const uint32_t *) (addr))
/* We need no special support for writing values either. */
# define put16u(addr, val) *((uint16_t *) (addr)) = (val)
# define put32u(addr, val) *((uint32_t *) (addr)) = (val)
#else
/* Distinguish between big endian and little endian. */
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define get16u(addr) \
(((__const unsigned char *) (addr))[1] << 8 \
| ((__const unsigned char *) (addr))[0])
# define get32u(addr) \
(((((__const unsigned char *) (addr))[3] << 8 \
| ((__const unsigned char *) (addr))[2]) << 8 \
| ((__const unsigned char *) (addr))[1]) << 8 \
| ((__const unsigned char *) (addr))[0])
# define put16u(addr, val) \
({ uint16_t __val = (val); \
((unsigned char *) (addr))[0] = __val; \
((unsigned char *) (addr))[1] = __val >> 8; \
(void) 0; })
# define put32u(addr, val) \
({ uint32_t __val = (val); \
((unsigned char *) (addr))[0] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[1] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[2] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[3] = __val; \
(void) 0; })
# else
# define get16u(addr) \
(((__const unsigned char *) (addr))[0] << 8 \
| ((__const unsigned char *) (addr))[1])
# define get32u(addr) \
(((((__const unsigned char *) (addr))[0] << 8 \
| ((__const unsigned char *) (addr))[1]) << 8 \
| ((__const unsigned char *) (addr))[2]) << 8 \
| ((__const unsigned char *) (addr))[3])
# define put16u(addr, val) \
({ uint16_t __val = (val); \
((unsigned char *) (addr))[1] = __val; \
((unsigned char *) (addr))[0] = __val >> 8; \
(void) 0; })
# define put32u(addr, val) \
({ uint32_t __val = (val); \
((unsigned char *) (addr))[3] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[2] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[1] = __val; \
__val >>= 8; \
((unsigned char *) (addr))[0] = __val; \
(void) 0; })
# endif
#endif
/* For conversions from a fixed width character set to another fixed width
character set we can define RESET_INPUT_BUFFER in a very fast way. */
#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
# if MIN_NEEDED_FROM == MAX_NEEDED_FROM && MIN_NEEDED_TO == MAX_NEEDED_TO
/* We have to use these `if's here since the compiler cannot know that
(outbuf - outerr) is always divisible by MIN_NEEDED_TO. */
# define RESET_INPUT_BUFFER \
if (MIN_NEEDED_FROM % MIN_NEEDED_TO == 0) \
*inptrp -= (outbuf - outerr) * (MIN_NEEDED_FROM / MIN_NEEDED_TO); \
else if (MIN_NEEDED_TO % MIN_NEEDED_FROM == 0) \
*inptrp -= (outbuf - outerr) / (MIN_NEEDED_TO / MIN_NEEDED_FROM); \
else \
*inptrp -= ((outbuf - outerr) / MIN_NEEDED_TO) * MIN_NEEDED_FROM
# endif
#endif
/* The default init function. It simply matches the name and initializes
the step data to point to one of the objects above. */
#if DEFINE_INIT
# ifndef CHARSET_NAME
# error "CHARSET_NAME not defined"
# endif
extern int gconv_init (struct __gconv_step *step);
int
gconv_init (struct __gconv_step *step)
{
/* Determine which direction. */
if (strcmp (step->__from_name, CHARSET_NAME) == 0)
{
step->__data = &from_object;
step->__min_needed_from = MIN_NEEDED_FROM;
step->__max_needed_from = MAX_NEEDED_FROM;
step->__min_needed_to = MIN_NEEDED_TO;
step->__max_needed_to = MAX_NEEDED_TO;
}
else if (__builtin_expect (strcmp (step->__to_name, CHARSET_NAME), 0) == 0)
{
step->__data = &to_object;
step->__min_needed_from = MIN_NEEDED_TO;
step->__max_needed_from = MAX_NEEDED_TO;
step->__min_needed_to = MIN_NEEDED_FROM;
step->__max_needed_to = MAX_NEEDED_FROM;
}
else
return __GCONV_NOCONV;
#ifdef SAVE_RESET_STATE
step->__stateful = 1;
#else
step->__stateful = 0;
#endif
return __GCONV_OK;
}
#endif
/* The default destructor function does nothing in the moment and so
we don't define it at all. But we still provide the macro just in
case we need it some day. */
#if DEFINE_FINI
#endif
/* If no arguments have to passed to the loop function define the macro
as empty. */
#ifndef EXTRA_LOOP_ARGS
# define EXTRA_LOOP_ARGS
#endif
/* This is the actual conversion function. */
#ifndef FUNCTION_NAME
# define FUNCTION_NAME gconv
#endif
/* The macros are used to access the function to convert single characters. */
#define SINGLE(fct) SINGLE2 (fct)
#define SINGLE2(fct) fct##_single
extern int FUNCTION_NAME (struct __gconv_step *step,
struct __gconv_step_data *data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outbufstart, size_t *irreversible,
int do_flush, int consume_incomplete);
int
FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outbufstart, size_t *irreversible, int do_flush,
int consume_incomplete)
{
struct __gconv_step *next_step = step + 1;
struct __gconv_step_data *next_data = data + 1;
__gconv_fct fct;
int status;
fct = (data->__flags & __GCONV_IS_LAST) ? NULL : next_step->__fct;
/* If the function is called with no input this means we have to reset
to the initial state. The possibly partly converted input is
dropped. */
if (__builtin_expect (do_flush, 0))
{
/* This should never happen during error handling. */
assert (outbufstart == NULL);
status = __GCONV_OK;
#ifdef EMIT_SHIFT_TO_INIT
if (do_flush == 1)
{
/* We preserve the initial values of the pointer variables. */
unsigned char *outbuf = data->__outbuf;
unsigned char *outstart = outbuf;
unsigned char *outend = data->__outbufend;
# ifdef PREPARE_LOOP
PREPARE_LOOP
# endif
# ifdef SAVE_RESET_STATE
SAVE_RESET_STATE (1);
# endif
/* Emit the escape sequence to reset the state. */
EMIT_SHIFT_TO_INIT;
/* Call the steps down the chain if there are any but only if we
successfully emitted the escape sequence. This should only
fail if the output buffer is full. If the input is invalid
it should be discarded since the user wants to start from a
clean state. */
if (status == __GCONV_OK)
{
if (data->__flags & __GCONV_IS_LAST)
/* Store information about how many bytes are available. */
data->__outbuf = outbuf;
else
{
/* Write out all output which was produced. */
if (outbuf > outstart)
{
const unsigned char *outerr = outstart;
int result;
result = DL_CALL_FCT (fct, (next_step, next_data,
&outerr, outbuf, NULL,
irreversible, 0,
consume_incomplete));
if (result != __GCONV_EMPTY_INPUT)
{
if (__builtin_expect (outerr != outbuf, 0))
{
/* We have a problem. Undo the conversion. */
outbuf = outstart;
/* Restore the state. */
# ifdef SAVE_RESET_STATE
SAVE_RESET_STATE (0);
# endif
}
/* Change the status. */
status = result;
}
}
if (status == __GCONV_OK)
/* Now flush the remaining steps. */
status = DL_CALL_FCT (fct, (next_step, next_data, NULL,
NULL, NULL, irreversible, 1,
consume_incomplete));
}
}
}
else
#endif
{
/* Clear the state object. There might be bytes in there from
previous calls with CONSUME_INCOMPLETE == 1. But don't emit
escape sequences. */
memset (data->__statep, '\0', sizeof (*data->__statep));
if (! (data->__flags & __GCONV_IS_LAST))
/* Now flush the remaining steps. */
status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
NULL, irreversible, do_flush,
consume_incomplete));
}
}
else
{
/* We preserve the initial values of the pointer variables. */
const unsigned char *inptr = *inptrp;
unsigned char *outbuf = (__builtin_expect (outbufstart == NULL, 1)
? data->__outbuf : *outbufstart);
unsigned char *outend = data->__outbufend;
unsigned char *outstart;
/* This variable is used to count the number of characters we
actually converted. */
size_t lirreversible = 0;
size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
#if defined _STRING_ARCH_unaligned \
|| MIN_NEEDED_FROM == 1 || MAX_NEEDED_FROM % MIN_NEEDED_FROM != 0 \
|| MIN_NEEDED_TO == 1 || MAX_NEEDED_TO % MIN_NEEDED_TO != 0
# define unaligned 0
#else
int unaligned;
# define GEN_unaligned(name) GEN_unaligned2 (name)
# define GEN_unaligned2(name) name##_unaligned
#endif
#ifdef PREPARE_LOOP
PREPARE_LOOP
#endif
#if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1
/* If the function is used to implement the mb*towc*() or wc*tomb*()
functions we must test whether any bytes from the last call are
stored in the `state' object. */
if (((MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1)
|| (MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
|| (MAX_NEEDED_TO > 1 && !FROM_DIRECTION))
&& consume_incomplete && (data->__statep->__count & 7) != 0)
{
/* Yep, we have some bytes left over. Process them now.
But this must not happen while we are called from an
error handler. */
assert (outbufstart == NULL);
# if MAX_NEEDED_FROM > 1
if (MAX_NEEDED_TO == 1 || FROM_DIRECTION)
status = SINGLE(FROM_LOOP) (step, data, inptrp, inend, &outbuf,
outend, lirreversiblep
EXTRA_LOOP_ARGS);
# endif
# if MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1 && !ONE_DIRECTION
else
# endif
# if MAX_NEEDED_TO > 1 && !ONE_DIRECTION
status = SINGLE(TO_LOOP) (step, data, inptrp, inend, &outbuf,
outend, lirreversiblep EXTRA_LOOP_ARGS);
# endif
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
return status;
}
#endif
#if !defined _STRING_ARCH_unaligned \
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
/* The following assumes that encodings, which have a variable length
what might unalign a buffer even though it is a aligned in the
beginning, either don't have the minimal number of bytes as a divisor
of the maximum length or have a minimum length of 1. This is true
for all known and supported encodings. */
unaligned = ((FROM_DIRECTION
&& ((uintptr_t) inptr % MIN_NEEDED_FROM != 0
|| ((data->__flags & __GCONV_IS_LAST)
&& (uintptr_t) outbuf % MIN_NEEDED_TO != 0)))
|| (!FROM_DIRECTION
&& (((data->__flags & __GCONV_IS_LAST)
&& (uintptr_t) outbuf % MIN_NEEDED_FROM != 0)
|| (uintptr_t) inptr % MIN_NEEDED_TO != 0)));
#endif
while (1)
{
struct __gconv_trans_data *trans;
/* Remember the start value for this round. */
inptr = *inptrp;
/* The outbuf buffer is empty. */
outstart = outbuf;
#ifdef SAVE_RESET_STATE
SAVE_RESET_STATE (1);
#endif
if (__builtin_expect (!unaligned, 1))
{
if (FROM_DIRECTION)
/* Run the conversion loop. */
status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
lirreversiblep EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
lirreversiblep EXTRA_LOOP_ARGS);
}
#if !defined _STRING_ARCH_unaligned \
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
else
{
if (FROM_DIRECTION)
/* Run the conversion loop. */
status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
&outbuf, outend,
lirreversiblep
EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
&outbuf, outend,
lirreversiblep
EXTRA_LOOP_ARGS);
}
#endif
/* If we were called as part of an error handling module we
don't do anything else here. */
if (__builtin_expect (outbufstart != NULL, 0))
{
*outbufstart = outbuf;
return status;
}
/* Give the transliteration module the chance to store the
original text and the result in case it needs a context. */
for (trans = data->__trans; trans != NULL; trans = trans->__next)
if (trans->__trans_context_fct != NULL)
DL_CALL_FCT (trans->__trans_context_fct,
(trans->__data, inptr, *inptrp, outstart, outbuf));
/* We finished one use of the loops. */
++data->__invocation_counter;
/* If this is the last step leave the loop, there is nothing
we can do. */
if (__builtin_expect (data->__flags & __GCONV_IS_LAST, 0))
{
/* Store information about how many bytes are available. */
data->__outbuf = outbuf;
/* Remember how many non-identical characters we
converted in a irreversible way. */
*irreversible += lirreversible;
break;
}
/* Write out all output which was produced. */
if (__builtin_expect (outbuf > outstart, 1))
{
const unsigned char *outerr = data->__outbuf;
int result;
result = DL_CALL_FCT (fct, (next_step, next_data, &outerr,
outbuf, NULL, irreversible, 0,
consume_incomplete));
if (result != __GCONV_EMPTY_INPUT)
{
if (__builtin_expect (outerr != outbuf, 0))
{
#ifdef RESET_INPUT_BUFFER
RESET_INPUT_BUFFER;
#else
/* We have a problem with the in on of the functions
below. Undo the conversion upto the error point. */
size_t nstatus;
/* Reload the pointers. */
*inptrp = inptr;
outbuf = outstart;
/* Restore the state. */
# ifdef SAVE_RESET_STATE
SAVE_RESET_STATE (0);
# endif
if (__builtin_expect (!unaligned, 1))
{
if (FROM_DIRECTION)
/* Run the conversion loop. */
nstatus = FROM_LOOP (step, data, inptrp, inend,
&outbuf, outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
nstatus = TO_LOOP (step, data, inptrp, inend,
&outbuf, outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
}
# if !defined _STRING_ARCH_unaligned \
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
else
{
if (FROM_DIRECTION)
/* Run the conversion loop. */
nstatus = GEN_unaligned (FROM_LOOP) (step, data,
inptrp, inend,
&outbuf,
outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
nstatus = GEN_unaligned (TO_LOOP) (step, data,
inptrp, inend,
&outbuf, outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
}
# endif
/* We must run out of output buffer space in this
rerun. */
assert (outbuf == outerr);
assert (nstatus == __GCONV_FULL_OUTPUT);
/* If we haven't consumed a single byte decrement
the invocation counter. */
if (__builtin_expect (outbuf == outstart, 0))
--data->__invocation_counter;
#endif /* reset input buffer */
}
/* Change the status. */
status = result;
}
else
/* All the output is consumed, we can make another run
if everything was ok. */
if (status == __GCONV_FULL_OUTPUT)
{
status = __GCONV_OK;
outbuf = data->__outbuf;
}
}
if (status != __GCONV_OK)
break;
/* Reset the output buffer pointer for the next round. */
outbuf = data->__outbuf;
}
#ifdef END_LOOP
END_LOOP
#endif
/* If we are supposed to consume all character store now all of the
remaining characters in the `state' object. */
#if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1
if (((MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1)
|| (MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
|| (MAX_NEEDED_TO > 1 && !FROM_DIRECTION))
&& __builtin_expect (consume_incomplete, 0)
&& status == __GCONV_INCOMPLETE_INPUT)
{
# ifdef STORE_REST
mbstate_t *state = data->__statep;
STORE_REST
# else
size_t cnt;
/* Make sure the remaining bytes fit into the state objects
buffer. */
assert (inend - *inptrp < 4);
for (cnt = 0; *inptrp < inend; ++cnt)
data->__statep->__value.__wchb[cnt] = *(*inptrp)++;
data->__statep->__count &= ~7;
data->__statep->__count |= cnt;
# endif
}
#endif
}
return status;
}
#undef DEFINE_INIT
#undef CHARSET_NAME
#undef DEFINE_FINI
#undef MIN_NEEDED_FROM
#undef MIN_NEEDED_TO
#undef MAX_NEEDED_FROM
#undef MAX_NEEDED_TO
#undef DEFINE_DIRECTION_OBJECTS
#undef FROM_DIRECTION
#undef EMIT_SHIFT_TO_INIT
#undef FROM_LOOP
#undef TO_LOOP
#undef SAVE_RESET_STATE
#undef RESET_INPUT_BUFFER
#undef FUNCTION_NAME
#undef PREPARE_LOOP
#undef END_LOOP
#undef ONE_DIRECTION
#undef STORE_REST

View File

@ -0,0 +1,341 @@
/* C string table handling.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/cdefs.h>
#include <sys/param.h>
struct Strent
{
const char *string;
size_t len;
struct Strent *next;
struct Strent *left;
struct Strent *right;
size_t offset;
char reverse[0];
};
struct memoryblock
{
struct memoryblock *next;
char memory[0];
};
struct Strtab
{
struct Strent *root;
struct memoryblock *memory;
char *backp;
size_t left;
size_t total;
struct Strent null;
};
/* Cache for the pagesize. We correct this value a bit so that `malloc'
is not allocating more than a page. */
static size_t ps;
extern void *xmalloc (size_t n) __attribute_malloc__;
/* Prototypes for our functions that are used from iconvconfig.c. If
you change these, change also iconvconfig.c. */
/* Create new C string table object in memory. */
extern struct Strtab *strtabinit (void);
/* Free resources allocated for C string table ST. */
extern void strtabfree (struct Strtab *st);
/* Add string STR (length LEN is != 0) to C string table ST. */
extern struct Strent *strtabadd (struct Strtab *st, const char *str,
size_t len);
/* Finalize string table ST and store size in *SIZE and return a pointer. */
extern void *strtabfinalize (struct Strtab *st, size_t *size);
/* Get offset in string table for string associated with SE. */
extern size_t strtaboffset (struct Strent *se);
struct Strtab *
strtabinit (void)
{
struct Strtab *ret;
if (ps == 0)
{
ps = sysconf (_SC_PAGESIZE) - 2 * sizeof (void *);
assert (sizeof (struct memoryblock) < ps);
}
ret = (struct Strtab *) calloc (1, sizeof (struct Strtab));
if (ret != NULL)
{
ret->null.len = 1;
ret->null.string = "";
}
return ret;
}
static void
morememory (struct Strtab *st, size_t len)
{
struct memoryblock *newmem;
if (len < ps)
len = ps;
newmem = (struct memoryblock *) malloc (len);
if (newmem == NULL)
abort ();
newmem->next = st->memory;
st->memory = newmem;
st->backp = newmem->memory;
st->left = len - offsetof (struct memoryblock, memory);
}
void
strtabfree (struct Strtab *st)
{
struct memoryblock *mb = st->memory;
while (mb != NULL)
{
void *old = mb;
mb = mb->next;
free (old);
}
free (st);
}
static struct Strent *
newstring (struct Strtab *st, const char *str, size_t len)
{
struct Strent *newstr;
size_t align;
int i;
/* Compute the amount of padding needed to make the structure aligned. */
align = ((__alignof__ (struct Strent)
- (((uintptr_t) st->backp)
& (__alignof__ (struct Strent) - 1)))
& (__alignof__ (struct Strent) - 1));
/* Make sure there is enough room in the memory block. */
if (st->left < align + sizeof (struct Strent) + len)
{
morememory (st, sizeof (struct Strent) + len);
align = 0;
}
/* Create the reserved string. */
newstr = (struct Strent *) (st->backp + align);
newstr->string = str;
newstr->len = len;
newstr->next = NULL;
newstr->left = NULL;
newstr->right = NULL;
newstr->offset = 0;
for (i = len - 2; i >= 0; --i)
newstr->reverse[i] = str[len - 2 - i];
newstr->reverse[len - 1] = '\0';
st->backp += align + sizeof (struct Strent) + len;
st->left -= align + sizeof (struct Strent) + len;
return newstr;
}
/* XXX This function should definitely be rewritten to use a balancing
tree algorith (AVL, red-black trees). For now a simple, correct
implementation is enough. */
static struct Strent **
searchstring (struct Strent **sep, struct Strent *newstr)
{
int cmpres;
/* More strings? */
if (*sep == NULL)
{
*sep = newstr;
return sep;
}
/* Compare the strings. */
cmpres = memcmp ((*sep)->reverse, newstr->reverse,
MIN ((*sep)->len, newstr->len) - 1);
if (cmpres == 0)
/* We found a matching string. */
return sep;
else if (cmpres > 0)
return searchstring (&(*sep)->left, newstr);
else
return searchstring (&(*sep)->right, newstr);
}
/* Add new string. The actual string is assumed to be permanent. */
struct Strent *
strtabadd (struct Strtab *st, const char *str, size_t len)
{
struct Strent *newstr;
struct Strent **sep;
/* Compute the string length if the caller doesn't know it. */
if (len == 0)
len = strlen (str) + 1;
/* Make sure all "" strings get offset 0. */
if (len == 1)
return &st->null;
/* Allocate memory for the new string and its associated information. */
newstr = newstring (st, str, len);
/* Search in the array for the place to insert the string. If there
is no string with matching prefix and no string with matching
leading substring, create a new entry. */
sep = searchstring (&st->root, newstr);
if (*sep != newstr)
{
/* This is not the same entry. This means we have a prefix match. */
if ((*sep)->len > newstr->len)
{
struct Strent *subs;
for (subs = (*sep)->next; subs; subs = subs->next)
if (subs->len == newstr->len)
{
/* We have an exact match with a substring. Free the memory
we allocated. */
st->left += st->backp - (char *) newstr;
st->backp = (char *) newstr;
return subs;
}
/* We have a new substring. This means we don't need the reverse
string of this entry anymore. */
st->backp -= newstr->len;
st->left += newstr->len;
newstr->next = (*sep)->next;
(*sep)->next = newstr;
}
else if ((*sep)->len != newstr->len)
{
/* When we get here it means that the string we are about to
add has a common prefix with a string we already have but
it is longer. In this case we have to put it first. */
st->total += newstr->len - (*sep)->len;
newstr->next = *sep;
newstr->left = (*sep)->left;
newstr->right = (*sep)->right;
*sep = newstr;
}
else
{
/* We have an exact match. Free the memory we allocated. */
st->left += st->backp - (char *) newstr;
st->backp = (char *) newstr;
newstr = *sep;
}
}
else
st->total += newstr->len;
return newstr;
}
static void
copystrings (struct Strent *nodep, char **freep, size_t *offsetp)
{
struct Strent *subs;
if (nodep->left != NULL)
copystrings (nodep->left, freep, offsetp);
/* Process the current node. */
nodep->offset = *offsetp;
*freep = (char *) memcpy (*freep, nodep->string, nodep->len);
*freep += nodep->len;
*offsetp += nodep->len;
for (subs = nodep->next; subs != NULL; subs = subs->next)
{
assert (subs->len < nodep->len);
subs->offset = nodep->offset + nodep->len - subs->len;
}
if (nodep->right != NULL)
copystrings (nodep->right, freep, offsetp);
}
void *
strtabfinalize (struct Strtab *st, size_t *size)
{
size_t copylen;
char *endp;
char *retval;
/* Fill in the information. */
endp = retval = (char *) xmalloc (st->total + 1);
/* Always put an empty string at the beginning so that a zero offset
can mean error. */
*endp++ = '\0';
/* Now run through the tree and add all the string while also updating
the offset members of the elfstrent records. */
copylen = 1;
copystrings (st->root, &endp, &copylen);
assert (copylen == st->total + 1);
assert (endp = retval + st->total + 1);
*size = copylen;
return retval;
}
size_t
strtaboffset (struct Strent *se)
{
return se->offset;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 1983, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ftp.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _ARPA_FTP_H_
#define _ARPA_FTP_H_
/* Definitions for FTP; see RFC-765. */
/*
* Reply codes.
*/
#define PRELIM 1 /* positive preliminary */
#define COMPLETE 2 /* positive completion */
#define CONTINUE 3 /* positive intermediate */
#define TRANSIENT 4 /* transient negative completion */
#define ERROR 5 /* permanent negative completion */
/*
* Type codes
*/
#define TYPE_A 1 /* ASCII */
#define TYPE_E 2 /* EBCDIC */
#define TYPE_I 3 /* image */
#define TYPE_L 4 /* local byte size */
#ifdef FTP_NAMES
char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" };
#endif
/*
* Form codes
*/
#define FORM_N 1 /* non-print */
#define FORM_T 2 /* telnet format effectors */
#define FORM_C 3 /* carriage control (ASA) */
#ifdef FTP_NAMES
char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" };
#endif
/*
* Structure codes
*/
#define STRU_F 1 /* file (no record structure) */
#define STRU_R 2 /* record structure */
#define STRU_P 3 /* page structure */
#ifdef FTP_NAMES
char *strunames[] = {"0", "File", "Record", "Page" };
#endif
/*
* Mode types
*/
#define MODE_S 1 /* stream */
#define MODE_B 2 /* block */
#define MODE_C 3 /* compressed */
#ifdef FTP_NAMES
char *modenames[] = {"0", "Stream", "Block", "Compressed" };
#endif
/*
* Record Tokens
*/
#define REC_ESC '\377' /* Record-mode Escape */
#define REC_EOR '\001' /* Record-mode End-of-Record */
#define REC_EOF '\002' /* Record-mode End-of-File */
/*
* Block Header
*/
#define BLK_EOR 0x80 /* Block is End-of-Record */
#define BLK_EOF 0x40 /* Block is End-of-File */
#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */
#define BLK_RESTART 0x10 /* Block is Restart Marker */
#define BLK_BYTECOUNT 2 /* Bytes in this block */
#endif /* !_FTP_H_ */

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* @(#)inet.h 8.1 (Berkeley) 6/2/93
* From: Id: inet.h,v 8.5 1997/01/29 08:48:09 vixie Exp $
* $FreeBSD: src/include/arpa/inet.h,v 1.22 2002/04/10 10:51:53 mike Exp $
*/
#ifndef _ARPA_INET_H_
#define _ARPA_INET_H_
/* External definitions for functions in inet(3), addr2ascii(3) */
#include <sys/cdefs.h>
#include <sys/types.h>
#include <machine/ansi.h>
/* Required for byteorder(3) functions. */
#include <machine/endian.h>
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
#ifndef _UINT16_T_DECLARED
typedef __uint16_t uint16_t;
#define _UINT16_T_DECLARED
#endif
#ifndef _UINT32_T_DECLARED
typedef __uint32_t uint32_t;
#define _UINT32_T_DECLARED
#endif
#ifndef _IN_ADDR_T_DECLARED
typedef uint32_t in_addr_t;
#define _IN_ADDR_T_DECLARED
#endif
#ifndef _IN_PORT_T_DECLARED
typedef uint16_t in_port_t;
#define _IN_PORT_T_DECLARED
#endif
#ifndef _POSIX_SOURCE
#ifdef _BSD_SIZE_T_
typedef _BSD_SIZE_T_ size_t;
#undef _BSD_SIZE_T_
#endif
#endif /* !_POSIX_SOURCE */
/*
* XXX socklen_t is used by a POSIX.1-2001 interface, but not required by
* POSIX.1-2001.
*/
#ifndef __socklen_t_defined
typedef unsigned int socklen_t;
#define __socklen_t_defined 1
#endif
#ifdef _BSD_SOCKLEN_T_
typedef _BSD_SOCKLEN_T_ socklen_t;
#undef _BSD_SOCKLEN_T_
#endif
#ifndef _STRUCT_IN_ADDR_DECLARED
struct in_addr {
in_addr_t s_addr;
};
#define _STRUCT_IN_ADDR_DECLARED
#endif
#define inet_addr __inet_addr
#define inet_aton __inet_aton
#define inet_lnaof __inet_lnaof
#define inet_makeaddr __inet_makeaddr
#define inet_neta __inet_neta
#define inet_netof __inet_netof
#define inet_network __inet_network
#define inet_net_ntop __inet_net_ntop
#define inet_net_pton __inet_net_pton
#define inet_ntoa __inet_ntoa
#define inet_pton __inet_pton
#define inet_ntop __inet_ntop
#define inet_nsap_addr __inet_nsap_addr
#define inet_nsap_ntoa __inet_nsap_ntoa
__BEGIN_DECLS
in_addr_t inet_addr(const char *);
char *inet_ntoa(struct in_addr);
const char *inet_ntop(int, const void *, char *, socklen_t);
int inet_pton(int, const char *, void *);
int ascii2addr(int, const char *, void *);
char *addr2ascii(int, const void *, int, char *);
int inet_aton(const char *, struct in_addr *);
in_addr_t inet_lnaof(struct in_addr);
struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
char * inet_neta(in_addr_t, char *, size_t);
in_addr_t inet_netof(struct in_addr);
in_addr_t inet_network(const char *);
char *inet_net_ntop(int, const void *, int, char *, size_t);
int inet_net_pton(int, const char *, void *, size_t);
unsigned inet_nsap_addr(const char *, unsigned char *, int);
char *inet_nsap_ntoa(int, const unsigned char *, char *);
__END_DECLS
#endif /* !_ARPA_INET_H_ */

View File

@ -0,0 +1,449 @@
/*
* Copyright (c) 1983, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* From: Id: nameser.h,v 8.16 1998/02/06 00:35:58 halley Exp
* $FreeBSD: src/include/arpa/nameser.h,v 1.16 2002/03/23 17:24:55 imp Exp $
*/
#ifndef _ARPA_NAMESER_H_
#define _ARPA_NAMESER_H_
#define BIND_4_COMPAT
#include <sys/types.h>
#include <sys/cdefs.h>
/*
* revision information. this is the release date in YYYYMMDD format.
* it can change every day so the right thing to do with it is use it
* in preprocessor commands such as "#if (__NAMESER > 19931104)". do not
* compare for equality; rather, use it to determine whether your libnameser.a
* is new enough to contain a certain feature.
*/
/* XXXRTH I made this bigger than __BIND in 4.9.5 T6B */
#define __NAMESER 19961001 /* New interface version stamp. */
/*
* Define constants based on RFC 883, RFC 1034, RFC 1035
*/
#define NS_PACKETSZ 512 /* maximum packet size */
#define NS_MAXDNAME 1025 /* maximum domain name */
#define NS_MAXCDNAME 255 /* maximum compressed domain name */
#define NS_MAXLABEL 63 /* maximum length of domain label */
#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */
#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */
#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */
#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */
#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */
#define NS_INADDRSZ 4 /* IPv4 T_A */
#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */
#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */
#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */
/*
* These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
* in synch with it.
*/
typedef enum __ns_sect {
ns_s_qd = 0, /* Query: Question. */
ns_s_zn = 0, /* Update: Zone. */
ns_s_an = 1, /* Query: Answer. */
ns_s_pr = 1, /* Update: Prerequisites. */
ns_s_ns = 2, /* Query: Name servers. */
ns_s_ud = 2, /* Update: Update. */
ns_s_ar = 3, /* Query|Update: Additional records. */
ns_s_max = 4
} ns_sect;
/*
* This is a message handle. It is caller allocated and has no dynamic data.
* This structure is intended to be opaque to all but ns_parse.c, thus the
* leading _'s on the member names. Use the accessor functions, not the _'s.
*/
typedef struct __ns_msg {
const u_char *_msg, *_eom;
u_int16_t _id, _flags, _counts[ns_s_max];
const u_char *_sections[ns_s_max];
ns_sect _sect;
int _rrnum;
const u_char *_ptr;
} ns_msg;
/* Private data structure - do not use from outside library. */
struct _ns_flagdata { int mask, shift; };
extern struct _ns_flagdata _ns_flagdata[];
/* Accessor macros - this is part of the public interface. */
#define ns_msg_getflag(handle, flag) ( \
((handle)._flags & _ns_flagdata[flag].mask) \
>> _ns_flagdata[flag].shift \
)
#define ns_msg_id(handle) ((handle)._id + 0)
#define ns_msg_base(handle) ((handle)._msg + 0)
#define ns_msg_end(handle) ((handle)._eom + 0)
#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
/*
* This is a parsed record. It is caller allocated and has no dynamic data.
*/
typedef struct __ns_rr {
char name[NS_MAXDNAME]; /* XXX need to malloc */
u_int16_t type;
u_int16_t rr_class;
u_int32_t ttl;
u_int16_t rdlength;
const u_char *rdata;
} ns_rr;
/* Accessor macros - this is part of the public interface. */
#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
#define ns_rr_type(rr) ((rr).type + 0)
#define ns_rr_class(rr) ((rr).rr_class + 0)
#define ns_rr_ttl(rr) ((rr).ttl + 0)
#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
#define ns_rr_rdata(rr) ((rr).rdata + 0)
/*
* These don't have to be in the same order as in the packet flags word,
* and they can even overlap in some cases, but they will need to be kept
* in synch with ns_parse.c:ns_flagdata[].
*/
typedef enum __ns_flag {
ns_f_qr, /* Question/Response. */
ns_f_opcode, /* Operation code. */
ns_f_aa, /* Authoritative Answer. */
ns_f_tc, /* Truncation occurred. */
ns_f_rd, /* Recursion Desired. */
ns_f_ra, /* Recursion Available. */
ns_f_z, /* MBZ. */
ns_f_ad, /* Authentic Data (DNSSEC). */
ns_f_cd, /* Checking Disabled (DNSSEC). */
ns_f_rcode, /* Response code. */
ns_f_max
} ns_flag;
/*
* Currently defined opcodes.
*/
typedef enum __ns_opcode {
ns_o_query = 0, /* Standard query. */
ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */
ns_o_status = 2, /* Name server status query (unsupported). */
/* Opcode 3 is undefined/reserved. */
ns_o_notify = 4, /* Zone change notification. */
ns_o_update = 5, /* Zone update message. */
ns_o_max = 6
} ns_opcode;
/*
* Currently defined response codes.
*/
typedef enum __ns_rcode {
ns_r_noerror = 0, /* No error occurred. */
ns_r_formerr = 1, /* Format error. */
ns_r_servfail = 2, /* Server failure. */
ns_r_nxdomain = 3, /* Name error. */
ns_r_notimpl = 4, /* Unimplemented. */
ns_r_refused = 5, /* Operation refused. */
/* these are for BIND_UPDATE */
ns_r_yxdomain = 6, /* Name exists */
ns_r_yxrrset = 7, /* RRset exists */
ns_r_nxrrset = 8, /* RRset does not exist */
ns_r_notauth = 9, /* Not authoritative for zone */
ns_r_notzone = 10, /* Zone of record different from zone section */
ns_r_max = 11
} ns_rcode;
/* BIND_UPDATE */
typedef enum __ns_update_operation {
ns_uop_delete = 0,
ns_uop_add = 1,
ns_uop_max = 2
} ns_update_operation;
/*
* This RR-like structure is particular to UPDATE.
*/
struct ns_updrec {
struct ns_updrec *r_prev; /* prev record */
struct ns_updrec *r_next; /* next record */
u_int8_t r_section; /* ZONE/PREREQUISITE/UPDATE */
char * r_dname; /* owner of the RR */
u_int16_t r_class; /* class number */
u_int16_t r_type; /* type number */
u_int32_t r_ttl; /* time to live */
u_char * r_data; /* rdata fields as text string */
u_int16_t r_size; /* size of r_data field */
int r_opcode; /* type of operation */
/* following fields for private use by the resolver/server routines */
struct ns_updrec *r_grpnext; /* next record when grouped */
struct databuf *r_dp; /* databuf to process */
struct databuf *r_deldp; /* databuf's deleted/overwritten */
u_int16_t r_zone; /* zone number on server */
};
typedef struct ns_updrec ns_updrec;
/*
* Currently defined type values for resources and queries.
*/
typedef enum __ns_type {
ns_t_a = 1, /* Host address. */
ns_t_ns = 2, /* Authoritative server. */
ns_t_md = 3, /* Mail destination. */
ns_t_mf = 4, /* Mail forwarder. */
ns_t_cname = 5, /* Canonical name. */
ns_t_soa = 6, /* Start of authority zone. */
ns_t_mb = 7, /* Mailbox domain name. */
ns_t_mg = 8, /* Mail group member. */
ns_t_mr = 9, /* Mail rename name. */
ns_t_null = 10, /* Null resource record. */
ns_t_wks = 11, /* Well known service. */
ns_t_ptr = 12, /* Domain name pointer. */
ns_t_hinfo = 13, /* Host information. */
ns_t_minfo = 14, /* Mailbox information. */
ns_t_mx = 15, /* Mail routing information. */
ns_t_txt = 16, /* Text strings. */
ns_t_rp = 17, /* Responsible person. */
ns_t_afsdb = 18, /* AFS cell database. */
ns_t_x25 = 19, /* X_25 calling address. */
ns_t_isdn = 20, /* ISDN calling address. */
ns_t_rt = 21, /* Router. */
ns_t_nsap = 22, /* NSAP address. */
ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
ns_t_sig = 24, /* Security signature. */
ns_t_key = 25, /* Security key. */
ns_t_px = 26, /* X.400 mail mapping. */
ns_t_gpos = 27, /* Geographical position (withdrawn). */
ns_t_aaaa = 28, /* Ip6 Address. */
ns_t_loc = 29, /* Location Information. */
ns_t_nxt = 30, /* Next domain (security). */
ns_t_eid = 31, /* Endpoint identifier. */
ns_t_nimloc = 32, /* Nimrod Locator. */
ns_t_srv = 33, /* Server Selection. */
ns_t_atma = 34, /* ATM Address */
ns_t_naptr = 35, /* Naming Authority PoinTeR */
ns_t_opt = 41, /* OPT pseudo-RR, RFC2761 */
/* Query type values which do not appear in resource records. */
ns_t_ixfr = 251, /* Incremental zone transfer. */
ns_t_axfr = 252, /* Transfer zone of authority. */
ns_t_mailb = 253, /* Transfer mailbox records. */
ns_t_maila = 254, /* Transfer mail agent records. */
ns_t_any = 255, /* Wildcard match. */
ns_t_max = 65536
} ns_type;
/*
* Values for class field
*/
typedef enum __ns_class {
ns_c_in = 1, /* Internet. */
/* Class 2 unallocated/unsupported. */
ns_c_chaos = 3, /* MIT Chaos-net. */
ns_c_hs = 4, /* MIT Hesiod. */
/* Query class values which do not appear in resource records */
ns_c_none = 254, /* for prereq. sections in update requests */
ns_c_any = 255, /* Wildcard match. */
ns_c_max = 65536
} ns_class;
/*
* Flags field of the KEY RR rdata
*/
#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */
#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */
#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */
#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */
#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */
/* The type bits can also be interpreted independently, as single bits: */
#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */
#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */
#define NS_KEY_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */
#define NS_KEY_RESERVED3 0x1000 /* reserved - must be zero */
#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */
#define NS_KEY_USERACCOUNT 0x0400 /* key is assoc. with a user acct */
#define NS_KEY_ENTITY 0x0200 /* key is assoc. with entity eg host */
#define NS_KEY_ZONEKEY 0x0100 /* key is zone key */
#define NS_KEY_IPSEC 0x0080 /* key is for IPSEC (host or user)*/
#define NS_KEY_EMAIL 0x0040 /* key is for email (MIME security) */
#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */
#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */
#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */
#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED3 | \
NS_KEY_RESERVED4 | \
NS_KEY_RESERVED10 | \
NS_KEY_RESERVED11 )
/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
#define NS_ALG_MD5RSA 1 /* MD5 with RSA */
#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */
#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */
/* Signatures */
#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */
#define NS_MD5RSA_MAX_BITS 2552
/* Total of binary mod and exp */
#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
/* Max length of text sig block */
#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
/* Offsets into SIG record rdata to find various values */
#define NS_SIG_TYPE 0 /* Type flags */
#define NS_SIG_ALG 2 /* Algorithm */
#define NS_SIG_LABELS 3 /* How many labels in name */
#define NS_SIG_OTTL 4 /* Original TTL */
#define NS_SIG_EXPIR 8 /* Expiration time */
#define NS_SIG_SIGNED 12 /* Signature time */
#define NS_SIG_FOOT 16 /* Key footprint */
#define NS_SIG_SIGNER 18 /* Domain name of who signed it */
/* How RR types are represented as bit-flags in NXT records */
#define NS_NXT_BITS 8
#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
/*
* Inline versions of get/put short/long. Pointer is advanced.
*/
#define NS_GET16(s, cp) { \
register u_char *t_cp = (u_char *)(cp); \
(s) = ((u_int16_t)t_cp[0] << 8) \
| ((u_int16_t)t_cp[1]) \
; \
(cp) += NS_INT16SZ; \
}
#define NS_GET32(l, cp) { \
register u_char *t_cp = (u_char *)(cp); \
(l) = ((u_int32_t)t_cp[0] << 24) \
| ((u_int32_t)t_cp[1] << 16) \
| ((u_int32_t)t_cp[2] << 8) \
| ((u_int32_t)t_cp[3]) \
; \
(cp) += NS_INT32SZ; \
}
#define NS_PUT16(s, cp) { \
register u_int16_t t_s = (u_int16_t)(s); \
register u_char *t_cp = (u_char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += NS_INT16SZ; \
}
#define NS_PUT32(l, cp) { \
register u_int32_t t_l = (u_int32_t)(l); \
register u_char *t_cp = (u_char *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += NS_INT32SZ; \
}
/*
* ANSI C identifier hiding.
*/
#define ns_get16 __ns_get16
#define ns_get32 __ns_get32
#define ns_put16 __ns_put16
#define ns_put32 __ns_put32
#define ns_initparse __ns_initparse
#define ns_parserr __ns_parserr
#define ns_sprintrr __ns_sprintrr
#define ns_sprintrrf __ns_sprintrrf
#define ns_format_ttl __ns_format_ttl
#define ns_parse_ttl __ns_parse_ttl
#define ns_name_ntop __ns_name_ntop
#define ns_name_pton __ns_name_pton
#define ns_name_unpack __ns_name_unpack
#define ns_name_pack __ns_name_pack
#define ns_name_compress __ns_name_compress
#define ns_name_uncompress __ns_name_uncompress
__BEGIN_DECLS
u_int ns_get16(const u_char *);
u_long ns_get32(const u_char *);
void ns_put16(u_int, u_char *);
void ns_put32(u_long, u_char *);
int ns_initparse(const u_char *, int, ns_msg *);
int ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
int ns_sprintrr(const ns_msg *, const ns_rr *,
const char *, const char *, char *, size_t);
int ns_sprintrrf(const u_char *, size_t, const char *,
ns_class, ns_type, u_long, const u_char *,
size_t, const char *, const char *,
char *, size_t);
int ns_format_ttl(u_long, char *, size_t);
int ns_parse_ttl(const char *, u_long *);
int ns_name_ntop(const u_char *, char *, size_t);
int ns_name_pton(const char *, u_char *, size_t);
int ns_name_unpack(const u_char *, const u_char *,
const u_char *, u_char *, size_t);
int ns_name_pack(const u_char *, u_char *, int,
const u_char **, const u_char **);
int ns_name_uncompress(const u_char *, const u_char *,
const u_char *, char *, size_t);
int ns_name_compress(const char *, u_char *, size_t,
const u_char **, const u_char **);
int ns_name_skip(const u_char **, const u_char *);
__END_DECLS
#ifdef BIND_4_COMPAT
#include <arpa/nameser_compat.h>
#endif
#endif /* !_ARPA_NAMESER_H_ */

Some files were not shown because too many files have changed in this diff Show More