[PATCH] D34345: [LLD][ELF] Extract temporary state used in assignAddresses()
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 6 09:01:15 PDT 2017
LGTM
Peter Smith via Phabricator <reviews at reviews.llvm.org> writes:
> peter.smith updated this revision to Diff 105398.
> peter.smith retitled this revision from "[LLD][ELF] Reset any accumulated state before calculating addresses" to "[LLD][ELF] Extract temporary state used in assignAddresses()".
> peter.smith edited the summary of this revision.
> peter.smith added a comment.
>
> I've updated to follow Rafael's suggestion to extract the state into a separate struct. The diff is mostly a replace Cur<State> with CurAddressState-><State>.
>
>
> https://reviews.llvm.org/D34345
>
> Files:
> ELF/LinkerScript.cpp
> ELF/LinkerScript.h
> ELF/ScriptParser.cpp
>
> Index: ELF/ScriptParser.cpp
> ===================================================================
> --- ELF/ScriptParser.cpp
> +++ ELF/ScriptParser.cpp
> @@ -1191,8 +1191,7 @@
> if (It != Script->Opt.MemoryRegions.end())
> setError("region '" + Name + "' already defined");
> else
> - Script->Opt.MemoryRegions[Name] = {Name, Origin, Length,
> - Origin, Flags, NegFlags};
> + Script->Opt.MemoryRegions[Name] = {Name, Origin, Length, Flags, NegFlags};
> }
> }
>
> Index: ELF/LinkerScript.h
> ===================================================================
> --- ELF/LinkerScript.h
> +++ ELF/LinkerScript.h
> @@ -110,7 +110,6 @@
> std::string Name;
> uint64_t Origin;
> uint64_t Length;
> - uint64_t Offset;
> uint32_t Flags;
> uint32_t NegFlags;
> };
> @@ -226,6 +225,17 @@
> };
>
> class LinkerScript final {
> + // Temporary state used in processCommands() and assignAddresses()
> + // that must be reinitialized for each call to the above functions, and must
> + // not be used outside of the scope of a call to the above functions.
> + struct AddressState {
> + uint64_t ThreadBssOffset = 0;
> + OutputSection *OutSec = nullptr;
> + MemoryRegion *MemRegion = nullptr;
> + llvm::DenseMap<const MemoryRegion *, uint64_t> MemRegionOffset;
> + std::function<uint64_t()> LMAOffset;
> + AddressState(const ScriptConfiguration &Opt);
> + };
> llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
> llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand;
>
> @@ -248,14 +258,10 @@
> void output(InputSection *Sec);
> void process(BaseCommand &Base);
>
> + AddressState *CurAddressState = nullptr;
> OutputSection *Aether;
>
> uint64_t Dot;
> - uint64_t ThreadBssOffset = 0;
> -
> - std::function<uint64_t()> LMAOffset;
> - OutputSection *CurOutSec = nullptr;
> - MemoryRegion *CurMemRegion = nullptr;
>
> public:
> bool ErrorOnMissingSection = false;
> Index: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -114,14 +114,14 @@
> if (Val < Dot) {
> if (InSec)
> error(Loc + ": unable to move location counter backward for: " +
> - CurOutSec->Name);
> + CurAddressState->OutSec->Name);
> else
> error(Loc + ": unable to move location counter backward");
> }
> Dot = Val;
> // Update to location counter means update to section size.
> if (InSec)
> - CurOutSec->Size = Dot - CurOutSec->Addr;
> + CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr;
> }
>
> // Sets value of a symbol. Two kinds of symbols are processed: synthetic
> @@ -373,7 +373,9 @@
> // which will map to whatever the first actual section is.
> Aether = make<OutputSection>("", 0, SHF_ALLOC);
> Aether->SectionIndex = 1;
> - CurOutSec = Aether;
> + auto State = make_unique<AddressState>(Opt);
> + CurAddressState = State.get();
> + CurAddressState->OutSec = Aether;
> Dot = 0;
>
> for (size_t I = 0; I < Opt.Commands.size(); ++I) {
> @@ -435,7 +437,6 @@
> }
> }
> }
> - CurOutSec = nullptr;
> }
>
> void LinkerScript::fabricateDefaultCommands() {
> @@ -521,54 +522,58 @@
> }
>
> uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) {
> - bool IsTbss = (CurOutSec->Flags & SHF_TLS) && CurOutSec->Type == SHT_NOBITS;
> - uint64_t Start = IsTbss ? Dot + ThreadBssOffset : Dot;
> + bool IsTbss = (CurAddressState->OutSec->Flags & SHF_TLS) &&
> + CurAddressState->OutSec->Type == SHT_NOBITS;
> + uint64_t Start = IsTbss ? Dot + CurAddressState->ThreadBssOffset : Dot;
> Start = alignTo(Start, Align);
> uint64_t End = Start + Size;
>
> if (IsTbss)
> - ThreadBssOffset = End - Dot;
> + CurAddressState->ThreadBssOffset = End - Dot;
> else
> Dot = End;
> return End;
> }
>
> void LinkerScript::output(InputSection *S) {
> uint64_t Pos = advance(S->getSize(), S->Alignment);
> - S->OutSecOff = Pos - S->getSize() - CurOutSec->Addr;
> + S->OutSecOff = Pos - S->getSize() - CurAddressState->OutSec->Addr;
>
> // Update output section size after adding each section. This is so that
> // SIZEOF works correctly in the case below:
> // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
> - CurOutSec->Size = Pos - CurOutSec->Addr;
> + CurAddressState->OutSec->Size = Pos - CurAddressState->OutSec->Addr;
>
> // If there is a memory region associated with this input section, then
> // place the section in that region and update the region index.
> - if (CurMemRegion) {
> - CurMemRegion->Offset += CurOutSec->Size;
> - uint64_t CurSize = CurMemRegion->Offset - CurMemRegion->Origin;
> - if (CurSize > CurMemRegion->Length) {
> - uint64_t OverflowAmt = CurSize - CurMemRegion->Length;
> - error("section '" + CurOutSec->Name + "' will not fit in region '" +
> - CurMemRegion->Name + "': overflowed by " + Twine(OverflowAmt) +
> - " bytes");
> + if (CurAddressState->MemRegion) {
> + uint64_t &CurOffset =
> + CurAddressState->MemRegionOffset[CurAddressState->MemRegion];
> + CurOffset += CurAddressState->OutSec->Size;
> + uint64_t CurSize = CurOffset - CurAddressState->MemRegion->Origin;
> + if (CurSize > CurAddressState->MemRegion->Length) {
> + uint64_t OverflowAmt = CurSize - CurAddressState->MemRegion->Length;
> + error("section '" + CurAddressState->OutSec->Name +
> + "' will not fit in region '" + CurAddressState->MemRegion->Name +
> + "': overflowed by " + Twine(OverflowAmt) + " bytes");
> }
> }
> }
>
> void LinkerScript::switchTo(OutputSection *Sec) {
> - if (CurOutSec == Sec)
> + if (CurAddressState->OutSec == Sec)
> return;
>
> - CurOutSec = Sec;
> - CurOutSec->Addr = advance(0, CurOutSec->Alignment);
> + CurAddressState->OutSec = Sec;
> + CurAddressState->OutSec->Addr =
> + advance(0, CurAddressState->OutSec->Alignment);
>
> // If neither AT nor AT> is specified for an allocatable section, the linker
> // will set the LMA such that the difference between VMA and LMA for the
> // section is the same as the preceding output section in the same region
> // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
> - if (LMAOffset)
> - CurOutSec->LMAOffset = LMAOffset();
> + if (CurAddressState->LMAOffset)
> + CurAddressState->OutSec->LMAOffset = CurAddressState->LMAOffset();
> }
>
> void LinkerScript::process(BaseCommand &Base) {
> @@ -580,9 +585,9 @@
>
> // Handle BYTE(), SHORT(), LONG(), or QUAD().
> if (auto *Cmd = dyn_cast<BytesDataCommand>(&Base)) {
> - Cmd->Offset = Dot - CurOutSec->Addr;
> + Cmd->Offset = Dot - CurAddressState->OutSec->Addr;
> Dot += Cmd->Size;
> - CurOutSec->Size = Dot - CurOutSec->Addr;
> + CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr;
> return;
> }
>
> @@ -607,7 +612,7 @@
>
> if (!Sec->Live)
> continue;
> - assert(CurOutSec == Sec->getParent());
> + assert(CurAddressState->OutSec == Sec->getParent());
> output(Sec);
> }
> }
> @@ -660,17 +665,17 @@
>
> if (Cmd->LMAExpr) {
> uint64_t D = Dot;
> - LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; };
> + CurAddressState->LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; };
> }
>
> - CurMemRegion = Cmd->MemRegion;
> - if (CurMemRegion)
> - Dot = CurMemRegion->Offset;
> + CurAddressState->MemRegion = Cmd->MemRegion;
> + if (CurAddressState->MemRegion)
> + Dot = CurAddressState->MemRegionOffset[CurAddressState->MemRegion];
> switchTo(Sec);
>
> // We do not support custom layout for compressed debug sectons.
> // At this point we already know their size and have compressed content.
> - if (CurOutSec->Flags & SHF_COMPRESSED)
> + if (CurAddressState->OutSec->Flags & SHF_COMPRESSED)
> return;
>
> for (BaseCommand *C : Cmd->Commands)
> @@ -827,9 +832,18 @@
> Phdrs.erase(PhdrI);
> }
>
> +LinkerScript::AddressState::AddressState(const ScriptConfiguration &Opt) {
> + for (auto &MRI : Opt.MemoryRegions) {
> + const MemoryRegion *MR = &MRI.second;
> + MemRegionOffset[MR] = MR->Origin;
> + }
> +}
> +
> void LinkerScript::assignAddresses() {
> // Assign addresses as instructed by linker script SECTIONS sub-commands.
> Dot = 0;
> + auto State = make_unique<AddressState>(Opt);
> + CurAddressState = State.get();
> ErrorOnMissingSection = true;
> switchTo(Aether);
>
> @@ -1163,7 +1177,7 @@
>
> ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
> if (S == ".")
> - return {CurOutSec, Dot - CurOutSec->Addr, Loc};
> + return {CurAddressState->OutSec, Dot - CurAddressState->OutSec->Addr, Loc};
> if (SymbolBody *B = findSymbol(S)) {
> if (auto *D = dyn_cast<DefinedRegular>(B))
> return {D->Section, D->Value, Loc};
More information about the llvm-commits
mailing list