使用 MEMORY 时忽略的段地址
Section address ignored when using MEMORY
我有一个 linker 脚本:
SECTIONS
{
.text 0x42000:
{
*(.text*)
}
aligned_dot = ALIGN(0x10 * 1024);
.data aligned_dot :
{
*(.data*)
}
}
如果我 link 一个(非常简单的)文件使用它它给出了我所期望的:
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*)
}
}
当我link使用这个脚本时,.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。
我认为这可能是 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;
在我看来,如果设置了 MemRegion
,它会忽略 AddrExpr
。如果我将倒数第二行更改为此,则它可以正常工作:
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);
}
}
我有一个 linker 脚本:
SECTIONS
{
.text 0x42000:
{
*(.text*)
}
aligned_dot = ALIGN(0x10 * 1024);
.data aligned_dot :
{
*(.data*)
}
}
如果我 link 一个(非常简单的)文件使用它它给出了我所期望的:
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*)
}
}
当我link使用这个脚本时,.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。
我认为这可能是 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;
在我看来,如果设置了 MemRegion
,它会忽略 AddrExpr
。如果我将倒数第二行更改为此,则它可以正常工作:
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);
}
}