This Question is Answered

1 "helpful" answer available (2 pts)
7 Replies Last post: Jun 24, 2009 8:45 AM by Bill_Oliver  
Click to view Bill_Oliver's profile   3 posts since
Jun 19, 2009

Jun 19, 2009 3:09 PM

$ORIGIN feature for C++ linking on AIX power?

Hello everyone!

I have an C++ application that uses a shared object. I would like to be able to build my program and then run it from another directory. Fine so far. My problem, is that I don't know where the shared library and executable will be installed - my software is provided to another group.

I think that typically the shared object would be installed at /usr/local/lib, or some application-specific path, like /opt/foo1/lib. But in my case, the shared object is side-by-side with the executable. Another group uses our objects and may choose to deploy this in a different directory.

Really, what I want is the $ORIGIN feature that is available on ELF systems. I suppose there is some way to do this with XCOFF, but I can't figure it out.

Here is an example to show the problem - the source files are taken form the "AIX Linking and Loading" guide. Assume 2 libraries (share1.c share2.c) and one executable (main.c)

bb04wrk31:/u/bioliv> cat share1.c
/************
  • share1.c: shared library source.
*************/
#include <stdio.h>
void func1 (){
printf("func1 called\n");
}
void func2 (){
printf("func2 called\n");
}

bb04wrk31:/u/bioliv> cat share2.c
/************
  • share2.c: shared library source.
*************/
void func3 (){
printf("func3 called\n");
}

bb04wrk31:/u/bioliv>
bb04wrk31:/u/bioliv>
bb04wrk31:/u/bioliv> cat main.c
#include <stdio.h>
extern void func1 (),
func2 (),
func3 ();
main (){
func1 ();
func2 ();
func3 ();
}

Build the shared libaries...

bb04wrk31:/u/bioliv> xlC -G -q64 share2.c -o share2.so
bb04wrk31:/u/bioliv> xlC -G -q64 share1.c -o share1.so

Build the main executable...
bb04wrk31:/u/bioliv> xlC -q64 main.c -o main share1.so share2.so

Works fine from current directory...
bb04wrk31:/u/bioliv> ./main
func1 called
func2 called
func3 called

Does not work when called from another directory...
bb04wrk31:/u/bioliv> mkdir foodir
bb04wrk31:/u/bioliv> cd foodir
bb04wrk31:/u/bioliv/foodir> ../main
Could not load program ../main:
Dependent module share1.so could not be loaded.
Could not load module share1.so.
System error: No such file or directory


Here is why...
bb04wrk31:/u/bioliv/foodir> ldd ../main
../main needs:
/usr/lib/libc.a(shr_64.o)
/usr/vacpp/lib/libC.a(shr_64.o)
/usr/vacpp/lib/libC.a(ansi_64.o)
Cannot find share1.so
Cannot find share2.so
/unix
/usr/lib/libcrypt.a(shr_64.o)
/usr/vacpp/lib/libC.a(ansicore_64.o)
/usr/vacpp/lib/libC.a(shrcore_64.o)
/usr/vacpp/lib/libC.a(shr3_64.o)
/usr/vacpp/lib/libC.a(shr2_64.o)
bb04wrk31:/u/bioliv/foodir> dump -H -X64 ../main

../main:

***Loader Section***
Loader Header Information
VERSION# #SYMtableENT #RELOCent LENidSTR
0x00000001 0x00000010 0x00000027 0x00000078

#IMPfilID OFFidSTR LENstrTBL OFFstrTBL
0x00000006 0x00000428 0x000000ee 0x000004a0

***Import File Strings***
INDEX PATH BASE MEMBER
0 /usr/vac/lib:/usr/vacpp/lib:/usr/lib:/lib
1 libc.a shr_64.o
2 libC.a shr_64.o
3 libC.a ansi_64.o
4 share1.so
5 share2.so

If I knew where the application would be deployed, I could write the install directory into the executable, using -blibpath, like this:

bb04wrk31:/u/bioliv> xlC -q64 main.c -o main share1.so share2.so -blibpath:/u/bioliv/:/usr/local/lib:/usr/lib:/lib
bb04wrk31:/u/bioliv> cd foodir
bb04wrk31:/u/bioliv/foodir> ../main
func1 called
func2 called
func3 called
bb04wrk31:/u/bioliv/foodir> !dump
dump -H -X64 ../main

../main:

***Loader Section***
Loader Header Information
VERSION# #SYMtableENT #RELOCent LENidSTR
0x00000001 0x00000010 0x00000027 0x00000076

#IMPfilID OFFidSTR LENstrTBL OFFstrTBL
0x00000006 0x00000428 0x000000ee 0x0000049e

***Import File Strings***
INDEX PATH BASE MEMBER
0 /u/bioliv/:/usr/local/lib:/usr/lib:/lib
1 libc.a shr_64.o
2 libC.a shr_64.o
3 libC.a ansi_64.o
4 share1.so
5 share2.so


I could also fix this at run-time using $LIBPATH, but that is not what I want. :-(

Really, what I want is something like this:

bb04wrk31:/u/bioliv> xlC -q64 main.c -o main share1.so share2.so -blibpath:\$ORIGIN:/usr/local/lib:/usr/lib:/lib

But that doesn't seem to work.

Help!

-bill

Click to view vijayka's profile   6 posts since
Jul 14, 2008

Have you looked at the possibility of using LD_LIBRARY_PATH environment variable that users of your shared objects may use to find the shared lib?

Vijay

Click to view cntaylor's profile   1 posts since
Jun 22, 2009

Hi Bill,

You have a few choices.

If you know the exact path that your shared libraries will be in while you're building your application, then you're on the right track with the -blibpath compiler option. Just remember that the search path you provide is taken literally (with no variable expansion).

If you're not sure where your shared libraries will be until runtime, you're also on the right track with LIBPATH. If you would rather not have your users specify this themselves, you could write a shell script to set this just prior to running your application.

For example, if your program, main, ends up getting installed to the directory, /opt/bill/, you could use the following shell script.
#!/bin/sh
export LIBPATH=/opt/bill/:$LIBPATH
exec /opt/bill/main "$@"

If your shared libraries end up getting installed to a different path (e.g. /opt/bill/lib) just replace the /opt/bill in the LIBPATH and you should be set.

#!/bin/sh
export LIBPATH=/opt/bill/lib:$LIBPATH
exec /opt/bill/main "$@"

Now if you really, really want to use your own environment variable (say, $ORIGIN) and have your users specify it, just replace the /opt/bill in your LIBPATH with $ORIGIN.

#!/bin/sh
export LIBPATH=$ORIGIN:$LIBPATH
exec /opt/bill/main "$@"

Hope this helps,


  • chris
Click to view Michael_Wong's profile   19 posts since
Sep 30, 2008
4. Jun 23, 2009 8:47 AM in response to: cntaylor
Re: $ORIGIN feature for C++ linking on AIX power?
I think this last answer is the only possible way and is the best answer. That is using a wrapper as Chris suggested:
#!/bin/sh
export LIBPATH=$ORIGIN:$LIBPATH
exec /opt/bill/main "$@"

I spoke with the AIX OS folks, and they tell me there is no facility for a runtime interpreted macro in the linker's -blibpath, i.e. there's no way to get exec to read a user-named environment variable.

Click to view jtk@us.ibm.com's profile   1 posts since
Jun 22, 2009
5. Jun 23, 2009 10:48 AM in response to: Michael_Wong
Re: $ORIGIN feature for C++ linking on AIX power?

Too bad there's no $ORIGIN like Solaris. It makes some use cases a lot easier, such as a .so intended to be dynamically loaded into some other process. If one doesn't have control over how that process starts, one can't ensure LD_LIBRARY_PATH/LIBPATH is set effectively.

Also for setuid/setgid programs, there are security issues with LD_LIBRARY_PATH/LIBPATH that the system enforces, such that the search path may be ignored. $ORIGIN has similar problems, though, so there's no perfect solution here.


Click to view Michael_Wong's profile   19 posts since
Sep 30, 2008
Yes, I agree that all the libpath type environment setting are really hacks anyway for temporarily testing a shared library.

Proposing something like this as a feature for the AIX OS is a good thought, especially if will help the Solaris folks move to AIX.
Bottom Banner