1

I have a linker script:

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

  aligned_dot = ALIGN(0x10 * 1024);  

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

If I link a (very simple) file using this it gives what I would expect:

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

And aligned_dot is:

00044000 A aligned_dot

However, I'd like to use a MEMORY command like this:

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

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

  aligned_dot = ALIGN(0x10 * 1024);  

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

When I link using this script, it seems like the address of the .data section is ignored!

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

Even though aligned_dot is still:

00044000 A aligned_dot

That is weird right? What is going on? This is using Clang's LLD.

Timmmm
  • 88,195
  • 71
  • 364
  • 509

1 Answers1

0

I think this might be a bug in LLVM. In LinkerScript.cpp we have:

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;

Which looks to me like it ignores the AddrExpr if MemRegion is set. If I change the penultimate line to this then it works fine:

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

Edit: Seems like this was not enough if there are sections after your manually address one. You need something like this, though I am even less sure about this:

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);
    }
  }
Timmmm
  • 88,195
  • 71
  • 364
  • 509