【问题标题】:consequences of multiple weak symbols(C Linker)多个弱符号的后果(C 链接器)
【发布时间】:2018-11-12 02:44:29
【问题描述】:

我只是有一个关于多个弱符号的潜在问题的问题,这个问题来自我的教科书:

一个模块A:

int x;
int y;
p1() {...}

另一个模块B:

double x;
p2() {...}

我的教科书说'在 p2 中写入 x 可能会覆盖 y' 我可以理解教科书的想法(double x 是 int x 大小的两倍,int y 放在 int x 之后,问题来了),但仍然迷失了细节,我知道何时有多个弱符号,链接器只会随机选择一个,所以我的问题是,链接器选择的模块的哪个 x 将导致写入 p2 中的 x 将覆盖 y。

这是我的理解:如果链接器选择模块A的int x会导致结果,因为那样x,y都是4个字节,p2(编译后的图像)是一个汇编代码 movq 与 p1 中的 movl 相比)将更改 8 个字节,因此覆盖 y。

但是我的导师说如果只有链接器选择模块B的双x,那会导致y覆盖,为什么,我是正确的还是我的导师是正确的?

【问题讨论】:

  • 为什么老师会这样讲废话?这些不是弱符号,除非您正在为具有此类错误的软件编写漏洞利用程序,否则发生什么并不重要,因为否则它只是未定义的行为,您只是不这样做。

标签: c linker


【解决方案1】:

根据 ISO C,程序调用未定义的行为。所使用的外部名称必须在程序中的某处具有完全相同的定义。*

“弱符号”是一些动态库系统中的一个概念,例如 GNU/Linux 上的 ELF。该术语不适用于此处。允许对外部符号进行多个定义的链接器据说正在实现“宽松的 ref/def”模型。该术语来自ANSI C rationale 的第 6.1.2.2 节。

如果我们将宽松的 ref/def 模型视为文档化的语言扩展,那么名称的多个定义将成为本地定义的行为。但是,如果它们的类型不一致怎么办?几乎可以肯定的是,这种情况类似于错误的类型别名。如果一个模块具有int x; int y; 而另一个模块具有double x,则通过double x 别名的写入可能会破坏y。这不是您可以便携式依赖的东西。故意获得混叠效果是一种非常糟糕的方法;您想在两个结构或类似结构之间使用union

现在关于“弱符号”:它们是共享库中的外部名称,可以被替代定义覆盖。例如,GNU/Linux 系统上的 GNU C 库中的大多数函数都是弱符号。例如,程序可以定义自己的read 函数来替换 POSIX 函数。无论read如何重新定义,库本身都不会损坏;当它需要调用read时,它不使用弱符号read,而是使用一些内部别名,如__libc_read。 这种机制很重要;它允许库符合 ISO C。允许严格符合 ISO C 程序使用read 作为外部名称。


* 在 ISO C99 标准中,这在 6.9 外部定义中给出:“如果用外部链接声明的标识符在表达式中使用(而不是作为sizeof 运算符,其结果是一个整数常量),在整个程序的某处,该标识符的外部定义应恰好有一个;否则,不应超过一个。”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 2014-10-19
    • 1970-01-01
    • 2017-09-20
    • 2012-10-16
    相关资源
    最近更新 更多