-R$ORIGIN and -z origin

-R$ORIGIN and -z origin

Post by Drazen Kac » Mon, 29 May 2000 04:00:00



I've looked at the Linker and Libraries Guide and ld and ld.so.1 man pages,
but there are a few things I don't understand. The platform is Solaris 7
and up.

Say I want to link libA.so which depends on libB.so like this (some
flags which are not relevant here omitted):

ld -G -o libA.so *.o -R$ORIGIN -z lazyload -lB -z nolazyload -lc

Both libA and libB are some general-purpose libraries, but applications
use libA as a wrapper and they never use libB directly. libA doesn't
invoke chdir(2). Some applications might do it prior to loading libB.

ld.so.1 man page says:

     LD_ORIGIN The immediate processing of $ORIGIN can be triggered by
               setting the environment variable LD_ORIGIN to any non-
               null value. This may be useful for applications that
               invoke chdir(2) prior to locating dependencies that
               employ the $ORIGIN string token.

I don't know how exactly is $ORIGIN handled by the run-time linker, but
the paragraph above implies it has to do something with the CWD of
the process in question. Which is kind of strange, since the binary
is usually not in the CWD when it's started, so I don't see why would
CWD be important. Except if it's only important in case when the binary
really is in the CWD (because of auxv handling).

Questions:
1. what does ld.so.1 do when it encounters $ORIGIN?
2. what exactly happens if the application invokes chdir(2) prior to
   $ORIGIN processing?
3. Does it affect my libraries and should I use -z origin when linking libA?
4. Are there any performance penalties associated with the use of -zorigin?
5. If the answer to the previous question is no, why is -zorigin an option?
   Is there any "creative" use of chdir(2) and $ORIGIN?

--
 .-.   .-.    I don't work for my employer.
(_  \ /  _)


 
 
 

-R$ORIGIN and -z origin

Post by Casper H.S. Dik - Network Security Engine » Tue, 30 May 2000 04:00:00


[[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


>I don't know how exactly is $ORIGIN handled by the run-time linker, but
>the paragraph above implies it has to do something with the CWD of
>the process in question. Which is kind of strange, since the binary
>is usually not in the CWD when it's started, so I don't see why would
>CWD be important. Except if it's only important in case when the binary
>really is in the CWD (because of auxv handling).

It has meaning when the program is invoked using a relative pathname.

Quote:>Questions:
>1. what does ld.so.1 do when it encounters $ORIGIN?

    It will replace $ORIGIN with the pathname where it found the object
    that specified $ORIGIN (not sure if it will be relative to the
    main executable or relative to the library in your case)

Quote:>2. what exactly happens if the application invokes chdir(2) prior to
>   $ORIGIN processing?

        Usually, it doesn't have any influence.

Quote:>3. Does it affect my libraries and should I use -z origin when linking libA?

Most likely, it will have no effect.

Quote:>4. Are there any performance penalties associated with the use of -zorigin?

    ??

Quote:>5. If the answer to the previous question is no, why is -zorigin an option?
>   Is there any "creative" use of chdir(2) and $ORIGIN?

it's no longer necessary in the next release.

Casper
--
Expressed in this posting are my opinions.  They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

 
 
 

-R$ORIGIN and -z origin

Post by Drazen Kac » Wed, 31 May 2000 04:00:00




> >Questions:
> >1. what does ld.so.1 do when it encounters $ORIGIN?

>     It will replace $ORIGIN with the pathname where it found the object
>     that specified $ORIGIN (not sure if it will be relative to the
>     main executable or relative to the library in your case)

Relative to the library; `ldd -s' shows it nicely. However, -zlazyload
seems to work only for the main executable. If a.out depends on libA (lazy
or not) and libA depends on libB (lazy) then both libA and libB will be
loaded (when the process encounters the first function from libA, even if
that function doesn't need anything from libB; this in case libA was
linked with -zlazyload).

That's bad. It means that if I want to take advantage of lazy loading, I have
to link the main executable with libB (lazy) and I must not link libA with
libB. And thus the main executable becomes dependant on the implementation
of libA, which should be private to libA and not exposed to the main
executable. And libA will not be self contained. Bad, bad, bad.

Is it actually impossible to implement lazy loading for shared libraries or
it has just not been done yet?

Quote:> >4. Are there any performance penalties associated with the use of -zorigin?

>     ??

/dev/mindreading malfunction detected... :-)

The main advantage of lazy loading is the faster start-up. And the main
part of that is elimination of disk accesses. Now, if -zorigin forces use
of something like getcwd(), that would actually result in slower start-up,
since getcwd() is terribly expensive in terms of disk accesses.

But it seems that getcwd() is used only when the executable is invoked
using relative path, which is good enough, because it doesn't happen
often.

--
 .-.   .-.    I don't work for my employer.
(_  \ /  _)


 
 
 

-R$ORIGIN and -z origin

Post by Rod Evan » Fri, 02 Jun 2000 04:00:00



> I don't know how exactly is $ORIGIN handled by the run-time linker, ...

There are many things at work here.  First, the kernel passes ld.so.1
the pathname of the executable that starts the process.  Typically,
because the shells prepend each element of PATH to the command being
executed, you get an exec() of a full pathname.  If however, you have
"." in your path, or explicitly execute a relative path (say ./foo),
then the relative name is passed to exec() and then onto ld.so.1.

If ld.so.1 is given a full path it can process any later $ORIGIN
expansion by using this path.  Otherwise it must determine the full
pathname.  Typically this is only relevant to the executable.
Dependencies are normally found by taking the needed
name, say libfoo.so.1, and prepending runpaths or default search paths,
hence they usually resolve to a full pathname as a process of loading them.

If the executable results in a relative path then we have to determine
the full path in case the current working directory is changed prior to
$ORIGIN expansion being required.  Probably not very typical, but you
could have a runpath with $ORIGIN that wasn't used until a dependency was
lazy loaded or dlopen'ed.

To get a full path, ld.so.1 performs a getcwd(), and although streamlined
compared to libc's version this is still a lot of work (getdents, stats etc.).
So, we defer any pathname expansion until the time we determine it needs
to be done (ie. when we first come across a $ORIGIN).  But, the application
may have changed directory before this expansion.  Thus the flags are there
to force relative path expansion up front.

So, if an application uses $ORIGIN, there will be a cost associated with
any relative path expansion.  Unless dependencies use relative paths there's
probably never going to be any cost in $ORIGIN use in a dependency.
As any applications runpaths are usually exhausted to find its immediate
dependencies (they'll even be used to find things like libc), the chances
of a change in the current working directory before this expansion occurs
is minimal (although you could try dlopen("$ORIGIN/lib/libfoo.so.1")  after
you've chdir()'d :-).

There is work in progress to make getcwd() have less overhead (use of
the new /etc/mnttab helps), and because of other requests that ld.so.1
provide full pathnames when tools attach to processes and use librtld_db,
the expansion of any relative pathname will probably become default, and
thus make -z origin and LD_ORIGIN obsolete.

Quote:> Relative to the library; `ldd -s' shows it nicely. However, -zlazyload
> seems to work only for the main executable. If a.out depends on libA (lazy
> or not) and libA depends on libB (lazy) then both libA and libB will be
> loaded (when the process encounters the first function from libA, even if
> that function doesn't need anything from libB; this in case libA was
> linked with -zlazyload).

> ...

> Is it actually impossible to implement lazy loading for shared libraries or
> it has just not been done yet?

You can lazyload anything .  Note that
lazy loading is triggered by relocations.  If libA references a data item
in libB, or if libA *hasn't* been built -Kpic, you'll have data references
to libB's functions rather than references that go through a .plt.  Data
relocations are carried out immediately when an object is loaded, thus any
lazy-loading of the dependency will occur immediately, making you think
that lazy-loading wasn't occurring.

You can see if lazy-loading is occurring with ldd much better in 2.8
(see -L option), or via ld.so.1's debugging (2.7 and up):

        % LD_DEBUG=files ld main.o
        ...
        10302: file=libelf.so.1;  lazy loaded; bindings \
                from file=`/usr/lib/libld.so.2' sym=`elf_version'
        ...

Rod.

 
 
 

-R$ORIGIN and -z origin

Post by Drazen Kac » Sat, 03 Jun 2000 04:00:00


[snip]

Quote:> So, if an application uses $ORIGIN, there will be a cost associated with
> any relative path expansion.  Unless dependencies use relative paths there's
> probably never going to be any cost in $ORIGIN use in a dependency.

I'm not sure I understand the last sentence. Relative paths, as used in the
snipped text, refer to relative file system paths, as in `./a.out'.
Runpaths are referred to as runpaths. $ORIGIN use in runpath is
clearly a relative path of some kind. Now, "unless dependencies use relative
paths", could only refer to something like dlopen("../lib/libfoo.so.1")
(and then libfoo needs libbar.so.1 and has $ORIGIN in its runpath),
but the sentence doesn't refer to dependencies which were given to ld(1)
at link time. Or did I miss something?

Quote:> > Is it actually impossible to implement lazy loading for shared libraries or
> > it has just not been done yet?

> You can lazyload anything .  Note that
> lazy loading is triggered by relocations.  If libA references a data item
> in libB, or if libA *hasn't* been built -Kpic,

Yes! Thanks. In my defense, I can only say that I had a fever and couldn't
think straight. I could have sworn I've seen it working fine earlier, but
I wasn't able to find out what was wrong with the simple test.

And I kind of remember there was some text about it in the Answerbook
in the section about relocations, but not at the places which talk
about lazy loading.

Life is beautiful, fever is gone, ld rocks, /me is going to link a lot of
things tomorrow. :-)

--
 .-.   .-.    I don't work for my employer.
(_  \ /  _)


 
 
 

-R$ORIGIN and -z origin

Post by Rod Evan » Tue, 06 Jun 2000 04:00:00



> > So, if an application uses $ORIGIN, there will be a cost associated with
> > any relative path expansion.  Unless dependencies use relative paths there's
> > probably never going to be any cost in $ORIGIN use in a dependency.

> I'm not sure I understand the last sentence. Relative paths, as used in the
> snipped text, refer to relative file system paths, as in `./a.out'.
> Runpaths are referred to as runpaths. $ORIGIN use in runpath is
> clearly a relative path of some kind. Now, "unless dependencies use relative
> paths", could only refer to something like dlopen("../lib/libfoo.so.1")
> (and then libfoo needs libbar.so.1 and has $ORIGIN in its runpath),
> but the sentence doesn't refer to dependencies which were given to ld(1)
> at link time. Or did I miss something?

I've seen this:

        % cc -o libbar.so -h ../../lib/libbar.so $(OBJS) ...

Thus if you link against this library you'll get a relative dependency:

        % cc -o libfoo.so $(OBJS) -L. -lbar
        % elfdump -d libfoo.so | fgrep NEEDED
               [0]  NEEDED        0xc1              ../../lib/libbar.so

Not very common I'd agree, but its amazing what folks come up with.

Quote:> Life is beautiful, fever is gone, ld rocks ....

If only all our users felt this way :-)

--

Rod.

 
 
 

1. origins of Motif/Unix-Haters FUD (was Re: Microsoft anti-UNIX/Linux)


Navindra> "A stated design goal of Motif was to give the X Window
Navindra> System the window management capabilities of HP's circa-1988
Navindra> window manager and the visual elegance of Microsoft
Navindra> Windows."
Navindra> --The Unix-Haters Handbook

Great, more b.s. from UHH.  The "visual elegance of Microsoft Windows"
should be the "visual elegance of OS/2's Presentation Manager".  Motif
is much prettier than circa 1988 Windows.  I'm beginning to believe
that UHH has an agenda like, say, criticizing anything that isn't a
Lisp machine using lies and half-truths.

From X Window System Programming (Nabajyoti Barkakati):

"OSF/Motif or Motif for short, is the common user interface style
selected by the Open Software Foundation (OSF).  The OSF was formed in
1988 by a group of major hardware bendors that includes IBM, DEC, and
Hewlett Packard.  OSF/Motif us a combination of several things: an X
toolkit for developing applications, the Motif Window Manager (wmw),
and a style guide for developers.  The Motif Window Manager has a
three-dimensional look and was derived from work done by Hewlett
Packard and Microsoft.  The look and feel of Motif comes from
Microsoft's Presentation Manager, which, in turn, is derived from
Microsoft Windows.  This heritage of OSF/motif has eased its
acceptance among the large number of PC users who are familiar with
Microsoft Windows and Presentation Manager."

-Kevin

2. Domain not available as .www

3. before exec login after telnet possible know origin ip address ?

4. scomail and sendmail 8.6.12?

5. Changing origin in forwarded mails

6. acer cdrom

7. origin of signal

8. PPP with null modem cable

9. origin of Linux

10. slackware name origin

11. Equivalent of W95 Origin (Graphics) available?

12. IP origin info?

13. Origin 200 and Video Card