diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-01-06 21:36:48 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-01-06 21:36:48 +0000 |
| commit | 97dd191f563d0b295e4abc86dc95a4f6276c6d8f (patch) | |
| tree | dc66d565f400b52657b1297dba15c40cf91b74a3 /ELF | |
| parent | ae1a339de31cf4065777531959a11e55a2e5fa00 (diff) | |
Notes
Diffstat (limited to 'ELF')
| -rw-r--r-- | ELF/Driver.cpp | 3 | ||||
| -rw-r--r-- | ELF/Relocations.cpp | 18 | ||||
| -rw-r--r-- | ELF/SyntheticSections.cpp | 10 | ||||
| -rw-r--r-- | ELF/Writer.cpp | 26 |
4 files changed, 37 insertions, 20 deletions
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index cc76fea2ad5e5..b159fe63eb181 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -1043,7 +1043,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { return; // Handle undefined symbols in DSOs. - Symtab->scanShlibUndefined<ELFT>(); + if (!Config->Shared) + Symtab->scanShlibUndefined<ELFT>(); // Handle the -exclude-libs option. if (Args.hasArg(OPT_exclude_libs)) diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 1aa0957b1d01e..37bc8bcbd571c 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -367,7 +367,7 @@ static bool isRelExpr(RelExpr Expr) { static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, InputSectionBase &S, uint64_t RelOff) { // These expressions always compute a constant - if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, + if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD, @@ -384,6 +384,10 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, if (!Config->Pic) return true; + // The size of a non preemptible symbol is a constant. + if (E == R_SIZE) + return true; + // For the target and the relocation, we want to know if they are // absolute or relative. bool AbsVal = isAbsoluteValue(Sym); @@ -592,6 +596,12 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, if (IsConstant) return Expr; + // We can create any dynamic relocation supported by the dynamic linker if a + // section is writable or we are passed -z notext. + bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText; + if (CanWrite && Target->isPicRel(Type)) + return Expr; + // If the relocation is to a weak undef, and we are producing // executable, give up on it and produce a non preemptible 0. if (!Config->Shared && Sym.isUndefWeak()) { @@ -600,12 +610,6 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, return Expr; } - // We can create any dynamic relocation supported by the dynamic linker if a - // section is writable or we are passed -z notext. - bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText; - if (CanWrite && Target->isPicRel(Type)) - return Expr; - // If we got here we know that this relocation would require the dynamic // linker to write a value to read only memory or use an unsupported // relocation. diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index a5e291b79a4db..f878acf8cf3f6 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -1064,7 +1064,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { addInt(DT_DEBUG, 0); this->Link = InX::DynStrTab->getParent()->SectionIndex; - if (InX::RelaDyn->getParent() && !InX::RelaDyn->empty()) { + if (!InX::RelaDyn->empty()) { addInSec(InX::RelaDyn->DynamicTag, InX::RelaDyn); addSize(InX::RelaDyn->SizeDynamicTag, InX::RelaDyn->getParent()); @@ -1081,7 +1081,13 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels); } } - if (InX::RelaPlt->getParent() && !InX::RelaPlt->empty()) { + // .rel[a].plt section usually consists of two parts, containing plt and + // iplt relocations. It is possible to have only iplt relocations in the + // output. In that case RelaPlt is empty and have zero offset, the same offset + // as RelaIplt have. And we still want to emit proper dynamic tags for that + // case, so here we always use RelaPlt as marker for the begining of + // .rel[a].plt section. + if (InX::RelaPlt->getParent()->Live) { addInSec(DT_JMPREL, InX::RelaPlt); addSize(DT_PLTRELSZ, InX::RelaPlt->getParent()); switch (Config->EMachine) { diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 15f3821047560..24c3e1ee207c1 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -1767,30 +1767,36 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { // virtual address (modulo the page size) so that the loader can load // executables without any address adjustment. static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) { - // If the section is not in a PT_LOAD, we just have to align it. - if (!Cmd->PtLoad) - return alignTo(Off, Cmd->Alignment); - - OutputSection *First = Cmd->PtLoad->FirstSec; + OutputSection *First = Cmd->PtLoad ? Cmd->PtLoad->FirstSec : nullptr; // The first section in a PT_LOAD has to have congruent offset and address // module the page size. if (Cmd == First) return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize), Cmd->Addr); + // For SHT_NOBITS we don't want the alignment of the section to impact the + // offset of the sections that follow. Since nothing seems to care about the + // sh_offset of the SHT_NOBITS section itself, just ignore it. + if (Cmd->Type == SHT_NOBITS) + return Off; + + // If the section is not in a PT_LOAD, we just have to align it. + if (!Cmd->PtLoad) + return alignTo(Off, Cmd->Alignment); + // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). return First->Offset + Cmd->Addr - First->Addr; } static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) { - if (Cmd->Type == SHT_NOBITS) { - Cmd->Offset = Off; - return Off; - } - Off = getFileAlignment(Off, Cmd); Cmd->Offset = Off; + + // For SHT_NOBITS we should not count the size. + if (Cmd->Type == SHT_NOBITS) + return Off; + return Off + Cmd->Size; } |
