【问题标题】:How to embed data in shared library?如何在共享库中嵌入数据?
【发布时间】:2020-03-20 12:17:09
【问题描述】:

例如,我想将 dicmap.bin 嵌入到共享库 libxxx.so。 我写了一个程序来验证它。

test_dicmap.cpp
#include <stdio.h>
#include <stdint.h>

extern "C" {
extern const uint8_t _binary_dicmap_bin_start[];
extern const uint8_t _binary_dicmap_bin_end[];
extern const void* _binary_dicmap_bin_size;
}

int main()
{
    size_t size = (size_t)&_binary_dicmap_bin_size;
    printf("start=%p, end=%p\nend-start=%zd, size=%zd\n", 
        _binary_dicmap_bin_start, 
        _binary_dicmap_bin_end,
        _binary_dicmap_bin_end - _binary_dicmap_bin_start,
        size);
    printf("data[0..8]=%02x %02x %02x %02x %02x %02x %02x %02x\n", 
            _binary_dicmap_bin_start[0], _binary_dicmap_bin_start[1], 
            _binary_dicmap_bin_start[2], _binary_dicmap_bin_start[3],
            _binary_dicmap_bin_start[4], _binary_dicmap_bin_start[5], 
            _binary_dicmap_bin_start[6], _binary_dicmap_bin_start[7]);
}

但是它的_start_end_size是无效的。

]$ ls dicmap.bin  -l
-rw-rw-r-- 1 kirbyzhou kirbyzhou 198600798 Feb 26 10:58 dicmap.bin

]# objcopy -B i386 -I binary -O elf64-x86-64 dicmap.bin dicmap.o && g++ -o libxxx.so dicmap.o -shared  &&  g++ -L. -lxxx  test_dicmap.cpp
/opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: warning: type and size of dynamic symbol `_binary_dicmap_bin_size' are not defined
/opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: warning: type and size of dynamic symbol `_binary_dicmap_bin_start' are not defined
/opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: warning: type and size of dynamic symbol `_binary_dicmap_bin_end' are not defined

]# ./a.out
start=0x601034, end=0x601034
end-start=0, size=6295604
data[0..8]=00 00 00 00 00 00 00 00

end-start 和 size 应为 sizeof dicmap.bin (198600798)。

我的 objcopy 是 rhel7 的 binutils-2.30-54.el7devtoolset-8

我尝试将共享标志添加到.o 文件,但发生错误:

objcopy -B i386 -I binary -O elf64-x86-64 dicmap.bin dicmap.o --set-section-flag .data=share
objcopy: BFD version 2.30-54.el7 internal error, aborting at elf.c:8869 in _bfd_elf_set_section_contents

objcopy: Please report this bug.

rhel7的binutils-2.27-41.base.el7_7.1.x86_64也有同样的问题。

有什么方法可以帮助我吗?

【问题讨论】:

  • 我认为您可能会在这里找到有用的答案:stackoverflow.com/questions/6171929/…
  • 我发布的方法似乎相同,并且不适用于共享库。
  • 在我的示例中,ld -r 用于创建目标文件。你可以试试吗?
  • 是的,我试过了,和objcopy的结果一模一样。 ld -s -r -o dicmap.o -b 二进制 dicmap.bin g++ -shared -fPIC dicmap.o -o libdicmap1.so g++ -c -o test_dicmap.o test_dicmap.cpp g++ libdicmap1.so test_dicmap.o -o test -dicmap1 ]$ ./test-dicmap1 start=0x60102c, end=0x60102c end-start=0, size=6295596 data[0..8]=00 00 00 00 00 00 00 00 test-dicmap1: test_dicmap.cpp:27 : int main(): 断言 `_binary_dicmap_bin_end - _binary_dicmap_bin_start == data_size' 失败。中止(核心转储)

标签: linux shared-libraries rhel binutils


【解决方案1】:

现在有两种方法适合我。

方法一: 使用 objcopy 将数据转换为“.o”,然后链接到“.so”。 然后用“-fPIC”链接“.so”和主代码。

objcopy -B i386 -I binary -O elf64-x86-64 dicmap.bin dicmap.o
g++ -shared -fPIC dicmap.o -o libdicmap1.so
# -fPIC is very import in the following line, 
# But it is very unusual when you compile and link main code.
g++ -fPIC test_dicmap.cpp libdicmap1.so -o test_dicmap1-PIC

方法二: 使用 assmbler 包装数据,并以不同的 objcopy 方式存储大小。

g++ -shared -fPIC dicmap3.s -o libdicmap3.so
g++ test_dicmap3.cpp libdicmap3.so -o test-dicmap3

代码:

test_dicmap.cpp:

#include <stdio.h>
#include <stdint.h>
#include <assert.h>
extern "C" {
extern const uint8_t _binary_dicmap_bin_start[];
extern const uint8_t _binary_dicmap_bin_end[];
extern const void* _binary_dicmap_bin_size;
}
int main()
{
    size_t data_size = (size_t)&_binary_dicmap_bin_size;
    printf("start=%p, end=%p\nend-start=%zd, size=%zd\n", 
        _binary_dicmap_bin_start, 
        _binary_dicmap_bin_end,
        _binary_dicmap_bin_end - _binary_dicmap_bin_start,
        data_size);
    printf("data[0..8]=%02x %02x %02x %02x %02x %02x %02x %02x\n", 
            _binary_dicmap_bin_start[0], _binary_dicmap_bin_start[1], 
            _binary_dicmap_bin_start[2], _binary_dicmap_bin_start[3],
            _binary_dicmap_bin_start[4], _binary_dicmap_bin_start[5], 
            _binary_dicmap_bin_start[6], _binary_dicmap_bin_start[7]);
    assert(_binary_dicmap_bin_end - _binary_dicmap_bin_start == data_size);
}

test_dicmap3.cpp:

#include <stdio.h>
#include <stdint.h>
#include <assert.h>

extern "C" {
extern const uint8_t _binary_dicmap_bin_start[];
extern const uint8_t _binary_dicmap_bin_end[];
extern const size_t _binary_dicmap_bin_size;
}


int main()
{
    size_t data_size = _binary_dicmap_bin_size;
    printf("start=%p, end=%p\nend-start=%zd, size=%zd\n", 
        _binary_dicmap_bin_start, 
        _binary_dicmap_bin_end,
        _binary_dicmap_bin_end - _binary_dicmap_bin_start,
    data_size);
    printf("data[0..8]=%02x %02x %02x %02x %02x %02x %02x %02x\n",
            _binary_dicmap_bin_start[0], _binary_dicmap_bin_start[1], 
            _binary_dicmap_bin_start[2], _binary_dicmap_bin_start[3],
            _binary_dicmap_bin_start[4], _binary_dicmap_bin_start[5], 
            _binary_dicmap_bin_start[6], _binary_dicmap_bin_start[7]);
    // _binary_dicmap_bin_end is invalid
    //assert(_binary_dicmap_bin_end - _binary_dicmap_bin_start == data_size);
}

dicmap3.s:

    .globl  _binary_dicmap_bin_start
    .globl  _binary_dicmap_bin_end
    .globl  _binary_dicmap_bin_size
    .section  .rodata
    .type   _binary_dicmap_bin_start, @object
    .align  8
_binary_dicmap_bin_start:
    .incbin "dicmap.bin"
    .align  1
    .size   _binary_dicmap_bin_end, 1
_binary_dicmap_bin_end:
    .byte   0
    .size   _binary_dicmap_bin_start, _binary_dicmap_bin_end - _binary_dicmap_bin_start
    .type   _binary_dicmap_bin_size, @object
    .size   _binary_dicmap_bin_size, 8
    .align  8
_binary_dicmap_bin_size:
    .quad   _binary_dicmap_bin_end - _binary_dicmap_bin_start

dicmap.bin:

helloworld

【讨论】:

    猜你喜欢
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多