是否可以强制 GCC 在 .rodata 中填充字符串常量

Is it possible to force GCC to pad string constants in .rodata

我正在努力将一些代码移植到对齐要求比 x86 更严格的环境中,但由于这个原因,我暂时 changing/testing 在 x86 Linux 机器上由于硬件访问等原因,更容易。

我已经将 运行 的第一个问题提炼成以下简明示例:

#include <stdio.h>
#include <string.h>

#define BUFFER_SIZE 1024
#define DMQUOTE_LOG "DMQUOTELOG"

void aFunction (const char *configPath)
{
    char LogFilename[BUFFER_SIZE] __attribute ((aligned));

//     printf ("A\n");
    strcpy (LogFilename, configPath);
    strcat (LogFilename, DMQUOTE_LOG);

    printf ("Log: %s\n", LogFilename);
}

int main (int argc, char **argv)
{
    __asm__("pushf\n"  
            "orl [=10=]x40000, (%esp)\n"  
            "popf");  

    aFunction ("");

    return 0;
}

运行 此代码按原样提供了预期的输出。但是,取消注释其他 printf 会导致在 strcat 行上触发总线错误。

在我看来,原因似乎是通过引入第二个字符串常量,定义中的常量被移动,因此它没有对齐。这是因为注意到如果字符串常量从 "A\n" 更改为 "AAA\n",一切都会再次工作(并且 gcc 神奇地将对 printf 的调用替换为对 puts 的调用,并从常量中删除 \n ).

有没有什么好的方法可以让 gcc 在它插入到 .rodata 部分的所有字符串常量之间插入额外的填充,以便正确对齐?

[编辑]

如下面的 fucanchik 所述,上面的 .rodata 部分是什么(启用了额外的 printf):

    .file   "sample.c"
    .section    .rodata
.LC0:
    .string "A"
.LC1:
    .string "DMQUOTELOG"
.LC2:
    .string "Log: %s\n"
    .text
.globl aFunction
...

没有强制对齐,这是有道理的,因为我是在 x86 下编译的,x86 并不严格要求它。自然地,将汇编程序修改为此具有预期的效果。但是,我看不到让 gcc 在运行中自行应用它的方法。不过,如果在一般情况下 glibc 本身无法处理 运行 这种模式,这当然可能没有实际意义。

    .file   "sample.c"
    .section    .rodata
.LC0:
    .string "A"
    .align 4,0
.LC1:
    .string "DMQUOTELOG"
.LC2:
    .string "Log: %s\n"
    .text
.globl aFunction
...

似乎没有任何方法可以做到这一点,至少在 GCC 中是这样。测试似乎表明,虽然编译器会对齐整数、双精度数等,但由于字符串常量由字符组成,而字符数据的对齐是在字节边界上,编译器觉得不需要对齐它们。

这个总线错误的细节似乎表明 glibc 使用优化的例程,一次复制数据字而不先检查对齐(没有查看源代码,我不知道这是不是真的然而)。

这让我开始研究 musl,一个替代的 libc 实现,它很容易按项目安装和使用 basis.The strcat 的 musl 版本的 C 源代码注意复制一次复制单词之前未对齐的字节,因此这个特定的问题消失了,尽管自然而然地其他问题仍然存在。