【问题标题】:strace: ld-linux fails to run a simple test binarystrace:ld-linux 无法运行简单的测试二进制文件
【发布时间】:2021-07-28 21:56:04
【问题描述】:

我正在尝试为我要构建的嵌入式系统编译一些东西。但是,在运行我为系统构建的二进制文件时,我遇到了failed to map segment from shared object: Invalid argument。这发生在任何不只是简单的循环和打印的事情上。

以调试的名义,我构建了一个二进制文件(testbin),它简单地列出了当前目录的内容:

#include<stdio.h>
#include<dirent.h>

int main(void)
{
    DIR *d;
    struct dirent *dir;
    d = opendir(".");
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            printf("%s\n", dir->d_name);
        }
        closedir(d);
    }
    return(0);
}

由于系统在库方面有些不合作,我必须全部覆盖,所以我以这种方式运行程序:./ld-linux.so.3 ./testbin 产生:

./testbin: error while loading shared libraries: ./shitls: failed to map segment from shared object: Invalid argument

...正如怀疑的那样,testbin 在需要外部库时也会遇到困难。我设法为系统静态编译strace,它以某种方式运行得很好。所以我相当确定罪魁祸首是每当需要libc.so

当通过ld-linux.so.3 在我的testbin 上运行strace 时,像这样:./strace ./ld-linux.so.3 ./testbin

..我得到了一些可以使用的东西:

execve("./ld-linux.so.3", ["./ld-linux.so.3", "./testbin"], 0xbee2b554 /* 74 vars */) = 0
brk(NULL)                               = 0xb873c000
open("./testbin", O_RDONLY)             = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\2\0(\0\1\0\0\0\311\203\0\0004\0\0\0"..., 512) = 512
lseek(3, 1920, SEEK_SET)                = 1920
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1240) = 1240
lseek(3, 1601, SEEK_SET)                = 1601
read(3, "A2\0\0\0aeabi\0\1(\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 51) = 51
fstat64(3, {st_mode=S_IFREG|0777, st_size=5379, ...}) = 0
getcwd("/mnt/output", 128)    = 22
mmap2(0x5241ae00, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = -1 EINVAL (Invalid argument)
close(3)                                = 0
writev(2, [{iov_base="./testbin", iov_len=9}, {iov_base=": ", iov_len=2}, {iov_base="error while loading shared libra"..., iov_len=36}, {iov_base=": ", iov_len=2}, {iov_base="./testbin", iov_len=9}, {iov_base=": ", iov_len=2}, {iov_base="failed to map segment from share"..., iov_len=40}, {iov_base=": ", iov_len=2}, {iov_base="Invalid argument", iov_len=16}, {iov_base="\n", iov_len=1}], 10./testbin: error while loading shared libraries: ./testbin: failed to map segment from shared object: Invalid argument
) = 119
exit_group(127)                         = ?
+++ exited with 127 +++

...但我不擅长阅读 strace 输出。关于二进制文件在哪里运行的任何指针?

【问题讨论】:

  • 来自mmap 手册页:“EINVAL(页面大小不是 4096 字节的各种平台。)偏移量 * 4096 不是系统页面大小的倍数。”
  • @o11c 值得注意的是,我不是 100% 确定目标架构。它是某种形式的 ARM 兼容海思芯片。这是否意味着我的编译目标错误?我正在基于尽力而为的设置在 qemu 环境中编译这些二进制文件。
  • 由于指定了MAP_FIXEDmmap2 调用可能会失败,因为地址0x5241ae00 不是页面对齐的。
  • 注意:它还没有尝试加载libc.so./ld-linux.so.3 在映射./testbin 文件中的“文本”部分(如PROT_EXEC 标志所示)期间失败。
  • @IanAbbott 我尝试使用正确的 libc.so 来 patchelf 二进制文件,但没有运气。然而,PROT_EXEC 让我印象深刻,因为我在尝试各种其他方法时也得到了“权限被拒绝”(我不记得究竟是哪种方法产生了这种情况),好像某些东西超出了通常的权限让我从运行文件。关于我在哪里可以找到更多信息的任何指针?

标签: c embedded-linux strace


【解决方案1】:

您的开发 sysroot 似乎与目标上的 sysroot 库不匹配。一种选择是为您的芯片找到合适的交叉开发工具。另一种选择是从目标中提取 rootfs 并尝试在您的 qemu 设置中构建它。例如:

LDFLAGS = -L/rootfs-mipsel/mipsel-linux-gnu -lusb-1.0 -ludev

此外,交叉编译器可以将所需的 rootfs 作为参数:--sysroot=/opt/rootfs-mipsel

您当前在 qemu 中的开发工具可能使用与目标不同的 ld.so 版本。编译后可以用 patchelf 编辑:

patchelf --set-interpreter /lib/ld.so.1 a.out

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-20
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 2016-09-19
    • 2019-01-26
    • 1970-01-01
    相关资源
    最近更新 更多