ld的数据文件使数据大小为*ABS*而不是整数

Tom*_*ald 5 c c++ variables pointers ld

我有一个c ++程序,它包含对空​​xlsx文件的外部依赖.要删除此依赖项,我将此文件转换为二进制对象,以便直接链接它,使用:

ld -r -b binary -o template.o template.xlsx
Run Code Online (Sandbox Code Playgroud)

其次是

objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

然后我告诉我的程序有关这些数据:

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
Run Code Online (Sandbox Code Playgroud)

这编译和链接很好,(虽然我在使用cmake自动化它时遇到一些麻烦,请参阅此处:使用cmake 编译并从二进制文件添加目标文件)

但是,当我在代码中使用_binary_template_xlsx_size时,它被解释为指向不存在的地址的指针.所以要获得我的数据大小,我必须通过(int)&_binary_template_xlsx_size(或(int)(_binary_template_xlsx_end - _binary_template_xlsx_start))

一些研究告诉我,*ABS*上面的objdump意味着"绝对价值",但我不明白为什么.如何让我的c ++(或c)程序将变量看作int而不是指针?

eca*_*mur 3

符号*ABS*是绝对地址;它通常是通过传递--defsym foo=0x1234给 ld 创建的。

--defsym symbol=expression
Run Code Online (Sandbox Code Playgroud)

在输出文件中创建一个全局符号,包含表达式给出的绝对地址。[...]

因为绝对符号是常量,所以不可能将其作为变量链接到 C 源文件中;所有 C 对象变量都有地址,但常量没有。

为了确保您不会意外取消引用地址(即读取变量),最好将其定义为const char []与其他符号相同的方式:

  extern const char _binary_template_xlsx_size[];
Run Code Online (Sandbox Code Playgroud)

如果您想确保将其用作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)
Run Code Online (Sandbox Code Playgroud)