1

编辑:已解决 - 应用于静态数据部分的链接器脚本属性“SUBALIGN(32)”完全符合我的要求,强制每个链接的目标文件与 32 字节边界对齐,并自动插入填充。

__bss_start = .;  
.bss            :  
SUBALIGN(32)  
{  
  *(.dynbss)  
  *(.bss .bss.* .gnu.linkonce.b.*)  
  *(COMMON)  
      SORT(CONSTRUCTORS)  
  . = ALIGN(32);  
} = 0  
  . = ALIGN(32);  

我正在缓存不连贯架构上构建多程序基准测试,该架构由重命名并链接在一起的 EEMBC 套件的多个实例组成。

问题是库在可写数据段中没有对齐缓存线,我在这里遇到数据损坏(通过连贯模拟中的缓存线抖动来证明)。

例如,0x7500 处的缓存行在 Viterb0 和 Viterb1 上运行的内核之间共享,映射输出表明这是库 0 运行到库 1 开始的缓存行的位置:

...  
 .bss           0x000068e8      0xc24 ../EEMBClib/libmark_0.a(renamed_renamed_viterb00_viterb00.o)  
 .bss           0x0000750c        0x4 ../EEMBClib/libmark_1.a(renamed_renamed_viterb00_bmark_lite.o)  
...  

我需要将各个数据段中链接的每个目标文件对齐到32字节的边界,我只知道如何对齐整个部分,当前的.bss部分是:

  __bss_start = .;  
  .bss            :  
  {  
    *(.dynbss)  
    *(.bss .bss.* .gnu.linkonce.b.*)  
    *(COMMON)  
        SORT(CONSTRUCTORS)  
    . = ALIGN(32);  
  } = 0  
    . = ALIGN(32);  

任何帮助在这里将不胜感激,使用填充重建库并不是我真正想要考虑的选项,因为我希望这个更强大的解决方案用于该平台上的未来链接目的。

4

2 回答 2

3

解决方案是链接描述文件属性“SUBALIGN(32)”。当应用于静态数据部分时,这完全符合我的要求,强制链接的每个目标文件与 32 字节边界对齐,并自动插入填充。

__bss_start = .;  
.bss            :  
SUBALIGN(32)  
{  
  *(.bss .bss.* .gnu.linkonce.b.*)
} = 0  
  . = ALIGN(32);  

给出固定结果

.bss 0x00006940 0xc24 ../EEMBClib/libmark_0.a(renamed_renamed_viterb00_viterb00.o)
fill 0x00007564 0x1c 00000000
.bss 0x00007580 0x4 ../EEMBClib/libmark_1.a(renamed_renamed_viterb00_bmark_lite.o)

代替

.bss           0x000068e8      0xc24 ../EEMBClib/libmark_0.a(renamed_renamed_viterb00_viterb00.o)  
.bss           0x0000750c        0x4 ../EEMBClib/libmark_1.a(renamed_renamed_viterb00_bmark_lite.o) 
于 2013-05-06T15:40:38.357 回答
1

(抱歉,这至少是目前的想法集合而不是具体答案,但在评论中发布会有点长)

可能值得做的第一件事是提出一些验证例程来解析 objdump/readelf 输出以验证是否满足对齐要求,并将其放入构建过程中作为检查。如果您不能在编译时执行此操作,则至少将其作为运行时检查。

然后可以研究一些实现对齐的路径。

假设创建了一个自定义部分,并且所有具有此要求的数据都与源代码中的编译指示一起放置在那里。如果链接器愿意遵守在每个目标文件中该节的出现中给出的节对齐设置,那么需要研究的内容。例如,您可以对其中一个对象进行十六进制编辑以增加对齐并使用转储处理器来查看发生了什么。如果这成功了,那就太好了——这似乎是处理任务的正确方法,并且希望有一种合理的方法来指定该部分的对齐大小要求,该部分最终将出现在目标文件中。

另一个想法是尝试某种脚本分配调整。例如,使用 objcopy 将所有适用的部分连接到一个文件中,同时将它们从其他部分中剥离出来。分析文件并找出您想要的分配,然后使用 objcopy 或自定义 elf 修改程序进行设置。也许您甚至可以对完全链接的结果进行此修改,至少如果您的链接器脚本将特殊部分放在最后,这样您就不必在增长时将其他分配移开以实现内部对齐。

如果您不想修改精灵,另一种使用脚本进行自己的辅助链接的方法可能是计算特殊部分中每个对象数据的大小,然后自动生成一个简单地填充该部分的附加对象文件到下一个对齐边界。然后,您的链接阶段将在列表中指定对象:program1.o padding1.o program2.o padding2.o

或者,您可以让每个程序将其特殊数据放在其自己唯一命名的链接器部分中。转储所有这些的大小,找出你想要它们的位置,然后让脚本创建一个自定义的链接器脚本,它将命名的部分明确地放在刚刚确定的位置。

于 2013-05-01T21:21:35.993 回答