即使重命名符号后,全局变量的地址也不会更改

时间:2016-09-12 07:57:26

标签: c gcc linker

我正在尝试创建全局变量的副本,每个SO一个副本。为此,我在使用objcopy进行编译后重命名全局变量。但我无法达到预期的效果。

我的abc.c如下:

#include <stdio.h>
int global_var = 0;                                                                                                                                                   

void xyz()
{    
    printf("%s:%d => %d\n",__FILE__,__LINE__,global_var);
    ++global_var;
    printf("%s:%d => %d\n",__FILE__,__LINE__,global_var);
    printf("%x\n",&global_var);
}    

main1.c如下:

void xyz();

void main_first()
{
    xyz();
}

main2.c如下:

void xyz();

void main_2nd()
{
    xyz();
}

并且testing.c为:

void main_first();
void main_2nd();

int main()
{
    main_first();
    main_2nd();
}

最后我的CMakeLists.txt如下:

cmake_minimum_required(VERSION 2.8)

project(sample_project)

set(CMAKE_OBJECT_COPY objcopy)

add_definitions(-fPIC)                                                                                                                                                

set(_tn libone.so)
add_library(one SHARED main1.c abc.c)
add_custom_command(TARGET one
            COMMAND ${CMAKE_OBJECT_COPY} --redefine-sym _Z3xyzv=_Z7one_xyzv --redefine-sym _ZL10global_var=_ZL14one_global_var ${_tn})

set(_tn libtwo.so)
add_library(two SHARED main2.c abc.c)
add_custom_command(TARGET two
            COMMAND ${CMAKE_OBJECT_COPY} --redefine-sym _Z3xyzv=_Z7two_xyzv --redefine-sym _ZL10global_var=_ZL14two_global_var ${_tn})

add_executable(sample test.c)

target_link_libraries(sample one two)

我在这里重命名xyz()global_var。所以,我希望两个SO都有global_var的不同副本。但是当我运行时,我得到了以下输出。

/home/gautam/cprog/sample_project/abc.c:8 => 0
/home/gautam/cprog/sample_project/abc.c:10 => 1
98eb5050
/home/gautam/cprog/sample_project/abc.c:8 => 1
/home/gautam/cprog/sample_project/abc.c:10 => 2
98eb5050

这与假设相反。在这两种情况下,打印的地址都应该不同。

此过程中哪一步不正确?

甚至可以实现这个目标吗?

是的,-fvisibility=hidden对我有用,他能做的其他任何事情都能实现吗?

4 个答案:

答案 0 :(得分:1)

objcopy --rename-symbol不会重命名动态符号。没有选项或实用程序。因此它适用于静态库或常规目标文件,但不适用于动态库。

要验证,请参阅

的输出
   nm libone.so
   nm -D libone.so

重命名前后。

您可以在任何阶段重命名符号以生成最终的共享库。

答案 1 :(得分:0)

在阅读了@n.m.的回答之后,我做了以下工作并且也工作了。(没有更改来源,即源文件与问题相同)。

gcc -c -fPIC abc.c -o abc1.o
objcopy --redefine-sym xyz=one_xyz --redefine-sym global_var=one_global_var abc1.o
gcc -c -fPIC main1.c -o main1.o
objcopy --redefine-sym xyz=one_xyz --redefine-sym global_var=one_global_var main1.o

gcc -shared main1.o abc1.o -o libone.so

gcc -c -fPIC abc.c -o abc2.o
objcopy --redefine-sym xyz=two_xyz --redefine-sym global_var=two_global_var abc2.o
gcc -c -fPIC main2.c -o main2.o
objcopy --redefine-sym xyz=two_xyz --redefine-sym global_var=two_global_var main2.o

gcc -shared main2.o abc2.o -o libtwo.so

gcc test.c -L. -lone -ltwo

输出是:

abc.c:8 => 0
abc.c:10 => 1
e10003c
abc.c:8 => 0
abc.c:10 => 1
defe03c

答案 2 :(得分:0)

另一种方法可以是构建如下:(本地化符号)

gcc -c -fPIC -fvisibility=hidden abc.c -o abc.o
objcopy --keep-global-symbol=xyz abc.o

gcc -c -fPIC  main1.c -o main1.o
gcc -shared main1.o abc.o -o libone.so

gcc -c -fPIC  main2.c -o main2.o
gcc -shared main2.o abc.o -o libtwo.so

gcc test.c -L. -lone -ltwo 

输出将为:

abc.c:8 => 0
abc.c:10 => 1
666a0034
abc.c:8 => 0
abc.c:10 => 1
6649e034

答案 3 :(得分:-1)

我能做到。将main1.c更改为:

void xyz();

__attribute__ ((visibility ("default"))) void main_first()                                                                                                            
{
    xyz();
}

并且main2.c为:

void xyz();

__attribute__ ((visibility ("default"))) void main_2nd()                                                                                                              
{
    xyz();
}

并在我的add_definitions(-fPIC -fvisibility=hidden)中添加了CMakeLists.txt

cmake_minimum_required(VERSION 2.8)      

project(sample_project)                  

set(CMAKE_OBJECT_COPY objcopy)           

add_definitions(-fPIC -fvisibility=hidden)                                                                                                                            

add_library(one SHARED main1.c abc.c)    

add_library(two SHARED main2.c abc2.c)   

add_executable(sample test.c)            

target_link_libraries(sample one two)  

它有效。

/home/gautam/cprog/sample_project/abc.c:8 => 0
/home/gautam/cprog/sample_project/abc.c:10 => 1
69e93048
/home/gautam/cprog/sample_project/abc2.c:8 => 0
/home/gautam/cprog/sample_project/abc2.c:10 => 1
69c91048

另外一例使用GCC pargma来达到类似的效果。像...

#pragma GCC visibility push(default)

void main_first()
{
    xyz();
}

#pragma GCC visibilty pop