Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2530,7 +2530,10 @@ static void replaceCommonSymbols(Ctx &ctx) {
if (!s)
continue;

auto *bss = make<BssSection>(ctx, "COMMON", s->size, s->alignment);
auto *bss =
(s->isLargeCommon)
? make<LbssSection>(ctx, "LARGE_COMMON", s->size, s->alignment)
: make<BssSection>(ctx, "COMMON", s->size, s->alignment);
bss->file = s->file;
ctx.inputSections.push_back(bss);
Defined(ctx, s->file, StringRef(), s->binding, s->stOther, s->type,
Expand Down
8 changes: 6 additions & 2 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1223,13 +1223,17 @@ void ObjFile<ELFT>::initializeSymbols(const object::ELFFile<ELFT> &obj) {

Symbol *sym = symbols[i];
sym->isUsedInRegularObj = true;
if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON)) {

bool isLargeCommon = LLVM_UNLIKELY(eSym.st_shndx == SHN_AMD64_LCOMMON) &&
ctx.arg.emachine == EM_X86_64;
if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON) || isLargeCommon) {

if (value == 0 || value >= UINT32_MAX)
Err(ctx) << this << ": common symbol '" << sym->getName()
<< "' has invalid alignment: " << value;
hasCommonSyms = true;
sym->resolve(ctx, CommonSymbol{ctx, this, StringRef(), binding, stOther,
type, value, size});
type, value, size, isLargeCommon});
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ InputSectionBase::InputSectionBase(InputFile *file, StringRef name,
Kind sectionKind)
: SectionBase(sectionKind, file, name, type, flags, link, info, addralign,
entsize),
bss(0), decodedCrel(0), keepUnique(0), nopFiller(0),
bss(0), lbss(0), decodedCrel(0), keepUnique(0), nopFiller(0),
content_(data.data()), size(data.size()) {
// In order to reduce memory allocation, we assume that mergeable
// sections are smaller than 4 GiB, which is not an unreasonable
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/InputSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class InputSectionBase : public SectionBase {

LLVM_PREFERRED_TYPE(bool)
uint8_t bss : 1;
uint8_t lbss : 1;

// Whether this section is SHT_CREL and has been decoded to RELA by
// relsOrRelas.
Expand Down
6 changes: 5 additions & 1 deletion lld/ELF/LinkerScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
return s->name;

// A BssSection created for a common symbol is identified as "COMMON" in
// linker scripts. It should go to .bss section.
// linker scripts. It should go to .bss section. A large bss section,
// LbssCommon, created for a large common symbol is identified as
// "LARGE_COMMON".
if (s->name == "COMMON")
return ".bss";
else if (s->name == "LARGE_COMMON")
return ".lbss";

if (hasSectionsCommand)
return s->name;
Expand Down
8 changes: 5 additions & 3 deletions lld/ELF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,21 +408,23 @@ class Defined : public Symbol {
class CommonSymbol : public Symbol {
public:
CommonSymbol(Ctx &ctx, InputFile *file, StringRef name, uint8_t binding,
uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size)
uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size,
bool isLargeCommon = false)
: Symbol(CommonKind, file, name, binding, stOther, type),
alignment(alignment), size(size) {
}
alignment(alignment), size(size), isLargeCommon(isLargeCommon) {}
void overwrite(Symbol &sym) const {
Symbol::overwrite(sym, CommonKind);
auto &s = static_cast<CommonSymbol &>(sym);
s.alignment = alignment;
s.size = size;
s.isLargeCommon = isLargeCommon;
}

static bool classof(const Symbol *s) { return s->isCommon(); }

uint32_t alignment;
uint64_t size;
bool isLargeCommon;
};

class Undefined : public Symbol {
Expand Down
6 changes: 6 additions & 0 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,12 @@ BssSection::BssSection(Ctx &ctx, StringRef name, uint64_t size,
this->size = size;
}

LbssSection::LbssSection(Ctx &ctx, StringRef name, uint64_t size,
uint32_t alignment)
: BssSection(ctx, name, size, alignment) {
this->lbss = true;
}

EhFrameSection::EhFrameSection(Ctx &ctx)
: SyntheticSection(ctx, ".eh_frame", SHT_PROGBITS, SHF_ALLOC, 1) {}

Expand Down
13 changes: 12 additions & 1 deletion lld/ELF/SyntheticSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ class BuildIdSection : public SyntheticSection {
// We create three instances of this class for .bss, .bss.rel.ro and "COMMON",
// that are used for writable symbols, read-only symbols and common symbols,
// respectively.
class BssSection final : public SyntheticSection {
class BssSection : public SyntheticSection {
public:
BssSection(Ctx &, StringRef name, uint64_t size, uint32_t addralign);
void writeTo(uint8_t *) override {}
Expand All @@ -185,6 +185,17 @@ class BssSection final : public SyntheticSection {
uint64_t size;
};

// LbssSection is used to reserve space for large common symbols on x86-64,
// "LARGE_COMMON".
class LbssSection final : public BssSection {
public:
LbssSection(Ctx &, StringRef name, uint64_t size, uint32_t addralign);

static bool classof(const SectionBase *s) {
return isa<SyntheticSection>(s) && cast<SyntheticSection>(s)->lbss;
}
};

class MipsGotSection final : public SyntheticSection {
public:
MipsGotSection(Ctx &);
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,11 @@ enum {
SHN_MIPS_SUNDEFINED = 0xff04 // Undefined symbols for global data area
};

// x86-64 speciifc section index
enum {
SHN_AMD64_LCOMMON = 0xff02, // Large FORTRAN COMMON variables
};

// ELF Relocation types for Mips
enum {
#include "ELFRelocs/Mips.def"
Expand Down