Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Reading Visibility in the GNU wiki, it is clear.

Taking this example from C++ Tutorials

// classes example
#include <iostream>
using namespace std;

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area() {return width*height;}
};

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

Is it possible to make area() public and set_values(int,int) local as shown in the first link without altering the code?

I wrote my makefile to get the .so

someproj.so : someproj.cpp
    g++ --std=c++11 -O3 -fPIC -shared someproj.cpp -o someproj.so

Modified to make all symbols hidden by adding -fvisibility=hidden

someproj.so : someproj.cpp
    g++ --std=c++11 -O3 -fvisibility=hidden -fPIC -shared someproj.cpp -o someproj.so

Is it possible to customized which functions are exposed by modifying the compilation command above?

Currently using 4.7.2 version of gcc

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
92 views
Welcome To Ask or Share your Answers For Others

1 Answer

Is it possible to customize which functions are exposed by modifying the compilation command above?

No. Compilation option -fvisibility=[default|internal|hidden|protected] (and note it is not a linkage option) makes the compiler attribute the specified dynamic visibility type to all global symbols generated in the compilation unit except those that are specifically excluded by having a countervailing __attribute__((visibility(....))) applied in the source code. Which makes the answer to your other question:

Is it possible to make area() public and set_values(int,int) local as shown in the first link without altering the code?

also No.

How would you change the source code to make Rectangle::area() dynamically visible while all other global symbols are hidden for dynamic linkage by -fvisibility=hidden? Here is a walk-through:

Let's start with:

rectangle.cpp (1)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area() {return width*height;}

};

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

and simply compile it to a PIC rectangle.o so:

$ g++ -Wall -c -fPIC rectangle.cpp

Then check the global symbol table:

$ nm -C rectangle.o
0000000000000000 T Rectangle::set_values(int, int)

Note that Rectangle::area isn't there. It's not available for linkage at all, so the question of its dynamic visibility just does not arise.

That is because it is defined inline in the class definition and never called in the compilation unit, so gcc need not even compile its definition. It vanishes from the object file.

Rectangle::set_values, on the other hand, is not defined inline, so the compiler emits a global symbol and definition.

To make Rectangle::area eligible for some visibility type, we first need to make it a global symbol by not defining it inline:

rectangle.cpp (2)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area();

};

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

Recompile and again check the global symbol table:

$ g++ -Wall -c -fPIC rectangle.cpp
$ nm -C rectangle.o
000000000000001a T Rectangle::set_values(int, int)
0000000000000000 T Rectangle::area()

Good. Now a global definition of Rectangle::area appears.

Next let's make a shared library librectangle.so from rectangle.o:

$ g++ -o librectangle.so --shared rectangle.o

Here are the Rectangle::* symbols in its global symbol table:

$ nm -C librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()

And here are the Rectangle::* symbols in its dynamic symbol table:

$ nm -CD librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()

They're the same.

Now let's hide those symbols for dynamic linkage. We need to recompile rectangle.cpp then relink the shared library:

$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o

Here again are the Rectangle::* symbols now in the global symbol table:

$ nm -C librectangle.so | grep 'Rectangle::'
0000000000000574 t Rectangle::set_values(int, int)
000000000000055a t Rectangle::area()

They're the same as before.

And here are the Rectangle::* symbols now in the dynamic symbol table:

$ nm -CD librectangle.so | grep 'Rectangle::'; echo Done
Done

Now there are none, thanks to -fvisibility=hidden.

Finally, let's make just Rectangle::area dynamically visible, keeping all the other global symbols dynamically hidden. We need to change the source code again:

rectangle.cpp (3)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    __attribute__((visibility("default"))) int area();

};

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

Then recompile and relink:

$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o

The global symbol table still shows:

$ nm -C librectangle.so | grep 'Rectangle::'
00000000000005a4 t Rectangle::set_values(int, int)
000000000000058a T Rectangle::area()

And the dynamic symbol table only shows:

$ nm -CD librectangle.so | grep 'Rectangle::'
000000000000058a T Rectangle::area()

Rectangle::area is now the only symbol that the shared library exposes for dynamic linkage.

And before you go...

One thing more about:

Is it possible to make area() public and set_values(int,int) local as shown in the first link without altering the code?

Making a symbol hidden for dynamic linkage doesn't make it local. Dynamic visibility (default|internal|hidden|protected) is an attribute of global symbols only. For linkage purposes, local symbols don't exist. The only ways to make a symbol local that would otherwise be global are:-

Then the symbol does not appear in the global, or dynamic, symbol tables.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...