Create .symtab_shndxr only when needed.

We need .symtab_shndxr if and only if a symbol references a section with an
index >= 0xff00.

The old code was trying to figure out if the section was needed ahead of time,
making it a fairly dependent on the code actually writing the table. It was
also somewhat conservative and would create the section in cases where it was
not needed.

If I remember correctly, the old structure was there so that the sections were
created in the same order gas creates them. That was valuable when MC's support
for ELF was new and we tested with elf-dump.py.

This patch refactors the symbol table creation to another class and makes it
obvious that .symtab_shndxr is really only created when we are about to output
a reference to a section index >= 0xff00.

While here, also improve the tests to use macros. One file is one section
short of needing .symtab_shndxr, the second one has just the right number.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204769 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2014-03-25 23:44:25 +00:00
parent 6a0f060f64
commit 81c66bcc13
5 changed files with 338 additions and 158685 deletions

View File

@ -38,7 +38,6 @@ using namespace llvm;
#define DEBUG_TYPE "reloc-info"
namespace {
class FragmentWriter {
bool IsLittleEndian;
@ -47,6 +46,36 @@ public:
template <typename T> void write(MCDataFragment &F, T Val);
};
typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy;
class SymbolTableWriter {
MCAssembler &Asm;
FragmentWriter &FWriter;
bool Is64Bit;
SectionIndexMapTy &SectionIndexMap;
// The symbol .symtab fragment we are writting to.
MCDataFragment *SymtabF;
// .symtab_shndx fragment we are writting to.
MCDataFragment *ShndxF;
// The numbel of symbols written so far.
unsigned NumWritten;
void createSymtabShndx();
template <typename T> void write(MCDataFragment &F, T Value);
public:
SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit,
SectionIndexMapTy &SectionIndexMap,
MCDataFragment *SymtabF);
void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
uint8_t other, uint32_t shndx, bool Reserved);
};
class ELFObjectWriter : public MCObjectWriter {
FragmentWriter FWriter;
@ -114,8 +143,6 @@ class ELFObjectWriter : public MCObjectWriter {
bool NeedsGOT;
bool NeedsSymtabShndx;
// This holds the symbol table index of the last local symbol.
unsigned LastLocalSymbolIndex;
// This holds the .strtab section index.
@ -162,7 +189,7 @@ class ELFObjectWriter : public MCObjectWriter {
ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &_OS,
bool IsLittleEndian)
: MCObjectWriter(_OS, IsLittleEndian), FWriter(IsLittleEndian),
TargetObjectWriter(MOTW), NeedsGOT(false), NeedsSymtabShndx(false) {}
TargetObjectWriter(MOTW), NeedsGOT(false) {}
virtual ~ELFObjectWriter();
@ -181,21 +208,12 @@ class ELFObjectWriter : public MCObjectWriter {
uint64_t SectionDataSize,
unsigned NumberOfSections);
void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
uint32_t name, uint8_t info, uint64_t value,
uint64_t size, uint8_t other, uint32_t shndx,
bool Reserved);
void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
ELFSymbolData &MSD,
void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout);
typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy;
void WriteSymbolTable(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
const MCAssembler &Asm,
void WriteSymbolTable(MCDataFragment *SymtabF, MCAssembler &Asm,
const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap);
SectionIndexMapTy &SectionIndexMap);
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
@ -294,6 +312,76 @@ template <typename T> void FragmentWriter::write(MCDataFragment &F, T Val) {
F.getContents().append(Start, Start + sizeof(T));
}
void SymbolTableWriter::createSymtabShndx() {
if (ShndxF)
return;
MCContext &Ctx = Asm.getContext();
const MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0,
SectionKind::getReadOnly(), 4, "");
MCSectionData *SymtabShndxSD =
&Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
ShndxF = new MCDataFragment(SymtabShndxSD);
unsigned Index = SectionIndexMap.size() + 1;
SectionIndexMap[SymtabShndxSection] = Index;
for (unsigned I = 0; I < NumWritten; ++I)
write(*ShndxF, uint32_t(0));
}
template <typename T>
void SymbolTableWriter::write(MCDataFragment &F, T Value) {
FWriter.write(F, Value);
}
SymbolTableWriter::SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter,
bool Is64Bit,
SectionIndexMapTy &SectionIndexMap,
MCDataFragment *SymtabF)
: Asm(Asm), FWriter(FWriter), Is64Bit(Is64Bit),
SectionIndexMap(SectionIndexMap), SymtabF(SymtabF), ShndxF(nullptr),
NumWritten(0) {}
void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
uint64_t size, uint8_t other,
uint32_t shndx, bool Reserved) {
bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;
if (LargeIndex)
createSymtabShndx();
if (ShndxF) {
if (LargeIndex)
write(*ShndxF, shndx);
else
write(*ShndxF, uint32_t(0));
}
uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
raw_svector_ostream OS(SymtabF->getContents());
if (Is64Bit) {
write(*SymtabF, name); // st_name
write(*SymtabF, info); // st_info
write(*SymtabF, other); // st_other
write(*SymtabF, Index); // st_shndx
write(*SymtabF, value); // st_value
write(*SymtabF, size); // st_size
} else {
write(*SymtabF, name); // st_name
write(*SymtabF, uint32_t(value)); // st_value
write(*SymtabF, uint32_t(size)); // st_size
write(*SymtabF, info); // st_info
write(*SymtabF, other); // st_other
write(*SymtabF, Index); // st_shndx
}
++NumWritten;
}
bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
const MCFixupKindInfo &FKI =
Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind);
@ -389,38 +477,6 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
Write16(ShstrtabIndex);
}
void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF,
MCDataFragment *ShndxF, uint32_t name,
uint8_t info, uint64_t value,
uint64_t size, uint8_t other,
uint32_t shndx, bool Reserved) {
if (ShndxF) {
if (shndx >= ELF::SHN_LORESERVE && !Reserved)
write(*ShndxF, shndx);
else
write(*ShndxF, uint32_t(0));
}
uint16_t Index = (shndx >= ELF::SHN_LORESERVE && !Reserved) ?
uint16_t(ELF::SHN_XINDEX) : shndx;
if (is64Bit()) {
write(*SymtabF, name); // st_name
write(*SymtabF, info); // st_info
write(*SymtabF, other); // st_other
write(*SymtabF, Index); // st_shndx
write(*SymtabF, value); // st_value
write(*SymtabF, size); // st_size
} else {
write(*SymtabF, name); // st_name
write(*SymtabF, uint32_t(value)); // st_value
write(*SymtabF, uint32_t(size)); // st_size
write(*SymtabF, info); // st_info
write(*SymtabF, other); // st_other
write(*SymtabF, Index); // st_shndx
}
}
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData,
const MCAsmLayout &Layout) {
MCSymbolData *Data = &OrigData;
@ -550,9 +606,7 @@ static const MCSymbol *getBaseSymbol(const MCAsmLayout &Layout,
return getBaseSymbol(Layout, A->getSymbol());
}
void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
ELFSymbolData &MSD,
void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
MCSymbolData &OrigData = *MSD.SymbolData;
MCSymbolData &Data =
@ -595,28 +649,28 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
}
// Write out the symbol table entry
WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value,
Size, Other, MSD.SectionIndex, IsReserved);
Writer.writeSymbol(MSD.StringIndex, Info, Value, Size, Other,
MSD.SectionIndex, IsReserved);
}
void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
const MCAssembler &Asm,
MCAssembler &Asm,
const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap) {
SectionIndexMapTy &SectionIndexMap) {
// The string table must be emitted first because we need the index
// into the string table for all the symbol names.
assert(StringTable.size() && "Missing string table");
// FIXME: Make sure the start of the symbol table is aligned.
SymbolTableWriter Writer(Asm, FWriter, is64Bit(), SectionIndexMap, SymtabF);
// The first entry is the undefined symbol entry.
WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) {
WriteSymbolEntry(SymtabF, ShndxF, FileSymbolData[i],
ELF::STT_FILE | ELF::STB_LOCAL, 0, 0,
ELF::STV_DEFAULT, ELF::SHN_ABS, true);
Writer.writeSymbol(FileSymbolData[i], ELF::STT_FILE | ELF::STB_LOCAL, 0, 0,
ELF::STV_DEFAULT, ELF::SHN_ABS, true);
}
// Write the symbol table entries.
@ -624,7 +678,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = LocalSymbolData[i];
WriteSymbol(SymtabF, ShndxF, MSD, Layout);
WriteSymbol(Writer, MSD, Layout);
}
// Write out a symbol table entry for each regular section.
@ -638,9 +692,8 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
Section.getType() == ELF::SHT_SYMTAB ||
Section.getType() == ELF::SHT_SYMTAB_SHNDX)
continue;
WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0,
ELF::STV_DEFAULT, SectionIndexMap.lookup(&Section),
false);
Writer.writeSymbol(0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT,
SectionIndexMap.lookup(&Section), false);
LastLocalSymbolIndex++;
}
@ -650,7 +703,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
assert(((Data.getFlags() & ELF_STB_Global) ||
(Data.getFlags() & ELF_STB_Weak)) &&
"External symbol requires STB_GLOBAL or STB_WEAK flag");
WriteSymbol(SymtabF, ShndxF, MSD, Layout);
WriteSymbol(Writer, MSD, Layout);
if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
@ -658,7 +711,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
WriteSymbol(SymtabF, ShndxF, MSD, Layout);
WriteSymbol(Writer, MSD, Layout);
if (MCELF::GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
@ -976,8 +1029,6 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCSectionELF &Section =
static_cast<const MCSectionELF&>(BaseSymbol->getSection());
MSD.SectionIndex = SectionIndexMap.lookup(&Section);
if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
NeedsSymtabShndx = true;
assert(MSD.SectionIndex && "Invalid section index!");
}
@ -1026,9 +1077,6 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
ExternalSymbolData[i].SymbolData->setIndex(Index++);
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
if (Index >= ELF::SHN_LORESERVE)
NeedsSymtabShndx = true;
}
void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm,
@ -1197,16 +1245,6 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
SymtabSD.setAlignment(is64Bit() ? 8 : 4);
MCSectionData *SymtabShndxSD = NULL;
if (NeedsSymtabShndx) {
const MCSectionELF *SymtabShndxSection =
Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0,
SectionKind::getReadOnly(), 4, "");
SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection);
SymtabShndxSD->setAlignment(4);
}
const MCSectionELF *StrtabSection;
StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
SectionKind::getReadOnly());
@ -1221,11 +1259,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
// Symbol table
F = new MCDataFragment(&SymtabSD);
MCDataFragment *ShndxF = NULL;
if (NeedsSymtabShndx) {
ShndxF = new MCDataFragment(SymtabShndxSD);
}
WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap);
WriteSymbolTable(F, Asm, Layout, SectionIndexMap);
F = new MCDataFragment(&StrtabSD);
F->getContents().append(StringTable.begin(), StringTable.end());

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

106
test/MC/ELF/many-sections.s Normal file
View File

@ -0,0 +1,106 @@
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
// RUN: llvm-readobj -s %t | FileCheck --check-prefix=SECTIONS %s
// RUN: llvm-readobj -t %t | FileCheck --check-prefix=SYMBOLS %s
// Test that we don't create a .symtab_shndx since we are one section short of
// SHN_LORESERVE (0xFF00).
// SECTIONS-NOT: Name: .symtab_shndx
// Check the last referenced section.
// SYMBOLS: Name: dm (0)
// SYMBOLS-NEXT: Value: 0x0
// SYMBOLS-NEXT: Size: 0
// SYMBOLS-NEXT: Binding: Local (0x0)
// SYMBOLS-NEXT: Type: Section (0x3)
// SYMBOLS-NEXT: Other: 0
// SYMBOLS-NEXT: Section: dm (0xFEFF)
// SYMBOLS-NEXT: }
// SYMBOLS-NEXT:]
.macro gen_sections4 x
.section a\x
.section b\x
.section c\x
.section d\x
.endm
.macro gen_sections8 x
gen_sections4 a\x
gen_sections4 b\x
.endm
.macro gen_sections16 x
gen_sections8 a\x
gen_sections8 b\x
.endm
.macro gen_sections32 x
gen_sections16 a\x
gen_sections16 b\x
.endm
.macro gen_sections64 x
gen_sections32 a\x
gen_sections32 b\x
.endm
.macro gen_sections128 x
gen_sections64 a\x
gen_sections64 b\x
.endm
.macro gen_sections256 x
gen_sections128 a\x
gen_sections128 b\x
.endm
.macro gen_sections512 x
gen_sections256 a\x
gen_sections256 b\x
.endm
.macro gen_sections1024 x
gen_sections512 a\x
gen_sections512 b\x
.endm
.macro gen_sections2048 x
gen_sections1024 a\x
gen_sections1024 b\x
.endm
.macro gen_sections4096 x
gen_sections2048 a\x
gen_sections2048 b\x
.endm
.macro gen_sections8192 x
gen_sections4096 a\x
gen_sections4096 b\x
.endm
.macro gen_sections16384 x
gen_sections8192 a\x
gen_sections8192 b\x
.endm
.macro gen_sections32768 x
gen_sections16384 a\x
gen_sections16384 b\x
.endm
gen_sections32768 a
gen_sections16384 b
gen_sections8192 c
gen_sections4096 d
gen_sections2048 e
gen_sections1024 f
gen_sections512 g
gen_sections128 h
gen_sections64 i
gen_sections32 j
gen_sections16 k
gen_sections8 l
gen_sections4 m

View File

@ -626,7 +626,7 @@ template <class ELFT>
void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
StringRef SymbolName = errorOrDefault(Obj->getSymbolName(Symbol));
unsigned SectionIndex = Obj->getSymbolTableIndex(&*Symbol);
unsigned SectionIndex = Symbol->st_shndx;
StringRef SectionName;
if (SectionIndex == SHN_UNDEF) {
SectionName = "Undefined";
@ -641,6 +641,8 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
} else if (SectionIndex == SHN_COMMON) {
SectionName = "Common";
} else {
if (SectionIndex == SHN_XINDEX)
SectionIndex = Obj->getSymbolTableIndex(&*Symbol);
assert(SectionIndex != SHN_XINDEX &&
"getSymbolTableIndex should handle this");
const Elf_Shdr *Sec = Obj->getSection(SectionIndex);
@ -666,7 +668,7 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
makeArrayRef(ElfSymbolBindings));
W.printEnum ("Type", Symbol->getType(), makeArrayRef(ElfSymbolTypes));
W.printNumber("Other", Symbol->st_other);
W.printHex ("Section", SectionName, Symbol->st_shndx);
W.printHex("Section", SectionName, SectionIndex);
}
#define LLVM_READOBJ_TYPE_CASE(name) \