linux - 如何在共享库中嵌入数据?
问题描述
例如,我想将 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
的是binutils-2.30-54.el7
rhel7 和devtoolset-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.
binutils-2.27-41.base.el7_7.1.x86_64
rhel7的也有同样的问题。
有什么方法可以帮助我吗?
解决方案
现在有两种方法对我有用。
方法一:使用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
方法2:使用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
推荐阅读
- apache-spark - 从 Spark 获取 Impala 表 varchar 列的长度
- java - 优化源代码以减少执行时间
- r - 如何删除包含两列之间顺序条件的行
- python - 无法用 2captcha python 解决 hcaptcha
- go - 自定义功能在模板中不起作用
- apache-spark - Spark on Kubernetes with Minio - Postgres -> Minio - 无法创建执行程序,因为
- python - 如何使用 ansible playbook 检查 linux 磁盘大小小于 10GB?
- recursion - 球拍彩虹形状递归
- teamcity - 未找到 TeamCity 安装
- tabulator - Tabulator V5 Ajax 排序