我有一个c ++程序,它包含对空xlsx文件的外部依赖。要删除此依赖项,我将此文件转换为二进制对象,以便直接链接它,使用:
ld -r -b binary -o template.o template.xlsx
接着是
objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o
使用objdump,我可以看到声明的三个变量:
$ objdump -x template.o
template.o: file format elf64-x86-64
template.o
architecture: i386:x86-64, flags 0x00000010:
HAS_SYMS
start address 0x0000000000000000
Sections:
Idx Name Size VMA LMA File off Algn
0 .rodata 00000fd1 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l d .rodata 0000000000000000 .rodata
0000000000000fd1 g *ABS* 0000000000000000 _binary_template_xlsx_size
0000000000000000 g .rodata 0000000000000000 _binary_template_xlsx_start
0000000000000fd1 g .rodata 0000000000000000 _binary_template_xlsx_end
然后我告诉我的程序这个数据:
template.h:
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <cstddef>
extern "C" {
extern const char _binary_template_xlsx_start[];
extern const char _binary_template_xlsx_end[];
extern const int _binary_template_xlsx_size;
}
#endif
编译和链接很好,(虽然我在使用cmake自动化时遇到一些麻烦,请看这里:compile and add object file from binary with cmake)
但是,当我在代码中使用_binary_template_xlsx_size时,它被解释为指向不存在的地址的指针。因此,为了获得我的数据大小,我必须通过(int)&_binary_template_xlsx_size
(或(int)(_binary_template_xlsx_end - _binary_template_xlsx_start)
)
一些研究告诉我,上面的objdump *ABS*
意味着“绝对价值”,但我不明白为什么。如何让我的c ++(或c)程序将变量看作int而不是指针?
答案 0 :(得分:3)
*ABS*
符号是绝对地址;它通常是通过将--defsym foo=0x1234
传递给ld。
--defsym symbol=expression
在输出文件中创建一个包含绝对值的全局符号 表达式给出的地址。 [...]
因为绝对符号是常量,所以不可能将它作为变量链接到C源文件中;所有C对象变量都有一个地址,但常量不具有。
为确保不会意外取消引用地址(即读取变量),最好将其定义为const char []
和其他符号一样:
extern const char _binary_template_xlsx_size[];
如果您想确保将其用作int
,则可以使用宏:
extern const char _abs_binary_template_xlsx_size[] asm("_binary_template_xlsx_size");
#define _binary_template_xlsx_size ((int) (intptr_t) _abs_binary_template_xlsx_size)