case MCSymbolRefExpr::VK_GOTNTPOFF:
case MCSymbolRefExpr::VK_TLSLDM:
case MCSymbolRefExpr::VK_DTPOFF:
+ case MCSymbolRefExpr::VK_TLSLD:
return true;
}
}
};
SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+ SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc;
DenseMap<const MCSymbol *, const MCSymbol *> Renames;
llvm::DenseMap<const MCSectionData*,
bool NeedsGOT;
+ bool NeedsSymtabShndx;
+
ELFObjectWriter *Writer;
raw_ostream &OS;
unsigned LastLocalSymbolIndex;
// This holds the .strtab section index.
unsigned StringTableIndex;
+ // This holds the .symtab section index.
+ unsigned SymbolTableIndex;
unsigned ShstrtabIndex;
ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
uint16_t _EMachine, bool _HasRelAddend,
Triple::OSType _OSType)
- : NeedsGOT(false), Writer(_Writer), OS(Writer->getStream()),
+ : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer),
+ OS(Writer->getStream()),
Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend),
OSType(_OSType), EMachine(_EMachine) {
}
void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections);
- void WriteSymbolEntry(MCDataFragment *F, uint64_t name, uint8_t info,
+ void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+ uint64_t name, uint8_t info,
uint64_t value, uint64_t size,
- uint8_t other, uint16_t shndx);
+ uint8_t other, uint32_t shndx,
+ bool Reserved);
- void WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
+ void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+ ELFSymbolData &MSD,
const MCAsmLayout &Layout);
- void WriteSymbolTable(MCDataFragment *F, const MCAssembler &Asm,
+ void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+ const MCAssembler &Asm,
const MCAsmLayout &Layout,
unsigned NumRegularSections);
Write16(Is64Bit ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents
- Write16(NumberOfSections);
+ if (NumberOfSections >= ELF::SHN_LORESERVE)
+ Write16(0);
+ else
+ Write16(NumberOfSections);
// e_shstrndx = Section # of '.shstrtab'
- Write16(ShstrtabIndex);
+ if (NumberOfSections >= ELF::SHN_LORESERVE)
+ Write16(ELF::SHN_XINDEX);
+ else
+ Write16(ShstrtabIndex);
}
-void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *F, uint64_t name,
+void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *SymtabF,
+ MCDataFragment *ShndxF,
+ uint64_t name,
uint8_t info, uint64_t value,
uint64_t size, uint8_t other,
- uint16_t shndx) {
+ uint32_t shndx,
+ bool Reserved) {
+ if (ShndxF) {
+ char buf[4];
+ if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+ String32(buf, shndx);
+ else
+ String32(buf, 0);
+ ShndxF->getContents() += StringRef(buf, 4);
+ }
+
if (Is64Bit) {
char buf[8];
String32(buf, name);
- F->getContents() += StringRef(buf, 4); // st_name
+ SymtabF->getContents() += StringRef(buf, 4); // st_name
String8(buf, info);
- F->getContents() += StringRef(buf, 1); // st_info
+ SymtabF->getContents() += StringRef(buf, 1); // st_info
String8(buf, other);
- F->getContents() += StringRef(buf, 1); // st_other
+ SymtabF->getContents() += StringRef(buf, 1); // st_other
- String16(buf, shndx);
- F->getContents() += StringRef(buf, 2); // st_shndx
+ if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+ String16(buf, ELF::SHN_XINDEX);
+ else
+ String16(buf, shndx);
+
+ SymtabF->getContents() += StringRef(buf, 2); // st_shndx
String64(buf, value);
- F->getContents() += StringRef(buf, 8); // st_value
+ SymtabF->getContents() += StringRef(buf, 8); // st_value
String64(buf, size);
- F->getContents() += StringRef(buf, 8); // st_size
+ SymtabF->getContents() += StringRef(buf, 8); // st_size
} else {
char buf[4];
String32(buf, name);
- F->getContents() += StringRef(buf, 4); // st_name
+ SymtabF->getContents() += StringRef(buf, 4); // st_name
String32(buf, value);
- F->getContents() += StringRef(buf, 4); // st_value
+ SymtabF->getContents() += StringRef(buf, 4); // st_value
String32(buf, size);
- F->getContents() += StringRef(buf, 4); // st_size
+ SymtabF->getContents() += StringRef(buf, 4); // st_size
String8(buf, info);
- F->getContents() += StringRef(buf, 1); // st_info
+ SymtabF->getContents() += StringRef(buf, 1); // st_info
String8(buf, other);
- F->getContents() += StringRef(buf, 1); // st_other
+ SymtabF->getContents() += StringRef(buf, 1); // st_other
+
+ if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+ String16(buf, ELF::SHN_XINDEX);
+ else
+ String16(buf, shndx);
- String16(buf, shndx);
- F->getContents() += StringRef(buf, 2); // st_shndx
+ SymtabF->getContents() += StringRef(buf, 2); // st_shndx
}
}
if (!Symbol.isInSection())
return 0;
- if (!Data.isCommon() && !(Data.getFlags() & ELF_STB_Weak))
- if (MCFragment *FF = Data.getFragment())
- return Layout.getSymbolAddress(&Data) -
- Layout.getSectionAddress(FF->getParent());
+ if (MCFragment *FF = Data.getFragment())
+ return Layout.getSymbolAddress(&Data) -
+ Layout.getSectionAddress(FF->getParent());
return 0;
}
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
ie = Asm.symbol_end(); it != ie; ++it) {
const MCSymbol &Alias = it->getSymbol();
- if (!Alias.isVariable())
- continue;
const MCSymbol &Symbol = AliasedSymbol(Alias);
+ MCSymbolData &SD = Asm.getSymbolData(Symbol);
+
+ // Undefined symbols are global, but this is the first place we
+ // are able to set it.
+ if (Symbol.isUndefined() && !Symbol.isVariable()) {
+ if (GetBinding(SD) == ELF::STB_LOCAL) {
+ SetBinding(SD, ELF::STB_GLOBAL);
+ SetBinding(*it, ELF::STB_GLOBAL);
+ }
+ }
+
+ // Not an alias.
+ if (&Symbol == &Alias)
+ continue;
+
StringRef AliasName = Alias.getName();
size_t Pos = AliasName.find('@');
if (Pos == StringRef::npos)
continue;
+ // Aliases defined with .symvar copy the binding from the symbol they alias.
+ // This is the first place we are able to copy this information.
+ it->setExternal(SD.isExternal());
+ SetBinding(*it, GetBinding(SD));
+
StringRef Rest = AliasName.substr(Pos);
if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
continue;
}
}
-void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
+void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *SymtabF,
+ MCDataFragment *ShndxF,
+ ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
MCSymbolData &OrigData = *MSD.SymbolData;
MCSymbolData &Data =
Layout.getAssembler().getSymbolData(AliasedSymbol(OrigData.getSymbol()));
+ bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
+ Data.getSymbol().isVariable();
+
uint8_t Binding = GetBinding(OrigData);
uint8_t Visibility = GetVisibility(OrigData);
uint8_t Type = GetType(Data);
}
// Write out the symbol table entry
- WriteSymbolEntry(F, MSD.StringIndex, Info, Value,
- Size, Other, MSD.SectionIndex);
+ WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value,
+ Size, Other, MSD.SectionIndex, IsReserved);
}
-void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
+void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *SymtabF,
+ MCDataFragment *ShndxF,
const MCAssembler &Asm,
const MCAsmLayout &Layout,
unsigned NumRegularSections) {
// FIXME: Make sure the start of the symbol table is aligned.
// The first entry is the undefined symbol entry.
- unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
- F->getContents().append(EntrySize, '\x00');
+ WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
// Write the symbol table entries.
LastLocalSymbolIndex = LocalSymbolData.size() + 1;
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = LocalSymbolData[i];
- WriteSymbol(F, MSD, Layout);
+ WriteSymbol(SymtabF, ShndxF, MSD, Layout);
}
// Write out a symbol table entry for each regular section.
// the relocations messed up
if (Section.getType() == ELF::SHT_RELA || Section.getType() == ELF::SHT_REL)
continue;
- WriteSymbolEntry(F, 0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, Index);
+ WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0,
+ ELF::STV_DEFAULT, Index, false);
LastLocalSymbolIndex++;
}
assert(((Data.getFlags() & ELF_STB_Global) ||
(Data.getFlags() & ELF_STB_Weak)) &&
"External symbol requires STB_GLOBAL or STB_WEAK flag");
- WriteSymbol(F, MSD, Layout);
+ WriteSymbol(SymtabF, ShndxF, MSD, Layout);
if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
- WriteSymbol(F, MSD, Layout);
+ WriteSymbol(SymtabF, ShndxF, MSD, Layout);
if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
int Index = 0;
int64_t Value = Target.getConstant();
const MCSymbol *Symbol = 0;
+ const MCSymbol *Renamed = 0;
bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
if (!Target.isAbsolute()) {
Symbol = &AliasedSymbol(Target.getSymA()->getSymbol());
- const MCSymbol *Renamed = Renames.lookup(Symbol);
- if (Renamed)
- Symbol = Renamed;
+ Renamed = Renames.lookup(Symbol);
+ if (!Renamed)
+ Renamed = &Target.getSymA()->getSymbol();
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
MCFragment *F = SD.getFragment();
// Offset of the symbol in the section
Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
} else {
- UsedInReloc.insert(Symbol);
+ UsedInReloc.insert(Renamed);
+ MCSymbolData &RenamedSD = Asm.getSymbolData(*Renamed);
+ if (RenamedSD.getFlags() & ELF_Other_Weakref) {
+ WeakrefUsedInReloc.insert(Symbol);
+ }
Index = -1;
}
Addend = Value;
case MCSymbolRefExpr::VK_TLSGD:
Type = ELF::R_X86_64_TLSGD;
break;
+ case MCSymbolRefExpr::VK_TLSLD:
+ Type = ELF::R_X86_64_TLSLD;
+ break;
}
} else {
switch ((unsigned)Fixup.getKind()) {
case MCSymbolRefExpr::VK_TPOFF:
Type = ELF::R_X86_64_TPOFF32;
break;
+ case MCSymbolRefExpr::VK_DTPOFF:
+ Type = ELF::R_X86_64_DTPOFF32;
+ break;
}
break;
case FK_Data_4:
ERE.Index = Index;
ERE.Type = Type;
- ERE.Symbol = Symbol;
+ ERE.Symbol = Renamed;
ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
bool Used, bool Renamed) {
+ if (Data.getFlags() & ELF_Other_Weakref)
+ return false;
+
if (Used)
return true;
const MCSymbol &Symbol = Data.getSymbol();
+ if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
+ return true;
+
const MCSymbol &A = AliasedSymbol(Symbol);
- if (&A != &Symbol && A.isUndefined())
+ if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
return false;
if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name);
MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym);
Data.setExternal(true);
+ SetBinding(Data, ELF::STB_GLOBAL);
}
// Build section lookup table.
ie = Asm.symbol_end(); it != ie; ++it) {
const MCSymbol &Symbol = it->getSymbol();
- if (!isInSymtab(Asm, *it, UsedInReloc.count(&Symbol),
+ bool Used = UsedInReloc.count(&Symbol);
+ bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
+ if (!isInSymtab(Asm, *it, Used || WeakrefUsed,
Renames.count(&Symbol)))
continue;
bool Local = isLocal(*it);
const MCSymbol &RefSymbol = AliasedSymbol(Symbol);
+ if (RefSymbol.isUndefined() && !Used && WeakrefUsed)
+ SetBinding(*it, ELF::STB_WEAK);
+
if (it->isCommon()) {
assert(!Local);
MSD.SectionIndex = ELF::SHN_COMMON;
MSD.SectionIndex = ELF::SHN_ABS;
} else if (RefSymbol.isUndefined()) {
MSD.SectionIndex = ELF::SHN_UNDEF;
- // FIXME: Undefined symbols are global, but this is the first place we
- // are able to set it.
- if (GetBinding(*it) == ELF::STB_LOCAL)
- SetBinding(*it, ELF::STB_GLOBAL);
} else {
MSD.SectionIndex = SectionIndexMap.lookup(&RefSymbol.getSection());
+ if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+ NeedsSymtabShndx = true;
assert(MSD.SectionIndex && "Invalid section index!");
}
RelaSection = Ctx.getELFSection(RelaSectionName, HasRelocationAddend ?
ELF::SHT_RELA : ELF::SHT_REL, 0,
SectionKind::getReadOnly(),
- false, EntrySize);
+ EntrySize);
MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection);
RelaSD.setAlignment(Is64Bit ? 8 : 4);
MCContext &Ctx = Asm.getContext();
MCDataFragment *F;
- const MCSection *SymtabSection;
unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
unsigned NumRegularSections = Asm.size();
// We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
- const MCSection *ShstrtabSection;
- ShstrtabSection = Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
- SectionKind::getReadOnly(), false);
+ const MCSection *ShstrtabSection =
+ Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
+ SectionKind::getReadOnly(), false);
MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
ShstrtabSD.setAlignment(1);
ShstrtabIndex = Asm.size();
- SymtabSection = Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
- SectionKind::getReadOnly(),
- false, EntrySize);
+ const MCSection *SymtabSection =
+ Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
+ SectionKind::getReadOnly(),
+ EntrySize);
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(Is64Bit ? 8 : 4);
+ SymbolTableIndex = Asm.size();
+
+ MCSectionData *SymtabShndxSD = NULL;
+
+ if (NeedsSymtabShndx) {
+ const MCSection *SymtabShndxSection =
+ Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0,
+ SectionKind::getReadOnly(), 4);
+ SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection);
+ SymtabShndxSD->setAlignment(4);
+ }
const MCSection *StrtabSection;
StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
// Symbol table
F = new MCDataFragment(&SymtabSD);
- WriteSymbolTable(F, Asm, Layout, NumRegularSections);
+ MCDataFragment *ShndxF = NULL;
+ if (NeedsSymtabShndx) {
+ ShndxF = new MCDataFragment(SymtabShndxSD);
+ Asm.AddSectionToTheEnd(*Writer, *SymtabShndxSD, Layout);
+ }
+ WriteSymbolTable(F, ShndxF, Asm, Layout, NumRegularSections);
Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout);
F = new MCDataFragment(&StrtabSD);
// Should we align the section header table?
//
// Null section first.
- WriteSecHdrEntry(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ uint64_t FirstSectionSize =
+ NumSections >= ELF::SHN_LORESERVE ? NumSections : 0;
+ uint32_t FirstSectionLink =
+ ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
+ WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
sh_info = LastLocalSymbolIndex;
break;
+ case ELF::SHT_SYMTAB_SHNDX:
+ sh_link = SymbolTableIndex;
+ break;
+
case ELF::SHT_PROGBITS:
case ELF::SHT_STRTAB:
case ELF::SHT_NOBITS: