我正在尝试创建全局变量的副本,每个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
对我有用,他能做的其他任何事情都能实现吗?
答案 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