Author Topic: Shared Library and rpath  (Read 12731 times)

Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Shared Library and rpath
« on: July 30, 2010, 06:16:56 pm »

Hello,

If I may, I would like to ask for some input regarding the usage of rpath and CodeBlocks.

I have gone through all the rpath related posts on the C::B forum and many other locations via Google (stackoverflow, etc).

I found much information but I am still having issues using rpath in my project build options. I am posting to this support forum after 1.5 days of not figuring this out.  :(


Summary:
rpath can be used as a linker option. It is used to add additional search paths to a binary executable. In my case, I need to have my main console app and the shared lib in the same directory regardless of my build directory structure.

Some Specifics:
I have an executable “driver program” and shared lib (both for Linux and Mac OS X). The shared lib is built to a common directory. The main console app then links to the shared *.so lib. The main executable binary image is also output to the common directory that holds the shared lib.

I want to be able to run the main console app within the C::B/debugger IDE and also from a console window using the command line. I am developing on Ubuntu 9.10 and Mac OS X 10.6.3.

On Ubuntu, I am using:
 g++  (4.4.1)
ld (2.20)

On Mac OS X 10.6.3:
 g++  (4.2.1)
ld (ld64-97.2)


I have tried many variants of using rpath in my C::B build options but I am at a loss why I can't seem to get this to work.

Thank you in advance for any assistance. Code blocks is great!


Thank you,

edwin


Offline jens

  • Administrator
  • Lives here!
  • *****
  • Posts: 7265
    • Jens' unofficial debian-repository for the Code::Blocks - IDE
Re: Shared Library and rpath
« Reply #1 on: July 30, 2010, 08:47:34 pm »
Add
Code: [Select]
-Wl,-rpath=. to the "Other linker settings:" in the targets (or projects) "Linker settings".

Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #2 on: July 30, 2010, 09:45:41 pm »
Thank you jens. I will try it out immediately on Linux and Mac and report back.

Super!!! :)


Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #3 on: August 11, 2010, 05:26:42 pm »
Hello jens,

Please excuse the delay of this post… I got side tracked with another task. Grrrr….


I must be doing something really dumb for I still can’t get this to work. :(

I understand your last post and updated my build project for the main executable “driver” app as you stated.

I am focusing on the Linux debug build of my code at the moment. I am testing the build by running the main executable under the debugger using the C::B IDE. The build of the main executable and my shared lib complete with no errors or warnings. When I attempt to start the debug build of the main executable by pressing F8, the debugger log in C::B generates the gdb message:

Program exited with code 0177.

…and the main executable fails to start.

My main executable and shared library are all built to the same target directory and C::B is set up to have the “execution working dir” set to the exact same dir of those binary images.

Also, I tried different combinations of how to specify the main executable links to the shared lib. I used a complete relative path to the shared lib for one of my tests. This build completed – no errors but running the main app in the IDE under the debugger or in a console window fails (cannot open shared object file: No such file or directory).

Then I use just the name of the shared lib while also specifying a separate “linker search path”. In this case, the build fails because for some reason the shared lib cannot be found during the build process.

Hmmm…. strange.

If you or anyone else could assist me further, I would be very grateful. I can post any other information you think will help.

I am using C::B SVN 6336 I built myself.



Thank you,

edwin


Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #4 on: August 11, 2010, 06:33:02 pm »
One other piece of information:

The main executable is called: PortingLayerTest
The shared lib is called: TestDll.so


When I execute this command from the shell:

readelf -d PortingLayerTest

I get this:

--------------------------------------------------------------------
Dynamic section at offset 0x4dee0 contains 29 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [bin/DebugLinux32/TestDll.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [.]
 0x0000000c (INIT)                       0x804ab1c
 0x0000000d (FINI)                       0x807df9c
 0x00000004 (HASH)                       0x80481ac
 0x6ffffef5 (GNU_HASH)                   0x804880c
 0x00000005 (STRTAB)                     0x80495fc
 0x00000006 (SYMTAB)                     0x80488ec
 0x0000000a (STRSZ)                      3051 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8095ff4
 0x00000002 (PLTRELSZ)                   1472 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x804a55c
 0x00000011 (REL)                        0x804a52c
 0x00000012 (RELSZ)                      48 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x804a38c
 0x6fffffff (VERNEEDNUM)                 7
 0x6ffffff0 (VERSYM)                     0x804a1e8
 0x00000000 (NULL)                       0x0
--------------------------------------------------------------------

I can see the rpath entry as I would expect.

It looks like the “bin/DebugLinux32/TestDll.so” entry is the issue. Looks like it should not have the relative path specified and simply be “TestDll.so”.

Yes???


Thank you,

edwin


Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 12126
    • Travis build status
Re: Shared Library and rpath
« Reply #5 on: August 11, 2010, 06:37:08 pm »
The configuration you've described should work without the rpath settings, remove it and report what have happened.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #6 on: August 11, 2010, 08:17:18 pm »

Hi oBFusCATed,

I removed rpath from the build and this is the result I get when I then run readelf:

Executed command:
readelf -d PortingLayerTest


Result:
Dynamic section at offset 0x4dee8 contains 28 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [bin/DebugLinux32/TestDll.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x804ab18
 0x0000000d (FINI)                       0x807df9c
 0x00000004 (HASH)                       0x80481ac
 0x6ffffef5 (GNU_HASH)                   0x804880c
 0x00000005 (STRTAB)                     0x80495fc
 0x00000006 (SYMTAB)                     0x80488ec
 0x0000000a (STRSZ)                      3049 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8095ff4
 0x00000002 (PLTRELSZ)                   1472 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x804a558
 0x00000011 (REL)                        0x804a528
 0x00000012 (RELSZ)                      48 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x804a388
 0x6fffffff (VERNEEDNUM)                 7
 0x6ffffff0 (VERSYM)                     0x804a1e6
 0x00000000 (NULL)                       0x0

Again, the “PortingLayerTest” executable and the “TestDll.so” shared lib are in the same dir. When I run the PortingLayerTest executable in a command window, I get:

./PortingLayerTest: error while loading shared libraries: bin/DebugLinux32/TestDll.so: cannot open shared object file: No such file or directory.

I would think that if I could rebuild the test app so that:

0x00000001 (NEEDED)                     Shared library: [bin/DebugLinux32/TestDll.so]

looks like this:

0x00000001 (NEEDED)                     Shared library: [TestDll.so]

…all would be OK.

I can’t believe I am not getting this…. hoping you can help.

edwin



Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 12126
    • Travis build status
Re: Shared Library and rpath
« Reply #7 on: August 11, 2010, 08:44:38 pm »
Again, the “PortingLayerTest” executable and the “TestDll.so” shared lib are in the same dir. When I run the PortingLayerTest executable in a command window, I get:

./PortingLayerTest: error while loading shared libraries: bin/DebugLinux32/TestDll.so: cannot open shared object file: No such file or directory.
On linux (and other unixes I suppose) the current directory is not added to the search path for executable and libraries. This is done for security reasons.
Try "export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:." && ./yourApp"
Also does your app run from inside C::B. Build -> Run or Debug->Start, both should work, they work for me.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline jens

  • Administrator
  • Lives here!
  • *****
  • Posts: 7265
    • Jens' unofficial debian-repository for the Code::Blocks - IDE
Re: Shared Library and rpath
« Reply #8 on: August 11, 2010, 09:00:28 pm »
How do you add your library ?
With full path or just as TestDll ?

Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #9 on: August 11, 2010, 09:35:43 pm »
Thanks for your response oBFusCATed.

Quote
On linux (and other unixes I suppose) the current directory is not added to the search path for executable and libraries.
This I did not realize! Thanks for telling me this.

I will try your LD_LIBRARY_PATH suggestion and see what occurs. What I was hoping to accomplish was to encode only the name of the shared lib into the exe and hope everything works out – and not have to do anything with environment vars.


I performed another test since my last post. I did the following:

1)
Copied the Debug shared lib image from the common output directory to the main EXE’s project directory.

2)
In the exe’s project settings, I configured the debug build to link to the “./TestDll.so” copy of the shared library.

2)
Rebuilt the Debug exe image.

3)
Checked the “dynamic section” dump info using readelf. This is what I received:

Dynamic section at offset 0x4dee8 contains 28 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
0x00000001 (NEEDED)                     Shared library: [./TestDll.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x804ab08
 0x0000000d (FINI)                       0x807df8c
 0x00000004 (HASH)                       0x80481ac
 0x6ffffef5 (GNU_HASH)                   0x804880c
 0x00000005 (STRTAB)                     0x80495fc
 0x00000006 (SYMTAB)                     0x80488ec
 0x0000000a (STRSZ)                      3034 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8095ff4
 0x00000002 (PLTRELSZ)                   1472 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x804a548
 0x00000011 (REL)                        0x804a518
 0x00000012 (RELSZ)                      48 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x804a378
 0x6fffffff (VERNEEDNUM)                 7
 0x6ffffff0 (VERSYM)                     0x804a1d6
 0x00000000 (NULL)                       0x0



Notice now the line:

0x00000001 (NEEDED)                     Shared library: [./TestDll.so]

Which does force the loader to look in the same dir as the EXE for the shared lib.

When I execute the main EXE program (I typed ./PortingLayerTest at the shell), it runs as expected and uses the shared lib in the exe’s dir.

Also, the exe built this way can be executed from the IDE and debugged from the IDE.

At this point, I get the behavior I was looking for but I don’t like the fact that I have to link to a copy of the shared lib in the EXE’s project dir.


Question:
Can I get this same effect somehow without having to copy over the shared lib to the EXE’s projectd dir and linking to that temp lib image?

I have been trying to get the same result as above using “link search path” build settings instead of copying the shared lib but I have failed up to this point. For some reason, specifying a shared lib linker search path causes the link phase to fail (not find the shared lib).

Any further thoughts you have are appreciated.

Thank you,

edwin

Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #10 on: August 11, 2010, 09:36:55 pm »

Hi jens,

Thanks also for your post + help.

Yes - I also tried using just the name of the shared lib in the “Link libraries” project setting (TestDll.so) AND setting the relative path to the shared lib in the ‘Search directories” linker tab.

I was hoping that once I built, I would see the following line using the readelf utility:

0x00000001 (NEEDED)                     Shared library: [TestDll.so]

I though this would have accomplished what I wanted but it did not. For some reason the linker did not use the lib search path and the build failed because the link phase could not find the shared lib – even though the linker search path appeared on the link command line (g++ -L option). Hmm…..


edwin


Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #11 on: August 11, 2010, 11:12:53 pm »
Hello,

I performed a few other tests and finally got the results I needed.

I added the rpath statement to my build:

Code: [Select]
-Wl,-rpath=.

Then I rebuilt the Debug image of my shared lib and the EXE (they are in the same C::B workspace). I linked to the shared lib as normal and not to a copy of the shared lib as I mention in a previous post. I linked to the shared lib using a relative path.

Using the command “readelf -d PortingLayerTest” at a shell, I received:
 
Dynamic section at offset 0x4dee0 contains 29 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
0x00000001 (NEEDED)                     Shared library: [bin/DebugLinux32/TestDll.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [.]
 0x0000000c (INIT)                       0x804ab1c
 0x0000000d (FINI)                       0x807df9c
 0x00000004 (HASH)                       0x80481ac
 0x6ffffef5 (GNU_HASH)                   0x804880c
 0x00000005 (STRTAB)                     0x80495fc
 0x00000006 (SYMTAB)                     0x80488ec
 0x0000000a (STRSZ)                      3051 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8095ff4
 0x00000002 (PLTRELSZ)                   1472 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x804a55c
 0x00000011 (REL)                        0x804a52c
 0x00000012 (RELSZ)                      48 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x804a38c
 0x6fffffff (VERNEEDNUM)                 7
 0x6ffffff0 (VERSYM)                     0x804a1e8
 0x00000000 (NULL)                       0x0

Where the path of the TestDll.so is not what I want.

I then took a hex editor and changed the executable file so the path to the shared lib is gone:

Dynamic section at offset 0x4dee0 contains 29 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
0x00000001 (NEEDED)                     Shared library: [TestDll.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [.]
 0x0000000c (INIT)                       0x804ab1c
 0x0000000d (FINI)                       0x807df9c
 0x00000004 (HASH)                       0x80481ac
 0x6ffffef5 (GNU_HASH)                   0x804880c
 0x00000005 (STRTAB)                     0x80495fc
 0x00000006 (SYMTAB)                     0x80488ec
 0x0000000a (STRSZ)                      3051 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8095ff4
 0x00000002 (PLTRELSZ)                   1472 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x804a55c
 0x00000011 (REL)                        0x804a52c
 0x00000012 (RELSZ)                      48 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x804a38c
 0x6fffffff (VERNEEDNUM)                 7
 0x6ffffff0 (VERSYM)                     0x804a1e8
 0x00000000 (NULL)                       0x0

Executing this from the shell, running it from the IDE and debugging it from the IDE all work.

Now the question is:
How can I get the C::B build process to only put the name of the shared lib in the “Dynamic section” of the EXE without using a relative path?

Thank you,

edwin



Offline jens

  • Administrator
  • Lives here!
  • *****
  • Posts: 7265
    • Jens' unofficial debian-repository for the Code::Blocks - IDE
Re: Shared Library and rpath
« Reply #12 on: August 11, 2010, 11:24:37 pm »
1. name the output-filename of your lib libTestDll.so,
2. copy it to the executables output directory (either in the libs post-build or in the exe's pre-build step, I would prefer the second),
3. add the output directory of the exe to the exe's linker search path,
4. add TestDll (without the lib and the .so) to the exe's link-libraries,
5. add -Wl,-rpath=. to the exe's linker settings

Now it should work from console, if you are in the folder where the files are, and with doubleclick from filemanager (if your exe is a gui-project).

Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #13 on: August 12, 2010, 12:32:41 am »
Hi jens,

Thank you for your information.

I know exactly what you are saying. I completely agree with everything you said in your last post.

Here is what I have:

1)
I changed the shared lib project to generate libTestDll.so

2)
I do not have to copy the libTestDll.so image to the EXEs output dir because the output dir the shared lib uses is the EXE’s output dir. When I build the shared lib, it gets built to the EXE’s output dir.

3)
Yes, I already had added the EXE output dir to the EXE’s linker search path.

4)
OK, this I changed. I had previously specified “TestDll.so”.

5)
Yes, this was previously configured.


Result:

Dynamic section at offset 0x3bee0 contains 29 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
0x00000001 (NEEDED)                     Shared library: [libTestDll.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
0x0000000f (RPATH)                      Library rpath: [.]
 0x0000000c (INIT)                       0x804a9ac
 0x0000000d (FINI)                       0x807366c
 0x00000004 (HASH)                       0x80481ac
 0x6ffffef5 (GNU_HASH)                   0x80487e0
 0x00000005 (STRTAB)                     0x8049520
 0x00000006 (SYMTAB)                     0x80488c0
 0x0000000a (STRSZ)                      3013 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8084ff4
 0x00000002 (PLTRELSZ)                   1384 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x804a444
 0x00000011 (REL)                        0x804a414
 0x00000012 (RELSZ)                      48 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x804a274
 0x6fffffff (VERNEEDNUM)                 7
 0x6ffffff0 (VERSYM)                     0x804a0e6
 0x00000000 (NULL)                       0x0

.. which looks good.

The EXE and shared lib runs as expected in the shell, from within the IDE and while debugging in the IDE.

Thank you very much!


Question 1:
How come the compiler/linker tool chain require a shared lib to be prefixed with “lib”?

I tried for a long time to use a linker search path and the name of the shared lib (like TestDll.so) and for everything I tried, the link phase would always fail because ld could not find the shared lib. I know this is a Linux naming convention but would it not make sence to be able to specify a literal shared lib name and still have the build succeed? I knew it had to be something simple.


Question 2:
I have to test this build on Mac Snow leopard 10.6.4. Do you think the same changes to the project file will have to be made? I would think yes.

I have beating my head - you made my day.   :)

Now I can finally get back to work…


Thank you,


edwin



Offline edwin

  • Multiple posting newcomer
  • *
  • Posts: 38
Re: Shared Library and rpath
« Reply #14 on: August 12, 2010, 12:45:30 am »
Forum Moderator:

I was testing my sig. Delete this if you want.

edwin