1

我有一个链接器脚本:

SECTIONS
{
  .text 0x42000:
  {
    *(.text*)
  }

  aligned_dot = ALIGN(0x10 * 1024);  

  .data aligned_dot :
  {
    *(.data*)
  }
}

如果我使用它链接一个(非常简单的)文件,它会给出我所期望的:

Sections:
Idx Name          Size      Address          Type
  0               00000000 0000000000000000 
  1 .text         00000008 0000000000042000 TEXT DATA 
  2 .data         00000000 0000000000044000 TEXT BSS

并且aligned_dot是:

00044000 A aligned_dot

但是,我想使用这样的MEMORY命令:

MEMORY
{
  ram (wxa) : ORIGIN = 0x42000, LENGTH = 0x100000
}

SECTIONS
{
  .text :
  {
    *(.text*)
  }

  aligned_dot = ALIGN(0x10 * 1024);  

  .data aligned_dot :
  {
    *(.data*)
  }
}

当我使用此脚本链接时,该部分的地址似乎.data被忽略了!

Sections:
Idx Name          Size      Address          Type
  0               00000000 0000000000000000 
  1 .text         00000008 0000000000042000 TEXT DATA 
  2 .data         00000000 0000000000042008 TEXT BSS

即使仍然aligned_dot是:

00044000 A aligned_dot

这很奇怪吧?到底是怎么回事?这是使用 Clang 的 LLD。

4

1 回答 1

0

我认为这可能是 LLVM 中的一个错误。在LinkerScript.cpp我们有:

void LinkerScript::assignOffsets(OutputSection *Sec) {
  if (!(Sec->Flags & SHF_ALLOC))
    Dot = 0;
  else if (Sec->AddrExpr)
    setDot(Sec->AddrExpr, Sec->Location, false);

  Ctx->MemRegion = Sec->MemRegion;
  Ctx->LMARegion = Sec->LMARegion;
  if (Ctx->MemRegion)
    Dot = Ctx->MemRegion->CurPos;

在我看来,它忽略了AddrExprifMemRegion设置。如果我将倒数第二行更改为此,则它可以正常工作:

  if (Ctx->MemRegion && !Sec->AddrExpr)

编辑:如果在您的手动地址之后有部分,这似乎还不够。你需要这样的东西,虽然我对此更不确定:

void LinkerScript::assignOffsets(OutputSection *Sec) {

  if (!(Sec->Flags & SHF_ALLOC))
    Dot = 0;
  else if (Sec->AddrExpr)
    setDot(Sec->AddrExpr, Sec->Location, false);

  Ctx->MemRegion = Sec->MemRegion;
  Ctx->LMARegion = Sec->LMARegion;
  if (Ctx->MemRegion && !Sec->AddrExpr)
    Dot = Ctx->MemRegion->CurPos;

  switchTo(Sec);

  if (Ctx->MemRegion && Sec->AddrExpr) {
    if (Ctx->MemRegion->CurPos < Dot) {
      expandMemoryRegions(Dot - Ctx->MemRegion->CurPos);
    }
  }
于 2018-06-18T13:23:27.347 回答