I am sponsoring the following self-reviewed case for myself.

It adds new archive rescan options to the Solaris link-editor
(ld). I believe it qualifies for self review:

     - The new -z rescan-now option is a straightforward
       variation on the existing -z rescan option.

     - The idea of archive rescan groups comes from
       an existing feature of the GNU ld, and is
       straightforward. Adding it to the Solaris ld
       is an additional move to improve Linux compatibility.

Copies of the current ld manpage (ld.1.orig), the proposed
new manpage (ld.1), and diffs between the two (ld.1.diffs)
can be found in the case materials.

-----

Release Binding:                                Patch/Micro

New ld options:
        -rescan-now                             Committed
        -rescan-start, --start-group, -(        Committed
        -rescan-end,   --end-group,   -)        Committed

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

This case delivers an overhaul of archive rescanning
by the ld link-editor. It adds new command options.

  There are two reasons for this work:

        1) The existing -z rescan option has a design flaw
           that must be maintained for backward compatibility.
           A new option (-z rescan-now) is needed to provide
           a solution.

        2) The GNU linker supports the concept of archive rescan
           groups. We have encountered makefiles from FOSS
           (Free and Open Source Software) that have attempted to
           pass these options to the Solaris ld. Supporting these
           options lowers the barrier to bringing software to
           Solaris.

These items involve interrelated changes to the same code,
making it convenient to address them together at this time.


New ld -z rescan-now Option
---------------------------

The CR

        6748160 problem with -zrescan

describes a problem encountered by a program built using
objects coming from multiple archives:

        cc -z rescan name.a main.a

The multiple archives have mutual dependencies, requiring
multiple passes through each archive, as triggered via
-zrescan. When the compiler calls the link-editor, the
ld command looks something like:

        ld .../crti.o .../crt1.o -z rescan name.a main.a -lc .../crtn.o

where the .../crt*.o files are supplied by the C compiler.

When ld sees a -z rescan, it waits until it has processed all of the
command arguments, and then it goes back and rescans all the archives
seen. This causes an unfortunate interaction with the crt*.o objects,
which was not foreseen when -z rescan was originally defined.

ELF init sections are constructed by concatenating the init
sections from the objects into a function called by the
runtime linker at object initialization. The function
entry is provided by crti.o, and the the return by crtn.o.
These are PROGBITS sections, with no special attributes other
than the fact that they all have the same name (.init). As such,
the link-editor is not aware of the crt*.o objects as having any
special properties --- it simply concatenates them together
in the order given, without interpretation, in the usual manner.

In the case given above, any init sections contributed by
an object in the archive that are brought into the link
via the operation of rescan will be added to the init section
in the output object after the function termination provided
by crtn.o. As such, that code will never run, and the
initializations they contain will not be carried out.

The the case of the customer related to CR 6748160, the result
of the missing initialization was a NULL pointer dereference
and a segmentation fault. Worse is the potential for such a
program to not crash in this case, and to instead silently
produce incorrect results.

The link editor has no basis to prevent this from occurring:

        - Compilers are not required to name their objects
          as crt*.o, so we cannot make any assumptions about
          special file names.

        - The glue code that is provided by these crt*.o
          objects are not tagged in a way that uniquely
          identifies their purpose.

        - Users are allowed to use the same names for their
          objects, so even if we could assume the names of
          these special compiler provided objects, we could only
          use that information if we knew where the compiler
          keeps them on disk. Compilers can be installed in
          arbitrary locations, so such assumptions are unworkable.

Note that example here involves init sections, but the
issue exists for other sections (e.g. fini), including some
that the linker may not even know about.

A good solution to this problem would be to make -z rescan
positional, taking effect at the point where the link editor
encounters it instead of waiting until all arguments have been
processed. This would work, assuming that the -z rescan follows
the archives needing rescanning. Unfortunately, there are existing
makefiles in the field that have been written knowing that the
position of -z rescan is unimportant. Changing this aspect of -z rescan
would break any existing makefiles where the -z rescan precedes
the archives, as in the example I gave above. Had the interaction
with init sections been noted when -z rescan was first defined,
making it positional would have been the likely answer. However,
it is too late to change that now.

Since -z rescan cannot be changed, the solution to the problem
outlined about  is to introduce a new option, -z rescan-now,
and to change the ld(1) manpage to indicate that -z rescan is
deprecated, and that -z rescan-now should be used instead.


Archive Rescan Groups
---------------------
The GNU linker supports the notion of archive rescan groups:

        gld ... --start-group ... --end-group ...

or using an alternative syntax

        gld ... -( ... -) ...

When the link editor encounters the closing delimiter of
such a group, it immediately initiates an archive rescan
operation that considers only archives found inside
the group.

To lower the barrier to Solaris encountered by code written
outside Sun, and because it is a simple extension to the
rescan code already being modified, I am taking this
opportunity to add support for archive rescan groups to
the Solaris link-editor. The native names of these options
are -z rescan-start, and -z rescan-end. The GNU ld names
described above will also be accepted, following the
precedent set by "PSARC 2008/583 add gld options to ld(1)".

Reply via email to