SUMMARY: shared libraries / multiuser dump (long)

From: Chuck Smoko - E41 (csmoko%earth@relay.nswc.navy.mil)
Date: Thu Jul 16 1992 - 03:37:37 CDT


Hello Fellow Sun Managers,
This is a summary of a couple of sun questions that I had. What I
asked for was sent in short order. I will first include the original
questions; then I will include the most intesesting replies. Thanks to
all who responded. I will enclose my comments in []s.

                                                        Thanks,
                                                        Chuck Smoko

                       csmoko@relay.nswc.navy.mil

> ==== Part 1 ====
>
> I have run into something that bothered me after replacing the shared libc
> on my SS2 (Sunos 4.1.2) with one that uses the resolver routines. I first
> replaced the shared libc resolver routines with the Sun supplied resolver
> routines. The instructions on how to do this were posted quite a while
> ago. The instructions were also updated when 4.1.2 came along. I also
> tried to install the Sunos port of bind 4.8.3, a.k.a. 'resolv+-2.0'. In
> both cases I ran into the same little worry. The actual install of each
> of these went well. Like the instructions said, I created a new
> libc.so.X.Y. I was just wondering why there was no corresponding
> libc.sa.X.Y. Neither the instructions for using the Sun supplied
> routines, nor the resolv+2.0 instructions, discussed how to create this
> file (libc.sa.X.Y that is).
>
> My curiosity got the best of me; so I went searching through the manuals
> to find out what was in this shared library. I found what I was looking
> for in the Programmer's Overview Utilities and Libraries Manual (or
> something like that). It was in chapter 1 in the section that covers what
> the libxxx.sa file is and how to make one. According to Sun, the
> libc.sa.X.Y file contains "global initialized data". Sun even gave an
> example using sys_errlist and said that this identifier needed to be
> referenced in lib.sa.X.Y because it was initialized and global. The Sun
> documentation also said (with a big bold faced CAUTION: label) saying
> that: "... Failure to do so (create the .sa file) can degrade system
> performance. ...".
>
> There are several things that I can do, a.) Don't worry about it. b.)
> Copy the libc.sa.X.Y-1 to libc.sa.X.Y (just use the old one). c.) Create
> a new libc.sa.X.Y file that has the initialized globals properly
> referenced. I do not have the source for the Sun supplied routines, but
> the resolv+-2.0 routines have initialized globals. Well, I am looking for
> some advice on the shared libc to see what would be best.
>
> The creator (port'er of BIND 4.8.3) of resolv+-2.0, who's Bill Wisner
> <wisner@ims.alaska.edu>, gives credit to Sun's Greg Earle for the
> information on how to create shared libs.
>

From: "Casper H.S. Dik" <casper@fwi.uva.nl>

 ....

The Sun manual is correct in stating that performance degradation will
result. Not with programs already compiled &linked, but for
programs compiled after the fact. In short, this is what happens:

When data from the shared library is referenced by an .o file that isn't
compiled with -pic, the linker must be able to resolve the address of
that data at link time. You can only resolve such an address at
link time when it is statically linked. If you fail to provide a
libc.sa.X.Y (with exactly the same name, s/so/sa/), the compile
time linker cannot resolve this. In that case the binding is postponed
to runtime. This final run-time binding degrades performance in several ways:
more linking done at runtime - slower program start, but most important:
the executable image can no longer be shared among programs: the effect is
that all executables get their own private copies of the text segment
on the swap space: - more VM use, more swap use, performance out of the door.
You can usually make a matching libc.sa.X.Y by making a link to the original
libc.sa.*.

Because of the way the X11R4 libraries were constructed, this was true
for most X11R4 programs.

Secondly, I would like to give a word of warning about replacing libc.so
with one using BIND 4.8.3/libresolv2.0+.

Sun's daemons that do hostname based access control (mountd/rshd/rlogind etc)
rely on the fact that gethostbyaddr() returns a double checked hostname.
(By doing a gethostbyname() after the initial gethostbyaddr(). This
holds for both the NIS based resolver (ypserv host map with resolver)
and the one in libresolv.a.

If you use bind 4.8.3/resolv+ you must make sure that the same checks are
performed or you're a walk over for most cracker. (And yes, crackers have
been doing these sort of things)

There is also at least one commercial software package that requires
gethostent(). It is missing from a shared library with the resolver.

-------------------------------------------------------------------------------

From: Piete.Brooks@cl.cam.ac.uk

 ...

Me too !

I do generate a new .sa. file to avoid sligging the system ....

libc.sa:
        ver=`/bin/ls /usr/lib/libc.so.* | awk -f ${AWKFILE}`; \
        rm -f libc.sa.$$ver; \
        (cd tmpa; ar cr ../libc.sa.$$ver *); \
        ranlib libc.sa.$$ver; \
        echo libc.sa.$$ver built.

be careful to extract the files from libc.sa.* rather than the shared library,
or you won;t be able to link it with -PIC objects (can't mix -pic and -PIC)

-------------------------------------------------------------------------------

From: seeger@thedon.cis.ufl.edu (F. L. Charles Seeger III)

 ....

Attached is a shar file for incorporating the true BSD 4.8.3 resolver
routines in the shared libc (none of the perversions of resolv+ or
Sun's resolvers). One must handle strings a bit differently. Otherwise
I only found one global initialized variable to add to libc.sa. If you
find another, please let me know. Also note that patch 100531-02 is
now available. I should make a new shar file.

I did this for 4.1.1, too. Don't know why it hasn't become as well
known as the others.

 ...

[ At the the end of the summary is the README from the included SHARFILE ]

-----------------------------------------------------------------------------

From: Dieter Muller <dworkin@merlin.rootgroup.com>
 
 ...

: Like the instructions said, I created a new libc.so.X.Y. I was just
: wondering why there was no corresponding libc.sa.X.Y. Neither the
: instructions for using the Sun supplied routines, nor the resolv+2.0
: instructions, discussed how to create this file (libc.sa.X.Y that is).

You take the initialized variables (globals and local statics), stuff
them into their own .c file, compile it, and include it in both the
.so and the .sa file. The .sa is identical to a .a, just the name has
been changed.

: The Sun documentation also said (with a big bold faced CAUTION:
: label) saying that: "... Failure to do so (create the .sa file) can
: degrade system performance. ...".

: There are several things that I can do, a.) Don't worry about it. b.)
: Copy the libc.sa.X.Y-1 to libc.sa.X.Y (just use the old one). c.)
: Create a new libc.sa.X.Y file that has the initialized globals
: properly referenced. I do not have the source for the Sun supplied
: routines, but the resolv+-2.0 routines have initialized globals.
: Well, I am looking for some advice on the shared libc to see what
: would be best.

First of all, the .sa file is only used at link time, not at run time.
Anything that's referenced in it gets included in the executable, just
like with static libraries. Therefore, you don't need to worry about
it unless you're compiling new applications.

The performance hit they mention is due to the way shared libraries
are mapped. The .so file is mapped copy-on-write into the process
address space. If you modify a variable, a private copy of the page
it is on is created, the page is marked writable, and life goes on.
This costs time (copying isn't free) and memory (another page of swap
is used, two copies of that particular page of the .so reside in
memory, etc). On some systems, making a page data-writable turns off
any instruction caching, which gives you a serious performance hit if
code and data are in the same 8K page.

If no new static or global initialized data has been introduced, you
don't need to worry at all (uninitialized data doesn't count, it
doesn't get allocated until run time). If new data does exist, you
can still ignore the problem and take a performance hit that you
probably won't notice. Or, you can go through the hassles of making
the new .sa. Note that this will only help applications built after
you do this. Older ones will still take the performance hit.

> ==== Part 2 ====
>
> I am looking for a MULTI-USER MODE dump(8) that will work on Suns. Yes, I
> know that dump should be run only while in single-user mode. However, I
> have heard from several reliable sources that, there have been hacks made
> to dump that allow running it in multi-user mode. Supposedly the modified
> dump will not backup inodes that have changed since the dump of that
> filesystem began. I have heard all kinds of horror stories of admins that
> have lost data due to using the vendor supplied dump on active
> filesystems. I hear that the dump completes, but the files on it MAY BE
> unusable.
>
> I would like to do incremental backups automaticly at 3am while in
> multi-user mode. (I have a bunch of shell scripts that feed dump the
> proper command line arguments.) Because most users would not be logged
> in, there would be little chance that anyone would be changing their
> files. I am partial to dump rather than tar or cpio because of dump's
> file system approach to backups. Not to mention, my scripts are also are
> written for dump. I also like the way dump does incremental backups by
> referring to /etc/dumpdates. I have considered the GNU version of tar(1),
> but it lacks the concept of a level X dump, containing all files that have
> changed since the date of level X-1 dump. GNU tar can backup all files
> that are newer than some date, but the date is entered on the command line,
> not read from a file. Dump is almost the idea program, except it to be
> run in single-user mode.

[ Many responded with advice to get Sun's "Backup Copilot" program which
solves the problem with filesystem locking. Others said to use
tar/cpio and someone thought that I should 'fix' GNUtar to read the
dumpdates file. Others thought that I should use Solbourne's dump.
But, most of the users seem to "take their chances" with running dump
in multiuser mode. ]

From: trdlnk!mike@uunet.UU.NET (Michael Sullivan)

 ...

I too have heard of the problem with using dump in multiuser mode.
Solbourne's dump(8) manual page has this addition (compared to Sun's):

     S Enables the Purdue ``live filesystem'' modifications.
          Files that are modified while dump is running are not
          dumped. This allows the dumping of filesystems while
          the system is running multi-user, without getting
          ``corrupted dump'' complaints from restore(8).

However, I am not too enthusiastic about files not getting dumped,
so I still don't do any important dumps in multiuser mode.

------------------------------------------------------------------------------

[ again ] From: Dieter Muller <dworkin@merlin.rootgroup.com>

If you're using sun4s, steal it off of a Solbourne. The Solbourne
dump has the changes included. You *don't* want to run dumps on a
live filesystem. Note that you could unmount a particular filesystem,
dump it, and remount it while multiuser, which will still avoid the
problem of the world changing out from under dump.

[ End of included messages ]

[ I am including the README from the included shar file from above ]

UFLnotes: This file is derived from Greg Earle's customized-for-DNS
                /usr/lib/shlib.etc/README file, updated for 4.1.2. It
                contains additional guidance for installing the resolver
                routines from the BIND-4.8.3 distribution.

                It should be possible to build the resolver routines without
                changing the Sun include files, but we will just integrate
                the latest changes from UCB. This entails installing
                paths.h in /usr/include, along with replacements for
                netdb.h, resolv.h, arpa/inet.h and arpa/nameser.h.

                Finally, small patches for res_init.c and res_query.c
                and the introduction of a new file res_data.c are needed
                to be compatible with Sun's shared libs. Makefile changes
                are left as an exercise, just be careful to compile with
                the "-pic" option.

                BTW, okeeffe.berkeley.edu:/4.3/bind.4.8.3.tar.Z

-------------------------------------------------------------------------

        This is a procedure you can use to substitute or add
a module in your shared libc library.

Note! If you are interested in a System V libc, please substitute
        libcs5_pic.a for libc_pic.a in step 3, and
        libcs5.so.x.y.z for libc.so.x.y.z in step 14.

-------------------------------------------------------------------------

1. Become super user
        % su

2. Make a temporary directory
        % mkdir tmp

3. Change to the "tmp" directory just made, extract the pic .o from
   libc_pic.a and rm the file __.SYMDEF. The reason you need to do
   the 3 "mv" commands is because "ar" truncated filenames over
   16 characters.
        % cd tmp
        % ar x ../libc_pic.a
        % rm __.SYMDEF
        % mv rpc_dtablesize. rpc_dtablesize.o
        % mv rpc_commondata. rpc_commondata.o
        % mv xccs_multibyte. xccs_multibyte.o

UFLnotes: That last command should be:
        % mv xccs.multibyte. xccs.multibyte.o

   Note: this last mv command is not present in the original version of the
   README file that comes in /usr/lib/shlib.etc/README. If this step is
   omitted, you will produce a shared libc.so that does not contain the
   xccs_multibyte.o module. This module contains versions of the library
   functions "mbtowc", "wctomb", "mbstowcs" and "wcstombs" (see mblen(3) for
   more info on these multi-byte character functions), which operate on the
   Xerox XCCS codeset standard. Specifically, the missing functions will be

        _mbtowc_xccs(pwc, s, n)
        _wctomb_xccs(s, pwc)
        _mbstowcs_xccs(pwc, s, n)
        _wcstombs_xccs(s, pwc, n)

   These are called by the corresponding "mbtowc", "wctomb", "mbstowcs" and
   "wcstombs" functions if the codeset is XCCS (other codesets include EUC,
   ISO 2022, and a default). In short, if you use any Internationalization
   features and need to handle multi-byte character sets, do not forget this
   step.

4. If you are doing this to specifically create a libc.so that contains
   the DNS resolver routines for doing hostname/hostaddr lookups via the
   Domain Name Service (and not NIS/YP), do these additional steps. If not,
   please skip down to step 10.

UFLnotes: We use BIND-4.8.3 resolver routines, with a few changes
                to be more friendly with shared libs. Compile these and
                copy the .o files into the tmp subdirectory rather than
                unpacking Sun's libresolv.a, as in Step 5. These should
                be compiled with the "cc -pic" option and verified with
                "ld -assert pure-text *.o". Note that Sun's libc already
                has mktemp(), strpbrk() and strncasecmp() (in stricmp.o).
                However, it has neither herror() nor strerror(), so herror.o
                and strerror.o must be added. Also note that res_data.o
                contains the global initialized structure _res. Further
                note that h_errno is declared in rpc_commondata.o, which
                is already included in both libc.so and libc.sa files.
                So, these are the files that need to be copied into the
                "tmp" directory:
                                gethostnamadr.o
                                sethostent.o
                                herror.o
                                res_data.o
                                res_query.o
                                res_mkquery.o
                                res_send.o
                                res_debug.o
                                res_comp.o
                                res_init.o
                                strerror.o
                Skip Steps 5 and 7.

5. Extract the contents of /usr/lib/libresolv.a into the tmp directory:
        % ar x /usr/lib/libresolv.a
        % rm __.SYMDEF

   The libresolv.a contains object modules that are position
   independant, so they can be added to the libc_pic modules without fear.

   NOTE: You may wish to install Sun patch 100465-01 *first* before taking
   this step, as it provides a newer patched version of /usr/lib/libresolv.a.
   This fixes a serious bug that causes DNS nameserver lookups to fail if the
   first name server query yields ECONNREFUSED (Connection refused), even if
   the other nameservers specified in /etc/resolv.conf are both up & working:

Patch i.d. Bug i.d's SunOS Description
---------- --------- ----- -----------
100465-01 1076977
                        4.1 4.1 4.1.2 DNS res_send() fails if first nameserver
                        in /etc/resolv.conf returns ECONNREFUSED

6. Remove the old routine to do the hostname/addr resolution:
        % rm gethostent.o

7. Remove the libresolv module that contains `strncasecmp' (which is now
   in the main C library, so it is redundant):
        % rm strcasecmp.o

8. As also mentioned below (in step 11), edit the file `lorder-sparc' in the ..
   directory. Remove the reference to `gethostent.o' and add the
   references to the resolver library routines by applying this patch:

        % cd ..
        % diff -rc2 lorder-sparc.orig lorder-sparc
        *** lorder-sparc.orig Thu Feb 8 05:27:46 1990
        --- lorder-sparc Mon Apr 9 12:58:59 1990
        ***************
        *** 150,154 ****
          getwd.o
          getnetgrent.o
        ! gethostent.o
          ypxdr.o
          ttyname.o
        --- 150,161 ----
          getwd.o
          getnetgrent.o
        ! gethostnamadr.o
        ! sethostent.o
        ! res_query.o
        ! res_mkquery.o
        ! res_send.o
        ! res_debug.o
        ! res_comp.o
        ! res_init.o
          ypxdr.o
          ttyname.o

UFLnotes: For our BIND-4.8.3 we make this change instead.
                Note, this was done after applying patch 100531-01,
                the domestic 4.1.2 libc jumbo patch, which includes a
                new shlib.etc directory.
                
        *** lorder-sparc.orig Wed Mar 18 17:12:00 1992
        --- lorder-sparc Wed Apr 1 05:06:31 1992
        ***************
        *** 149,155 ****
          listen.o
          getwd.o
          getnetgrent.o
        ! gethostent.o
          ypxdr.o
          ttyname.o
          setbuffer.o
        --- 149,165 ----
          listen.o
          getwd.o
          getnetgrent.o
        ! gethostnamadr.o
        ! sethostent.o
        ! herror.o
        ! res_data.o
        ! res_query.o
        ! res_mkquery.o
        ! res_send.o
        ! res_debug.o
        ! res_comp.o
        ! res_init.o
        ! strerror.o
          ypxdr.o
          ttyname.o
          setbuffer.o
        ***************
        *** 455,457 ****
        --- 465,468 ----
          _psignal.o
          _ftou.o
          _crypt.o
        + mblib.o

UFLnotes: Patch 100531-01 included a fixed Makefile, so the patch
                in Step 9 has already been applied. However, it did not
                include "mblib.o" in lorder-sparc.

9. If you are running under SunOS 4.1.2, you will want to add the entry
   "mblib.o" to the very end of the "lorder-sparc" file. If you aren't running
   SunOS 4.1.2, you may now skip down to step 13.

   Also, you will need to patch the Makefile, as follows:

        *** Makefile.orig Wed Oct 23 10:13:00 1991
        --- Makefile Mon Feb 24 18:38:08 1992
        ***************
        *** 9,13 ****
          
          libc.so:
        ! ld -assert pure-text `${OBJSORT} lorder-sparc tmp`
                  /bin/ls /usr/lib/libc.so.* > TMP_FILE
                  mv a.out libc.so.`cat TMP_FILE | awk -f ${AWKFILE}`
        --- 9,13 ----
          
          libc.so:
        ! ld -assert pure-text `${OBJSORT} lorder-sparc tmp` -ldl
                  /bin/ls /usr/lib/libc.so.* > TMP_FILE
                  mv a.out libc.so.`cat TMP_FILE | awk -f ${AWKFILE}`
        ***************
        *** 15,19 ****
          
          libcs5.so:
        ! ld -assert pure-text `${OBJSORT} lorder-sparc tmp`
                  /bin/ls /usr/5lib/libc.so.* > TMP_FILE
                  mv a.out libc.so.`cat TMP_FILE | awk -f ${AWKFILE}`
        --- 15,19 ----
          
          libcs5.so:
        ! ld -assert pure-text `${OBJSORT} lorder-sparc tmp` -ldl
                  /bin/ls /usr/5lib/libc.so.* > TMP_FILE
                  mv a.out libc.so.`cat TMP_FILE | awk -f ${AWKFILE}`

10. Replace or add the .o that you wanted by doing a copy. Please
    note here that you are advised to create your object with
    the following compiler option, i.e "cc -c -pic yourprogram.c" to make
    it shareable.
        % cp your.o .

11. If you add a new module then you need to do this step.
    You need to edit the file "lorder-sparc" and add the name of the file
    you have copied from step 4 at the end of this file.
        % vi ../lorder-sparc

12. % cd ..

13. % make libc.so

UFLnotes: May need to add current directory to your path, so that
                objsort can be executed. Or fix the makefile by changing
                the definition of OBJSORT to "./objsort".

UFLnotes: But, we aren't done just yet. We need to handle the
                global intialized data...
        Copy the original libc.sa. (For 4.1.2 x=1 and y=7).
                # cp -p /usr/lib/libc.sa.x.y libc.sa.x.y.z
        For adding the BIND-4.8.3 resolver.
                # ar rv libc.sa.x.y.z tmp/res_data.o
        Now ranlib it.
                # ranlib libc.sa.x.y.z

14. Now you should have some libc.so.x.y.z built in the current directory.
    It is recommended that you tested out this library at this point
    before installing it. You can do so by setting the environment
    LD_LIBRARY_PATH to the current directory for example:
           % setenv LD_LIBRARY_PATH `pwd`
        % your_favorite_test_cmd
    Once you are satisfied that the new library worked, you can proceed
    to install it with the following commands:
        % cp libc.so.x.y.z /usr/lib
        % ldconfig
        % unsetenv LD_LIBRARY_PATH

UFLnotes: Note that suid commands, e.g. ping and arp, may not
                honor the LD_LIBRARY_PATH as expected.
                Use this command instead of the one above if both the
                so and sa portions of the shared libc are being installed.
        # cp -p libc.so.x.y.z libc.sa.x.y.z /usr/lib
        # ranlib -t /usr/lib/libc.sa.x.y.z
        # ldconfig
        # unsetenv LD_LIBRARY_PATH

15. You are now running with the new library. You can verify this by
    doing a trace command of, let's say, "date".
        % trace date
    The output should informed you that the new library is being used.

UFLnotes: Now, we really should update the following libraries
                to remain consistent:
                        /usr/lib/libc.a
                        /usr/lib/libc_p.a
                        /usr/lib/libresolv.a
                        /usr/5lib/libc.a
                        /usr/5lib/libc_p.a
                        /usr/5lib/libc.sa.2.7
                        /usr/5lib/libc.so.2.7

[ End ]



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:06:45 CDT