bholanath
bholanath

Reputation: 1753

Unable to access own custom global function of shared library in linux from other module in C

I have downloaded libgcrypt library source code and added my own customize function inside one particular file.

Although compilation/build process of customized shared library is successful, and both nm and objdump show the customized function is global, it nonetheless shows an error (undefined reference) at linking time.

Here is what I have done:

inside /src/visibility.c file, I have added my custom function,

void __attribute__((visibility("default"))) MyFunction(void)
{
    printf("This is added just for testing purpose");   
}

build process

./configure --prefix=/usr/local --disable-ld-version-script

sudo make install

nm and objdump command find this custom function as global inside shared library.

nm /usr/local/lib/libgcrypt.so | grep MyFunction
000000000000fbf0 T MyFunction


objdump -t /usr/local/lib/libgcrypt.so | grep MyFunction
000000000000fbf0 g     F .text  0000000000000013              MyFunction

Here is my sample code to access my custom function.

//gcrypt_example_test.c
#include <stdio.h>
#include <gcrypt.h>
#include <assert.h>

int main()
{
    MyFunction();
    return 0;
}


export LD_RUN_PATH=/usr/local/lib
gcc gcrypt_example_test.c -o test -lgcrypt

/tmp/ccA0qgAB.o: In function `main': gcrypt_example_test.c:(.text+0x3a2): undefined reference to `MyFunction' collect2: error: ld returned 1 exit status

Edit 1:

I tried all possible way to include function prototype declaration inside header file (/src/gcrypt.h) as follows:

   void __attribute__((visibility("default"))) MyFunction(void);   

... or:

    extern void __attribute__((visibility("default"))) MyFunction(void);  

... or:

    extern void   MyFunction(void);

... or:

    void   MyFunction(void);

I am still getting the same error (undefined reference) although no build error results in all above cases.

Why is this happening, and what mistake am I making?

Although other global functions which are part of standard shared library and defined inside visibility.c (nm also shows T for those functions) are accessible, why is my customized global function (MyFunction) of the shared library still inaccessible? Thanks!

Any link or explanation to resolve this error will be highly appreciable.

Upvotes: 4

Views: 641

Answers (4)

bholanath
bholanath

Reputation: 1753

I don't understand the reason behind why it is working now, but not before. Anyway, I found the way to make the code working after adding customized function inside standard library. This post may help others in future.

I first locate libgcrypt.so and then remove all versions of libgcrypt.so

locate libgcrypt.so


sudo rm /usr/local/lib/libgcrypt.so 
sudo rm /usr/local/lib/libgcrypt.so.20 
sudo rm /usr/local/lib/libgcrypt.so.20.2.2

then I delete the libgcrypt folder (which I had extracted for building library) to start fresh.

Again, I follow these steps

Step 0 : extract libgcrypt source code

Step 1 : add my custom function, inside /src/visibility.c file

void __attribute__((visibility("default"))) MyFunction(void)
{
    printf("This is added just for testing purpose");   
}

Step 2 : build library

export LD_RUN_PATH=/usr/local/lib
./configure --prefix=/usr/local --disable-ld-version-script
sudo make install

Step 3: Open another terminal to compile

export LD_RUN_PATH=/usr/local/lib
gcc gcrypt_example_test.c -o test -lgcrypt

Step 4 : run

./test
This is added just for testing purpose

This is working fine now as expected.

What I noticed that __attribute__((visibility("default"))) in function definition and --disable-ld-version-script during build process is very important to make the customized function global, elimination of any makes the customized function local inside shared library(.so) file.

Upvotes: 1

Andrew Henle
Andrew Henle

Reputation: 1

From the GCC documentation (emphasis mine):

Some linkers allow you to specify the path to the library by setting LD_RUN_PATH in your environment when linking.

But, from the GNU ld man page:

   -rpath=dir
       Add a directory to the runtime library search path.  This is used
       when linking an ELF executable with shared objects.  All -rpath
       arguments are concatenated and passed to the runtime linker,
       which uses them to locate shared objects at runtime.  The -rpath
       option is also used when locating shared objects which are needed
       by shared objects explicitly included in the link; see the
       description of the -rpath-link option.  If -rpath is not used
       when linking an ELF executable, the contents of the environment
       variable "LD_RUN_PATH" will be used if it is defined.

Note that there is no mention at all of the link time library search path.

You need to compile/link with /usr/local/lib in the link time library search path:

gcc gcrypt_example_test.c -o test -L/usr/local/lib -lgcrypt

Upvotes: 4

anupkholgade
anupkholgade

Reputation: 26

Below changes are working at my end

visibility.h

#include <cstdio>

void __attribute__((visibility("default"))) MyFunction(void);

visibility.cpp

#include "visibility.h"


void MyFunction(void)
{
    printf("This is added just for testing purpose");
}

library build command

gcc -shared -o libtest.so -Wall -Werror -fpic -I. visibility.cpp

test.cpp

#include <stdio.h>
#include <gcrypt.h>
#include <assert.h>
#include "visibility.h"

extern void MyFunction();

int main()
{
  MyFunction();
  return 0;
}

exe build command

gcc test.cpp -o test -I. -L. -ltest -lstdc++

My gcc version is 4.4.7

And of-course I did not try and install the lib under /usr/local/lib but kept it local for quick testing.

Upvotes: 0

user3629249
user3629249

Reputation: 16540

most likely cause of the problem:

The header file for the library has not been updated to include the prototype for the new function

Upvotes: 1

Related Questions