forked from OSchip/llvm-project
				
			Move writeTo to OutputSectionCommand.
This reduces how many times we have to map from OutputSection to OutputSectionCommand. It is a required step to moving clearOutputSections earlier. In order to always use writeTo in OutputSectionCommand we have to call fabricateDefaultCommands for -r links and move section compression after it. llvm-svn: 303784
This commit is contained in:
		
							parent
							
								
									c98741c79e
								
							
						
					
					
						commit
						55b169bf5d
					
				| 
						 | 
					@ -20,6 +20,8 @@
 | 
				
			||||||
#include "SymbolTable.h"
 | 
					#include "SymbolTable.h"
 | 
				
			||||||
#include "Symbols.h"
 | 
					#include "Symbols.h"
 | 
				
			||||||
#include "SyntheticSections.h"
 | 
					#include "SyntheticSections.h"
 | 
				
			||||||
 | 
					#include "Target.h"
 | 
				
			||||||
 | 
					#include "Threads.h"
 | 
				
			||||||
#include "Writer.h"
 | 
					#include "Writer.h"
 | 
				
			||||||
#include "llvm/ADT/STLExtras.h"
 | 
					#include "llvm/ADT/STLExtras.h"
 | 
				
			||||||
#include "llvm/ADT/StringRef.h"
 | 
					#include "llvm/ADT/StringRef.h"
 | 
				
			||||||
| 
						 | 
					@ -198,6 +200,15 @@ bool OutputSectionCommand::classof(const BaseCommand *C) {
 | 
				
			||||||
  return C->Kind == OutputSectionKind;
 | 
					  return C->Kind == OutputSectionKind;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Fill [Buf, Buf + Size) with Filler.
 | 
				
			||||||
 | 
					// This is used for linker script "=fillexp" command.
 | 
				
			||||||
 | 
					static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
 | 
				
			||||||
 | 
					  size_t I = 0;
 | 
				
			||||||
 | 
					  for (; I + 4 < Size; I += 4)
 | 
				
			||||||
 | 
					    memcpy(Buf + I, &Filler, 4);
 | 
				
			||||||
 | 
					  memcpy(Buf + I, &Filler, Size - I);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool InputSectionDescription::classof(const BaseCommand *C) {
 | 
					bool InputSectionDescription::classof(const BaseCommand *C) {
 | 
				
			||||||
  return C->Kind == InputSectionKind;
 | 
					  return C->Kind == InputSectionKind;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1032,10 +1043,12 @@ OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const {
 | 
				
			||||||
  return I->second;
 | 
					  return I->second;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Optional<uint32_t> LinkerScript::getFiller(OutputSection *Sec) {
 | 
					uint32_t OutputSectionCommand::getFiller() {
 | 
				
			||||||
  if (OutputSectionCommand *Cmd = getCmd(Sec))
 | 
					  if (Filler)
 | 
				
			||||||
    return Cmd->Filler;
 | 
					    return *Filler;
 | 
				
			||||||
  return None;
 | 
					  if (Sec->Flags & SHF_EXECINSTR)
 | 
				
			||||||
 | 
					    return Target->TrapInstr;
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
 | 
					static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
 | 
				
			||||||
| 
						 | 
					@ -1051,9 +1064,43 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
 | 
				
			||||||
    llvm_unreachable("unsupported Size argument");
 | 
					    llvm_unreachable("unsupported Size argument");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) {
 | 
					template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
 | 
				
			||||||
  if (OutputSectionCommand *Cmd = getCmd(Sec))
 | 
					  Sec->Loc = Buf;
 | 
				
			||||||
    for (BaseCommand *Base : Cmd->Commands)
 | 
					
 | 
				
			||||||
 | 
					  // We may have already rendered compressed content when using
 | 
				
			||||||
 | 
					  // -compress-debug-sections option. Write it together with header.
 | 
				
			||||||
 | 
					  if (!Sec->CompressedData.empty()) {
 | 
				
			||||||
 | 
					    memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size());
 | 
				
			||||||
 | 
					    memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(),
 | 
				
			||||||
 | 
					           Sec->CompressedData.size());
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Write leading padding.
 | 
				
			||||||
 | 
					  ArrayRef<InputSection *> Sections = Sec->Sections;
 | 
				
			||||||
 | 
					  uint32_t Filler = getFiller();
 | 
				
			||||||
 | 
					  if (Filler)
 | 
				
			||||||
 | 
					    fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  parallelForEachN(0, Sections.size(), [=](size_t I) {
 | 
				
			||||||
 | 
					    InputSection *IS = Sections[I];
 | 
				
			||||||
 | 
					    IS->writeTo<ELFT>(Buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fill gaps between sections.
 | 
				
			||||||
 | 
					    if (Filler) {
 | 
				
			||||||
 | 
					      uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
 | 
				
			||||||
 | 
					      uint8_t *End;
 | 
				
			||||||
 | 
					      if (I + 1 == Sections.size())
 | 
				
			||||||
 | 
					        End = Buf + Sec->Size;
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        End = Buf + Sections[I + 1]->OutSecOff;
 | 
				
			||||||
 | 
					      fill(Start, End - Start, Filler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Linker scripts may have BYTE()-family commands with which you
 | 
				
			||||||
 | 
					  // can write arbitrary bytes to the output. Process them if any.
 | 
				
			||||||
 | 
					  for (BaseCommand *Base : Commands)
 | 
				
			||||||
    if (auto *Data = dyn_cast<BytesDataCommand>(Base))
 | 
					    if (auto *Data = dyn_cast<BytesDataCommand>(Base))
 | 
				
			||||||
      writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
 | 
					      writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1102,3 +1149,8 @@ size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) {
 | 
				
			||||||
  error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");
 | 
					  error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");
 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf);
 | 
				
			||||||
 | 
					template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf);
 | 
				
			||||||
 | 
					template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf);
 | 
				
			||||||
 | 
					template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,6 +130,9 @@ struct OutputSectionCommand : BaseCommand {
 | 
				
			||||||
  ConstraintKind Constraint = ConstraintKind::NoConstraint;
 | 
					  ConstraintKind Constraint = ConstraintKind::NoConstraint;
 | 
				
			||||||
  std::string Location;
 | 
					  std::string Location;
 | 
				
			||||||
  std::string MemoryRegionName;
 | 
					  std::string MemoryRegionName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template <class ELFT> void writeTo(uint8_t *Buf);
 | 
				
			||||||
 | 
					  uint32_t getFiller();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This struct represents one section match pattern in SECTIONS() command.
 | 
					// This struct represents one section match pattern in SECTIONS() command.
 | 
				
			||||||
| 
						 | 
					@ -213,7 +216,6 @@ struct ScriptConfiguration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LinkerScript final {
 | 
					class LinkerScript final {
 | 
				
			||||||
  llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
 | 
					  llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
 | 
				
			||||||
  OutputSectionCommand *getCmd(OutputSection *Sec) const;
 | 
					 | 
				
			||||||
  void assignSymbol(SymbolAssignment *Cmd, bool InSec);
 | 
					  void assignSymbol(SymbolAssignment *Cmd, bool InSec);
 | 
				
			||||||
  void setDot(Expr E, const Twine &Loc, bool InSec);
 | 
					  void setDot(Expr E, const Twine &Loc, bool InSec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -244,6 +246,7 @@ class LinkerScript final {
 | 
				
			||||||
  MemoryRegion *CurMemRegion = nullptr;
 | 
					  MemoryRegion *CurMemRegion = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					  OutputSectionCommand *getCmd(OutputSection *Sec) const;
 | 
				
			||||||
  bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
 | 
					  bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
 | 
				
			||||||
  uint64_t getDot() { return Dot; }
 | 
					  uint64_t getDot() { return Dot; }
 | 
				
			||||||
  OutputSection *getOutputSection(const Twine &Loc, StringRef S);
 | 
					  OutputSection *getOutputSection(const Twine &Loc, StringRef S);
 | 
				
			||||||
| 
						 | 
					@ -263,7 +266,6 @@ public:
 | 
				
			||||||
  std::vector<PhdrEntry> createPhdrs();
 | 
					  std::vector<PhdrEntry> createPhdrs();
 | 
				
			||||||
  bool ignoreInterpSection();
 | 
					  bool ignoreInterpSection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  llvm::Optional<uint32_t> getFiller(OutputSection *Sec);
 | 
					 | 
				
			||||||
  bool hasLMA(OutputSection *Sec);
 | 
					  bool hasLMA(OutputSection *Sec);
 | 
				
			||||||
  bool shouldKeep(InputSectionBase *S);
 | 
					  bool shouldKeep(InputSectionBase *S);
 | 
				
			||||||
  void assignOffsets(OutputSectionCommand *Cmd);
 | 
					  void assignOffsets(OutputSectionCommand *Cmd);
 | 
				
			||||||
| 
						 | 
					@ -272,7 +274,6 @@ public:
 | 
				
			||||||
  void synchronize();
 | 
					  void synchronize();
 | 
				
			||||||
  void assignAddresses(std::vector<PhdrEntry> &Phdrs);
 | 
					  void assignAddresses(std::vector<PhdrEntry> &Phdrs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void writeDataBytes(OutputSection *Sec, uint8_t *Buf);
 | 
					 | 
				
			||||||
  void addSymbol(SymbolAssignment *Cmd);
 | 
					  void addSymbol(SymbolAssignment *Cmd);
 | 
				
			||||||
  void processCommands(OutputSectionFactory &Factory);
 | 
					  void processCommands(OutputSectionFactory &Factory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@ template <class ELFT> void OutputSection::maybeCompress() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Write section contents to a temporary buffer and compress it.
 | 
					  // Write section contents to a temporary buffer and compress it.
 | 
				
			||||||
  std::vector<uint8_t> Buf(Size);
 | 
					  std::vector<uint8_t> Buf(Size);
 | 
				
			||||||
  writeTo<ELFT>(Buf.data());
 | 
					  Script->getCmd(this)->writeTo<ELFT>(Buf.data());
 | 
				
			||||||
  if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
 | 
					  if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
 | 
				
			||||||
    fatal("compress failed: " + llvm::toString(std::move(E)));
 | 
					    fatal("compress failed: " + llvm::toString(std::move(E)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,65 +259,6 @@ void OutputSection::sortCtorsDtors() {
 | 
				
			||||||
  std::stable_sort(Sections.begin(), Sections.end(), compCtors);
 | 
					  std::stable_sort(Sections.begin(), Sections.end(), compCtors);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Fill [Buf, Buf + Size) with Filler.
 | 
					 | 
				
			||||||
// This is used for linker script "=fillexp" command.
 | 
					 | 
				
			||||||
static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
 | 
					 | 
				
			||||||
  size_t I = 0;
 | 
					 | 
				
			||||||
  for (; I + 4 < Size; I += 4)
 | 
					 | 
				
			||||||
    memcpy(Buf + I, &Filler, 4);
 | 
					 | 
				
			||||||
  memcpy(Buf + I, &Filler, Size - I);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t OutputSection::getFiller() {
 | 
					 | 
				
			||||||
  // Determine what to fill gaps between InputSections with, as specified by the
 | 
					 | 
				
			||||||
  // linker script. If nothing is specified and this is an executable section,
 | 
					 | 
				
			||||||
  // fall back to trap instructions to prevent bad diassembly and detect invalid
 | 
					 | 
				
			||||||
  // jumps to padding.
 | 
					 | 
				
			||||||
  if (Optional<uint32_t> Filler = Script->getFiller(this))
 | 
					 | 
				
			||||||
    return *Filler;
 | 
					 | 
				
			||||||
  if (Flags & SHF_EXECINSTR)
 | 
					 | 
				
			||||||
    return Target->TrapInstr;
 | 
					 | 
				
			||||||
  return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
 | 
					 | 
				
			||||||
  Loc = Buf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // We may have already rendered compressed content when using
 | 
					 | 
				
			||||||
  // -compress-debug-sections option. Write it together with header.
 | 
					 | 
				
			||||||
  if (!CompressedData.empty()) {
 | 
					 | 
				
			||||||
    memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size());
 | 
					 | 
				
			||||||
    memcpy(Buf + ZDebugHeader.size(), CompressedData.data(),
 | 
					 | 
				
			||||||
           CompressedData.size());
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Write leading padding.
 | 
					 | 
				
			||||||
  uint32_t Filler = getFiller();
 | 
					 | 
				
			||||||
  if (Filler)
 | 
					 | 
				
			||||||
    fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  parallelForEachN(0, Sections.size(), [=](size_t I) {
 | 
					 | 
				
			||||||
    InputSection *Sec = Sections[I];
 | 
					 | 
				
			||||||
    Sec->writeTo<ELFT>(Buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Fill gaps between sections.
 | 
					 | 
				
			||||||
    if (Filler) {
 | 
					 | 
				
			||||||
      uint8_t *Start = Buf + Sec->OutSecOff + Sec->getSize();
 | 
					 | 
				
			||||||
      uint8_t *End;
 | 
					 | 
				
			||||||
      if (I + 1 == Sections.size())
 | 
					 | 
				
			||||||
        End = Buf + Size;
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        End = Buf + Sections[I + 1]->OutSecOff;
 | 
					 | 
				
			||||||
      fill(Start, End - Start, Filler);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Linker scripts may have BYTE()-family commands with which you
 | 
					 | 
				
			||||||
  // can write arbitrary bytes to the output. Process them if any.
 | 
					 | 
				
			||||||
  Script->writeDataBytes(this, Buf);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static uint64_t getOutFlags(InputSectionBase *S) {
 | 
					static uint64_t getOutFlags(InputSectionBase *S) {
 | 
				
			||||||
  return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
 | 
					  return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -484,8 +425,3 @@ template void OutputSection::maybeCompress<ELF32LE>();
 | 
				
			||||||
template void OutputSection::maybeCompress<ELF32BE>();
 | 
					template void OutputSection::maybeCompress<ELF32BE>();
 | 
				
			||||||
template void OutputSection::maybeCompress<ELF64LE>();
 | 
					template void OutputSection::maybeCompress<ELF64LE>();
 | 
				
			||||||
template void OutputSection::maybeCompress<ELF64BE>();
 | 
					template void OutputSection::maybeCompress<ELF64BE>();
 | 
				
			||||||
 | 
					 | 
				
			||||||
template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf);
 | 
					 | 
				
			||||||
template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf);
 | 
					 | 
				
			||||||
template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf);
 | 
					 | 
				
			||||||
template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf);
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,8 +82,6 @@ public:
 | 
				
			||||||
  void sort(std::function<int(InputSectionBase *S)> Order);
 | 
					  void sort(std::function<int(InputSectionBase *S)> Order);
 | 
				
			||||||
  void sortInitFini();
 | 
					  void sortInitFini();
 | 
				
			||||||
  void sortCtorsDtors();
 | 
					  void sortCtorsDtors();
 | 
				
			||||||
  uint32_t getFiller();
 | 
					 | 
				
			||||||
  template <class ELFT> void writeTo(uint8_t *Buf);
 | 
					 | 
				
			||||||
  template <class ELFT> void finalize();
 | 
					  template <class ELFT> void finalize();
 | 
				
			||||||
  template <class ELFT> void maybeCompress();
 | 
					  template <class ELFT> void maybeCompress();
 | 
				
			||||||
  void assignOffsets();
 | 
					  void assignOffsets();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2175,11 +2175,10 @@ MipsRldMapSection::MipsRldMapSection()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MipsRldMapSection::writeTo(uint8_t *Buf) {
 | 
					void MipsRldMapSection::writeTo(uint8_t *Buf) {
 | 
				
			||||||
  // Apply filler from linker script.
 | 
					  // Apply filler from linker script.
 | 
				
			||||||
  Optional<uint32_t> Fill = Script->getFiller(this->OutSec);
 | 
					  uint64_t Filler = Script->getCmd(this->OutSec)->getFiller();
 | 
				
			||||||
  if (!Fill || *Fill == 0)
 | 
					  if (Filler == 0)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint64_t Filler = *Fill;
 | 
					 | 
				
			||||||
  Filler = (Filler << 32) | Filler;
 | 
					  Filler = (Filler << 32) | Filler;
 | 
				
			||||||
  memcpy(Buf, &Filler, getSize());
 | 
					  memcpy(Buf, &Filler, getSize());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,7 @@ private:
 | 
				
			||||||
  void addStartStopSymbols(OutputSection *Sec);
 | 
					  void addStartStopSymbols(OutputSection *Sec);
 | 
				
			||||||
  uint64_t getEntryAddr();
 | 
					  uint64_t getEntryAddr();
 | 
				
			||||||
  OutputSection *findSection(StringRef Name);
 | 
					  OutputSection *findSection(StringRef Name);
 | 
				
			||||||
 | 
					  OutputSectionCommand *findSectionInScript(StringRef Name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::vector<PhdrEntry> Phdrs;
 | 
					  std::vector<PhdrEntry> Phdrs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,13 +255,21 @@ template <class ELFT> void Writer<ELFT>::run() {
 | 
				
			||||||
  if (ErrorCount)
 | 
					  if (ErrorCount)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (Config->Relocatable) {
 | 
					 | 
				
			||||||
    assignFileOffsets();
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
  if (!Script->Opt.HasSections) {
 | 
					  if (!Script->Opt.HasSections) {
 | 
				
			||||||
 | 
					    if (!Config->Relocatable)
 | 
				
			||||||
      fixSectionAlignments();
 | 
					      fixSectionAlignments();
 | 
				
			||||||
    Script->fabricateDefaultCommands();
 | 
					    Script->fabricateDefaultCommands();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // If -compressed-debug-sections is specified, we need to compress
 | 
				
			||||||
 | 
					  // .debug_* sections. Do it right now because it changes the size of
 | 
				
			||||||
 | 
					  // output sections.
 | 
				
			||||||
 | 
					  parallelForEach(OutputSections.begin(), OutputSections.end(),
 | 
				
			||||||
 | 
					                  [](OutputSection *S) { S->maybeCompress<ELFT>(); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (Config->Relocatable) {
 | 
				
			||||||
 | 
					    assignFileOffsets();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
    Script->synchronize();
 | 
					    Script->synchronize();
 | 
				
			||||||
    Script->assignAddresses(Phdrs);
 | 
					    Script->assignAddresses(Phdrs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1246,12 +1255,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 | 
				
			||||||
  for (OutputSection *Sec : OutputSections)
 | 
					  for (OutputSection *Sec : OutputSections)
 | 
				
			||||||
    Sec->finalize<ELFT>();
 | 
					    Sec->finalize<ELFT>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If -compressed-debug-sections is specified, we need to compress
 | 
					 | 
				
			||||||
  // .debug_* sections. Do it right now because it changes the size of
 | 
					 | 
				
			||||||
  // output sections.
 | 
					 | 
				
			||||||
  parallelForEach(OutputSections.begin(), OutputSections.end(),
 | 
					 | 
				
			||||||
                  [](OutputSection *S) { S->maybeCompress<ELFT>(); });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // createThunks may have added local symbols to the static symbol table
 | 
					  // createThunks may have added local symbols to the static symbol table
 | 
				
			||||||
  applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab},
 | 
					  applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab},
 | 
				
			||||||
                 [](SyntheticSection *SS) { SS->postThunkContents(); });
 | 
					                 [](SyntheticSection *SS) { SS->postThunkContents(); });
 | 
				
			||||||
| 
						 | 
					@ -1304,6 +1307,15 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
 | 
				
			||||||
  addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
 | 
					  addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <class ELFT>
 | 
				
			||||||
 | 
					OutputSectionCommand *Writer<ELFT>::findSectionInScript(StringRef Name) {
 | 
				
			||||||
 | 
					  for (BaseCommand *Base : Script->Opt.Commands)
 | 
				
			||||||
 | 
					    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
 | 
				
			||||||
 | 
					      if (Cmd->Name == Name)
 | 
				
			||||||
 | 
					        return Cmd;
 | 
				
			||||||
 | 
					  return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
 | 
					template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
 | 
				
			||||||
  for (OutputSection *Sec : OutputSections)
 | 
					  for (OutputSection *Sec : OutputSections)
 | 
				
			||||||
    if (Sec->Name == Name)
 | 
					    if (Sec->Name == Name)
 | 
				
			||||||
| 
						 | 
					@ -1743,9 +1755,14 @@ template <class ELFT> void Writer<ELFT>::openFile() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
 | 
					template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
 | 
				
			||||||
  uint8_t *Buf = Buffer->getBufferStart();
 | 
					  uint8_t *Buf = Buffer->getBufferStart();
 | 
				
			||||||
  for (OutputSection *Sec : OutputSections)
 | 
					  for (BaseCommand *Base : Script->Opt.Commands) {
 | 
				
			||||||
 | 
					    auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
 | 
				
			||||||
 | 
					    if (!Cmd)
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    OutputSection *Sec = Cmd->Sec;
 | 
				
			||||||
    if (Sec->Flags & SHF_ALLOC)
 | 
					    if (Sec->Flags & SHF_ALLOC)
 | 
				
			||||||
      Sec->writeTo<ELFT>(Buf + Sec->Offset);
 | 
					      Cmd->writeTo<ELFT>(Buf + Sec->Offset);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Write section contents to a mmap'ed file.
 | 
					// Write section contents to a mmap'ed file.
 | 
				
			||||||
| 
						 | 
					@ -1754,10 +1771,10 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // PPC64 needs to process relocations in the .opd section
 | 
					  // PPC64 needs to process relocations in the .opd section
 | 
				
			||||||
  // before processing relocations in code-containing sections.
 | 
					  // before processing relocations in code-containing sections.
 | 
				
			||||||
  Out::Opd = findSection(".opd");
 | 
					  if (auto *OpdCmd = findSectionInScript(".opd")) {
 | 
				
			||||||
  if (Out::Opd) {
 | 
					    Out::Opd = OpdCmd->Sec;
 | 
				
			||||||
    Out::OpdBuf = Buf + Out::Opd->Offset;
 | 
					    Out::OpdBuf = Buf + Out::Opd->Offset;
 | 
				
			||||||
    Out::Opd->template writeTo<ELFT>(Buf + Out::Opd->Offset);
 | 
					    OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  OutputSection *EhFrameHdr =
 | 
					  OutputSection *EhFrameHdr =
 | 
				
			||||||
| 
						 | 
					@ -1766,19 +1783,31 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
 | 
				
			||||||
  // In -r or -emit-relocs mode, write the relocation sections first as in
 | 
					  // In -r or -emit-relocs mode, write the relocation sections first as in
 | 
				
			||||||
  // ELf_Rel targets we might find out that we need to modify the relocated
 | 
					  // ELf_Rel targets we might find out that we need to modify the relocated
 | 
				
			||||||
  // section while doing it.
 | 
					  // section while doing it.
 | 
				
			||||||
  for (OutputSection *Sec : OutputSections)
 | 
					  for (BaseCommand *Base : Script->Opt.Commands) {
 | 
				
			||||||
 | 
					    auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
 | 
				
			||||||
 | 
					    if (!Cmd)
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    OutputSection *Sec = Cmd->Sec;
 | 
				
			||||||
    if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
 | 
					    if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
 | 
				
			||||||
      Sec->writeTo<ELFT>(Buf + Sec->Offset);
 | 
					      Cmd->writeTo<ELFT>(Buf + Sec->Offset);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (OutputSection *Sec : OutputSections)
 | 
					  for (BaseCommand *Base : Script->Opt.Commands) {
 | 
				
			||||||
 | 
					    auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
 | 
				
			||||||
 | 
					    if (!Cmd)
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    OutputSection *Sec = Cmd->Sec;
 | 
				
			||||||
    if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
 | 
					    if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
 | 
				
			||||||
        Sec->Type != SHT_RELA)
 | 
					        Sec->Type != SHT_RELA)
 | 
				
			||||||
      Sec->writeTo<ELFT>(Buf + Sec->Offset);
 | 
					      Cmd->writeTo<ELFT>(Buf + Sec->Offset);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // The .eh_frame_hdr depends on .eh_frame section contents, therefore
 | 
					  // The .eh_frame_hdr depends on .eh_frame section contents, therefore
 | 
				
			||||||
  // it should be written after .eh_frame is written.
 | 
					  // it should be written after .eh_frame is written.
 | 
				
			||||||
  if (EhFrameHdr && !EhFrameHdr->Sections.empty())
 | 
					  if (EhFrameHdr && !EhFrameHdr->Sections.empty()) {
 | 
				
			||||||
    EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
 | 
					    OutputSectionCommand *Cmd = Script->getCmd(EhFrameHdr);
 | 
				
			||||||
 | 
					    Cmd->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class ELFT> void Writer<ELFT>::writeBuildId() {
 | 
					template <class ELFT> void Writer<ELFT>::writeBuildId() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue