- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试:我在 /chroot/debian6.0/
中定义了一个环境我在其中绑定(bind)了一些目录并创建了其他目录。一个是 libs/
,它包含库 libOne.so
及其依赖项所以:
/chroot/debian6.0/
\--- libs/
\--- libOne.so
\--- other dependencies (*.so)
这个库已经在 chroot 环境中编译,我想用从包含环境运行的进程打开它。
这是代码:
#include <unistd.h>
#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int res = 0;
void* handle;
/*chdir to first argument(path1)*/
res = chdir(argv[1]);
if (res == 0) {
printf("\nchdir: %s", argv[1]);
} else {
printf("\nError chdir %s\n", argv[1]);
return 1;
}
/*chroot to path in first argument*/
res = chroot(argv[1]);
if (res == 0) {
printf("\nchroot: %s", argv[1]);
} else {
printf("\nError chroot %s\n", argv[1]);
return 1;
}
/*Define path for dependencies*/
putenv("LD_LIBRARY_PATH=/libs/");
/*Opens library*/
handle = dlopen(argv[2], RTLD_NOW);
if (handle == NULL) {
printf("\nError opening %s\n", argv[2]);
return 1;
} else {
printf("\ndlopen: library %s opened\n", argv[2]);
}
return 0;
}
然后我执行以下命令:
./remote "/chroot/debian6.0/Debian-6.0-chroot/" "/libs/libOne.so"
结果是尝试dlopen库时出错。strace 的最后几行:
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0P#\0\000"..., 1024) = 1024
fstat64(3, {st_mode=S_IFREG|0644, st_size=116600, ...}) = 0
old_mmap(NULL, 119656, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xb7644000
mprotect(0xb7661000, 872, PROT_NONE) = 0
old_mmap(0xb7661000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1c000) = 0xb7661000
close(3) = 0
munmap(0xb7f01000, 6291) = 0
munmap(0xb7770000, 6496996) = 0
munmap(0xb7757000, 98784) = 0
munmap(0xb7662000, 1000332) = 0
munmap(0xb7644000, 119656) = 0
write(1, "chroot: /chroot/debian6.0/Deb"..., 48chroot: /chroot/debian6.0/Debian-6.0-chroot/
) = 48
write(1, "Error opening /libs/libD"..., 50Error opening /libs/libOne.so
) = 50
munmap(0xb7f03000, 4096) = 0
_exit(1) = ?
该库似乎具有所有依赖项 - 在 chroot 中我可以 ldd libOne.so
然后我得到
linux-gate.so.1 => (0xb7f16000) libpthread.so.0 => /lib/libpthread.so.0 (0xb78c6000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb77d1000) libm.so.6 => /lib/libm.so.6 (0xb77aa000) libc.so.6 => /lib/libc.so.6 (0xb7665000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7647000) /lib/ld-linux.so.2 (0xb7f17000)
知道为什么 dlopen
失败了吗?或者如何让它发挥作用?
添加了 perror 和 dlerror,我得到:
Error opening library /lib/libc.so.6: version `GLIBC_2.4' not found (required by /libs/libOne.so)) = 117
更新:
虽然我已经将用于编译程序的 libc 版本复制到我的包含环境和 chroot' 环境(都在/lib 中),但我仍然在执行时收到相同的消息:
Error opening library /lib/libc.so.6: version `GLIBC_2.4' not found (required by /libs/libOne.so)) = 117
所以我去了每个 lib 文件夹,这就是我所看到的:
包含环境:
ll /lib
libc-2.2.4.so
libc.so.6 -> libc-2.2.4.so
ldd libc.so.6
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7dcc000)
Chroot 的环境:
ll /lib
libc.so.6 -> libc-2.11.3.so
libc-2.11.3.so
ldd libc.so.6
/lib/ld-linux.so.2 (0xb7fb4000)
linux-gate.so.1 => (0xb7fb3000)
在我的编译环境中:
ll /lib
libc.so.6 -> libc-2.11.3.so
libc-2.11.3.so
ldd libc.so.6
/lib/ld-linux.so.2 (0xf770f000)
linux-gate.so.1 => (0xf770c000)
所以看起来我的 libc.so.6 的编译和执行版本是相同的,并且链接到第二个相同的版本,即 libc-2.11.3.so
所以,我不明白为什么我会收到 GLIBC_2.4 消息
最后更新:现在,在 Petesh 的指导下使用 dlmopen
,我的 strace 抛出了下一条消息(在最后):
writev(2, [{"./remote", 5}, {": ", 2}, {"/lib/libdl.so.2", 15}, {": ", 2}, {"version \`GLIBC_2.3.4\' not found "..., 51}, {"\n", 1}], 6./remote: /lib/libdl.so.2: version `GLIBC_2.3.4' not found (required by ./remote) ) = 76
最佳答案
与 GLIBC_2.4
not being found 有关的错误很可能是因为 dlopen
的调用发生在一个已经映射到 libc 副本中的进程中不会公开该版本。
所以,我们需要有点创意,使用辅助例程 dlmopen
而不是简单的老式 dlopen
。
dlmopen 接受一个参数 lm_id
,它是一个命名空间,它加载所有相关的库 - 如果您使用默认值 (LM_ID_BASE
),它以命名空间开始程序运行于;例如,其中包含应用程序启动时已经加载的 libc
。
因此,我们不只是调用 handle = dlopen(argv[2], RTLD_NOW);
,而是调用:
handle = dlmopen(LM_ID_NEWLM, argv[2], RTLD_NOW | RTLD_LOCAL);
这会将 argv[2]
需要的所有库的新副本加载到该句柄使用的链接地址空间中。
然后您可以使用以下方法在库中引用符号:
symbol = dlsym(handle, "symname");
它应该可以工作。
我稍微改变了你的例子来利用这个:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int res = 0;
void* handle;
/*chdir to first argument(path1)*/
res = chdir(argv[1]);
if (res == 0) {
printf("\nchdir: %s", argv[1]);
} else {
printf("\nError chdir %s\n", argv[1]);
return 1;
}
/*chroot to path in first argument*/
res = chroot(argv[1]);
if (res == 0) {
printf("\nchroot: %s", argv[1]);
} else {
printf("\nError chroot %s\n", argv[1]);
return 1;
}
/*Define path for dependencies*/
putenv("LD_LIBRARY_PATH=/libs/");
/*Opens library*/
handle = dlmopen(LM_ID_NEWLM, argv[2], RTLD_NOW); // needs _GNU_SOURCE
if (handle == NULL) {
printf("\nError opening %s: %s\n", argv[2], dlerror());
return 1;
} else {
printf("\ndlopen: library %s opened\n", argv[2]);
}
int (*foo)(void);
foo = (int (*)(void))dlsym(handle, argv[3]);
if (foo == NULL) {
printf("\nError referencing %s: %s\n", argv[3], dlerror());
return 1;
}
printf("%d\n", foo());
return 0;
}
现在,putenv("LD_LIBRARY_PATH=/libs/");
没有做必要的事情 - 你不能在运行时改变 LD_LIBRARY_PATH
程序;根本不会检测到更改。因为您的程序非常简单,所以我们可以在 main 的开头做一些事情,例如:
if (0 == getenv("RE_EXEC")) {
putenv("RE_EXEC=1");
putenv("LD_LIBRARY_PATH=/libs/");
execvp(argv[0], argv);
perror("execvp failed");
exit(1);
}
将 LD_LIBRARY_PATH
设置为 /libs
重新执行,因此它将在那里搜索。
还有一些其他可能的解决方案——如果路径设置不适合重新执行
您可以确保 libOne.so
在二进制文件的 rpath 中有 $ORIGIN
。您可以在编译/链接时执行此操作:
-Wl,-rpath,'$ORIGIN'
引用是为了防止 $ORIGIN
被 shell 转义。如果这是在 makefile
中,那么您需要对目标操作使用 $$
语法。
您可以使用 patchelf
之类的工具对库进行事后修补(在我的系统上我做了一个简单的 sudo apt-get install patchelf
):
patchelf --set-rpath '$ORIGIN' libOne.so
这当然依赖于 ld.so
中对 $ORIGIN
的支持(我不记得它是什么时候添加到 ld.so
; 但已经有几年了);如果你的 ld.so
不支持 $ORIGIN
那么你总是可以用 /libs/
替换它,如果你找不到 patchelf
为你的发行版,那么你总是可以 build it yourself
关于c - dlopen 在 chroot 中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40157782/
我在使用以下代码时遇到问题: function http_file_exists($url){ $f=fopen($url,"r"); if($f){ fclose($f); retu
我已经通过 Git 部署到 Azure 几个月了,没有出现重大问题,但现在我似乎遇到了一个无法克服的错误。 我创建了一个新的 Azure 网站,为正在开发的项目创建单独的预览链接。我在新站点上设置了
我已经通过flutter创建了一个App并完成了它,我想在flutter文档中阅读时进行部署。 我收到此错误: FAILURE: Build failed with an exception. * W
我在Windows 10中使用一些简单的Powershell代码遇到了这个奇怪的问题,我认为这可能是我做错了,但我不是Powershell的天才。 我有这个: $ix = [System.Net.Dn
我正在尝试使用 RapidJSON 解析从服务器接收到的数据。以下是收到的确切字符串: [ { "Node": "9478149a08f9", "Address": "172.17
我尝试为 ios 编译 OpenCV。我总是收到这些错误。我用不同版本的opencv试了一下,结果都是一样的。 我运行这个:python 平台/ios/build_framework.py ios_o
我在一台机器上做基本的发布/订阅,我的客户端是 StackExchange-Redis 的 C# 客户端,我在同一台机器上运行基于 Windows 的 Redis 服务器(服务器版本 2.8.4) 当
我有这段代码,但无法执行,请帮我解决这个问题 连接 connect_error) { die ("connection failed: " . $terhubung->connect_erro
我在 tomcat 上运行并由 maven 编译的 Web 应用程序给出了以下警告和错误。我可以在本地存储库中看到所有 JAR,但有人可以帮忙吗。 WARNING: Failed to scan JA
我正在 Windows 8 上使用 Android Studio 开发一个 android 应用程序,我正在使用一些 native 代码。突然间我无法编译我的 C 文件。当我运行 ndk-build
下面的代码对类和结构的成员进行序列化和反序列化。序列化工作正常,但我在尝试使用 oarch >> BOOST_SERIALIZATION_NVP(outObj); 反序列化时遇到了以下错误; 代码中是
如果我运行此命令“rspec ./spec/requests/api/v1/password_reset_request_spec.rb”,此文件中的所有测试都会通过。 但是,当我运行“rspec”时
我在尝试执行测试以使用 Protractor 上传文件时出错,我的代码是这个 it('it should be possible to upload a file', function() {
System.loadLibrary("nativefaceswap"); 当我运行我的应用程序时,我在 Android Studio 中发现了此类错误。在logcat中显示: java.lang.U
我希望有人能帮助我!使用任何方法或命令行的任何 SSL/HTTPS 调用均无效。 我在 Windows 10 中使用 Ubuntu Server 18.04 作为子系统。我的问题是昨天才开始出现的,因
通过删除这两个值将日期字段从 null=True 和 Blank=True 更改为 required 时,使用 db.alter 命令时遇到问题。 当以下行被注释掉时,迁移运行不会出现问题。
我第一次使用 Heroku 尝试创建应用程序(使用 SendGrid 的 Inbound Parse Webhook"和 Twilio SMS 通过电子邮件发送和接收 SMS 消息)。通过 Virtu
我正在将我的 swift 项目更新到 Xcode 7 上的 Swift 2.0。xcode 在构建项目时报告了以下错误: 命令/Applications/Xcode.app/Contents/Deve
在我的代码中,SSL 库函数 SSL_library_init() 没有按预期返回 1。我如何才能看到它返回了什么错误? 我在 SSL_library_init() 之后调用了 SSL_load_er
我正在尝试运行在以下链接中找到的答案: Asynchronously Load the Contents of a Div 但是当我这样做时,我会遇到我不太理解的错误。 我的代码: $(documen
我是一名优秀的程序员,十分优秀!