forked from OSchip/llvm-project
ELF: Remove DefinedCommon.
Common symbols are now represented with a DefinedRegular that points to a BssSection, even during symbol resolution. Differential Revision: https://reviews.llvm.org/D39666 llvm-svn: 317447
This commit is contained in:
parent
32665f702e
commit
6c55a70838
|
|
@ -1121,14 +1121,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
if (!Config->Relocatable)
|
||||
InputSections.push_back(createCommentSection<ELFT>());
|
||||
|
||||
// Create a .bss section for each common symbol and then replace the common
|
||||
// symbol with a DefinedRegular symbol. As a result, all common symbols are
|
||||
// "instantiated" as regular defined symbols, so that we don't need to care
|
||||
// about common symbols beyond this point. Note that if -r is given, we just
|
||||
// need to pass through common symbols as-is.
|
||||
if (Config->DefineCommon)
|
||||
createCommonSections<ELFT>();
|
||||
|
||||
// Do size optimizations: garbage collection, merging of SHF_MERGE sections
|
||||
// and identical code folding.
|
||||
markLive<ELFT>();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
class DefinedCommon;
|
||||
class Symbol;
|
||||
struct SectionPiece;
|
||||
|
||||
|
|
@ -55,6 +54,8 @@ public:
|
|||
// If GC is disabled, all sections are considered live by default.
|
||||
unsigned Live : 1;
|
||||
|
||||
unsigned Bss : 1;
|
||||
|
||||
// These corresponds to the fields in Elf_Shdr.
|
||||
uint32_t Alignment;
|
||||
uint64_t Flags;
|
||||
|
|
@ -78,7 +79,7 @@ protected:
|
|||
SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,
|
||||
uint64_t Entsize, uint64_t Alignment, uint32_t Type,
|
||||
uint32_t Info, uint32_t Link)
|
||||
: Name(Name), SectionKind(SectionKind), Live(false),
|
||||
: Name(Name), SectionKind(SectionKind), Live(false), Bss(false),
|
||||
Alignment(Alignment), Flags(Flags), Entsize(Entsize), Type(Type),
|
||||
Link(Link), Info(Info) {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "LinkerScript.h"
|
||||
#include "Memory.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
|
|
@ -365,13 +366,13 @@ static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
|
|||
S->Binding = Binding;
|
||||
return Cmp;
|
||||
}
|
||||
if (isa<DefinedCommon>(S)) {
|
||||
// Non-common symbols take precedence over common symbols.
|
||||
if (Config->WarnCommon)
|
||||
warn("common " + S->getName() + " is overridden");
|
||||
return 1;
|
||||
}
|
||||
if (auto *R = dyn_cast<DefinedRegular>(S)) {
|
||||
if (R->Section && isa<BssSection>(R->Section)) {
|
||||
// Non-common symbols take precedence over common symbols.
|
||||
if (Config->WarnCommon)
|
||||
warn("common " + S->getName() + " is overridden");
|
||||
return 1;
|
||||
}
|
||||
if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute &&
|
||||
R->Value == Value)
|
||||
return -1;
|
||||
|
|
@ -388,11 +389,18 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
|
|||
/*CanOmitFromDynSym*/ false, File);
|
||||
int Cmp = compareDefined(S, WasInserted, Binding, N);
|
||||
if (Cmp > 0) {
|
||||
auto *Bss = make<BssSection>("COMMON", Size, Alignment);
|
||||
Bss->File = File;
|
||||
Bss->Live = !Config->GcSections;
|
||||
InputSections.push_back(Bss);
|
||||
|
||||
S->Binding = Binding;
|
||||
replaceSymbol<DefinedCommon>(S, File, N, Size, Alignment, StOther, Type);
|
||||
replaceSymbol<DefinedRegular>(S, File, N, /*IsLocal=*/false, StOther, Type,
|
||||
0, Size, Bss);
|
||||
} else if (Cmp == 0) {
|
||||
auto *C = dyn_cast<DefinedCommon>(S);
|
||||
if (!C) {
|
||||
auto *D = cast<DefinedRegular>(S);
|
||||
auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
|
||||
if (!Bss) {
|
||||
// Non-common symbols take precedence over common symbols.
|
||||
if (Config->WarnCommon)
|
||||
warn("common " + S->getName() + " is overridden");
|
||||
|
|
@ -400,11 +408,13 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
|
|||
}
|
||||
|
||||
if (Config->WarnCommon)
|
||||
warn("multiple common of " + S->getName());
|
||||
warn("multiple common of " + D->getName());
|
||||
|
||||
Alignment = C->Alignment = std::max(C->Alignment, Alignment);
|
||||
if (Size > C->Size)
|
||||
replaceSymbol<DefinedCommon>(S, File, N, Size, Alignment, StOther, Type);
|
||||
Bss->Alignment = std::max(Bss->Alignment, Alignment);
|
||||
if (Size > Bss->Size) {
|
||||
D->File = Bss->File = File;
|
||||
D->Size = Bss->Size = Size;
|
||||
}
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,8 +99,6 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
|
|||
}
|
||||
return VA;
|
||||
}
|
||||
case Symbol::DefinedCommonKind:
|
||||
llvm_unreachable("common are converted to bss");
|
||||
case Symbol::SharedKind: {
|
||||
auto &SS = cast<SharedSymbol>(Sym);
|
||||
if (SS.CopyRelSec)
|
||||
|
|
@ -182,8 +180,6 @@ uint64_t Symbol::getPltVA() const {
|
|||
}
|
||||
|
||||
uint64_t Symbol::getSize() const {
|
||||
if (const auto *C = dyn_cast<DefinedCommon>(this))
|
||||
return C->Size;
|
||||
if (const auto *DR = dyn_cast<DefinedRegular>(this))
|
||||
return DR->Size;
|
||||
if (const auto *S = dyn_cast<SharedSymbol>(this))
|
||||
|
|
@ -204,12 +200,6 @@ OutputSection *Symbol::getOutputSection() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (auto *S = dyn_cast<DefinedCommon>(this)) {
|
||||
if (Config->DefineCommon)
|
||||
return S->Section->getParent();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -321,12 +311,12 @@ void elf::printTraceSymbol(Symbol *Sym) {
|
|||
std::string S;
|
||||
if (Sym->isUndefined())
|
||||
S = ": reference to ";
|
||||
else if (Sym->isCommon())
|
||||
S = ": common definition of ";
|
||||
else if (Sym->isLazy())
|
||||
S = ": lazy definition of ";
|
||||
else if (Sym->isShared())
|
||||
S = ": shared definition of ";
|
||||
else if (dyn_cast_or_null<BssSection>(cast<DefinedRegular>(Sym)->Section))
|
||||
S = ": common definition of ";
|
||||
else
|
||||
S = ": definition of ";
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ public:
|
|||
enum Kind {
|
||||
DefinedFirst,
|
||||
DefinedRegularKind = DefinedFirst,
|
||||
DefinedCommonKind,
|
||||
DefinedLast = DefinedCommonKind,
|
||||
DefinedLast = DefinedRegularKind,
|
||||
SharedKind,
|
||||
UndefinedKind,
|
||||
LazyArchiveKind,
|
||||
|
|
@ -97,7 +96,6 @@ public:
|
|||
|
||||
bool isUndefined() const { return SymbolKind == UndefinedKind; }
|
||||
bool isDefined() const { return SymbolKind <= DefinedLast; }
|
||||
bool isCommon() const { return SymbolKind == DefinedCommonKind; }
|
||||
bool isShared() const { return SymbolKind == SharedKind; }
|
||||
bool isLocal() const { return IsLocal; }
|
||||
|
||||
|
|
@ -106,7 +104,7 @@ public:
|
|||
}
|
||||
|
||||
bool isInCurrentOutput() const {
|
||||
return SymbolKind == DefinedRegularKind || SymbolKind == DefinedCommonKind;
|
||||
return SymbolKind == DefinedRegularKind;
|
||||
}
|
||||
|
||||
// True is this is an undefined weak symbol. This only works once
|
||||
|
|
@ -199,26 +197,6 @@ public:
|
|||
static bool classof(const Symbol *S) { return S->isDefined(); }
|
||||
};
|
||||
|
||||
class DefinedCommon : public Defined {
|
||||
public:
|
||||
DefinedCommon(StringRef Name, uint64_t Size, uint32_t Alignment,
|
||||
uint8_t StOther, uint8_t Type)
|
||||
: Defined(DefinedCommonKind, Name, /*IsLocal=*/false, StOther, Type),
|
||||
Alignment(Alignment), Size(Size) {}
|
||||
|
||||
static bool classof(const Symbol *S) {
|
||||
return S->kind() == DefinedCommonKind;
|
||||
}
|
||||
|
||||
// The maximum alignment we have seen for this symbol.
|
||||
uint32_t Alignment;
|
||||
|
||||
// The output offset of this common symbol in the output bss.
|
||||
// Computed by the writer.
|
||||
uint64_t Size;
|
||||
BssSection *Section = nullptr;
|
||||
};
|
||||
|
||||
// Regular defined symbols read from object file symbol tables.
|
||||
class DefinedRegular : public Defined {
|
||||
public:
|
||||
|
|
@ -378,7 +356,6 @@ struct ElfSym {
|
|||
// using the placement new.
|
||||
union SymbolUnion {
|
||||
alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
|
||||
alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
|
||||
alignas(Undefined) char C[sizeof(Undefined)];
|
||||
alignas(SharedSymbol) char D[sizeof(SharedSymbol)];
|
||||
alignas(LazyArchive) char E[sizeof(LazyArchive)];
|
||||
|
|
|
|||
|
|
@ -63,29 +63,6 @@ uint64_t SyntheticSection::getVA() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Create a .bss section for each common symbol and replace the common symbol
|
||||
// with a DefinedRegular symbol.
|
||||
template <class ELFT> void elf::createCommonSections() {
|
||||
for (Symbol *S : Symtab->getSymbols()) {
|
||||
auto *Sym = dyn_cast<DefinedCommon>(S);
|
||||
|
||||
if (!Sym)
|
||||
continue;
|
||||
|
||||
// Create a synthetic section for the common data.
|
||||
auto *Section = make<BssSection>("COMMON", Sym->Size, Sym->Alignment);
|
||||
Section->File = Sym->getFile();
|
||||
Section->Live = !Config->GcSections;
|
||||
InputSections.push_back(Section);
|
||||
|
||||
// Replace all DefinedCommon symbols with DefinedRegular symbols so that we
|
||||
// don't have to care about DefinedCommon symbols beyond this point.
|
||||
replaceSymbol<DefinedRegular>(
|
||||
S, Sym->getFile(), Sym->getName(), static_cast<bool>(Sym->isLocal()),
|
||||
Sym->StOther, Sym->Type, 0, Sym->getSize(), Section);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an LLD version string.
|
||||
static ArrayRef<uint8_t> getVersion() {
|
||||
// Check LLD_VERSION first for ease of testing.
|
||||
|
|
@ -367,6 +344,7 @@ void BuildIdSection::computeHash(
|
|||
|
||||
BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment)
|
||||
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Name) {
|
||||
this->Bss = true;
|
||||
if (OutputSection *Sec = getParent())
|
||||
Sec->Alignment = std::max(Sec->Alignment, Alignment);
|
||||
this->Size = Size;
|
||||
|
|
@ -1596,12 +1574,16 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
ESym->st_name = Ent.StrTabOffset;
|
||||
|
||||
// Set a section index.
|
||||
if (const OutputSection *OutSec = Sym->getOutputSection())
|
||||
BssSection *CommonSec = nullptr;
|
||||
if (!Config->DefineCommon)
|
||||
if (auto *D = dyn_cast<DefinedRegular>(Sym))
|
||||
CommonSec = dyn_cast_or_null<BssSection>(D->Section);
|
||||
if (CommonSec)
|
||||
ESym->st_shndx = SHN_COMMON;
|
||||
else if (const OutputSection *OutSec = Sym->getOutputSection())
|
||||
ESym->st_shndx = OutSec->SectionIndex;
|
||||
else if (isa<DefinedRegular>(Sym))
|
||||
ESym->st_shndx = SHN_ABS;
|
||||
else if (isa<DefinedCommon>(Sym))
|
||||
ESym->st_shndx = SHN_COMMON;
|
||||
else
|
||||
ESym->st_shndx = SHN_UNDEF;
|
||||
|
||||
|
|
@ -1618,8 +1600,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
// st_value is usually an address of a symbol, but that has a
|
||||
// special meaining for uninstantiated common symbols (this can
|
||||
// occur if -r is given).
|
||||
if (!Config->DefineCommon && isa<DefinedCommon>(Sym))
|
||||
ESym->st_value = cast<DefinedCommon>(Sym)->Alignment;
|
||||
if (CommonSec)
|
||||
ESym->st_value = CommonSec->Alignment;
|
||||
else
|
||||
ESym->st_value = Sym->getVA();
|
||||
|
||||
|
|
@ -2642,11 +2624,6 @@ template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
|
|||
template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
|
||||
template void PltSection::addEntry<ELF64BE>(Symbol &Sym);
|
||||
|
||||
template void elf::createCommonSections<ELF32LE>();
|
||||
template void elf::createCommonSections<ELF32BE>();
|
||||
template void elf::createCommonSections<ELF64LE>();
|
||||
template void elf::createCommonSections<ELF64BE>();
|
||||
|
||||
template MergeInputSection *elf::createCommentSection<ELF32LE>();
|
||||
template MergeInputSection *elf::createCommentSection<ELF32BE>();
|
||||
template MergeInputSection *elf::createCommentSection<ELF64LE>();
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ public:
|
|||
bool empty() const override { return getSize() == 0; }
|
||||
size_t getSize() const override { return Size; }
|
||||
|
||||
private:
|
||||
static bool classof(const SectionBase *S) { return S->Bss; }
|
||||
uint64_t Size;
|
||||
};
|
||||
|
||||
|
|
@ -821,7 +821,6 @@ private:
|
|||
size_t Size = 0;
|
||||
};
|
||||
|
||||
template <class ELFT> void createCommonSections();
|
||||
InputSection *createInterpSection();
|
||||
template <class ELFT> MergeInputSection *createCommentSection();
|
||||
void decompressSections();
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
# DEFCOMM-NEXT: Binding: Global
|
||||
# DEFCOMM-NEXT: Type: Object
|
||||
# DEFCOMM-NEXT: Other: 0
|
||||
# DEFCOMM-NEXT: Section: COMMON (0x2)
|
||||
# DEFCOMM-NEXT: Section: COMMON
|
||||
# DEFCOMM-NEXT: }
|
||||
|
||||
.comm common,4,4
|
||||
|
|
|
|||
Loading…
Reference in New Issue