Objcopy将目录路径名添加到符号名之前
objcopy prepends directory pathname to symbol name
我试图使用objcopy
将文本文件的二进制形式包含到可执行文件中。(在运行时,我需要文件作为字符串)。在链接器需要从符号名中查找引用之前,这种方法可以正常工作。问题是objcopy
在文件的符号名前加上了路径名。因为我使用GNU Autotools来发布包,所以这个附加的路径名改变了,我不知道在C/c++程序中使用什么外部链接符号。
nm libtest.a |grep textfile
textfile.o:
00001d21 D _binary__home_git_textfile_end
00001d21 A _binary__home_git_textfile_size
00000000 D _binary__home_git_textfile_start
libtest.a
是由(提取自Makefile.am):
SUFFIXES = .txt
.txt.$(OBJEXT):
objcopy --input binary --output elf32-i386 --binary-architecture i386 $< $@
我怎么能告诉objcopy
只把文件名的词干作为链接符?还是有其他解决问题的方法?
.incbin汇编指令支持将原始数据包含到ELF中的通用方法。
技巧是创建模板.S文件,看起来像这样: .global foo_start
foo_start:
.incbin "foo.raw"
.global foo_end
foo_end:
这个文件是通过cpp预处理的,所以我们不必在那里硬编码文件名,例如。我们可以这样写:
.incbin __raw_file_path__
…然后在编译时传递它:
gcc -D__raw_file_path__='"data/foo.png"' foo.S -c -o data/foo.o
最后,当我们自己准备. s文件时,我们可以添加一些额外的数据和/或信息。如果你包含原始的"文本文件",并希望这些是可用的C字符串,你可以在原始数据后添加'0'字节:
.global foo_start
foo_start:
.incbin "foo.raw"
.global foo_end
foo_end:
.byte 0
.global foo_size
foo_size:
.int foo_end - foo_start
如果你想要完全的灵活性,你当然可以手动预处理文件来改变它的任何部分,例如
.global @sym@_start
@sym@_start:
.incbin "@file@"
.global @sym@_end
@sym@_end:
…然后编译它:
sed -e "s,@sym@,passwd,g" -e "s,@file@,/etc/passwd," <foo.S.in | gcc -x assembler-with-cpp - -o passwd.o -c
有点讽刺的是,你可以使用objcopy
来解决问题,通过--redefine-sym
选项,允许重命名符号…
如果我使用objcopy从另一个PNG中创建一个对象文件目录:
$ objcopy -I binary -O elf64-x86-64 -B i386 --rename-section .data=.rodata,alloc,load,data,contents,readonly ../../resources/test.png test_png.o
结果对象具有以下符号:
$readelf -s test_png.o -W Symbol table '.symtab' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_start 3: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_end 4: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT ABS _binary_______resources_test_png_size
这些可以重命名:
$objcopy --redefine-sym _binary_______resources_test_png_start=_binary_test_png_start test_png.o $objcopy --redefine-sym _binary_______resources_test_png_size=_binary_test_png_size test_png.o $objcopy --redefine-sym _binary_______resources_test_png_end=_binary_test_png_end test_png.o
生成一个具有objcopy所具有的符号名的对象如果PNG位于当前目录,则生成:
$readelf -s test_png.o -W Symbol table '.symtab' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_start 3: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_end 4: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT ABS _binary_test_png_size
我使用的另一种替代方法是将cd
添加到源目录,然后将源的基本名称赋给objcopy
。在bash
中,这将是:
cd $(dirname $SOURCE)
objcopy ... $(basename $SOURCE) $TARGET
这样生成的符号总是没有路径的_binary_file_name_xxx
。
我必须用cmake来做这件事,我最终使用/dev/stdin作为输入来获得一致的符号名称,然后重新定义符号字符串(MAKE_C_IDENTIFIER…)然后在生成的目标文件上使用objcopy——redefine-sym。
结果函数是:
function(make_binary_object __file)
get_filename_component(__file_name ${__file} NAME)
set(__object ${CMAKE_CURRENT_BINARY_DIR}/${__file_name}.obj)
string(MAKE_C_IDENTIFIER ${__file_name} __file_c_identifier)
add_custom_command(OUTPUT ${__object}
COMMAND ${CMAKE_OBJCOPY}
--input-format binary
--output-format elf64-x86-64
--binary-architecture i386:x86-64
/dev/stdin
${__object} < ${__file}
COMMAND ${CMAKE_OBJCOPY}
--redefine-sym _binary__dev_stdin_start=_binary_${__file_c_identifier}_start
--redefine-sym _binary__dev_stdin_end=_binary_${__file_c_identifier}_end
--redefine-sym _binary__dev_stdin_size=_binary_${__file_c_identifier}_size
${__object}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${__file})
set_source_files_properties(${__object} PROPERTIES EXTERNAL_OBJECT TRUE)
endfunction()
你可以这样使用:
make_binary_object(index.html)
add_executable(my_server
server.c
${CMAKE_CURRENT_BINARY_DIR}/index.html.obj)
一个简单的解决方案是将文本文件转换为可用于初始化char数组的格式。因此,对于"ABC012",您将得到0x41,0x42,0x43,0x30,0x31,0x32。然后可以#include这个字节序列。您还可以转义所有非ascii字符,而不是将所有内容转换为字节,以便在生成的include文件中大多数文本仍然可读。
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 添加符号 libgtest.so 错误:命令行中缺少 DSO
- libstdc++.so.6:添加符号时出错:命令行中缺少 DSO
- 当 lib 已添加到其他依赖项时,如何在 VS 中调试未解析的外部符号错误
- 如何将空文件夹和符号链接添加到存档 - libarchive
- ctypes,添加静态库时未定义的符号
- 计算机使用什么方法添加无符号整数
- 添加有符号和无符号整数
- 为什么隐藏的符号仍然添加到 DSO 中
- 在 gdb (Windows) 中添加 dll 的调试符号
- MySQL C++连接器:添加符号时出错:文件格式无法识别
- 当我尝试将文件添加到另一个文件时出现怪异符号时
- Openssl C++ AES 解密添加意外符号
- 英特尔 MKL 和 JNI:如何添加 ld 从中搜索符号的共享库?
- gcc添加符号时出现无效版本(max)错误:值错误
- 为什么RGB组件被打印为符号,直到我添加+'0'-'0'?
- C 实现CNN错误添加符号:命令行中缺少DSO
- 不使用 符号的添加
- 如何为宏符号添加前缀
- 在c++中调用函数时未定义的符号添加随机字符