[请教]关于共享库函数导出问题

ydogg 2006-04-03 01:52:59
本人对linux开发不熟悉,请大家不吝赐教。

在一个动态(共享)库中,有部分函数是只在内部使用,因此不能让用户看到这些接口。
在window下,开发标准dll时,可以使用MS提供的扩展语法dllexport将dll中的接口导出。
没有dllimport声明的函数就无法被外部使用。

但在linux上,生成的共享库(.so)如何能做到同样的效果? 目前我发现生成的.so中,nm可以看到所有的函数。

请指教!谢谢!
...全文
595 14 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
ydogg 2006-04-07
功能接口通过头文件提供给用户,但实现这些功能的内部支撑函数(比如内部管理之类的接口)不能提供给用户(定义这些函数的头文件是不发布的)。至少是不那么容易的被用户使用上。呵呵。
  • 打赏
  • 举报
回复
ydogg 2006-04-07
to tb01412(tb):
// 用static来修饰函数,这样可以防止用户连接你的程序,但无法向用户隐藏函数信息。其实
// 你若不向用户开放函数声明(也就是头文件),人家怎么通过你的库来看到你的函数原型
// 呢???如果人家不知道你的函数原型,又怎么能正常使用你的函数接口呢????

功能接口通过头文件提供给用户,但实现这些功能的内部支撑函数(比如内部管理之类的接口)不能提供给用户。至少是不那么容易的被用户使用上。呵呵。

to fierygnu(va_list):
这样不知道行不行,关键是和客户需求就不一致了。呵呵。

感谢大家的帮助,给分,结贴。


  • 打赏
  • 举报
回复
fierygnu 2006-04-07
好像是没有什么好办法。
要不然试试把不想输出的函数编译为静态库,其它的编译为动态库,在连接动态库时用--whole-archive把静态库的模块装入动态库,这样动态连接的应用或许不能调用那些静态库的模块,因为那些模块没有用-fPIC编译。
我手边没有系统,不知道是否可行。
  • 打赏
  • 举报
回复
hundlom 2006-04-06
tb01412(tb) 和fierygnu(va_list)都这么热心!呵呵,看你们这么认真的回帖子真好。很详细,特认真!
  • 打赏
  • 举报
回复
tb01412 2006-04-06
没有两全其美的办法了,既然你都列出了解决方案,你自己看着办吧!!!!
用static来修饰函数,这样可以防止用户连接你的程序,但无法向用户隐藏函数信息。其实你若不向用户开放函数声明(也就是头文件),人家怎么通过你的库来看到你的函数原型呢???如果人家不知道你的函数原型,又怎么能正常使用你的函数接口呢????
假定人家完全清楚你的函数接口,就算你用strip,人家同样可以重建符号表(假定人家一定要破解你的库的话),所以基本上没什么实质性的作用

你的需求是:
1. 用户无法在自己的代码中使用这些支撑函数,至少不能link通过
2. 在满足1的情况下,让用户无法得知这些函数被定义在库中或者被导出
解决办法是:
strip掉你想要向用户隐藏的符号
  • 打赏
  • 举报
回复
fierygnu 2006-04-06
tb01412(tb)分析的非常好,赞一个:)
楼主的需求是不明确。
static在elf格式里被放在local符号区,只能在本模块内使用,可以起到屏蔽的作用,但如果是一个内部使用的公用函数,这样会导致所有使用该函数的代码不得不放在一个源文件里,从而引起整个代码的物理架构的混乱。
  • 打赏
  • 举报
回复
lqh_wh 2006-04-06
不提供相关函数的声明,就象GTK+2.0做的。
  • 打赏
  • 举报
回复
ydogg 2006-04-06
多日未来,感谢诸位详尽的分析指点。谢一个,呵呵。

我的需求是:
1. 用户无法在自己的代码中使用这些支撑函数,至少不能link通过
2. 在满足1的情况下,让用户无法得知这些函数被定义在库中或者被导出


1.函数不能弄成内联或者宏,因为这些支撑函数都比较复杂
2.static方式指的是什么意思?静态链接?动态库能进行静态链接吗?还是定义为静态函数?
后者恐怕不行,原因如fierygnu(va_list)兄所述。

3.最后,strip -x或者strip -X似乎看起来就是我想要的...
但是,有个不爽的地方,每增加一个内部函数岂不是都要手工来重新设置这个选项?






  • 打赏
  • 举报
回复
tb01412 2006-04-05
对于内联函数的展开,每个编译器的实现略有不同,的确,如果内联函数过长,会被编译器当作普通函数来产生目标文件,宏与内联会让产生的代码膨张!!!!

对于static的限制,不仅作用于编译期,而且还会作用于连接阶段,目标文件中会有一个符号段,这里会对每个比如全局函数,全局变量,外部函数,外部变量等,在连接时会用到这种信息,如果你的一个函数由static关键字修饰,在连接时,若外部需要这个函数,连接时会报错,如果两个库中都有同一个全局函数名称,连接时根据搜索路径,如果先找到一个库中的相应函数,就会停止查找,因此就忽略了第二个库的函数,这种不好之处由C++中的命名空间进行解决的,当然,用户在使用你提供的库时,可以突破这种static的限制,就是修改目标文件的符号表,把static类型修改成全局类型,这样就让连接器认为是真的可导出的全局变量。若不相信,大家可以写代码进行测试

再说一下strip,在LINUX下通过strip的帮助看到以下信息:
[root@localhost root]# strip --help
Usage: strip <option(s)> in-file(s)
Removes symbols and sections from files
The options are:
-I --input-target=<bfdname> Assume input file is in format <bfdname>
-O --output-target=<bfdname> Create an output file in format <bfdname>
-F --target=<bfdname> Set both input and output format to <bfdname> -p --preserve-dates Copy modified/access timestamps to the output -R --remove-section=<name> Remove section <name> from the output
-s --strip-all Remove all symbol and relocation information
-g -S -d --strip-debug Remove all debugging symbols
--strip-unneeded Remove all symbols not needed by relocations
-N --strip-symbol=<name> Do not copy symbol <name>
-K --keep-symbol=<name> Only copy symbol <name>
-x --discard-all Remove all non-global symbols
-X --discard-locals Remove any compiler-generated symbols
-v --verbose List all object files modified
-V --version Display this program's version number
-h --help Display this output
-o <file> Place stripped output into <file>
大家注意-x.-X选项,这就是可以去掉某些符号声明,从而让nm看不到你想要隐藏的信息,也让用户看不到相应信息,还有-K选项,它可以用于伪装,给用户造成假象,其原理也是通过修改符号表来实现的!!!

结论:如果用户想要别人的程序不连接你的某些函数,用static关键字已足够,如果你想要隐葳函数名称,推荐你使用strip -x或者strip -X,但这种方法也不起根本性的作用,如果人家知道你内部的函数,完全可以再修改你的目标文件的符号表来重建相关函数声明,从而可以让用户程序连接你的代码。当然,没有用户会这样去做的!!!最彻底的办法莫过于将你的函数用宏的方式直接就地展开,这样用户就没有任何办法使用你的函数了!!!!!当然这样的后果就是造成代码膨胀,关键是LZ的需求是什么!!!!!
  • 打赏
  • 举报
回复
fierygnu 2006-04-05
用宏或者内联不现实,那样代码会多大姑且不说,超大的内联也会被编译器自动作为函数调用。
static限制的是编译,不是连接。
调试完成后用strip处理即可。
  • 打赏
  • 举报
回复
tb01412 2006-04-05
nm可以看到所有的函数,并不代表外部就可以使用这里面的任何函数,如果你仅是需要让外部不使用你的某些函数,就用static,如果你根本不想让用户看到你的某些函数,就要用内联函数或者用宏的方式,注意在编译的时候加上一点优化,否则编译器不会将你的内联函数展开

用strip的默认方式下,会将库中没有被用过的函数给去掉,并且会去掉调试信息,所以一般情况下只会在最终生成的ELF文件时用一次strip,在编译生成库的时候一般不用strip
  • 打赏
  • 举报
回复
fierygnu 2006-04-05
宏和static可能不行。用strip -K选项把想保留的留下试试。
  • 打赏
  • 举报
回复
hundlom 2006-04-03
static限制
  • 打赏
  • 举报
回复
YanDong_8212 2006-04-03
用宏定义来做限制,看到也不能用。
  • 打赏
  • 举报
回复
相关推荐
发帖
Linux/Unix社区

2.2w+

社区成员

Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
帖子事件
创建了帖子
2006-04-03 01:52
社区公告
暂无公告