【问题标题】:ld of data file makes size of data an *ABS* and not an integer数据文件的 ld 使数据大小成为 *ABS* 而不是整数
【发布时间】:2013-02-11 15:07:48
【问题描述】:

我有一个 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)&amp;_binary_template_xlsx_size(或(int)(_binary_template_xlsx_end - _binary_template_xlsx_start)

一些研究告诉我,上面 objdump 中的 *ABS* 表示“绝对值”,但我不明白为什么。如何让我的 c++(或 c)程序将变量视为 int 而不是指针?

【问题讨论】:

  • 我认为文档中可能有一些关于为什么或如何避免这种情况的提示。为什么不直接编写一个简单的脚本将文件转换为可包含的数组定义?
  • 该文件是一个 xlsx 文件:一个 xml 文件的压缩集合。我这样做的原因是因为我花了一些时间编写代码来解压缩、遍历文件并解析 xml,而我不想重做所有这些。而且这很有趣。
  • 我也可以很好地访问数据。我正试图找出这里发生了什么,因为我对这种行为很感兴趣。

标签: c++ c variables pointers ld


【解决方案1】:

*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)

【讨论】:

    猜你喜欢
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 2021-06-05
    相关资源
    最近更新 更多