如果我直接使用共享库中的函数,即通过在代码中声明该函数并在编译时进行链接,则LD_PRELOAD可以正常工作。但是,如果我使用dlopen()/dlsym(),则LD_PRELOAD无效!
问题是我想调试一个使用dlopen()加载某些插件的程序,并且该程序使用绝对文件名,因此仅使用LD_LIBRARY_PATH将无法工作。
这是说明问题的示例代码。
./libfoo.so
void foo() {
printf("version 1\n");
}
void foo() {
printf("version 2\n");
}
#include <stdio.h>
#include <dlfcn.h>
void foo();
int main(int argc, char *argv[]) {
void (*pfoo)();
foo(); // call foo() first so we are sure ./preload/libfoo.so is loaded when we call dlopen()
pfoo = dlsym(dlopen("libfoo.so", RTLD_NOW), "foo");
pfoo();
return 0;
}
dlopen(),并且有什么方法可以重定向dlopen(),尤其是在使用绝对路径时?
最佳答案
指定LD_PRELOAD将使加载程序在加载主可执行文件之前无条件加载(并初始化)指定的共享库。这使得在链接main之前可以使用预加载库中定义的符号,从而可以插入符号。 [注1]
因此,在您的示例中,对foo()的调用使用了预加载模块中的符号,如果您使用NULL句柄对其进行调用,则dlsym将返回相同的符号。
但是,对dlopen的调用未考虑您要查找的符号(出于明显的原因)。它只是加载指示的共享对象或返回该共享对象已缓存版本的句柄。如有必要,它不会将模块添加到要加载的模块列表中。它只是加载模块。当您将返回的句柄传递给dlsym时,dlsym恰好在该模块中查找以便解析符号,而不是搜索可执行文件中存在的一组外部符号。 [笔记2]
如前所述,如果dlopen已经加载了相同的共享对象,则它不会多次加载该对象。 [注3]。但是,您的LD_PRELOAD中的共享对象称为preload/libfoo.so,而不是libfoo.so。 (与某些其他操作系统不同,ELF不会从共享库名称中删除目录路径。)因此,当您调用dlopen("libfoo.so")时,动态加载程序将不会在已加载的共享库的高速缓存中找到任何名为libfoo.so的共享库。因为提供的文件名不包含/,所以使用库搜索路径在文件系统中查找该对象。
事实证明,ELF确实允许您指定共享库的名称。因此,您可以将预加载的模块的名称设置为稍后将动态加载的名称,然后dlopen将句柄返回到预加载的模块。
我们首先在原始问题中更正main.c的版本:
#include <stdio.h>
#include <dlfcn.h>
void foo();
int main(int argc, char *argv[]) {
const char* soname = argc > 1 ? argv[1] : "libfoo.so";
void (*pfoo)();
pfoo = dlsym(NULL, "foo"); // Find the preloaded symbol, if any.
if (pfoo) pfoo(); else puts("No symbol foo before dlopen.");
void* handle = dlopen(soname, RTLD_NOW);
if (handle) {
pfoo = dlsym(handle, "foo"); // Find the symbol in the loaded SO
if (pfoo) pfoo(); else puts("No symbol foo after dlopen.");
}
else puts("dlopen failed to find the shared object.");
return 0;
}
gcc -Wall -o main main.c -ldl
gcc -Wall -o libfoo.so -shared -fPIC libfoo.c
gcc -Wall -o preload/libfoo.so -shared -fPIC preload/libfoo.c
dlopen/dlsym在加载的模块中找到了符号:$ LD_PRELOAD=preload/libfoo.so LD_LIBRARY_PATH=. ./main libfoo.so
version 2
version 1
$ gcc -Wall -o preload/libfoo.so -Wl,--soname=libfoo.so -shared -fPIC preload/libfoo.c
$ LD_PRELOAD=preload/libfoo.so LD_LIBRARY_PATH=. ./main libfoo.so
version 2
version 2
dlopen正在寻找名为libfoo.so的共享对象。但是,加载插件的应用程序更有可能使用文件名而不是使用库搜索路径。这将导致不考虑预加载的共享库,因为名称不再匹配:$ LD_PRELOAD=preload/libfoo.so LD_LIBRARY_PATH=. ./main ./libfoo.so
version 2
version 1
$ gcc -Wall -o preload/libfoo.so -Wl,--soname=./libfoo.so -shared -fPIC preload/libfoo.c
$ LD_PRELOAD=preload/libfoo.so LD_LIBRARY_PATH=. ./main libfoo.so
version 2
version 2
dlsym仅查找符号,则可以传递NULL句柄。在这种情况下,dlsym将搜索dlopen加载的模块(包括dlopen加载的模块所需的模块)。但这几乎不是您想要的,因为使用dlsym加载插件的应用程序通常会指定插件必须定义的特定符号(或多个符号),并且这些符号将出现在每个已加载的插件中,从而使得按符号名称进行的查找不精确。 dlopen版本以覆盖共享对象名称查找。但这可能比必要的工作多得多。 关于c - LD_PRELOAD不会影响RTLD_NOW的dlopen(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37792037/
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
我很好奇.NET将如何影响Python和Ruby应用程序。用IronPython/IronRuby编写的应用程序是否会非常特定于.NET环境,以至于它们实际上将变得特定于平台?如果他们不使用任何.NET功能,那么IronPython/IronRuby相对于非.NET同类产品的优势是什么? 最佳答案 我不能说任何关于IronRuby的东西,但是大多数Python实现(如IronPython、Jython和PyPy)都试图尽可能忠实于CPython实现。不过,IronPython正在迅速成为这方面的佼佼者之一,并且在PlanetPyth
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我有可变数量的表格和可变数量的行,我想让它们一个接一个地显示,但如果表格不适合当前页面,请将其放在下一页,然后继续。我已将表格放入事务中,以便我可以回滚然后打印它(如果高度适合当前页面),但我如何获得表格高度?我现在有这段代码pdf.transactiondopdf.table@data,:font_size=>12,:border_style=>:grid,:horizontal_padding=>10,:vertical_padding=>3,:border_width=>2,:position=>:left,:row_colors=>["FFFFFF","DDDDDD"]pdf.
输入rakedb:create后我得到:LoadError:Couldnotopenlibrary'sodium':dlopen(sodium,5):imagenotfound.Couldnotopenlibrary'libsodium.dylib':dlopen(libsodium.dylib,5):imagenotfound这里还有一些输出。/Users/Mao/.rvm/gems/ruby-2.0.0-p451/gems/ffi-1.9.3/lib/ffi/library.rb:133:in`blockinffi_lib'/Users/Mao/.rvm/gems/ruby-2.0
我正在使用Rails5ApplicationController.renderer.render方法从模型中进行渲染。我需要将一些变量传递给我的布局,这是我使用locals选项完成的;如果直接访问此变量,则该变量在布局中可用,但不能通过self访问。这是我设置渲染的方式html_string=ApplicationController.renderer.render(file:"/#{template_path}/base/show",:formats=>[:pdf,:html],locals:{:@routing_form=>self,:controller_name=>contro
文章目录前言1.AI的发展历程2.我是如何接触到人工智能的概念和产品的3.对于ChatGPT的一点看法4.AI对大学毕业生的职业发展的利与弊5.对于AI的思考和问题前言随着ChatGPT的爆火,生成式AI,大模型的人工智能被越来越多的人注意到,同时他也带来了许多问题。本文将对几方面进行探讨。1.AI的发展历程远古时期在公元前第一个千禧年,中国,印度和希腊哲学家都提出了一些推理的研究理论,比如亚里士多德(Aristotle)进行了演绎推理三段论的完整分析,欧几里得(Euclid)所著Elements是一种形式推理的模型,MuḥammadibnMūsāal-Khwārizmī,发明了代数学,即我们
我一直试图在这里寻找答案,但我找不到任何有用的东西。我已经对我的Rails应用程序实现了:success和:dangerflash通知。它工作得很好,即:success是绿色的,:danger是红色的,有一个关闭按钮等等,但是自从添加了一些邮件文件后,我的:success现在显示为红色?application.html.erb摘录:×contact_mailer.rbclassContactMailercontacts_controller.rbclassContactsController还有,contact_email.html.erbNewMessagefromHoo