我的链接器有一个烦人的问题。我想将一些符号从共享库链接到静态库,但不导出它的符号(即,我不能简单地合并库或与 --whole-archive 链接)。我想要的是链接(如链接可执行文件,解决 undefined symbol )我的共享库到静态库并删除 undefined symbol 。
我正在寻找的东西可能只是一个链接器选项,但我无法找到它。
我会尽力描述问题(这并不容易),然后提供一个玩具最小的例子来玩。
简要说明:
我想使用 LD_PRELOAD在可执行文件中捕获一些函数调用的技巧。此可执行文件链接到第三方共享库,其中包含我要捕获的函数的函数定义。
这个第三方库还包含来自另一个库的符号,我也在我的库中使用它,但版本不同(不兼容)。
我想要做的是编译我的共享库并在编译时将它与最后一个(静态)库的定义链接,而不导出符号,以便我的共享库使用与我想要的不同的版本陷阱。
简化的问题描述
我有一个名为 libext.so 的第三方库,我没有源代码。这定义了一个函数 bar并使用函数 foo来自另一个库,但符号都在那里定义:
$> nm libext.so
0000000000000a16 T bar
00000000000009e8 T foo
正如我提到的,foo是一个外部依赖项,我想使用更新的版本。我有一个更新的库,我们称之为 libfoo.a :
$> nm libfoo.a
0000000000000000 T foo
现在的问题是我想创建一个动态库来重新定义 bar ,但我希望我的库使用 foo 的定义来自 libfoo.a我想要 libext.so 中的函数调用函数foo来自 libext.so .换句话说,我想要我的库的编译时链接到 libfoo.a .
我正在寻找的是定义一个使用 libfoo.a 的库但不导出其符号。如果我将我的图书馆链接到 libfoo.a ,我得到:
$> nm libmine.so
0000000000000a78 T bar
0000000000000b2c T foo
这意味着我都重载了foo和 bar (我不想覆盖 foo )。如果我不将我的图书馆链接到 libfoo.a ,我得到:
$> nm libmine.so
0000000000000a78 T bar
U foo
所以我的图书馆将使用他们的 foo 版本,我也不想要。我想要的是:
$> nm libmine.so
0000000000000a78 T bar
在哪里 foo在编译时链接,其符号未导出。
小例子
你不需要阅读这篇文章,但你可以用它来玩耍并找到解决方案。
bar.cpp : 代表我没有代码的第三方应用:
#include <iostream>
extern "C" void foo(){ std::cerr << "old::foo" << std::endl; }
extern "C" void bar(){ std::cerr << "old::bar" << std::endl; foo(); }
foo.cpp : 代表我的库和第三方都使用的函数的更新版本:
#include <iostream>
extern "C" void foo(){ std::cerr << "new::foo" << std::endl; }
trap.cpp : 我的库中的代码,它会捕获 bar , 调用新的 foo和转发:
#include <iostream>
extern "C" {
#include <dlfcn.h>
}
extern "C" void foo();
extern "C" void bar(){
std::cerr << "new::bar" << std::endl;
foo(); // Should be new::foo
void (*fwd)() = (void(*)())dlsym(RTLD_NEXT, "bar");
fwd(); // Should use old::foo
}
exec.cpp :调用bar的虚拟可执行文件:
extern "C" void bar();
int main(){
bar();
}
Makefile : 仅限 Unix,抱歉
default:
# The third party library
g++ -c -o bar.o bar.cpp -fpic
gcc -shared -Wl,-soname,libext.so -o libext.so bar.o
# The updated library
g++ -c -o foo.o foo.cpp -fPIC
ar rcs libfoo.a foo.o
# My trapping library
g++ -c -o trap.o trap.cpp -fPIC
gcc -shared -Wl,-soname,libmine.so -o libmine.so trap.o -ldl -L. -lfoo
# The dummy executable
g++ -o test exec.cpp -L. libext.so
在这种情况下,bar来电foo ;正常的执行是:
$> ./test
old::bar
old::foo
预加载我的库拦截 bar , 调用我的foo和转发bar ,当前执行的是:
$> LD_PRELOAD=libmine.so ./test
new::bar
new::foo
old::bar
new::foo
最后一行错了,想要的输出是:
$> LD_PRELOAD=libmine.so ./test
new::bar
new::foo
old::bar
old::foo
最佳答案
您想使用链接器版本脚本,该脚本导出您想要的符号(此处为 bar)并隐藏其他所有内容。
示例 here .
关于c++ - 将静态库链接到共享库并隐藏导出的符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22102470/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac
啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组
我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195
我刚刚了解到,在Java中,覆盖和隐藏之间是有区别的(静态方法是隐藏的,而不是覆盖),这意味着Java使用早期绑定(bind)和后期绑定(bind)。是否有与方法隐藏类似的东西,或者它只是具有方法重写? 最佳答案 Java具有三种不同的“方法”:实例方法,静态方法和构造函数。Ruby只有一个:实例方法。在Java中,静态方法的行为必须不同于实例方法,因为类不是对象。它们没有类,因此也没有父类(superclass),因此没有要覆盖的内容。在Ruby中,类与其他任何对象一样都是对象,它们具有一个类,该类可以具有父类(superclas
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“