【问题标题】:How to check that a symbol is defined in linker script如何检查链接描述文件中是否定义了符号
【发布时间】:2012-02-28 18:33:00
【问题描述】:

我正在使用不同的链接器脚本。在某些情况下,定义了一个值,在另一些情况下,它没有定义:

DIRECTORY_ADDRESS = 0x80100000;
DIRECTORY_SIZE = 32M;

在执行时,我想要在未定义此值时的默认行为,以及在定义时的特殊行为。

通常,我得到这样的值:

extern void * DIRECTORY_ADDRESS;
extern void * DIRECTORY_SIZE;

void f() { 
  void *dir_addr = &DIRECTORY_ADDRESS;
  int dir_size   = (int)&DIRECTORY_SIZE;
}

我的第一个导致条件执行代码根据链接脚本中这个值的存在是弱属性:

extern void * DIRECTORY_ADDRESS  __attribute__ ((weak)) = 0x0;
extern void * DIRECTORY_SIZE __attribute__ ((weak)) = 0x0;

void f() {
  if ( DIRECTORY_ADDRESS )
    // special code
  else
    // default code
}

但它不起作用,因为我正在初始化指针值,而不是它的地址:即使是未定义的弱符号也有一个地址。所以目录地址总是!= NULL。

我很确定这个问题已经解决了,但是我在网上找不到任何相关的问题。

【问题讨论】:

  • 你能不能只使用共享库并检查加载带有你的函数的库是否失败?

标签: gcc linker ld


【解决方案1】:

默认情况下,未初始化的全局变量很弱,所以你可以直接使用

void * DIRECTORY_ADDRESS;
void * DIRECTORY_SIZE;

如果没有为这些名称定义外部符号,则该值将默认为 NULL。要强制使用不同于 NULL 的默认值,您可以使用

void * DIRECTORY_ADDRESS __attribute__ ((weak)) = OTHER_VALUE;
void * DIRECTORY_SIZE __attribute__ ((weak)) = OTHER_VALUE;

请注意,初始化 extern 并没有真正的意义:extern 意味着定义在文件外部,但初始化提供了定义。我的编译器(gcc 4.4)警告用户,然后忽略 extern 修饰符。这意味着您的示例按预期工作(即使在初始化为 0x0 时),但您的编译器可能以不同方式处理这种模棱两可的情况。

【讨论】:

  • 谢谢。这就是我在自我回答中所解释的。实际上,弱符号的初始化是调试步骤之一,与这里无关!
【解决方案2】:

我的错!

我尝试了很多组合,这一个实际上是错误的:

当我初始化弱符号时,有“半弱”

extern void * DIRECTORY_ADDRESS  __attribute__ ((weak)) = 0x0;
extern void * DIRECTORY_SIZE __attribute__ ((weak)) = 0x0;

为了解决我的问题,我只需要让弱符号未初始化,那么如果它们没有用强符号定义,则符号地址将为NULL:

extern void * DIRECTORY_ADDRESS  __attribute__ ((weak));
extern void * DIRECTORY_SIZE __attribute__ ((weak));

【讨论】:

  • 他们并不是真的“半弱”;弱符号确实有默认值。
猜你喜欢
  • 2012-04-06
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 2013-11-08
  • 1970-01-01
  • 2011-06-03
  • 2012-06-19
相关资源
最近更新 更多